Skip to content

Commit

Permalink
feat(vae): 新增 reach 方法
Browse files Browse the repository at this point in the history
  • Loading branch information
fjc0k committed Aug 7, 2023
1 parent fffd59c commit a12917d
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 37 deletions.
23 changes: 0 additions & 23 deletions src/vae/VaeContext.ts

This file was deleted.

91 changes: 80 additions & 11 deletions src/vae/VaeSchema.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { DotPath, RequiredBy, RequiredDeep } from '../types'
import {
DotPath,
DotPathValue,
OneOrMore,
RequiredBy,
RequiredDeep,
} from '../types'
import {
assign,
castArray,
cloneDeepFast,
get,
includes,
Expand All @@ -12,13 +19,14 @@ import {
} from '../utils'
import { VaeArraySchema } from './VaeArraySchema'
import { VaeBooleanSchema } from './VaeBooleanSchema'
import { VaeContext } from './VaeContext'
import { VaeDateSchema } from './VaeDateSchema'
import { VaeError } from './VaeError'
import { VaeIssue } from './VaeIssue'
import { VaeLocale, VaeLocaleMessage } from './VaeLocale'
import { VaeNumberSchema } from './VaeNumberSchema'
import { VaeObjectSchema } from './VaeObjectSchema'
import { VaeSchemaParseContext } from './VaeSchemaParseContext'
import { VaeSchemaReachContext } from './VaeSchemaReachContext'
import { VaeStringSchema } from './VaeStringSchema'

export type VaeSchemaType =
Expand Down Expand Up @@ -59,7 +67,14 @@ export type VaeSchemaParseOptions = {
*
* @inner
*/
ctx?: VaeContext
ctx?: VaeSchemaParseContext

/**
* 当前路径,内部使用
*
* @inner
*/
curPath?: VaeSchemaPath

/**
* 是否提前终止
Expand Down Expand Up @@ -185,6 +200,59 @@ export abstract class VaeSchema<T extends any = any> {
return newSchema
}

reach<P extends DotPath<T>>(
paths: P[],
ctx?: VaeSchemaReachContext,
curPath?: VaeSchemaPath,
): {
[K in P]: VaeSchemaOf<DotPathValue<T, K>>
}
reach<P extends DotPath<T>>(
path: P,
ctx?: VaeSchemaReachContext,
curPath?: VaeSchemaPath,
): VaeSchemaOf<DotPathValue<T, P>>
reach(
path: OneOrMore<string>,
ctx?: VaeSchemaReachContext,
curPath?: VaeSchemaPath,
): any {
const paths = castArray(path)
const isRoot = !ctx
ctx = ctx ?? new VaeSchemaReachContext()
curPath = curPath ?? []

const currentDotPath = curPath.join('.')
if (paths.includes(currentDotPath)) {
ctx.addSchema(currentDotPath, this)
}

for (let i = 0; i < this._options.processors.length; i++) {
const processor = this._options.processors[i]
if (typeof processor === 'object') {
if (processor.fn instanceof VaeSchema) {
const fullPath = [...curPath, ...(processor.path || [])]
if (this._options.type === 'array' && processor.tag === 'element') {
processor.fn.reach(paths, ctx, [...fullPath, 0])
} else {
processor.fn.reach(paths, ctx, fullPath)
}
}
}
}

if (!isRoot) {
return
}

const res = ctx.schemas.reduce((res, item) => {
res[item.path] = item.schema
return res
}, {} as any)

return typeof path === 'string' ? res[path] : res
}

parse(data: T, options?: VaeSchemaParseOptions): VaeSchemaParseResult<T> {
// 字符串 trim
if (
Expand Down Expand Up @@ -242,23 +310,27 @@ export abstract class VaeSchema<T extends any = any> {
)
}

const ctx = options?.ctx || new VaeContext()
const ctx = options?.ctx ?? new VaeSchemaParseContext()
const curPath = options?.curPath ?? []
options = options || {}
options.ctx = ctx
options.curPath = curPath

for (let i = 0; i < processors.length; i++) {
const processor = processors[i]
if (typeof processor === 'object') {
const { fn, message, messageParams, path = [], tag } = processor
const fullPath = [...ctx.path, ...path]
const fullPath = [...curPath, ...path]
if (fn instanceof VaeSchema) {
const pathData = path.length ? get(data, path) : data
if (this._options.type === 'array' && tag === 'element') {
if (pathData) {
for (let j = 0; j < (pathData as any[]).length; j++) {
const item = (pathData as any[])[j]
ctx.setPath([...fullPath, j])
const res = fn.parse(item, options)
const res = fn.parse(item, {
...options,
curPath: [...fullPath, j],
})
if (res.success) {
set(data as any, [...path, j], res.data)
} else {
Expand All @@ -269,12 +341,10 @@ export abstract class VaeSchema<T extends any = any> {
}
}
}
ctx.restorePath()
}
}
} else {
ctx.setPath(fullPath)
const res = fn.parse(pathData, options)
const res = fn.parse(pathData, { ...options, curPath: fullPath })
if (res.success) {
if (path.length) {
set(data as any, path, res.data)
Expand All @@ -289,7 +359,6 @@ export abstract class VaeSchema<T extends any = any> {
}
}
}
ctx.restorePath()
}
} else if (!fn(data)) {
ctx.addIssue({
Expand Down
9 changes: 9 additions & 0 deletions src/vae/VaeSchemaParseContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { VaeIssue } from './VaeIssue'

export class VaeSchemaParseContext {
issues: VaeIssue[] = []

addIssue(issue: VaeIssue) {
this.issues.push(issue)
}
}
12 changes: 12 additions & 0 deletions src/vae/VaeSchemaReachContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { VaeSchema } from './VaeSchema'

export class VaeSchemaReachContext {
schemas: Array<{
path: string
schema: VaeSchema
}> = []

addSchema(path: string, schema: VaeSchema) {
this.schemas.push({ path, schema })
}
}
58 changes: 58 additions & 0 deletions src/vae/__snapshots__/vae.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -938,6 +938,64 @@ Object {
}
`;

exports[`vae reach 1`] = `
Object {
"issues": Array [
Object {
"message": "id应是一个正整数",
"path": Array [
"id",
],
},
Object {
"message": "extra.gender应是下列值之一:0,1",
"path": Array [
"extra",
"gender",
],
},
Object {
"message": "type应是下列值之一:3,4",
"path": Array [
"type",
],
},
],
"success": false,
}
`;

exports[`vae reach 2`] = `
Object {
"data": 1,
"success": true,
}
`;

exports[`vae reach 3`] = `
Object {
"issues": Array [
Object {
"message": ".应是下列值之一:0,1",
"path": Array [],
},
],
"success": false,
}
`;

exports[`vae reach 4`] = `
Object {
"issues": Array [
Object {
"message": ".应是字符串类型",
"path": Array [],
},
],
"success": false,
}
`;

exports[`vae string 1`] = `
Object {
"data": undefined,
Expand Down
39 changes: 38 additions & 1 deletion src/vae/vae.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ describe('vae', () => {
})

test('create', () => {
const schema = v.create(_ => _.string().required())
const schema = v.create<VaeSchemaOf<string>>(_ => _.string().required())
expect(schema.parse('1')).toMatchSnapshot()

const schema2: VaeSchemaOf<{
Expand All @@ -594,4 +594,41 @@ describe('vae', () => {
}),
).toMatchSnapshot()
})

test('reach', () => {
const schema = v.object<{
id: number
images: string[]
extra: {
gender: number
}
type: number
}>({
id: v.number().required().id(),
images: v.array(a => a.required().element(v.string())),
extra: v.object({
gender: v.number().required().enum([0, 1]),
}),
type: v.number().enum([3, 4]),
})

expect(
schema.parse({
id: 0,
images: [],
extra: {
gender: 3,
},
type: 5,
}),
).toMatchSnapshot()
expect(schema.reach('extra.gender').parse(1)).toMatchSnapshot()
expect(schema.reach('extra.gender').parse(2)).toMatchSnapshot()
expect(
schema.reach(['extra.gender', 'images.0'])['images.0'].parse(
// @ts-expect-error
false,
),
).toMatchSnapshot()
})
})
10 changes: 8 additions & 2 deletions src/vae/vae.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,12 @@ const schemaBuilders = {
export const v = {
...schemaBuilders,

create: <T>(cb: (_: typeof schemaBuilders) => T): T => cb(schemaBuilders),
create: <
R,
F extends (_: typeof schemaBuilders) => R = (_: typeof schemaBuilders) => R,
>(
cb: F,
): R => cb(schemaBuilders),

localeBuilder: VaeLocaleBuilder,
setLocale: (locale: VaeLocaleShape) => {
Expand All @@ -130,13 +135,14 @@ export const v = {
// @index('./Vae*.ts', f => `export * from '${f.path}'`)
export * from './VaeArraySchema'
export * from './VaeBooleanSchema'
export * from './VaeContext'
export * from './VaeDateSchema'
export * from './VaeError'
export * from './VaeIssue'
export * from './VaeLocale'
export * from './VaeNumberSchema'
export * from './VaeObjectSchema'
export * from './VaeSchema'
export * from './VaeSchemaParseContext'
export * from './VaeSchemaReachContext'
export * from './VaeStringSchema'
// @endindex

0 comments on commit a12917d

Please sign in to comment.