@e7w/easy-model 0.1.8 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +249 -178
  2. package/package.json +24 -1
package/README.md CHANGED
@@ -1,233 +1,304 @@
1
1
  # easy-model
2
2
 
3
- 轻量级的 React 状态管理与依赖注入库。
4
-
5
- easy-model 专注于在 React 中提供简洁、高效的状态管理,减少样板代码并保持良好的可组合性。
3
+ **easy-model** 是一个围绕「类模型(Model Class)+ 依赖注入 + 精细化变更监听」构建的 React 状态管理与 IoC 工具集。你可以用普通的 TypeScript 类描述业务模型,通过少量 API 即可:
4
+
5
+ - **在函数组件中直接创建 / 注入模型实例**(`useModel` / `useInstance`)
6
+ - **跨组件共享同一实例**,支持按参数分组实例缓存(`provide`)
7
+ - **监听模型及其嵌套属性的变化**(`watch` / `useWatcher`)
8
+ - **用装饰器和 IoC 容器做依赖注入**(`Container` / `CInjection` / `VInjection` / `inject`)
9
+ - **统一管理异步调用的加载状态**(`loader` / `useLoader`)
10
+
11
+ 相比 Redux / MobX / Zustand,easy-model 的目标是:**保持接近类 OOP 的心智模型,同时提供较好的性能和类型体验,并内建 IoC 能力。**
12
+
13
+ ### 核心特性一览
14
+
15
+ - **类模型驱动(Class-based Model)**
16
+ 直接用 TypeScript 类描述业务:字段即状态,方法即业务逻辑,没有额外的 action / reducer ceremony。
17
+
18
+ - **按参数缓存实例(Instance by arguments)**
19
+ 使用 `provide` 包装后,相同参数获取的是同一实例,不同参数获取不同实例,天然支持「按业务 key」分区的状态。
20
+
21
+ - **深层变更监听(Deep watch)**
22
+ `watch` / `useWatcher` 可以监听到:
23
+ - 模型自身字段的变化;
24
+ - 嵌套对象属性变化;
25
+ - 实例之间的嵌套 / 引用关系变化;
26
+ - getter 返回的衍生实例的变化。
27
+
28
+ - **React Hooks 友好**
29
+ - `useModel`:在组件中创建并订阅模型;
30
+ - `useInstance`:在组件中订阅已有实例;
31
+ - `useWatcher`:在函数组件中挂载监听回调;
32
+ - `useLoader`:统一获取全局 loading 状态及单个方法的 loading 状态。
33
+
34
+ - **IoC 容器与依赖注入**
35
+ - 使用 `Container` / `CInjection` / `VInjection` / `config` 配置注入;
36
+ - 使用 `inject` 装饰器在类中按 schema 声明依赖;
37
+ - 支持 namespace 隔离与 `clearNamespace` 清理。
38
+
39
+ ### 示例(example/)
40
+
41
+ `example/` 目录包含运行时示例,可帮助快速理解 API。下面是几个「直给」的核心用法片段。
42
+
43
+ - **基础计数器:`useModel` / `useWatcher`**(见 `example/index.tsx`)
44
+ 使用 `CounterModel` 展示如何在函数组件中创建模型实例、读取 / 更新字段,并监听变更:
45
+
46
+ ```tsx
47
+ import { useModel, useWatcher } from "easy-model";
48
+
49
+ class CounterModel {
50
+ count = 0;
51
+ label: string;
52
+ constructor(initial = 0, label = "计数器") {
53
+ this.count = initial;
54
+ this.label = label;
55
+ }
56
+ increment() {
57
+ this.count += 1;
58
+ }
59
+ decrement() {
60
+ this.count -= 1;
61
+ }
62
+ }
6
63
 
7
- ---
64
+ function Counter() {
65
+ const counter = useModel(CounterModel, [0, "示例"]);
66
+
67
+ useWatcher(counter, (keys, prev, next) => {
68
+ console.log("changed:", keys.join("."), prev, "->", next);
69
+ });
70
+
71
+ return (
72
+ <div>
73
+ <h2>{counter.label}</h2>
74
+ <div>{counter.count}</div>
75
+ <button onClick={() => counter.decrement()}>-</button>
76
+ <button onClick={() => counter.increment()}>+</button>
77
+ </div>
78
+ );
79
+ }
80
+ ```
8
81
 
