diff --git a/library/src/actions/index.ts b/library/src/actions/index.ts index be3f357a0..6a5a1610a 100644 --- a/library/src/actions/index.ts +++ b/library/src/actions/index.ts @@ -89,6 +89,7 @@ export * from './slug/index.ts'; export * from './someItem/index.ts'; export * from './sortItems/index.ts'; export * from './startsWith/index.ts'; +export * from './stringbool/index.ts'; export * from './stringifyJson/index.ts'; export * from './title/index.ts'; export * from './toLowerCase/index.ts'; diff --git a/library/src/actions/stringbool/index.ts b/library/src/actions/stringbool/index.ts new file mode 100644 index 000000000..91aad7459 --- /dev/null +++ b/library/src/actions/stringbool/index.ts @@ -0,0 +1 @@ +export * from './stringbool.ts'; diff --git a/library/src/actions/stringbool/stringbool.test-d.ts b/library/src/actions/stringbool/stringbool.test-d.ts new file mode 100644 index 000000000..97aa8bf9e --- /dev/null +++ b/library/src/actions/stringbool/stringbool.test-d.ts @@ -0,0 +1,49 @@ +import { describe, expectTypeOf, test } from 'vitest'; +import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; +import { + stringbool, + type StringboolAction, + type StringboolIssue, + type StringboolOptions, +} from './stringbool.ts'; + +describe('stringbool', () => { + describe('should return action object', () => { + test('with undefined options', () => { + type Action = StringboolAction<'foo', StringboolOptions>; + + expectTypeOf(stringbool<'foo'>()).toEqualTypeOf(); + expectTypeOf(stringbool<'foo'>(undefined)).toEqualTypeOf(); + }); + + test('with custom options', () => { + const options: StringboolOptions = { + truthy: ['yep'], + falsy: ['nope'], + case: 'sensitive', + }; + + expectTypeOf(stringbool<'foo'>(options)).toEqualTypeOf< + StringboolAction<'foo', StringboolOptions> + >(); + }); + }); + + describe('should infer correct types', () => { + type Action = StringboolAction<'foo', StringboolOptions>; + + test('of input', () => { + expectTypeOf>().toEqualTypeOf<'foo'>(); + }); + + test('of output', () => { + expectTypeOf>().toEqualTypeOf(); + }); + + test('of issue', () => { + expectTypeOf>().toEqualTypeOf< + StringboolIssue<'foo'> + >(); + }); + }); +}); diff --git a/library/src/actions/stringbool/stringbool.test.ts b/library/src/actions/stringbool/stringbool.test.ts new file mode 100644 index 000000000..84a5e7062 --- /dev/null +++ b/library/src/actions/stringbool/stringbool.test.ts @@ -0,0 +1,625 @@ +import { describe, expect, test } from 'vitest'; +import { + stringbool, + type StringboolAction, + type StringboolIssue, + type StringboolOptions, +} from './stringbool.ts'; + +describe('stringbool', () => { + const defaultExpected = + '("true" | "1" | "yes" | "y" | "on" | "enabled" | "false" | "0" | "no" | "n" | "off" | "disabled")'; + + describe('should return action object', () => { + test('for default options', () => { + expect(stringbool()).toStrictEqual({ + kind: 'transformation', + type: 'stringbool', + reference: stringbool, + expects: defaultExpected, + options: { + truthy: ['true', '1', 'yes', 'y', 'on', 'enabled'], + falsy: ['false', '0', 'no', 'n', 'off', 'disabled'], + case: 'insensitive', + }, + async: false, + '~run': expect.any(Function), + } satisfies StringboolAction); + }); + + test('for custom options truthy only', () => { + const options: StringboolOptions = { + truthy: ['yep'], + }; + + expect(stringbool(options)).toStrictEqual({ + kind: 'transformation', + type: 'stringbool', + reference: stringbool, + expects: '("yep" | "false" | "0" | "no" | "n" | "off" | "disabled")', + options: { + truthy: ['yep'], + falsy: ['false', '0', 'no', 'n', 'off', 'disabled'], + case: 'insensitive', + }, + async: false, + '~run': expect.any(Function), + } satisfies StringboolAction); + }); + + test('for custom options case undefined', () => { + const options: StringboolOptions = { + truthy: ['yep'], + falsy: ['nope'], + case: undefined, + }; + + expect(stringbool(options)).toStrictEqual({ + kind: 'transformation', + type: 'stringbool', + reference: stringbool, + expects: '("yep" | "nope")', + options: { + truthy: ['yep'], + falsy: ['nope'], + case: 'insensitive', + }, + async: false, + '~run': expect.any(Function), + } satisfies StringboolAction); + }); + + test('for custom options all together', () => { + const options: StringboolOptions = { + truthy: ['YEP'], + falsy: ['NOPE'], + case: 'sensitive', + }; + + expect(stringbool(options)).toStrictEqual({ + kind: 'transformation', + type: 'stringbool', + reference: stringbool, + expects: '("YEP" | "NOPE")', + options, + async: false, + '~run': expect.any(Function), + } satisfies StringboolAction); + }); + }); + + describe('should handle default options', () => { + const action = stringbool(); + + describe('for truthy values', () => { + test('for "true"', () => { + expect( + action['~run']({ typed: true, value: 'true' }, {}) + ).toStrictEqual({ + typed: true, + value: true, + }); + }); + + test('for "1"', () => { + expect(action['~run']({ typed: true, value: '1' }, {})).toStrictEqual({ + typed: true, + value: true, + }); + }); + + test('for "yes"', () => { + expect(action['~run']({ typed: true, value: 'yes' }, {})).toStrictEqual( + { + typed: true, + value: true, + } + ); + }); + + test('for "y"', () => { + expect(action['~run']({ typed: true, value: 'y' }, {})).toStrictEqual({ + typed: true, + value: true, + }); + }); + + test('for "on"', () => { + expect(action['~run']({ typed: true, value: 'on' }, {})).toStrictEqual({ + typed: true, + value: true, + }); + }); + + test('for "enabled"', () => { + expect( + action['~run']({ typed: true, value: 'enabled' }, {}) + ).toStrictEqual({ + typed: true, + value: true, + }); + }); + + test('for "TRUE"', () => { + expect( + action['~run']({ typed: true, value: 'TRUE' }, {}) + ).toStrictEqual({ + typed: true, + value: true, + }); + }); + }); + + describe('for falsy values', () => { + test('for "false"', () => { + expect( + action['~run']({ typed: true, value: 'false' }, {}) + ).toStrictEqual({ + typed: true, + value: false, + }); + }); + + test('for "0"', () => { + expect(action['~run']({ typed: true, value: '0' }, {})).toStrictEqual({ + typed: true, + value: false, + }); + }); + + test('for "no"', () => { + expect(action['~run']({ typed: true, value: 'no' }, {})).toStrictEqual({ + typed: true, + value: false, + }); + }); + + test('for "n"', () => { + expect(action['~run']({ typed: true, value: 'n' }, {})).toStrictEqual({ + typed: true, + value: false, + }); + }); + + test('for "off"', () => { + expect(action['~run']({ typed: true, value: 'off' }, {})).toStrictEqual( + { + typed: true, + value: false, + } + ); + }); + + test('for "disabled"', () => { + expect( + action['~run']({ typed: true, value: 'disabled' }, {}) + ).toStrictEqual({ + typed: true, + value: false, + }); + }); + + test('for "FALSE"', () => { + expect( + action['~run']({ typed: true, value: 'FALSE' }, {}) + ).toStrictEqual({ + typed: true, + value: false, + }); + }); + }); + }); + + describe('should handle custom options with `truthy` only', () => { + describe('for lowercase `truthy` values', () => { + const action = stringbool({ + truthy: ['yep'], + }); + + test('for "yep"', () => { + expect(action['~run']({ typed: true, value: 'yep' }, {})).toStrictEqual( + { + typed: true, + value: true, + } + ); + }); + + test('for "YEP"', () => { + expect(action['~run']({ typed: true, value: 'YEP' }, {})).toStrictEqual( + { + typed: true, + value: true, + } + ); + }); + + test('for "false"', () => { + expect( + action['~run']({ typed: true, value: 'false' }, {}) + ).toStrictEqual({ + typed: true, + value: false, + }); + }); + }); + + describe('for uppercase `truthy` values', () => { + const action = stringbool({ + truthy: ['YEP'], + }); + + test('for "yep"', () => { + expect(action['~run']({ typed: true, value: 'yep' }, {})).toStrictEqual( + { + typed: true, + value: true, + } + ); + }); + + test('for "YEP"', () => { + expect(action['~run']({ typed: true, value: 'YEP' }, {})).toStrictEqual( + { + typed: true, + value: true, + } + ); + }); + }); + }); + + describe('should handle custom options with `falsy` only', () => { + describe('for lowercase `falsy` values', () => { + const action = stringbool({ + falsy: ['nope'], + }); + + test('for "nope"', () => { + expect( + action['~run']({ typed: true, value: 'nope' }, {}) + ).toStrictEqual({ + typed: true, + value: false, + }); + }); + + test('for "NOPE"', () => { + expect( + action['~run']({ typed: true, value: 'NOPE' }, {}) + ).toStrictEqual({ + typed: true, + value: false, + }); + }); + + test('for "true"', () => { + expect( + action['~run']({ typed: true, value: 'true' }, {}) + ).toStrictEqual({ + typed: true, + value: true, + }); + }); + }); + + describe('for uppercase `falsy` values', () => { + const action = stringbool({ + falsy: ['NOPE'], + }); + + test('for "nope"', () => { + expect( + action['~run']({ typed: true, value: 'nope' }, {}) + ).toStrictEqual({ + typed: true, + value: false, + }); + }); + + test('for "NOPE"', () => { + expect( + action['~run']({ typed: true, value: 'NOPE' }, {}) + ).toStrictEqual({ + typed: true, + value: false, + }); + }); + }); + }); + + describe('should handle custom options with `case` only', () => { + describe('for case sensitive', () => { + const action = stringbool({ + case: 'sensitive', + }); + + test('for "true"', () => { + expect( + action['~run']({ typed: true, value: 'true' }, {}) + ).toStrictEqual({ + typed: true, + value: true, + }); + }); + + test('for "false"', () => { + expect( + action['~run']({ typed: true, value: 'false' }, {}) + ).toStrictEqual({ + typed: true, + value: false, + }); + }); + }); + + describe('for case insensitive', () => { + const action = stringbool({ + case: 'insensitive', + }); + + test('for "true"', () => { + expect( + action['~run']({ typed: true, value: 'true' }, {}) + ).toStrictEqual({ + typed: true, + value: true, + }); + }); + + test('for "TRUE"', () => { + expect( + action['~run']({ typed: true, value: 'TRUE' }, {}) + ).toStrictEqual({ + typed: true, + value: true, + }); + }); + + test('for "false"', () => { + expect( + action['~run']({ typed: true, value: 'false' }, {}) + ).toStrictEqual({ + typed: true, + value: false, + }); + }); + + test('for "FALSE"', () => { + expect( + action['~run']({ typed: true, value: 'FALSE' }, {}) + ).toStrictEqual({ + typed: true, + value: false, + }); + }); + }); + }); + + describe('should handle custom options all together', () => { + const action = stringbool({ + truthy: ['YEP'], + falsy: ['NOPE'], + case: 'sensitive', + }); + + test('for "YEP"', () => { + expect(action['~run']({ typed: true, value: 'YEP' }, {})).toStrictEqual({ + typed: true, + value: true, + }); + }); + + test('for "NOPE"', () => { + expect(action['~run']({ typed: true, value: 'NOPE' }, {})).toStrictEqual({ + typed: true, + value: false, + }); + }); + }); + + describe('should return dataset with issues', () => { + describe('for default options', () => { + const action = stringbool(); + + const baseIssue: Omit< + StringboolIssue, + 'input' | 'received' | 'message' + > = { + kind: 'transformation', + type: 'stringbool', + expected: defaultExpected, + requirement: undefined, + path: undefined, + issues: undefined, + lang: undefined, + abortEarly: undefined, + abortPipeEarly: undefined, + }; + + test('for invalid input as Symbol', () => { + const value = Symbol(); + + expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ + typed: false, + value, + issues: [ + { + ...baseIssue, + input: value, + received: 'symbol', + message: `Invalid stringbool: Expected ${defaultExpected} but received symbol`, + }, + ], + }); + }); + + test('for invalid input as string', () => { + const value = 'something'; + + expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ + typed: false, + value, + issues: [ + { + ...baseIssue, + input: value, + received: '"something"', + message: `Invalid stringbool: Expected ${defaultExpected} but received "something"`, + }, + ], + }); + }); + + test('for invalid input as number', () => { + const value = 123; + + expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ + typed: false, + value, + issues: [ + { + ...baseIssue, + input: value, + received: '123', + message: `Invalid stringbool: Expected ${defaultExpected} but received 123`, + }, + ], + }); + }); + }); + + describe('for custom options truthy only', () => { + const action = stringbool({ + truthy: ['yep'], + }); + + const baseIssue: Omit< + StringboolIssue, + 'input' | 'received' | 'message' + > = { + kind: 'transformation', + type: 'stringbool', + expected: '("yep" | "false" | "0" | "no" | "n" | "off" | "disabled")', + requirement: undefined, + path: undefined, + issues: undefined, + lang: undefined, + abortEarly: undefined, + abortPipeEarly: undefined, + }; + + test('for invalid input as string', () => { + const value = 'enabled'; + + expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ + typed: false, + value, + issues: [ + { + ...baseIssue, + input: value, + received: '"enabled"', + message: `Invalid stringbool: Expected ${baseIssue.expected} but received "enabled"`, + }, + ], + }); + }); + }); + + describe('for custom options falsy only', () => { + const action = stringbool({ + falsy: ['nope'], + }); + + const baseIssue: Omit< + StringboolIssue, + 'input' | 'received' | 'message' + > = { + kind: 'transformation', + type: 'stringbool', + expected: '("true" | "1" | "yes" | "y" | "on" | "enabled" | "nope")', + requirement: undefined, + path: undefined, + issues: undefined, + lang: undefined, + abortEarly: undefined, + abortPipeEarly: undefined, + }; + + test('for invalid input as string', () => { + const value = 'disabled'; + + expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ + typed: false, + value, + issues: [ + { + ...baseIssue, + input: value, + received: '"disabled"', + message: `Invalid stringbool: Expected ${baseIssue.expected} but received "disabled"`, + }, + ], + }); + }); + }); + + describe('for custom options all together', () => { + const action = stringbool({ + truthy: ['YEP'], + falsy: ['NOPE'], + case: 'sensitive', + }); + + const baseIssue: Omit< + StringboolIssue, + 'input' | 'received' | 'message' + > = { + kind: 'transformation', + type: 'stringbool', + expected: '("YEP" | "NOPE")', + requirement: undefined, + path: undefined, + issues: undefined, + lang: undefined, + abortEarly: undefined, + abortPipeEarly: undefined, + }; + + test('for invalid lowercase input as string "yep"', () => { + const value = 'yep'; + + expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ + typed: false, + value, + issues: [ + { + ...baseIssue, + input: value, + received: '"yep"', + message: `Invalid stringbool: Expected ${baseIssue.expected} but received "yep"`, + }, + ], + }); + }); + + test('for invalid lowercase input as string "nope"', () => { + const value = 'nope'; + + expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ + typed: false, + value, + issues: [ + { + ...baseIssue, + input: value, + received: '"nope"', + message: `Invalid stringbool: Expected ${baseIssue.expected} but received "nope"`, + }, + ], + }); + }); + }); + }); +}); diff --git a/library/src/actions/stringbool/stringbool.ts b/library/src/actions/stringbool/stringbool.ts new file mode 100644 index 000000000..104d6fa25 --- /dev/null +++ b/library/src/actions/stringbool/stringbool.ts @@ -0,0 +1,132 @@ +import type { + BaseIssue, + BaseTransformation, + MaybeReadonly, + OutputDataset, +} from '../../types/index.ts'; +import { _addIssue, _joinExpects, _stringify } from '../../utils/index.ts'; + +/** + * String to boolean options. + */ +export interface StringboolOptions { + truthy?: MaybeReadonly; + falsy?: MaybeReadonly; + /** + * Options: `"sensitive"`, `"insensitive"` + * + * @default `"insensitive"` + */ + case?: 'sensitive' | 'insensitive' | undefined; +} + +const defaultOptions: Required = { + truthy: ['true', '1', 'yes', 'y', 'on', 'enabled'], + falsy: ['false', '0', 'no', 'n', 'off', 'disabled'], + case: 'insensitive', +}; + +/** + * String to boolean issue interface. + */ +export interface StringboolIssue extends BaseIssue { + /** + * The issue kind. + */ + readonly kind: 'transformation'; + /** + * The issue type. + */ + readonly type: 'stringbool'; + /** + * The expected property. + */ + readonly expected: string; +} + +/** + * String to boolean action interface. + */ +export interface StringboolAction< + TInput, + TOptions extends StringboolOptions = StringboolOptions, +> extends BaseTransformation> { + /** + * The action type. + */ + readonly type: 'stringbool'; + /** + * The action reference. + */ + readonly reference: typeof stringbool; + /** + * The expected property. + */ + readonly expects: string; + /** + * The stringbool options. + */ + readonly options: TOptions; +} + +/** + * Creates a string to boolean transformation action. + * + * @param options The stringbool options. + * + * @returns A string to boolean action. + */ +// @__NO_SIDE_EFFECTS__ +export function stringbool< + TInput, + TOptions extends StringboolOptions = StringboolOptions, +>(options?: TOptions): StringboolAction { + let truthyValues = options?.truthy ?? defaultOptions.truthy; + let falsyValues = options?.falsy ?? defaultOptions.falsy; + const caseOption = options?.case ?? defaultOptions.case; + + if (caseOption !== 'sensitive') { + truthyValues = truthyValues.map((value) => value.toLowerCase()); + falsyValues = falsyValues.map((value) => value.toLowerCase()); + } + + const truthySet = new Set(truthyValues); + const falsySet = new Set(falsyValues); + const validValues = [...truthyValues, ...falsyValues]; + + const resolvedOptions = { + truthy: truthyValues, + falsy: falsyValues, + case: caseOption, + } as TOptions; + + return { + kind: 'transformation', + type: 'stringbool', + reference: stringbool, + expects: _joinExpects(validValues.map(_stringify), '|'), + options: resolvedOptions, + async: false, + '~run'(dataset, config) { + const inputAsString = String(dataset.value); + const inputValue = + resolvedOptions.case === 'insensitive' + ? inputAsString.toLowerCase() + : inputAsString; + + if (truthySet.has(inputValue)) { + // @ts-expect-error + dataset.value = true; + } else if (falsySet.has(inputValue)) { + // @ts-expect-error + dataset.value = false; + } else { + _addIssue(this, 'stringbool', dataset, config); + // @ts-expect-error + dataset.typed = false; + } + + return dataset as OutputDataset>; + }, + }; +} diff --git a/website/src/routes/api/(actions)/stringbool/index.mdx b/website/src/routes/api/(actions)/stringbool/index.mdx new file mode 100644 index 000000000..1022dc5e9 --- /dev/null +++ b/website/src/routes/api/(actions)/stringbool/index.mdx @@ -0,0 +1,76 @@ +--- +title: stringbool +description: Creates a string to boolean transformation action. +source: /actions/stringbool/stringbool.ts +contributors: + - alexilyaev +--- + +import { ApiList, Property } from '~/components'; +import { properties } from './properties'; + +# stringbool + +Creates a string to boolean transformation action. + +```ts +const Action = v.stringbool(options); +``` + +## Generics + +- `TInput` +- `TOptions` + +## Parameters + +- `options` + +### Explanation + +With `stringbool` you can parse certain "boolish" string values into a plain boolean value (e.g. parsing environment variables). + +## Returns + +- `Action` + +## Examples + +The following examples show how `stringbool` can be used. + +```ts +const EnvSchema = v.object({ + // Default behavior + PROD_MODE: v.pipe(v.string(), v.stringbool()), + + // Custom options + LOG_ENABLED: v.pipe( + v.string(), + v.stringbool({ + // These are the defaults + truthy: ['true', '1', 'yes', 'y', 'on', 'enabled'], + falsy: ['false', '0', 'no', 'n', 'off', 'disabled'], + case: 'insensitive', + }) + ), + + // Optional with default value + VERBOSE: v.optional(v.pipe(v.string(), v.stringbool()), 'false'), +}); +``` + +## Related + +The following APIs can be combined with `stringbool`. + +### Schemas + + + +### Methods + + + +### Utils + + diff --git a/website/src/routes/api/(actions)/stringbool/properties.ts b/website/src/routes/api/(actions)/stringbool/properties.ts new file mode 100644 index 000000000..10db86faf --- /dev/null +++ b/website/src/routes/api/(actions)/stringbool/properties.ts @@ -0,0 +1,44 @@ +import type { PropertyProps } from '~/components'; + +export const properties: Record = { + TInput: { + modifier: 'extends', + type: 'string', + }, + TOptions: { + modifier: 'extends', + type: { + type: 'custom', + name: 'StringboolOptions', + href: '../StringboolOptions/', + }, + default: { + type: 'custom', + name: 'StringboolOptions', + href: '../StringboolOptions/', + }, + }, + options: { + type: { + type: 'custom', + name: 'TOptions', + }, + }, + Action: { + type: { + type: 'custom', + name: 'StringboolAction', + href: '../StringboolAction/', + generics: [ + { + type: 'custom', + name: 'TInput', + }, + { + type: 'custom', + name: 'TOptions', + }, + ], + }, + }, +}; diff --git a/website/src/routes/api/(types)/StringboolAction/index.mdx b/website/src/routes/api/(types)/StringboolAction/index.mdx new file mode 100644 index 000000000..d7d0e8fe7 --- /dev/null +++ b/website/src/routes/api/(types)/StringboolAction/index.mdx @@ -0,0 +1,26 @@ +--- +title: StringboolAction +description: String to boolean action interface. +contributors: + - alexilyaev +--- + +import { Property } from '~/components'; +import { properties } from './properties'; + +# StringboolAction + +String to boolean action interface. + +## Generics + +- `TInput` +- `TOptions` + +## Definition + +- `StringboolAction` + - `type` + - `reference` + - `expects` + - `options` diff --git a/website/src/routes/api/(types)/StringboolAction/properties.ts b/website/src/routes/api/(types)/StringboolAction/properties.ts new file mode 100644 index 000000000..5b8b4a18d --- /dev/null +++ b/website/src/routes/api/(types)/StringboolAction/properties.ts @@ -0,0 +1,64 @@ +import type { PropertyProps } from '~/components'; + +export const properties: Record = { + TInput: { + modifier: 'extends', + type: 'string', + }, + TOptions: { + modifier: 'extends', + type: { + type: 'custom', + name: 'StringboolOptions', + href: '../StringboolOptions/', + }, + default: { + type: 'custom', + name: 'StringboolOptions', + href: '../StringboolOptions/', + }, + }, + BaseTransformation: { + modifier: 'extends', + type: { + type: 'custom', + name: 'BaseTransformation', + href: '../BaseTransformation/', + generics: [ + { + type: 'custom', + name: 'TInput', + }, + 'boolean', + { + type: 'custom', + name: 'StringboolIssue', + href: '../StringboolIssue/', + }, + ], + }, + }, + type: { + type: { + type: 'string', + value: 'stringbool', + }, + }, + reference: { + type: { + type: 'custom', + modifier: 'typeof', + name: 'stringbool', + href: '../stringbool/', + }, + }, + expects: { + type: 'string', + }, + options: { + type: { + type: 'custom', + name: 'TOptions', + }, + }, +}; diff --git a/website/src/routes/api/(types)/StringboolIssue/index.mdx b/website/src/routes/api/(types)/StringboolIssue/index.mdx new file mode 100644 index 000000000..4f0f800a9 --- /dev/null +++ b/website/src/routes/api/(types)/StringboolIssue/index.mdx @@ -0,0 +1,24 @@ +--- +title: StringboolIssue +description: String to boolean issue interface. +contributors: + - alexilyaev +--- + +import { Property } from '~/components'; +import { properties } from './properties'; + +# StringboolIssue + +String to boolean issue interface. + +## Generics + +- `TInput` + +## Definition + +- `StringboolIssue` + - `kind` + - `type` + - `expected` diff --git a/website/src/routes/api/(types)/StringboolIssue/properties.ts b/website/src/routes/api/(types)/StringboolIssue/properties.ts new file mode 100644 index 000000000..5e5e1ecd4 --- /dev/null +++ b/website/src/routes/api/(types)/StringboolIssue/properties.ts @@ -0,0 +1,37 @@ +import type { PropertyProps } from '~/components'; + +export const properties: Record = { + TInput: { + modifier: 'extends', + type: 'string', + }, + BaseIssue: { + modifier: 'extends', + type: { + type: 'custom', + name: 'BaseIssue', + href: '../BaseIssue/', + generics: [ + { + type: 'custom', + name: 'TInput', + }, + ], + }, + }, + kind: { + type: { + type: 'string', + value: 'transformation', + }, + }, + type: { + type: { + type: 'string', + value: 'stringbool', + }, + }, + expected: { + type: 'string', + }, +}; diff --git a/website/src/routes/api/(types)/StringboolOptions/index.mdx b/website/src/routes/api/(types)/StringboolOptions/index.mdx new file mode 100644 index 000000000..dc6a49e69 --- /dev/null +++ b/website/src/routes/api/(types)/StringboolOptions/index.mdx @@ -0,0 +1,20 @@ +--- +title: StringboolOptions +description: String to boolean options interface. +contributors: + - alexilyaev +--- + +import { Property } from '~/components'; +import { properties } from './properties'; + +# StringboolOptions + +String to boolean options interface. + +## Definition + +- `StringboolOptions` + - `truthy` + - `falsy` + - `case` diff --git a/website/src/routes/api/(types)/StringboolOptions/properties.ts b/website/src/routes/api/(types)/StringboolOptions/properties.ts new file mode 100644 index 000000000..d04a3c52a --- /dev/null +++ b/website/src/routes/api/(types)/StringboolOptions/properties.ts @@ -0,0 +1,50 @@ +import type { PropertyProps } from '~/components'; + +export const properties: Record = { + truthy: { + type: { + type: 'custom', + name: 'MaybeReadonly', + href: '../MaybeReadonly/', + generics: [ + { + type: 'array', + item: 'string', + }, + ], + }, + }, + falsy: { + type: { + type: 'custom', + name: 'MaybeReadonly', + href: '../MaybeReadonly/', + generics: [ + { + type: 'array', + item: 'string', + }, + ], + }, + }, + case: { + type: { + type: 'union', + options: [ + { + type: 'string', + value: 'sensitive', + }, + { + type: 'string', + value: 'insensitive', + }, + 'undefined', + ], + }, + default: { + type: 'string', + value: 'insensitive', + }, + }, +}; diff --git a/website/src/routes/api/menu.md b/website/src/routes/api/menu.md index 7bc8ef831..569b20b69 100644 --- a/website/src/routes/api/menu.md +++ b/website/src/routes/api/menu.md @@ -170,6 +170,7 @@ - [someItem](/api/someItem/) - [sortItems](/api/sortItems/) - [startsWith](/api/startsWith/) +- [stringbool](/api/stringbool/) - [stringifyJson](/api/stringifyJson/) - [title](/api/title/) - [toLowerCase](/api/toLowerCase/) @@ -656,6 +657,8 @@ - [StrictTupleSchemaAsync](/api/StrictTupleSchemaAsync/) - [StringIssue](/api/StringIssue/) - [StringSchema](/api/StringSchema/) +- [StringboolAction](/api/StringboolAction/) +- [StringboolIssue](/api/StringboolIssue/) - [StringifyJsonAction](/api/StringifyJsonAction/) - [StringifyJsonConfig](/api/StringifyJsonConfig/) - [StringifyJsonIssue](/api/StringifyJsonIssue/)