@anjianshi/utils 3.0.0 → 3.0.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.
Files changed (164) hide show
  1. package/env-browser/device.d.ts +24 -0
  2. package/env-browser/device.js +50 -0
  3. package/env-browser/global.d.ts +10 -0
  4. package/env-browser/global.js +15 -0
  5. package/env-browser/load-script.d.ts +5 -0
  6. package/env-browser/load-script.js +13 -0
  7. package/env-browser/logging.d.ts +18 -0
  8. package/env-browser/logging.js +49 -0
  9. package/env-browser/manage-vconsole.d.ts +16 -0
  10. package/env-browser/manage-vconsole.js +38 -0
  11. package/env-node/crypto-random.d.ts +13 -0
  12. package/env-node/crypto-random.js +28 -0
  13. package/env-node/fs.d.ts +19 -0
  14. package/env-node/fs.js +48 -0
  15. package/env-node/index.d.ts +5 -0
  16. package/env-node/index.js +5 -0
  17. package/env-node/logging/handlers.d.ts +58 -0
  18. package/env-node/logging/handlers.js +154 -0
  19. package/env-node/logging/index.d.ts +11 -0
  20. package/env-node/logging/index.js +14 -0
  21. package/{src/env-react/emotion-register-globals.ts → env-react/emotion-register-globals.d.ts} +2 -5
  22. package/env-react/emotion-register-globals.js +5 -0
  23. package/env-react/emotion.d.ts +20 -0
  24. package/env-react/emotion.jsx +34 -0
  25. package/env-react/hooks.d.ts +23 -0
  26. package/env-react/hooks.js +47 -0
  27. package/env-react/index.d.ts +1 -0
  28. package/env-react/index.js +1 -0
  29. package/env-react/react-register-globals.d.ts +21 -0
  30. package/env-react/react-register-globals.js +19 -0
  31. package/env-service/controllers.d.ts +30 -0
  32. package/env-service/controllers.js +41 -0
  33. package/env-service/env-reader.d.ts +55 -0
  34. package/env-service/env-reader.js +79 -0
  35. package/env-service/index.d.ts +6 -0
  36. package/env-service/index.js +6 -0
  37. package/env-service/prisma/adapt-logging.d.ts +21 -0
  38. package/env-service/prisma/adapt-logging.js +30 -0
  39. package/env-service/prisma/extensions/exist.d.ts +10 -0
  40. package/env-service/prisma/extensions/exist.js +16 -0
  41. package/env-service/prisma/extensions/find-and-count.d.ts +7 -0
  42. package/env-service/prisma/extensions/find-and-count.js +19 -0
  43. package/env-service/prisma/extensions/soft-delete.d.ts +52 -0
  44. package/env-service/prisma/extensions/soft-delete.js +123 -0
  45. package/env-service/prisma/extensions/with-transaction.d.ts +9 -0
  46. package/env-service/prisma/extensions/with-transaction.js +54 -0
  47. package/env-service/prisma/index.d.ts +6 -0
  48. package/env-service/prisma/index.js +6 -0
  49. package/env-service/prisma/transaction-contexted.d.ts +11 -0
  50. package/env-service/prisma/transaction-contexted.js +52 -0
  51. package/env-service/redis-cache.d.ts +39 -0
  52. package/env-service/redis-cache.js +116 -0
  53. package/env-service/tasks.d.ts +12 -0
  54. package/env-service/tasks.js +37 -0
  55. package/index.d.ts +4 -0
  56. package/index.js +4 -0
  57. package/init-dayjs.d.ts +2 -0
  58. package/init-dayjs.js +7 -0
  59. package/lang/async.d.ts +19 -0
  60. package/lang/async.js +34 -0
  61. package/lang/color.d.ts +37 -0
  62. package/lang/color.js +111 -0
  63. package/lang/index.d.ts +8 -0
  64. package/lang/index.js +8 -0
  65. package/lang/object.d.ts +12 -0
  66. package/lang/object.js +41 -0
  67. package/lang/random.d.ts +13 -0
  68. package/lang/random.js +24 -0
  69. package/lang/result.d.ts +47 -0
  70. package/lang/result.js +45 -0
  71. package/lang/string.d.ts +29 -0
  72. package/lang/string.js +92 -0
  73. package/lang/time.d.ts +10 -0
  74. package/lang/time.js +18 -0
  75. package/{src/lang/types.ts → lang/types.d.ts} +23 -43
  76. package/lang/types.js +28 -0
  77. package/logging/adapt.d.ts +10 -0
  78. package/logging/adapt.js +43 -0
  79. package/logging/formatters.d.ts +10 -0
  80. package/logging/formatters.js +22 -0
  81. package/logging/index.d.ts +45 -0
  82. package/logging/index.js +90 -0
  83. package/md5.d.ts +30 -0
  84. package/md5.js +308 -0
  85. package/package.json +10 -19
  86. package/safe-request.d.ts +53 -0
  87. package/safe-request.js +140 -0
  88. package/url.d.ts +77 -0
  89. package/url.js +149 -0
  90. package/validators/array.d.ts +30 -0
  91. package/validators/array.js +47 -0
  92. package/validators/base.d.ts +82 -0
  93. package/validators/base.js +42 -0
  94. package/validators/boolean.d.ts +3 -0
  95. package/validators/boolean.js +22 -0
  96. package/validators/datetime.d.ts +12 -0
  97. package/validators/datetime.js +30 -0
  98. package/validators/factory.d.ts +70 -0
  99. package/validators/factory.js +121 -0
  100. package/validators/index.d.ts +9 -0
  101. package/validators/index.js +9 -0
  102. package/validators/number.d.ts +19 -0
  103. package/validators/number.js +26 -0
  104. package/validators/object.d.ts +28 -0
  105. package/validators/object.js +49 -0
  106. package/validators/one-of.d.ts +10 -0
  107. package/validators/one-of.js +15 -0
  108. package/validators/string.d.ts +22 -0
  109. package/validators/string.js +35 -0
  110. package/README.md +0 -10
  111. package/eslint.config.cjs +0 -33
  112. package/publish-prepare.cjs +0 -16
  113. package/src/env-browser/device.ts +0 -62
  114. package/src/env-browser/global.ts +0 -21
  115. package/src/env-browser/load-script.ts +0 -13
  116. package/src/env-browser/logging.ts +0 -58
  117. package/src/env-browser/manage-vconsole.ts +0 -54
  118. package/src/env-node/crypto-random.ts +0 -30
  119. package/src/env-node/fs.ts +0 -50
  120. package/src/env-node/index.ts +0 -5
  121. package/src/env-node/logging/handlers.ts +0 -190
  122. package/src/env-node/logging/index.ts +0 -16
  123. package/src/env-react/emotion.tsx +0 -42
  124. package/src/env-react/hooks.ts +0 -59
  125. package/src/env-react/index.ts +0 -1
  126. package/src/env-react/react-register-globals.ts +0 -53
  127. package/src/env-service/controllers.ts +0 -93
  128. package/src/env-service/env-reader.ts +0 -141
  129. package/src/env-service/index.ts +0 -6
  130. package/src/env-service/prisma/adapt-logging.ts +0 -39
  131. package/src/env-service/prisma/extensions/exist.ts +0 -21
  132. package/src/env-service/prisma/extensions/find-and-count.ts +0 -24
  133. package/src/env-service/prisma/extensions/soft-delete.ts +0 -162
  134. package/src/env-service/prisma/extensions/with-transaction.ts +0 -65
  135. package/src/env-service/prisma/index.ts +0 -6
  136. package/src/env-service/prisma/transaction-contexted.ts +0 -80
  137. package/src/env-service/redis-cache.ts +0 -142
  138. package/src/env-service/tasks.ts +0 -45
  139. package/src/index.ts +0 -4
  140. package/src/init-dayjs.ts +0 -8
  141. package/src/lang/async.ts +0 -47
  142. package/src/lang/color.ts +0 -119
  143. package/src/lang/index.ts +0 -8
  144. package/src/lang/object.ts +0 -39
  145. package/src/lang/random.ts +0 -25
  146. package/src/lang/result.ts +0 -78
  147. package/src/lang/string.ts +0 -95
  148. package/src/lang/time.ts +0 -19
  149. package/src/logging/adapt.ts +0 -49
  150. package/src/logging/formatters.ts +0 -23
  151. package/src/logging/index.ts +0 -106
  152. package/src/md5.ts +0 -318
  153. package/src/safe-request.ts +0 -193
  154. package/src/url.ts +0 -185
  155. package/src/validators/array.ts +0 -97
  156. package/src/validators/base.ts +0 -145
  157. package/src/validators/boolean.ts +0 -21
  158. package/src/validators/datetime.ts +0 -39
  159. package/src/validators/factory.ts +0 -244
  160. package/src/validators/index.ts +0 -9
  161. package/src/validators/number.ts +0 -54
  162. package/src/validators/object.ts +0 -101
  163. package/src/validators/one-of.ts +0 -33
  164. package/src/validators/string.ts +0 -72
