Skip to content

Commit

Permalink
Merge pull request #211 from Saeris/feat/add-reflection-api
Browse files Browse the repository at this point in the history
Add Schema Reflection API
  • Loading branch information
fabian-hiller authored Nov 19, 2023
2 parents fbb4ee2 + a90ac7d commit db57a67
Show file tree
Hide file tree
Showing 276 changed files with 4,770 additions and 3,681 deletions.
4 changes: 4 additions & 0 deletions library/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

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

## vX.X.X (Month DD, YYYY)

- Change structure of schemas, validations and transformations to make properties accessible (pull request #211)

## v0.20.1 (November 2, 2023)

- Remove `never` from type signatur of strict objects and tuples (issue #234)
Expand Down
2 changes: 1 addition & 1 deletion library/src/error/ValiError/ValiError.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Issues } from '../../types.ts';
import type { Issues } from '../../types/index.ts';

/**
* A Valibot error with useful information.
Expand Down
2 changes: 1 addition & 1 deletion library/src/error/flatten/flatten.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, test } from 'vitest';
import type { Issue, Issues } from '../../types.ts';
import type { Issue, Issues } from '../../types/index.ts';
import { ValiError } from '../ValiError/index.ts';
import { flatten } from './flatten.ts';

Expand Down
2 changes: 1 addition & 1 deletion library/src/error/flatten/flatten.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import type {
BaseSchemaAsync,
Input,
Issues,
} from '../../types.ts';
} from '../../types/index.ts';
import type { ValiError } from '../ValiError/index.ts';

/**
Expand Down
2 changes: 1 addition & 1 deletion library/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ export * from './methods/index.ts';
export * from './regex.ts';
export * from './schemas/index.ts';
export * from './transformations/index.ts';
export * from './types/index.ts';
export * from './utils/index.ts';
export * from './validations/index.ts';
export * from './types.ts';
2 changes: 1 addition & 1 deletion library/src/methods/brand/brand.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, expect, expectTypeOf, test } from 'vitest';
import { object, string } from '../../schemas/index.ts';
import type { Output } from '../../types.ts';
import type { Output } from '../../types/index.ts';
import { parse } from '../parse/index.ts';
import { brand, type Brand } from './brand.ts';

Expand Down
2 changes: 1 addition & 1 deletion library/src/methods/brand/brand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type {
BaseSchemaAsync,
Input,
Output,
} from '../../types.ts';
} from '../../types/index.ts';

/**
* Brand symbol.
Expand Down
11 changes: 1 addition & 10 deletions library/src/methods/coerce/coerce.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { BaseSchema } from '../../types.ts';
import type { BaseSchema } from '../../types/index.ts';

/**
* Coerces the input of a schema to match the required type.
Expand All @@ -14,15 +14,6 @@ export function coerce<TSchema extends BaseSchema>(
): TSchema {
return {
...schema,

/**
* Parses unknown input based on its schema.
*
* @param input The input to be parsed.
* @param info The parse info.
*
* @returns The parsed output.
*/
_parse(input, info) {
return schema._parse(action(input), info);
},
Expand Down
11 changes: 1 addition & 10 deletions library/src/methods/coerce/coerceAsync.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { BaseSchemaAsync } from '../../types.ts';
import type { BaseSchemaAsync } from '../../types/index.ts';

/**
* Coerces the input of a async schema to match the required type.
Expand All @@ -14,15 +14,6 @@ export function coerceAsync<TSchema extends BaseSchemaAsync>(
): TSchema {
return {
...schema,

/**
* Parses unknown input based on its schema.
*
* @param input The input to be parsed.
* @param info The parse info.
*
* @returns The parsed output.
*/
async _parse(input, info) {
return schema._parse(await action(input), info);
},
Expand Down
41 changes: 17 additions & 24 deletions library/src/methods/fallback/fallback.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import type { BaseSchema, Output } from '../../types.ts';
import type { BaseSchema, Output } from '../../types/index.ts';
import { getOutput } from '../../utils/index.ts';
import { getFallback } from '../getFallback/index.ts';
import type { FallbackInfo } from './types.ts';

/**
* Schema with fallback type.
*/
export type SchemaWithFallback<
TSchema extends BaseSchema = BaseSchema,
TFallback extends Output<TSchema> = Output<TSchema>
> = TSchema & { getFallback: (info?: FallbackInfo) => TFallback };
TFallback extends
| Output<TSchema>
| ((info?: FallbackInfo) => Output<TSchema>) = Output<TSchema>
> = TSchema & {
/**
* The fallback value.
*/
fallback: TFallback;
};

/**
* Returns a fallback value when validating the passed schema failed.
Expand All @@ -20,36 +28,21 @@ export type SchemaWithFallback<
*/
export function fallback<
TSchema extends BaseSchema,
TFallback extends Output<TSchema>
const TFallback extends
| Output<TSchema>
| ((info?: FallbackInfo) => Output<TSchema>)
>(
schema: TSchema,
fallback: TFallback | ((info?: FallbackInfo) => TFallback)
fallback: TFallback
): SchemaWithFallback<TSchema, TFallback> {
return {
...schema,

/**
* Returns the fallback value.
*/
getFallback(info) {
return typeof fallback === 'function'
? (fallback as (info?: FallbackInfo) => TFallback)(info)
: (fallback as TFallback);
},

/**
* Parses unknown input based on its schema.
*
* @param input The input to be parsed.
* @param info The parse info.
*
* @returns The parsed output.
*/
fallback,
_parse(input, info) {
const result = schema._parse(input, info);
return getOutput(
result.issues
? this.getFallback({ input, issues: result.issues })
? getFallback(this, { input, issues: result.issues })
: result.output
);
},
Expand Down
47 changes: 19 additions & 28 deletions library/src/methods/fallback/fallbackAsync.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
import type { BaseSchemaAsync, Output } from '../../types.ts';
import type { BaseSchemaAsync, Output } from '../../types/index.ts';
import { getOutput } from '../../utils/index.ts';
import { getFallbackAsync } from '../getFallback/index.ts';
import type { FallbackInfo } from './types.ts';

/**
* Schema with fallback async type.
*/
export type SchemaWithFallbackAsync<
TSchema extends BaseSchemaAsync = BaseSchemaAsync,
TFallback extends Output<TSchema> = Output<TSchema>
> = TSchema & { getFallback: (info?: FallbackInfo) => Promise<TFallback> };
TFallback extends
| Output<TSchema>
| ((
info?: FallbackInfo
) => Output<TSchema> | Promise<Output<TSchema>>) = Output<TSchema>
> = TSchema & {
/**
* The fallback value.
*/
fallback: TFallback;
};

/**
* Returns a fallback value when validating the passed schema failed.
Expand All @@ -20,40 +30,21 @@ export type SchemaWithFallbackAsync<
*/
export function fallbackAsync<
TSchema extends BaseSchemaAsync,
TFallback extends Output<TSchema>
const TFallback extends
| Output<TSchema>
| ((info?: FallbackInfo) => Output<TSchema> | Promise<Output<TSchema>>)
>(
schema: TSchema,
fallback:
| TFallback
| ((info?: FallbackInfo) => TFallback | Promise<TFallback>)
fallback: TFallback
): SchemaWithFallbackAsync<TSchema, TFallback> {
return {
...schema,

/**
* Returns the default value.
*/
async getFallback(info) {
return typeof fallback === 'function'
? await (
fallback as (info?: FallbackInfo) => TFallback | Promise<TFallback>
)(info)
: (fallback as TFallback);
},

/**
* Parses unknown input based on its schema.
*
* @param input The input to be parsed.
* @param info The parse info.
*
* @returns The parsed output.
*/
fallback,
async _parse(input, info) {
const result = await schema._parse(input, info);
return getOutput(
result.issues
? await this.getFallback({ input, issues: result.issues })
? await getFallbackAsync(this, { input, issues: result.issues })
: result.output
);
},
Expand Down
2 changes: 1 addition & 1 deletion library/src/methods/fallback/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Issues } from '../../types.ts';
import type { Issues } from '../../types/index.ts';

/**
* Fallback info type.
Expand Down
13 changes: 10 additions & 3 deletions library/src/methods/getDefault/getDefault.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import type { BaseSchema, Output } from '../../types.ts';
import type { BaseSchema, Output } from '../../types/index.ts';
import type { DefaultValue } from './types.ts';

/**
* Schema with maybe default type.
*/
export type SchemaWithMaybeDefault<TSchema extends BaseSchema = BaseSchema> =
TSchema & { getDefault?: () => Output<TSchema> };
TSchema & {
/**
* The optional default value.
*/
default?: Output<TSchema> | (() => Output<TSchema> | undefined);
};

/**
* Returns the default value of the schema.
Expand All @@ -17,5 +22,7 @@ export type SchemaWithMaybeDefault<TSchema extends BaseSchema = BaseSchema> =
export function getDefault<TSchema extends SchemaWithMaybeDefault>(
schema: TSchema
): DefaultValue<TSchema> {
return schema.getDefault?.();
return typeof schema.default === 'function'
? schema.default()
: schema.default;
}
18 changes: 15 additions & 3 deletions library/src/methods/getDefault/getDefaultAsync.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { BaseSchemaAsync, Output } from '../../types.ts';
import type { BaseSchemaAsync, Output } from '../../types/index.ts';
import type { SchemaWithMaybeDefault } from './getDefault.ts';
import type { DefaultValue } from './types.ts';

Expand All @@ -7,7 +7,17 @@ import type { DefaultValue } from './types.ts';
*/
export type SchemaWithMaybeDefaultAsync<
TSchema extends BaseSchemaAsync = BaseSchemaAsync
> = TSchema & { getDefault?: () => Promise<Output<TSchema>> };
> = TSchema & {
/**
* The optional default value.
*/
default?:
| Output<TSchema>
| (() =>
| Output<TSchema>
| Promise<Output<TSchema> | undefined>
| undefined);
};

/**
* Returns the default value of the schema.
Expand All @@ -19,5 +29,7 @@ export type SchemaWithMaybeDefaultAsync<
export async function getDefaultAsync<
TSchema extends SchemaWithMaybeDefault | SchemaWithMaybeDefaultAsync
>(schema: TSchema): Promise<DefaultValue<TSchema>> {
return schema.getDefault?.();
return typeof schema.default === 'function'
? await schema.default()
: schema.default;
}
12 changes: 7 additions & 5 deletions library/src/methods/getDefault/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Output } from '../../types.ts';
import type { Output } from '../../types/index.ts';
import type { SchemaWithMaybeDefault } from './getDefault.ts';
import type { SchemaWithMaybeDefaultAsync } from './getDefaultAsync.ts';

Expand All @@ -7,8 +7,10 @@ import type { SchemaWithMaybeDefaultAsync } from './getDefaultAsync.ts';
*/
export type DefaultValue<
TSchema extends SchemaWithMaybeDefault | SchemaWithMaybeDefaultAsync
> = TSchema['getDefault'] extends () => Output<TSchema>
? ReturnType<TSchema['getDefault']>
: TSchema['getDefault'] extends () => Promise<Output<TSchema>>
? Awaited<ReturnType<TSchema['getDefault']>>
> = TSchema['default'] extends Output<TSchema> | undefined
? TSchema['default']
: TSchema['default'] extends () => Output<TSchema> | undefined
? ReturnType<TSchema['default']>
: TSchema['default'] extends () => Promise<Output<TSchema> | undefined>
? Awaited<ReturnType<TSchema['default']>>
: undefined;
11 changes: 7 additions & 4 deletions library/src/methods/getDefaults/getDefaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import type {
TupleItems,
TupleSchema,
} from '../../schemas/index.ts';
import type { BaseSchema } from '../../types.ts';
import type { SchemaWithMaybeDefault } from '../getDefault/getDefault.ts';
import type { BaseSchema } from '../../types/index.ts';
import {
getDefault,
type SchemaWithMaybeDefault,
} from '../getDefault/index.ts';
import type { DefaultValues } from './types.ts';

/**
Expand All @@ -28,8 +31,8 @@ export function getDefaults<
let defaults: any;

// If schema contains a default function, set its default value
if (schema.getDefault) {
defaults = schema.getDefault();
if (schema.default) {
defaults = getDefault(schema);

// Otherwise, check if schema is of kind object or tuple
} else if ('type' in schema) {
Expand Down
13 changes: 7 additions & 6 deletions library/src/methods/getDefaults/getDefaultsAsync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import type {
TupleSchema,
TupleSchemaAsync,
} from '../../schemas/index.ts';
import type { BaseSchema, BaseSchemaAsync } from '../../types.ts';
import type {
SchemaWithMaybeDefault,
SchemaWithMaybeDefaultAsync,
import type { BaseSchema, BaseSchemaAsync } from '../../types/index.ts';
import {
getDefaultAsync,
type SchemaWithMaybeDefault,
type SchemaWithMaybeDefaultAsync,
} from '../getDefault/index.ts';
import type { DefaultValues } from './types.ts';

Expand Down Expand Up @@ -43,8 +44,8 @@ export async function getDefaultsAsync<
let defaults: any;

// If schema contains a default function, set its default value
if (schema.getDefault) {
defaults = await schema.getDefault();
if (schema.default) {
defaults = await getDefaultAsync(schema);

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

0 comments on commit db57a67

Please sign in to comment.