Skip to content

Commit db57a67

Browse files
Merge pull request #211 from Saeris/feat/add-reflection-api
Add Schema Reflection API
2 parents fbb4ee2 + a90ac7d commit db57a67

File tree

276 files changed

+4770
-3681
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

276 files changed

+4770
-3681
lines changed

library/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
All notable changes to the library will be documented in this file.
44

5+
## vX.X.X (Month DD, YYYY)
6+
7+
- Change structure of schemas, validations and transformations to make properties accessible (pull request #211)
8+
59
## v0.20.1 (November 2, 2023)
610

711
- Remove `never` from type signatur of strict objects and tuples (issue #234)

library/src/error/ValiError/ValiError.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Issues } from '../../types.ts';
1+
import type { Issues } from '../../types/index.ts';
22

33
/**
44
* A Valibot error with useful information.

library/src/error/flatten/flatten.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, expect, test } from 'vitest';
2-
import type { Issue, Issues } from '../../types.ts';
2+
import type { Issue, Issues } from '../../types/index.ts';
33
import { ValiError } from '../ValiError/index.ts';
44
import { flatten } from './flatten.ts';
55

library/src/error/flatten/flatten.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import type {
2727
BaseSchemaAsync,
2828
Input,
2929
Issues,
30-
} from '../../types.ts';
30+
} from '../../types/index.ts';
3131
import type { ValiError } from '../ValiError/index.ts';
3232

3333
/**

library/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ export * from './methods/index.ts';
33
export * from './regex.ts';
44
export * from './schemas/index.ts';
55
export * from './transformations/index.ts';
6+
export * from './types/index.ts';
67
export * from './utils/index.ts';
78
export * from './validations/index.ts';
8-
export * from './types.ts';

library/src/methods/brand/brand.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { describe, expect, expectTypeOf, test } from 'vitest';
22
import { object, string } from '../../schemas/index.ts';
3-
import type { Output } from '../../types.ts';
3+
import type { Output } from '../../types/index.ts';
44
import { parse } from '../parse/index.ts';
55
import { brand, type Brand } from './brand.ts';
66

library/src/methods/brand/brand.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type {
33
BaseSchemaAsync,
44
Input,
55
Output,
6-
} from '../../types.ts';
6+
} from '../../types/index.ts';
77

88
/**
99
* Brand symbol.

library/src/methods/coerce/coerce.ts

+1-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { BaseSchema } from '../../types.ts';
1+
import type { BaseSchema } from '../../types/index.ts';
22

33
/**
44
* Coerces the input of a schema to match the required type.
@@ -14,15 +14,6 @@ export function coerce<TSchema extends BaseSchema>(
1414
): TSchema {
1515
return {
1616
...schema,
17-
18-
/**
19-
* Parses unknown input based on its schema.
20-
*
21-
* @param input The input to be parsed.
22-
* @param info The parse info.
23-
*
24-
* @returns The parsed output.
25-
*/
2617
_parse(input, info) {
2718
return schema._parse(action(input), info);
2819
},

library/src/methods/coerce/coerceAsync.ts

+1-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { BaseSchemaAsync } from '../../types.ts';
1+
import type { BaseSchemaAsync } from '../../types/index.ts';
22

33
/**
44
* Coerces the input of a async schema to match the required type.
@@ -14,15 +14,6 @@ export function coerceAsync<TSchema extends BaseSchemaAsync>(
1414
): TSchema {
1515
return {
1616
...schema,
17-
18-
/**
19-
* Parses unknown input based on its schema.
20-
*
21-
* @param input The input to be parsed.
22-
* @param info The parse info.
23-
*
24-
* @returns The parsed output.
25-
*/
2617
async _parse(input, info) {
2718
return schema._parse(await action(input), info);
2819
},

library/src/methods/fallback/fallback.ts

+17-24
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
1-
import type { BaseSchema, Output } from '../../types.ts';
1+
import type { BaseSchema, Output } from '../../types/index.ts';
22
import { getOutput } from '../../utils/index.ts';
3+
import { getFallback } from '../getFallback/index.ts';
34
import type { FallbackInfo } from './types.ts';
45

56
/**
67
* Schema with fallback type.
78
*/
89
export type SchemaWithFallback<
910
TSchema extends BaseSchema = BaseSchema,
10-
TFallback extends Output<TSchema> = Output<TSchema>
11-
> = TSchema & { getFallback: (info?: FallbackInfo) => TFallback };
11+
TFallback extends
12+
| Output<TSchema>
13+
| ((info?: FallbackInfo) => Output<TSchema>) = Output<TSchema>
14+
> = TSchema & {
15+
/**
16+
* The fallback value.
17+
*/
18+
fallback: TFallback;
19+
};
1220

1321
/**
1422
* Returns a fallback value when validating the passed schema failed.
@@ -20,36 +28,21 @@ export type SchemaWithFallback<
2028
*/
2129
export function fallback<
2230
TSchema extends BaseSchema,
23-
TFallback extends Output<TSchema>
31+
const TFallback extends
32+
| Output<TSchema>
33+
| ((info?: FallbackInfo) => Output<TSchema>)
2434
>(
2535
schema: TSchema,
26-
fallback: TFallback | ((info?: FallbackInfo) => TFallback)
36+
fallback: TFallback
2737
): SchemaWithFallback<TSchema, TFallback> {
2838
return {
2939
...schema,
30-
31-
/**
32-
* Returns the fallback value.
33-
*/
34-
getFallback(info) {
35-
return typeof fallback === 'function'
36-
? (fallback as (info?: FallbackInfo) => TFallback)(info)
37-
: (fallback as TFallback);
38-
},
39-
40-
/**
41-
* Parses unknown input based on its schema.
42-
*
43-
* @param input The input to be parsed.
44-
* @param info The parse info.
45-
*
46-
* @returns The parsed output.
47-
*/
40+
fallback,
4841
_parse(input, info) {
4942
const result = schema._parse(input, info);
5043
return getOutput(
5144
result.issues
52-
? this.getFallback({ input, issues: result.issues })
45+
? getFallback(this, { input, issues: result.issues })
5346
: result.output
5447
);
5548
},

library/src/methods/fallback/fallbackAsync.ts

+19-28
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,24 @@
1-
import type { BaseSchemaAsync, Output } from '../../types.ts';
1+
import type { BaseSchemaAsync, Output } from '../../types/index.ts';
22
import { getOutput } from '../../utils/index.ts';
3+
import { getFallbackAsync } from '../getFallback/index.ts';
34
import type { FallbackInfo } from './types.ts';
45

56
/**
67
* Schema with fallback async type.
78
*/
89
export type SchemaWithFallbackAsync<
910
TSchema extends BaseSchemaAsync = BaseSchemaAsync,
10-
TFallback extends Output<TSchema> = Output<TSchema>
11-
> = TSchema & { getFallback: (info?: FallbackInfo) => Promise<TFallback> };
11+
TFallback extends
12+
| Output<TSchema>
13+
| ((
14+
info?: FallbackInfo
15+
) => Output<TSchema> | Promise<Output<TSchema>>) = Output<TSchema>
16+
> = TSchema & {
17+
/**
18+
* The fallback value.
19+
*/
20+
fallback: TFallback;
21+
};
1222

1323
/**
1424
* Returns a fallback value when validating the passed schema failed.
@@ -20,40 +30,21 @@ export type SchemaWithFallbackAsync<
2030
*/
2131
export function fallbackAsync<
2232
TSchema extends BaseSchemaAsync,
23-
TFallback extends Output<TSchema>
33+
const TFallback extends
34+
| Output<TSchema>
35+
| ((info?: FallbackInfo) => Output<TSchema> | Promise<Output<TSchema>>)
2436
>(
2537
schema: TSchema,
26-
fallback:
27-
| TFallback
28-
| ((info?: FallbackInfo) => TFallback | Promise<TFallback>)
38+
fallback: TFallback
2939
): SchemaWithFallbackAsync<TSchema, TFallback> {
3040
return {
3141
...schema,
32-
33-
/**
34-
* Returns the default value.
35-
*/
36-
async getFallback(info) {
37-
return typeof fallback === 'function'
38-
? await (
39-
fallback as (info?: FallbackInfo) => TFallback | Promise<TFallback>
40-
)(info)
41-
: (fallback as TFallback);
42-
},
43-
44-
/**
45-
* Parses unknown input based on its schema.
46-
*
47-
* @param input The input to be parsed.
48-
* @param info The parse info.
49-
*
50-
* @returns The parsed output.
51-
*/
42+
fallback,
5243
async _parse(input, info) {
5344
const result = await schema._parse(input, info);
5445
return getOutput(
5546
result.issues
56-
? await this.getFallback({ input, issues: result.issues })
47+
? await getFallbackAsync(this, { input, issues: result.issues })
5748
: result.output
5849
);
5950
},

library/src/methods/fallback/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Issues } from '../../types.ts';
1+
import type { Issues } from '../../types/index.ts';
22

33
/**
44
* Fallback info type.

library/src/methods/getDefault/getDefault.ts

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
import type { BaseSchema, Output } from '../../types.ts';
1+
import type { BaseSchema, Output } from '../../types/index.ts';
22
import type { DefaultValue } from './types.ts';
33

44
/**
55
* Schema with maybe default type.
66
*/
77
export type SchemaWithMaybeDefault<TSchema extends BaseSchema = BaseSchema> =
8-
TSchema & { getDefault?: () => Output<TSchema> };
8+
TSchema & {
9+
/**
10+
* The optional default value.
11+
*/
12+
default?: Output<TSchema> | (() => Output<TSchema> | undefined);
13+
};
914

1015
/**
1116
* Returns the default value of the schema.
@@ -17,5 +22,7 @@ export type SchemaWithMaybeDefault<TSchema extends BaseSchema = BaseSchema> =
1722
export function getDefault<TSchema extends SchemaWithMaybeDefault>(
1823
schema: TSchema
1924
): DefaultValue<TSchema> {
20-
return schema.getDefault?.();
25+
return typeof schema.default === 'function'
26+
? schema.default()
27+
: schema.default;
2128
}

library/src/methods/getDefault/getDefaultAsync.ts

+15-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { BaseSchemaAsync, Output } from '../../types.ts';
1+
import type { BaseSchemaAsync, Output } from '../../types/index.ts';
22
import type { SchemaWithMaybeDefault } from './getDefault.ts';
33
import type { DefaultValue } from './types.ts';
44

@@ -7,7 +7,17 @@ import type { DefaultValue } from './types.ts';
77
*/
88
export type SchemaWithMaybeDefaultAsync<
99
TSchema extends BaseSchemaAsync = BaseSchemaAsync
10-
> = TSchema & { getDefault?: () => Promise<Output<TSchema>> };
10+
> = TSchema & {
11+
/**
12+
* The optional default value.
13+
*/
14+
default?:
15+
| Output<TSchema>
16+
| (() =>
17+
| Output<TSchema>
18+
| Promise<Output<TSchema> | undefined>
19+
| undefined);
20+
};
1121

1222
/**
1323
* Returns the default value of the schema.
@@ -19,5 +29,7 @@ export type SchemaWithMaybeDefaultAsync<
1929
export async function getDefaultAsync<
2030
TSchema extends SchemaWithMaybeDefault | SchemaWithMaybeDefaultAsync
2131
>(schema: TSchema): Promise<DefaultValue<TSchema>> {
22-
return schema.getDefault?.();
32+
return typeof schema.default === 'function'
33+
? await schema.default()
34+
: schema.default;
2335
}
+7-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Output } from '../../types.ts';
1+
import type { Output } from '../../types/index.ts';
22
import type { SchemaWithMaybeDefault } from './getDefault.ts';
33
import type { SchemaWithMaybeDefaultAsync } from './getDefaultAsync.ts';
44

@@ -7,8 +7,10 @@ import type { SchemaWithMaybeDefaultAsync } from './getDefaultAsync.ts';
77
*/
88
export type DefaultValue<
99
TSchema extends SchemaWithMaybeDefault | SchemaWithMaybeDefaultAsync
10-
> = TSchema['getDefault'] extends () => Output<TSchema>
11-
? ReturnType<TSchema['getDefault']>
12-
: TSchema['getDefault'] extends () => Promise<Output<TSchema>>
13-
? Awaited<ReturnType<TSchema['getDefault']>>
10+
> = TSchema['default'] extends Output<TSchema> | undefined
11+
? TSchema['default']
12+
: TSchema['default'] extends () => Output<TSchema> | undefined
13+
? ReturnType<TSchema['default']>
14+
: TSchema['default'] extends () => Promise<Output<TSchema> | undefined>
15+
? Awaited<ReturnType<TSchema['default']>>
1416
: undefined;

library/src/methods/getDefaults/getDefaults.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ import type {
44
TupleItems,
55
TupleSchema,
66
} from '../../schemas/index.ts';
7-
import type { BaseSchema } from '../../types.ts';
8-
import type { SchemaWithMaybeDefault } from '../getDefault/getDefault.ts';
7+
import type { BaseSchema } from '../../types/index.ts';
8+
import {
9+
getDefault,
10+
type SchemaWithMaybeDefault,
11+
} from '../getDefault/index.ts';
912
import type { DefaultValues } from './types.ts';
1013

1114
/**
@@ -28,8 +31,8 @@ export function getDefaults<
2831
let defaults: any;
2932

3033
// If schema contains a default function, set its default value
31-
if (schema.getDefault) {
32-
defaults = schema.getDefault();
34+
if (schema.default) {
35+
defaults = getDefault(schema);
3336

3437
// Otherwise, check if schema is of kind object or tuple
3538
} else if ('type' in schema) {

library/src/methods/getDefaults/getDefaultsAsync.ts

+7-6
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ import type {
88
TupleSchema,
99
TupleSchemaAsync,
1010
} from '../../schemas/index.ts';
11-
import type { BaseSchema, BaseSchemaAsync } from '../../types.ts';
12-
import type {
13-
SchemaWithMaybeDefault,
14-
SchemaWithMaybeDefaultAsync,
11+
import type { BaseSchema, BaseSchemaAsync } from '../../types/index.ts';
12+
import {
13+
getDefaultAsync,
14+
type SchemaWithMaybeDefault,
15+
type SchemaWithMaybeDefaultAsync,
1516
} from '../getDefault/index.ts';
1617
import type { DefaultValues } from './types.ts';
1718

@@ -43,8 +44,8 @@ export async function getDefaultsAsync<
4344
let defaults: any;
4445

4546
// If schema contains a default function, set its default value
46-
if (schema.getDefault) {
47-
defaults = await schema.getDefault();
47+
if (schema.default) {
48+
defaults = await getDefaultAsync(schema);
4849

4950
// Otherwise, check if schema is of kind object or tuple
5051
} else if ('type' in schema) {

0 commit comments

Comments
 (0)