9
- ## 特性
82
+ - **跨组件通信:`useModel` + `useInstance`**
83
+ 通过 `CommunicateModel` + `provide`,让多个组件共享同一实例(按参数分组):
10
84
 
11
- - 极简 API:基于 Hook 的使用方式,易上手、易迁移。
12
- - 依赖注入:内置简单的容器,支持按类型/命名空间注入与清理。
13
- - 响应式观察:`watch` 支持对对象变化进行监听并触发更新。
14
- - Loader:统一的异步数据加载与缓存机制,搭配 `useLoader` 使用。
15
- - 体积小、无侵入:适合大中小型项目或逐步引入到现有项目中。
85
+ ```tsx
86
+ import { provide, useModel, useInstance } from "easy-model";
16
87
 
17
- ---
88
+ class CommunicateModel {
89
+ constructor(public name: string) {}
90
+ value = 0;
91
+ random() {
92
+ this.value = Math.random();
93
+ }
94
+ }
18
95
 
19
- ## 安装
96
+ const CommunicateProvider = provide(CommunicateModel);
20
97
 
21
- 推荐使用 `pnpm`:
98
+ function CommunicateA() {
99
+ const { value, random } = useModel(CommunicateModel, ["channel"]);
100
+ return (
101
+ <div>
102
+ <span>组件 A:{value}</span>
103
+ <button onClick={random}>改变数值</button>
104
+ </div>
105
+ );
106
+ }
22
107
 
23
- ```bash
24
- pnpm add @e7w/easy-model
25
- ```
108
+ function CommunicateB() {
109
+ const { value } = useInstance(CommunicateProvider("channel"));
110
+ return <div>组件 B:{value}</div>;
111
+ }
112
+ ```
26
113
 
27
- 或使用 `npm` / `yarn`:
114
+ - **独立监听:`watch`**
115
+ 在 React 外部或普通函数中监听某个实例,将变更记录到日志列表中:
28
116
 
29
- ```bash
30
- npm install @e7w/easy-model
31
- yarn add @e7w/easy-model
32
- ```
117
+ ```tsx
118
+ import { provide, watch } from "easy-model";
33
119
 
34
- 开发(安装依赖并运行测试):
120
+ class WatchModel {
121
+ constructor(public name: string) {}
122
+ value = 0;
123
+ }
35
124
 
36
- ```bash
37
- pnpm install
38
- pnpm test
39
- ```
125
+ const WatchProvider = provide(WatchModel);
126
+ const inst = WatchProvider("watch-demo");
40
127
 
41
- (如需启动示例项目,使用 Vite `pnpm dev`,请参考 `package.json` 脚本。)
128
+ const stop = watch(inst, (keys, prev, next) => {
129
+ console.log(`${keys.join(".")}: ${prev} -> ${next}`);
130
+ });
42
131
 
43
- ---
132
+ inst.value += 1;
133
+ // 不再需要时取消监听
134
+ stop();
135
+ ```
44
136
 
45
- ## 快速上手(React)
137
+ - **异步加载与全局 Loading:`loader` / `useLoader`**
138
+ 通过装饰器标记异步方法,并在组件中读取全局 / 单方法 loading 状态:
46
139
 
47
- 下面演示核心用法,适合在函数组件中使用:
140
+ ```tsx
141
+ import { loader, useLoader, useModel } from "easy-model";
48
142
 
49
- ```tsx
50
- import React from "react";
51
- import {
52
- provide,
53
- useModel,
54
- loader,
55
- useLoader,
56
- inject,
57
- watch,
58
- } from "easy-model";
143
+ class LoaderModel {
144
+ constructor(public name: string) {}
59
145
 
60
- class Counter {
61
- count = 0;
62
- }
146
+ @loader.load(true)
147
+ async fetch() {
148
+ return new Promise<number>(resolve =>
149
+ setTimeout(() => resolve(42), 1000)
150
+ );
151
+ }
152
+ }
63
153
 
