rxtutils 1.1.1 → 1.1.2-beta.2

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 ADDED
@@ -0,0 +1,404 @@
1
+ # RUtils
2
+
3
+ 一个功能丰富的 TypeScript 工具库,提供缓存管理、HTTP 请求和状态管理等功能。
4
+
5
+ ## 📦 安装
6
+
7
+ ```bash
8
+ npm install rxtutils
9
+ # 或
10
+ yarn add rxtutils
11
+ # 或
12
+ pnpm add rxtutils
13
+ ```
14
+
15
+ ## 🚀 功能特性
16
+
17
+ - **缓存管理** - 支持内存、localStorage、sessionStorage 和 IndexedDB 多种存储方式
18
+ - **HTTP 请求** - 基于 axios 的请求封装,支持错误处理和缓存
19
+ - **状态管理** - 轻量级的状态管理解决方案,支持 React Hook
20
+ - **TypeScript** - 完整的 TypeScript 类型支持
21
+
22
+ ## 📚 模块介绍
23
+
24
+ ### 1. 缓存管理 (Cache)
25
+
26
+ 提供灵活的缓存管理功能,支持多种存储方式。
27
+
28
+ #### 基本用法
29
+
30
+ ```typescript
31
+ import { Cache } from 'rxtutils';
32
+
33
+ // 创建内存缓存
34
+ const memoryCache = new Cache<string, any>();
35
+
36
+ // 创建 localStorage 缓存
37
+ const localCache = new Cache<string, any>('localStorage', 'myCache', 300);
38
+
39
+ // 创建 IndexedDB 缓存
40
+ const dbCache = new Cache<string, any>('indexedDB', 'dbCache', 600, 'myDatabase');
41
+ ```
42
+
43
+ #### 缓存操作
44
+
45
+ ```typescript
46
+ // 设置缓存
47
+ cache.setCache('key1', { data: 'value1' });
48
+ cache.setCache('key2', { data: 'value2' }, { cacheTime: 120 }); // 2分钟过期
49
+
50
+ // 获取缓存
51
+ const data = cache.getCache('key1');
52
+ console.log(data); // { data: 'value1' }
53
+
54
+ // 清空缓存
55
+ cache.clear();
56
+ ```
57
+
58
+ #### 高级配置
59
+
60
+ ```typescript
61
+ import { Cache } from 'rxtutils';
62
+
63
+ // 自定义比较函数
64
+ const customCache = new Cache<{ id: number; name: string }, any>(
65
+ 'localStorage',
66
+ 'customCache',
67
+ 300,
68
+ 'customDB',
69
+ (prev, next) => prev.id === next.id // 只比较 id 字段
70
+ );
71
+ ```
72
+
73
+ ### 2. HTTP 请求 (createBaseRequest)
74
+
75
+ 基于 axios 的请求封装,支持错误处理、缓存和自定义配置。
76
+
77
+ #### 基本用法
78
+
79
+ ```typescript
80
+ import { createBaseRequest } from 'rxtutils';
81
+
82
+ // 创建请求实例
83
+ const request = createBaseRequest({
84
+ baseURL: 'https://api.example.com',
85
+ throwError: true,
86
+ defaultMessageShower: (message) => console.log(message)
87
+ });
88
+
89
+ // 创建具体请求
90
+ const getUserInfo = request<{ id: number }, { name: string; email: string }>({
91
+ method: 'GET',
92
+ url: '/user/:id'
93
+ });
94
+
95
+ // 发送请求
96
+ const userInfo = await getUserInfo({ params: { id: 123 } });
97
+ ```
98
+
99
+ #### 错误处理
100
+
101
+ ```typescript
102
+ const request = createBaseRequest({
103
+ baseURL: 'https://api.example.com',
104
+ errorCodeMap: {
105
+ '400': '请求参数错误',
106
+ '401': '未授权,请重新登录',
107
+ '500': (code, data, res) => ({
108
+ replaceResData: { error: '服务器内部错误' },
109
+ throwError: false
110
+ })
111
+ },
112
+ httpErrorCodeMap: {
113
+ 404: '资源不存在',
114
+ 500: '服务器错误'
115
+ }
116
+ });
117
+ ```
118
+
119
+ #### 缓存功能
120
+
121
+ ```typescript
122
+ const request = createBaseRequest({
123
+ baseURL: 'https://api.example.com',
124
+ enableCache: true,
125
+ cacheData: true,
126
+ cacheDataInStorage: 'localStorage',
127
+ cacheDataKey: 'api-cache',
128
+ cacheTime: 300
129
+ });
130
+
131
+ // 第一次请求会从服务器获取数据
132
+ const data1 = await getUserInfo({ params: { id: 123 } });
133
+
134
+ // 第二次请求会从缓存获取数据
135
+ const data2 = await getUserInfo({ params: { id: 123 } });
136
+
137
+ // 清空缓存
138
+ getUserInfo.clearCache();
139
+ ```
140
+
141
+ ### 3. 状态管理 (createStateStore)
142
+
143
+ 轻量级的状态管理解决方案,支持组件间状态共享。
144
+
145
+ #### 基本用法
146
+
147
+ ```typescript
148
+ import { createStateStore } from 'rxtutils';
149
+
150
+ // 创建状态存储
151
+ const userStore = createStateStore({
152
+ name: '',
153
+ email: '',
154
+ isLoggedIn: false
155
+ });
156
+
157
+ // 在组件中使用
158
+ function UserComponent() {
159
+ const [user, setUser] = userStore.use();
160
+
161
+ const handleLogin = () => {
162
+ setUser({
163
+ name: 'John Doe',
164
+ email: 'john@example.com',
165
+ isLoggedIn: true
166
+ });
167
+ };
168
+
169
+ return (
170
+ <div>
171
+ <p>用户名: {user.name}</p>
172
+ <p>邮箱: {user.email}</p>
173
+ <button onClick={handleLogin}>登录</button>
174
+ </div>
175
+ );
176
+ }
177
+ ```
178
+
179
+ #### 状态监听
180
+
181
+ ```typescript
182
+ // 监听状态变化
183
+ const unsubscribe = userStore.watch((state) => {
184
+ console.log('状态已更新:', state);
185
+ });
186
+
187
+ // 取消监听
188
+ unsubscribe();
189
+ ```
190
+
191
+ #### 直接访问和设置
192
+
193
+ ```typescript
194
+ // 直接获取状态
195
+ const currentUser = userStore.get();
196
+
197
+ // 直接设置状态
198
+ userStore.set({ name: 'Jane Doe', email: 'jane@example.com', isLoggedIn: true });
199
+ ```
200
+
201
+ ### 4. 状态计算器 (createStoreGetter)
202
+
203
+ 为状态存储提供计算属性和派生状态。
204
+
205
+ #### 基本用法
206
+
207
+ ```typescript
208
+ import { createStoreGetter, createStoreGetterMemo } from 'rxtutils';
209
+
210
+ const userStore = createStateStore({
211
+ firstName: 'John',
212
+ lastName: 'Doe',
213
+ age: 30
214
+ });
215
+
216
+ // 创建 getter 函数
217
+ const getters = {
218
+ fullName: (state) => `${state.firstName} ${state.lastName}`,
219
+ isAdult: (state) => state.age >= 18,
220
+ displayName: (state) => state.firstName
221
+ };
222
+
223
+ // 创建 getter 名称映射
224
+ const getterNameMaps = {
225
+ fullName: 'fullName',
226
+ isAdult: 'isAdult',
227
+ displayName: 'displayName'
228
+ };
229
+
230
+ // 创建 getter 对象(非响应式)
231
+ const userGetters = createStoreGetter(userStore, getters, getterNameMaps);
232
+ console.log(userGetters.fullName); // "John Doe"
233
+
234
+ // 创建 getter memo hook(响应式)
235
+ const useUserGetters = createStoreGetterMemo(userStore, getters, getterNameMaps);
236
+
237
+ function UserProfile() {
238
+ const { fullName, isAdult, displayName } = useUserGetters();
239
+
240
+ return (
241
+ <div>
242
+ <h1>{fullName}</h1>
243
+ <p>成年人: {isAdult ? '是' : '否'}</p>
244
+ <p>显示名: {displayName}</p>
245
+ </div>
246
+ );
247
+ }
248
+ ```
249
+
250
+ ## 🔧 配置选项
251
+
252
+ ### Cache 配置
253
+
254
+ | 参数 | 类型 | 默认值 | 说明 |
255
+ |------|------|--------|------|
256
+ | `storageType` | `'sessionStorage' \| 'localStorage' \| 'indexedDB'` | `undefined` | 存储类型 |
257
+ | `cacheKey` | `string` | `undefined` | 缓存键名 |
258
+ | `cacheTime` | `number` | `60` | 缓存时间(秒) |
259
+ | `indexDBName` | `string` | `'__apiCacheDatabase__'` | IndexedDB 数据库名称 |
260
+ | `cacheKeyEquals` | `function` | `defaultEquals` | 缓存键比较函数 |
261
+
262
+ ### Request 配置
263
+
264
+ | 参数 | 类型 | 默认值 | 说明 |
265
+ |------|------|--------|------|
266
+ | `baseURL` | `string` | `''` | 请求基础URL |
267
+ | `throwError` | `boolean` | `true` | 是否抛出错误 |
268
+ | `enableCache` | `boolean` | `false` | 是否启用缓存 |
269
+ | `cacheData` | `boolean` | `false` | 是否缓存数据 |
270
+ | `cacheTime` | `number` | `60` | 缓存时间(秒) |
271
+ | `cacheDataInStorage` | `StorageType` | `undefined` | 缓存存储类型 |
272
+ | `errorCodePath` | `string` | `'code'` | 错误码路径 |
273
+ | `successCodes` | `string[]` | `['0', '200']` | 成功状态码 |
274
+
275
+ ## 📝 类型定义
276
+
277
+ ### 缓存相关类型
278
+
279
+ ```typescript
280
+ // 缓存项接口
281
+ interface ICache<Param, Data> {
282
+ params: Param;
283
+ data: Data;
284
+ expireTime: string;
285
+ }
286
+
287
+ // 缓存选项接口
288
+ interface ICacheOptions<Param> {
289
+ storageType?: StorageType;
290
+ cacheKey?: string;
291
+ cacheTime?: number;
292
+ cacheKeyEquals: (prev: Param, next: Param) => boolean;
293
+ indexDBName?: string;
294
+ }
295
+ ```
296
+
297
+ ### 请求相关类型
298
+
299
+ ```typescript
300
+ // 请求配置接口
301
+ interface Options<Params, Data> {
302
+ baseURL?: string;
303
+ throwError?: boolean;
304
+ enableCache?: boolean;
305
+ cacheData?: boolean;
306
+ cacheTime?: number;
307
+ errorCodeMap?: Record<string, string | Function>;
308
+ httpErrorCodeMap?: Record<string, string | Function>;
309
+ // ... 更多配置选项
310
+ }
311
+
312
+ // 请求参数接口
313
+ interface RequestOptions<Param> {
314
+ method: Method;
315
+ url: string;
316
+ data?: Param;
317
+ params?: Param;
318
+ }
319
+ ```
320
+
321
+ ### 状态管理相关类型
322
+
323
+ ```typescript
324
+ // 状态存储接口
325
+ interface StateStore<S> {
326
+ use: () => [S, (state: IHookStateSetAction<S>) => void];
327
+ get: () => S;
328
+ set: (state: IHookStateSetAction<S>) => void;
329
+ watch: (callback: (state: S) => void) => () => void;
330
+ }
331
+
332
+ // 状态设置动作类型
333
+ type IHookStateSetAction<S> = S | IHookStateSetter<S>;
334
+ ```
335
+
336
+ ## 🎯 使用场景
337
+
338
+ ### 1. API 数据缓存
339
+
340
+ ```typescript
341
+ // 创建带缓存的 API 请求
342
+ const apiRequest = createBaseRequest({
343
+ baseURL: 'https://api.example.com',
344
+ enableCache: true,
345
+ cacheData: true,
346
+ cacheDataInStorage: 'localStorage',
347
+ cacheTime: 300
348
+ });
349
+
350
+ const getProductList = apiRequest<{ page: number }, { products: Product[] }>({
351
+ method: 'GET',
352
+ url: '/products'
353
+ });
354
+ ```
355
+
356
+ ### 2. 用户状态管理
357
+
358
+ ```typescript
359
+ // 创建用户状态存储
360
+ const userStore = createStateStore({
361
+ user: null,
362
+ permissions: [],
363
+ theme: 'light'
364
+ });
365
+
366
+ // 创建用户相关的计算属性
367
+ const userGetters = createStoreGetter(userStore, {
368
+ isLoggedIn: (state) => !!state.user,
369
+ canEdit: (state) => state.permissions.includes('edit'),
370
+ isDarkTheme: (state) => state.theme === 'dark'
371
+ }, {
372
+ isLoggedIn: 'isLoggedIn',
373
+ canEdit: 'canEdit',
374
+ isDarkTheme: 'isDarkTheme'
375
+ });
376
+ ```
377
+
378
+ ### 3. 表单数据缓存
379
+
380
+ ```typescript
381
+ // 创建表单缓存
382
+ const formCache = new Cache<string, FormData>('sessionStorage', 'form-cache', 1800);
383
+
384
+ // 保存表单数据
385
+ formCache.setCache('user-form', formData);
386
+
387
+ // 恢复表单数据
388
+ const savedData = formCache.getCache('user-form');
389
+ ```
390
+
391
+ ## 🤝 贡献
392
+
393
+ 欢迎提交 Issue 和 Pull Request 来帮助改进这个项目。
394
+
395
+ ## 📄 许可证
396
+
397
+ MIT License
398
+
399
+ ## 🔗 相关链接
400
+
401
+ - [TypeScript](https://www.typescriptlang.org/)
402
+ - [React](https://reactjs.org/)
403
+ - [Axios](https://axios-http.com/)
404
+ - [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API)
@@ -2,10 +2,27 @@
2
2
 
3
3
  var index = require('./cache/index.cjs');
4
4
  var index$1 = require('./request/index.cjs');
5
- var index$2 = require('./createStateStore/index.cjs');
5
+ var index$3 = require('./store/createGetter/index.cjs');
6
+ var index$2 = require('./store/createStateStore/index.cjs');
7
+ var validator = require('./validator/validator.cjs');
8
+ var decorators = require('./validator/decorators.cjs');
6
9
 
7
10
 
8
11
 
9
12
  exports.Cache = index.default;
10
13
  exports.createBaseRequest = index$1;
14
+ exports.createStoreGetter = index$3.createStoreGetter;
15
+ exports.createStoreGetterMemo = index$3.createStoreGetterMemo;
11
16
  exports.createStateStore = index$2.default;
17
+ exports.BaseValidator = validator.BaseValidator;
18
+ exports.VArray = decorators.VArray;
19
+ exports.VBoolean = decorators.VBoolean;
20
+ exports.VEmail = decorators.VEmail;
21
+ exports.VMax = decorators.VMax;
22
+ exports.VMaxLength = decorators.VMaxLength;
23
+ exports.VMin = decorators.VMin;
24
+ exports.VMinLength = decorators.VMinLength;
25
+ exports.VNumber = decorators.VNumber;
26
+ exports.VPattern = decorators.VPattern;
27
+ exports.VRequired = decorators.VRequired;
28
+ exports.VString = decorators.VString;
@@ -38,7 +38,7 @@ function createBaseRequest(baseOptions) {
38
38
  if (method.toLowerCase() === 'post') {
39
39
  requestDataOrParams = data;
40
40
  }
41
- var _d = tslib.__assign(tslib.__assign(tslib.__assign({}, baseOptions), createOptions), options).defaultMessageShower, defaultMessageShower = _d === void 0 ? alert : _d;
41
+ var _d = tslib.__assign(tslib.__assign(tslib.__assign({}, baseOptions), createOptions), options).defaultMessageShower, defaultMessageShower = _d === void 0 ? console.error : _d;
42
42
  var _e = tslib.__assign(tslib.__assign(tslib.__assign({}, baseOptions), createOptions), options), _f = _e.enableCache, enableCache = _f === void 0 ? false : _f, _g = _e.cacheData, cacheData = _g === void 0 ? false : _g, _h = _e.defaultErrorCodeHandler, defaultErrorCodeHandler = _h === void 0 ? defaultHandlers._defaultErrorCodeHandler.bind(null, defaultMessageShower) : _h, _j = _e.defaultHttpErrorCodeHandler, defaultHttpErrorCodeHandler = _j === void 0 ? defaultHandlers._defaultHttpErrorCodeHandler.bind(null, defaultMessageShower) : _j, _k = _e.otherErrorHandler, otherErrorHandler = _k === void 0 ? defaultHandlers._defaultOtherErrorCodeHandler.bind(null, defaultMessageShower) : _k, _l = _e.errorCodePath, errorCodePath = _l === void 0 ? 'code' : _l, _m = _e.cacheTime, cacheTime = _m === void 0 ? 60 : _m, _o = _e.errorCodeMap, errorCodeMap = _o === void 0 ? {} : _o, _p = _e.successCodes, successCodes = _p === void 0 ? ['0', '200'] : _p, _q = _e.httpErrorCodeMap, httpErrorCodeMap = _q === void 0 ? {} : _q, _r = _e.axiosOptions, axiosOptions = _r === void 0 ? {} : _r, _s = _e.throwError, throwError = _s === void 0 ? true : _s;
43
43
  if (enableCache) {
44
44
  var cacheItem = cache.getCache(requestDataOrParams);
@@ -0,0 +1,45 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+
5
+ /**
6
+ * 创建 store getter
7
+ * @param store store实例
8
+ * @param getters getter函数
9
+ * @param getterNameMaps 将 getter 函数和 getter 名称一一映射
10
+ * @returns getter object
11
+ */
12
+ var createStoreGetter = function (store, getters, getterNameMaps) {
13
+ var gettersObj = {};
14
+ Object.keys(getters).forEach(function (key) {
15
+ Object.defineProperty(gettersObj, getterNameMaps[key], {
16
+ get: function () { return getters[key](store.get()); }
17
+ });
18
+ });
19
+ return gettersObj;
20
+ };
21
+ /**
22
+ *
23
+ * @param store store实例
24
+ * @param getters getter函数
25
+ * @param getterNameMaps 将 getter 函数和 getter 名称一一映射
26
+ * @returns getter memo hook
27
+ */
28
+ var createStoreGetterMemo = function (store, getters, getterNameMaps) {
29
+ // 创建缓存数据 hook
30
+ return function () {
31
+ var storeData = store.use()[0];
32
+ var reducedData = react.useMemo(function () {
33
+ return Object.keys(getters).reduce(function (acc, key) {
34
+ var mappedKey = getterNameMaps[key];
35
+ var getterValue = getters[key](storeData);
36
+ acc[mappedKey] = getterValue;
37
+ return acc;
38
+ }, {});
39
+ }, [storeData]);
40
+ return reducedData;
41
+ };
42
+ };
43
+
44
+ exports.createStoreGetter = createStoreGetter;
45
+ exports.createStoreGetterMemo = createStoreGetterMemo;
@@ -0,0 +1,104 @@
1
+ 'use strict';
2
+
3
+ var validator = require('./validator.cjs');
4
+
5
+ function VRequired(noneVals) {
6
+ if (noneVals === void 0) { noneVals = [undefined]; }
7
+ return validator.BaseValidator.decoratorCreator(function (val) {
8
+ if (noneVals.includes(val)) {
9
+ return false;
10
+ }
11
+ return true;
12
+ });
13
+ }
14
+ var VString = validator.BaseValidator.decoratorCreator(function (val) {
15
+ if (typeof val !== 'string') {
16
+ return false;
17
+ }
18
+ return true;
19
+ });
20
+ var VNumber = validator.BaseValidator.decoratorCreator(function (val) {
21
+ if (typeof val !== 'number') {
22
+ return false;
23
+ }
24
+ return true;
25
+ });
26
+ var VArray = validator.BaseValidator.decoratorCreator(function (val) {
27
+ if (!Array.isArray(val)) {
28
+ return false;
29
+ }
30
+ return true;
31
+ });
32
+ // 常用校验装饰器
33
+ var VBoolean = validator.BaseValidator.decoratorCreator(function (val) {
34
+ if (typeof val !== 'boolean') {
35
+ return false;
36
+ }
37
+ return true;
38
+ });
39
+ var VMin = function (min) {
40
+ return validator.BaseValidator.decoratorCreator(function (val) {
41
+ if (typeof val !== 'number' || val < min) {
42
+ return false;
43
+ }
44
+ return true;
45
+ });
46
+ };
47
+ var VMax = function (max) {
48
+ return validator.BaseValidator.decoratorCreator(function (val) {
49
+ if (typeof val !== 'number' || val > max) {
50
+ return false;
51
+ }
52
+ return true;
53
+ });
54
+ };
55
+ var VMinLength = function (minLen) {
56
+ return validator.BaseValidator.decoratorCreator(function (val) {
57
+ if (typeof val !== 'string' && !Array.isArray(val)) {
58
+ return false;
59
+ }
60
+ if (val.length < minLen) {
61
+ return false;
62
+ }
63
+ return true;
64
+ });
65
+ };
66
+ var VMaxLength = function (maxLen) {
67
+ return validator.BaseValidator.decoratorCreator(function (val) {
68
+ if (typeof val !== 'string' && !Array.isArray(val)) {
69
+ return false;
70
+ }
71
+ if (val.length > maxLen) {
72
+ return false;
73
+ }
74
+ return true;
75
+ });
76
+ };
77
+ var VEmail = validator.BaseValidator.decoratorCreator(function (val) {
78
+ if (typeof val !== 'string') {
79
+ return false;
80
+ }
81
+ // 简单邮箱正则
82
+ var emailReg = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
83
+ return emailReg.test(val);
84
+ });
85
+ var VPattern = function (pattern) {
86
+ return validator.BaseValidator.decoratorCreator(function (val) {
87
+ if (typeof val !== 'string') {
88
+ return false;
89
+ }
90
+ return pattern.test(val);
91
+ });
92
+ };
93
+
94
+ exports.VArray = VArray;
95
+ exports.VBoolean = VBoolean;
96
+ exports.VEmail = VEmail;
97
+ exports.VMax = VMax;
98
+ exports.VMaxLength = VMaxLength;
99
+ exports.VMin = VMin;
100
+ exports.VMinLength = VMinLength;
101
+ exports.VNumber = VNumber;
102
+ exports.VPattern = VPattern;
103
+ exports.VRequired = VRequired;
104
+ exports.VString = VString;
@@ -0,0 +1,124 @@
1
+ 'use strict';
2
+
3
+ var tslib = require('tslib');
4
+
5
+ var BaseValidator = /** @class */ (function () {
6
+ function BaseValidator() {
7
+ this.__keySymbol = Symbol('key-description');
8
+ this.__keySymbol = Symbol('key-description');
9
+ this[this.__keySymbol] = {};
10
+ }
11
+ BaseValidator.prototype.validate = function (itemKey, itemAll) {
12
+ if (itemAll === void 0) { itemAll = false; }
13
+ var validatorMap = this[this.__keySymbol];
14
+ var errors = [];
15
+ // 校验每个 key
16
+ var validators = validatorMap[itemKey];
17
+ if (!validators) {
18
+ return errors;
19
+ }
20
+ for (var _i = 0, validators_1 = validators; _i < validators_1.length; _i++) {
21
+ var validator = validators_1[_i];
22
+ var res = validator(this[itemKey]);
23
+ if (!res.status) {
24
+ errors.push(res);
25
+ if (!itemAll)
26
+ break;
27
+ }
28
+ }
29
+ if (errors.length) {
30
+ return errors;
31
+ }
32
+ return null;
33
+ };
34
+ BaseValidator.prototype.validateAll = function (itemAll, everyItem, order) {
35
+ if (itemAll === void 0) { itemAll = false; }
36
+ if (everyItem === void 0) { everyItem = false; }
37
+ var validatorMap = this[this.__keySymbol];
38
+ var errors = [];
39
+ // 校验每个 key
40
+ var keys = order || Object.keys(validatorMap);
41
+ for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
42
+ var key = keys_1[_i];
43
+ var value = this[key];
44
+ var fns = validatorMap[key];
45
+ // 校验每个校验项目
46
+ for (var _a = 0, fns_1 = fns; _a < fns_1.length; _a++) {
47
+ var fn = fns_1[_a];
48
+ var res = fn(value);
49
+ if (!res.status) {
50
+ errors.push(res);
51
+ if (!itemAll)
52
+ break;
53
+ }
54
+ }
55
+ if (!everyItem) {
56
+ break;
57
+ }
58
+ }
59
+ if (errors.length) {
60
+ return errors;
61
+ }
62
+ return null;
63
+ };
64
+ BaseValidator.decoratorCreator = function (func) {
65
+ return function (message) {
66
+ if (message === void 0) { message = function (val, value, context) { return "".concat(String(context.name), "\u683C\u5F0F\u9519\u8BEF"); }; }
67
+ return function (value, context) {
68
+ context.addInitializer(function () {
69
+ var validators = this[this.__keySymbol];
70
+ if (!validators) {
71
+ this[this.__keySymbol] = {};
72
+ validators = this[this.__keySymbol];
73
+ }
74
+ var name = context.name;
75
+ var validator = function (val) {
76
+ var validateStatus = func(val, value, context);
77
+ if (validateStatus) {
78
+ return { status: true };
79
+ }
80
+ else {
81
+ var msg = '';
82
+ if (typeof message === 'function') {
83
+ msg = message(val, value, context);
84
+ }
85
+ else {
86
+ msg = message;
87
+ }
88
+ return { status: false, message: msg };
89
+ }
90
+ };
91
+ if (validators[name]) {
92
+ validators[name] = tslib.__spreadArray(tslib.__spreadArray([], validators[name], true), [validator], false);
93
+ }
94
+ else {
95
+ validators[name] = [validator];
96
+ }
97
+ });
98
+ };
99
+ };
100
+ };
101
+ return BaseValidator;
102
+ }());
103
+ // class User extends BaseValidator{
104
+ // @VString('名称必须为字符串')
105
+ // @(VRequired()('名称必须填写'))
106
+ // name?: string;
107
+ // @VNumber('年龄必须为数字')
108
+ // @(VRequired()('年龄必须填写'))
109
+ // age?: number;
110
+ // @VEmail('邮箱格式不正确')
111
+ // @(VRequired()('邮箱必须填写'))
112
+ // email?: string;
113
+ // @(VMinLength(6)('密码长度不能少于6位'))
114
+ // @(VRequired()('密码必须填写'))
115
+ // password?: string
116
+ // }
117
+ // const user = new User();
118
+ // user.name = '张三'
119
+ // user.email = ' asdfasdf'
120
+ // user.password = '12345'
121
+ // console.log(user)
122
+ // console.log(user.validateAll(false,true,['password','age','email']));
123
+
124
+ exports.BaseValidator = BaseValidator;
package/dist/es/index.mjs CHANGED
@@ -1,3 +1,6 @@
1
1
  export { default as Cache } from './cache/index.mjs';
2
2
  export { default as createBaseRequest } from './request/index.mjs';
3
- export { default as createStateStore } from './createStateStore/index.mjs';
3
+ export { createStoreGetter, createStoreGetterMemo } from './store/createGetter/index.mjs';
4
+ export { default as createStateStore } from './store/createStateStore/index.mjs';
5
+ export { BaseValidator } from './validator/validator.mjs';
6
+ export { VArray, VBoolean, VEmail, VMax, VMaxLength, VMin, VMinLength, VNumber, VPattern, VRequired, VString } from './validator/decorators.mjs';
@@ -36,7 +36,7 @@ function createBaseRequest(baseOptions) {
36
36
  if (method.toLowerCase() === 'post') {
37
37
  requestDataOrParams = data;
38
38
  }
39
- var _d = __assign(__assign(__assign({}, baseOptions), createOptions), options).defaultMessageShower, defaultMessageShower = _d === void 0 ? alert : _d;
39
+ var _d = __assign(__assign(__assign({}, baseOptions), createOptions), options).defaultMessageShower, defaultMessageShower = _d === void 0 ? console.error : _d;
40
40
  var _e = __assign(__assign(__assign({}, baseOptions), createOptions), options), _f = _e.enableCache, enableCache = _f === void 0 ? false : _f, _g = _e.cacheData, cacheData = _g === void 0 ? false : _g, _h = _e.defaultErrorCodeHandler, defaultErrorCodeHandler = _h === void 0 ? _defaultErrorCodeHandler.bind(null, defaultMessageShower) : _h, _j = _e.defaultHttpErrorCodeHandler, defaultHttpErrorCodeHandler = _j === void 0 ? _defaultHttpErrorCodeHandler.bind(null, defaultMessageShower) : _j, _k = _e.otherErrorHandler, otherErrorHandler = _k === void 0 ? _defaultOtherErrorCodeHandler.bind(null, defaultMessageShower) : _k, _l = _e.errorCodePath, errorCodePath = _l === void 0 ? 'code' : _l, _m = _e.cacheTime, cacheTime = _m === void 0 ? 60 : _m, _o = _e.errorCodeMap, errorCodeMap = _o === void 0 ? {} : _o, _p = _e.successCodes, successCodes = _p === void 0 ? ['0', '200'] : _p, _q = _e.httpErrorCodeMap, httpErrorCodeMap = _q === void 0 ? {} : _q, _r = _e.axiosOptions, axiosOptions = _r === void 0 ? {} : _r, _s = _e.throwError, throwError = _s === void 0 ? true : _s;
41
41
  if (enableCache) {
42
42
  var cacheItem = cache.getCache(requestDataOrParams);
@@ -0,0 +1,42 @@
1
+ import { useMemo } from 'react';
2
+
3
+ /**
4
+ * 创建 store getter
5
+ * @param store store实例
6
+ * @param getters getter函数
7
+ * @param getterNameMaps 将 getter 函数和 getter 名称一一映射
8
+ * @returns getter object
9
+ */
10
+ var createStoreGetter = function (store, getters, getterNameMaps) {
11
+ var gettersObj = {};
12
+ Object.keys(getters).forEach(function (key) {
13
+ Object.defineProperty(gettersObj, getterNameMaps[key], {
14
+ get: function () { return getters[key](store.get()); }
15
+ });
16
+ });
17
+ return gettersObj;
18
+ };
19
+ /**
20
+ *
21
+ * @param store store实例
22
+ * @param getters getter函数
23
+ * @param getterNameMaps 将 getter 函数和 getter 名称一一映射
24
+ * @returns getter memo hook
25
+ */
26
+ var createStoreGetterMemo = function (store, getters, getterNameMaps) {
27
+ // 创建缓存数据 hook
28
+ return function () {
29
+ var storeData = store.use()[0];
30
+ var reducedData = useMemo(function () {
31
+ return Object.keys(getters).reduce(function (acc, key) {
32
+ var mappedKey = getterNameMaps[key];
33
+ var getterValue = getters[key](storeData);
34
+ acc[mappedKey] = getterValue;
35
+ return acc;
36
+ }, {});
37
+ }, [storeData]);
38
+ return reducedData;
39
+ };
40
+ };
41
+
42
+ export { createStoreGetter, createStoreGetterMemo };
@@ -0,0 +1,92 @@
1
+ import { BaseValidator } from './validator.mjs';
2
+
3
+ function VRequired(noneVals) {
4
+ if (noneVals === void 0) { noneVals = [undefined]; }
5
+ return BaseValidator.decoratorCreator(function (val) {
6
+ if (noneVals.includes(val)) {
7
+ return false;
8
+ }
9
+ return true;
10
+ });
11
+ }
12
+ var VString = BaseValidator.decoratorCreator(function (val) {
13
+ if (typeof val !== 'string') {
14
+ return false;
15
+ }
16
+ return true;
17
+ });
18
+ var VNumber = BaseValidator.decoratorCreator(function (val) {
19
+ if (typeof val !== 'number') {
20
+ return false;
21
+ }
22
+ return true;
23
+ });
24
+ var VArray = BaseValidator.decoratorCreator(function (val) {
25
+ if (!Array.isArray(val)) {
26
+ return false;
27
+ }
28
+ return true;
29
+ });
30
+ // 常用校验装饰器
31
+ var VBoolean = BaseValidator.decoratorCreator(function (val) {
32
+ if (typeof val !== 'boolean') {
33
+ return false;
34
+ }
35
+ return true;
36
+ });
37
+ var VMin = function (min) {
38
+ return BaseValidator.decoratorCreator(function (val) {
39
+ if (typeof val !== 'number' || val < min) {
40
+ return false;
41
+ }
42
+ return true;
43
+ });
44
+ };
45
+ var VMax = function (max) {
46
+ return BaseValidator.decoratorCreator(function (val) {
47
+ if (typeof val !== 'number' || val > max) {
48
+ return false;
49
+ }
50
+ return true;
51
+ });
52
+ };
53
+ var VMinLength = function (minLen) {
54
+ return BaseValidator.decoratorCreator(function (val) {
55
+ if (typeof val !== 'string' && !Array.isArray(val)) {
56
+ return false;
57
+ }
58
+ if (val.length < minLen) {
59
+ return false;
60
+ }
61
+ return true;
62
+ });
63
+ };
64
+ var VMaxLength = function (maxLen) {
65
+ return BaseValidator.decoratorCreator(function (val) {
66
+ if (typeof val !== 'string' && !Array.isArray(val)) {
67
+ return false;
68
+ }
69
+ if (val.length > maxLen) {
70
+ return false;
71
+ }
72
+ return true;
73
+ });
74
+ };
75
+ var VEmail = BaseValidator.decoratorCreator(function (val) {
76
+ if (typeof val !== 'string') {
77
+ return false;
78
+ }
79
+ // 简单邮箱正则
80
+ var emailReg = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
81
+ return emailReg.test(val);
82
+ });
83
+ var VPattern = function (pattern) {
84
+ return BaseValidator.decoratorCreator(function (val) {
85
+ if (typeof val !== 'string') {
86
+ return false;
87
+ }
88
+ return pattern.test(val);
89
+ });
90
+ };
91
+
92
+ export { VArray, VBoolean, VEmail, VMax, VMaxLength, VMin, VMinLength, VNumber, VPattern, VRequired, VString };
@@ -0,0 +1,122 @@
1
+ import { __spreadArray } from 'tslib';
2
+
3
+ var BaseValidator = /** @class */ (function () {
4
+ function BaseValidator() {
5
+ this.__keySymbol = Symbol('key-description');
6
+ this.__keySymbol = Symbol('key-description');
7
+ this[this.__keySymbol] = {};
8
+ }
9
+ BaseValidator.prototype.validate = function (itemKey, itemAll) {
10
+ if (itemAll === void 0) { itemAll = false; }
11
+ var validatorMap = this[this.__keySymbol];
12
+ var errors = [];
13
+ // 校验每个 key
14
+ var validators = validatorMap[itemKey];
15
+ if (!validators) {
16
+ return errors;
17
+ }
18
+ for (var _i = 0, validators_1 = validators; _i < validators_1.length; _i++) {
19
+ var validator = validators_1[_i];
20
+ var res = validator(this[itemKey]);
21
+ if (!res.status) {
22
+ errors.push(res);
23
+ if (!itemAll)
24
+ break;
25
+ }
26
+ }
27
+ if (errors.length) {
28
+ return errors;
29
+ }
30
+ return null;
31
+ };
32
+ BaseValidator.prototype.validateAll = function (itemAll, everyItem, order) {
33
+ if (itemAll === void 0) { itemAll = false; }
34
+ if (everyItem === void 0) { everyItem = false; }
35
+ var validatorMap = this[this.__keySymbol];
36
+ var errors = [];
37
+ // 校验每个 key
38
+ var keys = order || Object.keys(validatorMap);
39
+ for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
40
+ var key = keys_1[_i];
41
+ var value = this[key];
42
+ var fns = validatorMap[key];
43
+ // 校验每个校验项目
44
+ for (var _a = 0, fns_1 = fns; _a < fns_1.length; _a++) {
45
+ var fn = fns_1[_a];
46
+ var res = fn(value);
47
+ if (!res.status) {
48
+ errors.push(res);
49
+ if (!itemAll)
50
+ break;
51
+ }
52
+ }
53
+ if (!everyItem) {
54
+ break;
55
+ }
56
+ }
57
+ if (errors.length) {
58
+ return errors;
59
+ }
60
+ return null;
61
+ };
62
+ BaseValidator.decoratorCreator = function (func) {
63
+ return function (message) {
64
+ if (message === void 0) { message = function (val, value, context) { return "".concat(String(context.name), "\u683C\u5F0F\u9519\u8BEF"); }; }
65
+ return function (value, context) {
66
+ context.addInitializer(function () {
67
+ var validators = this[this.__keySymbol];
68
+ if (!validators) {
69
+ this[this.__keySymbol] = {};
70
+ validators = this[this.__keySymbol];
71
+ }
72
+ var name = context.name;
73
+ var validator = function (val) {
74
+ var validateStatus = func(val, value, context);
75
+ if (validateStatus) {
76
+ return { status: true };
77
+ }
78
+ else {
79
+ var msg = '';
80
+ if (typeof message === 'function') {
81
+ msg = message(val, value, context);
82
+ }
83
+ else {
84
+ msg = message;
85
+ }
86
+ return { status: false, message: msg };
87
+ }
88
+ };
89
+ if (validators[name]) {
90
+ validators[name] = __spreadArray(__spreadArray([], validators[name], true), [validator], false);
91
+ }
92
+ else {
93
+ validators[name] = [validator];
94
+ }
95
+ });
96
+ };
97
+ };
98
+ };
99
+ return BaseValidator;
100
+ }());
101
+ // class User extends BaseValidator{
102
+ // @VString('名称必须为字符串')
103
+ // @(VRequired()('名称必须填写'))
104
+ // name?: string;
105
+ // @VNumber('年龄必须为数字')
106
+ // @(VRequired()('年龄必须填写'))
107
+ // age?: number;
108
+ // @VEmail('邮箱格式不正确')
109
+ // @(VRequired()('邮箱必须填写'))
110
+ // email?: string;
111
+ // @(VMinLength(6)('密码长度不能少于6位'))
112
+ // @(VRequired()('密码必须填写'))
113
+ // password?: string
114
+ // }
115
+ // const user = new User();
116
+ // user.name = '张三'
117
+ // user.email = ' asdfasdf'
118
+ // user.password = '12345'
119
+ // console.log(user)
120
+ // console.log(user.validateAll(false,true,['password','age','email']));
121
+
122
+ export { BaseValidator };
@@ -1,4 +1,7 @@
1
1
  export { default as Cache, ICache, ICacheOptions, StorageMap, StorageType } from './cache/index.js';
2
2
  export { ErrorHandlerReturnType, Options, RequestOptions, default as createBaseRequest } from './request/index.js';
3
- export { IHookStateInitAction, IHookStateInitialSetter, IHookStateResolvable, IHookStateSetAction, IHookStateSetter, default as createStateStore } from './createStateStore/index.js';
3
+ export { createStoreGetter, createStoreGetterMemo } from './store/createGetter/index.js';
4
+ export { IHookStateInitAction, IHookStateInitialSetter, IHookStateResolvable, IHookStateSetAction, IHookStateSetter, default as createStateStore } from './store/createStateStore/index.js';
5
+ export { BaseValidator } from './validator/validator.js';
6
+ export { VArray, VBoolean, VEmail, VMax, VMaxLength, VMin, VMinLength, VNumber, VPattern, VRequired, VString } from './validator/decorators.js';
4
7
  export { default as RequestError, RequestErrorType } from './request/error.js';
@@ -0,0 +1,30 @@
1
+ import createStateStore from '../createStateStore/index.js';
2
+
3
+ type StoreGetter<S = any> = {
4
+ [K in string]: (store: S) => any;
5
+ };
6
+ type GetterNameMap<G extends StoreGetter<any>> = {
7
+ [K in keyof G]: string;
8
+ };
9
+ type ReducedData<G extends StoreGetter<any>, M extends GetterNameMap<G>> = {
10
+ [K in keyof M as M[K]]: G[K extends keyof G ? K : never] extends (store: any) => infer R ? R : never;
11
+ };
12
+ /**
13
+ * 创建 store getter
14
+ * @param store store实例
15
+ * @param getters getter函数
16
+ * @param getterNameMaps 将 getter 函数和 getter 名称一一映射
17
+ * @returns getter object
18
+ */
19
+ declare const createStoreGetter: <S, G extends StoreGetter<S>, M extends GetterNameMap<G>>(store: ReturnType<typeof createStateStore<S>>, getters: G, getterNameMaps: M) => ReducedData<G, M>;
20
+ /**
21
+ *
22
+ * @param store store实例
23
+ * @param getters getter函数
24
+ * @param getterNameMaps 将 getter 函数和 getter 名称一一映射
25
+ * @returns getter memo hook
26
+ */
27
+ declare const createStoreGetterMemo: <S, G extends StoreGetter<S>, M extends GetterNameMap<G>>(store: ReturnType<typeof createStateStore<S>>, getters: G, getterNameMaps: M) => () => ReducedData<G, M>;
28
+
29
+ export { createStoreGetter, createStoreGetterMemo };
30
+ export type { GetterNameMap, ReducedData, StoreGetter };
@@ -0,0 +1,15 @@
1
+ import { BaseValidator } from './validator.js';
2
+
3
+ declare function VRequired(noneVals?: any[]): (message?: ((val: any, value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => string) | string) => (value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => void;
4
+ declare const VString: (message?: ((val: any, value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => string) | string) => (value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => void;
5
+ declare const VNumber: (message?: ((val: any, value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => string) | string) => (value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => void;
6
+ declare const VArray: (message?: ((val: any, value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => string) | string) => (value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => void;
7
+ declare const VBoolean: (message?: ((val: any, value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => string) | string) => (value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => void;
8
+ declare const VMin: (min: number) => (message?: ((val: any, value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => string) | string) => (value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => void;
9
+ declare const VMax: (max: number) => (message?: ((val: any, value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => string) | string) => (value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => void;
10
+ declare const VMinLength: (minLen: number) => (message?: ((val: any, value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => string) | string) => (value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => void;
11
+ declare const VMaxLength: (maxLen: number) => (message?: ((val: any, value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => string) | string) => (value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => void;
12
+ declare const VEmail: (message?: ((val: any, value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => string) | string) => (value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => void;
13
+ declare const VPattern: (pattern: RegExp) => (message?: ((val: any, value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => string) | string) => (value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => void;
14
+
15
+ export { VArray, VBoolean, VEmail, VMax, VMaxLength, VMin, VMinLength, VNumber, VPattern, VRequired, VString };
@@ -0,0 +1,24 @@
1
+ type Validator = (val: any) => {
2
+ status: boolean;
3
+ message?: string;
4
+ };
5
+ type ValidatorMap = {
6
+ [key: string]: Validator[];
7
+ };
8
+ declare class BaseValidator {
9
+ private __keySymbol;
10
+ [key: symbol]: ValidatorMap;
11
+ [key: string]: any;
12
+ constructor();
13
+ validate(itemKey: string, itemAll?: boolean): {
14
+ status: boolean;
15
+ message?: string;
16
+ }[];
17
+ validateAll(itemAll?: boolean, everyItem?: boolean, order?: string[]): {
18
+ status: boolean;
19
+ message?: string;
20
+ }[];
21
+ static decoratorCreator: (func: (val: any, value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => boolean) => (message?: ((val: any, value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => string) | string) => (value: undefined, context: ClassFieldDecoratorContext<BaseValidator>) => void;
22
+ }
23
+
24
+ export { BaseValidator };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rxtutils",
3
- "version": "1.1.1",
3
+ "version": "1.1.2-beta.2",
4
4
  "type": "module",
5
5
  "main": "dist/cjs/index.cjs",
6
6
  "module": "dist/es/index.mjs",
@@ -16,6 +16,7 @@
16
16
  "@rollup/plugin-typescript": "^12.1.2",
17
17
  "@types/lodash": "^4.17.17",
18
18
  "@types/node": "^22.15.29",
19
+ "@types/react": "^19.1.12",
19
20
  "rollup": "^4.41.1",
20
21
  "rollup-plugin-dts": "^6.2.1",
21
22
  "typescript": "^5.8.3",
@@ -25,9 +26,9 @@
25
26
  "react": "^19.1.0"
26
27
  },
27
28
  "dependencies": {
28
- "tslib": "^2.8.1",
29
29
  "axios": "^1.9.0",
30
30
  "lodash": "^4.17.21",
31
- "moment": "^2.30.1"
31
+ "moment": "^2.30.1",
32
+ "tslib": "^2.8.1"
32
33
  }
33
34
  }