react-native-hox 0.0.3 → 1.0.1

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.
package/README.md CHANGED
@@ -1,27 +1,44 @@
1
1
  # react-native-hox
2
2
 
3
- 面向 React Native 的轻量状态管理方案:类型安全、API 极简,支持组件内 Hook 与组件外 Vanilla 读写,并内置可选持久化能力。
3
+ 面向 React Native 的**极简状态管理**:类型安全、API 零心智负担,单文件架构,包体积极小。
4
4
 
5
5
  [![NPM Version](https://img.shields.io/npm/v/react-native-hox)](https://www.npmjs.com/package/react-native-hox)
6
6
  [![TypeScript](https://img.shields.io/badge/language-TypeScript-blue)](https://www.typescriptlang.org/)
7
7
  [![License](https://img.shields.io/npm/l/react-native-hox)](https://www.npmjs.com/package/react-native-hox)
8
8
 
9
+ ---
10
+
11
+ ## 亮点
12
+
13
+ | 特性 | 说明 |
14
+ |------|------|
15
+ | **包体积极小** | 单入口构建,**gzip 后 ESM ~1.5 KB / CJS ~1.6 KB**;运行时仅依赖 `use-sync-external-store`,持久化可选依赖 AsyncStorage |
16
+ | **类型安全** | 全 TypeScript,`createModel` 泛型推导完整,selector 与 setState 类型即文档 |
17
+ | **API 极简** | 一个 `createModel` 搞定:组件内用 Hook,组件外用 `model.data`,无需 Provider |
18
+ | **按需重渲染** | 支持 selector + 可选 `shallow`,只在关注字段变化时更新组件 |
19
+ | **可选持久化** | 内置 persist(默认 AsyncStorage),支持自定义 storage、防抖、迁移钩子 |
20
+ | **React 18 友好** | 基于 `useSyncExternalStore`,无 tearing,兼容并发渲染 |
21
+
22
+ ---
23
+
9
24
  ## 快速开始
10
25
 
11
26
  ### 安装
12
27
 
13
28
  ```bash
14
- npm i react-native-hox
29
+ npm i react-native-hox @react-native-async-storage/async-storage
15
30
  ```
16
31
 
32
+ > 项目中已有 `@react-native-async-storage/async-storage` 则无需重复安装。
33
+
17
34
  ### 最小示例
18
35
 
19
36
  ```ts
20
37
  // stores/user.ts
21
38
  import { createModel } from 'react-native-hox';
22
39
 
23
- export const userStore = createModel({ name: 'Guest' }); // 数据只存在内存
24
- // export const userStore = createModel({ name: 'Guest' }, { persist: 'user_v1' }); // 数据存在缓存 AsyncStorage
40
+ export const userStore = createModel({ name: 'Guest' });
41
+ // 持久化:createModel({ name: 'Guest' }, { persist: 'user_v1' });
25
42
  ```
26
43
 
27
44
  ```tsx
@@ -41,198 +58,102 @@ export function Profile() {
41
58
  }
42
59
  ```
43
60
 
44
- ## 功能点
45
-
46
- ### 1) 更新状态:自动合并 / 显式替换
47
-
48
- ```ts
49
- import { createModel } from 'react-native-hox';
50
-
51
- export const profileStore = createModel({ name: 'Guest', role: 'user' as 'user' | 'admin' });
52
- ```
53
-
54
- ```tsx
55
- import React from 'react';
56
- import { View, Text, Button } from 'react-native';
57
- import { profileStore } from './stores/profile';
61
+ ---
58
62
 
59
- export function UpdateExample() {
60
- const profile = profileStore.getState();
63
+ ## 功能概览
61
64
 
62
- return (
63
- <View>
64
- <Text>{profile.name}</Text>
65
- <Text>{profile.role}</Text>
66
- <Button title="Merge Update" onPress={() => profileStore.setState({ name: 'Alice' })} />
67
- <Button title="Replace" onPress={() => profileStore.setState({ name: 'Bob', role: 'admin' }, true)} />
68
- </View>
69
- );
70
- }
71
- ```
72
-
73
- ### 2) Selector:只在关注的数据变化时重渲染
65
+ ### 1) 更新状态:自动合并 / 显式替换
74
66
 
75
67
  ```ts
76
- import { createModel } from 'react-native-hox';
77
-
78
- export const counterStore = createModel({ count: 0, text: 'a' });
68
+ const profileStore = createModel({ name: 'Guest', role: 'user' as 'user' | 'admin' });
79
69
  ```
80
70
 
81
71
  ```tsx
82
- import React from 'react';
83
- import { View, Text, Button } from 'react-native';
84
- import { counterStore } from './stores/counter';
85
-
86
- export function SelectorExample() {
87
- const count = counterStore.getState((s) => s.count);
88
-
89
- return (
90
- <View>
91
- <Text>{count}</Text>
92
- <Button title="Inc" onPress={() => counterStore.setState((s) => ({ count: s.count + 1 }))} />
93
- <Button title="Change Text" onPress={() => counterStore.setState({ text: String(Math.random()) })} />
94
- </View>
95
- );
96
- }
72
+ profileStore.setState({ name: 'Alice' }); // 合并
73
+ profileStore.setState({ name: 'Bob', role: 'admin' }, true); // 整体替换
97
74
  ```
98
75
 
99
- selector 返回对象/数组时,传入 `equalityFn`(例如 `shallow`)避免无意义重渲染:
76
+ ### 2) Selector:只在关注数据变化时重渲染
100
77
 
101
78
  ```tsx
102
- import { shallow } from 'react-native-hox';
103
- import { counterStore } from './stores/counter';
104
-
79
+ const count = counterStore.getState((s) => s.count);
80
+ // 返回对象时建议用 shallow
105
81
  const picked = counterStore.getState((s) => ({ count: s.count }), shallow);
106
82
  ```
107
83
 
108
84
  ### 3) 组件外读写:Vanilla API
109
85
 
110
86
  ```ts
111
- import { userStore } from './stores/user';
112
-
113
- const name1 = userStore.data.state.name;
114
- const name2 = userStore.data.getState().name;
115
-
116
- const unsub = userStore.data.subscribe((next, prev) => {
117
- console.log(next, prev);
118
- });
119
- unsub();
120
- ```
121
-
122
- ### 4) 持久化:persist(默认 AsyncStorage)
123
-
124
- 只要提供一个 key 即可开启持久化(默认使用 `@react-native-async-storage/async-storage`,无需重复传 `storage`):
125
-
126
- ```ts
127
- import { createModel } from 'react-native-hox';
128
-
129
- export const authStore = createModel({ token: '' }, { persist: 'auth_v1' });
87
+ const name = userStore.data.state.name;
88
+ userStore.data.getState();
89
+ userStore.data.subscribe((next, prev) => {});
130
90
  ```
131
91
 
132
- 如果你希望替换存储引擎,可以在 `persist.storage` 传入实现同等接口的存储对象:
92
+ ### 4) 持久化
133
93
 
134
94
  ```ts
135
- import { createModel } from 'react-native-hox';
136
- import type { StorageEngine } from 'react-native-hox';
137
-
138
- const storage: StorageEngine = {
139
- getItem: async (key) => null,
140
- setItem: async (key, value) => {},
141
- removeItem: async (key) => {},
142
- };
143
-
144
- export const authStore = createModel({ token: '' }, { persist: { key: 'auth_v1', storage } });
95
+ createModel({ token: '' }, { persist: 'auth_v1' });
96
+ // 或自定义 storage / beforeRecover / beforePersist
97
+ createModel({ token: '' }, { persist: { key: 'auth_v1', storage: myStorage } });
145
98
  ```
146
99
 
147
100
  ### 5) reset / destroy / strict
148
101
 
149
102
  ```ts
150
- import { userStore } from './stores/user';
151
-
152
103
  userStore.reset();
153
104
  userStore.destroy();
105
+ createModel({ count: 0 }, { strict: { forbidSetStateAfterDestroy: true } });
154
106
  ```
155
107
 
156
- ```ts
157
- import { createModel } from 'react-native-hox';
108
+ ---
158
109
 
159
- export const strictStore = createModel(
160
- { count: 0 },
161
- { strict: { forbidSetStateAfterDestroy: true } }
162
- );
163
- ```
164
-
165
- ## 进阶使用
110
+ ## 进阶
166
111
 
167
- ### 1) subscribe(selector):只在 slice 变化时触发
112
+ ### subscribe(selector):按 slice 订阅
168
113
 
169
114
  ```tsx
170
- import React, { useEffect } from 'react';
171
- import { View, Text } from 'react-native';
172
- import { userStore } from './stores/user';
173
-
174
- export function SubscribeExample() {
175
- const name = userStore.getState((s) => s.name);
176
-
177
- useEffect(() => {
178
- const unsub = userStore.data.subscribe(
179
- (s) => s.name,
180
- (next, prev) => {
181
- console.log('name changed:', prev, '->', next);
182
- },
183
- { fireImmediately: true }
184
- );
185
- return unsub;
186
- }, []);
187
-
188
- return (
189
- <View>
190
- <Text>{name}</Text>
191
- </View>
192
- );
193
- }
115
+ userStore.data.subscribe(
116
+ (s) => s.name,
117
+ (next, prev) => console.log(next, prev),
118
+ { fireImmediately: true }
119
+ );
194
120
  ```
195
121
 
196
- ### 2) 持久化安全边界:版本化与数据迁移
122
+ ### 持久化迁移
197
123
 
198
124
  ```ts
199
- import { createModel } from 'react-native-hox';
200
-
201
- export const userPersistStore = createModel(
125
+ createModel(
202
126
  { token: '', isLogin: false },
203
127
  {
204
128
  persist: {
205
129
  key: 'user_v1',
206
- beforeRecover: (v) => ({
207
- token: v?.token ?? '',
208
- isLogin: Boolean(v?.token),
209
- }),
130
+ beforeRecover: (v) => ({ token: v?.token ?? '', isLogin: Boolean(v?.token) }),
210
131
  },
211
132
  }
212
133
  );
213
134
  ```
214
135
 
215
- ### 3) initialState 支持纯函数
136
+ ### 初始状态用函数
216
137
 
217
138
  ```ts
218
- import { createModel } from 'react-native-hox';
219
-
220
- export const appStore = createModel(() => ({ bootAt: Date.now() }));
139
+ createModel(() => ({ bootAt: Date.now() }));
221
140
  ```
222
141
 
223
- ## API 参考(简版)
142
+ ---
224
143
 
225
- ### `createModel(initialState, options?)`
144
+ ## API 简表
226
145
 
227
- - `initialState`: `T` `() => T`
228
- - `options.persist`: `string` 或 `{ key, storage?, debounce?, beforePersist?, beforeRecover? }`
229
- - `options.strict.forbidSetStateAfterDestroy`: `boolean`
230
- - `options.logger`: `{ warn, error }`
146
+ | 方法 / 属性 | 说明 |
147
+ |-------------|------|
148
+ | `model()` / `model.getState()` / `model.use()` / `model.useState()` | 组件内 Hook,可传 selector + equalityFn |
149
+ | `model.setState(partial, replace?)` | 更新状态 |
150
+ | `model.data.state` / `model.data.getState()` | 组件外读状态 |
151
+ | `model.data.setState` / `model.data.subscribe` | 组件外写与订阅 |
152
+ | `model.reset()` / `model.destroy()` | 重置为初始值、销毁 |
231
153
 
232
- 返回的 `Model` 同时支持:
154
+ **options**:`persist`(string `{ key, storage?, debounce?, beforePersist?, beforeRecover? }`)、`logger`、`strict.forbidSetStateAfterDestroy`。
233
155
 
234
- - 组件内(Hook):`model.getState()` / `model.use()` / `model.useState()`
235
- - 组件外(Vanilla):`model.data.state` / `model.data.getState()` / `model.data.setState()` / `model.data.subscribe()`
156
+ ---
236
157
 
237
158
  ## License
238
159
 
package/dist/index.d.mts CHANGED
@@ -1,61 +1,71 @@
1
- type Listener<T> = (state: T, prevState: T) => void;
2
- interface StorageEngine {
3
- getItem: (key: string) => string | null | Promise<string | null>;
4
- setItem: (key: string, value: string) => void | Promise<void>;
5
- removeItem: (key: string) => void | Promise<void>;
6
- }
7
- type EqualityFn<T> = (a: T, b: T) => boolean;
8
-
1
+ type Listener<T> = (state: T, prev: T) => void;
9
2
  type Selector<T, U> = (state: T) => U;
3
+ type EqualityFn<T> = (a: T, b: T) => boolean;
4
+ type SetState<T> = (partial: T | Partial<T> | ((s: T) => T | Partial<T>), replace?: boolean) => void;
10
5
  type ModelHook<T> = {
11
6
  (): T;
12
- <U>(selector: Selector<T, U>, equalityFn?: EqualityFn<U>): U;
7
+ <U>(sel: Selector<T, U>, eq?: EqualityFn<U>): U;
8
+ };
9
+ type StorageEngine = {
10
+ getItem(key: string): string | null | Promise<string | null>;
11
+ setItem(key: string, value: string): void | Promise<void>;
12
+ removeItem(key: string): void | Promise<void>;
13
13
  };
14
14
  interface PersistOptions<T> {
15
15
  key: string;
16
16
  storage?: StorageEngine;
17
17
  debounce?: number;
18
- beforePersist?: (state: T) => any;
19
- beforeRecover?: (value: any) => T | Partial<T>;
20
- }
21
- interface Logger {
22
- warn: (...args: any[]) => void;
23
- error: (...args: any[]) => void;
18
+ beforePersist?(state: T): any;
19
+ beforeRecover?(value: any): T | Partial<T>;
24
20
  }
25
21
  interface CreateModelOptions<T> {
26
22
  persist?: string | PersistOptions<T>;
27
- logger?: Logger;
23
+ logger?: {
24
+ warn(...a: any[]): void;
25
+ error(...a: any[]): void;
26
+ };
28
27
  strict?: {
29
28
  forbidSetStateAfterDestroy?: boolean;
30
29
  };
31
30
  }
32
31
  interface SubscribeWithSelectorOptions<U> {
33
- equalityFn?: EqualityFn<U>;
32
+ equalityFn?(a: U, b: U): boolean;
34
33
  fireImmediately?: boolean;
35
34
  }
36
35
  interface Subscribe<T> {
37
36
  (listener: Listener<T>): () => void;
38
- <U>(selector: Selector<T, U>, listener: (selected: U, prevSelected: U) => void, options?: SubscribeWithSelectorOptions<U>): () => void;
37
+ <U>(sel: Selector<T, U>, fn: (s: U, p: U) => void, opts?: SubscribeWithSelectorOptions<U>): () => void;
39
38
  }
40
39
  interface ModelData<T> {
41
- getState: () => T;
42
- setState: (partial: T | Partial<T> | ((state: T) => T | Partial<T>), replace?: boolean) => void;
40
+ getState(): T;
41
+ setState: SetState<T>;
43
42
  subscribe: Subscribe<T>;
44
- destroy: () => void;
45
- reset: () => void;
43
+ destroy(): void;
44
+ reset(): void;
46
45
  state: T;
47
46
  }
48
47
  type Model<T> = ModelHook<T> & {
49
48
  getState: ModelHook<T>;
50
49
  useState: ModelHook<T>;
51
- setState: (partial: T | Partial<T> | ((state: T) => T | Partial<T>), replace?: boolean) => void;
52
- destroy: () => void;
53
- reset: () => void;
54
- data: ModelData<T>;
55
50
  use: ModelHook<T>;
51
+ setState: SetState<T>;
52
+ destroy(): void;
53
+ reset(): void;
54
+ data: ModelData<T>;
55
+ };
56
+ declare function shallow<T>(a: T, b: T): boolean;
57
+ declare function debounce<T extends (...a: any[]) => any>(fn: T, ms: number): {
58
+ (...a: Parameters<T>): void;
59
+ flush(): void;
60
+ cancel(): void;
61
+ };
62
+ declare const createStore: <T>(init: T) => {
63
+ getState: () => T;
64
+ getInitialState: () => T;
65
+ setState(partial: T | Partial<T> | ((s: T) => T | Partial<T>), replace?: boolean): void;
66
+ subscribe(l: Listener<T>): () => void;
67
+ destroy(): void;
56
68
  };
57
69
  declare function createModel<T>(initialState: T | (() => T), options?: CreateModelOptions<T>): Model<T>;
58
70
 
59
- declare function shallow<T>(objA: T, objB: T): boolean;
60
-
61
- export { type CreateModelOptions, type Model, type ModelData, type PersistOptions, type StorageEngine, type SubscribeWithSelectorOptions, createModel, shallow };
71
+ export { type CreateModelOptions, type Model, type ModelData, type PersistOptions, type StorageEngine, type SubscribeWithSelectorOptions, createModel, createStore, debounce, shallow };
package/dist/index.d.ts CHANGED
@@ -1,61 +1,71 @@
1
- type Listener<T> = (state: T, prevState: T) => void;
2
- interface StorageEngine {
3
- getItem: (key: string) => string | null | Promise<string | null>;
4
- setItem: (key: string, value: string) => void | Promise<void>;
5
- removeItem: (key: string) => void | Promise<void>;
6
- }
7
- type EqualityFn<T> = (a: T, b: T) => boolean;
8
-
1
+ type Listener<T> = (state: T, prev: T) => void;
9
2
  type Selector<T, U> = (state: T) => U;
3
+ type EqualityFn<T> = (a: T, b: T) => boolean;
4
+ type SetState<T> = (partial: T | Partial<T> | ((s: T) => T | Partial<T>), replace?: boolean) => void;
10
5
  type ModelHook<T> = {
11
6
  (): T;
12
- <U>(selector: Selector<T, U>, equalityFn?: EqualityFn<U>): U;
7
+ <U>(sel: Selector<T, U>, eq?: EqualityFn<U>): U;
8
+ };
9
+ type StorageEngine = {
10
+ getItem(key: string): string | null | Promise<string | null>;
11
+ setItem(key: string, value: string): void | Promise<void>;
12
+ removeItem(key: string): void | Promise<void>;
13
13
  };
14
14
  interface PersistOptions<T> {
15
15
  key: string;
16
16
  storage?: StorageEngine;
17
17
  debounce?: number;
18
- beforePersist?: (state: T) => any;
19
- beforeRecover?: (value: any) => T | Partial<T>;
20
- }
21
- interface Logger {
22
- warn: (...args: any[]) => void;
23
- error: (...args: any[]) => void;
18
+ beforePersist?(state: T): any;
19
+ beforeRecover?(value: any): T | Partial<T>;
24
20
  }
25
21
  interface CreateModelOptions<T> {
26
22
  persist?: string | PersistOptions<T>;
27
- logger?: Logger;
23
+ logger?: {
24
+ warn(...a: any[]): void;
25
+ error(...a: any[]): void;
26
+ };
28
27
  strict?: {
29
28
  forbidSetStateAfterDestroy?: boolean;
30
29
  };
31
30
  }
32
31
  interface SubscribeWithSelectorOptions<U> {
33
- equalityFn?: EqualityFn<U>;
32
+ equalityFn?(a: U, b: U): boolean;
34
33
  fireImmediately?: boolean;
35
34
  }
36
35
  interface Subscribe<T> {
37
36
  (listener: Listener<T>): () => void;
38
- <U>(selector: Selector<T, U>, listener: (selected: U, prevSelected: U) => void, options?: SubscribeWithSelectorOptions<U>): () => void;
37
+ <U>(sel: Selector<T, U>, fn: (s: U, p: U) => void, opts?: SubscribeWithSelectorOptions<U>): () => void;
39
38
  }
40
39
  interface ModelData<T> {
41
- getState: () => T;
42
- setState: (partial: T | Partial<T> | ((state: T) => T | Partial<T>), replace?: boolean) => void;
40
+ getState(): T;
41
+ setState: SetState<T>;
43
42
  subscribe: Subscribe<T>;
44
- destroy: () => void;
45
- reset: () => void;
43
+ destroy(): void;
44
+ reset(): void;
46
45
  state: T;
47
46
  }
48
47
  type Model<T> = ModelHook<T> & {
49
48
  getState: ModelHook<T>;
50
49
  useState: ModelHook<T>;
51
- setState: (partial: T | Partial<T> | ((state: T) => T | Partial<T>), replace?: boolean) => void;
52
- destroy: () => void;
53
- reset: () => void;
54
- data: ModelData<T>;
55
50
  use: ModelHook<T>;
51
+ setState: SetState<T>;
52
+ destroy(): void;
53
+ reset(): void;
54
+ data: ModelData<T>;
55
+ };
56
+ declare function shallow<T>(a: T, b: T): boolean;
57
+ declare function debounce<T extends (...a: any[]) => any>(fn: T, ms: number): {
58
+ (...a: Parameters<T>): void;
59
+ flush(): void;
60
+ cancel(): void;
61
+ };
62
+ declare const createStore: <T>(init: T) => {
63
+ getState: () => T;
64
+ getInitialState: () => T;
65
+ setState(partial: T | Partial<T> | ((s: T) => T | Partial<T>), replace?: boolean): void;
66
+ subscribe(l: Listener<T>): () => void;
67
+ destroy(): void;
56
68
  };
57
69
  declare function createModel<T>(initialState: T | (() => T), options?: CreateModelOptions<T>): Model<T>;
58
70
 
59
- declare function shallow<T>(objA: T, objB: T): boolean;
60
-
61
- export { type CreateModelOptions, type Model, type ModelData, type PersistOptions, type StorageEngine, type SubscribeWithSelectorOptions, createModel, shallow };
71
+ export { type CreateModelOptions, type Model, type ModelData, type PersistOptions, type StorageEngine, type SubscribeWithSelectorOptions, createModel, createStore, debounce, shallow };
package/dist/index.js CHANGED
@@ -1,254 +1 @@
1
- 'use strict';
2
-
3
- var useSyncExternalStoreExports = require('use-sync-external-store/shim/with-selector');
4
- var AsyncStorage = require('@react-native-async-storage/async-storage');
5
-
6
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
-
8
- var useSyncExternalStoreExports__default = /*#__PURE__*/_interopDefault(useSyncExternalStoreExports);
9
- var AsyncStorage__default = /*#__PURE__*/_interopDefault(AsyncStorage);
10
-
11
- // src/createModel.ts
12
-
13
- // src/vanilla.ts
14
- function isPlainObject(value) {
15
- if (Object.prototype.toString.call(value) !== "[object Object]") {
16
- return false;
17
- }
18
- const proto = Object.getPrototypeOf(value);
19
- return proto === Object.prototype || proto === null;
20
- }
21
- var createStore = (initialState) => {
22
- let state = initialState;
23
- const listeners = /* @__PURE__ */ new Set();
24
- const setState = (partial, replace) => {
25
- const nextState = typeof partial === "function" ? partial(state) : partial;
26
- if (!Object.is(nextState, state)) {
27
- const previousState = state;
28
- const shouldReplace = replace != null ? replace : !isPlainObject(state) || !isPlainObject(nextState);
29
- state = shouldReplace ? nextState : Object.assign({}, state, nextState);
30
- const snapshot = new Set(listeners);
31
- snapshot.forEach((listener) => listener(state, previousState));
32
- }
33
- };
34
- const getState = () => state;
35
- const getInitialState = () => initialState;
36
- const subscribe = (listener) => {
37
- listeners.add(listener);
38
- return () => listeners.delete(listener);
39
- };
40
- const destroy = () => {
41
- listeners.clear();
42
- };
43
- return { getState, getInitialState, setState, subscribe, destroy };
44
- };
45
-
46
- // src/utils.ts
47
- function shallow(objA, objB) {
48
- if (Object.is(objA, objB)) {
49
- return true;
50
- }
51
- if (typeof objA !== "object" || objA === null || typeof objB !== "object" || objB === null) {
52
- return false;
53
- }
54
- const keysA = Object.keys(objA);
55
- const keysB = Object.keys(objB);
56
- if (keysA.length !== keysB.length) {
57
- return false;
58
- }
59
- for (let i = 0; i < keysA.length; i++) {
60
- if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !Object.is(objA[keysA[i]], objB[keysA[i]])) {
61
- return false;
62
- }
63
- }
64
- return true;
65
- }
66
- function debounce(func, wait) {
67
- let timeout;
68
- let lastArgs;
69
- let context;
70
- const debounced = function(...args) {
71
- context = this;
72
- lastArgs = args;
73
- clearTimeout(timeout);
74
- timeout = setTimeout(() => {
75
- func.apply(context, args);
76
- lastArgs = void 0;
77
- timeout = void 0;
78
- }, wait);
79
- };
80
- debounced.flush = () => {
81
- if (timeout && lastArgs) {
82
- clearTimeout(timeout);
83
- func.apply(context, lastArgs);
84
- lastArgs = void 0;
85
- timeout = void 0;
86
- }
87
- };
88
- debounced.cancel = () => {
89
- clearTimeout(timeout);
90
- lastArgs = void 0;
91
- timeout = void 0;
92
- };
93
- return debounced;
94
- }
95
-
96
- // src/createModel.ts
97
- var { useSyncExternalStoreWithSelector } = useSyncExternalStoreExports__default.default;
98
- var identity = (v) => v;
99
- function isInvalidHookCallError(error) {
100
- return error instanceof Error && /Invalid hook call|Hooks can only be called/i.test(error.message);
101
- }
102
- function createModel(initialState, options) {
103
- var _a;
104
- const initialValue = typeof initialState === "function" ? initialState() : initialState;
105
- const store = createStore(initialValue);
106
- const logger = (_a = options == null ? void 0 : options.logger) != null ? _a : console;
107
- setupModelSideEffects(store, options, logger);
108
- let isDestroyed = false;
109
- const setState = (partial, replace) => {
110
- var _a2;
111
- if (isDestroyed && ((_a2 = options == null ? void 0 : options.strict) == null ? void 0 : _a2.forbidSetStateAfterDestroy)) {
112
- const error = new Error("[react-native-hox] model \u5DF2\u9500\u6BC1\uFF0C\u65E0\u6CD5\u518D\u8C03\u7528 setState\u3002");
113
- logger.error(error);
114
- throw error;
115
- }
116
- store.setState(partial, replace);
117
- };
118
- const destroy = () => {
119
- isDestroyed = true;
120
- store.destroy();
121
- };
122
- const reset = () => setState(initialValue, true);
123
- const subscribe = createSubscribe(store);
124
- const data = {
125
- getState: store.getState,
126
- setState,
127
- subscribe,
128
- destroy,
129
- reset
130
- };
131
- Object.defineProperty(data, "state", {
132
- get: () => store.getState(),
133
- enumerable: true
134
- });
135
- const hook = createModelHook(store);
136
- const model = {
137
- getState: hook,
138
- useState: hook,
139
- use: hook,
140
- // Add 'use' alias
141
- setState,
142
- reset,
143
- destroy,
144
- data
145
- };
146
- const modelFn = function(selector, equalityFn) {
147
- return hook(selector, equalityFn);
148
- };
149
- Object.assign(modelFn, model);
150
- return modelFn;
151
- }
152
- function createSubscribe(store) {
153
- return ((arg1, arg2, arg3) => {
154
- var _a;
155
- if (typeof arg1 === "function" && typeof arg2 !== "function") {
156
- return store.subscribe(arg1);
157
- }
158
- const selector = arg1;
159
- const listener = arg2;
160
- const options = arg3 != null ? arg3 : {};
161
- const equalityFn = (_a = options.equalityFn) != null ? _a : Object.is;
162
- let lastSelected = selector(store.getState());
163
- if (options.fireImmediately) {
164
- listener(lastSelected, lastSelected);
165
- }
166
- return store.subscribe((nextState) => {
167
- const nextSelected = selector(nextState);
168
- if (equalityFn(lastSelected, nextSelected)) {
169
- return;
170
- }
171
- const prevSelected = lastSelected;
172
- lastSelected = nextSelected;
173
- listener(nextSelected, prevSelected);
174
- });
175
- });
176
- }
177
- function createModelHook(store) {
178
- const useModel = ((selector, equalityFn = shallow) => {
179
- try {
180
- return useSyncExternalStoreWithSelector(
181
- store.subscribe,
182
- store.getState,
183
- store.getInitialState,
184
- selector != null ? selector : identity,
185
- equalityFn
186
- );
187
- } catch (error) {
188
- if (isInvalidHookCallError(error)) {
189
- throw new Error(
190
- "[react-native-hox] \u4F60\u6B63\u5728\u7EC4\u4EF6\u5916\u8C03\u7528 Hook \u8BFB\u53D6\u72B6\u6001\uFF1B\u8BF7\u5728\u7EC4\u4EF6\u5185\u4F7F\u7528 `model()` / `model.use()` / `model.getState()` / `model.useState()`\uFF0C\u7EC4\u4EF6\u5916\u8BF7\u4F7F\u7528 `model.data.getState()` / `model.data.state`\u3002"
191
- );
192
- }
193
- throw error;
194
- }
195
- });
196
- return useModel;
197
- }
198
- function setupModelSideEffects(store, options, logger) {
199
- var _a, _b, _c, _d;
200
- const persist = typeof (options == null ? void 0 : options.persist) === "string" ? { key: options.persist } : options == null ? void 0 : options.persist;
201
- const persistKey = persist == null ? void 0 : persist.key;
202
- const storage = (_a = persist == null ? void 0 : persist.storage) != null ? _a : AsyncStorage__default.default;
203
- if (!persistKey) {
204
- return;
205
- }
206
- const beforePersist = (_b = persist == null ? void 0 : persist.beforePersist) != null ? _b : ((s) => s);
207
- const beforeRecover = (_c = persist == null ? void 0 : persist.beforeRecover) != null ? _c : ((v) => v);
208
- const debounceMs = (_d = persist == null ? void 0 : persist.debounce) != null ? _d : 100;
209
- if (!storage) {
210
- logger.warn(
211
- "[react-native-hox] persist \u5DF2\u5F00\u542F\u4F46 storage \u4E0D\u53EF\u7528\uFF1A\u8BF7\u5728 persist.storage \u4F20\u5165 AsyncStorage/MMKV \u7B49\u3002"
212
- );
213
- return;
214
- }
215
- let isDestroyed = false;
216
- Promise.resolve().then(() => storage.getItem(persistKey)).then((val) => {
217
- if (isDestroyed) return;
218
- if (!val) return;
219
- try {
220
- const parsed = JSON.parse(val);
221
- const recovered = beforeRecover(parsed);
222
- store.setState(recovered, false);
223
- } catch (e) {
224
- logger.error("[react-native-hox] Failed to parse stored value:", e);
225
- }
226
- }).catch((e) => {
227
- logger.error("[react-native-hox] Recover failed:", e);
228
- });
229
- const save = debounce((state) => {
230
- if (isDestroyed) return;
231
- try {
232
- const prepared = beforePersist(state);
233
- const result = storage.setItem(persistKey, JSON.stringify(prepared));
234
- Promise.resolve(result).catch((e) => {
235
- logger.error("[react-native-hox] Save failed:", e);
236
- });
237
- } catch (e) {
238
- logger.error("[react-native-hox] Save failed:", e);
239
- }
240
- }, debounceMs);
241
- const unsubscribe = store.subscribe((state) => {
242
- save(state);
243
- });
244
- const originalDestroy = store.destroy;
245
- store.destroy = () => {
246
- unsubscribe();
247
- save.flush();
248
- isDestroyed = true;
249
- originalDestroy();
250
- };
251
- }
252
-
253
- exports.createModel = createModel;
254
- exports.shallow = shallow;
1
+ 'use strict';var E=require('use-sync-external-store/shim/with-selector'),w=require('@react-native-async-storage/async-storage');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var E__default=/*#__PURE__*/_interopDefault(E);var w__default=/*#__PURE__*/_interopDefault(w);var I=E__default.default.useSyncExternalStoreWithSelector,M=o=>{if(Object.prototype.toString.call(o)!=="[object Object]")return false;let e=Object.getPrototypeOf(o);return e===Object.prototype||e===null};function H(o,e){if(Object.is(o,e))return true;if(typeof o!="object"||!o||typeof e!="object"||!e)return false;let r=Object.keys(o);return r.length===Object.keys(e).length&&r.every(t=>Object.prototype.hasOwnProperty.call(e,t)&&Object.is(o[t],e[t]))}function q(o,e){let r,t,n=function(...l){t=l,clearTimeout(r),r=setTimeout(()=>{o(...l),t=r=void 0;},e);};return n.flush=()=>{r&&t&&(clearTimeout(r),o(...t),t=r=void 0);},n.cancel=()=>{clearTimeout(r),t=r=void 0;},n}var F=o=>{let e=o,r=new Set;return {getState:()=>e,getInitialState:()=>o,setState(t,n){let l=typeof t=="function"?t(e):t;if(!Object.is(l,e)){let f=e;e=(n!=null?n:!M(e)||!M(l))?l:{...e,...l},new Set(r).forEach(S=>S(e,f));}},subscribe(t){return r.add(t),()=>{r.delete(t);}},destroy(){r.clear();}}};function L(o,e){var h,O,k,x,P;let r=typeof o=="function"?o():o,t=F(r),n=(h=e==null?void 0:e.logger)!=null?h:console,l=false,f,S=(s,c)=>{var i;if(l&&((i=e==null?void 0:e.strict)!=null&&i.forbidSetStateAfterDestroy)){let u=new Error("[react-native-hox] model \u5DF2\u9500\u6BC1\uFF0C\u65E0\u6CD5\u518D\u8C03\u7528 setState\u3002");throw n.error(u),u}t.setState(s,c);},d=typeof(e==null?void 0:e.persist)=="string"?{key:e.persist}:e==null?void 0:e.persist;if(d!=null&&d.key){let s=(O=d.storage)!=null?O:w__default.default;if(s){let c=(k=d.beforePersist)!=null?k:(a=>a),i=(x=d.beforeRecover)!=null?x:(a=>a),u=false;Promise.resolve().then(()=>s.getItem(d.key)).then(a=>{if(!(u||!a))try{t.setState(i(JSON.parse(a)),!1);}catch(y){n.error("[react-native-hox] Failed to parse stored value:",y);}}).catch(a=>n.error("[react-native-hox] Recover failed:",a));let T=q(a=>{if(!u)try{Promise.resolve(s.setItem(d.key,JSON.stringify(c(a)))).catch(y=>n.error("[react-native-hox] Save failed:",y));}catch(y){n.error("[react-native-hox] Save failed:",y);}},(P=d.debounce)!=null?P:100),g=t.subscribe(a=>T(a));f=()=>{g(),T.flush(),u=true;};}else n.warn("[react-native-hox] persist \u5DF2\u5F00\u542F\u4F46 storage \u4E0D\u53EF\u7528\uFF1A\u8BF7\u5728 persist.storage \u4F20\u5165 AsyncStorage/MMKV \u7B49\u3002");}let v=()=>{f==null||f(),l=true,t.destroy();},p=()=>S(r,true),U=((s,c,i)=>{if(typeof s=="function"&&typeof c!="function")return t.subscribe(s);let u=i!=null?i:{},T=s(t.getState());return u.fireImmediately&&c(T,T),t.subscribe(g=>{var y;let a=s(g);if(!((y=u.equalityFn)!=null?y:Object.is)(T,a)){let j=T;T=a,c(a,j);}})}),b=((s,c=H)=>{try{return I(t.subscribe,t.getState,t.getInitialState,s!=null?s:(i=>i),c)}catch(i){throw i instanceof Error&&/Invalid hook call|Hooks can only be called/i.test(i.message)?new Error("[react-native-hox] \u7EC4\u4EF6\u5916\u8BF7\u4F7F\u7528 model.data.getState() / model.data.state"):i}}),m={getState:t.getState,setState:S,subscribe:U,destroy:v,reset:p};return Object.defineProperty(m,"state",{get:t.getState,enumerable:true}),Object.assign((s,c)=>b(s,c),{getState:b,useState:b,use:b,setState:S,destroy:v,reset:p,data:m})}exports.createModel=L;exports.createStore=F;exports.debounce=q;exports.shallow=H;
package/dist/index.mjs CHANGED
@@ -1,246 +1 @@
1
- import useSyncExternalStoreExports from 'use-sync-external-store/shim/with-selector';
2
- import AsyncStorage from '@react-native-async-storage/async-storage';
3
-
4
- // src/createModel.ts
5
-
6
- // src/vanilla.ts
7
- function isPlainObject(value) {
8
- if (Object.prototype.toString.call(value) !== "[object Object]") {
9
- return false;
10
- }
11
- const proto = Object.getPrototypeOf(value);
12
- return proto === Object.prototype || proto === null;
13
- }
14
- var createStore = (initialState) => {
15
- let state = initialState;
16
- const listeners = /* @__PURE__ */ new Set();
17
- const setState = (partial, replace) => {
18
- const nextState = typeof partial === "function" ? partial(state) : partial;
19
- if (!Object.is(nextState, state)) {
20
- const previousState = state;
21
- const shouldReplace = replace != null ? replace : !isPlainObject(state) || !isPlainObject(nextState);
22
- state = shouldReplace ? nextState : Object.assign({}, state, nextState);
23
- const snapshot = new Set(listeners);
24
- snapshot.forEach((listener) => listener(state, previousState));
25
- }
26
- };
27
- const getState = () => state;
28
- const getInitialState = () => initialState;
29
- const subscribe = (listener) => {
30
- listeners.add(listener);
31
- return () => listeners.delete(listener);
32
- };
33
- const destroy = () => {
34
- listeners.clear();
35
- };
36
- return { getState, getInitialState, setState, subscribe, destroy };
37
- };
38
-
39
- // src/utils.ts
40
- function shallow(objA, objB) {
41
- if (Object.is(objA, objB)) {
42
- return true;
43
- }
44
- if (typeof objA !== "object" || objA === null || typeof objB !== "object" || objB === null) {
45
- return false;
46
- }
47
- const keysA = Object.keys(objA);
48
- const keysB = Object.keys(objB);
49
- if (keysA.length !== keysB.length) {
50
- return false;
51
- }
52
- for (let i = 0; i < keysA.length; i++) {
53
- if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !Object.is(objA[keysA[i]], objB[keysA[i]])) {
54
- return false;
55
- }
56
- }
57
- return true;
58
- }
59
- function debounce(func, wait) {
60
- let timeout;
61
- let lastArgs;
62
- let context;
63
- const debounced = function(...args) {
64
- context = this;
65
- lastArgs = args;
66
- clearTimeout(timeout);
67
- timeout = setTimeout(() => {
68
- func.apply(context, args);
69
- lastArgs = void 0;
70
- timeout = void 0;
71
- }, wait);
72
- };
73
- debounced.flush = () => {
74
- if (timeout && lastArgs) {
75
- clearTimeout(timeout);
76
- func.apply(context, lastArgs);
77
- lastArgs = void 0;
78
- timeout = void 0;
79
- }
80
- };
81
- debounced.cancel = () => {
82
- clearTimeout(timeout);
83
- lastArgs = void 0;
84
- timeout = void 0;
85
- };
86
- return debounced;
87
- }
88
-
89
- // src/createModel.ts
90
- var { useSyncExternalStoreWithSelector } = useSyncExternalStoreExports;
91
- var identity = (v) => v;
92
- function isInvalidHookCallError(error) {
93
- return error instanceof Error && /Invalid hook call|Hooks can only be called/i.test(error.message);
94
- }
95
- function createModel(initialState, options) {
96
- var _a;
97
- const initialValue = typeof initialState === "function" ? initialState() : initialState;
98
- const store = createStore(initialValue);
99
- const logger = (_a = options == null ? void 0 : options.logger) != null ? _a : console;
100
- setupModelSideEffects(store, options, logger);
101
- let isDestroyed = false;
102
- const setState = (partial, replace) => {
103
- var _a2;
104
- if (isDestroyed && ((_a2 = options == null ? void 0 : options.strict) == null ? void 0 : _a2.forbidSetStateAfterDestroy)) {
105
- const error = new Error("[react-native-hox] model \u5DF2\u9500\u6BC1\uFF0C\u65E0\u6CD5\u518D\u8C03\u7528 setState\u3002");
106
- logger.error(error);
107
- throw error;
108
- }
109
- store.setState(partial, replace);
110
- };
111
- const destroy = () => {
112
- isDestroyed = true;
113
- store.destroy();
114
- };
115
- const reset = () => setState(initialValue, true);
116
- const subscribe = createSubscribe(store);
117
- const data = {
118
- getState: store.getState,
119
- setState,
120
- subscribe,
121
- destroy,
122
- reset
123
- };
124
- Object.defineProperty(data, "state", {
125
- get: () => store.getState(),
126
- enumerable: true
127
- });
128
- const hook = createModelHook(store);
129
- const model = {
130
- getState: hook,
131
- useState: hook,
132
- use: hook,
133
- // Add 'use' alias
134
- setState,
135
- reset,
136
- destroy,
137
- data
138
- };
139
- const modelFn = function(selector, equalityFn) {
140
- return hook(selector, equalityFn);
141
- };
142
- Object.assign(modelFn, model);
143
- return modelFn;
144
- }
145
- function createSubscribe(store) {
146
- return ((arg1, arg2, arg3) => {
147
- var _a;
148
- if (typeof arg1 === "function" && typeof arg2 !== "function") {
149
- return store.subscribe(arg1);
150
- }
151
- const selector = arg1;
152
- const listener = arg2;
153
- const options = arg3 != null ? arg3 : {};
154
- const equalityFn = (_a = options.equalityFn) != null ? _a : Object.is;
155
- let lastSelected = selector(store.getState());
156
- if (options.fireImmediately) {
157
- listener(lastSelected, lastSelected);
158
- }
159
- return store.subscribe((nextState) => {
160
- const nextSelected = selector(nextState);
161
- if (equalityFn(lastSelected, nextSelected)) {
162
- return;
163
- }
164
- const prevSelected = lastSelected;
165
- lastSelected = nextSelected;
166
- listener(nextSelected, prevSelected);
167
- });
168
- });
169
- }
170
- function createModelHook(store) {
171
- const useModel = ((selector, equalityFn = shallow) => {
172
- try {
173
- return useSyncExternalStoreWithSelector(
174
- store.subscribe,
175
- store.getState,
176
- store.getInitialState,
177
- selector != null ? selector : identity,
178
- equalityFn
179
- );
180
- } catch (error) {
181
- if (isInvalidHookCallError(error)) {
182
- throw new Error(
183
- "[react-native-hox] \u4F60\u6B63\u5728\u7EC4\u4EF6\u5916\u8C03\u7528 Hook \u8BFB\u53D6\u72B6\u6001\uFF1B\u8BF7\u5728\u7EC4\u4EF6\u5185\u4F7F\u7528 `model()` / `model.use()` / `model.getState()` / `model.useState()`\uFF0C\u7EC4\u4EF6\u5916\u8BF7\u4F7F\u7528 `model.data.getState()` / `model.data.state`\u3002"
184
- );
185
- }
186
- throw error;
187
- }
188
- });
189
- return useModel;
190
- }
191
- function setupModelSideEffects(store, options, logger) {
192
- var _a, _b, _c, _d;
193
- const persist = typeof (options == null ? void 0 : options.persist) === "string" ? { key: options.persist } : options == null ? void 0 : options.persist;
194
- const persistKey = persist == null ? void 0 : persist.key;
195
- const storage = (_a = persist == null ? void 0 : persist.storage) != null ? _a : AsyncStorage;
196
- if (!persistKey) {
197
- return;
198
- }
199
- const beforePersist = (_b = persist == null ? void 0 : persist.beforePersist) != null ? _b : ((s) => s);
200
- const beforeRecover = (_c = persist == null ? void 0 : persist.beforeRecover) != null ? _c : ((v) => v);
201
- const debounceMs = (_d = persist == null ? void 0 : persist.debounce) != null ? _d : 100;
202
- if (!storage) {
203
- logger.warn(
204
- "[react-native-hox] persist \u5DF2\u5F00\u542F\u4F46 storage \u4E0D\u53EF\u7528\uFF1A\u8BF7\u5728 persist.storage \u4F20\u5165 AsyncStorage/MMKV \u7B49\u3002"
205
- );
206
- return;
207
- }
208
- let isDestroyed = false;
209
- Promise.resolve().then(() => storage.getItem(persistKey)).then((val) => {
210
- if (isDestroyed) return;
211
- if (!val) return;
212
- try {
213
- const parsed = JSON.parse(val);
214
- const recovered = beforeRecover(parsed);
215
- store.setState(recovered, false);
216
- } catch (e) {
217
- logger.error("[react-native-hox] Failed to parse stored value:", e);
218
- }
219
- }).catch((e) => {
220
- logger.error("[react-native-hox] Recover failed:", e);
221
- });
222
- const save = debounce((state) => {
223
- if (isDestroyed) return;
224
- try {
225
- const prepared = beforePersist(state);
226
- const result = storage.setItem(persistKey, JSON.stringify(prepared));
227
- Promise.resolve(result).catch((e) => {
228
- logger.error("[react-native-hox] Save failed:", e);
229
- });
230
- } catch (e) {
231
- logger.error("[react-native-hox] Save failed:", e);
232
- }
233
- }, debounceMs);
234
- const unsubscribe = store.subscribe((state) => {
235
- save(state);
236
- });
237
- const originalDestroy = store.destroy;
238
- store.destroy = () => {
239
- unsubscribe();
240
- save.flush();
241
- isDestroyed = true;
242
- originalDestroy();
243
- };
244
- }
245
-
246
- export { createModel, shallow };
1
+ import E from'use-sync-external-store/shim/with-selector';import w from'@react-native-async-storage/async-storage';var I=E.useSyncExternalStoreWithSelector,M=o=>{if(Object.prototype.toString.call(o)!=="[object Object]")return false;let e=Object.getPrototypeOf(o);return e===Object.prototype||e===null};function H(o,e){if(Object.is(o,e))return true;if(typeof o!="object"||!o||typeof e!="object"||!e)return false;let r=Object.keys(o);return r.length===Object.keys(e).length&&r.every(t=>Object.prototype.hasOwnProperty.call(e,t)&&Object.is(o[t],e[t]))}function q(o,e){let r,t,n=function(...l){t=l,clearTimeout(r),r=setTimeout(()=>{o(...l),t=r=void 0;},e);};return n.flush=()=>{r&&t&&(clearTimeout(r),o(...t),t=r=void 0);},n.cancel=()=>{clearTimeout(r),t=r=void 0;},n}var F=o=>{let e=o,r=new Set;return {getState:()=>e,getInitialState:()=>o,setState(t,n){let l=typeof t=="function"?t(e):t;if(!Object.is(l,e)){let f=e;e=(n!=null?n:!M(e)||!M(l))?l:{...e,...l},new Set(r).forEach(S=>S(e,f));}},subscribe(t){return r.add(t),()=>{r.delete(t);}},destroy(){r.clear();}}};function L(o,e){var h,O,k,x,P;let r=typeof o=="function"?o():o,t=F(r),n=(h=e==null?void 0:e.logger)!=null?h:console,l=false,f,S=(s,c)=>{var i;if(l&&((i=e==null?void 0:e.strict)!=null&&i.forbidSetStateAfterDestroy)){let u=new Error("[react-native-hox] model \u5DF2\u9500\u6BC1\uFF0C\u65E0\u6CD5\u518D\u8C03\u7528 setState\u3002");throw n.error(u),u}t.setState(s,c);},d=typeof(e==null?void 0:e.persist)=="string"?{key:e.persist}:e==null?void 0:e.persist;if(d!=null&&d.key){let s=(O=d.storage)!=null?O:w;if(s){let c=(k=d.beforePersist)!=null?k:(a=>a),i=(x=d.beforeRecover)!=null?x:(a=>a),u=false;Promise.resolve().then(()=>s.getItem(d.key)).then(a=>{if(!(u||!a))try{t.setState(i(JSON.parse(a)),!1);}catch(y){n.error("[react-native-hox] Failed to parse stored value:",y);}}).catch(a=>n.error("[react-native-hox] Recover failed:",a));let T=q(a=>{if(!u)try{Promise.resolve(s.setItem(d.key,JSON.stringify(c(a)))).catch(y=>n.error("[react-native-hox] Save failed:",y));}catch(y){n.error("[react-native-hox] Save failed:",y);}},(P=d.debounce)!=null?P:100),g=t.subscribe(a=>T(a));f=()=>{g(),T.flush(),u=true;};}else n.warn("[react-native-hox] persist \u5DF2\u5F00\u542F\u4F46 storage \u4E0D\u53EF\u7528\uFF1A\u8BF7\u5728 persist.storage \u4F20\u5165 AsyncStorage/MMKV \u7B49\u3002");}let v=()=>{f==null||f(),l=true,t.destroy();},p=()=>S(r,true),U=((s,c,i)=>{if(typeof s=="function"&&typeof c!="function")return t.subscribe(s);let u=i!=null?i:{},T=s(t.getState());return u.fireImmediately&&c(T,T),t.subscribe(g=>{var y;let a=s(g);if(!((y=u.equalityFn)!=null?y:Object.is)(T,a)){let j=T;T=a,c(a,j);}})}),b=((s,c=H)=>{try{return I(t.subscribe,t.getState,t.getInitialState,s!=null?s:(i=>i),c)}catch(i){throw i instanceof Error&&/Invalid hook call|Hooks can only be called/i.test(i.message)?new Error("[react-native-hox] \u7EC4\u4EF6\u5916\u8BF7\u4F7F\u7528 model.data.getState() / model.data.state"):i}}),m={getState:t.getState,setState:S,subscribe:U,destroy:v,reset:p};return Object.defineProperty(m,"state",{get:t.getState,enumerable:true}),Object.assign((s,c)=>b(s,c),{getState:b,useState:b,use:b,setState:S,destroy:v,reset:p,data:m})}export{L as createModel,F as createStore,q as debounce,H as shallow};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-hox",
3
- "version": "0.0.3",
3
+ "version": "1.0.1",
4
4
  "description": "一个轻量级、类型安全、零心智负担的 React Native 状态管理解决方案。",
5
5
  "keywords": [
6
6
  "react-native",
@@ -20,7 +20,7 @@
20
20
  },
21
21
  "homepage": "https://gitee.com/ws18250840411/react-native-hox#readme",
22
22
  "license": "ISC",
23
- "author": "wangws",
23
+ "author": "wangwenshan",
24
24
  "sideEffects": false,
25
25
  "main": "dist/index.js",
26
26
  "module": "dist/index.mjs",
@@ -46,12 +46,12 @@
46
46
  "prepack": "npm run build"
47
47
  },
48
48
  "dependencies": {
49
- "@react-native-async-storage/async-storage": "^2.2.0",
50
49
  "use-sync-external-store": "^1.6.0"
51
50
  },
52
51
  "peerDependencies": {
53
52
  "react": ">=16.8",
54
- "react-native": ">=0.65"
53
+ "react-native": ">=0.65",
54
+ "@react-native-async-storage/async-storage": ">=2.0.0"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@types/jest": "^30.0.0",