-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
schema.ts
135 lines (125 loc) 路 3.4 KB
/
schema.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import { each, toArr } from './array'
import { getIn, setIn } from './accessor'
import { isFn, Path, ISchema, ArrayPath } from '@uform/types'
import { isEmpty } from './isEmpty'
const numberRE = /^\d+$/
const VIRTUAL_BOXES = {}
interface IRuleDescription {
required?: boolean
message?: string
pattern?: RegExp | string
validator?: RuleHandler
}
interface IPathInfo {
name: string
path: string[]
schemaPath: string[]
}
type RuleHandler = (
value: any,
rule: IRuleDescription,
values: object,
name: string
) => string | null
export const getSchemaNodeFromPath = (schema: ISchema, path: Path) => {
let res = schema
let suc = 0
path = toArr(path)
for (let i = 0; i < path.length; i++) {
const key = path[i]
if (res && !isEmpty(res.properties)) {
res = res.properties[key]
suc++
} else if (res && !isEmpty(res.items) && numberRE.test(key as string)) {
res = res.items
suc++
}
}
return suc === path.length ? res : undefined
}
export const schemaIs = (schema: ISchema, type: string) => {
return schema && schema.type === type
}
export const isVirtualBox = (name: string) => {
return !!VIRTUAL_BOXES[name]
}
export const registerVirtualboxFlag = (name: string) => {
VIRTUAL_BOXES[name] = true
}
const isVirtualBoxSchema = (schema: ISchema) => {
return isVirtualBox(schema.type) || isVirtualBox(schema['x-component'])
}
const schemaTraverse = (
schema: ISchema,
callback: any,
path: ArrayPath = [],
schemaPath = []
) => {
if (schema) {
if (isVirtualBoxSchema(schema)) {
path = path.slice(0, path.length - 1)
}
callback(schema, { path, schemaPath })
if (schemaIs(schema, 'object') || schema.properties) {
each(schema.properties, (subSchema, key) => {
schemaTraverse(
subSchema,
callback,
path.concat(key),
schemaPath.concat(key)
)
})
} else if (schemaIs(schema, 'array') || schema.items) {
if (schema.items) {
callback(
schema.items,
key => {
schemaTraverse(
schema.items,
callback,
path.concat(key),
schemaPath.concat(key)
)
},
path
)
}
}
}
}
export const calculateSchemaInitialValues = (
schema: ISchema,
initialValues: any,
callback?: (pathInfo: IPathInfo, schema: ISchema, value: any) => void
) => {
initialValues = initialValues || schema.default || {}
schemaTraverse(schema, (subSchema, $path, parentPath) => {
const defaultValue = subSchema.default
if (isFn($path) && parentPath) {
each(toArr(getIn(initialValues, parentPath)), (value, index) => {
$path(index)
})
} else if ($path) {
const isVirtualBoxInstance = isVirtualBoxSchema(subSchema)
const name = isVirtualBoxInstance
? $path.schemaPath.join('.')
: $path.path.join('.')
const path = isVirtualBoxInstance ? $path.schemaPath : $path.path
const schemaPath = $path.schemaPath
const initialValue = getIn(initialValues, name)
const value = !isEmpty(initialValue) ? initialValue : defaultValue
if (!isEmpty(value)) {
setIn(initialValues, name, value)
}
if (callback && isFn(callback)) {
const newPath = {
name,
path,
schemaPath
}
callback(newPath, subSchema, value)
}
}
})
return initialValues
}