@cmtlyt/lingshu-toolkit 0.4.0 → 0.6.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.
- package/README.md +10 -0
- package/dist/665.js +1 -0
- package/dist/893.js +1 -0
- package/dist/react/index.js +1 -205
- package/dist/react/use-boolean/index.d.ts +2 -1
- package/dist/react/use-boolean/index.js +1 -16
- package/dist/react/use-controllable-value/index.d.ts +3 -3
- package/dist/react/use-controllable-value/index.js +1 -32
- package/dist/react/use-counter/index.d.ts +2 -2
- package/dist/react/use-counter/index.js +1 -49
- package/dist/react/use-force-update/index.d.ts +2 -1
- package/dist/react/use-force-update/index.js +1 -6
- package/dist/react/use-mount/index.d.ts +2 -1
- package/dist/react/use-mount/index.js +1 -16
- package/dist/react/use-ref-state/index.d.ts +3 -2
- package/dist/react/use-ref-state/index.js +1 -33
- package/dist/react/use-storage/index.d.ts +2 -1
- package/dist/react/use-storage/index.js +1 -15
- package/dist/react/use-title/index.d.ts +2 -2
- package/dist/react/use-title/index.js +1 -24
- package/dist/react/use-toggle/index.d.ts +4 -4
- package/dist/react/use-toggle/index.js +1 -26
- package/dist/react/use-valid-data/index.d.ts +5 -4
- package/dist/react/use-valid-data/index.js +1 -14
- package/dist/shared/allx/index.d.ts +2 -1
- package/dist/shared/allx/index.js +1 -44
- package/dist/shared/allx/types.d.ts +6 -0
- package/dist/shared/allx/utils.d.ts +9 -7
- package/dist/shared/allx/utils.js +1 -94
- package/dist/shared/animation/index.d.ts +3 -2
- package/dist/shared/animation/index.js +1 -77
- package/dist/shared/animation/types.d.ts +8 -0
- package/dist/shared/animation/utils.d.ts +3 -10
- package/dist/shared/animation/utils.js +1 -134
- package/dist/shared/api-controller/create-api.d.ts +26 -0
- package/dist/shared/api-controller/create-api.js +1 -0
- package/dist/shared/api-controller/index.d.ts +3 -0
- package/dist/shared/api-controller/index.js +1 -0
- package/dist/shared/api-controller/request.d.ts +7 -0
- package/dist/shared/api-controller/request.js +1 -0
- package/dist/shared/api-controller/types.d.ts +140 -0
- package/dist/shared/api-controller/types.js +0 -0
- package/dist/shared/api-controller/utils.d.ts +13 -0
- package/dist/shared/api-controller/utils.js +1 -0
- package/dist/shared/condition-merge/index.d.ts +6 -6
- package/dist/shared/condition-merge/index.js +1 -30
- package/dist/shared/create-storage-handler/index.d.ts +4 -3
- package/dist/shared/create-storage-handler/index.js +1 -68
- package/dist/shared/data-handler/index.d.ts +4 -3
- package/dist/shared/data-handler/index.js +1 -77
- package/dist/shared/data-handler/tools.d.ts +6 -23
- package/dist/shared/data-handler/tools.js +1 -48
- package/dist/shared/data-handler/types.d.ts +20 -2
- package/dist/shared/data-mixed-manager/constants.js +1 -9
- package/dist/shared/data-mixed-manager/index.js +1 -226
- package/dist/shared/data-mixed-manager/types.d.ts +1 -2
- package/dist/shared/index.d.ts +3 -0
- package/dist/shared/index.js +1 -2
- package/dist/shared/logger/index.d.ts +5 -0
- package/dist/shared/logger/index.js +1 -9
- package/dist/shared/priority-queue/index.d.ts +45 -0
- package/dist/shared/priority-queue/index.js +1 -0
- package/dist/shared/priority-queue/types.d.ts +10 -0
- package/dist/shared/priority-queue/types.js +0 -0
- package/dist/shared/priority-queue/utils.d.ts +7 -0
- package/dist/shared/priority-queue/utils.js +1 -0
- package/dist/shared/throw-error/index.d.ts +4 -3
- package/dist/shared/throw-error/index.js +1 -10
- package/dist/shared/try-call/index.d.ts +22 -0
- package/dist/shared/try-call/index.js +1 -0
- package/dist/shared/types/base.d.ts +2 -0
- package/dist/shared/types/index.js +1 -2
- package/dist/shared/types/pack.d.ts +3 -3
- package/dist/shared/types/pack.js +1 -1
- package/dist/shared/utils/base.d.ts +1 -1
- package/dist/shared/utils/base.js +1 -6
- package/dist/shared/utils/index.js +1 -2
- package/dist/shared/utils/verify.d.ts +1 -1
- package/dist/shared/utils/verify.js +1 -67
- package/dist/shared/with-resolvers/index.d.ts +5 -3
- package/dist/shared/with-resolvers/index.js +1 -15
- package/dist/vue/index.js +1 -29
- package/dist/vue/use-title/index.d.ts +2 -2
- package/dist/vue/use-title/index.js +1 -29
- package/package.json +29 -26
- package/dist/607.js +0 -737
- package/dist/707.js +0 -141
- package/dist/react/use-boolean/index.test.d.ts +0 -1
- package/dist/react/use-controllable-value/index.test.d.ts +0 -1
- package/dist/react/use-counter/index.test.d.ts +0 -1
- package/dist/react/use-force-update/index.test.d.ts +0 -1
- package/dist/react/use-mount/index.test.d.ts +0 -1
- package/dist/react/use-ref-state/index.test.d.ts +0 -1
- package/dist/react/use-storage/index.test.d.ts +0 -1
- package/dist/react/use-title/index.test.d.ts +0 -1
- package/dist/react/use-toggle/index.test.d.ts +0 -1
- package/dist/react/use-valid-data/index.test.d.ts +0 -1
- package/dist/shared/allx/__test__/allsettled.test.d.ts +0 -1
- package/dist/shared/allx/__test__/basic.test.d.ts +0 -1
- package/dist/shared/allx/__test__/circular-dependency.test.d.ts +0 -1
- package/dist/shared/allx/__test__/dependency.test.d.ts +0 -1
- package/dist/shared/allx/__test__/edge-cases.test.d.ts +0 -1
- package/dist/shared/allx/__test__/error-handling.test.d.ts +0 -1
- package/dist/shared/allx/__test__/execution-order.test.d.ts +0 -1
- package/dist/shared/allx/__test__/falsy-values.test.d.ts +0 -1
- package/dist/shared/allx/__test__/performance.test.d.ts +0 -1
- package/dist/shared/allx/__test__/type-checking.test.d.ts +0 -1
- package/dist/shared/allx/__test__/use-cases.test.d.ts +0 -1
- package/dist/shared/animation/__test__/animation-pause-resume.test.d.ts +0 -1
- package/dist/shared/animation/__test__/animation.test.d.ts +0 -1
- package/dist/shared/animation/__test__/step-animation.test.d.ts +0 -1
- package/dist/shared/animation/__test__/utils.test.d.ts +0 -1
- package/dist/shared/condition-merge/index.test-d.js +0 -108
- package/dist/shared/condition-merge/index.test.d.ts +0 -1
- package/dist/shared/create-storage-handler/index.browser.test.d.ts +0 -1
- package/dist/shared/create-storage-handler/index.test.d.ts +0 -1
- package/dist/shared/data-handler/index.test.d.ts +0 -1
- package/dist/shared/data-mixed-manager/__test__/basic.test.d.ts +0 -1
- package/dist/shared/data-mixed-manager/__test__/build-options.test.d.ts +0 -1
- package/dist/shared/data-mixed-manager/__test__/constructor-options.test.d.ts +0 -1
- package/dist/shared/data-mixed-manager/__test__/data-management.test.d.ts +0 -1
- package/dist/shared/data-mixed-manager/__test__/edge-cases.test.d.ts +0 -1
- package/dist/shared/data-mixed-manager/__test__/events.browser.test.d.ts +0 -1
- package/dist/shared/data-mixed-manager/__test__/events.test.d.ts +0 -1
- package/dist/shared/data-mixed-manager/__test__/fixed-slots.test.d.ts +0 -1
- package/dist/shared/data-mixed-manager/__test__/insert-mode.test.d.ts +0 -1
- package/dist/shared/throw-error/index.test.d.ts +0 -1
- package/dist/shared/utils/__test__/base.test.d.ts +0 -1
- package/dist/shared/utils/__test__/verify.test.d.ts +0 -1
- package/dist/shared/with-resolvers/index.test.d.ts +0 -1
- package/dist/test/utils.d.ts +0 -13
- package/dist/vue/use-title/index.test.d.ts +0 -1
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { APIConfig, APIInstance, APIMap, DefaultAPIConfig } from './types';
|
|
2
|
+
export declare function isAbsUrl(url?: string): boolean;
|
|
3
|
+
export declare function targetUrlParser(_url: string, _baseUrl: string): URL;
|
|
4
|
+
export declare function urlParamsParser(url: string, params: Record<string, string | number> | undefined): string;
|
|
5
|
+
export declare function getBody(data: any, tdto?: APIConfig['tdto']): any;
|
|
6
|
+
export declare function instanceMemberGetter(prop: string, instanceObj: Record<string, any>): any;
|
|
7
|
+
export declare function createInstance(apiMap: APIConfig | APIMap, realDefaultConfig: DefaultAPIConfig, defaultConfig?: DefaultAPIConfig): APIInstance<any, any>;
|
|
8
|
+
export declare function getInstanceMemberOrApi(target: APIMap, prop: string, receiver: any, instanceObj: APIInstance<any, any>): undefined | {
|
|
9
|
+
api?: APIConfig | APIMap;
|
|
10
|
+
isCustom?: boolean;
|
|
11
|
+
instanceMember?: any;
|
|
12
|
+
};
|
|
13
|
+
export declare function apiNamesCheck(_apiMap: APIMap, isDeep?: boolean): string[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{logger as e}from"../logger/index.js";import{throwError as t,throwType as r}from"../throw-error/index.js";import{getType as n}from"../utils/base.js";import{isPlainNumber as a,isString as i}from"../utils/verify.js";let s=/^[a-z][a-z\d+\-.]*:/imu;function l(e){return!!e&&s.test(e)}function o(e,t){if(l(e))return new URL(e);l(t)||r("apiController.request","baseUrl 配置不合法, 必须是绝对路径");let n=new URL(t),a="/"===n.pathname?"":n.pathname.replace(/\/$/u,""),i=e.startsWith("/")?e:`/${e}`;return new URL(`${a}${i}`,n)}function u(e,t){if(!e.includes("/:"))return e;t||r("apiController.parseParams","url 中存在 params 参数, params 配置不能为空, 请使用 custom 方法调用并传递 params 配置");let n=e.split("/"),i=[];for(let e=1;e<n.length;++e){if(":"!==n[e][0])continue;let r=n[e].slice(1),s=t[r];if(!(a(s)||s)){i.push(r);continue}let l=encodeURIComponent(String(s));n[e]=l}return i.length>0&&r("apiController.parseParams",`params 配置中缺少 [${i.join(", ")}] 参数`),n.join("/")}function c(e,t){let r=t?t(e):e;switch(n(r)){case"object":case"array":case"number":case"boolean":case"function":return JSON.stringify(r);default:return r}}function p(e,t){return t[e]}function f(e,r,n){return{$:e,$$:n,$$r:r,$updateBaseUrl(e){if(l(e))r.baseUrl=e;else{let{origin:n}=globalThis.location||{};n||t("apiController.$updateBaseUrl","location.origin is undefined");let a=(e||"/").startsWith("/")?e||"":`/${e}`;r.baseUrl=`${n}${a}`}}}}function m(e,t,r,n){if(Reflect.getOwnPropertyDescriptor(n,t))return{instanceMember:p(t,n)};let a=i(t)&&Reflect.has(e,t),s=i(t)&&t.endsWith("Custom")&&!a,l=s?t.slice(0,-6):t;if(!Reflect.getOwnPropertyDescriptor(e,l))return;let o=Reflect.get(e,l,r);if(!s||i(o.url))return{api:o,isCustom:s}}function h(t,r=!1){let n=Reflect.ownKeys(t),a=[];for(let e=0;e<n.length;e++){let r=n[e];r.endsWith("Custom")&&a.push(r),i(t[r].url)||a.push(...h(t[r],!0))}return!r&&a.length>0&&e.warn("apiController.createApiWithMap","api 命名不应该使用 Custom 结尾, 因为这是一个内部实现的方法",a),a}export{h as apiNamesCheck,f as createInstance,c as getBody,m as getInstanceMemberOrApi,p as instanceMemberGetter,l as isAbsUrl,o as targetUrlParser,u as urlParamsParser};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { IsPrimitive, Printify, UnionToIntersection } from '../types';
|
|
1
|
+
import type { IsPrimitive, Printify, UnionToIntersection } from '../types/base';
|
|
2
2
|
type AssertValue = Record<PropertyKey, any> | any[];
|
|
3
3
|
type ConditionArrayItem = [boolean, AssertValue, AssertValue?];
|
|
4
|
-
|
|
4
|
+
interface ConditionObjItem {
|
|
5
5
|
condition: boolean;
|
|
6
6
|
value: AssertValue;
|
|
7
7
|
fullback?: AssertValue;
|
|
8
|
-
}
|
|
8
|
+
}
|
|
9
9
|
type ConditionItem = ConditionObjItem | ConditionArrayItem;
|
|
10
10
|
type GetDefaultValue<V> = IsPrimitive<V> extends true ? never : Record<never, any>;
|
|
11
11
|
type ParseDefaultValue<V, D> = FormatValue<unknown extends D ? (V extends any[] ? [] : GetDefaultValue<V>) : D extends undefined | null ? GetDefaultValue<V> : D>;
|
|
@@ -26,6 +26,6 @@ type MergedResult<T extends ConditionItem[]> = T extends [
|
|
|
26
26
|
] ? ParseConditionValue<First> & MergedResult<Last> : ParseConditionValue<T[0]>;
|
|
27
27
|
type CMInput = ConditionItem[];
|
|
28
28
|
type FormatResult<T extends any[]> = T[0] & Record<PropertyKey, any>;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
export {};
|
|
29
|
+
declare function conditionMerge<T extends CMInput>(...input: T): FormatResult<MergedResult<T>>;
|
|
30
|
+
declare function conditionMerge<T extends CMInput>(input: T): FormatResult<MergedResult<T>>;
|
|
31
|
+
export { conditionMerge };
|
|
@@ -1,30 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
function getEmpty(_v) {
|
|
3
|
-
return Array.isArray(_v) ? [] : {};
|
|
4
|
-
}
|
|
5
|
-
function valueCheck(_v) {
|
|
6
|
-
return Array.isArray(_v) || 'object' == typeof _v;
|
|
7
|
-
}
|
|
8
|
-
function conditionMerge(...input) {
|
|
9
|
-
const conditionItems = (input.length > 1 ? input : input[0]).map((item)=>{
|
|
10
|
-
let result = null;
|
|
11
|
-
if (Array.isArray(item)) {
|
|
12
|
-
const [condition, value, fullback] = item;
|
|
13
|
-
result = {
|
|
14
|
-
condition,
|
|
15
|
-
value,
|
|
16
|
-
fullback
|
|
17
|
-
};
|
|
18
|
-
} else if (Object.getOwnPropertyDescriptor(item, 'condition')) result = item;
|
|
19
|
-
else throwType('conditionMerge', 'input must be an ConditionItem');
|
|
20
|
-
const validValue = valueCheck(result.value);
|
|
21
|
-
const validFullback = void 0 === result.fullback || valueCheck(result.fullback);
|
|
22
|
-
if (!(validValue && validFullback)) throwType('conditionMerge', 'value and fullback must be an array or object');
|
|
23
|
-
return result;
|
|
24
|
-
});
|
|
25
|
-
const result = getEmpty(conditionItems[0].value);
|
|
26
|
-
const mergeFn = Array.isArray(result) ? (a1, a2)=>Reflect.apply(Array.prototype.splice.bind(a1, a1.length, 0), null, a2) : Object.assign;
|
|
27
|
-
for(let i = 0, item = conditionItems[i]; i < conditionItems.length; item = conditionItems[++i])mergeFn(result, item.condition ? item.value : item.fullback || getEmpty(item.value));
|
|
28
|
-
return result;
|
|
29
|
-
}
|
|
30
|
-
export { conditionMerge };
|
|
1
|
+
import{throwType as r}from"../throw-error/index.js";function e(r){return Array.isArray(r)?[]:{}}function t(r){return Array.isArray(r)||"object"==typeof r}function n(...o){let i=(1===o.length&&Array.isArray(o[0])?o[0]:o).map(e=>{let n=null;if(Array.isArray(e)){let[r,t,o]=e;n={condition:r,value:t,fullback:o}}else Object.getOwnPropertyDescriptor(e,"condition")?n=e:r("conditionMerge","input must be an ConditionItem");let o=t(n.value),i=void 0===n.fullback||t(n.fullback);return o&&i||r("conditionMerge","value and fullback must be an array or object"),n}),l=e((i[0]||{}).value),a=Array.isArray(l)?(r,e)=>Reflect.apply(Array.prototype.splice.bind(r,r.length,0),null,e):Object.assign;for(let r=0,t=i[r];r<i.length;t=i[++r])a(l,t.condition?t.value:t.fullback||e(t.value));return l}export{n as conditionMerge};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
interface CreateStorageOptions {
|
|
2
2
|
storageType: 'local' | 'session' | 'memory';
|
|
3
3
|
autoSaveInterval: number;
|
|
4
4
|
}
|
|
5
|
-
|
|
5
|
+
interface StorageHandler<T extends Record<string, any>> {
|
|
6
6
|
get: <K extends keyof T | (string & {})>(key?: K) => string extends K ? T : T[K & keyof T];
|
|
7
7
|
set: <K extends keyof T | (string & {})>(value: string extends K ? T : T[K & keyof T], key?: K) => void;
|
|
8
8
|
clear: () => void;
|
|
9
9
|
}
|
|
10
|
-
|
|
10
|
+
declare function createStorageHandler<T extends Record<string, any>>(storageKey: string, initialData?: T, options?: Partial<CreateStorageOptions>): StorageHandler<T>;
|
|
11
|
+
export { type CreateStorageOptions, createStorageHandler, type StorageHandler };
|
|
@@ -1,68 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { logger } from "../logger/index.js";
|
|
3
|
-
import { throwError } from "../throw-error/index.js";
|
|
4
|
-
const validInfo = $dt({
|
|
5
|
-
storageKey: 'validString',
|
|
6
|
-
storageType: $t["enum"]([
|
|
7
|
-
'local',
|
|
8
|
-
'session',
|
|
9
|
-
'memory'
|
|
10
|
-
], 'local'),
|
|
11
|
-
autoSaveInterval: $t.number(0)
|
|
12
|
-
});
|
|
13
|
-
const memoryStorage = {
|
|
14
|
-
data: {},
|
|
15
|
-
getItem (key) {
|
|
16
|
-
return this.data[key];
|
|
17
|
-
},
|
|
18
|
-
setItem (key, value) {
|
|
19
|
-
this.data[key] = value;
|
|
20
|
-
},
|
|
21
|
-
removeItem (key) {
|
|
22
|
-
delete this.data[key];
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
function getStorage(storageType) {
|
|
26
|
-
try {
|
|
27
|
-
if ('memory' === storageType) return memoryStorage;
|
|
28
|
-
return 'local' === storageType ? localStorage : sessionStorage;
|
|
29
|
-
} catch {
|
|
30
|
-
logger.warn('createStorage', 'Failed to access localStorage or sessionStorage, using memoryStorage instead.');
|
|
31
|
-
return memoryStorage;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
const CLEAR_FLAG = Symbol('cleared');
|
|
35
|
-
function createStorageHandler(storageKey, initialData, options = {}) {
|
|
36
|
-
const { storageKey: validStorageKey, storageType, autoSaveInterval } = dataHandler({
|
|
37
|
-
storageKey,
|
|
38
|
-
...options
|
|
39
|
-
}, validInfo, {
|
|
40
|
-
unwrap: true
|
|
41
|
-
});
|
|
42
|
-
const storage = getStorage(storageType);
|
|
43
|
-
const storageData = storage.getItem(validStorageKey);
|
|
44
|
-
const context = {
|
|
45
|
-
data: storageData ? JSON.parse(storageData) : initialData || {}
|
|
46
|
-
};
|
|
47
|
-
return {
|
|
48
|
-
get (key) {
|
|
49
|
-
if (context.data === CLEAR_FLAG) throwError('createStorageHandler', 'Storage has been cleared.');
|
|
50
|
-
if (null == key) return context.data;
|
|
51
|
-
return context.data[key];
|
|
52
|
-
},
|
|
53
|
-
set (value, key) {
|
|
54
|
-
if (context.data === CLEAR_FLAG) throwError('createStorageHandler', 'Storage has been cleared.');
|
|
55
|
-
if (null == key) context.data = value;
|
|
56
|
-
else context.data[key] = value;
|
|
57
|
-
if (autoSaveInterval > 0) setTimeout(()=>{
|
|
58
|
-
storage.setItem(validStorageKey, JSON.stringify(context.data));
|
|
59
|
-
}, autoSaveInterval);
|
|
60
|
-
else storage.setItem(validStorageKey, JSON.stringify(context.data));
|
|
61
|
-
},
|
|
62
|
-
clear () {
|
|
63
|
-
context.data = CLEAR_FLAG;
|
|
64
|
-
storage.removeItem(validStorageKey);
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
export { createStorageHandler };
|
|
1
|
+
import{$dt as e,$t as t,dataHandler as a}from"../data-handler/index.js";import{logger as r}from"../logger/index.js";import{throwError as o}from"../throw-error/index.js";import{isNullOrUndef as i}from"../utils/verify.js";let l=e({storageKey:"validString",storageType:t.enum(["local","session","memory"],"local"),autoSaveInterval:t.number(0)}),n={data:{},getItem(e){return this.data[e]},setItem(e,t){this.data[e]=t},removeItem(e){delete this.data[e]}},s=Symbol("cleared");function m(e,t,d={}){let{storageKey:g,storageType:c,autoSaveInterval:u}=a({storageKey:e,...d},l,{unwrap:!0}),S=function(e){try{if("memory"===e)return n;return"local"===e?localStorage:sessionStorage}catch{return r.warn("createStorage","Failed to access localStorage or sessionStorage, using memoryStorage instead."),n}}(c),y=S.getItem(g),f={data:y?JSON.parse(y):t||{},timer:null},h=()=>{null!==f.timer&&(clearTimeout(f.timer),f.timer=null)};return{get:e=>(f.data===s&&o("createStorageHandler","Storage has been cleared."),i(e))?f.data:f.data[e],set(e,t){f.data===s&&o("createStorageHandler","Storage has been cleared."),i(t)?f.data=e:f.data[t]=e,u>0?(h(),f.timer=setTimeout(()=>{S.setItem(g,JSON.stringify(f.data))},u)):S.setItem(g,JSON.stringify(f.data))},clear(){h(),f.data=s,S.removeItem(g)}}}export{m as createStorageHandler};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import type { Equal, Printify } from '../types';
|
|
1
|
+
import type { Equal, Printify } from '../types/base';
|
|
2
2
|
import type { Transform2Type } from './tools';
|
|
3
3
|
import type { DataHandlerOptions, Handler } from './types';
|
|
4
4
|
type MergeResult<BaseResult extends Record<PropertyKey, any>, HandlerResult extends Handler<any>> = Printify<HandlerResult extends (...args: any[]) => any ? BaseResult : BaseResult & {
|
|
5
5
|
[K in keyof HandlerResult]: Equal<HandlerResult[K], any> extends true ? Required<BaseResult>[K] : HandlerResult[K];
|
|
6
6
|
}>;
|
|
7
|
-
|
|
7
|
+
declare function dataHandler<M extends Record<PropertyKey, any>, H extends Handler<M> = Handler<M>, O extends DataHandlerOptions<M> = DataHandlerOptions<M>>(data: M & Partial<O['defaultValue']>, handler: H, options?: O): O['unwrap'] extends true ? MergeResult<M & O['defaultValue'], Transform2Type<H>> : {
|
|
8
8
|
result: MergeResult<M & O['defaultValue'], Transform2Type<H>>;
|
|
9
9
|
errors: string[];
|
|
10
10
|
};
|
|
11
|
-
export
|
|
11
|
+
export { $dt, $t, defineTransform } from './tools';
|
|
12
|
+
export { dataHandler };
|
|
@@ -1,77 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
export * from "./tools.js";
|
|
3
|
-
function createActions() {
|
|
4
|
-
const ctx = {
|
|
5
|
-
errors: [],
|
|
6
|
-
transforms: [],
|
|
7
|
-
handledErrorKeys: new Set()
|
|
8
|
-
};
|
|
9
|
-
const handler = {
|
|
10
|
-
addError (key, msg = `${String(key)} is not valid`) {
|
|
11
|
-
if (ctx.handledErrorKeys.has(key)) return;
|
|
12
|
-
ctx.handledErrorKeys.add(key);
|
|
13
|
-
ctx.errors.push(msg);
|
|
14
|
-
},
|
|
15
|
-
addTransform (key, value) {
|
|
16
|
-
ctx.transforms.push([
|
|
17
|
-
key,
|
|
18
|
-
value
|
|
19
|
-
]);
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
return [
|
|
23
|
-
ctx,
|
|
24
|
-
handler,
|
|
25
|
-
(key)=>({
|
|
26
|
-
assert: (flag, msg = `${String(key)} is not valid`)=>{
|
|
27
|
-
if (!flag) handler.addError(key, msg);
|
|
28
|
-
return flag;
|
|
29
|
-
},
|
|
30
|
-
transform: (value)=>{
|
|
31
|
-
if (!ctx.handledErrorKeys.has(key)) handler.addTransform(key, value);
|
|
32
|
-
return value;
|
|
33
|
-
}
|
|
34
|
-
})
|
|
35
|
-
];
|
|
36
|
-
}
|
|
37
|
-
function transformApply(data, transforms) {
|
|
38
|
-
if (!transforms.length) return;
|
|
39
|
-
for(let i = 0, [key, value] = transforms[i]; i < transforms.length; [key, value] = transforms[++i] || [])data[key] = value;
|
|
40
|
-
}
|
|
41
|
-
function handleProcess(data, keys, handleFn, getActions, actionHandlers) {
|
|
42
|
-
for(let i = 0, key = keys[i]; i < keys.length; key = keys[++i]){
|
|
43
|
-
const flag = handleFn(data[key], key, getActions(key), data);
|
|
44
|
-
if (false === flag) actionHandlers.addError(key);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
function errorProcess(errors, errorHandler, strict) {
|
|
48
|
-
if (!errors.length) return;
|
|
49
|
-
if (errorHandler) errorHandler(errors);
|
|
50
|
-
else if (strict) throwType('dataHandler', errors.join('\n'));
|
|
51
|
-
}
|
|
52
|
-
function filterData(data, ctx, defaultValue = {}) {
|
|
53
|
-
ctx.handledErrorKeys.forEach((key)=>{
|
|
54
|
-
data[key] = defaultValue[key];
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
function dataHandler(data, handler, options) {
|
|
58
|
-
if (!handler) throwType('dataHandler', 'handler is required');
|
|
59
|
-
const { strict = false, errorHandler, defaultValue, unwrap = false } = options || {};
|
|
60
|
-
const handlerIsFunction = 'function' == typeof handler;
|
|
61
|
-
const handleFn = handlerIsFunction ? handler : (value, key, ...args)=>handler[key](value, ...args);
|
|
62
|
-
const tempData = {
|
|
63
|
-
...defaultValue,
|
|
64
|
-
...data
|
|
65
|
-
};
|
|
66
|
-
const keys = handlerIsFunction ? Reflect.ownKeys(data) : Reflect.ownKeys(handler);
|
|
67
|
-
const [ctx, actionHandler, getActions] = createActions();
|
|
68
|
-
handleProcess(tempData, keys, handleFn, getActions, actionHandler);
|
|
69
|
-
errorProcess(ctx.errors, errorHandler, strict);
|
|
70
|
-
transformApply(tempData, ctx.transforms);
|
|
71
|
-
filterData(tempData, ctx, defaultValue);
|
|
72
|
-
return unwrap ? tempData : {
|
|
73
|
-
result: tempData,
|
|
74
|
-
errors: ctx.errors
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
export { dataHandler };
|
|
1
|
+
import{throwType as r}from"../throw-error/index.js";import{isEmptyArray as e}from"../utils/verify.js";function o(o,s,n){let t,a;s||r("dataHandler","handler is required");let{strict:d=!1,errorHandler:f,defaultValue:l,unwrap:i=!1}=n||{},h="function"==typeof s,m=h?s:(r,e,...o)=>s[e](r,...o),u={...l,...o},y=h?Reflect.ownKeys(o):Reflect.ownKeys(s),[E,p,K]=(t={errors:[],transforms:[],handledErrorKeys:new Set},a={addError(r,e=`${String(r)} is not valid`){t.handledErrorKeys.has(r)||(t.handledErrorKeys.add(r),t.errors.push(e))},addTransform(r,e){t.transforms.push([r,e])}},[t,a,r=>({assert:(e,o=`${String(r)} is not valid`)=>(e||a.addError(r,o),e),transform:e=>(t.handledErrorKeys.has(r)||a.addTransform(r,e),e)})]);for(let r=0,e=y[r];r<y.length;e=y[++r])!1===m(u[e],e,K(e),u)&&p.addError(e);c=E.errors,!e(c)&&(f?f(c):d&&r("dataHandler",c.join("\n")));var c,g=E.transforms;if(!e(g))for(let r=0,[e,o]=g[r];r<g.length;[e,o]=g[++r]||[])u[e]=o;return!function(r,e,o={}){e.handledErrorKeys.forEach(e=>{r[e]=o[e]})}(u,E,l),i?u:{result:u,errors:E.errors}}export{$dt,$t,defineTransform}from"./tools.js";export{o as dataHandler};
|
|
@@ -1,21 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
type TypeHandlerParams = Parameters<TypeHandler> extends [any, ...infer Rest] ? Rest : never;
|
|
4
|
-
type ParseType<T extends string> = T extends keyof TypeMap ? TypeMap[T] : any;
|
|
5
|
-
type TypeHandlerInfo<T extends string> = (value: ParseType<T>, ...args: TypeHandlerParams) => ReturnType<TypeHandler>;
|
|
6
|
-
interface TypeMap {
|
|
7
|
-
notNullable: any & {};
|
|
8
|
-
string: string;
|
|
9
|
-
validString: string;
|
|
10
|
-
number: number;
|
|
11
|
-
validNumber: number;
|
|
12
|
-
boolean: boolean;
|
|
13
|
-
object: Record<PropertyKey, any>;
|
|
14
|
-
array: any[];
|
|
15
|
-
function: (...args: any[]) => any;
|
|
16
|
-
symbol: symbol;
|
|
17
|
-
enum: any & {};
|
|
18
|
-
}
|
|
1
|
+
import type { Fullback, ParseType, TypeHandler, TypeHandlerInfo } from './types';
|
|
2
|
+
export declare function typeHandler<T extends string>(type: T, verifyFn?: (_v: any) => boolean): (fullback?: Fullback<T>) => TypeHandlerInfo<T>;
|
|
19
3
|
export declare const $t: {
|
|
20
4
|
notNullable: (fullback?: any) => TypeHandlerInfo<"notNullable">;
|
|
21
5
|
string: (fullback?: string | ((_v: any) => string) | undefined) => TypeHandlerInfo<"string">;
|
|
@@ -29,14 +13,13 @@ export declare const $t: {
|
|
|
29
13
|
symbol: (fullback?: symbol | ((_v: any) => symbol) | undefined) => TypeHandlerInfo<"symbol">;
|
|
30
14
|
enum: <T>(list: T[], fullback?: T) => TypeHandlerInfo<"enum">;
|
|
31
15
|
};
|
|
32
|
-
type TransformMap = typeof $t;
|
|
33
|
-
type TransformKey = Exclude<keyof TransformMap, 'enum'>;
|
|
34
|
-
type DataTransformResult<D extends Record<PropertyKey, TransformKey | TypeHandler | undefined>> = {
|
|
16
|
+
export type TransformMap = typeof $t;
|
|
17
|
+
export type TransformKey = Exclude<keyof TransformMap, 'enum'>;
|
|
18
|
+
export type DataTransformResult<D extends Record<PropertyKey, TransformKey | TypeHandler | undefined>> = {
|
|
35
19
|
[K in keyof D]: D[K] extends TransformKey ? TransformMap[D[K]] : D[K];
|
|
36
20
|
};
|
|
37
21
|
export type Transform2Type<R extends DataTransformResult<any>> = {
|
|
38
22
|
[K in keyof R]: R[K] extends TypeHandlerInfo<infer T> ? ParseType<T> & {} : any & {};
|
|
39
23
|
};
|
|
40
24
|
export declare function defineTransform<T extends Record<PropertyKey, any>, D extends Partial<Record<keyof T, TransformKey | TypeHandler>> = Partial<Record<keyof T, TransformKey | TypeHandler>>>(dataInfo: D): DataTransformResult<D>;
|
|
41
|
-
export
|
|
42
|
-
export {};
|
|
25
|
+
export { defineTransform as $dt };
|
|
@@ -1,48 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { throwType } from "../throw-error/index.js";
|
|
3
|
-
import { getType } from "../utils/base.js";
|
|
4
|
-
function typeHandler(type, verifyFn) {
|
|
5
|
-
return (fullback)=>(_v, actions)=>{
|
|
6
|
-
if (verifyFn ? verifyFn(_v) : getType(_v) === type) return true;
|
|
7
|
-
if (null == fullback) return false;
|
|
8
|
-
let fullbackValue = fullback;
|
|
9
|
-
if ('function' == typeof fullback) fullbackValue = fullback(_v);
|
|
10
|
-
actions.transform(fullbackValue);
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
const $t = {
|
|
14
|
-
notNullable: typeHandler('notNullable', (_v)=>null != _v),
|
|
15
|
-
string: typeHandler('string'),
|
|
16
|
-
validString: typeHandler('validString', (_v)=>'string' == typeof _v && _v.length > 0),
|
|
17
|
-
number: typeHandler('number'),
|
|
18
|
-
validNumber: typeHandler('validNumber', (_v)=>'number' == typeof _v && !Number.isNaN(_v)),
|
|
19
|
-
boolean: typeHandler('boolean'),
|
|
20
|
-
object: typeHandler('object'),
|
|
21
|
-
array: typeHandler('array'),
|
|
22
|
-
function: typeHandler('function'),
|
|
23
|
-
symbol: typeHandler('symbol'),
|
|
24
|
-
enum: (list, fullback)=>{
|
|
25
|
-
if (!Array.isArray(list)) throwType('$t.enum', 'list must be an array');
|
|
26
|
-
const set = new Set(list);
|
|
27
|
-
return typeHandler('enum', (_v)=>set.has(_v))(fullback);
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
function defineTransform(dataInfo) {
|
|
31
|
-
const verifyInfo = {};
|
|
32
|
-
const keys = Reflect.ownKeys(dataInfo);
|
|
33
|
-
for(let i = 0, key = keys[i], item = dataInfo[key]; i < keys.length; key = keys[++i], item = dataInfo[key]){
|
|
34
|
-
if ('function' == typeof item) {
|
|
35
|
-
verifyInfo[key] = item;
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
const handler = $t[item];
|
|
39
|
-
if (!handler) {
|
|
40
|
-
logger.warn('defineTransform', `${item} is not a valid type`);
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
verifyInfo[key] = handler();
|
|
44
|
-
}
|
|
45
|
-
return verifyInfo;
|
|
46
|
-
}
|
|
47
|
-
const $dt = defineTransform;
|
|
48
|
-
export { $dt, $t, defineTransform };
|
|
1
|
+
import{logger as r}from"../logger/index.js";import{throwType as e}from"../throw-error/index.js";import{getType as n}from"../utils/base.js";import{isNullOrUndef as t}from"../utils/verify.js";function o(r,e){return o=>(i,a)=>{if(e?e(i):n(i)===r)return!0;if(t(o))return!1;let l=o;"function"==typeof o&&(l=o(i)),a.transform(l)}}let i={notNullable:o("notNullable",r=>!t(r)),string:o("string"),validString:o("validString",r=>"string"==typeof r&&r.length>0),number:o("number"),validNumber:o("validNumber",r=>"number"==typeof r&&!Number.isNaN(r)),boolean:o("boolean"),object:o("object"),array:o("array"),function:o("function"),symbol:o("symbol"),enum:(r,n)=>{Array.isArray(r)||e("$t.enum","list must be an array");let t=new Set(r);return o("enum",r=>t.has(r))(n)}};function a(e){let n={},t=Reflect.ownKeys(e);for(let o=0,a=t[o],l=e[a];o<t.length;l=e[a=t[++o]]){if("function"==typeof l){n[a]=l;continue}let e=i[l];if(!e){r.warn("defineTransform",`${l} is not a valid type`);continue}n[a]=e()}return n}export{i as $t,a as $dt,a as defineTransform,o as typeHandler};
|
|
@@ -16,8 +16,8 @@ export interface ActionContext {
|
|
|
16
16
|
handledErrorKeys: Set<PropertyKey>;
|
|
17
17
|
}
|
|
18
18
|
export interface ActionHandlers {
|
|
19
|
-
addError(key: PropertyKey, msg?: string)
|
|
20
|
-
addTransform(key: PropertyKey, value: any)
|
|
19
|
+
addError: (key: PropertyKey, msg?: string) => void;
|
|
20
|
+
addTransform: (key: PropertyKey, value: any) => void;
|
|
21
21
|
}
|
|
22
22
|
export interface DataHandlerOptions<M extends Record<PropertyKey, any>> {
|
|
23
23
|
strict?: boolean;
|
|
@@ -25,3 +25,21 @@ export interface DataHandlerOptions<M extends Record<PropertyKey, any>> {
|
|
|
25
25
|
defaultValue?: M;
|
|
26
26
|
unwrap?: boolean;
|
|
27
27
|
}
|
|
28
|
+
export interface TypeMap {
|
|
29
|
+
notNullable: any & {};
|
|
30
|
+
string: string;
|
|
31
|
+
validString: string;
|
|
32
|
+
number: number;
|
|
33
|
+
validNumber: number;
|
|
34
|
+
boolean: boolean;
|
|
35
|
+
object: Record<PropertyKey, any>;
|
|
36
|
+
array: any[];
|
|
37
|
+
function: (...args: any[]) => any;
|
|
38
|
+
symbol: symbol;
|
|
39
|
+
enum: any & {};
|
|
40
|
+
}
|
|
41
|
+
export type TypeHandler = NonNullable<Exclude<Handler<any>, (...args: any[]) => any>[string]>;
|
|
42
|
+
export type TypeHandlerParams = Parameters<TypeHandler> extends [any, ...infer Rest] ? Rest : never;
|
|
43
|
+
export type ParseType<T extends string> = T extends keyof TypeMap ? TypeMap[T] : any;
|
|
44
|
+
export type TypeHandlerInfo<T extends string> = (value: ParseType<T>, ...args: TypeHandlerParams) => ReturnType<TypeHandler>;
|
|
45
|
+
export type Fullback<T extends string> = T extends 'function' ? (_v: any) => ParseType<T> : ((_v: any) => ParseType<T>) | (ParseType<T> & {});
|
|
@@ -1,226 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { throwError } from "../throw-error/index.js";
|
|
3
|
-
import { SLOT_TYPE } from "./constants.js";
|
|
4
|
-
const validInfo = $dt({
|
|
5
|
-
name: $t.string('default'),
|
|
6
|
-
fixedSlots: $t.array([]),
|
|
7
|
-
dataList: $t.array([]),
|
|
8
|
-
listener: $t.object({})
|
|
9
|
-
});
|
|
10
|
-
class DataMixedManager extends EventTarget {
|
|
11
|
-
addEventListener(...args) {
|
|
12
|
-
return super.addEventListener.apply(this, args);
|
|
13
|
-
}
|
|
14
|
-
removeEventListener(...args) {
|
|
15
|
-
return super.removeEventListener.apply(this, args);
|
|
16
|
-
}
|
|
17
|
-
options;
|
|
18
|
-
fixedSlots = new Map();
|
|
19
|
-
dataList = [];
|
|
20
|
-
mixedData = [];
|
|
21
|
-
lastMixedSlotIdx = -1;
|
|
22
|
-
prevDataLength = 0;
|
|
23
|
-
isBatching = false;
|
|
24
|
-
constructor(options){
|
|
25
|
-
super();
|
|
26
|
-
const validOptions = dataHandler(options || {}, validInfo, {
|
|
27
|
-
unwrap: true
|
|
28
|
-
});
|
|
29
|
-
const { fixedSlots, dataList, listener } = validOptions;
|
|
30
|
-
this.options = validOptions;
|
|
31
|
-
this.addFixedSlots(fixedSlots, {
|
|
32
|
-
lazy: true
|
|
33
|
-
});
|
|
34
|
-
this.appendList(dataList);
|
|
35
|
-
try {
|
|
36
|
-
this.initListener(listener);
|
|
37
|
-
} catch (error) {
|
|
38
|
-
throwError('dataMixedManager', error.message, error.constructor);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
initListener(listener) {
|
|
42
|
-
const listenerNames = Object.keys(listener);
|
|
43
|
-
for(let i = 0, name = listenerNames[i], handler = listener[name]; i < listenerNames.length; name = listenerNames[++i], handler = listener[name])this.addEventListener(name, handler);
|
|
44
|
-
}
|
|
45
|
-
getTypeText(_type) {
|
|
46
|
-
switch(_type){
|
|
47
|
-
case SLOT_TYPE.fixed:
|
|
48
|
-
return 'fixed';
|
|
49
|
-
case SLOT_TYPE.insert:
|
|
50
|
-
return 'insert';
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
buildSlotConfig(config, type) {
|
|
54
|
-
const typeText = this.getTypeText(config.type || type);
|
|
55
|
-
return {
|
|
56
|
-
...config,
|
|
57
|
-
type: typeText,
|
|
58
|
-
inputPosition: config.position,
|
|
59
|
-
insertMode: config.insertMode || 'cover'
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
addFixedSlot(config, buildOptions) {
|
|
63
|
-
const realConfig = this.reorderFixedSlots(this.buildSlotConfig(config, SLOT_TYPE.fixed));
|
|
64
|
-
this.fixedSlots.set(realConfig.position, realConfig);
|
|
65
|
-
this.buildMixedData(buildOptions);
|
|
66
|
-
return realConfig.position;
|
|
67
|
-
}
|
|
68
|
-
reorderFixedSlots(config) {
|
|
69
|
-
const { position: oldPosition, insertMode } = config;
|
|
70
|
-
if (null == insertMode || 'cover' === insertMode || !this.fixedSlots.has(oldPosition)) return {
|
|
71
|
-
...config,
|
|
72
|
-
inputPosition: oldPosition
|
|
73
|
-
};
|
|
74
|
-
const position = 'after' === insertMode ? oldPosition + 1 : oldPosition;
|
|
75
|
-
for(let i = position + 1, preItem = this.fixedSlots.get(i - 1), currItem = this.fixedSlots.get(i); preItem; ++i, preItem = currItem, currItem = this.fixedSlots.get(i)){
|
|
76
|
-
preItem.position = i;
|
|
77
|
-
this.fixedSlots.set(i, preItem);
|
|
78
|
-
}
|
|
79
|
-
return {
|
|
80
|
-
...config,
|
|
81
|
-
position,
|
|
82
|
-
inputPosition: oldPosition
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
addFixedSlots(configs, buildOptions) {
|
|
86
|
-
if (!configs.length) return [];
|
|
87
|
-
const positions = this.batchUpdate(()=>configs.map((config)=>this.addFixedSlot(config)));
|
|
88
|
-
this.buildMixedData(buildOptions);
|
|
89
|
-
return positions;
|
|
90
|
-
}
|
|
91
|
-
deleteFixedSlot(position, buildOptions) {
|
|
92
|
-
this.fixedSlots.delete(position);
|
|
93
|
-
this.buildMixedData(buildOptions);
|
|
94
|
-
}
|
|
95
|
-
deleteFixedSlots(positions, buildOptions) {
|
|
96
|
-
if (!positions.length) return;
|
|
97
|
-
this.batchUpdate(()=>positions.forEach((position)=>void this.deleteFixedSlot(position)));
|
|
98
|
-
this.buildMixedData(buildOptions);
|
|
99
|
-
}
|
|
100
|
-
batchUpdate(callback) {
|
|
101
|
-
try {
|
|
102
|
-
this.isBatching = true;
|
|
103
|
-
const result = callback();
|
|
104
|
-
return result;
|
|
105
|
-
} finally{
|
|
106
|
-
this.isBatching = false;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
clearFixedSlots(buildOptions) {
|
|
110
|
-
this.fixedSlots.clear();
|
|
111
|
-
this.buildMixedData(buildOptions);
|
|
112
|
-
}
|
|
113
|
-
appendList(list, buildOptions) {
|
|
114
|
-
if (!list.length) return;
|
|
115
|
-
this.dataList.push(...list);
|
|
116
|
-
this.buildMixedData({
|
|
117
|
-
...buildOptions,
|
|
118
|
-
lazy: true === (buildOptions || {}).lazy
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
clearList() {
|
|
122
|
-
this.dataList.length = 0;
|
|
123
|
-
this.mixedData.length = 0;
|
|
124
|
-
this.dispatch('change', {
|
|
125
|
-
mode: 'clear',
|
|
126
|
-
mixedData: this.getMixedData({
|
|
127
|
-
mode: 'rebuild'
|
|
128
|
-
})
|
|
129
|
-
});
|
|
130
|
-
this.dispatch('clear');
|
|
131
|
-
}
|
|
132
|
-
getMixedData(buildOptions) {
|
|
133
|
-
this.buildMixedData({
|
|
134
|
-
...buildOptions,
|
|
135
|
-
lazy: false
|
|
136
|
-
});
|
|
137
|
-
return this.mixedData.slice();
|
|
138
|
-
}
|
|
139
|
-
dispatch(name, data) {
|
|
140
|
-
const detail = {
|
|
141
|
-
name: this.options.name,
|
|
142
|
-
...data
|
|
143
|
-
};
|
|
144
|
-
this.dispatchEvent(new CustomEvent(name, {
|
|
145
|
-
detail
|
|
146
|
-
}));
|
|
147
|
-
if ("u" > typeof window) window.dispatchEvent(new CustomEvent(`[DMM]:${name}`, {
|
|
148
|
-
detail
|
|
149
|
-
}));
|
|
150
|
-
}
|
|
151
|
-
buildMixedData(buildOptions) {
|
|
152
|
-
if (this.isBatching) return;
|
|
153
|
-
const { lazy, mode } = buildOptions || {};
|
|
154
|
-
if ('rebuild' === mode) {
|
|
155
|
-
this.prevDataLength = 0;
|
|
156
|
-
this.lastMixedSlotIdx = -1;
|
|
157
|
-
}
|
|
158
|
-
if (false !== lazy || this.dataList.length <= this.prevDataLength) return;
|
|
159
|
-
let dataStartIdx = this.prevDataLength;
|
|
160
|
-
const dataEndIdx = this.dataList.length;
|
|
161
|
-
const newItemCount = dataEndIdx - dataStartIdx;
|
|
162
|
-
this.prevDataLength = dataEndIdx;
|
|
163
|
-
const isPatchMode = dataStartIdx > 0;
|
|
164
|
-
const filteredSlots = this.sliceSlots(isPatchMode ? this.mixedData.length : this.lastMixedSlotIdx, this.mixedData.length + newItemCount);
|
|
165
|
-
this.lastMixedSlotIdx = filteredSlots.at(-1) ?? this.lastMixedSlotIdx;
|
|
166
|
-
let mixedStartIdx = isPatchMode ? this.mixedData.length : 0;
|
|
167
|
-
this.mixedData.length = (isPatchMode ? newItemCount + mixedStartIdx : dataEndIdx) + filteredSlots.length;
|
|
168
|
-
for(let fpIdx = 0, fpItem = filteredSlots[fpIdx]; dataStartIdx < dataEndIdx; ++mixedStartIdx)if (mixedStartIdx === fpItem) {
|
|
169
|
-
const fixedSlot = this.fixedSlots.get(fpItem);
|
|
170
|
-
this.mixedData[mixedStartIdx] = {
|
|
171
|
-
isFixed: true,
|
|
172
|
-
type: fixedSlot.type,
|
|
173
|
-
data: fixedSlot.data
|
|
174
|
-
};
|
|
175
|
-
fpItem = filteredSlots[++fpIdx];
|
|
176
|
-
} else {
|
|
177
|
-
this.mixedData[mixedStartIdx] = {
|
|
178
|
-
isFixed: false,
|
|
179
|
-
type: 'plain',
|
|
180
|
-
data: this.dataList[dataStartIdx]
|
|
181
|
-
};
|
|
182
|
-
++dataStartIdx;
|
|
183
|
-
}
|
|
184
|
-
this.dispatch('change', {
|
|
185
|
-
mode: isPatchMode ? 'patch' : 'rebuild',
|
|
186
|
-
mixedData: this.mixedData.slice()
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
sliceSlots(startIdx, endIdx = 1 / 0) {
|
|
190
|
-
let prevItem = -2;
|
|
191
|
-
let count = 0;
|
|
192
|
-
return Array.from(this.fixedSlots.keys()).sort((ai, bi)=>ai - bi).filter((item)=>{
|
|
193
|
-
if (item >= startIdx && item < endIdx + count || item - 1 === prevItem) {
|
|
194
|
-
++count;
|
|
195
|
-
prevItem = item;
|
|
196
|
-
return true;
|
|
197
|
-
}
|
|
198
|
-
return false;
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
insertSlot(config) {
|
|
202
|
-
const realPosition = this.addFixedSlot({
|
|
203
|
-
...config,
|
|
204
|
-
type: SLOT_TYPE.insert
|
|
205
|
-
});
|
|
206
|
-
if (realPosition > this.mixedData.length) return realPosition;
|
|
207
|
-
this.buildMixedData({
|
|
208
|
-
lazy: false,
|
|
209
|
-
mode: 'rebuild'
|
|
210
|
-
});
|
|
211
|
-
return realPosition;
|
|
212
|
-
}
|
|
213
|
-
insertSlots(configs) {
|
|
214
|
-
if (!configs.length) return [];
|
|
215
|
-
const positions = this.batchUpdate(()=>configs.map((config)=>this.insertSlot(config)));
|
|
216
|
-
this.buildMixedData({
|
|
217
|
-
lazy: false,
|
|
218
|
-
mode: 'rebuild'
|
|
219
|
-
});
|
|
220
|
-
return positions;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
function dataMixedManager(options) {
|
|
224
|
-
return new DataMixedManager(options);
|
|
225
|
-
}
|
|
226
|
-
export { dataMixedManager };
|
|
1
|
+
import{$dt as t,$t as e,dataHandler as i}from"../data-handler/index.js";import{throwError as s}from"../throw-error/index.js";import{isEmptyArray as a,isNullOrUndef as d}from"../utils/verify.js";import{SLOT_TYPE as l}from"./constants.js";let r=t({name:e.string("default"),fixedSlots:e.array([]),dataList:e.array([]),listener:e.object({})});class h extends EventTarget{addEventListener(...t){super.addEventListener.apply(this,t)}removeEventListener(...t){super.removeEventListener.apply(this,t)}options;fixedSlots=new Map;dataList=[];mixedData=[];lastMixedSlotIdx=-1;prevDataLength=0;isBatching=!1;constructor(t){super();let e=i(t||{},r,{unwrap:!0}),{fixedSlots:a,dataList:d,listener:l}=e;this.options=e,this.addFixedSlots(a,{lazy:!0}),this.appendList(d);try{this.initListener(l)}catch(t){s("dataMixedManager",t.message,t.constructor)}}initListener(t){let e=Object.keys(t);for(let i=0,s=e[i],a=t[s];i<e.length;a=t[s=e[++i]])this.addEventListener(s,a)}getTypeText(t){switch(t){case l.fixed:return"fixed";case l.insert:return"insert"}}buildSlotConfig(t,e){let i=this.getTypeText(t.type||e);return{...t,type:i,inputPosition:t.position,insertMode:t.insertMode??"cover"}}addFixedSlot(t,e){let i=this.reorderFixedSlots(this.buildSlotConfig(t,l.fixed));return this.fixedSlots.set(i.position,i),this.buildMixedData(e),i.position}reorderFixedSlots(t){let{position:e,insertMode:i}=t;if(d(i)||"cover"===i||!this.fixedSlots.has(e))return{...t,inputPosition:e};let s="after"===i?e+1:e;for(let t=s+1,e=this.fixedSlots.get(t-1),i=this.fixedSlots.get(t);e;++t,e=i,i=this.fixedSlots.get(t))e.position=t,this.fixedSlots.set(t,e);return{...t,position:s,inputPosition:e}}addFixedSlots(t,e){if(a(t))return[];let i=this.batchUpdate(()=>t.map(t=>this.addFixedSlot(t)));return this.buildMixedData(e),i}deleteFixedSlot(t,e){this.fixedSlots.delete(t),this.buildMixedData(e)}deleteFixedSlots(t,e){a(t)||(this.batchUpdate(()=>t.forEach(t=>void this.deleteFixedSlot(t))),this.buildMixedData(e))}batchUpdate(t){try{return this.isBatching=!0,t()}finally{this.isBatching=!1}}clearFixedSlots(t){this.fixedSlots.clear(),this.buildMixedData(t)}appendList(t,e){a(t)||(this.dataList.push(...t),this.buildMixedData({...e,lazy:!0===(e||{}).lazy}))}clearList(){this.dataList.length=0,this.mixedData.length=0,this.dispatch("change",{mode:"clear",mixedData:this.getMixedData({mode:"rebuild"})}),this.dispatch("clear")}getMixedData(t){return this.buildMixedData({...t,lazy:!1}),this.mixedData.slice()}dispatch(t,e){let i={name:this.options.name,...e};this.dispatchEvent(new CustomEvent(t,{detail:i})),void 0!==globalThis.window&&globalThis.window.dispatchEvent(new CustomEvent(`[DMM]:${t}`,{detail:i}))}buildMixedData(t){if(this.isBatching)return;let{lazy:e,mode:i}=t||{};if("rebuild"===i&&(this.prevDataLength=0,this.lastMixedSlotIdx=-1),!1!==e||this.dataList.length<=this.prevDataLength)return;let s=this.prevDataLength,a=this.dataList.length,d=a-s;this.prevDataLength=a;let l=s>0,r=this.sliceSlots(l?this.mixedData.length:this.lastMixedSlotIdx,this.mixedData.length+d);this.lastMixedSlotIdx=r.at(-1)??this.lastMixedSlotIdx;let h=l?this.mixedData.length:0;this.mixedData.length=(l?d+h:a)+r.length;for(let t=0,e=r[t];s<a;++h)if(h===e){let i=this.fixedSlots.get(e);this.mixedData[h]={isFixed:!0,type:i.type,data:i.data},e=r[++t]}else this.mixedData[h]={isFixed:!1,type:"plain",data:this.dataList[s]},++s;this.dispatch("change",{mode:l?"patch":"rebuild",mixedData:this.mixedData.slice()})}sliceSlots(t,e=1/0){let i=-2,s=0;return Array.from(this.fixedSlots.keys()).sort((t,e)=>t-e).filter(a=>(a>=t&&a<e+s||a-1===i)&&(++s,i=a,!0))}insertSlot(t){let e=this.addFixedSlot({...t,type:l.insert});return e>this.mixedData.length||this.buildMixedData({lazy:!1,mode:"rebuild"}),e}insertSlots(t){if(a(t))return[];let e=this.batchUpdate(()=>t.map(t=>this.insertSlot(t)));return this.buildMixedData({lazy:!1,mode:"rebuild"}),e}}function n(t){return new h(t)}export{n as dataMixedManager};
|
|
@@ -59,7 +59,7 @@ export interface BuildOptions {
|
|
|
59
59
|
/** 构建模式:rebuild-全量重建,patch-增量更新 */
|
|
60
60
|
mode?: 'rebuild' | 'patch';
|
|
61
61
|
}
|
|
62
|
-
interface DiffEventDetailMap<T> {
|
|
62
|
+
export interface DiffEventDetailMap<T> {
|
|
63
63
|
change: {
|
|
64
64
|
mode: NonNullable<BuildOptions['mode']> | 'clear';
|
|
65
65
|
mixedData: MixedDataItem<T>[];
|
|
@@ -87,4 +87,3 @@ export interface DataMixedManagerOptions<T> {
|
|
|
87
87
|
[K in keyof EventDetailMap<T>]?: DMMEventHandler<T, K>;
|
|
88
88
|
};
|
|
89
89
|
}
|
|
90
|
-
export {};
|