64
- // 组件中读取并响应模型变化
65
- function Counter() {
66
- const model = useModel(Counter, []);
67
- return (
68
- <div>
69
- <button onClick={() => model.count--}>-</button>
70
- <span>{model.count}</span>
71
- <button onClick={() => model.count++}>+</button>
72
- </div>
73
- );
74
- }
75
-
76
- // 异步 loader 示例
77
- class Photos {
78
- @loader.load(true)
79
- data = [];
80
- async fetcher() {
81
- const res = await fetch("/api/photos");
82
- this.data = res.json();
154
+ function LoaderDemo() {
155
+ const { isGlobalLoading, isLoading } = useLoader();
156
+ const inst = useModel(LoaderModel, ["loader-demo"]);
157
+
158
+ return (
159
+ <div>
160
+ <div>全局加载状态:{String(isGlobalLoading)}</div>
161
+ <div>当前加载状态:{String(isLoading(inst.fetch))}</div>
162
+ <button onClick={() => inst.fetch()} disabled={isGlobalLoading}>
163
+ 触发一次异步加载
164
+ </button>
165
+ </div>
166
+ );
83
167
  }
84
- }
85
-
86
- function Gallery() {
87
- const { data, fetcher } = useModel(Photos, []);
88
- const { isGlobalLoading, isLoading } = useLoader();
89
- useEffect(() => {
90
- fetcher();
91
- }, [fetcher]);
92
- if (isGlobalLoading) return <div>全局loading</div>;
93
- if (isLoading(fetcher)) return <div>本函数loading...</div>;
94
- return (
95
- <ul>
96
- {data.map((p: any) => (
97
- <li key={p.id}>{p.title}</li>
98
- ))}
99
- </ul>
100
- );
101
- }
102
-
103
- // 依赖注入示例(类/服务)
104
- const schema = object({
105
- number: number(),
106
- }).describe("测试用schema");
107
- const schema2 = object({
108
- xxx: number(),
109
- }).describe("Test类的schema");
110
-
111
- class Test {
112
- xxx = 1;
113
- }
114
- class MFoo {
115
- @inject(schema)
116
- bar?: Infer<typeof schema>;
117
- baz?: number;
118
- @inject(schema2)
119
- qux?: Infer<typeof schema2>;
120
- }
121
-
122
- config(
123
- <>
124
- <Container>
125
- <CInjection schema={schema2} ctor={Test} />
126
- <VInjection
127
- schema={schema}
128
- val={{
129
- number: 100,
130
- }}
131
- />
132
- </Container>
133
- </>
134
- );
168
+ ```
135
169
 
136
- const Foo = provide(MFoo);
137
- let foo: MFoo | undefined = Foo();
138
- foo.baz = 20;
139
- document.writeln(JSON.stringify(foo.bar));
140
- document.writeln(String(foo.baz));
141
- document.writeln(JSON.stringify(foo.qux));
142
- ```
170
+ - **依赖注入示例:`example/inject.tsx`**
171
+ 展示了如何用 zod schema 描述依赖,并通过容器完成注入:
143
172
 
144
- 更多示例见项目自带的 [example](example).
173
+ ```tsx
174
+ import {
175
+ CInjection,
176
+ Container,
177
+ VInjection,
178
+ config,
179
+ inject,
180
+ } from "easy-model";
181
+ import { object, number } from "zod";
145
182
 
146
- ---
183
+ const schema = object({ number: number() }).describe("测试用schema");
147
184
 
148
- ## API(概览)
185
+ class Test {
186
+ xxx = 1;
187
+ }
149
188
 
150
- - `watch` — 响应式监听函数。
151
- - `provide`, `finalizationRegistry` — 提供和清理模型/服务。
152
- - `useModel`, `useInstance`, `useWatcher` — React Hook,用于绑定模型或自定义观察者。
153
- - `loader`, `useLoader` — 异步加载器与 Hook。
154
- - `Container`, `CInjection`, `VInjection`, `inject`, `clearNamespace`, `isRegistered`, `config` — IoC/容器与注入相关工具。
189
+ class MFoo {
190
+ @inject(schema)
191
+ bar?: { number: number };
192
+ baz?: number;
193
+ }
194
+
195
+ config(
196
+ <Container>
197
+ <CInjection schema={schema} ctor={Test} />
198
+ <VInjection schema={schema} val={{ number: 100 }} />
199
+ </Container>
200
+ );
201
+ ```
155
202
 
156
- ---
203
+ - **Benchmark 示例:`example/benchmark.tsx`**
204
+ 提供 easy-model / Redux / MobX / Zustand 在同一场景下的**粗略性能对比面板**,下文有详细说明。
157
205
 
158
- ## 与常见库对比(简要)
206
+ ### 测试(test/)
159
207
 
160
- - Redux:
161
- - Redux 适合大型、严格的全局状态管理,具有强大的中间件生态,但模板代码较多(actions/reducers)。
162
- - easy-model 更轻量,基于对象与 Hook,适合快速开发,整合 DI 和 loader,减少样板代码。
208
+ `test/` 目录使用 Vitest + React Testing Library 覆盖了核心行为:
163
209
 
164
- - MobX:
165
- - MobX 提供细粒度响应式,学习曲线较低。easy-model 提供类似的响应式监听器和 Hook,但 API 更显式,集成 DI 更方便。
210
+ - **provide 与实例缓存**
211
+ - 相同参数返回同一实例;
212
+ - 不同参数返回不同实例。
166
213
 
167
- - Zustand:
168
- - Zustand 也很小巧,以 store 函数为中心。easy-model 的优势在于:内建依赖注入、loader 管理与更直接的对象模型(常见类/实例注入更友好)。
214
+ - **watch 的深层监听能力**
215
+ - 监听简单字段变更;
216
+ - 监听嵌套对象属性变更;
217
+ - 处理实例之间的嵌套引用关系;
218
+ - 支持 getter 返回实例(如 `child2`)的变更路径监听。
169
219
 
170
- - React Context:
171
- - Context 适合简单传递,性能需配合 memo/selector 优化。easy-model 提供专门的 Hook 与内部优化,减少组件重新渲染并支持按需注入。
220
+ - **IoC 配置与命名空间**
221
+ - 通过 `config` + `Container` + `CInjection` / `VInjection` 注册依赖;
222
+ - `isRegistered` 判断指定 schema 是否已在某个 namespace 注册;
223
+ - `clearNamespace` 清理命名空间中的注册项。
172
224
 
173
- 总的来说,easy-model 的优势可以概括为:
225
+ - **Hooks 行为**
226
+ - `useModel` + `useInstance` 在两个组件间共享状态并同步更新 UI;
227
+ - `useWatcher` 在函数组件中监听模型变化;
228
+ - `loader` + `useLoader` 正确反映全局 / 单个方法的 loading 状态。
174
229
 
175
- - **组合性强**:同一套模型既可以作为 React 状态容器,又可以作为依赖注入的服务,还可以挂载 loader / watch 等逻辑,减少在多个库之间来回穿梭。
176
- - **API 简单、一致**:以“类 + Hook”为中心(`useModel` / `useInstance`),不需要额外的 action、reducer 或复杂的装饰器配置,迁移成本低。
177
- - **性能可接受且易优化**:在典型的批量更新场景中,相比 Redux 有数量级的性能优势,同时通过内部的批量调度与轻量级响应式实现,保证在多数业务场景下不会成为性能瓶颈。
178
- - **渐进式引入友好**:无需改造全局 store,可以从单个模块/页面开始使用模型类和 Hook,逐步替换原有状态管理方案。
230
+ ### Redux / MobX / Zustand 的对比
179
231
 
180
- ### 简单 benchmark 结论
232
+ 下表是从「心智模型 / 用法复杂度 / 性能 & 能力边界」等角度对比 easy-model 与常见方案:
181
233
 
182
- 项目在 `example/benchmark.tsx` 中提供了一个**粗略的**对比示例,核心场景为:
234
+ | 方案 | 编程模型 | 典型心智负担 | 内建 IoC / DI | 性能特征(本项目场景) |
235
+ | -------------- | ------------------------ | ------------------------------------------------------------------ | ---------------------- | --------------------------------------- |
236
+ | **easy-model** | 类模型 + Hooks + IoC | 写类 + 写方法即可,少量 API(`provide` / `useModel` / `watch` 等) | 是 | 在极端批量更新下仍为**个位数毫秒** |
237
+ | **Redux** | 不可变 state + reducer | 需要 action / reducer / dispatch 等模板代码 | 否 | 在同场景下为**数十毫秒级** |
238
+ | **MobX** | 可观察对象 + 装饰器 | 对响应式系统有一定学习成本,隐藏的依赖追踪 | 否(偏响应式而非 IoC) | 性能优于 Redux,但仍是**十几毫秒级** |
239
+ | **Zustand** | Hooks store + 函数式更新 | API 简洁,偏轻量,适合局部状态 | 否 | 在本场景下是**最快**,但不提供 IoC 能力 |
183
240
 
184
- - 初始化一个包含 10,000 个数字的数组;
185
- - 点击按钮后,对所有元素做 5 轮自增;
186
- - 使用 `performance.now()` 统计这段同步计算与状态写入时间(不计入 React 首屏渲染)。
241
+ 从项目角度看,easy-model 的特点在于:
187
242
 
188
- 在一台常规开发机上的一次测试结果(单位:ms,取单次运行的代表值)大致如下:
243
+ - **对比 Redux**:
244
+ - 不需要拆分 action / reducer / selector,业务逻辑直接写在模型方法里;
245
+ - 避免大量模板代码,类型推断更直接(基于类字段和方法签名);
246
+ - 自动处理实例缓存与变更订阅,无需手动 connect / useSelector。
189
247
 
190
- | 实现 | 耗时(ms) | 说明 |
191
- | ---------- | ---------- | ----------------------------------- |
192
- | easy-model | ≈ 3.1 | 基于类实例 + `observe` 的响应式模型 |
193
- | Redux | ≈ 51.5 | `createSlice` + Immer 不可变更新 |
194
- | MobX | ≈ 16.9 | `makeAutoObservable` + observer |
195
- | Zustand | ≈ 0.6 | 极简 store 函数实现 |
248
+ - **对比 MobX**:
249
+ - 保留类模型的直觉优势,同时用显式 API(`watch` / `useWatcher`)暴露依赖关系;
250
+ - 依赖注入、命名空间、清理等能力是 easy-model 的一等公民,而非额外工具。
196
251
 
197
- 从这个场景可以得到几个结论(仅作趋势参考):
252
+ - **对比 Zustand**:
253
+ - 性能接近(在本项目 benchmark 中 easy-model 仍处于个位数毫秒),但提供更完整的 IoC / DI / deep watch 组合能力;
254
+ - 更适合中大型、需要明确领域模型和依赖关系的项目,而不仅是「轻量局部状态 store」。
198
255
 
199
- - **对比 Redux**:easy-model 在该批量场景中大约比 Redux 快一个数量级(\~3ms vs \~50ms),同时完全避免了 action / reducer 等模板代码,更新路径更直接。
200
- - **对比 MobX**:easy-model 与 MobX 属于同一数量级,前者以更简单的 Hook API + DI/loader 一体化为主打,后者在响应式生态上更成熟。
201
- - **对比 Zustand**:Zustand 在这个极简数组场景下可以做到非常小的开销;easy-model 并不以“单一场景下绝对最快”为目标,而是在保持性能可接受的前提下,提供更丰富的能力组合(依赖注入、loader、watch 等)。
256
+ ### Benchmark 场景说明(与 Redux / MobX / Zustand 的粗略性能对比)
202
257
 
203
- 整体来说:
258
+ 在 `example/benchmark.tsx` 中,项目提供了一个**简单且偏极端**的 benchmark,用来在同一台机器上粗略比较不同状态管理方案在「大量同步写入」场景下的表现。核心场景为:
204
259
 
205
- - 在常见的批量更新场景里,**easy-model 相比 Redux 有明显的性能和开发体验优势**;
206
- - MobX / Zustand 相比,easy-model 的优势更多体现在**组合能力与 API 一致性**:一套模型可以同时承担状态管理、依赖注入和异步加载,而不需要在多个库之间来回切换。
260
+ 1. **初始化一个包含 10,000 个数字的数组**;
261
+ 2. 点击按钮后,对所有元素做 **5 轮自增**;
262
+ 3. 使用 `performance.now()` 统计这段**同步计算与状态写入**时间;
263
+ 4. **不计入 React 首屏渲染时间**,仅关注每次点击触发的计算 + 状态写入耗时。
207
264
 
208
- > 说明:该 benchmark 仅为示例级别,不是严谨的基准测试。不同设备、浏览器和实现细节都会显著影响具体数值,建议按需 clone 仓库后自行在本地运行 `pnpm dev`,并在示例页面的 “Benchmark” 区块里手动对比。
265
+ 在一台常规开发机上的一次测试结果(单位:ms,取单次运行的代表值)大致如下(数值可能因环境而异,仅供参考):
209
266
 
210
- ---
267
+ | 实现 | 耗时(ms) |
268
+ | -------------- | ---------- |
269
+ | **easy-model** | ≈ 3.1 |
270
+ | **Redux** | ≈ 51.5 |
271
+ | **MobX** | ≈ 16.9 |
272
+ | **Zustand** | ≈ 0.6 |
211
273
 
212
- ## 开发 & 测试
274
+ 需要特别强调:
213
275
 
214
- 运行测试:
276
+ - **这是一个刻意放大的「批量更新」场景**,主要目的是放大不同实现之间在「大量同步写入 + 通知」路径上的差异;
277
+ - 结果会受到:浏览器 / Node 版本、硬件性能、打包模式等多种因素影响,因此这里只能作为**趋势性的参考**,而非严谨的性能报告;
278
+ - Zustand 在这个场景下表现最好,这是符合其「极简 store + 函数式更新」定位的;
279
+ - easy-model 虽然在这类极端场景下略慢于 Zustand,但**仍明显快于 Redux / MobX**,同时提供:
280
+ - 类模型 + IoC + 深度监听等高级能力;
281
+ - 更适合中大型业务的结构化编码体验。
215
282
 
216
- ```bash
217
- pnpm install
218
- pnpm test
219
- ```
283
+ ### 项目链接与关键词
220
284
 
221
- 查看示例:打开 `example/index.tsx` 并参考 `vite`/`npm` 脚本运行本地示例(一般为 `pnpm dev`)。
285
+ - **GitHub 仓库**: [`ZYF93/easy-model`](https://github.com/ZYF93/easy-model)
286
+ - **npm 包**: [`@e7w/easy-model`](https://www.npmjs.com/package/@e7w/easy-model)
287
+ - **关键词**: `react` / `state management` / `state manager` / `ioc` / `dependency injection` / `class model` / `react hooks` / `watcher` / `loader` / `typescript`
222
288
 
223
- ---
289
+ ### 适用场景
224
290
 
225
- ## 贡献
291
+ easy-model 更适合以下类型的项目:
226
292
 
227
- 欢迎提交 issue 和 PR。请遵循项目的代码风格与测试约定。若要运行或修改示例,请先安装依赖并运行 `pnpm test` 验证现有用例。
293
+ - 领域模型清晰、希望用类来承载业务状态与方法;
294
+ - 需要在各处优雅地做依赖注入(如仓储、服务、配置、schema 等);
295
+ - 对「监听某个模型 / 某个嵌套字段的变化」有较强需求;
296
+ - 希望在保证结构化代码与可维护性的同时,获得接近轻量状态库的性能。
228
297
 
229
- ---
298
+ 如果你目前在使用 Redux / MobX / Zustand,想要:
230
299
 
231
- ## 许可证
300
+ - 减少心智负担和模板代码;
301
+ - 获得更自然的类模型与 IoC 能力;
302
+ - 又不希望在性能上明显吃亏;
232
303
 
233
- MIT
304
+ 那么可以尝试将部分模块迁移到 easy-model,并先在 `example/benchmark.tsx` 中实际运行一次 benchmark,观察在你的机器和真实业务数据规模下的表现。
package/package.json CHANGED
@@ -1,12 +1,35 @@
1
1
  {
2
2
  "name": "@e7w/easy-model",
3
- "version": "0.1.8",
3
+ "keywords": [
4
+ "react",
5
+ "state management",
6
+ "state manager",
7
+ "ioc",
8
+ "dependency injection",
9
+ "model",
10
+ "class model",
11
+ "react hooks",
12
+ "watcher",
13
+ "loader",
14
+ "typescript"
15
+ ],
16
+ "description": "一个基于类模型和依赖注入的 React 状态管理库。",
17
+ "version": "0.2.0",
4
18
  "module": "./dist/index.es.js",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/ZYF93/easy-model.git"
22
+ },
5
23
  "publishConfig": {
6
24
  "access": "public",
7
25
  "registry": "https://registry.npmjs.org/"
8
26
  },
9
27
  "type": "module",
28
+ "homepage": "https://github.com/ZYF93/easy-model#readme",
29
+ "bugs": {
30
+ "url": "https://github.com/ZYF93/easy-model/issues"
31
+ },
32
+ "author": "张一凡",
10
33
  "types": "./dist/index.d.ts",
11
34
  "exports": {
12
35
  ".": {