feat: Reinitialize frontend with SvelteKit and TypeScript

- Delete old Vite+Svelte frontend
- Initialize new SvelteKit project with TypeScript
- Configure Tailwind CSS v4 + DaisyUI
- Implement JWT authentication with auto-refresh
- Create login page with form validation (Zod)
- Add protected route guards
- Update Docker configuration for single-stage build
- Add E2E tests with Playwright (6/11 passing)
- Fix Svelte 5 reactivity with $state() runes

Known issues:
- 5 E2E tests failing (timing/async issues)
- Token refresh implementation needs debugging
- Validation error display timing
This commit is contained in:
2026-02-17 16:19:59 -05:00
parent 54df6018f5
commit de2d83092e
28274 changed files with 3816354 additions and 90 deletions

View File

@@ -0,0 +1,545 @@
//#region rolldown:runtime
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) {
__defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
}
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
//#endregion
let valibot = require("valibot");
valibot = __toESM(valibot);
//#region src/utils/addError.ts
/**
* Adds an error message to the errors array.
*
* @param errors The array of error messages.
* @param message The error message to add.
*
* @returns The new errors.
*/
function addError(errors, message) {
if (errors) {
errors.push(message);
return errors;
}
return [message];
}
//#endregion
//#region src/utils/handleError.ts
/**
* Throws an error or logs a warning based on the configuration.
*
* @param message The message to throw or log.
* @param config The conversion configuration.
*/
function handleError(message, config) {
switch (config?.errorMode) {
case "ignore": break;
case "warn":
console.warn(message);
break;
default: throw new Error(message);
}
}
//#endregion
//#region src/converters/convertAction/convertAction.ts
/**
* Converts any supported Valibot action to the JSON Schema format.
*
* @param jsonSchema The JSON Schema object.
* @param valibotAction The Valibot action object.
* @param config The conversion configuration.
*
* @returns The converted JSON Schema.
*/
function convertAction(jsonSchema, valibotAction, config) {
if (config?.ignoreActions?.includes(valibotAction.type)) return jsonSchema;
let errors;
switch (valibotAction.type) {
case "base64":
jsonSchema.contentEncoding = "base64";
break;
case "bic":
case "cuid2":
case "decimal":
case "digits":
case "emoji":
case "hexadecimal":
case "hex_color":
case "nanoid":
case "octal":
case "ulid":
jsonSchema.pattern = valibotAction.requirement.source;
break;
case "description":
jsonSchema.description = valibotAction.description;
break;
case "email":
jsonSchema.format = "email";
break;
case "empty":
if (jsonSchema.type === "array") jsonSchema.maxItems = 0;
else {
if (jsonSchema.type !== "string") errors = addError(errors, `The "${valibotAction.type}" action is not supported on type "${jsonSchema.type}".`);
jsonSchema.maxLength = 0;
}
break;
case "entries":
jsonSchema.minProperties = valibotAction.requirement;
jsonSchema.maxProperties = valibotAction.requirement;
break;
case "examples":
if (Array.isArray(jsonSchema.examples)) jsonSchema.examples = [...jsonSchema.examples, ...valibotAction.examples];
else jsonSchema.examples = valibotAction.examples;
break;
case "integer":
jsonSchema.type = "integer";
break;
case "ipv4":
jsonSchema.format = "ipv4";
break;
case "ipv6":
jsonSchema.format = "ipv6";
break;
case "iso_date":
jsonSchema.format = "date";
break;
case "iso_date_time":
case "iso_timestamp":
jsonSchema.format = "date-time";
break;
case "iso_time":
jsonSchema.format = "time";
break;
case "length":
if (jsonSchema.type === "array") {
jsonSchema.minItems = valibotAction.requirement;
jsonSchema.maxItems = valibotAction.requirement;
} else {
if (jsonSchema.type !== "string") errors = addError(errors, `The "${valibotAction.type}" action is not supported on type "${jsonSchema.type}".`);
jsonSchema.minLength = valibotAction.requirement;
jsonSchema.maxLength = valibotAction.requirement;
}
break;
case "max_entries":
jsonSchema.maxProperties = valibotAction.requirement;
break;
case "max_length":
if (jsonSchema.type === "array") jsonSchema.maxItems = valibotAction.requirement;
else {
if (jsonSchema.type !== "string") errors = addError(errors, `The "${valibotAction.type}" action is not supported on type "${jsonSchema.type}".`);
jsonSchema.maxLength = valibotAction.requirement;
}
break;
case "max_value":
if (jsonSchema.type !== "number" && jsonSchema.type !== "integer") errors = addError(errors, `The "max_value" action is not supported on type "${jsonSchema.type}".`);
jsonSchema.maximum = valibotAction.requirement;
break;
case "metadata":
if (typeof valibotAction.metadata.title === "string") jsonSchema.title = valibotAction.metadata.title;
if (typeof valibotAction.metadata.description === "string") jsonSchema.description = valibotAction.metadata.description;
if (Array.isArray(valibotAction.metadata.examples)) if (Array.isArray(jsonSchema.examples)) jsonSchema.examples = [...jsonSchema.examples, ...valibotAction.metadata.examples];
else jsonSchema.examples = valibotAction.metadata.examples;
break;
case "min_entries":
jsonSchema.minProperties = valibotAction.requirement;
break;
case "min_length":
if (jsonSchema.type === "array") jsonSchema.minItems = valibotAction.requirement;
else {
if (jsonSchema.type !== "string") errors = addError(errors, `The "${valibotAction.type}" action is not supported on type "${jsonSchema.type}".`);
jsonSchema.minLength = valibotAction.requirement;
}
break;
case "min_value":
if (jsonSchema.type !== "number" && jsonSchema.type !== "integer") errors = addError(errors, `The "min_value" action is not supported on type "${jsonSchema.type}".`);
jsonSchema.minimum = valibotAction.requirement;
break;
case "multiple_of":
jsonSchema.multipleOf = valibotAction.requirement;
break;
case "non_empty":
if (jsonSchema.type === "array") jsonSchema.minItems = 1;
else {
if (jsonSchema.type !== "string") errors = addError(errors, `The "${valibotAction.type}" action is not supported on type "${jsonSchema.type}".`);
jsonSchema.minLength = 1;
}
break;
case "regex":
if (valibotAction.requirement.flags) errors = addError(errors, "RegExp flags are not supported by JSON Schema.");
jsonSchema.pattern = valibotAction.requirement.source;
break;
case "title":
jsonSchema.title = valibotAction.title;
break;
case "url":
jsonSchema.format = "uri";
break;
case "uuid":
jsonSchema.format = "uuid";
break;
case "value":
jsonSchema.const = valibotAction.requirement;
break;
default: errors = addError(errors, `The "${valibotAction.type}" action cannot be converted to JSON Schema.`);
}
if (config?.overrideAction) {
const actionOverride = config.overrideAction({
valibotAction,
jsonSchema,
errors
});
if (actionOverride) return { ...actionOverride };
}
if (errors) for (const message of errors) handleError(message, config);
return jsonSchema;
}
//#endregion
//#region src/converters/convertSchema/convertSchema.ts
/**
* Flattens a Valibot pipe by recursively expanding nested pipes.
*
* @param pipe The pipeline to flatten.
*
* @returns A flat pipeline.
*/
function flattenPipe(pipe) {
return pipe.flatMap((item) => "pipe" in item ? flattenPipe(item.pipe) : item);
}
let refCount = 0;
/**
* Converts any supported Valibot schema to the JSON Schema format.
*
* @param jsonSchema The JSON Schema object.
* @param valibotSchema The Valibot schema object.
* @param config The conversion configuration.
* @param context The conversion context.
* @param skipRef Whether to skip using a reference.
*
* @returns The converted JSON Schema.
*/
function convertSchema(jsonSchema, valibotSchema, config, context, skipRef = false) {
if (!skipRef) {
const referenceId = context.referenceMap.get(valibotSchema);
if (referenceId) {
jsonSchema.$ref = `#/$defs/${referenceId}`;
if (config?.overrideRef) {
const refOverride = config.overrideRef({
...context,
referenceId,
valibotSchema,
jsonSchema
});
if (refOverride) jsonSchema.$ref = refOverride;
}
return jsonSchema;
}
}
if ("pipe" in valibotSchema) {
const flatPipe = flattenPipe(valibotSchema.pipe);
let startIndex = 0;
let stopIndex = flatPipe.length - 1;
if (config?.typeMode === "input") {
const inputStopIndex = flatPipe.slice(1).findIndex((item) => item.kind === "schema" || item.kind === "transformation" && (item.type === "find_item" || item.type === "parse_json" || item.type === "raw_transform" || item.type === "reduce_items" || item.type === "stringify_json" || item.type === "to_bigint" || item.type === "to_boolean" || item.type === "to_date" || item.type === "to_number" || item.type === "to_string" || item.type === "transform"));
if (inputStopIndex !== -1) stopIndex = inputStopIndex;
} else if (config?.typeMode === "output") {
const outputStartIndex = flatPipe.findLastIndex((item) => item.kind === "schema");
if (outputStartIndex !== -1) startIndex = outputStartIndex;
}
for (let index = startIndex; index <= stopIndex; index++) {
const valibotPipeItem = flatPipe[index];
if (valibotPipeItem.kind === "schema") {
if (index > startIndex) handleError("Set the \"typeMode\" config to \"input\" or \"output\" to convert pipelines with multiple schemas.", config);
jsonSchema = convertSchema(jsonSchema, valibotPipeItem, config, context, true);
} else jsonSchema = convertAction(jsonSchema, valibotPipeItem, config);
}
return jsonSchema;
}
let errors;
switch (valibotSchema.type) {
case "boolean":
jsonSchema.type = "boolean";
break;
case "null":
if (config?.target === "openapi-3.0") jsonSchema.enum = [null];
else jsonSchema.type = "null";
break;
case "number":
jsonSchema.type = "number";
break;
case "string":
jsonSchema.type = "string";
break;
case "array":
jsonSchema.type = "array";
jsonSchema.items = convertSchema({}, valibotSchema.item, config, context);
break;
case "tuple":
case "tuple_with_rest":
case "loose_tuple":
case "strict_tuple":
jsonSchema.type = "array";
if (config?.target === "openapi-3.0") {
jsonSchema.items = { anyOf: [] };
jsonSchema.minItems = valibotSchema.items.length;
for (const item of valibotSchema.items) jsonSchema.items.anyOf.push(convertSchema({}, item, config, context));
if (valibotSchema.type === "tuple_with_rest") jsonSchema.items.anyOf.push(convertSchema({}, valibotSchema.rest, config, context));
else if (valibotSchema.type === "strict_tuple" || valibotSchema.type === "tuple") jsonSchema.maxItems = valibotSchema.items.length;
} else if (config?.target === "draft-2020-12") {
jsonSchema.prefixItems = [];
jsonSchema.minItems = valibotSchema.items.length;
for (const item of valibotSchema.items) jsonSchema.prefixItems.push(convertSchema({}, item, config, context));
if (valibotSchema.type === "tuple_with_rest") jsonSchema.items = convertSchema({}, valibotSchema.rest, config, context);
else if (valibotSchema.type === "strict_tuple") jsonSchema.items = false;
} else {
jsonSchema.items = [];
jsonSchema.minItems = valibotSchema.items.length;
for (const item of valibotSchema.items) jsonSchema.items.push(convertSchema({}, item, config, context));
if (valibotSchema.type === "tuple_with_rest") jsonSchema.additionalItems = convertSchema({}, valibotSchema.rest, config, context);
else if (valibotSchema.type === "strict_tuple") jsonSchema.additionalItems = false;
}
break;
case "object":
case "object_with_rest":
case "loose_object":
case "strict_object":
jsonSchema.type = "object";
jsonSchema.properties = {};
jsonSchema.required = [];
for (const key in valibotSchema.entries) {
const entry = valibotSchema.entries[key];
jsonSchema.properties[key] = convertSchema({}, entry, config, context);
if (entry.type !== "exact_optional" && entry.type !== "nullish" && entry.type !== "optional") jsonSchema.required.push(key);
}
if (valibotSchema.type === "object_with_rest") jsonSchema.additionalProperties = convertSchema({}, valibotSchema.rest, config, context);
else if (valibotSchema.type === "strict_object") jsonSchema.additionalProperties = false;
break;
case "record":
if (config?.target === "openapi-3.0" && "pipe" in valibotSchema.key) errors = addError(errors, "The \"record\" schema with a schema for the key that contains a \"pipe\" cannot be converted to JSON Schema.");
if (valibotSchema.key.type !== "string") errors = addError(errors, `The "record" schema with the "${valibotSchema.key.type}" schema for the key cannot be converted to JSON Schema.`);
jsonSchema.type = "object";
if (config?.target !== "openapi-3.0") jsonSchema.propertyNames = convertSchema({}, valibotSchema.key, config, context);
jsonSchema.additionalProperties = convertSchema({}, valibotSchema.value, config, context);
break;
case "any":
case "unknown": break;
case "nullable":
case "nullish":
if (config?.target === "openapi-3.0") {
const innerSchema = convertSchema({}, valibotSchema.wrapped, config, context);
Object.assign(jsonSchema, innerSchema);
jsonSchema.nullable = true;
} else jsonSchema.anyOf = [convertSchema({}, valibotSchema.wrapped, config, context), { type: "null" }];
if (valibotSchema.default !== void 0) jsonSchema.default = valibot.getDefault(valibotSchema);
break;
case "exact_optional":
case "optional":
case "undefinedable":
jsonSchema = convertSchema(jsonSchema, valibotSchema.wrapped, config, context);
if (valibotSchema.default !== void 0) jsonSchema.default = valibot.getDefault(valibotSchema);
break;
case "literal":
if (typeof valibotSchema.literal !== "boolean" && typeof valibotSchema.literal !== "number" && typeof valibotSchema.literal !== "string") errors = addError(errors, "The value of the \"literal\" schema is not JSON compatible.");
if (config?.target === "openapi-3.0") jsonSchema.enum = [valibotSchema.literal];
else jsonSchema.const = valibotSchema.literal;
break;
case "enum":
jsonSchema.enum = valibotSchema.options;
break;
case "picklist":
if (valibotSchema.options.some((option) => typeof option !== "number" && typeof option !== "string")) errors = addError(errors, "An option of the \"picklist\" schema is not JSON compatible.");
jsonSchema.enum = valibotSchema.options;
break;
case "union":
jsonSchema.anyOf = valibotSchema.options.map((option) => convertSchema({}, option, config, context));
break;
case "variant":
jsonSchema.oneOf = valibotSchema.options.map((option) => convertSchema({}, option, config, context));
break;
case "intersect":
jsonSchema.allOf = valibotSchema.options.map((option) => convertSchema({}, option, config, context));
break;
case "lazy": {
let wrappedValibotSchema = context.getterMap.get(valibotSchema.getter);
if (!wrappedValibotSchema) {
wrappedValibotSchema = valibotSchema.getter(void 0);
context.getterMap.set(valibotSchema.getter, wrappedValibotSchema);
}
let referenceId = context.referenceMap.get(wrappedValibotSchema);
if (!referenceId) {
referenceId = `${refCount++}`;
context.referenceMap.set(wrappedValibotSchema, referenceId);
context.definitions[referenceId] = convertSchema({}, wrappedValibotSchema, config, context, true);
}
jsonSchema.$ref = `#/$defs/${referenceId}`;
if (config?.overrideRef) {
const refOverride = config.overrideRef({
...context,
referenceId,
valibotSchema: wrappedValibotSchema,
jsonSchema
});
if (refOverride) jsonSchema.$ref = refOverride;
}
break;
}
default: errors = addError(errors, `The "${valibotSchema.type}" schema cannot be converted to JSON Schema.`);
}
if (config?.overrideSchema) {
const schemaOverride = config.overrideSchema({
...context,
referenceId: context.referenceMap.get(valibotSchema),
valibotSchema,
jsonSchema,
errors
});
if (schemaOverride) return { ...schemaOverride };
}
if (errors) for (const message of errors) handleError(message, config);
return jsonSchema;
}
//#endregion
//#region src/storages/globalDefs/globalDefs.ts
let store;
/**
* Adds new definitions to the global schema definitions.
*
* @param definitions The schema definitions.
*
* @beta
*/
function addGlobalDefs(definitions) {
store = {
...store ?? {},
...definitions
};
}
/**
* Returns the current global schema definitions.
*
* @returns The schema definitions.
*
* @beta
*/
function getGlobalDefs() {
return store;
}
//#endregion
//#region src/functions/toJsonSchema/toJsonSchema.ts
/**
* Converts a Valibot schema to the JSON Schema format.
*
* @param schema The Valibot schema object.
* @param config The JSON Schema configuration.
*
* @returns The converted JSON Schema.
*/
function toJsonSchema(schema, config) {
const context = {
definitions: {},
referenceMap: /* @__PURE__ */ new Map(),
getterMap: /* @__PURE__ */ new Map()
};
const definitions = config?.definitions ?? getGlobalDefs();
if (definitions) {
for (const key in definitions) context.referenceMap.set(definitions[key], key);
for (const key in definitions) context.definitions[key] = convertSchema({}, definitions[key], config, context, true);
}
const jsonSchema = convertSchema({}, schema, config, context);
const target = config?.target ?? "draft-07";
if (target === "draft-2020-12") jsonSchema.$schema = "https://json-schema.org/draft/2020-12/schema";
else if (target === "draft-07") jsonSchema.$schema = "http://json-schema.org/draft-07/schema#";
if (context.referenceMap.size) jsonSchema.$defs = context.definitions;
return jsonSchema;
}
//#endregion
//#region src/functions/toJsonSchemaDefs/toJsonSchemaDefs.ts
/**
* Converts Valibot schema definitions to JSON Schema definitions.
*
* @param definitions The Valibot schema definitions.
* @param config The JSON Schema configuration.
*
* @returns The converted JSON Schema definitions.
*/
function toJsonSchemaDefs(definitions, config) {
const context = {
definitions: {},
referenceMap: /* @__PURE__ */ new Map(),
getterMap: /* @__PURE__ */ new Map()
};
for (const key in definitions) context.referenceMap.set(definitions[key], key);
for (const key in definitions) context.definitions[key] = convertSchema({}, definitions[key], config, context, true);
return context.definitions;
}
//#endregion
//#region src/functions/toStandardJsonSchema/toStandardJsonSchema.ts
const SUPPORTED_TARGETS = [
"draft-07",
"draft-2020-12",
"openapi-3.0"
];
/**
* Converts a Valibot schema to the Standard JSON Schema format.
*
* @param schema The Valibot schema object.
*
* @returns The Standard JSON Schema.
*/
function toStandardJsonSchema(schema) {
return { "~standard": {
...schema["~standard"],
jsonSchema: {
input(options) {
if (SUPPORTED_TARGETS.includes(options.target)) return toJsonSchema(schema, {
typeMode: "input",
target: options.target,
...options.libraryOptions
});
throw new Error(`Unsupported target: ${options.target}`);
},
output(options) {
if (SUPPORTED_TARGETS.includes(options.target)) return toJsonSchema(schema, {
typeMode: "output",
target: options.target,
...options.libraryOptions
});
throw new Error(`Unsupported target: ${options.target}`);
}
}
} };
}
//#endregion
exports.addGlobalDefs = addGlobalDefs;
exports.getGlobalDefs = getGlobalDefs;
exports.toJsonSchema = toJsonSchema;
exports.toJsonSchemaDefs = toJsonSchemaDefs;
exports.toStandardJsonSchema = toStandardJsonSchema;