@@ -1,244 +0,0 @@
1
- /**
2
- * 实现创建 validator 的快捷方式
3
- */
4
- import {
5
- type ArrayOptions,
6
- getArrayValidator,
7
- type TupleOptions,
8
- getTupleValidator,
9
- } from './array.js'
10
- import { type Validator, type CommonOptions, type Validated, getAnyValidator } from './base.js'
11
- import { type BooleanOptions, getBooleanValidator } from './boolean.js'
12
- import { type DatetimeOptions, type DatetimeValue, getDatetimeValidator } from './datetime.js'
13
- import { type NumberOptions, type NumberValueWithChoices, getNumberValidator } from './number.js'
14
- import {
15
- type RecordOptions,
16
- getRecordValidator,
17
- type StructOptions,
18
- getStructValidator,
19
- } from './object.js'
20
- import { type OneOfOptions, getOneOfValidator } from './one-of.js'
21
- import { type StringOptions, type StringValueWithChoices, getStringValidator } from './string.js'
22
-
23
- export interface AnyDefinition extends CommonOptions {
24
- type: 'any'
25
- }
26
- export interface BooleanDefinition extends BooleanOptions {
27
- type: 'boolean'
28
- }
29
- export interface NumberDefinition extends NumberOptions {
30
- type: 'number'
31
- }
32
- export interface StringDefinition extends StringOptions {
33
- type: 'string'
34
- }
35
- export interface DatetimeDefinition extends DatetimeOptions {
36
- type: 'datetime'
37
- }
38
- export interface ArrayDefinition extends Omit<ArrayOptions, 'item'> {
39
- type: 'array'
40
- item: Definition
41
- }
42
- export interface TupleDefinition extends Omit<TupleOptions, 'tuple'> {
43
- type: 'tuple'
44
- tuple: Definition[]
45
- }
46
- export interface StructDefinition extends Omit<StructOptions, 'struct'> {
47
- type: 'struct'
48
- struct: Record<string, Definition>
49
- }
50
- export interface RecordDefinition extends Omit<RecordOptions, 'record'> {
51
- type: 'record'
52
- record: Definition
53
- }
54
- export interface OneOfDefinition extends Omit<OneOfOptions, 'validators'> {
55
- type: 'oneOf'
56
- validators: Definition[]
57
- }
58
-
59
- export type Definition =
60
- | AnyDefinition
61
- | BooleanDefinition
62
- | NumberDefinition
63
- | StringDefinition
64
- | DatetimeDefinition
65
- | ArrayDefinition
66
- | TupleDefinition
67
- | StructDefinition
68
- | RecordDefinition
69
- | OneOfDefinition
70
-
71
- export type ValueOfDefinition<Def extends Definition> = Def extends AnyDefinition
72
- ? unknown
73
- : Def extends BooleanDefinition
74
- ? boolean
75
- : Def extends NumberDefinition
76
- ? NumberValueWithChoices<Def>
77
- : Def extends StringDefinition
78
- ? StringValueWithChoices<Def>
79
- : Def extends DatetimeDefinition
80
- ? DatetimeValue<Def>
81
- : Def extends ArrayDefinition
82
- ? Validated<ValueOfDefinition<Def['item']>, Def['item']>[]
83
- : Def extends TupleDefinition
84
- ? {
85
- [Key in keyof Def['tuple']]: Def['tuple'][Key] extends Definition
86
- ? Validated<ValueOfDefinition<Def['tuple'][Key]>, Def['tuple'][Key]>
87
- : Def['tuple'][Key]
88
- }
89
- : Def extends StructDefinition
90
- ? {
91
- [Key in keyof Def['struct']]: Validated<
92
- ValueOfDefinition<Def['struct'][Key]>,
93
- Def['struct'][Key]
94
- >
95
- }
96
- : Def extends RecordDefinition
97
- ? Record<string, Validated<ValueOfDefinition<Def['record']>, Def['record']>>
98
- : Def extends OneOfDefinition
99
- ? {
100
- [Key in keyof Def['validators']]: Def['validators'][Key] extends Definition
101
- ? Validated<ValueOfDefinition<Def['validators'][Key]>, Def['validators'][Key]>
102
- : Def['validators'][Key]
103
- }[number]
104
- : never
105
-
106
- export type OptionsFromDefinition<Def extends Definition> = Def extends ArrayDefinition
107
- ? Omit<Def, 'item'> & { item: ValidatorForDefinition<Def['item']> }
108
- : Def extends TupleDefinition
109
- ? Omit<Def, 'tuple'> & {
110
- tuple: {
111
- [Key in keyof Def['tuple']]: Def['tuple'][Key] extends Definition
112
- ? ValidatorForDefinition<Def['tuple'][Key]>
113
- : never
114
- }
115
- }
116
- : Def extends StructDefinition
117
- ? Omit<Def, 'struct'> & {
118
- struct: { [Key in keyof Def['struct']]: ValidatorForDefinition<Def['struct'][Key]> }
119
- }
120
- : Def extends RecordDefinition
121
- ? Omit<Def, 'record'> & { record: ValidatorForDefinition<Def['record']> }
122
- : Def
123
-
124
- export type ValidatorForDefinition<Def extends Definition> = Validator<
125
- ValueOfDefinition<Def>,
126
- OptionsFromDefinition<Def>
127
- >
128
-
129
- export type ResultForDefinition<Def extends Definition> = ReturnType<ValidatorForDefinition<Def>>
130
-
131
- export function getValidator<const InputDefinition extends Definition>(
132
- definition: InputDefinition
133
- ): ValidatorForDefinition<InputDefinition> {
134
- type GotValidator = ValidatorForDefinition<InputDefinition>
135
- switch (definition.type) {
136
- case 'any':
137
- return getAnyValidator(definition) as GotValidator
138
- case 'boolean':
139
- return getBooleanValidator(definition) as GotValidator
140
- case 'number':
141
- return getNumberValidator(definition) as GotValidator
142
- case 'string':
143
- return getStringValidator(definition) as GotValidator
144
- case 'datetime':
145
- return getDatetimeValidator(definition) as GotValidator
146
- case 'array':
147
- // @ts-ignore 允许递归类型推断
148
- return getArrayValidator({
149
- // @ts-ignore 允许递归类型推断
150
- ...definition,
151
- item: getValidator(definition.item),
152
- }) as GotValidator
153
- case 'tuple':
154
- return getTupleValidator({
155
- ...definition,
156
- tuple: definition.tuple.map(def => getValidator(def)),
157
- }) as GotValidator
158
- case 'struct': {
159
- const struct: Record<string, Validator<unknown, CommonOptions>> = {}
160
- for (const [key, def] of Object.entries(definition.struct)) struct[key] = getValidator(def)
161
- return getStructValidator({ ...definition, struct }) as GotValidator
162
- }
163
- case 'record':
164
- return getRecordValidator({
165
- ...definition,
166
- record: getValidator(definition.record),
167
- }) as GotValidator
168
- case 'oneOf':
169
- return getOneOfValidator({
170
- ...definition,
171
- validators: definition.validators.map(def => getValidator(def)),
172
- }) as GotValidator
173
- }
174
- }
175
-
176
- // ---------------- 测试用例 -----------------
177
-
178
- // const v1 = getValidator({ type: 'string' })(1)
179
- // const v2 = getValidator({ type: 'string', null: true })(1)
180
- // const v3 = getValidator({ type: 'string', null: true, required: false })(1)
181
- // const v4 = getValidator({ type: 'string', null: true, required: false, choices: ['a', 'b', 'c'] })(
182
- // 1,
183
- // )
184
- // const v5 = getValidator({
185
- // type: 'string',
186
- // null: true,
187
- // required: false,
188
- // choices: ['a', 'b', 'c'],
189
- // defaults: 'd',
190
- // })(1)
191
- // const v6 = getValidator({
192
- // type: 'array',
193
- // null: true,
194
- // required: false,
195
- // item: { type: 'string', null: true, choices: ['a', 'b', 'c'] },
196
- // })(1)
197
- // const v7 = getValidator({
198
- // type: 'tuple',
199
- // tuple: [
200
- // { type: 'string', choices: ['a', 'b', 'c'] },
201
- // { type: 'string', null: true },
202
- // ],
203
- // })(1)
204
- // if (v7.success) {
205
- // const [a, b] = v7.data
206
- // }
207
- // const v8 = getValidator({
208
- // type: 'struct',
209
- // struct: {
210
- // x: { type: 'string', choices: ['a', 'b', 'c'] },
211
- // y: { type: 'string', null: true },
212
- // },
213
- // })(1)
214
- // if (v8.success) {
215
- // const { x, y } = v8.data
216
- // }
217
- // const v9 = getValidator({
218
- // type: 'record',
219
- // record: { type: 'string', null: true, choices: ['a', 'b', 'c'] },
220
- // })(1)
221
- // const v10 = getValidator({
222
- // type: 'oneOf',
223
- // validators: [
224
- // { type: 'string', choices: ['a', 'b', 'c'] },
225
- // { type: 'number', null: true },
226
- // ],
227
- // defaults: true,
228
- // })(1)
229
- // const v11 = getValidator({
230
- // type: 'string',
231
- // custom(value) {
232
- // return { success: true, data: value }
233
- // },
234
- // defaults: 'some text',
235
- // })(1)
236
- // const v12 = getValidator({
237
- // type: 'datetime',
238
- // null: true,
239
- // required: false,
240
- // })(1)
241
- // const v13 = getValidator({
242
- // type: 'datetime',
243
- // raw: true,
244
- // })(1)
@@ -1,9 +0,0 @@
1
- export * from './base.js'
2
- export * from './boolean.js'
3
- export * from './number.js'
4
- export * from './string.js'
5
- export * from './datetime.js'
6
- export * from './array.js'
7
- export * from './object.js'
8
- export * from './one-of.js'
9
- export * from './factory.js'
@@ -1,54 +0,0 @@
1
- import { truthy, success, failed } from '../lang/index.js'
2
- import { getValidatorGenerator, type CommonOptions } from './base.js'
3
-
4
- export interface NumberOptions extends CommonOptions<number> {
5
- /** 数值最小值 */
6
- min?: number
7
-
8
- /** 数值最大值 */
9
- max?: number
10
-
11
- /** 是否允许小数 @default false */
12
- float?: boolean
13
-
14
- /**
15
- * 指定可选值
16
- * 若指定,前几个选项将不再生效 */
17
- choices?: number[] | Record<number, string>
18
- }
19
-
20
- export type NumberValueWithChoices<Options extends NumberOptions> = Options extends {
21
- choices: (infer T)[]
22
- }
23
- ? T
24
- : Options extends { choices: Record<number, string> }
25
- ? Options['choices'][keyof Options['choices']]
26
- : number
27
-
28
- export function getNumberValidator<const Options extends NumberOptions>(
29
- options: Options = {} as Options,
30
- ) {
31
- return getValidatorGenerator<NumberValueWithChoices<Options>, Options>(
32
- function validate(field, value) {
33
- if (typeof value === 'string') value = parseFloat(value)
34
- if (typeof value !== 'number' || !isFinite(value))
35
- return failed(`${field} must be a valid number`)
36
-
37
- if ('choices' in options && options.choices) {
38
- const choices = Array.isArray(options.choices)
39
- ? options.choices
40
- : Object.values(options.choices).map(v => parseInt(v, 10))
41
- if (!choices.includes(value))
42
- return failed(`${field} can only be one of ${choices.join(', ')}.`)
43
- } else {
44
- if (!truthy(options.float) && value % 1 !== 0) return failed(`${field} must be a integer`)
45
- if (typeof options.min === 'number' && value < options.min)
46
- return failed(`${field} must >= ${options.min}`)
47
- if (typeof options.max === 'number' && value > options.max)
48
- return failed(`${field} must <= ${options.max}`)
49
- }
50
-
51
- return success(value as NumberValueWithChoices<Options>)
52
- },
53
- )(options)
54
- }
@@ -1,101 +0,0 @@
1
- import isPlainObject from 'lodash/isPlainObject.js'
2
- import { success, failed } from '../lang/index.js'
3
- import {
4
- getValidatorGenerator,
5
- type CommonOptions,
6
- type Validator,
7
- type Validated,
8
- type AllowedInputValue,
9
- } from './base.js'
10
-
11
- /** 验证有明确键值对结构的对象 */
12
- export interface StructOptions extends CommonOptions {
13
- /** 定义对象结构,及各个值的验证规则 */
14
- struct: Record<string, Validator<unknown, CommonOptions>>
15
- }
16
-
17
- type StructValues<Options extends StructOptions> = {
18
- [Key in keyof Options['struct']]: Options['struct'][Key] extends Validator<
19
- infer Value,
20
- infer Options
21
- >
22
- ? Validated<Value, Options>
23
- : never
24
- }
25
-
26
- export function getStructValidator<const Options extends StructOptions>(options: Options) {
27
- return getValidatorGenerator<StructValues<Options>, Options>(
28
- function validate(field, value, options) {
29
- if (!isPlainObject(value)) return failed(`${field} should be a plain object`)
30
-
31
- const formatted: Record<string, unknown> = {}
32
- for (const [key, itemValidator] of Object.entries(options.struct)) {
33
- const itemResult = itemValidator(
34
- `${field}["${key}"]`,
35
- (value as Record<string, AllowedInputValue>)[key],
36
- )
37
- if (itemResult.success) {
38
- if (itemResult.data !== undefined) formatted[key] = itemResult.data
39
- } else {
40
- return itemResult
41
- }
42
- }
43
- return success(formatted as StructValues<Options>)
44
- },
45
- )(options)
46
- }
47
-
48
- // ---------------------------------------------------
49
-
50
- /**
51
- * 验证有任意多个 key,但值的类型固定的对象
52
- */
53
- export interface RecordOptions extends CommonOptions {
54
- /** 验证单个值 */
55
- record: Validator<unknown, CommonOptions>
56
-
57
- /** 对象至少要有几项 */
58
- min?: number
59
-
60
- /** 对象最多有几项 */
61
- max?: number
62
- }
63
-
64
- type RecordValues<Options extends RecordOptions> = Record<
65
- string,
66
- Validated<
67
- Options extends { record: Validator<infer T, CommonOptions> } ? T : never,
68
- Options extends { record: Validator<unknown, infer T> } ? T : never
69
- >
70
- >
71
-
72
- export function getRecordValidator<Options extends RecordOptions>(options: Options) {
73
- return getValidatorGenerator<RecordValues<Options>, Options>(
74
- function validate(field, value, options) {
75
- if (!isPlainObject(value)) return failed(`${field} should be a plain object`)
76
-
77
- const formatted: Record<string, unknown> = {}
78
- for (const [key, itemValue] of Object.entries(value as Record<string, AllowedInputValue>)) {
79
- // record 场景下,值为 undefined 的项目视为不存在,不保留在验证结果里,
80
- // 不然一些因为不想赋值而填充了 undefined 值的项目可能意外触发验证失败,或意外得到了默认值。
81
- // (因此 validator 的 required 选项和 defaults 选项也没有意义了)
82
- if (itemValue === undefined) continue
83
-
84
- const itemResult = options.record(`${field}["${key}"]`, itemValue)
85
- if (itemResult.success) {
86
- if (itemResult.data !== undefined) formatted[key] = itemResult.data
87
- } else {
88
- return itemResult
89
- }
90
- }
91
-
92
- const length = Object.keys(formatted).length
93
- if (typeof options.min === 'number' && length < options.min)
94
- return failed(`size of ${field} should >= ${options.min}`)
95
- if (typeof options.max === 'number' && length > options.max)
96
- return failed(`size of ${field} should <= ${options.max}`)
97
-
98
- return success(formatted as RecordValues<Options>)
99
- },
100
- )(options)
101
- }
@@ -1,33 +0,0 @@
1
- import { failed, type Result } from '../lang/index.js'
2
- import {
3
- getValidatorGenerator,
4
- type CommonOptions,
5
- type Validator,
6
- type AllowedInputValue,
7
- } from './base.js'
8
-
9
- /** 要求返回值通过其中一个验证器的检查 */
10
- export interface OneOfOptions extends CommonOptions {
11
- /** 验证数组各元素 */
12
- validators: Validator<unknown, CommonOptions>[]
13
- }
14
-
15
- export type OneOfValue<Options extends OneOfOptions> = Options extends {
16
- validators: Validator<infer T, CommonOptions>[]
17
- }
18
- ? T
19
- : never
20
-
21
- export function getOneOfValidator<const Options extends OneOfOptions>(
22
- options: Options = {} as Options,
23
- ) {
24
- return getValidatorGenerator<OneOfValue<Options>, Options>(function validate(field, value) {
25
- const errors: string[] = []
26
- for (const validator of options.validators) {
27
- const result = validator(field, value as AllowedInputValue)
28
- if (result.success) return result as Result<OneOfValue<Options>>
29
- else errors.push(result.message)
30
- }
31
- return failed(`${field} do not match any valid format:\n- ` + errors.join('\n- '))
32
- })(options)
33
- }
@@ -1,72 +0,0 @@
1
- import { success, failed } from '../lang/index.js'
2
- import { getValidatorGenerator, type CommonOptions } from './base.js'
3
-
4
- export interface StringOptions extends CommonOptions<string> {
5
- /** 字符串最小长度。defaults='' 时默认为 0,否则默认为 1 */
6
- min?: number
7
-
8
- /** 字符串最大长度。 */
9
- max?: number
10
-
11
- /** 字符串需匹配此正则,也可传入关键词使用预置的正则。正则通常应以 ^ 和 $ 开头结尾。 */
12
- pattern?: RegExp | 'uuid' | 'mobile'
13
-
14
- /**
15
- * 指定一个数组或 TypeScript enum,字段值必须在此 enum 之中。
16
- * 若指定,前几个选项将不再生效。
17
- */
18
- choices?: string[] | Record<string, string>
19
-
20
- /** 验证之前,是否先清除两侧空白字符 @default true */
21
- trim?: boolean
22
- }
23
-
24
- export type StringValueWithChoices<Options extends StringOptions> = Options extends {
25
- choices: (infer T)[]
26
- }
27
- ? T
28
- : Options extends { choices: Record<string, infer T> }
29
- ? T
30
- : string
31
-
32
- export function getStringValidator<const Options extends StringOptions>(
33
- options: Options = {} as Options,
34
- ) {
35
- return getValidatorGenerator<StringValueWithChoices<Options>, Options>(
36
- function validate(field, value) {
37
- if (typeof value !== 'string') return failed(`${field} must be a string`)
38
-
39
- const trim = options.trim ?? true
40
- const formatted = trim ? value.trim() : value
41
-
42
- if ('choices' in options && options.choices) {
43
- const validValues: string[] = Array.isArray(options.choices)
44
- ? options.choices
45
- : Object.values(options.choices)
46
- if (!validValues.includes(formatted))
47
- return failed(`${field} can only be one of ${validValues.join(', ')}.`)
48
- } else {
49
- const { min = options.defaults === '' ? 0 : 1, max, pattern } = options
50
-
51
- if (typeof min === 'number' && formatted.length < min)
52
- return failed(`${field}'s length must >= ${min}`)
53
-
54
- if (typeof max === 'number' && formatted.length > max)
55
- return failed(`${field}'s length must <= ${max}`)
56
-
57
- if (pattern !== undefined) {
58
- if (pattern instanceof RegExp && !pattern.exec(formatted))
59
- return failed(`${field} does not match the pattern`)
60
- if (pattern === 'mobile' && !/^1\d{10}$/.test(formatted))
61
- return failed(`${field} is not a valid mobile number`)
62
- if (pattern === 'uuid') {
63
- if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(formatted))
64
- return failed(`${field} is not a valid uuid`)
65
- }
66
- }
67
- }
68
-
69
- return success(formatted as StringValueWithChoices<Options>)
70
- },
71
- )(options)
72
- }