|
1 | | -import { PATH_DELIMITER } from '../consts'; |
2 | | -import type { AutoStore } from '../store/store'; |
3 | | -import type { Dict } from '../types'; |
4 | | -import { isSchemaBuilder, markRaw, pathStartsWith, setVal } from '../utils'; |
5 | | -import { getVal } from '../utils/getVal'; |
6 | | -import { parseFunc } from '../utils/parseFunc'; |
| 1 | +import { PATH_DELIMITER } from "../consts"; |
| 2 | +import type { AutoStore } from "../store/store"; |
| 3 | +import type { Dict } from "../types"; |
| 4 | +import { isSchemaBuilder, markRaw, pathStartsWith, setVal } from "../utils"; |
| 5 | +import { getVal } from "../utils/getVal"; |
| 6 | +import { parseFunc } from "../utils/parseFunc"; |
7 | 7 | import type { |
8 | | - SchemaOptions, |
9 | | - SchemaValidator, |
10 | | - ComputedSchemaState, |
11 | | - SchemaDescriptor, |
12 | | - SchemaDescriptorBuilder, |
13 | | -} from './types'; |
| 8 | + SchemaOptions, |
| 9 | + SchemaValidator, |
| 10 | + ComputedSchemaState, |
| 11 | + SchemaDescriptor, |
| 12 | + SchemaDescriptorBuilder, |
| 13 | +} from "./types"; |
14 | 14 |
|
15 | 15 | export class SchemaManager< |
16 | | - State extends Dict, |
17 | | - SchemaStore extends AutoStore<ComputedSchemaState<State>> = AutoStore< |
18 | | - ComputedSchemaState<State> |
19 | | - >, |
| 16 | + State extends Dict, |
| 17 | + SchemaStore extends AutoStore<ComputedSchemaState<State>> = AutoStore<ComputedSchemaState<State>>, |
20 | 18 | > { |
21 | | - errors: Dict<string> = {}; // {<路径名称>:"错误信息"} |
22 | | - _subscribers: any[] = []; |
23 | | - store!: SchemaStore; |
24 | | - _descriptors: Record<string, SchemaDescriptor['options']> = {}; |
25 | | - constructor(public shadow: AutoStore<any>) {} |
| 19 | + errors: Dict<string> = {}; // {<路径名称>:"错误信息"} |
| 20 | + _subscribers: any[] = []; |
| 21 | + store!: SchemaStore; |
| 22 | + _descriptors: Record<string, SchemaDescriptor["options"]> = {}; |
| 23 | + constructor(public shadow: AutoStore<any>) {} |
26 | 24 |
|
27 | | - get fields() { |
28 | | - return this.store.state as Record<string, SchemaOptions>; |
29 | | - } |
30 | | - get size() { |
31 | | - return Object.keys(this.fields).length; |
32 | | - } |
| 25 | + get fields() { |
| 26 | + return this.store.state as Record<string, SchemaOptions>; |
| 27 | + } |
| 28 | + get size() { |
| 29 | + return Object.keys(this.fields).length; |
| 30 | + } |
33 | 31 |
|
34 | | - _getKey(path: any): string { |
35 | | - return Array.isArray(path) ? path.join('_$_') : path.split(PATH_DELIMITER).join('_$_'); |
36 | | - } |
37 | | - _getPath(path: string) { |
38 | | - return path.split('_$_'); |
39 | | - } |
| 32 | + _getKey(path: any): string { |
| 33 | + return Array.isArray(path) ? path.join("_$_") : path.split(PATH_DELIMITER).join("_$_"); |
| 34 | + } |
| 35 | + _getPath(path: string) { |
| 36 | + return path.split("_$_"); |
| 37 | + } |
40 | 38 |
|
41 | | - add<V = any, Options extends SchemaOptions<V> = SchemaOptions<V>>( |
42 | | - path: string | string[], |
43 | | - schema: SchemaDescriptorBuilder | SchemaDescriptor<V, Options>, |
44 | | - ) { |
45 | | - const descriptor = isSchemaBuilder(schema) ? schema() : schema; |
| 39 | + add<V = any, Options extends SchemaOptions<V> = SchemaOptions<V>>( |
| 40 | + path: string | string[], |
| 41 | + schema: SchemaDescriptorBuilder | SchemaDescriptor<V, Options>, |
| 42 | + ) { |
| 43 | + const descriptor = isSchemaBuilder(schema) ? schema() : schema; |
46 | 44 |
|
47 | | - const pathKey = Array.isArray(path) ? path : path.split(PATH_DELIMITER); |
48 | | - const key = this._getKey(path); |
49 | | - if (!descriptor.options.onFail) descriptor.options.onFail = 'throw-pass'; |
| 45 | + const pathKey = Array.isArray(path) ? path : path.split(PATH_DELIMITER); |
| 46 | + const key = this._getKey(path); |
| 47 | + if (!descriptor.options.onFail) descriptor.options.onFail = "throw-pass"; |
50 | 48 |
|
51 | | - const finalDescriptor = Object.assign( |
52 | | - {}, |
53 | | - this.shadow.options.defaultSchemaOptions, |
54 | | - descriptor.options, |
55 | | - { |
56 | | - path: pathKey, |
57 | | - datatype: descriptor.datatype, |
58 | | - value: descriptor.value, |
59 | | - }, |
60 | | - ) as unknown as SchemaDescriptor['options']; |
| 49 | + const finalDescriptor = Object.assign({}, this.shadow.options.defaultSchemaOptions, descriptor.options, { |
| 50 | + path: pathKey, |
| 51 | + datatype: descriptor.datatype, |
| 52 | + value: descriptor.value, |
| 53 | + }) as unknown as SchemaDescriptor["options"]; |
61 | 54 |
|
62 | | - if (typeof finalDescriptor.onValidate === 'string') { |
63 | | - finalDescriptor.onValidate = markRaw(parseFunc(finalDescriptor.onValidate)) as any; |
64 | | - } |
| 55 | + if (typeof finalDescriptor.onValidate === "string") { |
| 56 | + finalDescriptor.onValidate = markRaw(parseFunc(finalDescriptor.onValidate)) as any; |
| 57 | + } |
65 | 58 |
|
66 | | - this._descriptors[key] = finalDescriptor; |
| 59 | + this._descriptors[key] = finalDescriptor; |
67 | 60 |
|
68 | | - if (this.shadow && descriptor.value !== undefined) { |
69 | | - this.shadow.update( |
70 | | - (state) => { |
71 | | - setVal(state, pathKey, descriptor.value); |
72 | | - }, |
73 | | - { |
74 | | - validate: 'pass', |
75 | | - }, |
76 | | - ); |
77 | | - } |
78 | | - return descriptor; |
79 | | - } |
80 | | - /** |
81 | | - * 等store的所有计算属性处理完毕再创建schemas |
82 | | - * |
83 | | - */ |
84 | | - build() { |
85 | | - if (this.store) return; |
86 | | - if (!this._descriptors) return; |
87 | | - this.store = this.shadow.shadow(this._descriptors) as unknown as SchemaStore; |
88 | | - } |
89 | | - get<T extends keyof SchemaStore['state'] = keyof SchemaStore['state']>( |
90 | | - path: T, |
91 | | - ): SchemaOptions | undefined { |
92 | | - if (!this.store) return; |
93 | | - return getVal(this.store.state, [this._getKey(path as any)]); |
94 | | - } |
95 | | - has(path: keyof SchemaStore['state']): boolean { |
96 | | - if (!this.store) return false; |
97 | | - const key = this._getKey(path); |
98 | | - return key in (this.store.state as any); |
99 | | - } |
100 | | - watch() { |
101 | | - // @ts-ignore |
102 | | - return this.store.watch(...arguemnts); |
103 | | - } |
104 | | - getValidator<T extends keyof SchemaStore['state'] = keyof SchemaStore['state']>( |
105 | | - path: T, |
106 | | - ): SchemaValidator<SchemaStore['state'][T]> | undefined { |
107 | | - if (!this.store) return; |
108 | | - const options = this.get(path); |
109 | | - if (!options) return; |
110 | | - return { |
111 | | - validate: options.onValidate!, |
112 | | - onFail: options.onFail!, |
113 | | - message: options.invalidTips!, |
114 | | - }; |
115 | | - } |
| 61 | + if (this.shadow && descriptor.value !== undefined) { |
| 62 | + this.shadow.update( |
| 63 | + (state) => { |
| 64 | + setVal(state, pathKey, descriptor.value); |
| 65 | + }, |
| 66 | + { |
| 67 | + validate: "pass", |
| 68 | + }, |
| 69 | + ); |
| 70 | + } |
| 71 | + return descriptor; |
| 72 | + } |
| 73 | + /** |
| 74 | + * 等store的所有计算属性处理完毕再创建schemas |
| 75 | + * |
| 76 | + */ |
| 77 | + build() { |
| 78 | + if (this.store) return; |
| 79 | + if (!this._descriptors) return; |
| 80 | + this.store = this.shadow.shadow(this._descriptors) as unknown as SchemaStore; |
| 81 | + } |
| 82 | + get<T extends keyof SchemaStore["state"] = keyof SchemaStore["state"]>(path: T): SchemaOptions | undefined { |
| 83 | + if (!this.store) return; |
| 84 | + return getVal(this.store.state, [this._getKey(path as any)]); |
| 85 | + } |
| 86 | + has(path: string | string[]): boolean { |
| 87 | + if (!this.store) return false; |
| 88 | + const key = this._getKey(path); |
| 89 | + return key in (this.store.state as any); |
| 90 | + } |
| 91 | + watch() { |
| 92 | + // @ts-ignore |
| 93 | + return this.store.watch(...arguemnts); |
| 94 | + } |
| 95 | + getValidator<T extends keyof SchemaStore["state"] = keyof SchemaStore["state"]>( |
| 96 | + path: T, |
| 97 | + ): SchemaValidator<SchemaStore["state"][T]> | undefined { |
| 98 | + if (!this.store) return; |
| 99 | + const options = this.get(path); |
| 100 | + if (!options) return; |
| 101 | + return { |
| 102 | + validate: options.onValidate!, |
| 103 | + onFail: options.onFail!, |
| 104 | + message: options.invalidTips!, |
| 105 | + }; |
| 106 | + } |
116 | 107 |
|
117 | | - addValidator(path: string[], validator: SchemaValidator) { |
118 | | - if (!this.store) return; |
119 | | - const key = this._getKey(path); |
120 | | - this.store.update((state) => { |
121 | | - Object.assign((state as any)[key], { |
122 | | - onValidate: markRaw(validator.validate), |
123 | | - onFail: validator.onFail || 'throw-pass', |
124 | | - invalidTips: validator.message, |
125 | | - }); |
126 | | - }); |
127 | | - } |
| 108 | + addValidator(path: string[], validator: SchemaValidator) { |
| 109 | + if (!this.store) return; |
| 110 | + const key = this._getKey(path); |
| 111 | + this.store.update((state) => { |
| 112 | + Object.assign((state as any)[key], { |
| 113 | + onValidate: markRaw(validator.validate), |
| 114 | + onFail: validator.onFail || "throw-pass", |
| 115 | + invalidTips: validator.message, |
| 116 | + }); |
| 117 | + }); |
| 118 | + } |
128 | 119 |
|
129 | | - remove(path: keyof SchemaStore['state']) { |
130 | | - const key = this._getKey(path); |
131 | | - if (this.store) { |
132 | | - delete (this.store.state as any)[key]; |
133 | | - } |
134 | | - } |
| 120 | + remove(path: keyof SchemaStore["state"]) { |
| 121 | + const key = this._getKey(path); |
| 122 | + if (this.store) { |
| 123 | + delete (this.store.state as any)[key]; |
| 124 | + } |
| 125 | + } |
135 | 126 |
|
136 | | - getValues() { |
137 | | - const values: Record<string, any> = {}; |
138 | | - Object.entries(this._descriptors || {}).forEach(([key, options]) => { |
139 | | - const path = this._getPath(key); |
140 | | - const name = (options as any).name ?? path.join(PATH_DELIMITER); |
141 | | - this.shadow.peep((state) => { |
142 | | - values[name] = getVal(state, path); |
143 | | - }); |
144 | | - }); |
145 | | - return values; |
146 | | - } |
147 | | - /** |
148 | | - * 过滤出指定路径的schema |
149 | | - * |
150 | | - * 如: |
151 | | - * schemas.find("user.order") |
152 | | - * schemas.find(["user.order","order"]) |
153 | | - * |
154 | | - * @param path |
155 | | - */ |
156 | | - find(path: string | string[]) { |
157 | | - const spath = Array.isArray(path) ? path : path.split(PATH_DELIMITER); |
158 | | - return Object.entries(this.fields) |
159 | | - .filter(([key]) => { |
160 | | - return pathStartsWith(spath, this._getPath(key)); |
161 | | - }) |
162 | | - .map(([_, options]) => { |
163 | | - return options; |
164 | | - }); |
165 | | - } |
| 127 | + getValues() { |
| 128 | + const values: Record<string, any> = {}; |
| 129 | + Object.entries(this._descriptors || {}).forEach(([key, options]) => { |
| 130 | + const path = this._getPath(key); |
| 131 | + const name = (options as any).name ?? path.join(PATH_DELIMITER); |
| 132 | + this.shadow.peep((state) => { |
| 133 | + values[name] = getVal(state, path); |
| 134 | + }); |
| 135 | + }); |
| 136 | + return values; |
| 137 | + } |
| 138 | + /** |
| 139 | + * 过滤出指定路径的schema |
| 140 | + * |
| 141 | + * 如: |
| 142 | + * schemas.find("user.order") |
| 143 | + * schemas.find(["user.order","order"]) |
| 144 | + * |
| 145 | + * @param path |
| 146 | + */ |
| 147 | + find(path: string | string[]) { |
| 148 | + const spath = Array.isArray(path) ? path : path.split(PATH_DELIMITER); |
| 149 | + return Object.entries(this.fields) |
| 150 | + .filter(([key]) => { |
| 151 | + return pathStartsWith(spath, this._getPath(key)); |
| 152 | + }) |
| 153 | + .map(([_, options]) => { |
| 154 | + return options; |
| 155 | + }); |
| 156 | + } |
166 | 157 | } |
0 commit comments