View File

@@ -0,0 +1,955 @@
//#region ../../library/src/types/metadata.d.ts
/**
* Base metadata interface.
*/
interface BaseMetadata<TInput$1> {
/**
* The object kind.
*/
readonly kind: "metadata";
/**
* The metadata type.
*/
readonly type: string;
/**
* The metadata reference.
*/
readonly reference: (...args: any[]) => BaseMetadata<any>;
/**
* The input, output and issue type.
*
* @internal
*/
readonly "~types"?: {
readonly input: TInput$1;
readonly output: TInput$1;
readonly issue: never;
} | undefined;
}
//#endregion
//#region ../../library/src/types/dataset.d.ts
/**
* Unknown dataset interface.
*/
interface UnknownDataset {
/**
* Whether is's typed.
*/
typed?: false;
/**
* The dataset value.
*/
value: unknown;
/**
* The dataset issues.
*/
issues?: undefined;
}
/**
* Success dataset interface.
*/
interface SuccessDataset<TValue$1> {
/**
* Whether is's typed.
*/
typed: true;
/**
* The dataset value.
*/
value: TValue$1;
/**
* The dataset issues.
*/
issues?: undefined;
}
/**
* Partial dataset interface.
*/
interface PartialDataset<TValue$1, TIssue extends BaseIssue<unknown>> {
/**
* Whether is's typed.
*/
typed: true;
/**
* The dataset value.
*/
value: TValue$1;
/**
* The dataset issues.
*/
issues: [TIssue, ...TIssue[]];
}
/**
* Failure dataset interface.
*/
interface FailureDataset<TIssue extends BaseIssue<unknown>> {
/**
* Whether is's typed.
*/
typed: false;
/**
* The dataset value.
*/
value: unknown;
/**
* The dataset issues.
*/
issues: [TIssue, ...TIssue[]];
}
/**
* Output dataset type.
*/
type OutputDataset<TValue$1, TIssue extends BaseIssue<unknown>> = SuccessDataset<TValue$1> | PartialDataset<TValue$1, TIssue> | FailureDataset<TIssue>;
//#endregion
//#region ../../library/src/types/standard.d.ts
/**
* The Standard Schema properties interface.
*/
interface StandardProps<TInput$1, TOutput> {
/**
* The version number of the standard.
*/
readonly version: 1;
/**
* The vendor name of the schema library.
*/
readonly vendor: "valibot";
/**
* Validates unknown input values.
*/
readonly validate: (value: unknown) => StandardResult<TOutput> | Promise<StandardResult<TOutput>>;
/**
* Inferred types associated with the schema.
*/
readonly types?: StandardTypes<TInput$1, TOutput> | undefined;
}
/**
* The result interface of the validate function.
*/
type StandardResult<TOutput> = StandardSuccessResult<TOutput> | StandardFailureResult;
/**
* The result interface if validation succeeds.
*/
interface StandardSuccessResult<TOutput> {
/**
* The typed output value.
*/
readonly value: TOutput;
/**
* The non-existent issues.
*/
readonly issues?: undefined;
}
/**
* The result interface if validation fails.
*/
interface StandardFailureResult {
/**
* The issues of failed validation.
*/
readonly issues: readonly StandardIssue[];
}
/**
* The issue interface of the failure output.
*/
interface StandardIssue {
/**
* The error message of the issue.
*/
readonly message: string;
/**
* The path of the issue, if any.
*/
readonly path?: readonly (PropertyKey | StandardPathItem)[] | undefined;
}
/**
* The path item interface of the issue.
*/
interface StandardPathItem {
/**
* The key of the path item.
*/
readonly key: PropertyKey;
}
/**
* The Standard Schema types interface.
*/
interface StandardTypes<TInput$1, TOutput> {
/**
* The input type of the schema.
*/
readonly input: TInput$1;
/**
* The output type of the schema.
*/
readonly output: TOutput;
}
//#endregion
//#region ../../library/src/types/schema.d.ts
/**
* Base schema interface.
*/
interface BaseSchema<TInput$1, TOutput, TIssue extends BaseIssue<unknown>> {
/**
* The object kind.
*/
readonly kind: "schema";
/**
* The schema type.
*/
readonly type: string;
/**
* The schema reference.
*/
readonly reference: (...args: any[]) => BaseSchema<unknown, unknown, BaseIssue<unknown>>;
/**
* The expected property.
*/
readonly expects: string;
/**
* Whether it's async.
*/
readonly async: false;
/**
* The Standard Schema properties.
*
* @internal
*/
readonly "~standard": StandardProps<TInput$1, TOutput>;
/**
* Parses unknown input values.
*
* @param dataset The input dataset.
* @param config The configuration.
*
* @returns The output dataset.
*
* @internal
*/
readonly "~run": (dataset: UnknownDataset, config: Config<BaseIssue<unknown>>) => OutputDataset<TOutput, TIssue>;
/**
* The input, output and issue type.
*
* @internal
*/
readonly "~types"?: {
readonly input: TInput$1;
readonly output: TOutput;
readonly issue: TIssue;
} | undefined;
}
/**
* Base schema async interface.
*/
interface BaseSchemaAsync<TInput$1, TOutput, TIssue extends BaseIssue<unknown>> extends Omit<BaseSchema<TInput$1, TOutput, TIssue>, "reference" | "async" | "~run"> {
/**
* The schema reference.
*/
readonly reference: (...args: any[]) => BaseSchema<unknown, unknown, BaseIssue<unknown>> | BaseSchemaAsync<unknown, unknown, BaseIssue<unknown>>;
/**
* Whether it's async.
*/
readonly async: true;
/**
* Parses unknown input values.
*
* @param dataset The input dataset.
* @param config The configuration.
*
* @returns The output dataset.
*
* @internal
*/
readonly "~run": (dataset: UnknownDataset, config: Config<BaseIssue<unknown>>) => Promise<OutputDataset<TOutput, TIssue>>;
}
//#endregion
//#region ../../library/src/types/transformation.d.ts
/**
* Base transformation interface.
*/
interface BaseTransformation<TInput$1, TOutput, TIssue extends BaseIssue<unknown>> {
/**
* The object kind.
*/
readonly kind: "transformation";
/**
* The transformation type.
*/
readonly type: string;
/**
* The transformation reference.
*/
readonly reference: (...args: any[]) => BaseTransformation<any, any, BaseIssue<unknown>>;
/**
* Whether it's async.
*/
readonly async: false;
/**
* Transforms known input values.
*
* @param dataset The input dataset.
* @param config The configuration.
*
* @returns The output dataset.
*
* @internal
*/
readonly "~run": (dataset: SuccessDataset<TInput$1>, config: Config<BaseIssue<unknown>>) => OutputDataset<TOutput, BaseIssue<unknown> | TIssue>;
/**
* The input, output and issue type.
*
* @internal
*/
readonly "~types"?: {
readonly input: TInput$1;
readonly output: TOutput;
readonly issue: TIssue;
} | undefined;
}
/**
* Base transformation async interface.
*/
interface BaseTransformationAsync<TInput$1, TOutput, TIssue extends BaseIssue<unknown>> extends Omit<BaseTransformation<TInput$1, TOutput, TIssue>, "reference" | "async" | "~run"> {
/**
* The transformation reference.
*/
readonly reference: (...args: any[]) => BaseTransformation<any, any, BaseIssue<unknown>> | BaseTransformationAsync<any, any, BaseIssue<unknown>>;
/**
* Whether it's async.
*/
readonly async: true;
/**
* Transforms known input values.
*
* @param dataset The input dataset.
* @param config The configuration.
*
* @returns The output dataset.
*
* @internal
*/
readonly "~run": (dataset: SuccessDataset<TInput$1>, config: Config<BaseIssue<unknown>>) => Promise<OutputDataset<TOutput, BaseIssue<unknown> | TIssue>>;
}
//#endregion
//#region ../../library/src/types/validation.d.ts
/**
* Base validation interface.
*/
interface BaseValidation<TInput$1, TOutput, TIssue extends BaseIssue<unknown>> {
/**
* The object kind.
*/
readonly kind: "validation";
/**
* The validation type.
*/
readonly type: string;
/**
* The validation reference.
*/
readonly reference: (...args: any[]) => BaseValidation<any, any, BaseIssue<unknown>>;
/**
* The expected property.
*/
readonly expects: string | null;
/**
* Whether it's async.
*/
readonly async: false;
/**
* Validates known input values.
*
* @param dataset The input dataset.
* @param config The configuration.
*
* @returns The output dataset.
*
* @internal
*/
readonly "~run": (dataset: OutputDataset<TInput$1, BaseIssue<unknown>>, config: Config<BaseIssue<unknown>>) => OutputDataset<TOutput, BaseIssue<unknown> | TIssue>;
/**
* The input, output and issue type.
*
* @internal
*/
readonly "~types"?: {
readonly input: TInput$1;
readonly output: TOutput;
readonly issue: TIssue;
} | undefined;
}
/**
* Base validation async interface.
*/
interface BaseValidationAsync<TInput$1, TOutput, TIssue extends BaseIssue<unknown>> extends Omit<BaseValidation<TInput$1, TOutput, TIssue>, "reference" | "async" | "~run"> {
/**
* The validation reference.
*/
readonly reference: (...args: any[]) => BaseValidation<any, any, BaseIssue<unknown>> | BaseValidationAsync<any, any, BaseIssue<unknown>>;
/**
* Whether it's async.
*/
readonly async: true;
/**
* Validates known input values.
*
* @param dataset The input dataset.
* @param config The configuration.
*
* @returns The output dataset.
*
* @internal
*/
readonly "~run": (dataset: OutputDataset<TInput$1, BaseIssue<unknown>>, config: Config<BaseIssue<unknown>>) => Promise<OutputDataset<TOutput, BaseIssue<unknown> | TIssue>>;
}
//#endregion
//#region ../../library/src/types/infer.d.ts
/**
* Infer input type.
*/
type InferInput<TItem$1 extends BaseSchema<unknown, unknown, BaseIssue<unknown>> | BaseSchemaAsync<unknown, unknown, BaseIssue<unknown>> | BaseValidation<any, unknown, BaseIssue<unknown>> | BaseValidationAsync<any, unknown, BaseIssue<unknown>> | BaseTransformation<any, unknown, BaseIssue<unknown>> | BaseTransformationAsync<any, unknown, BaseIssue<unknown>> | BaseMetadata<any>> = NonNullable<TItem$1["~types"]>["input"];
/**
* Infer output type.
*/
type InferOutput<TItem$1 extends BaseSchema<unknown, unknown, BaseIssue<unknown>> | BaseSchemaAsync<unknown, unknown, BaseIssue<unknown>> | BaseValidation<any, unknown, BaseIssue<unknown>> | BaseValidationAsync<any, unknown, BaseIssue<unknown>> | BaseTransformation<any, unknown, BaseIssue<unknown>> | BaseTransformationAsync<any, unknown, BaseIssue<unknown>> | BaseMetadata<any>> = NonNullable<TItem$1["~types"]>["output"];
//#endregion
//#region ../../library/src/types/utils.d.ts
/**
* Constructs a type that is maybe readonly.
*/
type MaybeReadonly<TValue$1> = TValue$1 | Readonly<TValue$1>;
//#endregion
//#region ../../library/src/types/other.d.ts
/**
* Error message type.
*/
type ErrorMessage<TIssue extends BaseIssue<unknown>> = ((issue: TIssue) => string) | string;
//#endregion
//#region ../../library/src/types/issue.d.ts
/**
* Array path item interface.
*/
interface ArrayPathItem {
/**
* The path item type.
*/
readonly type: "array";
/**
* The path item origin.
*/
readonly origin: "value";
/**
* The path item input.
*/
readonly input: MaybeReadonly<unknown[]>;
/**
* The path item key.
*/
readonly key: number;
/**
* The path item value.
*/
readonly value: unknown;
}
/**
* Map path item interface.
*/
interface MapPathItem {
/**
* The path item type.
*/
readonly type: "map";
/**
* The path item origin.
*/
readonly origin: "key" | "value";
/**
* The path item input.
*/
readonly input: Map<unknown, unknown>;
/**
* The path item key.
*/
readonly key: unknown;
/**
* The path item value.
*/
readonly value: unknown;
}
/**
* Object path item interface.
*/
interface ObjectPathItem {
/**
* The path item type.
*/
readonly type: "object";
/**
* The path item origin.
*/
readonly origin: "key" | "value";
/**
* The path item input.
*/
readonly input: Record<string, unknown>;
/**
* The path item key.
*/
readonly key: string;
/**
* The path item value.
*/
readonly value: unknown;
}
/**
* Set path item interface.
*/
interface SetPathItem {
/**
* The path item type.
*/
readonly type: "set";
/**
* The path item origin.
*/
readonly origin: "value";
/**
* The path item input.
*/
readonly input: Set<unknown>;
/**
* The path item key.
*/
readonly key: null;
/**
* The path item key.
*/
readonly value: unknown;
}
/**
* Unknown path item interface.
*/
interface UnknownPathItem {
/**
* The path item type.
*/
readonly type: "unknown";
/**
* The path item origin.
*/
readonly origin: "key" | "value";
/**
* The path item input.
*/
readonly input: unknown;
/**
* The path item key.
*/
readonly key: unknown;
/**
* The path item value.
*/
readonly value: unknown;
}
/**
* Issue path item type.
*/
type IssuePathItem = ArrayPathItem | MapPathItem | ObjectPathItem | SetPathItem | UnknownPathItem;
/**
* Base issue interface.
*/
interface BaseIssue<TInput$1> extends Config<BaseIssue<TInput$1>> {
/**
* The issue kind.
*/
readonly kind: "schema" | "validation" | "transformation";
/**
* The issue type.
*/
readonly type: string;
/**
* The raw input data.
*/
readonly input: TInput$1;
/**
* The expected property.
*/
readonly expected: string | null;
/**
* The received property.
*/
readonly received: string;
/**
* The error message.
*/
readonly message: string;
/**
* The input requirement.
*/
readonly requirement?: unknown | undefined;
/**
* The issue path.
*/
readonly path?: [IssuePathItem, ...IssuePathItem[]] | undefined;
/**
* The sub issues.
*/
readonly issues?: [BaseIssue<TInput$1>, ...BaseIssue<TInput$1>[]] | undefined;
}
//#endregion
//#region ../../library/src/types/config.d.ts
/**
* Config interface.
*/
interface Config<TIssue extends BaseIssue<unknown>> {
/**
* The selected language.
*/
readonly lang?: string | undefined;
/**
* The error message.
*/
readonly message?: ErrorMessage<TIssue> | undefined;
/**
* Whether it should be aborted early.
*/
readonly abortEarly?: boolean | undefined;
/**
* Whether a pipe should be aborted early.
*/
readonly abortPipeEarly?: boolean | undefined;
}
//#endregion
//#region ../../library/src/types/pipe.d.ts
/**
* Pipe action type.
*/
type PipeAction<TInput$1, TOutput, TIssue extends BaseIssue<unknown>> = BaseValidation<TInput$1, TOutput, TIssue> | BaseTransformation<TInput$1, TOutput, TIssue> | BaseMetadata<TInput$1>;
//#endregion
//#region src/types/schema.d.ts
type JsonSchemaTypeName = "string" | "number" | "integer" | "boolean" | "object" | "array" | "null";
type JsonSchemaType = string | number | boolean | JsonSchemaObject | JsonSchemaArray | null;
interface JsonSchemaObject {
[key: string]: JsonSchemaType;
}
interface JsonSchemaArray extends Array<JsonSchemaType> {}
type JsonSchemaDefinition = JsonSchema | boolean;
/**
* JSON Schema interface.
*/
interface JsonSchema {
$id?: string | undefined;
$ref?: string | undefined;
$schema?: string | undefined;
$comment?: string | undefined;
$defs?: Record<string, JsonSchemaDefinition> | undefined;
type?: JsonSchemaTypeName | JsonSchemaTypeName[] | undefined;
nullable?: boolean | undefined;
enum?: JsonSchemaType[] | undefined;
const?: JsonSchemaType | undefined;
multipleOf?: number | undefined;
maximum?: number | undefined;
exclusiveMaximum?: number | undefined;
minimum?: number | undefined;
exclusiveMinimum?: number | undefined;
maxLength?: number | undefined;
minLength?: number | undefined;
pattern?: string | undefined;
items?: JsonSchemaDefinition | JsonSchemaDefinition[] | undefined;
prefixItems?: JsonSchemaDefinition[] | undefined;
additionalItems?: JsonSchemaDefinition | undefined;
maxItems?: number | undefined;
minItems?: number | undefined;
uniqueItems?: boolean | undefined;
contains?: JsonSchemaDefinition | undefined;
maxProperties?: number | undefined;
minProperties?: number | undefined;
required?: string[] | undefined;
properties?: Record<string, JsonSchemaDefinition> | undefined;
patternProperties?: Record<string, JsonSchemaDefinition> | undefined;
additionalProperties?: JsonSchemaDefinition | undefined;
dependencies?: Record<string, JsonSchemaDefinition | string[]> | undefined;
propertyNames?: JsonSchemaDefinition | undefined;
if?: JsonSchemaDefinition | undefined;
then?: JsonSchemaDefinition | undefined;
else?: JsonSchemaDefinition | undefined;
allOf?: JsonSchemaDefinition[] | undefined;
anyOf?: JsonSchemaDefinition[] | undefined;
oneOf?: JsonSchemaDefinition[] | undefined;
not?: JsonSchemaDefinition | undefined;
format?: string | undefined;
contentMediaType?: string | undefined;
contentEncoding?: string | undefined;
definitions?: Record<string, JsonSchemaDefinition> | undefined;
title?: string | undefined;
description?: string | undefined;
default?: JsonSchemaType | undefined;
readOnly?: boolean | undefined;
writeOnly?: boolean | undefined;
examples?: JsonSchemaType | undefined;
}
/**
* JSON Schema 7 interface.
*
* @deprecated Use `JsonSchema` instead.
*/
interface JSONSchema7 extends JsonSchema {}
//#endregion
//#region src/types/config.d.ts
/**
* JSON Schema conversion context interface.
*/
interface ConversionContext {
/**
* The JSON Schema definitions that have already been created.
*/
readonly definitions: Record<string, JsonSchema>;
/**
* The JSON Schema reference map that is used to look up the reference ID
* for a given Valibot schema.
*/
readonly referenceMap: Map<BaseSchema<unknown, unknown, BaseIssue<unknown>>, string>;
/**
* The lazy schema getter map that is used internally to ensure that
* recursive lazy schemas are unwrapped only once.
*/
readonly getterMap: Map<(input: unknown) => BaseSchema<unknown, unknown, BaseIssue<unknown>>, BaseSchema<unknown, unknown, BaseIssue<unknown>>>;
}
/**
* JSON Schema override context interface for schemas.
*
* @beta
*/
interface OverrideSchemaContext extends ConversionContext {
/**
* The JSON Schema reference ID.
*/
readonly referenceId: string | undefined;
/**
* The Valibot schema to be converted.
*/
readonly valibotSchema: BaseSchema<unknown, unknown, BaseIssue<unknown>>;
/**
* The converted JSON Schema.
*/
readonly jsonSchema: JsonSchema;
/**
* The errors of the current Valibot schema conversion.
*/
readonly errors: [string, ...string[]] | undefined;
}
/**
* JSON Schema override context interface for actions.
*
* @beta
*/
interface OverrideActionContext {
/**
* The Valibot action to be converted.
*/
readonly valibotAction: PipeAction<any, any, BaseIssue<unknown>>;
/**
* The converted JSON Schema.
*/
readonly jsonSchema: JsonSchema;
/**
* The errors of the current Valibot action conversion.
*/
readonly errors: [string, ...string[]] | undefined;
}
/**
* JSON Schema override context interface for references.
*
* @beta
*/
interface OverrideRefContext extends ConversionContext {
/**
* The JSON Schema reference ID.
*/
readonly referenceId: string;
/**
* The Valibot schema to be converted.
*/
readonly valibotSchema: BaseSchema<unknown, unknown, BaseIssue<unknown>>;
/**
* The converted JSON Schema.
*/
readonly jsonSchema: JsonSchema;
}
/**
* JSON Schema conversion config interface.
*/
interface ConversionConfig {
/**
* The target JSON Schema draft version. Defaults to 'draft-07'.
*/
readonly target?: "draft-07" | "draft-2020-12" | "openapi-3.0";
/**
* Whether to convert the input or output type of the Valibot schema to JSON Schema.
*
* When set to 'input', conversion stops before the first potential type
* transformation action or second schema in any pipeline.
*
* When set to 'output', conversion of any pipelines starts from the last
* schema in the pipeline. Therefore, the output type must be specified
* explicitly with a schema after the last type transformation action.
*
* @beta
*/
readonly typeMode?: "ignore" | "input" | "output";
/**
* The policy for handling incompatible schemas and actions.
*/
readonly errorMode?: "throw" | "warn" | "ignore";
/**
* The schema definitions for constructing recursive schemas. If not
* specified, the definitions are generated automatically as needed.
*/
readonly definitions?: Record<string, BaseSchema<unknown, unknown, BaseIssue<unknown>>>;
/**
* Overrides the JSON Schema conversion for a specific Valibot schema.
*
* Only return a JSON Schema if you want to override the default conversion
* behaviour and suppress errors for a specific schema. Returning either
* `null` or `undefined` will skip the override.
*
* @param context The conversion context.
*
* @returns A JSON Schema, if overridden.
*
* @beta
*/
readonly overrideSchema?: (context: OverrideSchemaContext) => JsonSchema | null | undefined;
/**
* The actions that should be ignored during the conversion.
*
* @beta
*/
readonly ignoreActions?: string[];
/**
* Overrides the JSON Schema reference for a specific Valibot action.
*
* Only return a JSON Schema if you want to override the default conversion
* behaviour and suppress errors for a specific action. Returning either
* `null` or `undefined` will skip the override.
*
* @param context The conversion context.
*
* @returns A JSON Schema, if overridden.
*
* @beta
*/
readonly overrideAction?: (context: OverrideActionContext) => JsonSchema | null | undefined;
/**
* Overrides the JSON Schema reference for a specific reference ID.
*
* @param context The conversion context.
*
* @returns A reference ID, if overridden.
*
* @beta
*/
readonly overrideRef?: (context: OverrideRefContext) => string | null | undefined;
}
//#endregion
//#region src/types/standard.d.ts
/**
* JSON Schema interface.
*/
interface StandardJsonSchema<TInput$1, TOutput> {
/**
* The Standard JSON Schema properties.
*/
readonly "~standard": StandardJsonProps<TInput$1, TOutput>;
}
/**
* The Standard JSON Schema properties interface.
*/
interface StandardJsonProps<TInput$1, TOutput> extends StandardProps<TInput$1, TOutput> {
/**
* Methods for generating the input/output JSON Schema.
*/
readonly jsonSchema: StandardJsonConverter;
}
/**
* The Standard JSON Schema converter interface.
*/
interface StandardJsonConverter {
/**
* Converts the input type to JSON Schema. May throw if conversion is not supported.
*/
readonly input: (options: StandardJsonOptions) => Record<string, unknown>;
/**
* Converts the output type to JSON Schema. May throw if conversion is not supported.
*/
readonly output: (options: StandardJsonOptions) => Record<string, unknown>;
}
/**
* The target version of the generated JSON Schema.
*/
type StandardJsonTarget = "draft-2020-12" | "draft-07" | "openapi-3.0" | ({} & string);
/**
* The options for the input/output methods.
*/
interface StandardJsonOptions {
/**
* Specifies the target version of the generated JSON Schema.
*/
readonly target: StandardJsonTarget;
/**
* Explicit support for additional vendor-specific parameters, if needed.
*/
readonly libraryOptions?: Record<string, unknown> | undefined;
}
//#endregion
//#region src/functions/toJsonSchema/toJsonSchema.d.ts
/**
* Converts a Valibot schema to the JSON Schema format.
*
* @param schema The Valibot schema object.
* @param config The JSON Schema configuration.
*
* @returns The converted JSON Schema.
*/
declare function toJsonSchema(schema: BaseSchema<unknown, unknown, BaseIssue<unknown>>, config?: ConversionConfig): JsonSchema;
//#endregion
//#region src/functions/toJsonSchemaDefs/toJsonSchemaDefs.d.ts
/**
* Converts Valibot schema definitions to JSON Schema definitions.
*
* @param definitions The Valibot schema definitions.
* @param config The JSON Schema configuration.
*
* @returns The converted JSON Schema definitions.
*/
declare function toJsonSchemaDefs<TDefinitions extends Record<string, BaseSchema<unknown, unknown, BaseIssue<unknown>>>>(definitions: TDefinitions, config?: Omit<ConversionConfig, "definitions">): { [TKey in keyof TDefinitions]: JsonSchema };
//#endregion
//#region src/functions/toStandardJsonSchema/toStandardJsonSchema.d.ts
/**
* Converts a Valibot schema to the Standard JSON Schema format.
*
* @param schema The Valibot schema object.
*
* @returns The Standard JSON Schema.
*/
declare function toStandardJsonSchema<TSchema extends BaseSchema<unknown, unknown, BaseIssue<unknown>>>(schema: TSchema): StandardJsonSchema<InferInput<TSchema>, InferOutput<TSchema>>;
//#endregion
//#region src/storages/globalDefs/globalDefs.d.ts
/**
* Adds new definitions to the global schema definitions.
*
* @param definitions The schema definitions.
*
* @beta
*/
declare function addGlobalDefs(definitions: Record<string, BaseSchema<unknown, unknown, BaseIssue<unknown>>>): void;
/**
* Returns the current global schema definitions.
*
* @returns The schema definitions.
*
* @beta
*/
declare function getGlobalDefs(): Record<string, BaseSchema<unknown, unknown, BaseIssue<unknown>>> | undefined;
//#endregion
export { ConversionConfig, ConversionContext, JSONSchema7, JsonSchema, OverrideActionContext, OverrideRefContext, OverrideSchemaContext, StandardJsonSchema, addGlobalDefs, getGlobalDefs, toJsonSchema, toJsonSchemaDefs, toStandardJsonSchema };

View File

@@ -0,0 +1,955 @@
//#region ../../library/src/types/metadata.d.ts
/**
* Base metadata interface.
*/
interface BaseMetadata<TInput$1> {
/**
* The object kind.
*/
readonly kind: "metadata";
/**
* The metadata type.
*/
readonly type: string;
/**
* The metadata reference.
*/
readonly reference: (...args: any[]) => BaseMetadata<any>;
/**
* The input, output and issue type.
*
* @internal
*/
readonly "~types"?: {
readonly input: TInput$1;
readonly output: TInput$1;
readonly issue: never;
} | undefined;
}
//#endregion
//#region ../../library/src/types/dataset.d.ts
/**
* Unknown dataset interface.
*/
interface UnknownDataset {
/**
* Whether is's typed.
*/
typed?: false;
/**
* The dataset value.
*/
value: unknown;
/**
* The dataset issues.
*/
issues?: undefined;
}
/**
* Success dataset interface.
*/
interface SuccessDataset<TValue$1> {
/**
* Whether is's typed.
*/
typed: true;
/**
* The dataset value.
*/
value: TValue$1;
/**
* The dataset issues.
*/
issues?: undefined;
}
/**
* Partial dataset interface.
*/
interface PartialDataset<TValue$1, TIssue extends BaseIssue<unknown>> {
/**
* Whether is's typed.
*/
typed: true;
/**
* The dataset value.
*/
value: TValue$1;
/**
* The dataset issues.
*/
issues: [TIssue, ...TIssue[]];
}
/**
* Failure dataset interface.
*/
interface FailureDataset<TIssue extends BaseIssue<unknown>> {
/**
* Whether is's typed.
*/
typed: false;
/**
* The dataset value.
*/
value: unknown;
/**
* The dataset issues.
*/
issues: [TIssue, ...TIssue[]];
}
/**
* Output dataset type.
*/
type OutputDataset<TValue$1, TIssue extends BaseIssue<unknown>> = SuccessDataset<TValue$1> | PartialDataset<TValue$1, TIssue> | FailureDataset<TIssue>;
//#endregion
//#region ../../library/src/types/standard.d.ts
/**
* The Standard Schema properties interface.
*/
interface StandardProps<TInput$1, TOutput> {
/**
* The version number of the standard.
*/
readonly version: 1;
/**
* The vendor name of the schema library.
*/
readonly vendor: "valibot";
/**
* Validates unknown input values.
*/
readonly validate: (value: unknown) => StandardResult<TOutput> | Promise<StandardResult<TOutput>>;
/**
* Inferred types associated with the schema.
*/
readonly types?: StandardTypes<TInput$1, TOutput> | undefined;
}
/**
* The result interface of the validate function.
*/
type StandardResult<TOutput> = StandardSuccessResult<TOutput> | StandardFailureResult;
/**
* The result interface if validation succeeds.
*/
interface StandardSuccessResult<TOutput> {
/**
* The typed output value.
*/
readonly value: TOutput;
/**
* The non-existent issues.
*/
readonly issues?: undefined;
}
/**
* The result interface if validation fails.
*/
interface StandardFailureResult {
/**
* The issues of failed validation.
*/
readonly issues: readonly StandardIssue[];
}
/**
* The issue interface of the failure output.
*/
interface StandardIssue {
/**
* The error message of the issue.
*/
readonly message: string;
/**
* The path of the issue, if any.
*/
readonly path?: readonly (PropertyKey | StandardPathItem)[] | undefined;
}
/**
* The path item interface of the issue.
*/
interface StandardPathItem {
/**
* The key of the path item.
*/
readonly key: PropertyKey;
}
/**
* The Standard Schema types interface.
*/
interface StandardTypes<TInput$1, TOutput> {
/**
* The input type of the schema.
*/
readonly input: TInput$1;
/**
* The output type of the schema.
*/
readonly output: TOutput;
}
//#endregion
//#region ../../library/src/types/schema.d.ts
/**
* Base schema interface.
*/
interface BaseSchema<TInput$1, TOutput, TIssue extends BaseIssue<unknown>> {
/**
* The object kind.
*/
readonly kind: "schema";
/**
* The schema type.
*/
readonly type: string;
/**
* The schema reference.
*/
readonly reference: (...args: any[]) => BaseSchema<unknown, unknown, BaseIssue<unknown>>;
/**
* The expected property.
*/
readonly expects: string;
/**
* Whether it's async.
*/
readonly async: false;
/**
* The Standard Schema properties.
*
* @internal
*/
readonly "~standard": StandardProps<TInput$1, TOutput>;
/**
* Parses unknown input values.
*
* @param dataset The input dataset.
* @param config The configuration.
*
* @returns The output dataset.
*
* @internal
*/
readonly "~run": (dataset: UnknownDataset, config: Config<BaseIssue<unknown>>) => OutputDataset<TOutput, TIssue>;
/**
* The input, output and issue type.
*
* @internal
*/
readonly "~types"?: {
readonly input: TInput$1;
readonly output: TOutput;
readonly issue: TIssue;
} | undefined;
}
/**
* Base schema async interface.
*/
interface BaseSchemaAsync<TInput$1, TOutput, TIssue extends BaseIssue<unknown>> extends Omit<BaseSchema<TInput$1, TOutput, TIssue>, "reference" | "async" | "~run"> {
/**
* The schema reference.
*/
readonly reference: (...args: any[]) => BaseSchema<unknown, unknown, BaseIssue<unknown>> | BaseSchemaAsync<unknown, unknown, BaseIssue<unknown>>;
/**
* Whether it's async.
*/
readonly async: true;
/**
* Parses unknown input values.
*
* @param dataset The input dataset.
* @param config The configuration.
*
* @returns The output dataset.
*
* @internal
*/
readonly "~run": (dataset: UnknownDataset, config: Config<BaseIssue<unknown>>) => Promise<OutputDataset<TOutput, TIssue>>;
}
//#endregion
//#region ../../library/src/types/transformation.d.ts
/**
* Base transformation interface.
*/
interface BaseTransformation<TInput$1, TOutput, TIssue extends BaseIssue<unknown>> {
/**
* The object kind.
*/
readonly kind: "transformation";
/**
* The transformation type.
*/
readonly type: string;
/**
* The transformation reference.
*/
readonly reference: (...args: any[]) => BaseTransformation<any, any, BaseIssue<unknown>>;
/**
* Whether it's async.
*/
readonly async: false;
/**
* Transforms known input values.
*
* @param dataset The input dataset.
* @param config The configuration.
*
* @returns The output dataset.
*
* @internal
*/
readonly "~run": (dataset: SuccessDataset<TInput$1>, config: Config<BaseIssue<unknown>>) => OutputDataset<TOutput, BaseIssue<unknown> | TIssue>;
/**
* The input, output and issue type.
*
* @internal
*/
readonly "~types"?: {
readonly input: TInput$1;
readonly output: TOutput;
readonly issue: TIssue;
} | undefined;
}
/**
* Base transformation async interface.
*/
interface BaseTransformationAsync<TInput$1, TOutput, TIssue extends BaseIssue<unknown>> extends Omit<BaseTransformation<TInput$1, TOutput, TIssue>, "reference" | "async" | "~run"> {
/**
* The transformation reference.
*/
readonly reference: (...args: any[]) => BaseTransformation<any, any, BaseIssue<unknown>> | BaseTransformationAsync<any, any, BaseIssue<unknown>>;
/**
* Whether it's async.
*/
readonly async: true;
/**
* Transforms known input values.
*
* @param dataset The input dataset.
* @param config The configuration.
*
* @returns The output dataset.
*
* @internal
*/
readonly "~run": (dataset: SuccessDataset<TInput$1>, config: Config<BaseIssue<unknown>>) => Promise<OutputDataset<TOutput, BaseIssue<unknown> | TIssue>>;
}
//#endregion
//#region ../../library/src/types/validation.d.ts
/**
* Base validation interface.
*/
interface BaseValidation<TInput$1, TOutput, TIssue extends BaseIssue<unknown>> {
/**
* The object kind.
*/
readonly kind: "validation";
/**
* The validation type.
*/
readonly type: string;
/**
* The validation reference.
*/
readonly reference: (...args: any[]) => BaseValidation<any, any, BaseIssue<unknown>>;
/**
* The expected property.
*/
readonly expects: string | null;
/**
* Whether it's async.
*/
readonly async: false;
/**
* Validates known input values.
*
* @param dataset The input dataset.
* @param config The configuration.
*
* @returns The output dataset.
*
* @internal
*/
readonly "~run": (dataset: OutputDataset<TInput$1, BaseIssue<unknown>>, config: Config<BaseIssue<unknown>>) => OutputDataset<TOutput, BaseIssue<unknown> | TIssue>;
/**
* The input, output and issue type.
*
* @internal
*/
readonly "~types"?: {
readonly input: TInput$1;
readonly output: TOutput;
readonly issue: TIssue;
} | undefined;
}
/**
* Base validation async interface.
*/
interface BaseValidationAsync<TInput$1, TOutput, TIssue extends BaseIssue<unknown>> extends Omit<BaseValidation<TInput$1, TOutput, TIssue>, "reference" | "async" | "~run"> {
/**
* The validation reference.
*/
readonly reference: (...args: any[]) => BaseValidation<any, any, BaseIssue<unknown>> | BaseValidationAsync<any, any, BaseIssue<unknown>>;
/**
* Whether it's async.
*/
readonly async: true;
/**
* Validates known input values.
*
* @param dataset The input dataset.
* @param config The configuration.
*
* @returns The output dataset.
*
* @internal
*/
readonly "~run": (dataset: OutputDataset<TInput$1, BaseIssue<unknown>>, config: Config<BaseIssue<unknown>>) => Promise<OutputDataset<TOutput, BaseIssue<unknown> | TIssue>>;
}
//#endregion
//#region ../../library/src/types/infer.d.ts
/**
* Infer input type.
*/
type InferInput<TItem$1 extends BaseSchema<unknown, unknown, BaseIssue<unknown>> | BaseSchemaAsync<unknown, unknown, BaseIssue<unknown>> | BaseValidation<any, unknown, BaseIssue<unknown>> | BaseValidationAsync<any, unknown, BaseIssue<unknown>> | BaseTransformation<any, unknown, BaseIssue<unknown>> | BaseTransformationAsync<any, unknown, BaseIssue<unknown>> | BaseMetadata<any>> = NonNullable<TItem$1["~types"]>["input"];
/**
* Infer output type.
*/
type InferOutput<TItem$1 extends BaseSchema<unknown, unknown, BaseIssue<unknown>> | BaseSchemaAsync<unknown, unknown, BaseIssue<unknown>> | BaseValidation<any, unknown, BaseIssue<unknown>> | BaseValidationAsync<any, unknown, BaseIssue<unknown>> | BaseTransformation<any, unknown, BaseIssue<unknown>> | BaseTransformationAsync<any, unknown, BaseIssue<unknown>> | BaseMetadata<any>> = NonNullable<TItem$1["~types"]>["output"];
//#endregion
//#region ../../library/src/types/utils.d.ts
/**
* Constructs a type that is maybe readonly.
*/
type MaybeReadonly<TValue$1> = TValue$1 | Readonly<TValue$1>;
//#endregion
//#region ../../library/src/types/other.d.ts
/**
* Error message type.
*/
type ErrorMessage<TIssue extends BaseIssue<unknown>> = ((issue: TIssue) => string) | string;
//#endregion
//#region ../../library/src/types/issue.d.ts
/**
* Array path item interface.
*/
interface ArrayPathItem {
/**
* The path item type.
*/
readonly type: "array";
/**
* The path item origin.
*/
readonly origin: "value";
/**
* The path item input.
*/
readonly input: MaybeReadonly<unknown[]>;
/**
* The path item key.
*/
readonly key: number;
/**
* The path item value.
*/
readonly value: unknown;
}
/**
* Map path item interface.
*/
interface MapPathItem {
/**
* The path item type.
*/
readonly type: "map";
/**
* The path item origin.
*/
readonly origin: "key" | "value";
/**
* The path item input.
*/
readonly input: Map<unknown, unknown>;
/**
* The path item key.
*/
readonly key: unknown;
/**
* The path item value.
*/
readonly value: unknown;
}
/**
* Object path item interface.
*/
interface ObjectPathItem {
/**
* The path item type.
*/
readonly type: "object";
/**
* The path item origin.
*/
readonly origin: "key" | "value";
/**
* The path item input.
*/
readonly input: Record<string, unknown>;
/**
* The path item key.
*/
readonly key: string;
/**
* The path item value.
*/
readonly value: unknown;
}
/**
* Set path item interface.
*/
interface SetPathItem {
/**
* The path item type.
*/
readonly type: "set";
/**
* The path item origin.
*/
readonly origin: "value";
/**
* The path item input.
*/
readonly input: Set<unknown>;
/**
* The path item key.
*/
readonly key: null;
/**
* The path item key.
*/
readonly value: unknown;
}
/**
* Unknown path item interface.
*/
interface UnknownPathItem {
/**
* The path item type.
*/
readonly type: "unknown";
/**
* The path item origin.
*/
readonly origin: "key" | "value";
/**
* The path item input.
*/
readonly input: unknown;
/**
* The path item key.
*/
readonly key: unknown;
/**
* The path item value.
*/
readonly value: unknown;
}
/**
* Issue path item type.
*/
type IssuePathItem = ArrayPathItem | MapPathItem | ObjectPathItem | SetPathItem | UnknownPathItem;
/**
* Base issue interface.
*/
interface BaseIssue<TInput$1> extends Config<BaseIssue<TInput$1>> {
/**
* The issue kind.
*/
readonly kind: "schema" | "validation" | "transformation";
/**
* The issue type.
*/
readonly type: string;
/**
* The raw input data.
*/
readonly input: TInput$1;
/**
* The expected property.
*/
readonly expected: string | null;
/**
* The received property.
*/
readonly received: string;
/**
* The error message.
*/
readonly message: string;
/**
* The input requirement.
*/
readonly requirement?: unknown | undefined;
/**
* The issue path.
*/
readonly path?: [IssuePathItem, ...IssuePathItem[]] | undefined;
/**
* The sub issues.
*/
readonly issues?: [BaseIssue<TInput$1>, ...BaseIssue<TInput$1>[]] | undefined;
}
//#endregion
//#region ../../library/src/types/config.d.ts
/**
* Config interface.
*/
interface Config<TIssue extends BaseIssue<unknown>> {
/**
* The selected language.
*/
readonly lang?: string | undefined;
/**
* The error message.
*/
readonly message?: ErrorMessage<TIssue> | undefined;
/**
* Whether it should be aborted early.
*/
readonly abortEarly?: boolean | undefined;
/**
* Whether a pipe should be aborted early.
*/
readonly abortPipeEarly?: boolean | undefined;
}
//#endregion
//#region ../../library/src/types/pipe.d.ts
/**
* Pipe action type.
*/
type PipeAction<TInput$1, TOutput, TIssue extends BaseIssue<unknown>> = BaseValidation<TInput$1, TOutput, TIssue> | BaseTransformation<TInput$1, TOutput, TIssue> | BaseMetadata<TInput$1>;
//#endregion
//#region src/types/schema.d.ts
type JsonSchemaTypeName = "string" | "number" | "integer" | "boolean" | "object" | "array" | "null";
type JsonSchemaType = string | number | boolean | JsonSchemaObject | JsonSchemaArray | null;
interface JsonSchemaObject {
[key: string]: JsonSchemaType;
}
interface JsonSchemaArray extends Array<JsonSchemaType> {}
type JsonSchemaDefinition = JsonSchema | boolean;
/**
* JSON Schema interface.
*/
interface JsonSchema {
$id?: string | undefined;
$ref?: string | undefined;
$schema?: string | undefined;
$comment?: string | undefined;
$defs?: Record<string, JsonSchemaDefinition> | undefined;
type?: JsonSchemaTypeName | JsonSchemaTypeName[] | undefined;
nullable?: boolean | undefined;
enum?: JsonSchemaType[] | undefined;
const?: JsonSchemaType | undefined;
multipleOf?: number | undefined;
maximum?: number | undefined;
exclusiveMaximum?: number | undefined;
minimum?: number | undefined;
exclusiveMinimum?: number | undefined;
maxLength?: number | undefined;
minLength?: number | undefined;
pattern?: string | undefined;
items?: JsonSchemaDefinition | JsonSchemaDefinition[] | undefined;
prefixItems?: JsonSchemaDefinition[] | undefined;
additionalItems?: JsonSchemaDefinition | undefined;
maxItems?: number | undefined;
minItems?: number | undefined;
uniqueItems?: boolean | undefined;
contains?: JsonSchemaDefinition | undefined;
maxProperties?: number | undefined;
minProperties?: number | undefined;
required?: string[] | undefined;
properties?: Record<string, JsonSchemaDefinition> | undefined;
patternProperties?: Record<string, JsonSchemaDefinition> | undefined;
additionalProperties?: JsonSchemaDefinition | undefined;
dependencies?: Record<string, JsonSchemaDefinition | string[]> | undefined;
propertyNames?: JsonSchemaDefinition | undefined;
if?: JsonSchemaDefinition | undefined;
then?: JsonSchemaDefinition | undefined;
else?: JsonSchemaDefinition | undefined;
allOf?: JsonSchemaDefinition[] | undefined;
anyOf?: JsonSchemaDefinition[] | undefined;
oneOf?: JsonSchemaDefinition[] | undefined;
not?: JsonSchemaDefinition | undefined;
format?: string | undefined;
contentMediaType?: string | undefined;
contentEncoding?: string | undefined;
definitions?: Record<string, JsonSchemaDefinition> | undefined;
title?: string | undefined;
description?: string | undefined;
default?: JsonSchemaType | undefined;
readOnly?: boolean | undefined;
writeOnly?: boolean | undefined;
examples?: JsonSchemaType | undefined;
}
/**
* JSON Schema 7 interface.
*
* @deprecated Use `JsonSchema` instead.
*/
interface JSONSchema7 extends JsonSchema {}
//#endregion
//#region src/types/config.d.ts
/**
* JSON Schema conversion context interface.
*/
interface ConversionContext {
/**
* The JSON Schema definitions that have already been created.
*/
readonly definitions: Record<string, JsonSchema>;
/**
* The JSON Schema reference map that is used to look up the reference ID
* for a given Valibot schema.
*/
readonly referenceMap: Map<BaseSchema<unknown, unknown, BaseIssue<unknown>>, string>;
/**
* The lazy schema getter map that is used internally to ensure that
* recursive lazy schemas are unwrapped only once.
*/
readonly getterMap: Map<(input: unknown) => BaseSchema<unknown, unknown, BaseIssue<unknown>>, BaseSchema<unknown, unknown, BaseIssue<unknown>>>;
}
/**
* JSON Schema override context interface for schemas.
*
* @beta
*/
interface OverrideSchemaContext extends ConversionContext {
/**
* The JSON Schema reference ID.
*/
readonly referenceId: string | undefined;
/**
* The Valibot schema to be converted.
*/
readonly valibotSchema: BaseSchema<unknown, unknown, BaseIssue<unknown>>;
/**
* The converted JSON Schema.
*/
readonly jsonSchema: JsonSchema;
/**
* The errors of the current Valibot schema conversion.
*/
readonly errors: [string, ...string[]] | undefined;
}
/**
* JSON Schema override context interface for actions.
*
* @beta
*/
interface OverrideActionContext {
/**
* The Valibot action to be converted.
*/
readonly valibotAction: PipeAction<any, any, BaseIssue<unknown>>;
/**
* The converted JSON Schema.
*/
readonly jsonSchema: JsonSchema;
/**
* The errors of the current Valibot action conversion.
*/
readonly errors: [string, ...string[]] | undefined;
}
/**
* JSON Schema override context interface for references.
*
* @beta
*/
interface OverrideRefContext extends ConversionContext {
/**
* The JSON Schema reference ID.
*/
readonly referenceId: string;
/**
* The Valibot schema to be converted.
*/
readonly valibotSchema: BaseSchema<unknown, unknown, BaseIssue<unknown>>;
/**
* The converted JSON Schema.
*/
readonly jsonSchema: JsonSchema;
}
/**
* JSON Schema conversion config interface.
*/
interface ConversionConfig {
/**
* The target JSON Schema draft version. Defaults to 'draft-07'.
*/
readonly target?: "draft-07" | "draft-2020-12" | "openapi-3.0";
/**
* Whether to convert the input or output type of the Valibot schema to JSON Schema.
*
* When set to 'input', conversion stops before the first potential type
* transformation action or second schema in any pipeline.
*
* When set to 'output', conversion of any pipelines starts from the last
* schema in the pipeline. Therefore, the output type must be specified
* explicitly with a schema after the last type transformation action.
*
* @beta
*/
readonly typeMode?: "ignore" | "input" | "output";
/**
* The policy for handling incompatible schemas and actions.
*/
readonly errorMode?: "throw" | "warn" | "ignore";
/**
* The schema definitions for constructing recursive schemas. If not
* specified, the definitions are generated automatically as needed.
*/
readonly definitions?: Record<string, BaseSchema<unknown, unknown, BaseIssue<unknown>>>;
/**
* Overrides the JSON Schema conversion for a specific Valibot schema.
*
* Only return a JSON Schema if you want to override the default conversion
* behaviour and suppress errors for a specific schema. Returning either
* `null` or `undefined` will skip the override.
*
* @param context The conversion context.
*
* @returns A JSON Schema, if overridden.
*
* @beta
*/
readonly overrideSchema?: (context: OverrideSchemaContext) => JsonSchema | null | undefined;
/**
* The actions that should be ignored during the conversion.
*
* @beta
*/
readonly ignoreActions?: string[];
/**
* Overrides the JSON Schema reference for a specific Valibot action.
*
* Only return a JSON Schema if you want to override the default conversion
* behaviour and suppress errors for a specific action. Returning either
* `null` or `undefined` will skip the override.
*
* @param context The conversion context.
*
* @returns A JSON Schema, if overridden.
*
* @beta
*/
readonly overrideAction?: (context: OverrideActionContext) => JsonSchema | null | undefined;
/**
* Overrides the JSON Schema reference for a specific reference ID.
*
* @param context The conversion context.
*
* @returns A reference ID, if overridden.
*
* @beta
*/
readonly overrideRef?: (context: OverrideRefContext) => string | null | undefined;
}
//#endregion
//#region src/types/standard.d.ts
/**
* JSON Schema interface.
*/
interface StandardJsonSchema<TInput$1, TOutput> {
/**
* The Standard JSON Schema properties.
*/
readonly "~standard": StandardJsonProps<TInput$1, TOutput>;
}
/**
* The Standard JSON Schema properties interface.
*/
interface StandardJsonProps<TInput$1, TOutput> extends StandardProps<TInput$1, TOutput> {
/**
* Methods for generating the input/output JSON Schema.
*/
readonly jsonSchema: StandardJsonConverter;
}
/**
* The Standard JSON Schema converter interface.
*/
interface StandardJsonConverter {
/**
* Converts the input type to JSON Schema. May throw if conversion is not supported.
*/
readonly input: (options: StandardJsonOptions) => Record<string, unknown>;
/**
* Converts the output type to JSON Schema. May throw if conversion is not supported.
*/
readonly output: (options: StandardJsonOptions) => Record<string, unknown>;
}
/**
* The target version of the generated JSON Schema.
*/
type StandardJsonTarget = "draft-2020-12" | "draft-07" | "openapi-3.0" | ({} & string);
/**
* The options for the input/output methods.
*/
interface StandardJsonOptions {
/**
* Specifies the target version of the generated JSON Schema.
*/
readonly target: StandardJsonTarget;
/**
* Explicit support for additional vendor-specific parameters, if needed.
*/
readonly libraryOptions?: Record<string, unknown> | undefined;
}
//#endregion
//#region src/functions/toJsonSchema/toJsonSchema.d.ts
/**
* Converts a Valibot schema to the JSON Schema format.
*
* @param schema The Valibot schema object.
* @param config The JSON Schema configuration.
*
* @returns The converted JSON Schema.
*/
declare function toJsonSchema(schema: BaseSchema<unknown, unknown, BaseIssue<unknown>>, config?: ConversionConfig): JsonSchema;
//#endregion
//#region src/functions/toJsonSchemaDefs/toJsonSchemaDefs.d.ts
/**
* Converts Valibot schema definitions to JSON Schema definitions.
*
* @param definitions The Valibot schema definitions.
* @param config The JSON Schema configuration.
*
* @returns The converted JSON Schema definitions.
*/
declare function toJsonSchemaDefs<TDefinitions extends Record<string, BaseSchema<unknown, unknown, BaseIssue<unknown>>>>(definitions: TDefinitions, config?: Omit<ConversionConfig, "definitions">): { [TKey in keyof TDefinitions]: JsonSchema };
//#endregion
//#region src/functions/toStandardJsonSchema/toStandardJsonSchema.d.ts
/**
* Converts a Valibot schema to the Standard JSON Schema format.
*
* @param schema The Valibot schema object.
*
* @returns The Standard JSON Schema.
*/
declare function toStandardJsonSchema<TSchema extends BaseSchema<unknown, unknown, BaseIssue<unknown>>>(schema: TSchema): StandardJsonSchema<InferInput<TSchema>, InferOutput<TSchema>>;
//#endregion
//#region src/storages/globalDefs/globalDefs.d.ts
/**
* Adds new definitions to the global schema definitions.
*
* @param definitions The schema definitions.
*
* @beta
*/
declare function addGlobalDefs(definitions: Record<string, BaseSchema<unknown, unknown, BaseIssue<unknown>>>): void;
/**
* Returns the current global schema definitions.
*
* @returns The schema definitions.
*
* @beta
*/
declare function getGlobalDefs(): Record<string, BaseSchema<unknown, unknown, BaseIssue<unknown>>> | undefined;
//#endregion
export { ConversionConfig, ConversionContext, JSONSchema7, JsonSchema, OverrideActionContext, OverrideRefContext, OverrideSchemaContext, StandardJsonSchema, addGlobalDefs, getGlobalDefs, toJsonSchema, toJsonSchemaDefs, toStandardJsonSchema };

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,513 @@
import * as v from "valibot";
//#region src/utils/addError.ts
/**
* Adds an error message to the errors array.
*
* @param errors The array of error messages.
* @param message The error message to add.
*
* @returns The new errors.
*/
function addError(errors, message) {
if (errors) {
errors.push(message);
return errors;
}
return [message];
}
//#endregion
//#region src/utils/handleError.ts
/**
* Throws an error or logs a warning based on the configuration.
*
* @param message The message to throw or log.
* @param config The conversion configuration.
*/
function handleError(message, config) {
switch (config?.errorMode) {
case "ignore": break;
case "warn":
console.warn(message);
break;
default: throw new Error(message);
}
}
//#endregion
//#region src/converters/convertAction/convertAction.ts
/**
* Converts any supported Valibot action to the JSON Schema format.
*
* @param jsonSchema The JSON Schema object.
* @param valibotAction The Valibot action object.
* @param config The conversion configuration.
*
* @returns The converted JSON Schema.
*/
function convertAction(jsonSchema, valibotAction, config) {
if (config?.ignoreActions?.includes(valibotAction.type)) return jsonSchema;
let errors;
switch (valibotAction.type) {
case "base64":
jsonSchema.contentEncoding = "base64";
break;
case "bic":
case "cuid2":
case "decimal":
case "digits":
case "emoji":
case "hexadecimal":
case "hex_color":
case "nanoid":
case "octal":
case "ulid":
jsonSchema.pattern = valibotAction.requirement.source;
break;
case "description":
jsonSchema.description = valibotAction.description;
break;
case "email":
jsonSchema.format = "email";
break;
case "empty":
if (jsonSchema.type === "array") jsonSchema.maxItems = 0;
else {
if (jsonSchema.type !== "string") errors = addError(errors, `The "${valibotAction.type}" action is not supported on type "${jsonSchema.type}".`);
jsonSchema.maxLength = 0;
}
break;
case "entries":
jsonSchema.minProperties = valibotAction.requirement;
jsonSchema.maxProperties = valibotAction.requirement;
break;
case "examples":
if (Array.isArray(jsonSchema.examples)) jsonSchema.examples = [...jsonSchema.examples, ...valibotAction.examples];
else jsonSchema.examples = valibotAction.examples;
break;
case "integer":
jsonSchema.type = "integer";
break;
case "ipv4":
jsonSchema.format = "ipv4";
break;
case "ipv6":
jsonSchema.format = "ipv6";
break;
case "iso_date":
jsonSchema.format = "date";
break;
case "iso_date_time":
case "iso_timestamp":
jsonSchema.format = "date-time";
break;
case "iso_time":
jsonSchema.format = "time";
break;
case "length":
if (jsonSchema.type === "array") {
jsonSchema.minItems = valibotAction.requirement;
jsonSchema.maxItems = valibotAction.requirement;
} else {
if (jsonSchema.type !== "string") errors = addError(errors, `The "${valibotAction.type}" action is not supported on type "${jsonSchema.type}".`);
jsonSchema.minLength = valibotAction.requirement;
jsonSchema.maxLength = valibotAction.requirement;
}
break;
case "max_entries":
jsonSchema.maxProperties = valibotAction.requirement;
break;
case "max_length":
if (jsonSchema.type === "array") jsonSchema.maxItems = valibotAction.requirement;
else {
if (jsonSchema.type !== "string") errors = addError(errors, `The "${valibotAction.type}" action is not supported on type "${jsonSchema.type}".`);
jsonSchema.maxLength = valibotAction.requirement;
}
break;
case "max_value":
if (jsonSchema.type !== "number" && jsonSchema.type !== "integer") errors = addError(errors, `The "max_value" action is not supported on type "${jsonSchema.type}".`);
jsonSchema.maximum = valibotAction.requirement;
break;
case "metadata":
if (typeof valibotAction.metadata.title === "string") jsonSchema.title = valibotAction.metadata.title;
if (typeof valibotAction.metadata.description === "string") jsonSchema.description = valibotAction.metadata.description;
if (Array.isArray(valibotAction.metadata.examples)) if (Array.isArray(jsonSchema.examples)) jsonSchema.examples = [...jsonSchema.examples, ...valibotAction.metadata.examples];
else jsonSchema.examples = valibotAction.metadata.examples;
break;
case "min_entries":
jsonSchema.minProperties = valibotAction.requirement;
break;
case "min_length":
if (jsonSchema.type === "array") jsonSchema.minItems = valibotAction.requirement;
else {
if (jsonSchema.type !== "string") errors = addError(errors, `The "${valibotAction.type}" action is not supported on type "${jsonSchema.type}".`);
jsonSchema.minLength = valibotAction.requirement;
}
break;
case "min_value":
if (jsonSchema.type !== "number" && jsonSchema.type !== "integer") errors = addError(errors, `The "min_value" action is not supported on type "${jsonSchema.type}".`);
jsonSchema.minimum = valibotAction.requirement;
break;
case "multiple_of":
jsonSchema.multipleOf = valibotAction.requirement;
break;
case "non_empty":
if (jsonSchema.type === "array") jsonSchema.minItems = 1;
else {
if (jsonSchema.type !== "string") errors = addError(errors, `The "${valibotAction.type}" action is not supported on type "${jsonSchema.type}".`);
jsonSchema.minLength = 1;
}
break;
case "regex":
if (valibotAction.requirement.flags) errors = addError(errors, "RegExp flags are not supported by JSON Schema.");
jsonSchema.pattern = valibotAction.requirement.source;
break;
case "title":
jsonSchema.title = valibotAction.title;
break;
case "url":
jsonSchema.format = "uri";
break;
case "uuid":
jsonSchema.format = "uuid";
break;
case "value":
jsonSchema.const = valibotAction.requirement;
break;
default: errors = addError(errors, `The "${valibotAction.type}" action cannot be converted to JSON Schema.`);
}
if (config?.overrideAction) {
const actionOverride = config.overrideAction({
valibotAction,
jsonSchema,
errors
});
if (actionOverride) return { ...actionOverride };
}
if (errors) for (const message of errors) handleError(message, config);
return jsonSchema;
}
//#endregion
//#region src/converters/convertSchema/convertSchema.ts
/**
* Flattens a Valibot pipe by recursively expanding nested pipes.
*
* @param pipe The pipeline to flatten.
*
* @returns A flat pipeline.
*/
function flattenPipe(pipe) {
return pipe.flatMap((item) => "pipe" in item ? flattenPipe(item.pipe) : item);
}
let refCount = 0;
/**
* Converts any supported Valibot schema to the JSON Schema format.
*
* @param jsonSchema The JSON Schema object.
* @param valibotSchema The Valibot schema object.
* @param config The conversion configuration.
* @param context The conversion context.
* @param skipRef Whether to skip using a reference.
*
* @returns The converted JSON Schema.
*/
function convertSchema(jsonSchema, valibotSchema, config, context, skipRef = false) {
if (!skipRef) {
const referenceId = context.referenceMap.get(valibotSchema);
if (referenceId) {
jsonSchema.$ref = `#/$defs/${referenceId}`;
if (config?.overrideRef) {
const refOverride = config.overrideRef({
...context,
referenceId,
valibotSchema,
jsonSchema
});
if (refOverride) jsonSchema.$ref = refOverride;
}
return jsonSchema;
}
}
if ("pipe" in valibotSchema) {
const flatPipe = flattenPipe(valibotSchema.pipe);
let startIndex = 0;
let stopIndex = flatPipe.length - 1;
if (config?.typeMode === "input") {
const inputStopIndex = flatPipe.slice(1).findIndex((item) => item.kind === "schema" || item.kind === "transformation" && (item.type === "find_item" || item.type === "parse_json" || item.type === "raw_transform" || item.type === "reduce_items" || item.type === "stringify_json" || item.type === "to_bigint" || item.type === "to_boolean" || item.type === "to_date" || item.type === "to_number" || item.type === "to_string" || item.type === "transform"));
if (inputStopIndex !== -1) stopIndex = inputStopIndex;
} else if (config?.typeMode === "output") {
const outputStartIndex = flatPipe.findLastIndex((item) => item.kind === "schema");
if (outputStartIndex !== -1) startIndex = outputStartIndex;
}
for (let index = startIndex; index <= stopIndex; index++) {
const valibotPipeItem = flatPipe[index];
if (valibotPipeItem.kind === "schema") {
if (index > startIndex) handleError("Set the \"typeMode\" config to \"input\" or \"output\" to convert pipelines with multiple schemas.", config);
jsonSchema = convertSchema(jsonSchema, valibotPipeItem, config, context, true);
} else jsonSchema = convertAction(jsonSchema, valibotPipeItem, config);
}
return jsonSchema;
}
let errors;
switch (valibotSchema.type) {
case "boolean":
jsonSchema.type = "boolean";
break;
case "null":
if (config?.target === "openapi-3.0") jsonSchema.enum = [null];
else jsonSchema.type = "null";
break;
case "number":
jsonSchema.type = "number";
break;
case "string":
jsonSchema.type = "string";
break;
case "array":
jsonSchema.type = "array";
jsonSchema.items = convertSchema({}, valibotSchema.item, config, context);
break;
case "tuple":
case "tuple_with_rest":
case "loose_tuple":
case "strict_tuple":
jsonSchema.type = "array";
if (config?.target === "openapi-3.0") {
jsonSchema.items = { anyOf: [] };
jsonSchema.minItems = valibotSchema.items.length;
for (const item of valibotSchema.items) jsonSchema.items.anyOf.push(convertSchema({}, item, config, context));
if (valibotSchema.type === "tuple_with_rest") jsonSchema.items.anyOf.push(convertSchema({}, valibotSchema.rest, config, context));
else if (valibotSchema.type === "strict_tuple" || valibotSchema.type === "tuple") jsonSchema.maxItems = valibotSchema.items.length;
} else if (config?.target === "draft-2020-12") {
jsonSchema.prefixItems = [];
jsonSchema.minItems = valibotSchema.items.length;
for (const item of valibotSchema.items) jsonSchema.prefixItems.push(convertSchema({}, item, config, context));
if (valibotSchema.type === "tuple_with_rest") jsonSchema.items = convertSchema({}, valibotSchema.rest, config, context);
else if (valibotSchema.type === "strict_tuple") jsonSchema.items = false;
} else {
jsonSchema.items = [];
jsonSchema.minItems = valibotSchema.items.length;
for (const item of valibotSchema.items) jsonSchema.items.push(convertSchema({}, item, config, context));
if (valibotSchema.type === "tuple_with_rest") jsonSchema.additionalItems = convertSchema({}, valibotSchema.rest, config, context);
else if (valibotSchema.type === "strict_tuple") jsonSchema.additionalItems = false;
}
break;
case "object":
case "object_with_rest":
case "loose_object":
case "strict_object":
jsonSchema.type = "object";
jsonSchema.properties = {};
jsonSchema.required = [];
for (const key in valibotSchema.entries) {
const entry = valibotSchema.entries[key];
jsonSchema.properties[key] = convertSchema({}, entry, config, context);
if (entry.type !== "exact_optional" && entry.type !== "nullish" && entry.type !== "optional") jsonSchema.required.push(key);
}
if (valibotSchema.type === "object_with_rest") jsonSchema.additionalProperties = convertSchema({}, valibotSchema.rest, config, context);
else if (valibotSchema.type === "strict_object") jsonSchema.additionalProperties = false;
break;
case "record":
if (config?.target === "openapi-3.0" && "pipe" in valibotSchema.key) errors = addError(errors, "The \"record\" schema with a schema for the key that contains a \"pipe\" cannot be converted to JSON Schema.");
if (valibotSchema.key.type !== "string") errors = addError(errors, `The "record" schema with the "${valibotSchema.key.type}" schema for the key cannot be converted to JSON Schema.`);
jsonSchema.type = "object";
if (config?.target !== "openapi-3.0") jsonSchema.propertyNames = convertSchema({}, valibotSchema.key, config, context);
jsonSchema.additionalProperties = convertSchema({}, valibotSchema.value, config, context);
break;
case "any":
case "unknown": break;
case "nullable":
case "nullish":
if (config?.target === "openapi-3.0") {
const innerSchema = convertSchema({}, valibotSchema.wrapped, config, context);
Object.assign(jsonSchema, innerSchema);
jsonSchema.nullable = true;
} else jsonSchema.anyOf = [convertSchema({}, valibotSchema.wrapped, config, context), { type: "null" }];
if (valibotSchema.default !== void 0) jsonSchema.default = v.getDefault(valibotSchema);
break;
case "exact_optional":
case "optional":
case "undefinedable":
jsonSchema = convertSchema(jsonSchema, valibotSchema.wrapped, config, context);
if (valibotSchema.default !== void 0) jsonSchema.default = v.getDefault(valibotSchema);
break;
case "literal":
if (typeof valibotSchema.literal !== "boolean" && typeof valibotSchema.literal !== "number" && typeof valibotSchema.literal !== "string") errors = addError(errors, "The value of the \"literal\" schema is not JSON compatible.");
if (config?.target === "openapi-3.0") jsonSchema.enum = [valibotSchema.literal];
else jsonSchema.const = valibotSchema.literal;
break;
case "enum":
jsonSchema.enum = valibotSchema.options;
break;
case "picklist":
if (valibotSchema.options.some((option) => typeof option !== "number" && typeof option !== "string")) errors = addError(errors, "An option of the \"picklist\" schema is not JSON compatible.");
jsonSchema.enum = valibotSchema.options;
break;
case "union":
jsonSchema.anyOf = valibotSchema.options.map((option) => convertSchema({}, option, config, context));
break;
case "variant":
jsonSchema.oneOf = valibotSchema.options.map((option) => convertSchema({}, option, config, context));
break;
case "intersect":
jsonSchema.allOf = valibotSchema.options.map((option) => convertSchema({}, option, config, context));
break;
case "lazy": {
let wrappedValibotSchema = context.getterMap.get(valibotSchema.getter);
if (!wrappedValibotSchema) {
wrappedValibotSchema = valibotSchema.getter(void 0);
context.getterMap.set(valibotSchema.getter, wrappedValibotSchema);
}
let referenceId = context.referenceMap.get(wrappedValibotSchema);
if (!referenceId) {
referenceId = `${refCount++}`;
context.referenceMap.set(wrappedValibotSchema, referenceId);
context.definitions[referenceId] = convertSchema({}, wrappedValibotSchema, config, context, true);
}
jsonSchema.$ref = `#/$defs/${referenceId}`;
if (config?.overrideRef) {
const refOverride = config.overrideRef({
...context,
referenceId,
valibotSchema: wrappedValibotSchema,
jsonSchema
});
if (refOverride) jsonSchema.$ref = refOverride;
}
break;
}
default: errors = addError(errors, `The "${valibotSchema.type}" schema cannot be converted to JSON Schema.`);
}
if (config?.overrideSchema) {
const schemaOverride = config.overrideSchema({
...context,
referenceId: context.referenceMap.get(valibotSchema),
valibotSchema,
jsonSchema,
errors
});
if (schemaOverride) return { ...schemaOverride };
}
if (errors) for (const message of errors) handleError(message, config);
return jsonSchema;
}
//#endregion
//#region src/storages/globalDefs/globalDefs.ts
let store;
/**
* Adds new definitions to the global schema definitions.
*
* @param definitions The schema definitions.
*
* @beta
*/
function addGlobalDefs(definitions) {
store = {
...store ?? {},
...definitions
};
}
/**
* Returns the current global schema definitions.
*
* @returns The schema definitions.
*
* @beta
*/
function getGlobalDefs() {
return store;
}
//#endregion
//#region src/functions/toJsonSchema/toJsonSchema.ts
/**
* Converts a Valibot schema to the JSON Schema format.
*
* @param schema The Valibot schema object.
* @param config The JSON Schema configuration.
*
* @returns The converted JSON Schema.
*/
function toJsonSchema(schema, config) {
const context = {
definitions: {},
referenceMap: /* @__PURE__ */ new Map(),
getterMap: /* @__PURE__ */ new Map()
};
const definitions = config?.definitions ?? getGlobalDefs();
if (definitions) {
for (const key in definitions) context.referenceMap.set(definitions[key], key);
for (const key in definitions) context.definitions[key] = convertSchema({}, definitions[key], config, context, true);
}
const jsonSchema = convertSchema({}, schema, config, context);
const target = config?.target ?? "draft-07";
if (target === "draft-2020-12") jsonSchema.$schema = "https://json-schema.org/draft/2020-12/schema";
else if (target === "draft-07") jsonSchema.$schema = "http://json-schema.org/draft-07/schema#";
if (context.referenceMap.size) jsonSchema.$defs = context.definitions;
return jsonSchema;
}
//#endregion
//#region src/functions/toJsonSchemaDefs/toJsonSchemaDefs.ts
/**
* Converts Valibot schema definitions to JSON Schema definitions.
*
* @param definitions The Valibot schema definitions.
* @param config The JSON Schema configuration.
*
* @returns The converted JSON Schema definitions.
*/
function toJsonSchemaDefs(definitions, config) {
const context = {
definitions: {},
referenceMap: /* @__PURE__ */ new Map(),
getterMap: /* @__PURE__ */ new Map()
};
for (const key in definitions) context.referenceMap.set(definitions[key], key);
for (const key in definitions) context.definitions[key] = convertSchema({}, definitions[key], config, context, true);
return context.definitions;
}
//#endregion
//#region src/functions/toStandardJsonSchema/toStandardJsonSchema.ts
const SUPPORTED_TARGETS = [
"draft-07",
"draft-2020-12",
"openapi-3.0"
];
/**
* Converts a Valibot schema to the Standard JSON Schema format.
*
* @param schema The Valibot schema object.
*
* @returns The Standard JSON Schema.
*/
function toStandardJsonSchema(schema) {
return { "~standard": {
...schema["~standard"],
jsonSchema: {
input(options) {
if (SUPPORTED_TARGETS.includes(options.target)) return toJsonSchema(schema, {
typeMode: "input",
target: options.target,
...options.libraryOptions
});
throw new Error(`Unsupported target: ${options.target}`);
},
output(options) {
if (SUPPORTED_TARGETS.includes(options.target)) return toJsonSchema(schema, {
typeMode: "output",
target: options.target,
...options.libraryOptions
});
throw new Error(`Unsupported target: ${options.target}`);
}
}
} };
}
//#endregion
export { addGlobalDefs, getGlobalDefs, toJsonSchema, toJsonSchemaDefs, toStandardJsonSchema };