Repository: open-circle/valibot Branch: main Commit: f3f475e7711b Files: 3219 Total size: 7.0 MB Directory structure: gitextract_iir2u9y5/ ├── .agents/ │ └── skills/ │ ├── repo-source-code-document/ │ │ └── SKILL.md │ ├── repo-source-code-review/ │ │ └── SKILL.md │ ├── repo-structure-navigate/ │ │ └── SKILL.md │ ├── repo-website-api-create/ │ │ └── SKILL.md │ ├── repo-website-api-update/ │ │ └── SKILL.md │ └── repo-website-guide-create/ │ └── SKILL.md ├── .github/ │ ├── FUNDING.yml │ ├── actions/ │ │ └── environment/ │ │ └── action.yml │ └── workflows/ │ ├── ci.yml │ └── publish.yml ├── .gitignore ├── .grit/ │ ├── .gitignore │ ├── grit.yaml │ └── patterns/ │ └── migrate_to_v0_31_0.md ├── .prettierignore ├── AGENTS.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── SECURITY.md ├── codemod/ │ ├── README.md │ ├── migrate-to-v0.31.0/ │ │ ├── .codemodrc.json │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── README.md │ │ ├── __testfixtures__/ │ │ │ ├── fixture1.input.ts │ │ │ ├── fixture1.output.ts │ │ │ ├── fixture10.input.ts │ │ │ ├── fixture10.output.ts │ │ │ ├── fixture11.input.ts │ │ │ ├── fixture11.output.ts │ │ │ ├── fixture12.input.ts │ │ │ ├── fixture12.output.ts │ │ │ ├── fixture13.input.ts │ │ │ ├── fixture13.output.ts │ │ │ ├── fixture14.input.ts │ │ │ ├── fixture14.output.ts │ │ │ ├── fixture15.input.ts │ │ │ ├── fixture15.output.ts │ │ │ ├── fixture16.input.ts │ │ │ ├── fixture16.output.ts │ │ │ ├── fixture17.input.ts │ │ │ ├── fixture17.output.ts │ │ │ ├── fixture2.input.ts │ │ │ ├── fixture2.output.ts │ │ │ ├── fixture3.input.ts │ │ │ ├── fixture3.output.ts │ │ │ ├── fixture4.input.ts │ │ │ ├── fixture4.output.ts │ │ │ ├── fixture5.input.ts │ │ │ ├── fixture5.output.ts │ │ │ ├── fixture6.input.ts │ │ │ ├── fixture6.output.ts │ │ │ ├── fixture7.input.ts │ │ │ ├── fixture7.output.ts │ │ │ ├── fixture8.input.ts │ │ │ ├── fixture8.output.ts │ │ │ ├── fixture9.input.ts │ │ │ └── fixture9.output.ts │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ └── zod-to-valibot/ │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── __testfixtures__/ │ │ ├── any-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── array-element/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── array-nonempty/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── array-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── array-validation-methods/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── bigint-validation-methods/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── coerce-bigint-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── coerce-boolean-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── coerce-date-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── coerce-number-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── coerce-string-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── custom-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── date-validation-methods/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── default/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── default-import/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── default-import-with-alias/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── default-import-with-specific-alias/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── describe/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── discriminated-union-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── instanceof-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── intersection-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── literal-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── map-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── multiple-imports-from-zod/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── named-import/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── named-import-with-alias/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── named-import-with-specific-alias/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── namespace-import/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── nan-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── native-enum/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── never-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── null-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── nullable-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── nullish-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── number-validation-methods/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── object-catchall/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── object-deepPartial/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── object-extend/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── object-keyof/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── object-merge/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── object-omit/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── object-partial/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── object-passthrough/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── object-pick/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── object-required/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── object-shape/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── object-strict/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── object-strip/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── optional-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── or/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── parsing/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── readonly/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── record-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── refine/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── schema-chain/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── schema-options/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── set-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── set-validation-methods/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── specific-default-import/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── specific-namespace-import/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── string-validation-methods/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── symbol-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── transform/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── tuple-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── type-inference/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── undefined-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── union-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── unknown-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── validation-error-msg/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ ├── void-schema/ │ │ │ ├── input.ts │ │ │ └── output.ts │ │ └── zod-enum/ │ │ ├── input.ts │ │ └── output.ts │ ├── cli.mjs │ ├── package.json │ ├── src/ │ │ ├── test-setup.test.ts │ │ ├── transform/ │ │ │ ├── imports/ │ │ │ │ ├── imports.ts │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ └── schemas-and-links/ │ │ │ ├── constants.ts │ │ │ ├── helpers.ts │ │ │ ├── index.ts │ │ │ ├── methods/ │ │ │ │ ├── array/ │ │ │ │ │ ├── array.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── catchall/ │ │ │ │ │ ├── catchall.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── deepPartial/ │ │ │ │ │ ├── deepPartial.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── default/ │ │ │ │ │ ├── default.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── exclude/ │ │ │ │ │ ├── exclude.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── extend/ │ │ │ │ │ ├── extend.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── extract/ │ │ │ │ │ ├── extract.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ ├── keyof/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── keyof.ts │ │ │ │ ├── merge/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── merge.ts │ │ │ │ ├── nullable/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── nullable.ts │ │ │ │ ├── nullish/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── nullish.ts │ │ │ │ ├── omit/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── omit.ts │ │ │ │ ├── optional/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── optional.ts │ │ │ │ ├── or/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── or.ts │ │ │ │ ├── parse/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── parse.ts │ │ │ │ ├── parseAsync/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── parseAsync.ts │ │ │ │ ├── partial/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── partial.ts │ │ │ │ ├── passthrough/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── passthrough.ts │ │ │ │ ├── pick/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── pick.ts │ │ │ │ ├── refine/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── refine.ts │ │ │ │ ├── required/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── required.ts │ │ │ │ ├── rest/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── rest.ts │ │ │ │ ├── safeParse/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── safeParse.ts │ │ │ │ ├── safeParseAsync/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── safeParseAsync.ts │ │ │ │ ├── strict/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── strict.ts │ │ │ │ ├── strip/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── strip.ts │ │ │ │ ├── transform/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── transform.ts │ │ │ │ └── unwrap/ │ │ │ │ ├── index.ts │ │ │ │ └── unwrap.ts │ │ │ ├── properties/ │ │ │ │ ├── description.ts │ │ │ │ ├── element.ts │ │ │ │ ├── index.ts │ │ │ │ └── shape.ts │ │ │ ├── schemas/ │ │ │ │ ├── any/ │ │ │ │ │ ├── any.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── array/ │ │ │ │ │ ├── array.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── bigint/ │ │ │ │ │ ├── bigint.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── boolean/ │ │ │ │ │ ├── boolean.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── custom/ │ │ │ │ │ ├── custom.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── date/ │ │ │ │ │ ├── date.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── discriminatedUnion/ │ │ │ │ │ ├── discriminatedUnion.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── enum/ │ │ │ │ │ ├── enum.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── helpers.ts │ │ │ │ ├── index.ts │ │ │ │ ├── instanceof/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── instanceof.ts │ │ │ │ ├── intersection/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── intersection.ts │ │ │ │ ├── literal/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── literal.ts │ │ │ │ ├── map/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── map.ts │ │ │ │ ├── nan/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── nan.ts │ │ │ │ ├── nativeEnum/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── nativeEnum.ts │ │ │ │ ├── never/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── never.ts │ │ │ │ ├── null/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── null.ts │ │ │ │ ├── nullable/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── nullable.ts │ │ │ │ ├── number/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── number.ts │ │ │ │ ├── object/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── object.ts │ │ │ │ ├── optional/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── optional.ts │ │ │ │ ├── record/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── record.ts │ │ │ │ ├── set/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── set.ts │ │ │ │ ├── string/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── string.ts │ │ │ │ ├── symbol/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── symbol.ts │ │ │ │ ├── tuple/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── tuple.ts │ │ │ │ ├── types.ts │ │ │ │ ├── undefined/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── undefined.ts │ │ │ │ ├── union/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── union.ts │ │ │ │ ├── unknown/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── unknown.ts │ │ │ │ └── void/ │ │ │ │ ├── index.ts │ │ │ │ └── void.ts │ │ │ ├── schemas-and-links.ts │ │ │ ├── types.ts │ │ │ └── validators/ │ │ │ ├── base64/ │ │ │ │ ├── base64.ts │ │ │ │ └── index.ts │ │ │ ├── cuid2/ │ │ │ │ ├── cuid2.ts │ │ │ │ └── index.ts │ │ │ ├── date/ │ │ │ │ ├── date.ts │ │ │ │ └── index.ts │ │ │ ├── datetime/ │ │ │ │ ├── datetime.ts │ │ │ │ └── index.ts │ │ │ ├── describe/ │ │ │ │ ├── describe.ts │ │ │ │ └── index.ts │ │ │ ├── email/ │ │ │ │ ├── email.ts │ │ │ │ └── index.ts │ │ │ ├── emoji/ │ │ │ │ ├── emoji.ts │ │ │ │ └── index.ts │ │ │ ├── endsWith/ │ │ │ │ ├── endsWith.ts │ │ │ │ └── index.ts │ │ │ ├── finite/ │ │ │ │ ├── finite.ts │ │ │ │ └── index.ts │ │ │ ├── gt/ │ │ │ │ ├── gt.ts │ │ │ │ └── index.ts │ │ │ ├── gte/ │ │ │ │ ├── gte.ts │ │ │ │ └── index.ts │ │ │ ├── helpers.ts │ │ │ ├── includes/ │ │ │ │ ├── includes.ts │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── int/ │ │ │ │ ├── index.ts │ │ │ │ └── int.ts │ │ │ ├── ip/ │ │ │ │ ├── index.ts │ │ │ │ └── ip.ts │ │ │ ├── length/ │ │ │ │ ├── index.ts │ │ │ │ └── length.ts │ │ │ ├── lt/ │ │ │ │ ├── index.ts │ │ │ │ └── lt.ts │ │ │ ├── lte/ │ │ │ │ ├── index.ts │ │ │ │ └── lte.ts │ │ │ ├── max/ │ │ │ │ ├── index.ts │ │ │ │ └── max.ts │ │ │ ├── min/ │ │ │ │ ├── index.ts │ │ │ │ └── min.ts │ │ │ ├── multipleOf/ │ │ │ │ ├── index.ts │ │ │ │ └── multipleOf.ts │ │ │ ├── nanoid/ │ │ │ │ ├── index.ts │ │ │ │ └── nanoid.ts │ │ │ ├── negative/ │ │ │ │ ├── index.ts │ │ │ │ └── negative.ts │ │ │ ├── nonempty/ │ │ │ │ ├── index.ts │ │ │ │ └── nonempty.ts │ │ │ ├── nonnegative/ │ │ │ │ ├── index.ts │ │ │ │ └── nonnegative.ts │ │ │ ├── nonpositive/ │ │ │ │ ├── index.ts │ │ │ │ └── nonpositive.ts │ │ │ ├── positive/ │ │ │ │ ├── index.ts │ │ │ │ └── positive.ts │ │ │ ├── readonly/ │ │ │ │ ├── index.ts │ │ │ │ └── readonly.ts │ │ │ ├── regex/ │ │ │ │ ├── index.ts │ │ │ │ └── regex.ts │ │ │ ├── safe/ │ │ │ │ ├── index.ts │ │ │ │ └── safe.ts │ │ │ ├── size/ │ │ │ │ ├── index.ts │ │ │ │ └── size.ts │ │ │ ├── startsWith/ │ │ │ │ ├── index.ts │ │ │ │ └── startsWith.ts │ │ │ ├── time/ │ │ │ │ ├── index.ts │ │ │ │ └── time.ts │ │ │ ├── toLowerCase/ │ │ │ │ ├── index.ts │ │ │ │ └── toLowerCase.ts │ │ │ ├── toUpperCase/ │ │ │ │ ├── index.ts │ │ │ │ └── toUpperCase.ts │ │ │ ├── trim/ │ │ │ │ ├── index.ts │ │ │ │ └── trim.ts │ │ │ ├── ulid/ │ │ │ │ ├── index.ts │ │ │ │ └── ulid.ts │ │ │ ├── url/ │ │ │ │ ├── index.ts │ │ │ │ └── url.ts │ │ │ └── uuid/ │ │ │ ├── index.ts │ │ │ └── uuid.ts │ │ └── utils.ts │ ├── tsconfig.json │ └── tsdown.config.ts ├── library/ │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── eslint.config.js │ ├── jsr.json │ ├── mod.ts │ ├── package.json │ ├── playground.ts │ ├── src/ │ │ ├── actions/ │ │ │ ├── args/ │ │ │ │ ├── args.test-d.ts │ │ │ │ ├── args.test.ts │ │ │ │ ├── args.ts │ │ │ │ ├── argsAsync.test-d.ts │ │ │ │ ├── argsAsync.test.ts │ │ │ │ ├── argsAsync.ts │ │ │ │ └── index.ts │ │ │ ├── await/ │ │ │ │ ├── awaitAsync.test-d.ts │ │ │ │ ├── awaitAsync.test.ts │ │ │ │ ├── awaitAsync.ts │ │ │ │ └── index.ts │ │ │ ├── base64/ │ │ │ │ ├── base64.test-d.ts │ │ │ │ ├── base64.test.ts │ │ │ │ ├── base64.ts │ │ │ │ └── index.ts │ │ │ ├── bic/ │ │ │ │ ├── bic.test-d.ts │ │ │ │ ├── bic.test.ts │ │ │ │ ├── bic.ts │ │ │ │ └── index.ts │ │ │ ├── brand/ │ │ │ │ ├── brand.test-d.ts │ │ │ │ ├── brand.test.ts │ │ │ │ ├── brand.ts │ │ │ │ └── index.ts │ │ │ ├── bytes/ │ │ │ │ ├── bytes.test-d.ts │ │ │ │ ├── bytes.test.ts │ │ │ │ ├── bytes.ts │ │ │ │ └── index.ts │ │ │ ├── check/ │ │ │ │ ├── check.test-d.ts │ │ │ │ ├── check.test.ts │ │ │ │ ├── check.ts │ │ │ │ ├── checkAsync.test-d.ts │ │ │ │ ├── checkAsync.test.ts │ │ │ │ ├── checkAsync.ts │ │ │ │ ├── index.ts │ │ │ │ └── types.ts │ │ │ ├── checkItems/ │ │ │ │ ├── checkItems.test-d.ts │ │ │ │ ├── checkItems.test.ts │ │ │ │ ├── checkItems.ts │ │ │ │ ├── checkItemsAsync.test-d.ts │ │ │ │ ├── checkItemsAsync.test.ts │ │ │ │ ├── checkItemsAsync.ts │ │ │ │ ├── index.ts │ │ │ │ └── types.ts │ │ │ ├── creditCard/ │ │ │ │ ├── creditCard.test-d.ts │ │ │ │ ├── creditCard.test.ts │ │ │ │ ├── creditCard.ts │ │ │ │ └── index.ts │ │ │ ├── cuid2/ │ │ │ │ ├── cuid2.test-d.ts │ │ │ │ ├── cuid2.test.ts │ │ │ │ ├── cuid2.ts │ │ │ │ └── index.ts │ │ │ ├── decimal/ │ │ │ │ ├── decimal.test-d.ts │ │ │ │ ├── decimal.test.ts │ │ │ │ ├── decimal.ts │ │ │ │ └── index.ts │ │ │ ├── description/ │ │ │ │ ├── description.test-d.ts │ │ │ │ ├── description.test.ts │ │ │ │ ├── description.ts │ │ │ │ └── index.ts │ │ │ ├── digits/ │ │ │ │ ├── digits.test-d.ts │ │ │ │ ├── digits.test.ts │ │ │ │ ├── digits.ts │ │ │ │ └── index.ts │ │ │ ├── domain/ │ │ │ │ ├── domain.test-d.ts │ │ │ │ ├── domain.test.ts │ │ │ │ ├── domain.ts │ │ │ │ └── index.ts │ │ │ ├── email/ │ │ │ │ ├── email.test-d.ts │ │ │ │ ├── email.test.ts │ │ │ │ ├── email.ts │ │ │ │ └── index.ts │ │ │ ├── emoji/ │ │ │ │ ├── emoji.test-d.ts │ │ │ │ ├── emoji.test.ts │ │ │ │ ├── emoji.ts │ │ │ │ └── index.ts │ │ │ ├── empty/ │ │ │ │ ├── empty.test-d.ts │ │ │ │ ├── empty.test.ts │ │ │ │ ├── empty.ts │ │ │ │ └── index.ts │ │ │ ├── endsWith/ │ │ │ │ ├── endsWith.test-d.ts │ │ │ │ ├── endsWith.test.ts │ │ │ │ ├── endsWith.ts │ │ │ │ └── index.ts │ │ │ ├── entries/ │ │ │ │ ├── entries.test-d.ts │ │ │ │ ├── entries.test.ts │ │ │ │ ├── entries.ts │ │ │ │ └── index.ts │ │ │ ├── everyItem/ │ │ │ │ ├── everyItem.test-d.ts │ │ │ │ ├── everyItem.test.ts │ │ │ │ ├── everyItem.ts │ │ │ │ └── index.ts │ │ │ ├── examples/ │ │ │ │ ├── examples.test-d.ts │ │ │ │ ├── examples.test.ts │ │ │ │ ├── examples.ts │ │ │ │ └── index.ts │ │ │ ├── excludes/ │ │ │ │ ├── excludes.test-d.ts │ │ │ │ ├── excludes.test.ts │ │ │ │ ├── excludes.ts │ │ │ │ └── index.ts │ │ │ ├── filterItems/ │ │ │ │ ├── filterItems.test-d.ts │ │ │ │ ├── filterItems.test.ts │ │ │ │ ├── filterItems.ts │ │ │ │ └── index.ts │ │ │ ├── findItem/ │ │ │ │ ├── findItem.test-d.ts │ │ │ │ ├── findItem.test.ts │ │ │ │ ├── findItem.ts │ │ │ │ └── index.ts │ │ │ ├── finite/ │ │ │ │ ├── finite.test-d.ts │ │ │ │ ├── finite.test.ts │ │ │ │ ├── finite.ts │ │ │ │ └── index.ts │ │ │ ├── flavor/ │ │ │ │ ├── flavor.test-d.ts │ │ │ │ ├── flavor.test.ts │ │ │ │ ├── flavor.ts │ │ │ │ └── index.ts │ │ │ ├── graphemes/ │ │ │ │ ├── graphemes.test-d.ts │ │ │ │ ├── graphemes.test.ts │ │ │ │ ├── graphemes.ts │ │ │ │ └── index.ts │ │ │ ├── gtValue/ │ │ │ │ ├── gtValue.test.ts │ │ │ │ ├── gtValue.ts │ │ │ │ ├── gtValues.test-d.ts │ │ │ │ └── index.ts │ │ │ ├── guard/ │ │ │ │ ├── guard.test-d.ts │ │ │ │ ├── guard.test.ts │ │ │ │ ├── guard.ts │ │ │ │ └── index.ts │ │ │ ├── hash/ │ │ │ │ ├── hash.test-d.ts │ │ │ │ ├── hash.test.ts │ │ │ │ ├── hash.ts │ │ │ │ └── index.ts │ │ │ ├── hexColor/ │ │ │ │ ├── hexColor.test-d.ts │ │ │ │ ├── hexColor.test.ts │ │ │ │ ├── hexColor.ts │ │ │ │ └── index.ts │ │ │ ├── hexadecimal/ │ │ │ │ ├── hexadecimal.test-d.ts │ │ │ │ ├── hexadecimal.test.ts │ │ │ │ ├── hexadecimal.ts │ │ │ │ └── index.ts │ │ │ ├── imei/ │ │ │ │ ├── imei.test-d.ts │ │ │ │ ├── imei.test.ts │ │ │ │ ├── imei.ts │ │ │ │ └── index.ts │ │ │ ├── includes/ │ │ │ │ ├── includes.test-d.ts │ │ │ │ ├── includes.test.ts │ │ │ │ ├── includes.ts │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── integer/ │ │ │ │ ├── index.ts │ │ │ │ ├── integer.test-d.ts │ │ │ │ ├── integer.test.ts │ │ │ │ └── integer.ts │ │ │ ├── ip/ │ │ │ │ ├── index.ts │ │ │ │ ├── ip.test-d.ts │ │ │ │ ├── ip.test.ts │ │ │ │ └── ip.ts │ │ │ ├── ipv4/ │ │ │ │ ├── index.ts │ │ │ │ ├── ipv4.test-d.ts │ │ │ │ ├── ipv4.test.ts │ │ │ │ └── ipv4.ts │ │ │ ├── ipv6/ │ │ │ │ ├── index.ts │ │ │ │ ├── ipv6.test-d.ts │ │ │ │ ├── ipv6.test.ts │ │ │ │ └── ipv6.ts │ │ │ ├── isbn/ │ │ │ │ ├── index.ts │ │ │ │ ├── isbn.test-d.ts │ │ │ │ ├── isbn.test.ts │ │ │ │ ├── isbn.ts │ │ │ │ └── utils/ │ │ │ │ ├── _isIsbn10.test.ts │ │ │ │ ├── _isIsbn10.ts │ │ │ │ ├── _isIsbn13.test.ts │ │ │ │ ├── _isIsbn13.ts │ │ │ │ └── index.ts │ │ │ ├── isoDate/ │ │ │ │ ├── index.ts │ │ │ │ ├── isoDate.test-d.ts │ │ │ │ ├── isoDate.test.ts │ │ │ │ └── isoDate.ts │ │ │ ├── isoDateTime/ │ │ │ │ ├── index.ts │ │ │ │ ├── isoDateTime.test-d.ts │ │ │ │ ├── isoDateTime.test.ts │ │ │ │ └── isoDateTime.ts │ │ │ ├── isoTime/ │ │ │ │ ├── index.ts │ │ │ │ ├── isoTime.test-d.ts │ │ │ │ ├── isoTime.test.ts │ │ │ │ └── isoTime.ts │ │ │ ├── isoTimeSecond/ │ │ │ │ ├── index.ts │ │ │ │ ├── isoTimeSecond.test-d.ts │ │ │ │ ├── isoTimeSecond.test.ts │ │ │ │ └── isoTimeSecond.ts │ │ │ ├── isoTimestamp/ │ │ │ │ ├── index.ts │ │ │ │ ├── isoTimestamp.test-d.ts │ │ │ │ ├── isoTimestamp.test.ts │ │ │ │ └── isoTimestamp.ts │ │ │ ├── isoWeek/ │ │ │ │ ├── index.ts │ │ │ │ ├── isoWeek.test-d.ts │ │ │ │ ├── isoWeek.test.ts │ │ │ │ └── isoWeek.ts │ │ │ ├── isrc/ │ │ │ │ ├── index.ts │ │ │ │ ├── isrc.test-d.ts │ │ │ │ ├── isrc.test.ts │ │ │ │ └── isrc.ts │ │ │ ├── jwsCompact/ │ │ │ │ ├── index.ts │ │ │ │ ├── jwsCompact.test-d.ts │ │ │ │ ├── jwsCompact.test.ts │ │ │ │ └── jwsCompact.ts │ │ │ ├── length/ │ │ │ │ ├── index.ts │ │ │ │ ├── length.test-d.ts │ │ │ │ ├── length.test.ts │ │ │ │ └── length.ts │ │ │ ├── ltValue/ │ │ │ │ ├── index.ts │ │ │ │ ├── ltValue.test-d.ts │ │ │ │ ├── ltValue.test.ts │ │ │ │ └── ltValue.ts │ │ │ ├── mac/ │ │ │ │ ├── index.ts │ │ │ │ ├── mac.test-d.ts │ │ │ │ ├── mac.test.ts │ │ │ │ └── mac.ts │ │ │ ├── mac48/ │ │ │ │ ├── index.ts │ │ │ │ ├── mac48.test-d.ts │ │ │ │ ├── mac48.test.ts │ │ │ │ └── mac48.ts │ │ │ ├── mac64/ │ │ │ │ ├── index.ts │ │ │ │ ├── mac64.test-d.ts │ │ │ │ ├── mac64.test.ts │ │ │ │ └── mac64.ts │ │ │ ├── mapItems/ │ │ │ │ ├── index.ts │ │ │ │ ├── mapItems.test-d.ts │ │ │ │ ├── mapItems.test.ts │ │ │ │ └── mapItems.ts │ │ │ ├── maxBytes/ │ │ │ │ ├── index.ts │ │ │ │ ├── maxBytes.test-d.ts │ │ │ │ ├── maxBytes.test.ts │ │ │ │ └── maxBytes.ts │ │ │ ├── maxEntries/ │ │ │ │ ├── index.ts │ │ │ │ ├── maxEntries.test-d.ts │ │ │ │ ├── maxEntries.test.ts │ │ │ │ └── maxEntries.ts │ │ │ ├── maxGraphemes/ │ │ │ │ ├── index.ts │ │ │ │ ├── maxGraphemes.test-d.ts │ │ │ │ ├── maxGraphemes.test.ts │ │ │ │ └── maxGraphemes.ts │ │ │ ├── maxLength/ │ │ │ │ ├── index.ts │ │ │ │ ├── maxLength.test-d.ts │ │ │ │ ├── maxLength.test.ts │ │ │ │ └── maxLength.ts │ │ │ ├── maxSize/ │ │ │ │ ├── index.ts │ │ │ │ ├── maxSize.test-d.ts │ │ │ │ ├── maxSize.test.ts │ │ │ │ └── maxSize.ts │ │ │ ├── maxValue/ │ │ │ │ ├── index.ts │ │ │ │ ├── maxValue.test-d.ts │ │ │ │ ├── maxValue.test.ts │ │ │ │ └── maxValue.ts │ │ │ ├── maxWords/ │ │ │ │ ├── index.ts │ │ │ │ ├── maxWords.test-d.ts │ │ │ │ ├── maxWords.test.ts │ │ │ │ └── maxWords.ts │ │ │ ├── metadata/ │ │ │ │ ├── index.ts │ │ │ │ ├── metadata.test-d.ts │ │ │ │ ├── metadata.test.ts │ │ │ │ └── metadata.ts │ │ │ ├── mimeType/ │ │ │ │ ├── index.ts │ │ │ │ ├── mimeType.test-d.ts │ │ │ │ ├── mimeType.test.ts │ │ │ │ └── mimeType.ts │ │ │ ├── minBytes/ │ │ │ │ ├── index.ts │ │ │ │ ├── minBytes.test-d.ts │ │ │ │ ├── minBytes.test.ts │ │ │ │ └── minBytes.ts │ │ │ ├── minEntries/ │ │ │ │ ├── index.ts │ │ │ │ ├── minEntries.test-d.ts │ │ │ │ ├── minEntries.test.ts │ │ │ │ └── minEntries.ts │ │ │ ├── minGraphemes/ │ │ │ │ ├── index.ts │ │ │ │ ├── minGraphemes.test-d.ts │ │ │ │ ├── minGraphemes.test.ts │ │ │ │ └── minGraphemes.ts │ │ │ ├── minLength/ │ │ │ │ ├── index.ts │ │ │ │ ├── minLength.test-d.ts │ │ │ │ ├── minLength.test.ts │ │ │ │ └── minLength.ts │ │ │ ├── minSize/ │ │ │ │ ├── index.ts │ │ │ │ ├── minSize.test-d.ts │ │ │ │ ├── minSize.test.ts │ │ │ │ └── minSize.ts │ │ │ ├── minValue/ │ │ │ │ ├── index.ts │ │ │ │ ├── minValue.test-d.ts │ │ │ │ ├── minValue.test.ts │ │ │ │ └── minValue.ts │ │ │ ├── minWords/ │ │ │ │ ├── index.ts │ │ │ │ ├── minWords.test-d.ts │ │ │ │ ├── minWords.test.ts │ │ │ │ └── minWords.ts │ │ │ ├── multipleOf/ │ │ │ │ ├── index.ts │ │ │ │ ├── multipleOf.test-d.ts │ │ │ │ ├── multipleOf.test.ts │ │ │ │ └── multipleOf.ts │ │ │ ├── nanoid/ │ │ │ │ ├── index.ts │ │ │ │ ├── nanoid.test-d.ts │ │ │ │ ├── nanoid.test.ts │ │ │ │ └── nanoid.ts │ │ │ ├── nonEmpty/ │ │ │ │ ├── index.ts │ │ │ │ ├── nonEmpty.test-d.ts │ │ │ │ ├── nonEmpty.test.ts │ │ │ │ └── nonEmpty.ts │ │ │ ├── normalize/ │ │ │ │ ├── index.ts │ │ │ │ ├── normalize.test-d.ts │ │ │ │ ├── normalize.test.ts │ │ │ │ └── normalize.ts │ │ │ ├── notBytes/ │ │ │ │ ├── index.ts │ │ │ │ ├── notBytes.test-d.ts │ │ │ │ ├── notBytes.test.ts │ │ │ │ └── notBytes.ts │ │ │ ├── notEntries/ │ │ │ │ ├── index.ts │ │ │ │ ├── notEntries.test-d.ts │ │ │ │ ├── notEntries.test.ts │ │ │ │ └── notEntries.ts │ │ │ ├── notGraphemes/ │ │ │ │ ├── index.ts │ │ │ │ ├── notGraphemes.test-d.ts │ │ │ │ ├── notGraphemes.test.ts │ │ │ │ └── notGraphemes.ts │ │ │ ├── notLength/ │ │ │ │ ├── index.ts │ │ │ │ ├── notLength.test-d.ts │ │ │ │ ├── notLength.test.ts │ │ │ │ └── notLength.ts │ │ │ ├── notSize/ │ │ │ │ ├── index.ts │ │ │ │ ├── notSize.test-d.ts │ │ │ │ ├── notSize.test.ts │ │ │ │ └── notSize.ts │ │ │ ├── notValue/ │ │ │ │ ├── index.ts │ │ │ │ ├── notValue.test-d.ts │ │ │ │ ├── notValue.test.ts │ │ │ │ └── notValue.ts │ │ │ ├── notValues/ │ │ │ │ ├── index.ts │ │ │ │ ├── notValues.test-d.ts │ │ │ │ ├── notValues.test.ts │ │ │ │ └── notValues.ts │ │ │ ├── notWords/ │ │ │ │ ├── index.ts │ │ │ │ ├── notWords.test-d.ts │ │ │ │ ├── notWords.test.ts │ │ │ │ └── notWords.ts │ │ │ ├── octal/ │ │ │ │ ├── index.ts │ │ │ │ ├── octal.test-d.ts │ │ │ │ ├── octal.test.ts │ │ │ │ └── octal.ts │ │ │ ├── parseBoolean/ │ │ │ │ ├── index.ts │ │ │ │ ├── parseBoolean.test-d.ts │ │ │ │ ├── parseBoolean.test.ts │ │ │ │ └── parseBoolean.ts │ │ │ ├── parseJson/ │ │ │ │ ├── index.ts │ │ │ │ ├── parseJson.test-d.ts │ │ │ │ ├── parseJson.test.ts │ │ │ │ └── parseJson.ts │ │ │ ├── partialCheck/ │ │ │ │ ├── index.ts │ │ │ │ ├── partialCheck.test-d.ts │ │ │ │ ├── partialCheck.test.ts │ │ │ │ ├── partialCheck.ts │ │ │ │ ├── partialCheckAsync.test-d.ts │ │ │ │ ├── partialCheckAsync.test.ts │ │ │ │ ├── partialCheckAsync.ts │ │ │ │ ├── types.ts │ │ │ │ └── utils/ │ │ │ │ ├── _isPartiallyTyped/ │ │ │ │ │ ├── _isPartiallyTyped.test.ts │ │ │ │ │ ├── _isPartiallyTyped.ts │ │ │ │ │ └── index.ts │ │ │ │ └── index.ts │ │ │ ├── rawCheck/ │ │ │ │ ├── index.ts │ │ │ │ ├── rawCheck.test-d.ts │ │ │ │ ├── rawCheck.test.ts │ │ │ │ ├── rawCheck.ts │ │ │ │ ├── rawCheckAsync.test-d.ts │ │ │ │ ├── rawCheckAsync.test.ts │ │ │ │ ├── rawCheckAsync.ts │ │ │ │ └── types.ts │ │ │ ├── rawTransform/ │ │ │ │ ├── index.ts │ │ │ │ ├── rawTransform.test-d.ts │ │ │ │ ├── rawTransform.test.ts │ │ │ │ ├── rawTransform.ts │ │ │ │ ├── rawTransformAsync.test-d.ts │ │ │ │ ├── rawTransformAsync.test.ts │ │ │ │ ├── rawTransformAsync.ts │ │ │ │ └── types.ts │ │ │ ├── readonly/ │ │ │ │ ├── index.ts │ │ │ │ ├── readonly.test-d.ts │ │ │ │ ├── readonly.test.ts │ │ │ │ └── readonly.ts │ │ │ ├── reduceItems/ │ │ │ │ ├── index.ts │ │ │ │ ├── reduceItems.test-d.ts │ │ │ │ ├── reduceItems.test.ts │ │ │ │ └── reduceItems.ts │ │ │ ├── regex/ │ │ │ │ ├── index.ts │ │ │ │ ├── regex.test-d.ts │ │ │ │ ├── regex.test.ts │ │ │ │ └── regex.ts │ │ │ ├── returns/ │ │ │ │ ├── index.ts │ │ │ │ ├── returns.test-d.ts │ │ │ │ ├── returns.test.ts │ │ │ │ ├── returns.ts │ │ │ │ ├── returnsAsync.test-d.ts │ │ │ │ ├── returnsAsync.test.ts │ │ │ │ └── returnsAsync.ts │ │ │ ├── rfcEmail/ │ │ │ │ ├── index.ts │ │ │ │ ├── rfcEmail.test-d.ts │ │ │ │ ├── rfcEmail.test.ts │ │ │ │ └── rfcEmail.ts │ │ │ ├── safeInteger/ │ │ │ │ ├── index.ts │ │ │ │ ├── safeInteger.test-d.ts │ │ │ │ ├── safeInteger.test.ts │ │ │ │ └── safeInteger.ts │ │ │ ├── size/ │ │ │ │ ├── index.ts │ │ │ │ ├── size.test-d.ts │ │ │ │ ├── size.test.ts │ │ │ │ └── size.ts │ │ │ ├── slug/ │ │ │ │ ├── index.ts │ │ │ │ ├── slug.test-d.ts │ │ │ │ ├── slug.test.ts │ │ │ │ └── slug.ts │ │ │ ├── someItem/ │ │ │ │ ├── index.ts │ │ │ │ ├── someItem.test-d.ts │ │ │ │ ├── someItem.test.ts │ │ │ │ └── someItem.ts │ │ │ ├── sortItems/ │ │ │ │ ├── index.ts │ │ │ │ ├── sortItems.test-d.ts │ │ │ │ ├── sortItems.test.ts │ │ │ │ └── sortItems.ts │ │ │ ├── startsWith/ │ │ │ │ ├── index.ts │ │ │ │ ├── startsWith.test-d.ts │ │ │ │ ├── startsWith.test.ts │ │ │ │ └── startsWith.ts │ │ │ ├── stringifyJson/ │ │ │ │ ├── index.ts │ │ │ │ ├── stringifyJson.test-d.ts │ │ │ │ ├── stringifyJson.test.ts │ │ │ │ └── stringifyJson.ts │ │ │ ├── title/ │ │ │ │ ├── index.ts │ │ │ │ ├── title.test-d.ts │ │ │ │ ├── title.test.ts │ │ │ │ └── title.ts │ │ │ ├── toBigint/ │ │ │ │ ├── index.ts │ │ │ │ ├── toBigint.test-d.ts │ │ │ │ ├── toBigint.test.ts │ │ │ │ └── toBigint.ts │ │ │ ├── toBoolean/ │ │ │ │ ├── index.ts │ │ │ │ ├── toBoolean.test-d.ts │ │ │ │ ├── toBoolean.test.ts │ │ │ │ └── toBoolean.ts │ │ │ ├── toDate/ │ │ │ │ ├── index.ts │ │ │ │ ├── toDate.test-d.ts │ │ │ │ ├── toDate.test.ts │ │ │ │ └── toDate.ts │ │ │ ├── toLowerCase/ │ │ │ │ ├── index.ts │ │ │ │ ├── toLowerCase.test-d.ts │ │ │ │ ├── toLowerCase.test.ts │ │ │ │ └── toLowerCase.ts │ │ │ ├── toMaxValue/ │ │ │ │ ├── index.ts │ │ │ │ ├── toMaxValue.test-d.ts │ │ │ │ ├── toMaxValue.test.ts │ │ │ │ └── toMaxValue.ts │ │ │ ├── toMinValue/ │ │ │ │ ├── index.ts │ │ │ │ ├── toMinValue.test-d.ts │ │ │ │ ├── toMinValue.test.ts │ │ │ │ └── toMinValue.ts │ │ │ ├── toNumber/ │ │ │ │ ├── index.ts │ │ │ │ ├── toNumber.test-d.ts │ │ │ │ ├── toNumber.test.ts │ │ │ │ └── toNumber.ts │ │ │ ├── toString/ │ │ │ │ ├── index.ts │ │ │ │ ├── toString.test-d.ts │ │ │ │ ├── toString.test.ts │ │ │ │ └── toString.ts │ │ │ ├── toUpperCase/ │ │ │ │ ├── index.ts │ │ │ │ ├── toUpperCase.test-d.ts │ │ │ │ ├── toUpperCase.test.ts │ │ │ │ └── toUpperCase.ts │ │ │ ├── transform/ │ │ │ │ ├── index.ts │ │ │ │ ├── transform.test-d.ts │ │ │ │ ├── transform.test.ts │ │ │ │ ├── transform.ts │ │ │ │ ├── transformAsync.test-d.ts │ │ │ │ ├── transformAsync.test.ts │ │ │ │ └── transformAsync.ts │ │ │ ├── trim/ │ │ │ │ ├── index.ts │ │ │ │ ├── trim.test-d.ts │ │ │ │ ├── trim.test.ts │ │ │ │ └── trim.ts │ │ │ ├── trimEnd/ │ │ │ │ ├── index.ts │ │ │ │ ├── trimEnd.test-d.ts │ │ │ │ ├── trimEnd.test.ts │ │ │ │ └── trimEnd.ts │ │ │ ├── trimStart/ │ │ │ │ ├── index.ts │ │ │ │ ├── trimStart.test-d.ts │ │ │ │ ├── trimStart.test.ts │ │ │ │ └── trimStart.ts │ │ │ ├── types.ts │ │ │ ├── ulid/ │ │ │ │ ├── index.ts │ │ │ │ ├── ulid.test-d.ts │ │ │ │ ├── ulid.test.ts │ │ │ │ └── ulid.ts │ │ │ ├── url/ │ │ │ │ ├── index.ts │ │ │ │ ├── url.test-d.ts │ │ │ │ ├── url.test.ts │ │ │ │ └── url.ts │ │ │ ├── uuid/ │ │ │ │ ├── index.ts │ │ │ │ ├── uuid.test-d.ts │ │ │ │ ├── uuid.test.ts │ │ │ │ └── uuid.ts │ │ │ ├── value/ │ │ │ │ ├── index.ts │ │ │ │ ├── value.test-d.ts │ │ │ │ ├── value.test.ts │ │ │ │ └── value.ts │ │ │ ├── values/ │ │ │ │ ├── index.ts │ │ │ │ ├── values.test-d.ts │ │ │ │ ├── values.test.ts │ │ │ │ └── values.ts │ │ │ └── words/ │ │ │ ├── index.ts │ │ │ ├── words.test-d.ts │ │ │ ├── words.test.ts │ │ │ └── words.ts │ │ ├── index.ts │ │ ├── methods/ │ │ │ ├── assert/ │ │ │ │ ├── assert.test-d.ts │ │ │ │ ├── assert.test.ts │ │ │ │ ├── assert.ts │ │ │ │ └── index.ts │ │ │ ├── cache/ │ │ │ │ ├── _LruCache.test.ts │ │ │ │ ├── _LruCache.ts │ │ │ │ ├── cache.test-d.ts │ │ │ │ ├── cache.test.ts │ │ │ │ ├── cache.ts │ │ │ │ ├── cacheAsync.test-d.ts │ │ │ │ ├── cacheAsync.test.ts │ │ │ │ ├── cacheAsync.ts │ │ │ │ ├── index.ts │ │ │ │ └── types.ts │ │ │ ├── config/ │ │ │ │ ├── config.test-d.ts │ │ │ │ ├── config.test.ts │ │ │ │ ├── config.ts │ │ │ │ └── index.ts │ │ │ ├── fallback/ │ │ │ │ ├── fallback.test-d.ts │ │ │ │ ├── fallback.test.ts │ │ │ │ ├── fallback.ts │ │ │ │ ├── fallbackAsync.test-d.ts │ │ │ │ ├── fallbackAsync.test.ts │ │ │ │ ├── fallbackAsync.ts │ │ │ │ └── index.ts │ │ │ ├── flatten/ │ │ │ │ ├── flatten.test-d.ts │ │ │ │ ├── flatten.test.ts │ │ │ │ ├── flatten.ts │ │ │ │ └── index.ts │ │ │ ├── forward/ │ │ │ │ ├── forward.test-d.ts │ │ │ │ ├── forward.test.ts │ │ │ │ ├── forward.ts │ │ │ │ ├── forwardAsync.test-d.ts │ │ │ │ ├── forwardAsync.test.ts │ │ │ │ ├── forwardAsync.ts │ │ │ │ ├── index.ts │ │ │ │ └── types.ts │ │ │ ├── getDefault/ │ │ │ │ ├── getDefault.test-d.ts │ │ │ │ ├── getDefault.test.ts │ │ │ │ ├── getDefault.ts │ │ │ │ └── index.ts │ │ │ ├── getDefaults/ │ │ │ │ ├── getDefaults.test-d.ts │ │ │ │ ├── getDefaults.test.ts │ │ │ │ ├── getDefaults.ts │ │ │ │ ├── getDefaultsAsync.test-d.ts │ │ │ │ ├── getDefaultsAsync.test.ts │ │ │ │ ├── getDefaultsAsync.ts │ │ │ │ ├── index.ts │ │ │ │ └── types.ts │ │ │ ├── getDescription/ │ │ │ │ ├── getDescription.test.ts │ │ │ │ ├── getDescription.ts │ │ │ │ └── index.ts │ │ │ ├── getExamples/ │ │ │ │ ├── getExamples.test-d.ts │ │ │ │ ├── getExamples.test.ts │ │ │ │ ├── getExamples.ts │ │ │ │ └── index.ts │ │ │ ├── getFallback/ │ │ │ │ ├── getFallback.test-d.ts │ │ │ │ ├── getFallback.test.ts │ │ │ │ ├── getFallback.ts │ │ │ │ └── index.ts │ │ │ ├── getFallbacks/ │ │ │ │ ├── getFallbacks.test-d.ts │ │ │ │ ├── getFallbacks.test.ts │ │ │ │ ├── getFallbacks.ts │ │ │ │ ├── getFallbacksAsync.test-d.ts │ │ │ │ ├── getFallbacksAsync.test.ts │ │ │ │ ├── getFallbacksAsync.ts │ │ │ │ ├── index.ts │ │ │ │ └── types.ts │ │ │ ├── getMetadata/ │ │ │ │ ├── getMetadata.test-d.ts │ │ │ │ ├── getMetadata.test.ts │ │ │ │ ├── getMetadata.ts │ │ │ │ └── index.ts │ │ │ ├── getTitle/ │ │ │ │ ├── getTitle.test.ts │ │ │ │ ├── getTitle.ts │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── is/ │ │ │ │ ├── index.ts │ │ │ │ ├── is.test-d.ts │ │ │ │ ├── is.test.ts │ │ │ │ └── is.ts │ │ │ ├── keyof/ │ │ │ │ ├── index.ts │ │ │ │ ├── keyof.test-d.ts │ │ │ │ ├── keyof.test.ts │ │ │ │ └── keyof.ts │ │ │ ├── message/ │ │ │ │ ├── index.ts │ │ │ │ ├── message.test-d.ts │ │ │ │ ├── message.test.ts │ │ │ │ └── message.ts │ │ │ ├── omit/ │ │ │ │ ├── index.ts │ │ │ │ ├── omit.test-d.ts │ │ │ │ ├── omit.test.ts │ │ │ │ └── omit.ts │ │ │ ├── parse/ │ │ │ │ ├── index.ts │ │ │ │ ├── parse.test-d.ts │ │ │ │ ├── parse.test.ts │ │ │ │ ├── parse.ts │ │ │ │ ├── parseAsync.test-d.ts │ │ │ │ ├── parseAsync.test.ts │ │ │ │ └── parseAsync.ts │ │ │ ├── parser/ │ │ │ │ ├── index.ts │ │ │ │ ├── parser.test-d.ts │ │ │ │ ├── parser.test.ts │ │ │ │ ├── parser.ts │ │ │ │ ├── parserAsync.test-d.ts │ │ │ │ ├── parserAsync.test.ts │ │ │ │ └── parserAsync.ts │ │ │ ├── partial/ │ │ │ │ ├── index.ts │ │ │ │ ├── partial.test-d.ts │ │ │ │ ├── partial.test.ts │ │ │ │ ├── partial.ts │ │ │ │ ├── partialAsync.test-d.ts │ │ │ │ ├── partialAsync.test.ts │ │ │ │ └── partialAsync.ts │ │ │ ├── pick/ │ │ │ │ ├── index.ts │ │ │ │ ├── pick.test-d.ts │ │ │ │ ├── pick.test.ts │ │ │ │ └── pick.ts │ │ │ ├── pipe/ │ │ │ │ ├── index.ts │ │ │ │ ├── pipe.test-d.ts │ │ │ │ ├── pipe.test.ts │ │ │ │ ├── pipe.ts │ │ │ │ ├── pipeAsync.test-d.ts │ │ │ │ ├── pipeAsync.test.ts │ │ │ │ └── pipeAsync.ts │ │ │ ├── required/ │ │ │ │ ├── index.ts │ │ │ │ ├── required.test-d.ts │ │ │ │ ├── required.test.ts │ │ │ │ ├── required.ts │ │ │ │ ├── requiredAsync.test-d.ts │ │ │ │ ├── requiredAsync.test.ts │ │ │ │ └── requiredAsync.ts │ │ │ ├── safeParse/ │ │ │ │ ├── index.ts │ │ │ │ ├── safeParse.test-d.ts │ │ │ │ ├── safeParse.test.ts │ │ │ │ ├── safeParse.ts │ │ │ │ ├── safeParseAsync.test-d.ts │ │ │ │ ├── safeParseAsync.test.ts │ │ │ │ ├── safeParseAsync.ts │ │ │ │ └── types.ts │ │ │ ├── safeParser/ │ │ │ │ ├── index.ts │ │ │ │ ├── safeParser.test-d.ts │ │ │ │ ├── safeParser.test.ts │ │ │ │ ├── safeParser.ts │ │ │ │ ├── safeParserAsync.test-d.ts │ │ │ │ ├── safeParserAsync.test.ts │ │ │ │ └── safeParserAsync.ts │ │ │ ├── summarize/ │ │ │ │ ├── index.ts │ │ │ │ ├── summarize.test.ts │ │ │ │ └── summarize.ts │ │ │ └── unwrap/ │ │ │ ├── index.ts │ │ │ ├── unwrap.test-d.ts │ │ │ ├── unwrap.test.ts │ │ │ └── unwrap.ts │ │ ├── regex.ts │ │ ├── schemas/ │ │ │ ├── any/ │ │ │ │ ├── any.test-d.ts │ │ │ │ ├── any.test.ts │ │ │ │ ├── any.ts │ │ │ │ └── index.ts │ │ │ ├── array/ │ │ │ │ ├── array.test-d.ts │ │ │ │ ├── array.test.ts │ │ │ │ ├── array.ts │ │ │ │ ├── arrayAsync.test-d.ts │ │ │ │ ├── arrayAsync.test.ts │ │ │ │ ├── arrayAsync.ts │ │ │ │ ├── index.ts │ │ │ │ └── types.ts │ │ │ ├── bigint/ │ │ │ │ ├── bigint.test-d.ts │ │ │ │ ├── bigint.test.ts │ │ │ │ ├── bigint.ts │ │ │ │ └── index.ts │ │ │ ├── blob/ │ │ │ │ ├── blob.test-d.ts │ │ │ │ ├── blob.test.ts │ │ │ │ ├── blob.ts │ │ │ │ └── index.ts │ │ │ ├── boolean/ │ │ │ │ ├── boolean.test-d.ts │ │ │ │ ├── boolean.test.ts │ │ │ │ ├── boolean.ts │ │ │ │ └── index.ts │ │ │ ├── custom/ │ │ │ │ ├── custom.test-d.ts │ │ │ │ ├── custom.test.ts │ │ │ │ ├── custom.ts │ │ │ │ ├── customAsync.test-d.ts │ │ │ │ ├── customAsync.test.ts │ │ │ │ ├── customAsync.ts │ │ │ │ ├── index.ts │ │ │ │ └── types.ts │ │ │ ├── date/ │ │ │ │ ├── date.test-d.ts │ │ │ │ ├── date.test.ts │ │ │ │ ├── date.ts │ │ │ │ └── index.ts │ │ │ ├── enum/ │ │ │ │ ├── enum.test-d.ts │ │ │ │ ├── enum.test.ts │ │ │ │ ├── enum.ts │ │ │ │ └── index.ts │ │ │ ├── exactOptional/ │ │ │ │ ├── exactOptional.test-d.ts │ │ │ │ ├── exactOptional.test.ts │ │ │ │ ├── exactOptional.ts │ │ │ │ ├── exactOptionalAsync.test-d.ts │ │ │ │ ├── exactOptionalAsync.test.ts │ │ │ │ ├── exactOptionalAsync.ts │ │ │ │ └── index.ts │ │ │ ├── file/ │ │ │ │ ├── file.test-d.ts │ │ │ │ ├── file.test.ts │ │ │ │ ├── file.ts │ │ │ │ └── index.ts │ │ │ ├── function/ │ │ │ │ ├── function.test-d.ts │ │ │ │ ├── function.test.ts │ │ │ │ ├── function.ts │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── instance/ │ │ │ │ ├── index.ts │ │ │ │ ├── instance.test-d.ts │ │ │ │ ├── instance.test.ts │ │ │ │ └── instance.ts │ │ │ ├── intersect/ │ │ │ │ ├── index.ts │ │ │ │ ├── intersect.test-d.ts │ │ │ │ ├── intersect.test.ts │ │ │ │ ├── intersect.ts │ │ │ │ ├── intersectAsync.test-d.ts │ │ │ │ ├── intersectAsync.test.ts │ │ │ │ ├── intersectAsync.ts │ │ │ │ ├── types.ts │ │ │ │ └── utils/ │ │ │ │ ├── _merge/ │ │ │ │ │ ├── _merge.test.ts │ │ │ │ │ ├── _merge.ts │ │ │ │ │ └── index.ts │ │ │ │ └── index.ts │ │ │ ├── lazy/ │ │ │ │ ├── index.ts │ │ │ │ ├── lazy.test-d.ts │ │ │ │ ├── lazy.test.ts │ │ │ │ ├── lazy.ts │ │ │ │ ├── lazyAsync.test-d.ts │ │ │ │ ├── lazyAsync.test.ts │ │ │ │ └── lazyAsync.ts │ │ │ ├── literal/ │ │ │ │ ├── index.ts │ │ │ │ ├── literal.test-d.ts │ │ │ │ ├── literal.test.ts │ │ │ │ └── literal.ts │ │ │ ├── looseObject/ │ │ │ │ ├── index.ts │ │ │ │ ├── looseObject.test-d.ts │ │ │ │ ├── looseObject.test.ts │ │ │ │ ├── looseObject.ts │ │ │ │ ├── looseObjectAsync.test-d.ts │ │ │ │ ├── looseObjectAsync.test.ts │ │ │ │ ├── looseObjectAsync.ts │ │ │ │ └── types.ts │ │ │ ├── looseTuple/ │ │ │ │ ├── index.ts │ │ │ │ ├── looseTuple.test-d.ts │ │ │ │ ├── looseTuple.test.ts │ │ │ │ ├── looseTuple.ts │ │ │ │ ├── looseTupleAsync.test-d.ts │ │ │ │ ├── looseTupleAsync.test.ts │ │ │ │ ├── looseTupleAsync.ts │ │ │ │ └── types.ts │ │ │ ├── map/ │ │ │ │ ├── index.ts │ │ │ │ ├── map.test-d.ts │ │ │ │ ├── map.test.ts │ │ │ │ ├── map.ts │ │ │ │ ├── mapAsync.test-d.ts │ │ │ │ ├── mapAsync.test.ts │ │ │ │ ├── mapAsync.ts │ │ │ │ └── types.ts │ │ │ ├── nan/ │ │ │ │ ├── index.ts │ │ │ │ ├── nan.test-d.ts │ │ │ │ ├── nan.test.ts │ │ │ │ └── nan.ts │ │ │ ├── never/ │ │ │ │ ├── index.ts │ │ │ │ ├── never.test-d.ts │ │ │ │ ├── never.test.ts │ │ │ │ └── never.ts │ │ │ ├── nonNullable/ │ │ │ │ ├── index.ts │ │ │ │ ├── nonNullable.test-d.ts │ │ │ │ ├── nonNullable.test.ts │ │ │ │ ├── nonNullable.ts │ │ │ │ ├── nonNullableAsync.test-d.ts │ │ │ │ ├── nonNullableAsync.test.ts │ │ │ │ ├── nonNullableAsync.ts │ │ │ │ └── types.ts │ │ │ ├── nonNullish/ │ │ │ │ ├── index.ts │ │ │ │ ├── nonNullish.test-d.ts │ │ │ │ ├── nonNullish.test.ts │ │ │ │ ├── nonNullish.ts │ │ │ │ ├── nonNullishAsync.test-d.ts │ │ │ │ ├── nonNullishAsync.test.ts │ │ │ │ ├── nonNullishAsync.ts │ │ │ │ └── types.ts │ │ │ ├── nonOptional/ │ │ │ │ ├── index.ts │ │ │ │ ├── nonOptional.test-d.ts │ │ │ │ ├── nonOptional.test.ts │ │ │ │ ├── nonOptional.ts │ │ │ │ ├── nonOptionalAsync.test-d.ts │ │ │ │ ├── nonOptionalAsync.test.ts │ │ │ │ ├── nonOptionalAsync.ts │ │ │ │ └── types.ts │ │ │ ├── null/ │ │ │ │ ├── index.ts │ │ │ │ ├── null.test-d.ts │ │ │ │ ├── null.test.ts │ │ │ │ └── null.ts │ │ │ ├── nullable/ │ │ │ │ ├── index.ts │ │ │ │ ├── nullable.test-d.ts │ │ │ │ ├── nullable.test.ts │ │ │ │ ├── nullable.ts │ │ │ │ ├── nullableAsync.test-d.ts │ │ │ │ ├── nullableAsync.test.ts │ │ │ │ ├── nullableAsync.ts │ │ │ │ └── types.ts │ │ │ ├── nullish/ │ │ │ │ ├── index.ts │ │ │ │ ├── nullish.test-d.ts │ │ │ │ ├── nullish.test.ts │ │ │ │ ├── nullish.ts │ │ │ │ ├── nullishAsync.test-d.ts │ │ │ │ ├── nullishAsync.test.ts │ │ │ │ ├── nullishAsync.ts │ │ │ │ └── types.ts │ │ │ ├── number/ │ │ │ │ ├── index.ts │ │ │ │ ├── number.test-d.ts │ │ │ │ ├── number.test.ts │ │ │ │ └── number.ts │ │ │ ├── object/ │ │ │ │ ├── index.ts │ │ │ │ ├── object.test-d.ts │ │ │ │ ├── object.test.ts │ │ │ │ ├── object.ts │ │ │ │ ├── objectAsync.test-d.ts │ │ │ │ ├── objectAsync.test.ts │ │ │ │ ├── objectAsync.ts │ │ │ │ └── types.ts │ │ │ ├── objectWithRest/ │ │ │ │ ├── index.ts │ │ │ │ ├── objectWithRest.test-d.ts │ │ │ │ ├── objectWithRest.test.ts │ │ │ │ ├── objectWithRest.ts │ │ │ │ ├── objectWithRestAsync.test-d.ts │ │ │ │ ├── objectWithRestAsync.test.ts │ │ │ │ ├── objectWithRestAsync.ts │ │ │ │ └── types.ts │ │ │ ├── optional/ │ │ │ │ ├── index.ts │ │ │ │ ├── optional.test-d.ts │ │ │ │ ├── optional.test.ts │ │ │ │ ├── optional.ts │ │ │ │ ├── optionalAsync.test-d.ts │ │ │ │ ├── optionalAsync.test.ts │ │ │ │ ├── optionalAsync.ts │ │ │ │ └── types.ts │ │ │ ├── picklist/ │ │ │ │ ├── index.ts │ │ │ │ ├── picklist.test-d.ts │ │ │ │ ├── picklist.test.ts │ │ │ │ └── picklist.ts │ │ │ ├── promise/ │ │ │ │ ├── index.ts │ │ │ │ ├── promise.test-d.ts │ │ │ │ ├── promise.test.ts │ │ │ │ └── promise.ts │ │ │ ├── record/ │ │ │ │ ├── index.ts │ │ │ │ ├── record.test-d.ts │ │ │ │ ├── record.test.ts │ │ │ │ ├── record.ts │ │ │ │ ├── recordAsync.test-d.ts │ │ │ │ ├── recordAsync.test.ts │ │ │ │ ├── recordAsync.ts │ │ │ │ └── types.ts │ │ │ ├── set/ │ │ │ │ ├── index.ts │ │ │ │ ├── set.test-d.ts │ │ │ │ ├── set.test.ts │ │ │ │ ├── set.ts │ │ │ │ ├── setAsync.test-d.ts │ │ │ │ ├── setAsync.test.ts │ │ │ │ ├── setAsync.ts │ │ │ │ └── types.ts │ │ │ ├── strictObject/ │ │ │ │ ├── index.ts │ │ │ │ ├── strictObject.test-d.ts │ │ │ │ ├── strictObject.test.ts │ │ │ │ ├── strictObject.ts │ │ │ │ ├── strictObjectAsync.test-d.ts │ │ │ │ ├── strictObjectAsync.test.ts │ │ │ │ ├── strictObjectAsync.ts │ │ │ │ └── types.ts │ │ │ ├── strictTuple/ │ │ │ │ ├── index.ts │ │ │ │ ├── strictTuple.test-d.ts │ │ │ │ ├── strictTuple.test.ts │ │ │ │ ├── strictTuple.ts │ │ │ │ ├── strictTupleAsync.test-d.ts │ │ │ │ ├── strictTupleAsync.test.ts │ │ │ │ ├── strictTupleAsync.ts │ │ │ │ └── types.ts │ │ │ ├── string/ │ │ │ │ ├── index.ts │ │ │ │ ├── string.test-d.ts │ │ │ │ ├── string.test.ts │ │ │ │ └── string.ts │ │ │ ├── symbol/ │ │ │ │ ├── index.ts │ │ │ │ ├── symbol.test-d.ts │ │ │ │ ├── symbol.test.ts │ │ │ │ └── symbol.ts │ │ │ ├── tuple/ │ │ │ │ ├── index.ts │ │ │ │ ├── tuple.test-d.ts │ │ │ │ ├── tuple.test.ts │ │ │ │ ├── tuple.ts │ │ │ │ ├── tupleAsync.test-d.ts │ │ │ │ ├── tupleAsync.test.ts │ │ │ │ ├── tupleAsync.ts │ │ │ │ └── types.ts │ │ │ ├── tupleWithRest/ │ │ │ │ ├── index.ts │ │ │ │ ├── tupleWithRest.test-d.ts │ │ │ │ ├── tupleWithRest.test.ts │ │ │ │ ├── tupleWithRest.ts │ │ │ │ ├── tupleWithRestAsync.test-d.ts │ │ │ │ ├── tupleWithRestAsync.test.ts │ │ │ │ ├── tupleWithRestAsync.ts │ │ │ │ └── types.ts │ │ │ ├── undefined/ │ │ │ │ ├── index.ts │ │ │ │ ├── undefined.test-d.ts │ │ │ │ ├── undefined.test.ts │ │ │ │ └── undefined.ts │ │ │ ├── undefinedable/ │ │ │ │ ├── index.ts │ │ │ │ ├── types.ts │ │ │ │ ├── undefinedable.test-d.ts │ │ │ │ ├── undefinedable.test.ts │ │ │ │ ├── undefinedable.ts │ │ │ │ ├── undefinedableAsync.test-d.ts │ │ │ │ ├── undefinedableAsync.test.ts │ │ │ │ └── undefinedableAsync.ts │ │ │ ├── union/ │ │ │ │ ├── index.ts │ │ │ │ ├── types.ts │ │ │ │ ├── union.test-d.ts │ │ │ │ ├── union.test.ts │ │ │ │ ├── union.ts │ │ │ │ ├── unionAsync.test-d.ts │ │ │ │ ├── unionAsync.test.ts │ │ │ │ ├── unionAsync.ts │ │ │ │ └── utils/ │ │ │ │ ├── _subIssues/ │ │ │ │ │ ├── _subIssues.test.ts │ │ │ │ │ ├── _subIssues.ts │ │ │ │ │ └── index.ts │ │ │ │ └── index.ts │ │ │ ├── unknown/ │ │ │ │ ├── index.ts │ │ │ │ ├── unknown.test-d.ts │ │ │ │ ├── unknown.test.ts │ │ │ │ └── unknown.ts │ │ │ ├── variant/ │ │ │ │ ├── index.ts │ │ │ │ ├── types.ts │ │ │ │ ├── variant.test-d.ts │ │ │ │ ├── variant.test.ts │ │ │ │ ├── variant.ts │ │ │ │ ├── variantAsync.test-d.ts │ │ │ │ ├── variantAsync.test.ts │ │ │ │ └── variantAsync.ts │ │ │ └── void/ │ │ │ ├── index.ts │ │ │ ├── void.test-d.ts │ │ │ ├── void.test.ts │ │ │ └── void.ts │ │ ├── storages/ │ │ │ ├── globalConfig/ │ │ │ │ ├── globalConfig.test.ts │ │ │ │ ├── globalConfig.ts │ │ │ │ └── index.ts │ │ │ ├── globalMessage/ │ │ │ │ ├── globalMessage.test.ts │ │ │ │ ├── globalMessage.ts │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── schemaMessage/ │ │ │ │ ├── index.ts │ │ │ │ ├── schemaMessage.test.ts │ │ │ │ └── schemaMessage.ts │ │ │ └── specificMessage/ │ │ │ ├── index.ts │ │ │ ├── specificMessage.test.ts │ │ │ └── specificMessage.ts │ │ ├── types/ │ │ │ ├── config.ts │ │ │ ├── dataset.ts │ │ │ ├── index.ts │ │ │ ├── infer.ts │ │ │ ├── issue.ts │ │ │ ├── metadata.ts │ │ │ ├── object.ts │ │ │ ├── other.ts │ │ │ ├── pipe.ts │ │ │ ├── schema.ts │ │ │ ├── standard.ts │ │ │ ├── transformation.ts │ │ │ ├── tuple.ts │ │ │ ├── utils.ts │ │ │ └── validation.ts │ │ ├── utils/ │ │ │ ├── ValiError/ │ │ │ │ ├── ValiError.test-d.ts │ │ │ │ ├── ValiError.test.ts │ │ │ │ ├── ValiError.ts │ │ │ │ └── index.ts │ │ │ ├── _addIssue/ │ │ │ │ ├── _addIssue.test.ts │ │ │ │ ├── _addIssue.ts │ │ │ │ └── index.ts │ │ │ ├── _cloneDataset/ │ │ │ │ ├── _cloneDataset.test.ts │ │ │ │ ├── _cloneDataset.ts │ │ │ │ └── index.ts │ │ │ ├── _getByteCount/ │ │ │ │ ├── _getByteCount.test.ts │ │ │ │ ├── _getByteCount.ts │ │ │ │ └── index.ts │ │ │ ├── _getGraphemeCount/ │ │ │ │ ├── _getGraphemeCount.test.ts │ │ │ │ ├── _getGraphemeCount.ts │ │ │ │ └── index.ts │ │ │ ├── _getLastMetadata/ │ │ │ │ ├── _getLastMetadata.test.ts │ │ │ │ ├── _getLastMetadata.ts │ │ │ │ └── index.ts │ │ │ ├── _getStandardProps/ │ │ │ │ ├── _getStandardProps.test-d.ts │ │ │ │ ├── _getStandardProps.test.ts │ │ │ │ ├── _getStandardProps.ts │ │ │ │ └── index.ts │ │ │ ├── _getWordCount/ │ │ │ │ ├── _getWordCount.test.ts │ │ │ │ ├── _getWordCount.ts │ │ │ │ └── index.ts │ │ │ ├── _isLuhnAlgo/ │ │ │ │ ├── _isLuhnAlgo.test.ts │ │ │ │ ├── _isLuhnAlgo.ts │ │ │ │ └── index.ts │ │ │ ├── _isValidObjectKey/ │ │ │ │ ├── _isValidObjectKey.test.ts │ │ │ │ ├── _isValidObjectKey.ts │ │ │ │ └── index.ts │ │ │ ├── _joinExpects/ │ │ │ │ ├── _joinExpects.test.ts │ │ │ │ ├── _joinExpects.ts │ │ │ │ └── index.ts │ │ │ ├── _stringify/ │ │ │ │ ├── _stringify.test.ts │ │ │ │ ├── _stringify.ts │ │ │ │ └── index.ts │ │ │ ├── entriesFromList/ │ │ │ │ ├── entriesFromList.test-d.ts │ │ │ │ ├── entriesFromList.test.ts │ │ │ │ ├── entriesFromList.ts │ │ │ │ └── index.ts │ │ │ ├── entriesFromObjects/ │ │ │ │ ├── entriesFromObjects.test-d.ts │ │ │ │ ├── entriesFromObjects.test.ts │ │ │ │ ├── entriesFromObjects.ts │ │ │ │ └── index.ts │ │ │ ├── getDotPath/ │ │ │ │ ├── getDotPath.test-d.ts │ │ │ │ ├── getDotPath.test.ts │ │ │ │ ├── getDotPath.ts │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── isOfKind/ │ │ │ │ ├── index.ts │ │ │ │ ├── isOfKind.test.ts │ │ │ │ └── isOfKind.ts │ │ │ ├── isOfType/ │ │ │ │ ├── index.ts │ │ │ │ ├── isOfType.test.ts │ │ │ │ └── isOfType.ts │ │ │ └── isValiError/ │ │ │ ├── index.ts │ │ │ ├── isValiError.test.ts │ │ │ └── isValiError.ts │ │ └── vitest/ │ │ ├── expectActionIssue.ts │ │ ├── expectActionIssueAsync.ts │ │ ├── expectNoActionIssue.ts │ │ ├── expectNoActionIssueAsync.ts │ │ ├── expectNoSchemaIssue.ts │ │ ├── expectNoSchemaIssueAsync.ts │ │ ├── expectSchemaIssue.ts │ │ ├── expectSchemaIssueAsync.ts │ │ └── index.ts │ ├── tsconfig.json │ ├── tsdown.config.ts │ └── vitest.config.ts ├── package.json ├── packages/ │ ├── i18n/ │ │ ├── .gitignore │ │ ├── CHANGELOG.md │ │ ├── LICENSE.md │ │ ├── README.md │ │ ├── jsr.json │ │ ├── package.json │ │ ├── scripts/ │ │ │ ├── build-jsr.ts │ │ │ └── build-npm.ts │ │ ├── src/ │ │ │ ├── ar.ts │ │ │ ├── az.ts │ │ │ ├── ca.ts │ │ │ ├── cs.ts │ │ │ ├── de.ts │ │ │ ├── el.ts │ │ │ ├── en.ts │ │ │ ├── es.ts │ │ │ ├── fa.ts │ │ │ ├── fi.ts │ │ │ ├── fr.ts │ │ │ ├── hu.ts │ │ │ ├── id.ts │ │ │ ├── it.ts │ │ │ ├── ja.ts │ │ │ ├── ko.ts │ │ │ ├── kr.ts │ │ │ ├── mn.ts │ │ │ ├── nb.ts │ │ │ ├── nl.ts │ │ │ ├── pl.ts │ │ │ ├── pt.ts │ │ │ ├── ro.ts │ │ │ ├── ru.ts │ │ │ ├── sk.ts │ │ │ ├── sl.ts │ │ │ ├── sv.ts │ │ │ ├── tr.ts │ │ │ ├── types.ts │ │ │ ├── uk.ts │ │ │ ├── vi.ts │ │ │ ├── zh-CN.ts │ │ │ └── zh-TW.ts │ │ └── tsconfig.json │ └── to-json-schema/ │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ ├── eslint.config.js │ ├── jsr.json │ ├── package.json │ ├── src/ │ │ ├── converters/ │ │ │ ├── convertAction/ │ │ │ │ ├── convertAction.test.ts │ │ │ │ ├── convertAction.ts │ │ │ │ └── index.ts │ │ │ ├── convertSchema/ │ │ │ │ ├── convertSchema.test.ts │ │ │ │ ├── convertSchema.ts │ │ │ │ └── index.ts │ │ │ └── index.ts │ │ ├── functions/ │ │ │ ├── index.ts │ │ │ ├── toJsonSchema/ │ │ │ │ ├── index.ts │ │ │ │ ├── toJsonSchema.test.ts │ │ │ │ └── toJsonSchema.ts │ │ │ ├── toJsonSchemaDefs/ │ │ │ │ ├── index.ts │ │ │ │ ├── toJsonSchemaDefs.test.ts │ │ │ │ └── toJsonSchemaDefs.ts │ │ │ └── toStandardJsonSchema/ │ │ │ ├── index.ts │ │ │ ├── toStandardJsonSchema.test.ts │ │ │ └── toStandardJsonSchema.ts │ │ ├── index.ts │ │ ├── storages/ │ │ │ ├── globalDefs/ │ │ │ │ ├── globalDefs.test.ts │ │ │ │ ├── globalDefs.ts │ │ │ │ └── index.ts │ │ │ └── index.ts │ │ ├── types/ │ │ │ ├── config.ts │ │ │ ├── index.ts │ │ │ ├── schema.ts │ │ │ └── standard.ts │ │ ├── utils/ │ │ │ ├── addError.ts │ │ │ ├── escapeRegExp.ts │ │ │ ├── handleError.ts │ │ │ ├── index.ts │ │ │ ├── isJsonConstValue.ts │ │ │ └── isJsonEnumValues.ts │ │ └── vitest/ │ │ ├── createContext.ts │ │ └── index.ts │ ├── tsconfig.json │ ├── tsdown.config.ts │ └── vitest.config.ts ├── pnpm-workspace.yaml ├── prettier.config.cjs └── website/ ├── .gitignore ├── .node-version ├── .prettierignore ├── README.md ├── adapters/ │ └── vercel-edge/ │ └── vite.config.ts ├── eslint.config.js ├── package.json ├── public/ │ ├── manifest.json │ └── robots.txt ├── scripts/ │ ├── contributors.ts │ ├── llms.ts │ ├── sitemap.ts │ ├── sources.ts │ └── utils/ │ ├── findNestedFiles.ts │ └── index.ts ├── src/ │ ├── components/ │ │ ├── ActionButton.tsx │ │ ├── ApiList.tsx │ │ ├── ButtonGroup.tsx │ │ ├── Chapters.tsx │ │ ├── CodeEditor.tsx │ │ ├── Credits.tsx │ │ ├── DiscordIconLink.tsx │ │ ├── DocSearch.tsx │ │ ├── DocsLayout.tsx │ │ ├── Expandable.tsx │ │ ├── Footer.tsx │ │ ├── GitHubIconLink.tsx │ │ ├── Head.tsx │ │ ├── Header.tsx │ │ ├── IconButton.tsx │ │ ├── Link.tsx │ │ ├── MainMenuToggle.tsx │ │ ├── Navigation.tsx │ │ ├── PostCover.tsx │ │ ├── PostList.tsx │ │ ├── PostMeta.tsx │ │ ├── Property.tsx │ │ ├── RoutingIndicator.tsx │ │ ├── SearchToggle.tsx │ │ ├── SideBar.tsx │ │ ├── SpeedInsights.tsx │ │ ├── Spinner.tsx │ │ ├── SystemIcon.tsx │ │ ├── TextLink.tsx │ │ ├── ThemeToggle.tsx │ │ ├── UnstyledButton.tsx │ │ └── index.ts │ ├── entry.dev.tsx │ ├── entry.preview.tsx │ ├── entry.ssr.tsx │ ├── entry.vercel-edge.tsx │ ├── hooks/ │ │ ├── index.ts │ │ ├── useFocusTrap.ts │ │ ├── useMDXComponents.tsx │ │ ├── useResetSignal.ts │ │ └── useStorageSignal.ts │ ├── icons/ │ │ ├── AngleRightIcon.tsx │ │ ├── AngleUpIcon.tsx │ │ ├── ArrowLeftIcon.tsx │ │ ├── ArrowRrightIcon.tsx │ │ ├── BinIcon.tsx │ │ ├── CheckIcon.tsx │ │ ├── CloseIcon.tsx │ │ ├── CopyIcon.tsx │ │ ├── DiscordIcon.tsx │ │ ├── GitHubIcon.tsx │ │ ├── HashtagIcon.tsx │ │ ├── LogoIcon.tsx │ │ ├── MarkdownIcon.tsx │ │ ├── MenuIcon.tsx │ │ ├── NightIcon.tsx │ │ ├── PageIcon.tsx │ │ ├── PenIcon.tsx │ │ ├── PlayIcon.tsx │ │ ├── PlusIcon.tsx │ │ ├── SearchIcon.tsx │ │ ├── ShareIcon.tsx │ │ ├── SunIcon.tsx │ │ └── index.ts │ ├── images/ │ │ └── index.ts │ ├── json/ │ │ └── TypeScript.tmLanguage.json │ ├── logos/ │ │ ├── AlgoliaLogo.tsx │ │ ├── BoltLogo.tsx │ │ ├── BuilderLogo.tsx │ │ ├── DailyDevLogo.tsx │ │ ├── DigitalOceanLogo.tsx │ │ ├── HdmLogo.tsx │ │ ├── LambdaTestLogo.tsx │ │ ├── MotionLogo.tsx │ │ ├── NetlifyLogo.tsx │ │ ├── PaceLogo.tsx │ │ ├── StainlessLogo.tsx │ │ ├── TestMuAiLogo.tsx │ │ ├── VercelLogo.tsx │ │ └── index.ts │ ├── root.tsx │ ├── routes/ │ │ ├── (legal)/ │ │ │ ├── contact/ │ │ │ │ └── index.mdx │ │ │ ├── layout.tsx │ │ │ └── privacy/ │ │ │ └── index.mdx │ │ ├── 404.tsx │ │ ├── api/ │ │ │ ├── (actions)/ │ │ │ │ ├── args/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── base64/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── bic/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── brand/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── bytes/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── check/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── checkItems/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── creditCard/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── cuid2/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── decimal/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── description/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── digits/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── domain/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── email/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── emoji/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── empty/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── endsWith/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── entries/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── everyItem/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── examples/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── excludes/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── filterItems/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── findItem/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── finite/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── flavor/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── graphemes/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── gtValue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── guard/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── hash/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── hexColor/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── hexadecimal/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── imei/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── includes/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── integer/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ip/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ipv4/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ipv6/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── isbn/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── isoDate/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── isoDateTime/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── isoTime/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── isoTimeSecond/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── isoTimestamp/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── isoWeek/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── isrc/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── jwsCompact/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── length/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ltValue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── mac/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── mac48/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── mac64/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── mapItems/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── maxBytes/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── maxEntries/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── maxGraphemes/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── maxLength/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── maxSize/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── maxValue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── maxWords/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── metadata/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── mimeType/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── minBytes/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── minEntries/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── minGraphemes/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── minLength/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── minSize/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── minValue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── minWords/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── multipleOf/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── nanoid/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── nonEmpty/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── normalize/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── notBytes/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── notEntries/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── notGraphemes/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── notLength/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── notSize/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── notValue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── notValues/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── notWords/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── octal/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── parseBoolean/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── parseJson/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── partialCheck/ │ │ │ │ │ ├── ValidPaths/ │ │ │ │ │ │ └── index.mdx │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── rawCheck/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── rawTransform/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── readonly/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── reduceItems/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── regex/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── returns/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── rfcEmail/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── safeInteger/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── size/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── slug/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── someItem/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── sortItems/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── startsWith/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── stringifyJson/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── title/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── toBigint/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── toBoolean/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── toDate/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── toLowerCase/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── toMaxValue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── toMinValue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── toNumber/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── toString/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── toUpperCase/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── transform/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── trim/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── trimEnd/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── trimStart/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ulid/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── url/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── uuid/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── value/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── values/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ └── words/ │ │ │ │ ├── index.mdx │ │ │ │ └── properties.ts │ │ │ ├── (async)/ │ │ │ │ ├── argsAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── arrayAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── awaitAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── cacheAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── checkAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── checkItemsAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── customAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── exactOptionalAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── fallbackAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── forwardAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── getDefaultsAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── getFallbacksAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── intersectAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── lazyAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── looseObjectAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── looseTupleAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── mapAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── nonNullableAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── nonNullishAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── nonOptionalAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── nullableAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── nullishAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── objectAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── objectWithRestAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── optionalAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── parseAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── parserAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── partialAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── partialCheckAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── pipeAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── rawCheckAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── rawTransformAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── recordAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── requiredAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── returnsAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── safeParseAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── safeParserAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── setAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── strictObjectAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── strictTupleAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── transformAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── tupleAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── tupleWithRestAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── undefinedableAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── unionAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ └── variantAsync/ │ │ │ │ ├── index.mdx │ │ │ │ └── properties.ts │ │ │ ├── (methods)/ │ │ │ │ ├── assert/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── cache/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── config/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── fallback/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── flatten/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── forward/ │ │ │ │ │ ├── ValidPath/ │ │ │ │ │ │ └── index.mdx │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── getDefault/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── getDefaults/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── getDescription/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── getExamples/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── getFallback/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── getFallbacks/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── getMetadata/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── getTitle/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── is/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── keyof/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── message/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── omit/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── parse/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── parser/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── partial/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── pick/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── pipe/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── required/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── safeParse/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── safeParser/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── summarize/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ └── unwrap/ │ │ │ │ ├── index.mdx │ │ │ │ └── properties.ts │ │ │ ├── (schemas)/ │ │ │ │ ├── any/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── array/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── bigint/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── blob/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── boolean/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── custom/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── date/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── enum/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── exactOptional/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── file/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── function/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── instance/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── intersect/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── lazy/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── literal/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── looseObject/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── looseTuple/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── map/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── nan/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── never/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── nonNullable/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── nonNullish/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── nonOptional/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── null/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── nullable/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── nullish/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── number/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── object/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── objectWithRest/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── optional/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── picklist/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── promise/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── record/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── set/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── strictObject/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── strictTuple/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── string/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── symbol/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── tuple/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── tupleWithRest/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── undefined/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── undefinedable/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── union/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── unknown/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── variant/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ └── void/ │ │ │ │ ├── index.mdx │ │ │ │ └── properties.ts │ │ │ ├── (storages)/ │ │ │ │ ├── deleteGlobalConfig/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── deleteGlobalMessage/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── deleteSchemaMessage/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── deleteSpecificMessage/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── getGlobalConfig/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── getGlobalMessage/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── getSchemaMessage/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── getSpecificMessage/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── setGlobalConfig/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── setGlobalMessage/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── setSchemaMessage/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ └── setSpecificMessage/ │ │ │ │ ├── index.mdx │ │ │ │ └── properties.ts │ │ │ ├── (types)/ │ │ │ │ ├── AnySchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ArgsAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ArgsActionAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ArrayInput/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ArrayIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ArrayPathItem/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ArrayRequirement/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ArrayRequirementAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ArraySchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ArraySchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── AwaitActionAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Base64Action/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Base64Issue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── BaseIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── BaseMetadata/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── BaseSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── BaseSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── BaseTransformation/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── BaseTransformationAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── BaseValidation/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── BaseValidationAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── BicAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── BicIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── BigintIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── BigintSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── BlobIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── BlobSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── BooleanIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── BooleanSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Brand/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── BrandAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── BrandName/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── BytesAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── BytesIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Cache/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── CacheConfig/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── CheckAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── CheckActionAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── CheckIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── CheckItemsAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── CheckItemsActionAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── CheckItemsIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Class/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Config/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ContentInput/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ContentRequirement/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── CreditCardAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── CreditCardIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Cuid2Action/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Cuid2Issue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── CustomIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── CustomSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── CustomSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── DateIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── DateSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── DecimalAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── DecimalIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── DeepPickN/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── Default/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── DefaultAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── DefaultValue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── DescriptionAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── DigitsAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── DigitsIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── DomainAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── DomainIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── EmailAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── EmailIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── EmojiAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── EmojiIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── EmptyAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── EmptyIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── EndsWithAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── EndsWithIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── EntriesAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── EntriesInput/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── EntriesIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Enum/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── EnumIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── EnumSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ErrorMessage/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── EveryItemAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── EveryItemIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ExactOptionalSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ExactOptionalSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ExamplesAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ExcludesAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ExcludesIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── FailureDataset/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Fallback/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── FallbackAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── FileIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── FileSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── FilterItemsAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── FindItemAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── FiniteAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── FiniteIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── FirstTupleItem/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── FlatErrors/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── Flavor/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── FlavorAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── FlavorName/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── FunctionIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── FunctionSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── GenericIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── GenericMetadata/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── GenericPipeAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── GenericPipeActionAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── GenericPipeItem/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── GenericPipeItemAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── GenericSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── GenericSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── GenericTransformation/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── GenericTransformationAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── GenericValidation/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── GenericValidationAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── GlobalConfig/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── GraphemesAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── GraphemesIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── GtValueAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── GtValueIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── GuardAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── GuardFunction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── GuardIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── HashAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── HashIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── HashType/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── HexColorAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── HexColorIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── HexadecimalAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── HexadecimalIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ImeiAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ImeiIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IncludesAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IncludesIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── InferDefault/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferDefaults/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferExamples/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferFallback/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferFallbacks/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferGuardOutput/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── InferInput/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── InferIntersectInput/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferIntersectOutput/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── InferMapInput/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── InferMapOutput/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── InferMetadata/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferNonNullableInput/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferNonNullableIssue/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferNonNullableOutput/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferNonNullishInput/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferNonNullishIssue/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferNonNullishOutput/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferNonOptionalInput/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferNonOptionalIssue/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferNonOptionalOutput/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferNullableOutput/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── InferNullishOutput/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── InferObjectInput/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferObjectIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── InferObjectOutput/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferOptionalOutput/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── InferOutput/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── InferRecordInput/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferRecordOutput/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferSetInput/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── InferSetOutput/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── InferTupleInput/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferTupleIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── InferTupleOutput/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── InferVariantIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── InstanceIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── InstanceSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IntegerAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IntegerIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IntersectIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IntersectOptions/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IntersectOptionsAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IntersectSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IntersectSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IpAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IpIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Ipv4Action/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Ipv4Issue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Ipv6Action/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Ipv6Issue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IsbnAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IsbnIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IsoDateAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IsoDateIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IsoDateTimeAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IsoDateTimeIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IsoTimeAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IsoTimeIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IsoTimeSecondAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IsoTimeSecondIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IsoTimestampAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IsoTimestampIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IsoWeekAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IsoWeekIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IsrcAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IsrcIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── IssueDotPath/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── IssuePathItem/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── JwsCompactAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── JwsCompactIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── LastTupleItem/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── LazySchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── LazySchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── LengthAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── LengthInput/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── LengthIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Literal/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── LiteralIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── LiteralSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── LooseObjectIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── LooseObjectSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── LooseObjectSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── LooseTupleIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── LooseTupleSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── LooseTupleSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── LtValueAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── LtValueIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Mac48Action/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Mac48Issue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Mac64Action/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Mac64Issue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MacAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MacIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MapIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MapItemsAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MapPathItem/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MapSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MapSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MaxBytesAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MaxBytesIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MaxEntriesAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MaxEntriesIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MaxGraphemesAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MaxGraphemesIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MaxLengthAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MaxLengthIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MaxSizeAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MaxSizeIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MaxValueAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MaxValueIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MaxWordsAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MaxWordsIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MaybePromise/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MaybeReadonly/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MetadataAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MimeTypeAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MimeTypeIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MinBytesAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MinBytesIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MinEntriesAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MinEntriesIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MinGraphemesAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MinGraphemesIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MinLengthAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MinLengthIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MinSizeAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MinSizeIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MinValueAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MinValueIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MinWordsAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MinWordsIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MultipleOfAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── MultipleOfIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NanIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NanSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NeverIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NeverSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NonEmptyAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NonEmptyIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NonNullable/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NonNullableIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NonNullableSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NonNullableSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NonNullish/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NonNullishIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NonNullishSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NonNullishSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NonOptional/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NonOptionalIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NonOptionalSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NonOptionalSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NormalizeAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NormalizeForm/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NotBytesAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NotBytesIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NotEntriesAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NotEntriesIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NotGraphemesAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NotGraphemesIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NotLengthAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NotLengthIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NotSizeAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NotSizeIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NotValueAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NotValueIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NotValuesAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NotValuesIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NotWordsAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NotWordsIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NullIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NullSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NullableSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NullableSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NullishSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NullishSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NumberIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── NumberSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ObjectEntries/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ObjectEntriesAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ObjectIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ObjectKeys/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ObjectPathItem/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ObjectSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ObjectSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ObjectWithRestIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ObjectWithRestSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ObjectWithRestSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── OctalAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── OctalIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── OptionalSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── OptionalSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── OutputDataset/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ParseBooleanAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ParseBooleanConfig/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ParseBooleanIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ParseJsonAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ParseJsonConfig/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ParseJsonIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Parser/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ParserAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── PartialCheckAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── PartialCheckActionAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── PartialCheckIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── PartialDataset/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── PartialInput/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Path/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── PicklistIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── PicklistOptions/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── PicklistSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── PipeAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── PipeActionAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── PipeItem/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── PipeItemAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── PromiseIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── PromiseSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── RawCheckAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── RawCheckActionAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── RawCheckAddIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── RawCheckContext/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── RawCheckIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── RawCheckIssueInfo/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── RawTransformAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── RawTransformActionAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── RawTransformAddIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── RawTransformContext/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── RawTransformIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── RawTransformIssueInfo/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ReadonlyAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── RecordIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── RecordSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── RecordSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ReduceItemsAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── Reference/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── RegexAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── RegexIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── RequiredPath/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── RequiredPaths/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ReturnsAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ReturnsActionAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── RfcEmailAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── RfcEmailIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SafeIntegerAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SafeIntegerIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SafeParseResult/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SafeParser/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SafeParserAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SchemaWithCache/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SchemaWithCacheAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SchemaWithFallback/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SchemaWithFallbackAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SchemaWithPartial/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── SchemaWithPartialAsync/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── SchemaWithPipe/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SchemaWithPipeAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SchemaWithRequired/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── SchemaWithRequiredAsync/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── SchemaWithoutPipe/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SetIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SetPathItem/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SetSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SetSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SizeAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SizeInput/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SizeIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SlugAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SlugIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SomeItemAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SomeItemIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SortItemsAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── StandardFailureResult/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── StandardIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── StandardPathItem/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── StandardProps/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── StandardResult/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── StandardSuccessResult/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── StandardTypes/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── StartsWithAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── StartsWithIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── StrictObjectIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── StrictObjectSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── StrictObjectSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── StrictTupleIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── StrictTupleSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── StrictTupleSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── StringIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── StringSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── StringifyJsonAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── StringifyJsonConfig/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── StringifyJsonIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SuccessDataset/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SymbolIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── SymbolSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── TitleAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ToBigintAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ToBigintIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ToBooleanAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ToDateAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ToDateIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ToLowerCaseAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ToMaxValueAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ToMinValueAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ToNumberAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ToNumberIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ToStringAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ToStringIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ToUpperCaseAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── TransformAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── TransformActionAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── TrimAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── TrimEndAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── TrimStartAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── TupleIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── TupleItems/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── TupleItemsAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── TupleSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── TupleSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── TupleWithRestIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── TupleWithRestSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── TupleWithRestSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── UlidAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── UlidIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── UndefinedIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── UndefinedSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── UndefinedableSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── UndefinedableSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── UnionIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── UnionOptions/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── UnionOptionsAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── UnionSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── UnionSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── UnknownDataset/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── UnknownPathItem/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── UnknownSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── UrlAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── UrlIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── UuidAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── UuidIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ValueAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ValueInput/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ValueIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ValuesAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── ValuesIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── VariantIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── VariantOption/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── VariantOptionAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── VariantOptions/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── VariantOptionsAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── VariantSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── VariantSchemaAsync/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── VoidIssue/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── VoidSchema/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── WordsAction/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ └── WordsIssue/ │ │ │ │ ├── index.mdx │ │ │ │ └── properties.ts │ │ │ ├── (utils)/ │ │ │ │ ├── ValiError/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── entriesFromList/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── entriesFromObjects/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── getDotPath/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── isOfKind/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ ├── isOfType/ │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── properties.ts │ │ │ │ └── isValiError/ │ │ │ │ ├── index.mdx │ │ │ │ └── properties.ts │ │ │ ├── index.tsx │ │ │ ├── layout.tsx │ │ │ └── menu.md │ │ ├── blog/ │ │ │ ├── (posts)/ │ │ │ │ ├── first-draft-of-the-new-pipe-function/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── how-valibot-has-evolved-this-year/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── introducing-open-circle/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── json-schema-package-upgrade/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── layout.tsx │ │ │ │ ├── should-we-change-the-object-schema/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── should-we-change-valibots-api/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── valibot-v0.31.0-is-finally-available/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── valibot-v1-rc-is-available/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── valibot-v1-the-1-kb-schema-library/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── valibot-v1.1-release-notes/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── valibot-v1.2-release-notes/ │ │ │ │ │ └── index.mdx │ │ │ │ └── valibot-v1.3-release-notes/ │ │ │ │ └── index.mdx │ │ │ └── index.tsx │ │ ├── guides/ │ │ │ ├── (advanced)/ │ │ │ │ ├── async-validation/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── extend-valibot/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── integrate-valibot/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── internal-architecture/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── internationalization/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── json-schema/ │ │ │ │ │ └── index.mdx │ │ │ │ └── naming-convention/ │ │ │ │ └── index.mdx │ │ │ ├── (get-started)/ │ │ │ │ ├── comparison/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── ecosystem/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── installation/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── introduction/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── llms-txt/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── quick-start/ │ │ │ │ │ └── index.mdx │ │ │ │ └── use-cases/ │ │ │ │ └── index.mdx │ │ │ ├── (main-concepts)/ │ │ │ │ ├── errors/ │ │ │ │ │ └── index.tsx │ │ │ │ ├── infer-types/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── issues/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── mental-model/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── methods/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── parse-data/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── pipelines/ │ │ │ │ │ └── index.mdx │ │ │ │ └── schemas/ │ │ │ │ └── index.mdx │ │ │ ├── (migration)/ │ │ │ │ ├── migrate-from-v0.30.0/ │ │ │ │ │ └── index.ts │ │ │ │ ├── migrate-from-zod/ │ │ │ │ │ ├── CodemodEditor.tsx │ │ │ │ │ ├── index.mdx │ │ │ │ │ └── zod/ │ │ │ │ │ ├── code.ts │ │ │ │ │ ├── v3/ │ │ │ │ │ │ ├── index.d.ts │ │ │ │ │ │ └── package.json │ │ │ │ │ └── v4/ │ │ │ │ │ ├── index.d.ts │ │ │ │ │ └── package.json │ │ │ │ └── migrate-to-v0.31.0/ │ │ │ │ └── index.mdx │ │ │ ├── (schemas)/ │ │ │ │ ├── arrays/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── enums/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── intersections/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── objects/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── optionals/ │ │ │ │ │ └── index.mdx │ │ │ │ ├── other/ │ │ │ │ │ └── index.mdx │ │ │ │ └── unions/ │ │ │ │ └── index.mdx │ │ │ ├── index.tsx │ │ │ ├── layout.tsx │ │ │ └── menu.md │ │ ├── index.tsx │ │ ├── layout.tsx │ │ ├── og-image/ │ │ │ └── index.ts │ │ ├── playground/ │ │ │ ├── editorCode.ts │ │ │ ├── iframeCode.js │ │ │ └── index.tsx │ │ ├── plugin@chapters.ts │ │ └── plugin@theme.ts │ ├── styles/ │ │ ├── pace.css │ │ └── root.css │ └── utils/ │ ├── disableTransitions.ts │ ├── index.ts │ └── trackEvent.ts ├── tsconfig.json ├── vercel.json └── vite.config.ts ================================================ FILE CONTENTS ================================================ ================================================ FILE: .agents/skills/repo-source-code-document/SKILL.md ================================================ --- name: repo-source-code-document description: Write JSDoc comments and inline documentation for Valibot library source code in /library/src/. Use when documenting schemas, actions, methods, or utilities. Covers interface documentation, function overloads, purity annotations, inline comment patterns, and terminology consistency. --- # Valibot Source Code Documentation Documentation patterns for library source code in `/library/src/`. ## JSDoc Patterns ### Interface Documentation ```typescript /** * String issue interface. */ export interface StringIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'string'; } ``` **Rules:** - First line: `[Name] [category] interface.` (e.g., "String issue interface.") - Property comments: `The [description].` (always start with "The", end with period) - All properties use `readonly` - No blank lines between property and its comment ### Function Overloads Each overload gets its own complete JSDoc: ```typescript /** * Creates a string schema. * * @returns A string schema. */ export function string(): StringSchema; /** * Creates a string schema. * * @param message The error message. * * @returns A string schema. */ export function string< const TMessage extends ErrorMessage | undefined, >(message: TMessage): StringSchema; ``` **Rules:** - First line: `Creates a [name] [category].` (use "a" vs "an" correctly) - Blank line after description - `@param name The [description].` (start with "The", end with period) - Blank line after params - `@returns A [name] [category].` or `@returns The [description].` ### Hints Add hints after the main description, before `@param`: ```typescript /** * Creates an object schema. * * Hint: This schema removes unknown entries. To include unknown entries, use * `looseObject`. To reject unknown entries, use `strictObject`. * * @param entries The entries schema. * * @returns An object schema. */ ``` ### Links Link to external resources when relevant using markdown format: ```typescript /** * Creates an [email](https://en.wikipedia.org/wiki/Email_address) validation action. */ ``` ### Implementation Function The implementation has **NO JSDoc** but uses `// @__NO_SIDE_EFFECTS__`: ```typescript // @__NO_SIDE_EFFECTS__ export function string( message?: ErrorMessage ): StringSchema | undefined> { return { /* ... */ }; } ``` **`// @__NO_SIDE_EFFECTS__` rules:** - Add for pure functions (no external state mutation, no I/O) - Most schema/action/method factories are pure - **Do NOT add** for functions that mutate arguments (like `_addIssue`) - Used by bundlers for tree-shaking ### Utility Functions ```typescript /** * Stringifies an unknown input to a literal or type string. * * @param input The unknown input. * * @returns A literal or type string. * * @internal */ // @__NO_SIDE_EFFECTS__ export function _stringify(input: unknown): string { // ... } ``` **Rules:** - Use `@internal` tag for internal utilities - Prefix internal functions with `_` - Only add `// @__NO_SIDE_EFFECTS__` if function is pure ## Inline Comment Patterns ### Section Headers ```typescript '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (Array.isArray(input)) { // Set typed to true and value to empty array dataset.typed = true; dataset.value = []; // Parse schema of each array item for (let key = 0; key < input.length; key++) { // ... } } } ``` **Rules:** - Describe WHAT the next code block does - Present tense verbs: "Get", "Parse", "Check", "Set", "Add", "Create" - **Omit articles** ("the", "a", "an"): "Get input value" not "Get the input value" - No period at end - Blank line before comment, no blank line after ### Conditional Logic ```typescript // If root type is valid, check nested types if (input && typeof input === 'object') { // ... } // Otherwise, add issue else { _addIssue(this, 'type', dataset, config); } ``` **Rules:** - Use "If [condition], [action]" - Use "Otherwise, [action]" for else branches - Omit articles ### Hint Comments (Exception) ```typescript // Hint: The issue is deliberately not constructed with the spread operator // for performance reasons const issue: BaseIssue = { /* ... */ }; ``` **Rules:** - Start with "Hint:" - Explain WHY, not just what - **CAN use articles** (unlike other inline comments) - Document performance decisions, non-obvious logic ### TODO Comments ```typescript // TODO: Should we add "n" suffix to bigints? if (type === 'bigint') { /* ... */ } ``` ### @ts-expect-error Used for internal dataset mutations TypeScript can't track: ```typescript // @ts-expect-error dataset.typed = true; ``` ## File Type Patterns ### Schema Files (`string.ts`, `object.ts`, etc.) 1. Issue interface with JSDoc 2. Schema interface with JSDoc 3. Function overloads with full JSDoc each 4. Implementation with `// @__NO_SIDE_EFFECTS__` 5. Return object with `'~run'` method containing inline comments ### Action Files (`email.ts`, `minLength.ts`, etc.) 1. Issue interface (for validation actions) 2. Action interface with JSDoc 3. Function overloads with JSDoc 4. Implementation with `// @__NO_SIDE_EFFECTS__` ### Method Files (`parse.ts`, `pipe.ts`, etc.) More complex logic, require more inline comments. ### Utility Files (`_addIssue.ts`, `_stringify.ts`) 1. Single function with JSDoc including `@internal` 2. `// @__NO_SIDE_EFFECTS__` only if pure ## Terminology Consistency JSDoc descriptions must match the `kind` property if present: | `kind` Property | JSDoc Wording | | ------------------ | -------------------------------------- | | `'schema'` | "Creates a ... schema." | | `'validation'` | "Creates a ... validation action." | | `'transformation'` | "Creates a ... transformation action." | ## Quick Reference ### JSDoc First Lines | Type | Pattern | | --------- | ------------------------------ | | Interface | `[Name] [category] interface.` | | Type | `[Name] [category] type.` | | Function | `Creates a [name] [category].` | | Utility | `[Verb]s [description].` | ### Inline Comment Starters | Pattern | Example | | ------------------------------ | ---------------------------------------------- | | `// Get [what]` | `// Get input value from dataset` | | `// If [condition], [action]` | `// If root type is valid, check nested types` | | `// Otherwise, [action]` | `// Otherwise, add issue` | | `// Create [what]` | `// Create object path item` | | `// Add [what] to [where]` | `// Add issues to dataset` | | `// Parse [what]` | `// Parse schema of each array item` | | `// Set [property] to [value]` | `// Set typed to true` | | `// Hint: [explanation]` | `// Hint: This is for performance` | | `// TODO: [task]` | `// TODO: Add bigint suffix` | ## Terminology Use consistently: - **Schema** (not "validator") - **Action** (not "validation" for the object) - **Issue** (not "error" in type names) - **Dataset** (internal data structure) - **Config/Configuration** (not "options") ## Checklist - [ ] Interfaces: `[Name] [category] interface.` - [ ] Properties: `The [description].` - [ ] Overloads: Complete JSDoc each - [ ] Implementation: NO JSDoc - [ ] Pure functions: `// @__NO_SIDE_EFFECTS__` - [ ] Impure functions (mutate args): NO `@__NO_SIDE_EFFECTS__` - [ ] Internal utilities: `@internal` tag - [ ] Inline comments: No articles (except Hint), no periods - [ ] JSDoc comments: End with periods ================================================ FILE: .agents/skills/repo-source-code-review/SKILL.md ================================================ --- name: repo-source-code-review description: Review pull requests and source code changes in /library/src/. Use when reviewing PRs, validating implementation patterns, or checking code quality before merging. Covers code quality checks, type safety, documentation review, test coverage, and common issues to watch for. --- # Reviewing Source Code Changes Guide for reviewing PRs and source code changes in `/library/src/`. ## When to Use This Guide - Reviewing pull requests modifying library source - Validating implementation patterns before merging - Checking code quality, types, documentation, and tests ## Review Process 1. **Understand the change** — Read PR description, identify affected files 2. **Check patterns** — Verify code follows existing conventions 3. **Verify types** — Ensure type safety and proper inference 4. **Review docs** — Confirm JSDoc is complete and accurate 5. **Check tests** — Validate runtime and type test coverage ## What to Review ### Code Quality | Check | Requirement | | ----------------- | --------------------------------------------------------------------- | | Naming | Matches existing patterns (`StringSchema`, `minLength`, `_parse`) | | Purity annotation | `// @__NO_SIDE_EFFECTS__` before pure factory functions | | Import extensions | All imports use `.ts` extension | | Interface vs type | Use `interface` for object shapes, `type` for unions/aliases | | Folder structure | Each API has: `name.ts`, `name.test.ts`, `name.test-d.ts`, `index.ts` | **Good — purity annotation:** ```typescript // @__NO_SIDE_EFFECTS__ export function string(message?: ErrorMessage): StringSchema { return { /* ... */ }; } ``` **Bad — missing annotation:** ```typescript export function string(message?: ErrorMessage): StringSchema { return { /* ... */ }; } ``` ### Type Safety | Check | Requirement | | ----------------- | ----------------------------------------------------- | | Generic inference | Types infer correctly without explicit annotations | | Constraints | Generic parameters have appropriate `extends` clauses | | Return types | Explicit return types on exported functions | | Type tests | `.test-d.ts` file covers type inference scenarios | **Good — constrained generic:** ```typescript export function minLength< TInput extends LengthInput, TRequirement extends number, >( requirement: TRequirement, message?: ErrorMessage> ): MinLengthAction; ``` ### Documentation | Check | Requirement | | -------------- | ------------------------------------------------- | | JSDoc present | All exported functions have JSDoc | | First line | Action verb matching function purpose (see below) | | `@param` tags | Every parameter documented | | `@returns` tag | Return value documented | | Overloads | Every overload has its own complete JSDoc block | **First line patterns by category:** | Category | Pattern | | -------------- | ---------------------------------------------- | | Schemas | `Creates a ... schema.` | | Actions | `Creates a ... action.` | | Parse methods | `Parses ...` | | Type guards | `Checks if ...` | | Unwrap methods | `Unwraps ...` | | Other methods | `Creates a ...`, `Returns ...`, `Forwards ...` | See `repo-source-code-document` skill for full documentation rules. ### Tests | Check | Requirement | | -------------- | ---------------------------------------------------------- | | Runtime tests | `.test.ts` covers success cases, failure cases, edge cases | | Type tests | `.test-d.ts` validates type inference with `expectTypeOf` | | Issue messages | Tests verify correct error messages and issue structure | ## Common Issues | Issue | What to Look For | | ------------------------- | ------------------------------------------------------------ | | Missing purity annotation | Factory function without `// @__NO_SIDE_EFFECTS__` | | Incomplete JSDoc | Missing `@param` or `@returns`, wrong description format | | No type tests | New API without `.test-d.ts` file | | Wrong import extension | Imports without `.ts` suffix | | Inconsistent naming | Schema not ending in `Schema`, action not ending in `Action` | | Side effects in pure code | Mutations, I/O, or global state in schema/action creation | ## Checklist - [ ] Implementation follows existing patterns in similar files - [ ] `// @__NO_SIDE_EFFECTS__` on pure factory functions - [ ] All imports use `.ts` extension - [ ] `interface` used for object shapes - [ ] JSDoc complete on all exports - [ ] Runtime tests in `.test.ts` - [ ] Type tests in `.test-d.ts` - [ ] Naming conventions followed ## Related Skills - `repo-structure-navigate` — Navigate the codebase - `repo-source-code-document` — JSDoc requirements ================================================ FILE: .agents/skills/repo-structure-navigate/SKILL.md ================================================ --- name: repo-structure-navigate description: Navigate the Valibot repository structure. Use when looking for files, understanding the codebase layout, finding schema/action/method implementations, locating tests, API docs, or guide pages. Covers monorepo layout, library architecture, file naming conventions, and quick lookups. --- # Valibot Repository Structure ## Monorepo Layout ``` valibot/ ├── library/ # Core valibot package (zero dependencies) ├── packages/ │ ├── i18n/ # Translated error messages (25+ languages) │ └── to-json-schema/ # JSON Schema converter ├── codemod/ │ ├── migrate-to-v0.31.0/ # Version migration │ └── zod-to-valibot/ # Zod converter ├── website/ # valibot.dev (Qwik + Vite) ├── brand/ # Brand assets ├── skills/ # Agent skills (this folder) └── prompts/ # Legacy AI agent guides ``` ## Core Library (`/library/src/`) ### Directory Structure | Directory | Purpose | Examples | | ----------- | ------------------------------- | --------------------------------------------- | | `schemas/` | Data type validators | `string/`, `object/`, `array/`, `union/` | | `actions/` | Validation & transformation | `email/`, `minLength/`, `trim/`, `transform/` | | `methods/` | High-level API | `parse/`, `safeParse/`, `pipe/`, `partial/` | | `types/` | TypeScript definitions | `schema.ts`, `issue.ts`, `dataset.ts` | | `utils/` | Internal helpers (prefixed `_`) | `_addIssue/`, `_stringify/`, `ValiError/` | | `storages/` | Global state | Config, message storage | ### Schema Categories - **Primitives**: `string`, `number`, `boolean`, `bigint`, `date`, `symbol`, `blob`, `file` - **Objects**: `object`, `strictObject`, `looseObject`, `objectWithRest` - **Arrays**: `array`, `tuple`, `strictTuple`, `looseTuple`, `tupleWithRest` - **Advanced**: `union`, `variant`, `intersect`, `record`, `map`, `set`, `lazy`, `custom` - **Modifiers**: `optional`, `nullable`, `nullish`, `nonNullable`, `nonNullish`, `nonOptional` ### Action Types **Validation** (return issues): `email`, `url`, `uuid`, `regex`, `minLength`, `maxValue`, `check` **Transformation** (modify data): `trim`, `toLowerCase`, `toUpperCase`, `mapItems`, `transform` **Metadata**: `brand`, `flavor`, `metadata`, `description`, `title` ### File Naming Convention Each schema/action/method has its own directory: ``` schemas/string/ ├── string.ts # Implementation ├── string.test.ts # Runtime tests ├── string.test-d.ts # Type tests └── index.ts # Re-export ``` ### Core Patterns **Schemas** define data types: ```typescript export interface StringSchema extends BaseSchema<...> { readonly kind: 'schema'; readonly type: 'string'; // ... } ``` **Actions** validate/transform in pipelines: ```typescript export interface EmailAction extends BaseValidation<...> { readonly kind: 'validation'; readonly type: 'email'; // ... } ``` **Methods** provide API functions: ```typescript export function parse( schema: TSchema, input: unknown ): InferOutput; ``` ### Key Types - `BaseSchema`, `BaseValidation`, `BaseTransformation` - Base interfaces - `InferOutput`, `InferInput`, `InferIssue` - Type inference - `Config`, `ErrorMessage`, `BaseIssue` - Configuration and errors - `'~standard'` property - [Standard Schema](https://github.com/standard-schema/standard-schema) compatibility ## Website (`/website/src/routes/`) ### API Documentation ``` routes/api/ ├── (schemas)/string/ # Schema docs │ ├── index.mdx # MDX content │ └── properties.ts # Type definitions ├── (actions)/email/ # Action docs ├── (methods)/parse/ # Method docs ├── (types)/StringSchema/ # Type docs └── menu.md # Navigation ``` ### Guides ``` routes/guides/ ├── (get-started)/ # Intro, installation ├── (main-concepts)/ # Schemas, pipelines, parsing ├── (schemas)/ # Objects, arrays, unions ├── (advanced)/ # Async, i18n, JSON Schema ├── (migration)/ # Version upgrades └── menu.md # Navigation ``` ## Development ### Playground Use `library/playground.ts` for quick experimentation. ### Adding a Schema/Action 1. Create directory: `library/src/schemas/yourSchema/` 2. Create files: `yourSchema.ts`, `yourSchema.test.ts`, `yourSchema.test-d.ts`, `index.ts` 3. Follow existing patterns (copy similar implementation) 4. Export from category `index.ts` 5. Run `pnpm -C library test` ### Modifying Core Types ⚠️ Changes to `library/src/types/` affect the entire library. Always run full test suite. ## Quick Lookups | Looking for... | Location | | --------------------- | ---------------------------------------------- | | Schema implementation | `library/src/schemas/[name]/[name].ts` | | Action implementation | `library/src/actions/[name]/[name].ts` | | Method implementation | `library/src/methods/[name]/[name].ts` | | Type definitions | `library/src/types/` | | Internal utilities | `library/src/utils/` | | Error messages (i18n) | `packages/i18n/[lang]/` | | API docs page | `website/src/routes/api/(category)/[name]/` | | Guide page | `website/src/routes/guides/(category)/[name]/` | | Tests | Same directory as source, `.test.ts` suffix | | Type tests | Same directory as source, `.test-d.ts` suffix | ## Commands ```bash # Library pnpm -C library build # Build pnpm -C library test # Run tests pnpm -C library lint # Lint pnpm -C library format # Format # Website pnpm -C website dev # Dev server pnpm -C website build # Production build # Root pnpm install # Install all pnpm format # Format all ``` ## Key Principles 1. **Modularity** - Small, focused functions; one per file 2. **Zero dependencies** - Core library has no runtime deps 3. **100% test coverage** - Required for library 4. **Tree-shakable** - Use `// @__NO_SIDE_EFFECTS__` annotation 5. **Type-safe** - Full TypeScript with strict mode 6. **ESM only** - Imports include `.ts` extensions ## Do's and Don'ts **Do:** - Follow existing code patterns - Write runtime and type tests - Add JSDoc documentation - Keep functions small and focused - Check bundle size impact **Don't:** - Add external dependencies - Modify core types without full test run - Skip tests - Create large multi-purpose functions - Modify generated files (`dist/`, `coverage/`) ================================================ FILE: .agents/skills/repo-website-api-create/SKILL.md ================================================ --- name: repo-website-api-create description: Create new API reference pages for the Valibot website at website/src/routes/api/. Use when adding documentation for new schemas, actions, methods, or types. Covers reading source code, creating properties.ts and index.mdx files, updating menu.md, and cross-referencing related APIs. --- # Adding API Documentation to Website Guide for creating new API reference pages at `website/src/routes/api/`. ## Process Overview 1. Read source code in `/library/src/` 2. Create folder in `/website/src/routes/api/(category)/[name]/` 3. Create `properties.ts` with type definitions 4. Create `index.mdx` with documentation 5. Update `menu.md` 6. Create type documentation if needed (Issue, Schema/Action interfaces) ## File Structure ``` website/src/routes/api/ ├── (schemas)/string/ │ ├── index.mdx # Documentation content │ └── properties.ts # Type definitions for Property component ├── (actions)/email/ ├── (methods)/parse/ ├── (types)/StringSchema/ └── menu.md # Navigation (alphabetical order) ``` Categories: `(schemas)`, `(actions)`, `(methods)`, `(types)`, `(utils)`, `(async)`, `(storages)` ## Reading Source Code ### What to Extract From `/library/src/schemas/string/string.ts`: ```typescript // 1. Issue interface → Document in (types)/StringIssue/ export interface StringIssue extends BaseIssue { ... } // 2. Schema interface → Document in (types)/StringSchema/ export interface StringSchema | undefined> extends BaseSchema { ... } // 3. Function overloads → Main documentation export function string(): StringSchema; export function string(message: TMessage): StringSchema; // 4. JSDoc → Description, hints, parameter docs /** * Creates a string schema. * * Hint: This is an example hint. * * @param message The error message. * * @returns A string schema. */ ``` **JSDoc hints** become blockquotes in the Explanation section: ```mdx > This is an example hint. ``` ### Extract for properties.ts - Generic parameters and constraints (e.g., `TMessage extends ErrorMessage<...> | undefined`) - Function parameters and types - Return type ## properties.ts Import and define properties matching source code: ```typescript import type { PropertyProps } from '~/components'; export const properties: Record = { // Generics (use modifier: 'extends') TMessage: { modifier: 'extends', type: { type: 'union', options: [ { type: 'custom', name: 'ErrorMessage', href: '../ErrorMessage/', generics: [ { type: 'custom', name: 'StringIssue', href: '../StringIssue/' }, ], }, 'undefined', ], }, }, // Parameters (reference generic or direct type) message: { type: { type: 'custom', name: 'TMessage' }, }, // Return type Schema: { type: { type: 'custom', name: 'StringSchema', href: '../StringSchema/', generics: [{ type: 'custom', name: 'TMessage' }], }, }, }; ``` ### Optional Object Keys For optional object keys from TypeScript source such as `key?: string`, do not append `?` to the property name in `properties.ts`. Use the plain key name and represent optionality in the value type with `undefined` as the last union option: ```typescript payload: { type: { type: 'object', entries: [ { key: 'key', value: { type: 'union', options: ['string', 'undefined'], }, }, ], }, }, ``` ### DefinitionData Types | Type | Syntax | | --------------- | ------------------------------------------------------------------------------ | | Primitive | `'string'`, `'number'`, `'boolean'`, `'unknown'`, etc. | | Literal string | `{ type: 'string', value: 'email' }` | | Literal number | `{ type: 'number', value: 5 }` | | Custom/Named | `{ type: 'custom', name: 'TypeName', href: '../TypeName/', generics: [...] }` | | Custom+modifier | `{ type: 'custom', modifier: 'typeof', name: 'string', href: '../string/' }` | | Union | `{ type: 'union', options: [type1, type2] }` | | Intersect | `{ type: 'intersect', options: [type1, type2] }` | | Array | `{ type: 'array', item: elementType }` | | Tuple | `{ type: 'tuple', items: [type1, type2] }` | | Object | `{ type: 'object', entries: [{ key: 'name', value: type }] }` | | Function | `{ type: 'function', params: [{ name: 'x', type: t }], return: retType }` | | Template | `{ type: 'template', parts: [{ type: 'string', value: '>=' }, otherType] }` | ## index.mdx Template ```mdx --- title: functionName description: One-line description from JSDoc. source: /schemas/string/string.ts contributors: - github-username --- import { ApiList, Property } from '~/components'; import { properties } from './properties'; # functionName Creates a string schema. \`\`\`ts const Schema = v.functionName(message); \`\`\` ## Generics - \`TMessage\` ## Parameters - \`message\` ### Explanation With \`functionName\` you can validate... If the input does not match, you can use \`message\` to customize the error message. ## Returns - \`Schema\` ## Examples The following examples show how \`functionName\` can be used. ### Email schema Schema to validate an email. \`\`\`ts const EmailSchema = v.pipe( v.string(), v.nonEmpty('Please enter your email.'), v.email('The email is badly formatted.') ); \`\`\` ## Related The following APIs can be combined with \`functionName\`. ### Schemas ### Methods ### Actions ### Utils ``` **Related section order:** Schemas → Methods → Actions → Utils (omit empty sections) ## Key Conventions ### Naming - Schema variables: `PascalCase` + `Schema` suffix: `EmailSchema`, `UserSchema` - Action variables: `PascalCase` + `Action`: `MinLengthAction` - Parse output: `output` or descriptive name ### Examples - Always include error messages for validation actions - Progress from simple to complex - Use realistic, practical scenarios - Start with `import * as v from 'valibot';` pattern ### Error Messages Use friendly, actionable messages: - ✅ "Your password is too short." - ✅ "Please enter your email." - ❌ "Invalid" or "Error" ### Links - Use `href: '../TypeName/'` for type references (with trailing slash) - Use `\`parse\``in MDX prose (import from`~/components`) - Link to related guides when relevant: `object guide` ## Update Related Files ### menu.md Add alphabetically to `/website/src/routes/api/menu.md`: ```markdown ## Schemas - [any](/api/any/) - [newSchema](/api/newSchema/) ← Add here - [string](/api/string/) ``` ### Related Sections of Other API Docs Existing API pages have a `## Related` section with `` components. When adding a new API, update related APIs to include the new one. **Rule:** An API is "related" if: - It makes sense to use it as an argument of the other API, or vice versa - It makes sense to use them together in the same `pipe` (e.g., `v.pipe(v.string(), v.email())` → `string` and `email` are related) Examples: - `string` schema lists `email` action because they work together in a pipe - `email` action lists `string` schema because it validates string input - `pipe` method lists all schemas because any schema can be piped - `minLength` action lists `string`, `array`, `tuple` because it validates their length **Process:** 1. Review a few existing API docs in the same category to understand the pattern 2. Check `menu.md` to identify potentially related APIs 3. For each related API, edit its `index.mdx` and add the new API to the appropriate `` **Shortcut:** If your new API is very similar to an existing one (e.g., `guard` is similar to `check`), add it everywhere the similar API appears. This ensures consistent coverage across all related docs. ### Concept Guides Add the new API to the appropriate guide in `/website/src/routes/guides/`: | API Category | Guide to Update | | ------------ | ------------------------------------- | | Schema | `(main-concepts)/schemas/index.mdx` | | Action | `(main-concepts)/pipelines/index.mdx` | | Method | `(main-concepts)/methods/index.mdx` | Also update topic-specific guides if relevant (e.g., `(schemas)/objects/`, `(schemas)/arrays/`, `(advanced)/async/`). ### Type Documentation Create pages for new types in `(types)/`: - Issue interfaces (e.g., `StringIssue`) - Schema/Action interfaces (e.g., `StringSchema`) Type pages differ from function docs: - **No `source` field** in frontmatter - **No Examples or Related sections** - Use `## Definition` instead of `## Returns` Type page structure: ```mdx --- title: StringSchema description: String schema interface. contributors: - github-username --- import { Property } from '~/components'; import { properties } from './properties'; # StringSchema String schema interface. ## Generics - \`TMessage\` ## Definition - \`StringSchema\` - \`type\` - \`reference\` - \`expects\` - \`message\` ``` ## Checklist - [ ] Read source file completely - [ ] `properties.ts` matches source types exactly - [ ] `index.mdx` signature matches source - [ ] All generics documented - [ ] All parameters documented - [ ] Examples are realistic with error messages - [ ] `menu.md` updated (alphabetically) - [ ] Related type pages created if needed - [ ] Related API docs updated (add new API to their `## Related` sections) - [ ] Concept guide updated (schemas/pipelines/methods) - [ ] All `href` links valid with trailing slashes ================================================ FILE: .agents/skills/repo-website-api-update/SKILL.md ================================================ --- name: repo-website-api-update description: Update existing API documentation pages after source code changes. Use when syncing docs with library changes like new parameters, type constraint changes, interface updates, or function renames. Covers common change patterns and verification steps. --- # Updating API Documentation Guide for syncing API docs with source code changes. **Prerequisite:** Read the `repo-website-api-create` skill for `properties.ts` and `index.mdx` patterns. ## When to Update Update documentation when source code changes: - Function signatures (parameters, generics, return types) - Interface properties - JSDoc descriptions or hints - Behavior changes affecting examples **Do NOT update for:** Internal implementation changes (`~run` method), test changes, non-JSDoc comments. ## Process 1. **Read full source file** - Don't just look at diff; understand complete current state 2. **Identify changes** - Categorize as addition, removal, or modification 3. **Update `properties.ts`** - Match types exactly to source; for optional object keys, keep the plain key name and use a union with `undefined` as the last option instead of appending `?` 4. **Update `index.mdx`** - Signature, generics, parameters, examples 5. **Update related files** - Type docs, `menu.md` if renamed ## Common Change Types ### New Parameter Added ```typescript // Before: one overload export function action(requirement: TRequirement): Action<...>; // After: two overloads (message is optional) export function action(requirement: TRequirement): Action<..., undefined>; export function action(requirement: TRequirement, message: TMessage): Action<..., TMessage>; ``` Update: 1. Add `TMessage` generic to `properties.ts` 2. Add `message` parameter to `properties.ts` 3. Update signature in `index.mdx` 4. Add generic and parameter documentation 5. Update examples to show new parameter ### Parameter Removed (Breaking) 1. Remove from `properties.ts` 2. Update signature in `index.mdx` 3. Remove from Parameters section 4. Update all examples 5. Consider adding migration note in Explanation ### Type Constraint Changed ```typescript // Before TRequirement extends number // After TRequirement extends number | string ``` Update: 1. Update type in `properties.ts` 2. Update Explanation to mention both types 3. Add examples for new type usage ### Interface Property Added 1. Update type documentation in `(types)/TypeName/` 2. Add new property to `properties.ts`; if the source key is optional, do not append `?` to the key name and model it as a union with `undefined` last 3. Document in Definition section ### Function Renamed 1. Rename folder 2. Update all references in files 3. Update `menu.md` (maintain alphabetical order) 4. Update cross-references in related API docs 5. Consider redirect if widely used ### Deprecation Add notice at top of `index.mdx` (import `Link` from `~/components`): ```mdx > **⚠️ Deprecated**: Use \`newFunction\` instead. Will be removed in v2.0. ``` ### New Helper Type Introduced When source introduces a type alias: ```typescript // Before: TInput extends string | unknown[] // After: TInput extends LengthInput ``` 1. Update `properties.ts` to reference new type with `href` 2. Create documentation for the new type in `(types)/` 3. Update explanation if supported types changed ### Multiple Overloads Added (Sync/Async) When sync and async variants are added: 1. Update signature to show general pattern or both overloads 2. Add explanation about sync vs async usage 3. Add examples for both use cases 4. Update Related section for async schemas if relevant ## Related Files to Update When a function changes, check: - **Type docs** - If interfaces changed (`(types)/TypeName/`) - **Related API docs** - Other APIs that reference this function in their Related section - **Guide files** - If usage patterns changed significantly - **menu.md** - If function renamed or moved ## Verification After updating, verify: - [ ] All types match source exactly - [ ] Function signature matches source - [ ] All examples work with new API - [ ] All `href` links are valid - [ ] Related type docs updated if interfaces changed - [ ] `menu.md` updated if renamed - [ ] Related API docs updated (their Related sections) ## Best Practices - **Read full source file** - Don't just look at diff - **Update incrementally** - `properties.ts` → `index.mdx` → related files - **Don't over-document internals** - Only user-facing changes need docs - **Preserve example quality** - Keep realistic, demonstrate best practices - **Check related APIs** - They may reference the changed function ## When to Ask for Help - Major breaking changes (complete signature overhaul) - Complex generic constraint changes - Unclear intent from source changes - Many related files affected - Need to document migration path ## Quick Reference | Change | Files to Update | | ----------------- | -------------------------------------------------------------------- | | New parameter | `properties.ts`, `index.mdx` (signature, generics, params, examples) | | Removed parameter | `properties.ts`, `index.mdx` | | Type change | `properties.ts`, `index.mdx` (explanation, examples) | | Interface change | `(types)/TypeName/properties.ts`, `(types)/TypeName/index.mdx` | | Renamed function | Folder name, all files, `menu.md`, cross-references | | Deprecation | `index.mdx` (add warning) | ================================================ FILE: .agents/skills/repo-website-guide-create/SKILL.md ================================================ --- name: repo-website-guide-create description: Create conceptual documentation and tutorial pages for the Valibot website at website/src/routes/guides/. Use when adding guides about schemas, pipelines, async validation, migration, or other topics. Covers directory structure, MDX templates, frontmatter, and content guidelines. --- # Adding Guides to Website Guide for creating conceptual documentation at `website/src/routes/guides/`. ## Directory Structure ``` website/src/routes/guides/ ├── menu.md # Navigation menu ├── (get-started)/ # Intro, installation, quick start ├── (main-concepts)/ # Schemas, pipelines, parsing ├── (schemas)/ # Objects, arrays, unions ├── (advanced)/ # Async, i18n, JSON Schema ├── (migration)/ # Version upgrades, Zod migration └── (category)/guide-slug/ └── index.mdx # Guide content ``` Note: Category folders use parentheses (Qwik route grouping). ## Process 1. Review 2-3 existing guides in the target category to understand style 2. Choose category from existing or create new 3. Create folder: `(category)/guide-slug/` 4. Create `index.mdx` with content 5. Update `menu.md` ## index.mdx Template ```mdx --- title: Guide Title description: >- A concise description of what this guide covers. contributors: - github-username --- import { ApiList, Link } from '~/components'; # Guide Title Opening paragraph explaining what the reader will learn. ## Section Heading Content with clear, concise language. \`\`\`ts import \* as v from 'valibot'; const Schema = v.object({ name: v.string(), email: v.pipe(v.string(), v.email()), }); \`\`\` ## Another Section Continue with additional sections as needed. Use \`pipe\` for internal links. ``` ## Frontmatter Required fields: - **title**: Page title and navigation label - **description**: SEO description (use `>-` for multi-line) - **contributors**: Array of GitHub usernames ## Content Guidelines ### Code Examples - Use TypeScript (`ts` language) - Import as `import * as v from 'valibot';` - Include comments for complex code ### Links Internal links use the `Link` component: ```mdx schemas guide \`pipe\` ``` ### Components ```mdx ``` ### Formatting - `inline code` for API names, variables, file names - **bold** for genuine emphasis only — not as inline section labels - Proper heading hierarchy (h1 title, h2 sections, h3 subsections) ### Writing tone - Write conversational prose, not terse reference-doc style - Use first-person plural: "we recommend" not "you should" - Do not use bold as inline section labels (e.g. avoid `**Label:** content`). Use a proper subheading instead - Do not prefix blockquotes with bold labels (e.g. avoid `> **Note:** ...`). A plain `>` is correct - Bullet list items do not need a bold prefix on each item ### Images Place images in the same folder as `index.mdx`: ```mdx ![Alt text](./diagram-light.jpg) ``` Consider light/dark theme variants if applicable (e.g., `diagram-light.jpg`, `diagram-dark.jpg`). ## Update menu.md Add to `/website/src/routes/guides/menu.md`: ```markdown ## Category Name - [Existing Guide](/guides/existing/) - [New Guide Title](/guides/guide-slug/) ``` Maintain logical ordering within categories. ## Checklist - [ ] Reviewed existing guides in the same category - [ ] Folder structure: `(category)/guide-slug/index.mdx` - [ ] Frontmatter: title, description, contributors - [ ] Internal links use `Link` component - [ ] Code examples use `import * as v from 'valibot';` - [ ] Added to `menu.md` - [ ] Style matches existing guides ================================================ FILE: .github/FUNDING.yml ================================================ github: [fabian-hiller, EltonLobo07, Bilboramix] open_collective: valibot ================================================ FILE: .github/actions/environment/action.yml ================================================ name: Setup environment description: Setup environment with Node.js, Deno and pnpm runs: using: composite steps: - name: Setup pnpm uses: pnpm/action-setup@v4 with: version: 9 run_install: false - name: Setup Node.js uses: actions/setup-node@v6 with: node-version: 24 registry-url: 'https://registry.npmjs.org' cache: pnpm - name: Setup npm shell: bash run: npm install --global npm@11.11.1 - name: Setup Deno uses: denoland/setup-deno@v2 with: deno-version: v2.5.6 - name: Install dependencies shell: bash run: pnpm install - name: Build library shell: bash run: pnpm build working-directory: library - name: Build to-json-schema shell: bash run: pnpm build working-directory: packages/to-json-schema - name: Build zod-to-valibot shell: bash run: pnpm build working-directory: codemod/zod-to-valibot ================================================ FILE: .github/workflows/ci.yml ================================================ name: CI on: push: branches: [main] pull_request: workflow_call: jobs: install: name: Install packages runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 - name: Setup environment uses: ./.github/actions/environment library_preview: name: Publish library via pkg.pr.new needs: install runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 - name: Setup environment uses: ./.github/actions/environment - name: Publish library run: pnpx pkg-pr-new publish --compact --comment=update --pnpm working-directory: library library_prettier: name: Run Prettier in library needs: install runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 - name: Setup environment uses: ./.github/actions/environment - name: Prettier check run: pnpm format.check working-directory: library library_eslint: name: Run ESLint in library needs: install runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 - name: Setup environment uses: ./.github/actions/environment - name: ESLint check run: pnpm lint working-directory: library library_vitest: name: Run Vitest in library needs: install runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 - name: Setup environment uses: ./.github/actions/environment - name: Vitest tests run: pnpm test working-directory: library to_json_schema_prettier: name: Run Prettier in packages/to-json-schema needs: install runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 - name: Setup environment uses: ./.github/actions/environment - name: Prettier check run: pnpm format.check working-directory: packages/to-json-schema to_json_schema_eslint: name: Run ESLint in packages/to-json-schema needs: install runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 - name: Setup environment uses: ./.github/actions/environment - name: ESLint check run: pnpm lint working-directory: packages/to-json-schema to_json_schema_vitest: name: Run Vitest in packages/to-json-schema needs: install runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 - name: Setup environment uses: ./.github/actions/environment - name: Vitest tests run: pnpm test working-directory: packages/to-json-schema website_prettier: name: Run Prettier in website needs: install runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 - name: Setup environment uses: ./.github/actions/environment - name: Prettier check run: pnpm format.check working-directory: website website_eslint: name: Run ESLint in website needs: install runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 - name: Setup environment uses: ./.github/actions/environment - name: ESLint check run: pnpm lint working-directory: website zod_to_valibot_vitest: name: Run Vitest in codemod/zod-to-valibot needs: install runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 - name: Setup environment uses: ./.github/actions/environment - name: Vitest tests run: pnpm test working-directory: codemod/zod-to-valibot ================================================ FILE: .github/workflows/publish.yml ================================================ name: Publish on: release: types: [published] workflow_dispatch: jobs: default_ci: name: Run default CI of repository uses: ./.github/workflows/ci.yml library_npm: name: Publish library to NPM needs: default_ci runs-on: ubuntu-latest permissions: contents: read id-token: write steps: - name: Checkout repository uses: actions/checkout@v6 - name: Setup environment uses: ./.github/actions/environment - name: Build library run: pnpm build working-directory: library - name: Publish library run: npm publish --access public working-directory: library continue-on-error: true library_jsr: name: Publish library to JSR needs: default_ci runs-on: ubuntu-latest permissions: contents: read id-token: write steps: - name: Checkout repository uses: actions/checkout@v6 - name: Publish library run: npx jsr publish working-directory: library i18n_npm: name: Publish i18n to NPM needs: default_ci runs-on: ubuntu-latest permissions: contents: read id-token: write steps: - name: Checkout repository uses: actions/checkout@v6 - name: Setup environment uses: ./.github/actions/environment - name: Build i18n run: pnpm build.npm working-directory: packages/i18n - name: Publish i18n run: npm publish --access public working-directory: packages/i18n continue-on-error: true i18n_jsr: name: Publish i18n to JSR needs: default_ci runs-on: ubuntu-latest permissions: contents: read id-token: write steps: - name: Checkout repository uses: actions/checkout@v6 - name: Setup environment uses: ./.github/actions/environment - name: Build i18n run: pnpm build.jsr working-directory: packages/i18n - name: Publish i18n run: npx jsr publish --allow-dirty working-directory: packages/i18n to_json_schema_npm: name: Publish to-json-schema to NPM needs: default_ci runs-on: ubuntu-latest permissions: contents: read id-token: write steps: - name: Checkout repository uses: actions/checkout@v6 - name: Setup environment uses: ./.github/actions/environment - name: Build to-json-schema run: pnpm build working-directory: packages/to-json-schema - name: Publish to-json-schema run: npm publish --access public working-directory: packages/to-json-schema continue-on-error: true to_json_schema_jsr: name: Publish to-json-schema to JSR needs: default_ci runs-on: ubuntu-latest permissions: contents: read id-token: write steps: - name: Checkout repository uses: actions/checkout@v6 - name: Setup environment uses: ./.github/actions/environment - name: Publish to-json-schema run: npx jsr publish working-directory: packages/to-json-schema ================================================ FILE: .gitignore ================================================ # Dependencies node_modules # Production dist build server # Tests coverage # Backups backups # Services .vscode .netlify .vercel # Others logs *.log .cache temp tmp # Local env files .env*.local # IDEs and editors .idea .project .classpath *.launch .settings # System files .DS_Store Thumbs.db *.pem ================================================ FILE: .grit/.gitignore ================================================ .gritmodules* *.log ================================================ FILE: .grit/grit.yaml ================================================ version: 0.1.0 patterns: - name: github.com/getgrit/stdlib#* ================================================ FILE: .grit/patterns/migrate_to_v0_31_0.md ================================================ # Migrate to v0.31.0 You can use [Grit](https://docs.grit.io/cli/quickstart) to automatically update your code to the new API. See the [migration guide](https://valibot.dev/guides/migrate-to-v0.31.0/) for more details on the changes. ```grit language js pattern rewritten_names() { or { // This could end up as a three-way rename, so we only apply it in first phase `custom` => `check`, `customAsync` => `checkAsync`, `special` => `custom`, `specialAsync` => `customAsync`, // These are safe to apply in the second phase `anyAsync` => `any`, `BaseSchema` => `GenericSchema`, `bigintAsync` => `bigint`, `blobAsync` => `blob`, `booleanAsync` => `boolean`, `dateAsync` => `date`, `enumAsync` => `enum_`, `Input` => `InferInput`, `instanceAsync` => `instance`, `literalAsync` => `literal`, `nanAsync` => `nan`, `neverAsync` => `never`, `nullAsync` => `null_`, `numberAsync` => `number`, `Output` => `InferOutput`, `picklistAsync` => `picklist`, `SchemaConfig` => `Config`, `stringAsync` => `string`, `symbolAsync` => `symbol`, `undefinedAsync` => `undefined_`, `unknownAsync` => `unknown`, `toCustom` => `transform`, `toTrimmed` => `trim`, `toTrimmedEnd` => `trimEnd`, `toTrimmedStart` => `trimStart`, `voidAsync` => `void_`, } } pattern rewrite_names($v) { or { rewritten_names() as $name where { $name <: imported_from(`"valibot"`) }, `$v.$name` where { $name <: rewritten_names(), }, } } pattern schema_names() { or { `any`, `array`, `bigint`, `blob`, `boolean`, `custom`, `date`, `enum_`, `instance`, `intersect`, `lazy`, `literal`, `looseObject`, `looseTuple`, `map`, `nan`, `never`, `nonNullable`, `nonNullish`, `nonOptional`, `null_`, `nullable`, `nullish`, `number`, `object`, `objectWithRest`, `optional`, `picklist`, `record`, `set`, `strictObject`, `strictTuple`, `string`, `symbol`, `tuple`, `tupleWithRest`, `undefined_`, `union`, `unknown`, `variant`, `void_` } } // These schemas have a mandatory array argument that is not a pipeline pattern schema_names_with_array_arg() { or { `union`, `intersect`, `tuple`, `looseTuple`, `strictTuple`, `picklist`, `variant` } } pattern extract_pipe_args($schema, $new_schema_args, $pipe_args) { or { [$maybe_pipe] where $other_args = [], [$one_arg, $maybe_pipe] where $other_args = [$one_arg], [$one_arg, $two_arg, $maybe_pipe] where $other_args = [$one_arg, $two_arg], [$one_arg, $two_arg, $three_arg, $maybe_pipe] where $other_args = [$one_arg, $two_arg, $three_arg] } where { $maybe_pipe <: `[$pipe_args]` where { or { $schema <: not schema_names_with_array_arg(), // Skip mandatory array arguments and { $schema <: schema_names_with_array_arg(), $one_arg <: not undefined, if ($schema <: `variant`) { $two_arg <: not undefined } }, } }, $new_schema_args = join($other_args, `, `) } } pattern rewrite_pipes($v, $pipe_args) { or { `$v.$schema($schema_args)` where { $schema <: schema_names(), $schema_args <: extract_pipe_args($schema, $new_schema_args, $pipe_args) } => `$v.pipe($v.$schema($new_schema_args), $pipe_args)`, `$schema($schema_args)` where { $schema <: schema_names(), $schema_args <: extract_pipe_args($schema, $new_schema_args, $pipe_args), add_import(`pipe`, `'valibot'`) } => `pipe($schema($new_schema_args), $pipe_args)` } } pattern rewrite_brand_and_transform($v, $schema, $pipe_args) { `$v.$method($schema, $method_arg)` as $outer where { $method <: or {`brand`, `transform`}, or { and { $schema <: rewrite_pipes($v, $pipe_args), $pipe_args += `, $v.$method($method_arg)`, $outer => $schema }, and { // Handle nested case $schema <: bubble($outer, $v, $method, $method_arg) rewrite_brand_and_transform(v=$_, $schema, $pipe_args) where { $pipe_args += `, $v.$method($method_arg)`, $outer => `$v.pipe($schema, $pipe_args)` } }, and { $pipe_args = `$v.$method($method_arg)`, $outer => `$v.pipe($schema, $pipe_args)` } } } } pattern rewrite_coerce($v) { `$v.coerce($schema, $fn)` => `$v.pipe($v.unknown(), $v.transform($fn))` } pattern rewrite_flatten($v) { `$flatten($error)` => `$flatten($error.issues)` where { $error <: identifier(), $flatten <: or { `flatten`, `$v.flatten` } } } pattern rewrite_nested_pipes($v, $args) { `$v.pipe($args)` where { $args <: maybe contains { bubble rewrite_nested_pipes($v, args=$inner) => $inner } // Don't traverse inside schemas until `$_($_)` } } pattern rewrite_object_and_tuple($v) { or { `$v.object($obj, $v.unknown(), '$message', $pipe)` => `$v.looseObject($obj, '$message', $pipe)`, `$v.object($obj, $v.unknown(), $pipe)` => `$v.looseObject($obj, $pipe)`, `$v.object($obj, $v.unknown())` => `$v.looseObject($obj)`, `$v.tuple($tuple, $v.unknown(), '$message', $pipe)` => `$v.looseTuple($tuple, '$message', $pipe)`, `$v.tuple($tuple, $v.unknown(), $pipe)` => `$v.looseTuple($tuple, $pipe)`, `$v.tuple($tuple, $v.unknown())` => `$v.looseTuple($tuple)`, `$v.object($obj, $v.never(), '$message', $pipe)` => `$v.strictObject($obj, '$message', $pipe)`, `$v.object($obj, $v.never(), $pipe)` => `$v.strictObject($obj, $pipe)`, `$v.object($obj, $v.never())` => `$v.strictObject($obj)`, `$v.tuple($tuple, $v.never(), '$message', $pipe)` => `$v.strictTuple($tuple, '$message', $pipe)`, `$v.tuple($tuple, $v.never(), $pipe)` => `$v.strictTuple($tuple, $pipe)`, `$v.tuple($tuple, $v.never())` => `$v.strictTuple($tuple)`, `$v.object($obj, $v.$rest(), '$message', $pipe)` => `$v.objectWithRest($obj, $v.$rest(), '$message', $pipe)`, `$v.object($obj, $v.$rest(), $pipe)` => `$v.objectWithRest($obj, $v.$rest(), $pipe)`, `$v.object($obj, $v.$rest())` => `$v.objectWithRest($obj, $v.$rest())`, `$v.tuple($tuple, $v.$rest(), '$message', $pipe)` => `$v.tupleWithRest($tuple, $v.$rest(), '$message', $pipe)`, `$v.tuple($tuple, $v.$rest(), $pipe)` => `$v.tupleWithRest($tuple, $v.$rest(), $pipe)`, `$v.tuple($tuple, $v.$rest())` => `$v.tupleWithRest($tuple, $v.$rest())`, } } pattern rewrite_merge($v) { or { `$v.merge([$schemas], $rest, '$message', $pipe)`, `$v.merge([$schemas], '$message', $pipe)`, `$v.merge([$schemas], $rest, $pipe)`, `$v.merge([$schemas], $pipe)`, `$v.merge([$schemas])`, } where { $entries = [], $schemas <: some bubble($entries) $schema where { $entries += `...$schema.entries`, }, $entries = join($entries, `, `), $args = `{ $entries }`, if ($rest <: not undefined) { $args += `, $rest` }, if ($message <: not undefined) { $args += `, '$message'` }, if ($pipe <: not undefined) { $args += `, $pipe`, }, } => `$v.object($args)` } pattern is_valibot() { `$v` where { $v <: or { // Direct imports undefined, // Default wildcard specification `v`, // Other wildcard imports identifier() where $program <: contains `import * as $v from 'valibot'` } } } pattern rewrite_functions() { any { rewrite_pipes($v), rewrite_brand_and_transform($v), rewrite_coerce($v), rewrite_flatten($v), rewrite_nested_pipes($v), rewrite_object_and_tuple($v), rewrite_merge($v), } where { $v <: is_valibot() } } sequential { bubble file($body) where $body <: contains or { rewrite_functions(), rewrite_names($v) where $v <: is_valibot() }, bubble file($body) where $body <: maybe contains rewrite_functions(), bubble file($body) where $body <: maybe contains rewrite_functions(), } ``` ## Should transform simple pipe Before: ```javascript const Schema1 = v.string([v.email('Email required')]); const Schema2 = v.string([v.email(), v.endsWith('@example.com')]); const Schema3 = v.string([v.email(), v.endsWith('@example.com'), v.maxLength(30)]); ``` After: ```javascript const Schema1 = v.pipe(v.string(), v.email('Email required')); const Schema2 = v.pipe(v.string(), v.email(), v.endsWith('@example.com')); const Schema3 = v.pipe(v.string(), v.email(), v.endsWith('@example.com'), v.maxLength(30)); ``` ## Should transform nested pipe Before: ```javascript const Schema1 = v.map(v.number(), v.string([v.url(), v.endsWith('@example.com')]), [v.maxSize(10)]); const Schema2 = v.object({ list: v.array(v.string([v.minLength(3)]), [v.minLength(3), v.includes('foo')]), length: v.number([v.integer()]) }, [v.custom((input) => input.list.length === input.length)]); ``` After: ```javascript const Schema1 = v.pipe(v.map(v.number(), v.pipe(v.string(), v.url(), v.endsWith('@example.com'))), v.maxSize(10)); const Schema2 = v.pipe(v.object({ list: v.pipe(v.array(v.pipe(v.string(), v.minLength(3))), v.minLength(3), v.includes('foo')), length: v.pipe(v.number(), v.integer()) }), v.check((input) => input.list.length === input.length)); ``` ## Should not transform non pipe Before: ```js const Schema = v.object({ normal: v.string([v.email(() => 'Email required')]), union: v.union([v.string([v.decimal()]), v.number()], [v.minValue(10)]), intersection: v.intersect([v.object({ a: v.string() }), v.object({ b: v.number() })]), variant: v.variant('type', [v.object({ type: v.literal('a') }), v.object({ type: v.literal('b') })]), picklist: v.picklist(['a', 'b']), tuple: v.tuple([v.string(), v.number()]), }); ``` After: ```js const Schema = v.object({ normal: v.pipe(v.string(), v.email(() => 'Email required')), union: v.pipe(v.union([v.pipe(v.string(), v.decimal()), v.number()]), v.minValue(10)), intersection: v.intersect([v.object({ a: v.string() }), v.object({ b: v.number() })]), variant: v.variant('type', [v.object({ type: v.literal('a') }), v.object({ type: v.literal('b') })]), picklist: v.picklist(['a', 'b']), tuple: v.tuple([v.string(), v.number()]), }); ``` ## Should transform coerce method Before: ```javascript const Schema = v.coerce(v.date(), (input) => new Date(input)); ``` After: ```javascript const Schema = v.pipe(v.unknown(), v.transform((input) => new Date(input))); ``` ## Should transform flatten argument Before: ```js const flatErrors1 = v.flatten(error); // This should be unchanged const flatErrors2 = v.flatten([issue]); const flatErrors3 = v.flatten(result.issues); ``` After: ```js const flatErrors1 = v.flatten(error.issues); // This should be unchanged const flatErrors2 = v.flatten([issue]); const flatErrors3 = v.flatten(result.issues); ``` ## Should transform any Valibot wildcard Before: ```js import * as foo from 'valibot'; import * as notFoo from 'zod'; const Schema1 = foo.string([foo.email()]); const Schema2 = notFoo.string([notFoo.email()]); ``` After: ```js import * as foo from 'valibot'; import * as notFoo from 'zod'; const Schema1 = foo.pipe(foo.string(), foo.email()); const Schema2 = notFoo.string([notFoo.email()]); ``` ## Should transform direct Valibot imports Before: ```js import { email, string } from 'valibot'; const Schema = string([email()]); ``` After: ```js import { email, string, pipe } from 'valibot'; const Schema = pipe(string(), email()); ``` ## Should transform brand and transform method Before: ```js const Schema1 = v.brand(v.string([v.url()]), 'foo'); const Schema2 = v.transform(v.string(), (input) => input.length); const Schema3 = v.transform(v.brand(v.string(), 'Name'), (input) => input.length); const Schema4 = v.brand(v.brand(v.string(), 'Name1'), 'Name2'); ``` After: ```js const Schema1 = v.pipe(v.string(), v.url(), v.brand('foo')); const Schema2 = v.pipe(v.string(), v.transform((input) => input.length)); const Schema3 = v.pipe(v.string(), v.brand('Name'), v.transform((input) => input.length)); const Schema4 = v.pipe(v.string(), v.brand('Name1'), v.brand('Name2')); ``` ## Should transform unnecessary pipes Before: ```js const Schema1 = v.pipe(v.pipe(v.pipe(v.string()), v.email()), v.maxLength(10)); const Schema2 = v.transform(v.coerce(v.date(), (input) => new Date(input)), (input) => input.toJSON()); const Schema3 = v.pipe(v.array(v.pipe(v.string(), v.decimal())), v.transform((input) => input.length)); ``` After: ```js const Schema1 = v.pipe(v.string(), v.email(), v.maxLength(10)); const Schema2 = v.pipe(v.unknown(), v.transform((input) => new Date(input)), v.transform((input) => input.toJSON())); const Schema3 = v.pipe(v.array(v.pipe(v.string(), v.decimal())), v.transform((input) => input.length)); ``` ## Should not rename unrelated methods Before: ```js import { special } from 'valibot'; import * as vb from 'valibot'; import { Input } from '~/ui'; const foo = const bar = special(); const baz = vb.toCustom(); ``` After: ```js import { custom } from 'valibot'; import * as vb from 'valibot'; import { Input } from '~/ui'; const foo = const bar = custom(); const baz = vb.transform(); ``` ## Should transform objects and tuples Before: ```js const ObjectSchema = v.object({ key: v.string() }, v.null_()); const TupleSchema = v.tuple([v.string()], v.null_()); const LooseObjectSchema = v.object({ key: v.string() }, v.unknown()); const LooseTupleSchema = v.tuple([v.string()], v.unknown()); const StrictObjectSchema = v.object({ key: v.string() }, v.never()); const StrictTupleSchema = v.tuple([v.string()], v.never()); ``` After: ```js const ObjectSchema = v.objectWithRest({ key: v.string() }, v.null_()); const TupleSchema = v.tupleWithRest([v.string()], v.null_()); const LooseObjectSchema = v.looseObject({ key: v.string() }); const LooseTupleSchema = v.looseTuple([v.string()]); const StrictObjectSchema = v.strictObject({ key: v.string() }); const StrictTupleSchema = v.strictTuple([v.string()]); ``` ## Should transform object merging Before: ```js const ObjectSchema1 = v.object({ foo: v.string() }); const ObjectSchema2 = v.object({ bar: v.number() }); const MergedObject = v.merge([ObjectSchema1, ObjectSchema2]); ``` After: ```js const ObjectSchema1 = v.object({ foo: v.string() }); const ObjectSchema2 = v.object({ bar: v.number() }); const MergedObject = v.object({ ...ObjectSchema1.entries, ...ObjectSchema2.entries }); ``` ## Should transform object with additional arguments Before: ```js const Schema = v.merge([ObjectSchema1, ObjectSchema1], v.string(), 'Error message', [v.custom(() => true)]); ``` After: ```js const Schema = v.pipe(v.objectWithRest({ ...ObjectSchema1.entries, ...ObjectSchema1.entries }, v.string(), 'Error message'), v.check(() => true)); ``` ================================================ FILE: .prettierignore ================================================ **/*.log **/.DS_Store *. .vscode/settings.json .history .yarn bazel-* bazel-bin bazel-out bazel-qwik bazel-testlogs dist dist-dev lib lib-types etc external node_modules temp tsc-out tsdoc-metadata.json target output build .cache .vscode .rollup.cache tsconfig.tsbuildinfo *.spec.tsx *.spec.ts .netlify pnpm-lock.yaml package-lock.json yarn.lock server .grit/patterns codemod/zod-to-valibot/__testfixtures__ ================================================ FILE: AGENTS.md ================================================ # AI Instructions Valibot is a modular, type-safe schema validation library with zero runtime dependencies. ## Monorepo Layout | Directory | Purpose | | -------------------------- | ----------------------------------------------- | | `library/` | Core `valibot` package — most work happens here | | `packages/to-json-schema/` | JSON Schema converter | | `packages/i18n/` | Translated error messages | | `website/` | valibot.dev (Qwik + Vite) | | `codemod/` | Migration and conversion tools | ## Essential Commands ```bash pnpm install # Install dependencies pnpm test # Run tests (all packages) pnpm lint # ESLint + tsc + deno check (all packages) pnpm format # Format code with Prettier (all packages) pnpm build # Build for publishing (all packages) ``` ## Code Conventions - **ESM with `.ts` extensions** in imports (enforced by ESLint) - **`interface` over `type`** for object shapes - **JSDoc required** on exported functions (first overload only for overload sets) - **`// @__NO_SIDE_EFFECTS__`** before pure factory functions for tree-shaking ## Other Rules - **Source code is the single source of truth.** All documentation must match `/library/src/`. - **Lint and format after modifying code.** Run `pnpm lint` and `pnpm format` so CI passes. - **Use the GitHub CLI for GitHub-related tasks.** Prefer `gh` for pull requests, issues, checks, and other GitHub operations. ## Library Architecture Schemas, actions, and methods are plain objects with a `'~run'` method: ``` library/src/ ├── schemas/ → Data types (string, object, array...) ├── actions/ → Validations & transforms (email, minLength, trim...) ├── methods/ → API functions (parse, pipe, partial...) ├── types/ → TypeScript definitions └── utils/ → Internal helpers (prefixed with _) ``` Each has its own folder: `name.ts`, `name.test.ts`, `name.test-d.ts`, `index.ts`. ## Agent Skills This repository includes agent skills in `/skills/` following the [Agent Skills](https://agentskills.io) open standard. **Naming:** Skills prefixed with `repo-` are local repository skills ================================================ FILE: CODE_OF_CONDUCT.md ================================================ # Contributor Covenant Code of Conduct ## Our Pledge We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards Examples of behavior that contributes to a positive environment for our community include: - Demonstrating empathy and kindness toward other people - Being respectful of differing opinions, viewpoints, and experiences - Giving and gracefully accepting constructive feedback - Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience - Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: - The use of sexualized language or imagery, and sexual attention or advances of any kind - Trolling, insulting or derogatory comments, and personal or political attacks - Public or private harassment - Publishing others' private information, such as a physical or email address, without their explicit permission - Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at hello@fabianhiller.com. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. ## Enforcement Guidelines Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: ### 1. Correction **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. ### 2. Warning **Community Impact**: A violation through a single incident or series of actions. **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. ### 3. Temporary Ban **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within the community. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at [https://www.contributor-covenant.org/translations][translations]. [homepage]: https://www.contributor-covenant.org [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html [Mozilla CoC]: https://github.com/mozilla/diversity [FAQ]: https://www.contributor-covenant.org/faq [translations]: https://www.contributor-covenant.org/translations ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing We love pull requests from everyone. By contributing to this repository, you agree to abide by the [Code of Conduct](CODE_OF_CONDUCT.md). ## Get started - First [fork][fork] the repository and then clone it using: ```bash git clone git@github.com:your-username/valibot.git ``` - After that create a branch for your changes. For example: - `feat-XXX` if you will add functionality. - `fix-XXX` if you will fix a bug. - `test-XXX` if you wrote a test/s. - `doc-XXX` if you added to or edited documentation. - `refactor-XXX` if you refactor some part of the code. You may contribute by: - Implementing a new validation action. - Optimizing or improving the existing code. - Suggest a different solution for a problem. - Finding and fixing bugs and typos. - Adding examples to explain the usage. - Adding and improving test cases. - Improving our website and documentation. ## Pull requests Push to your fork and [submit a pull request][pr]. ### Best practices As we strive for excellence in our codebase, here are some guidelines to make your contributions shine: - Code in TypeScript: Embrace the power of TypeScript for writing your code. It helps in maintaining consistency and leveraging TypeScript's robust features. - Clarity and cleanliness: Write code that speaks for itself. Aim for simplicity and clarity, making it easy for others to read and understand at a glance. - Commenting and documentation: Illuminate your code with clear comments. Explain the purpose and functionality of your code. Where applicable, include links to relevant Wiki articles or external sources for further context. - Illustrative examples: Enhance understanding by providing minimal yet meaningful examples to demonstrate the expected output of your code. - Include test cases: Show the robustness of your code by accompanying it with well-thought-out test cases. This practice not only validates your code but also assists in maintaining the code quality in the long run. - Size matters for PRs: Keep your pull requests concise and focused. Smaller PRs are easier to review and merge, speeding up the development process. This approach helps in isolating changes and simplifying troubleshooting. - Crafting a good commit message: Your commit messages are a roadmap of your changes. Make them informative and useful for everyone. ## Issues Submit a [new issue][newissue] if there is a feature to be added, or if a bug was found in the existing code. Before submitting a new issue please review the [existing issues][issues] to avoid creating duplicates. Also, consider resolving current issues or contributing to the discussion on an issue. ## Collaborators You can ask for any help or clarifications from the collaborators. - [Fabian Hiller](https://github.com/fabian-hiller) - [Elton Lobo](https://github.com/EltonLobo07) - [Aris Kemper](https://github.com/ariskemper) [fork]: https://help.github.com/articles/fork-a-repo/ [pr]: https://github.com/open-circle/valibot/compare [newissue]: https://github.com/open-circle/valibot/issues/new [issues]: https://github.com/open-circle/valibot/issues ================================================ FILE: LICENSE.md ================================================ MIT License Copyright (c) Fabian Hiller Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: SECURITY.md ================================================ # Reporting Security Issues To report a vulnerability, please contact us via hello@fabianhiller.com. We recommend that you use the latest versions of the library to ensure that your application remains as secure as possible. ================================================ FILE: codemod/README.md ================================================ # Codemod ## Run options The preferred way to run these codemods is via the [codemod registry](https://codemod.com/registry), but as a fallback you can also run them from the source file by running the following command. ```bash npx codemod@latest path-to-source-file.ts --engine=workflow ``` ================================================ FILE: codemod/migrate-to-v0.31.0/.codemodrc.json ================================================ { "$schema": "https://codemod-utils.s3.us-west-1.amazonaws.com/configuration_schema.json", "version": "0.2.2", "private": false, "name": "valibot/migrate-to-v0.31.0", "engine": "workflow", "meta": { "tags": ["valibot", "v0.31.0", "pipeline", "pipe"], "git": "https://github.com/open-circle/valibot/tree/main/codemod/migrate-to-v0.31.0" }, "applicability": { "from": [["valibot", "<=", "0.30.0"]] } } ================================================ FILE: codemod/migrate-to-v0.31.0/.gitignore ================================================ node_modules dist ================================================ FILE: codemod/migrate-to-v0.31.0/LICENSE ================================================ The MIT License (MIT) Copyright (c) 2024 arybitskiy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: codemod/migrate-to-v0.31.0/README.md ================================================ # Migrate to v0.31.0 You can use [Codemod](https://codemod.com/) to automatically update your code to the new API. See the [migration guide](https://valibot.dev/guides/migrate-to-v0.31.0/) for more details on the changes. ## Examples ### Before ```ts import * as v from 'valibot'; v.object({ email: v.string([v.email(), v.endsWith('@gmail.com')]), password: v.string([v.minLength(8)]), other: v.union([v.string([v.decimal()]), v.number()]), }); ``` ### After ```ts import * as v from 'valibot'; v.object({ email: v.pipe(v.string(), v.email(), v.endsWith('@gmail.com')), password: v.pipe(v.string(), v.minLength(8)), other: v.union([v.pipe(v.string(), v.decimal()), v.number()]), }); ``` ### Before ```ts import * as v from 'valibot'; import { object, tuple } from 'valibot'; const ObjectSchema = object({ key: v.string() }, v.null_()); const TupleSchema = tuple([v.string()], v.null_()); ``` ### After ```ts import * as v from 'valibot'; import { objectWithRest, tupleWithRest } from 'valibot'; const ObjectSchema = objectWithRest({ key: v.string() }, v.null_()); const TupleSchema = tupleWithRest([v.string()], v.null_()); ``` ### Before ```ts import * as v from 'valibot'; const ObjectSchema1 = v.object({ foo: v.string() }); const ObjectSchema2 = v.object({ bar: v.number() }); const MergedObject = v.merge([ObjectSchema1, ObjectSchema2]); ``` ### After ```ts import * as v from 'valibot'; const ObjectSchema1 = v.object({ foo: v.string() }); const ObjectSchema2 = v.object({ bar: v.number() }); const MergedObject = v.object({ ...ObjectSchema1.entries, ...ObjectSchema2.entries, }); ``` ### Before ```ts import * as v from 'valibot'; const BrandedSchema = v.brand(v.string(), 'foo'); const TransformedSchema = v.transform(v.string(), (input) => input.length); ``` ### After ```ts import * as v from 'valibot'; const BrandedSchema = v.pipe(v.string(), v.brand('foo')); const TransformedSchema = v.pipe( v.string(), v.transform((input) => input.length) ); ``` ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture1.input.ts ================================================ import * as v from 'valibot'; import { email } from 'valibot'; const Schema1 = v.string([email()]); const Schema2 = v.string('asd', [email()]); const Schema3 = v.string('asd', '123', [email()]); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture1.output.ts ================================================ import * as v from 'valibot'; import { email } from 'valibot'; const Schema1 = v.pipe(v.string(), email()); const Schema2 = v.pipe(v.string('asd'), email()); const Schema3 = v.pipe(v.string('asd', '123'), email()); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture10.input.ts ================================================ import * as v from 'valibot'; const Schema = v.transform( v.brand(v.string(), 'Name'), (input) => input.length ); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture10.output.ts ================================================ import * as v from 'valibot'; const Schema = v.pipe( v.string(), v.brand('Name'), v.transform((input) => input.length) ); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture11.input.ts ================================================ import * as v from 'valibot'; const Schema = v.object( { name: v.string(), age: v.number(), }, [ v.forward( v.custom((i) => i.age > 18, 'You must be over 18'), ['age'] ), ] ); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture11.output.ts ================================================ import * as v from 'valibot'; const Schema = v.pipe( v.object({ name: v.string(), age: v.number(), }), v.forward( v.check((i) => i.age > 18, 'You must be over 18'), ['age'] ) ); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture12.input.ts ================================================ import * as v from 'valibot'; const Schema = v.brand(v.string([v.url()]), 'foo'); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture12.output.ts ================================================ import * as v from 'valibot'; const Schema = v.pipe(v.string(), v.url(), v.brand('foo')); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture13.input.ts ================================================ import * as v from 'valibot'; const Schema1 = v.map( v.number(), v.string([v.url(), v.endsWith('@example.com')]), [v.maxSize(10)] ); const Schema2 = v.object( { list: v.array(v.string([v.minLength(3)]), [ v.minLength(3), v.includes('foo'), ]), length: v.number([v.integer()]), }, [v.custom((input) => input.list.length === input.length)] ); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture13.output.ts ================================================ import * as v from 'valibot'; const Schema1 = v.pipe( v.map(v.number(), v.pipe(v.string(), v.url(), v.endsWith('@example.com'))), v.maxSize(10) ); const Schema2 = v.pipe( v.object({ list: v.pipe( v.array(v.pipe(v.string(), v.minLength(3))), v.minLength(3), v.includes('foo') ), length: v.pipe(v.number(), v.integer()), }), v.check((input) => input.list.length === input.length) ); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture14.input.ts ================================================ import * as v from 'valibot'; const Schema = v.object({ normal: v.string([v.email(() => 'Email required')]), union: v.union([v.string([v.decimal()]), v.number()], [v.minValue(10)]), intersection: v.intersect([ v.object({ a: v.string() }), v.object({ b: v.number() }), ]), variant: v.variant('type', [ v.object({ type: v.literal('a') }), v.object({ type: v.literal('b') }), ]), picklist: v.picklist(['a', 'b']), tuple: v.tuple([v.string(), v.number()]), }); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture14.output.ts ================================================ import * as v from 'valibot'; const Schema = v.object({ normal: v.pipe( v.string(), v.email(() => 'Email required') ), union: v.pipe( v.union([v.pipe(v.string(), v.decimal()), v.number()]), v.minValue(10) ), intersection: v.intersect([ v.object({ a: v.string() }), v.object({ b: v.number() }), ]), variant: v.variant('type', [ v.object({ type: v.literal('a') }), v.object({ type: v.literal('b') }), ]), picklist: v.picklist(['a', 'b']), tuple: v.tuple([v.string(), v.number()]), }); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture15.input.ts ================================================ import * as v from 'valibot'; const Schema = v.coerce(v.date(), (input) => new Date(input)); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture15.output.ts ================================================ import * as v from 'valibot'; const Schema = v.pipe( v.unknown(), v.transform((input) => new Date(input)) ); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture16.input.ts ================================================ import * as v from 'valibot'; const flatErrors1 = v.flatten(error); const flatErrors2 = v.flatten([issue]); const flatErrors3 = v.flatten(result.issues); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture16.output.ts ================================================ import * as v from 'valibot'; const flatErrors1 = v.flatten(error.issues); const flatErrors2 = v.flatten([issue]); const flatErrors3 = v.flatten(result.issues); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture17.input.ts ================================================ import * as v from 'valibot'; const Schema1 = v.union([v.string(), v.number()], [v.minValue(123)]); const Schema2 = v.union([v.string(), v.number()], 'error', [v.minValue(123)]); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture17.output.ts ================================================ import * as v from 'valibot'; const Schema1 = v.pipe(v.union([v.string(), v.number()]), v.minValue(123)); const Schema2 = v.pipe( v.union([v.string(), v.number()], 'error'), v.minValue(123) ); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture2.input.ts ================================================ import * as v from 'valibot'; import { type BaseSchema, toCustom } from 'valibot'; v.custom(); BaseSchema(); v.Input(); v.Output(); v.special(); toCustom(); toTrimmed(); v.toTrimmedEnd(); v.toTrimmedStart(); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture2.output.ts ================================================ import * as v from 'valibot'; import { type GenericSchema, transform } from 'valibot'; v.check(); GenericSchema(); v.InferInput(); v.InferOutput(); v.custom(); transform(); toTrimmed(); v.trimEnd(); v.trimStart(); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture3.input.ts ================================================ import * as v from 'valibot'; v.object({ email: v.string([v.email(), v.endsWith('@gmail.com')]), password: v.string([v.minLength(8)]), other: v.union([v.string([v.decimal()]), v.number()]), }); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture3.output.ts ================================================ import * as v from 'valibot'; v.object({ email: v.pipe(v.string(), v.email(), v.endsWith('@gmail.com')), password: v.pipe(v.string(), v.minLength(8)), other: v.union([v.pipe(v.string(), v.decimal()), v.number()]), }); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture4.input.ts ================================================ import * as v from 'valibot'; import { object, tuple } from 'valibot'; const ObjectSchema = object({ key: v.string() }, v.null_()); const TupleSchema = tuple([v.string()], v.null_()); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture4.output.ts ================================================ import * as v from 'valibot'; import { objectWithRest, tupleWithRest } from 'valibot'; const ObjectSchema = objectWithRest({ key: v.string() }, v.null_()); const TupleSchema = tupleWithRest([v.string()], v.null_()); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture5.input.ts ================================================ import { never, object, string, tuple, unknown } from 'valibot'; const LooseObjectSchema = object({ key: string() }, unknown()); const LooseTupleSchema = tuple([string()], unknown()); const StrictObjectSchema = object({ key: string() }, never()); const StrictTupleSchema = tuple([string()], never()); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture5.output.ts ================================================ import { looseObject, looseTuple, never, object, strictObject, strictTuple, string, tuple, unknown, } from 'valibot'; const LooseObjectSchema = looseObject({ key: string() }); const LooseTupleSchema = looseTuple([string()]); const StrictObjectSchema = strictObject({ key: string() }); const StrictTupleSchema = strictTuple([string()]); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture6.input.ts ================================================ import * as v from 'valibot'; const ObjectSchema1 = v.object({ foo: v.string() }); const ObjectSchema2 = v.object({ bar: v.number() }); const MergedObject = v.merge([ObjectSchema1, ObjectSchema2]); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture6.output.ts ================================================ import * as v from 'valibot'; const ObjectSchema1 = v.object({ foo: v.string() }); const ObjectSchema2 = v.object({ bar: v.number() }); const MergedObject = v.object({ ...ObjectSchema1.entries, ...ObjectSchema2.entries, }); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture7.input.ts ================================================ import * as v from 'valibot'; const BrandedSchema = v.brand(v.string(), 'foo'); const TransformedSchema = v.transform(v.string(), (input) => input.length); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture7.output.ts ================================================ import * as v from 'valibot'; const BrandedSchema = v.pipe(v.string(), v.brand('foo')); const TransformedSchema = v.pipe( v.string(), v.transform((input) => input.length) ); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture8.input.ts ================================================ import * as v from 'valibot'; const Schema = v.string([v.toTrimmed(), v.url()]); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture8.output.ts ================================================ import * as v from 'valibot'; const Schema = v.pipe(v.string(), v.trim(), v.url()); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture9.input.ts ================================================ import { string, url } from 'valibot'; const Schema = string([url()]); ================================================ FILE: codemod/migrate-to-v0.31.0/__testfixtures__/fixture9.output.ts ================================================ import { pipe, string, url } from 'valibot'; const Schema = pipe(string(), url()); ================================================ FILE: codemod/migrate-to-v0.31.0/package.json ================================================ { "name": "migrate-to-v0.31.0", "license": "MIT", "author": "Codemod, Inc.", "type": "module", "files": [ "README.md", ".codemodrc.json", "./dist/index.cjs" ], "devDependencies": { "@codemod.com/workflow": "^0.0.31", "@types/node": "^24.10.1", "typescript": "^5.9.3" } } ================================================ FILE: codemod/migrate-to-v0.31.0/src/index.ts ================================================ import type { Api } from '@codemod.com/workflow'; // List of all schema names const SCHEMAS = [ 'any', 'array', 'bigint', 'blob', 'boolean', 'custom', 'date', 'enum_', 'instance', 'intersect', 'lazy', 'literal', 'looseObject', 'looseTuple', 'map', 'nan', 'never', 'nonNullable', 'nonNullish', 'nonOptional', 'null_', 'nullable', 'nullish', 'number', 'object', 'objectWithRest', 'optional', 'picklist', 'record', 'set', 'strictObject', 'strictTuple', 'string', 'symbol', 'tuple', 'tupleWithRest', 'undefined_', 'union', 'unknown', 'variant', 'void_', ]; // List of schema names with an mandatory array argument const SCHEMAS_WITH_ARRAY_ARG = [ 'union', 'intersect', 'tuple', 'looseTuple', 'strictTuple', 'picklist', 'variant', ]; // List of names that have changed const RENAMES: [string, string][] = [ ['anyAsync', 'any'], ['BaseSchema', 'GenericSchema'], ['bigintAsync', 'bigint'], ['blobAsync', 'blob'], ['booleanAsync', 'boolean'], ['custom', 'check'], ['customAsync', 'checkAsync'], ['dateAsync', 'date'], ['enumAsync', 'enum_'], ['Input', 'InferInput'], ['instanceAsync', 'instance'], ['literalAsync', 'literal'], ['nanAsync', 'nan'], ['neverAsync', 'never'], ['nullAsync', 'null_'], ['numberAsync', 'number'], ['Output', 'InferOutput'], ['picklistAsync', 'picklist'], ['special', 'custom'], ['specialAsync', 'customAsync'], ['SchemaConfig', 'Config'], ['stringAsync', 'string'], ['symbolAsync', 'symbol'], ['undefinedAsync', 'undefined_'], ['unknownAsync', 'unknown'], ['toCustom', 'transform'], ['toTrimmed', 'trim'], ['toTrimmedEnd', 'trimEnd'], ['toTrimmedStart', 'trimStart'], ['voidAsync', 'void_'], ]; /** * Codemod workflow that migrates Valibot code to v0.31.0. */ export async function workflow({ jsFiles }: Api) { await jsFiles(async ({ astGrep, addImport, removeImport, getImports }) => { // Query wildcard import const wildcardImport = ( await getImports('import * as $IMPORT from "valibot"').map( ({ getMatch }) => getMatch('IMPORT')?.text() ) ).shift(); // Query direct imports const directImports = ( await getImports('import { $$$IMPORTS } from "valibot"').map( ({ getMultipleMatches }) => getMultipleMatches('IMPORTS') .filter((node) => node.kind() === 'import_specifier') .map( (node) => node.find({ rule: { kind: 'identifier' } })?.text() ?? node.text() ) ) ).reduce((allImports, imports) => { allImports.push(...imports); return allImports; }, []); /** * Returns a function that checks if it is a valid wildcard or direct * import. */ function createImportCheck() { return (name: string | undefined): boolean => { if ( name && ((wildcardImport && name.startsWith(`${wildcardImport}.`)) || directImports.includes(name)) ) { return true; } return false; }; } /** * Returns a function that checks if it is a valid wildcard or direct * import of a specific name. */ function createNameCheck(names: string[]) { const isImported = createImportCheck(); return (name: string | undefined): boolean => { if ( name && isImported(name) && ((wildcardImport && names.includes( name.replace(new RegExp(`^${wildcardImport}.`), '') )) || names.includes(name)) ) { return true; } return false; }; } /** * Deeply searches for specific patterns. */ async function deepSearch( action: (continue_: () => void) => Promise ) { let notDone = true; while (notDone) { notDone = false; await action(() => (notDone = true)); } } // Create util functions const isImported = createImportCheck(); const isSchema = createNameCheck(SCHEMAS); const isSchemaWithArrayArg = createNameCheck(SCHEMAS_WITH_ARRAY_ARG); const isObject = createNameCheck(['object']); const isTuple = createNameCheck(['tuple']); const isObjectOrTuple = createNameCheck(['object', 'tuple']); const isUnknown = createNameCheck(['unknown']); const isNever = createNameCheck(['never']); const isPipe = createNameCheck(['pipe']); const isMerge = createNameCheck(['merge']); const isBrandOrTransform = createNameCheck(['brand', 'transform']); const isCoerce = createNameCheck(['coerce']); const isFlatten = createNameCheck(['flatten']); // Create wildcard prefix const wildcardPrefix = wildcardImport ? `${wildcardImport}.` : ''; // Rewrite names for (const [from, to] of [ ...(wildcardImport ? RENAMES.map(([prev, next]) => [ `${wildcardImport}.${prev}`, `${wildcardImport}.${next}`, ]) : []), ...RENAMES, ]) { // Rewrite only if imported by Valibot if (isImported(from)) { await astGrep(from).replace(() => to); await astGrep({ rule: { regex: from, kind: 'type_identifier' }, }).replace(() => to); } } // Rewrite object merging await astGrep`$METHOD($$$ARGS)`.replace( ({ getMatch, getMultipleMatches }) => { // Get and process node const methodName = getMatch('METHOD')?.text(); // Continue if it is merge method if (isMerge(methodName)) { // Get and process nodes const argsNodes = getMultipleMatches('ARGS'); const entriesText = argsNodes[0] ?.children() .slice(1, -1) .filter((node) => node.kind() !== ',') .map((node) => `...${node.text()}.entries`) .join(', '); const restText = argsNodes .slice(1) .filter((node) => node.kind() !== ',') .map((node) => node.text()) .join(', '); // Update imports if necessary if (!wildcardImport) { addImport(`import { object } from "valibot"`); removeImport(`import { merge } from "valibot"`); directImports.push(`object`); } // Return rewritten code return `${wildcardPrefix}object({${entriesText}}${restText ? `, ${restText}` : ''})`; } } ); // Rewrite objects and tuples with rest await astGrep`$SCHEMA($SHAPE, $$$REST)`.replace( ({ getMatch, getMultipleMatches }) => { // Get and process nodes const schemaName = getMatch('SCHEMA')?.text(); const shapeText = getMatch('SHAPE')?.text(); const restNodes = getMultipleMatches('REST'); const restSchemaName = restNodes[0]?.child(0)?.text(); // Continue if it is object or tuple with rest if ( isObjectOrTuple(schemaName) && isSchema(restSchemaName) && !isUnknown(restSchemaName) && !isNever(restSchemaName) ) { // Process nodes const restText = restNodes .filter((node) => node.kind() !== ',') .map((node) => node.text()) .join(', '); // Update imports if necessary // Hint: We do not remove the object or tuple import because we do // not know if it will be used elsewhere. if (schemaName && !schemaName.startsWith(`${wildcardImport}.`)) { addImport(`import { ${schemaName}WithRest } from "valibot"`); directImports.push(`${schemaName}WithRest`); } // Return rewritten code return `${schemaName}WithRest(${shapeText}, ${restText})`; } } ); // Rewrite loose and strict objects and tuples await astGrep`$SCHEMA($SHAPE, $$$REST)`.replace( ({ getMatch, getMultipleMatches }) => { // Get and process nodes const schemaName = getMatch('SCHEMA')?.text(); const shapeText = getMatch('SHAPE')?.text(); const restNodes = getMultipleMatches('REST'); const restSchemaName = restNodes[0]?.child(0)?.text(); // Create necessary variables let schemaPrefix: string | undefined; let schemaSuffix: string | undefined; // Set schema suffix and imports if (isObject(schemaName)) { schemaSuffix = 'Object'; } else if (isTuple(schemaName)) { schemaSuffix = 'Tuple'; } // Set schema prefix and imports if (isUnknown(restSchemaName)) { schemaPrefix = 'loose'; } else if (isNever(restSchemaName)) { schemaPrefix = 'strict'; } // Continue if prefix and suffix are set if (schemaPrefix && schemaSuffix) { // Process nodes const restText = restNodes .slice(1) .filter((node) => node.kind() !== ',') .map((node) => node.text()) .join(', '); // Update imports if necessary // Hint: We do not remove any imports because we do not know if it // will be used elsewhere. if (!wildcardImport) { addImport( `import { ${schemaPrefix}${schemaSuffix} } from "valibot"` ); directImports.push(`${schemaPrefix}${schemaSuffix}`); } // Return rewritten code return `${wildcardPrefix}${schemaPrefix}${schemaSuffix}(${shapeText}${restText ? `, ${restText}` : ''})`; } } ); // Rewrite coerce await astGrep`$METHOD($REMOVE, $LASTARG)`.replace(({ getMatch }) => { // Get and process nodes const methodName = getMatch('METHOD')?.text(); const lastArgText = getMatch('LASTARG')?.text(); // Continue if it is coerce method if (isCoerce(methodName)) { // Update imports if necessary if (!wildcardImport) { addImport(`import { pipe, unknown, transform } from "valibot"`); removeImport(`import { coerce } from "valibot"`); } // Return rewritten code return `${wildcardPrefix}pipe(${wildcardPrefix}unknown(), ${wildcardPrefix}transform(${lastArgText}))`; } }); // Rewrite flatten await astGrep`$METHOD($ARG)`.replace(({ getMatch }) => { // Get and process node const methodName = getMatch('METHOD')?.text(); const argChildLength = getMatch('ARG')?.children().length; // Continue if it is flatten method with error argument if (isFlatten(methodName) && !argChildLength) { // Return rewritten code return `$METHOD($ARG.issues)`; } }); // Rewrite brand and transform await deepSearch((continue_) => astGrep`$METHOD($SCHEMA, $LASTARG)`.replace(({ getMatch }) => { // Get and process nodes const methodName = getMatch('METHOD')?.text(); const schemaText = getMatch('SCHEMA')?.text(); const lastArgText = getMatch('LASTARG')?.text(); // Continue if it is brand or transform method if (isBrandOrTransform(methodName)) { // Continue searching continue_(); // Update imports if necessary if (!wildcardImport) { addImport(`import { pipe } from "valibot"`); directImports.push(`pipe`); } // Return rewritten code return `${wildcardPrefix}pipe(${schemaText}, ${methodName}(${lastArgText}))`; } }) ); // Rewrite pipelines for schemas with mandatory array argument await deepSearch((continue_) => astGrep`$SCHEMA([$$$ITEMS], $$$REST, [$$$ACTIONS])`.replace( ({ getMatch, getMultipleMatches }) => { // Get and process nodes const schemaName = getMatch('SCHEMA')?.text(); // Continue if it is schema with array argument if (isSchemaWithArrayArg(schemaName)) { // Get and process nodes const itemsText = getMultipleMatches('ITEMS') .filter((node) => node.kind() !== ',') .map((node) => node.text()) .join(', '); const restText = getMultipleMatches('REST') .filter((node) => node.kind() !== ',') .map((node) => node.text()) .join(', '); const actionNodes = getMultipleMatches('ACTIONS'); // If pipe is not empty, rewrite it to new pipe method if (actionNodes.length) { // Continue searching continue_(); const actionsText = actionNodes .filter((node) => node.kind() !== ',') .map((node) => node.text()) .join(', '); // Update imports if necessary if (!wildcardImport) { addImport(`import { pipe } from "valibot"`); directImports.push(`pipe`); } // Return rewritten code return `${wildcardPrefix}pipe(${schemaName}([${itemsText}]${restText ? `, ${restText}` : ''}), ${actionsText})`; } // Otherwise, remove pipe argument from schema return `${schemaName}([${itemsText}]${restText ? `, ${restText}` : ''})`; } } ) ); // Rewrite pipelines for schemas without mandatory array argument await deepSearch((continue_) => astGrep`$SCHEMA($$$REST, [$$$ACTIONS])`.replace( ({ getMatch, getMultipleMatches }) => { // Get and process nodes const schemaName = getMatch('SCHEMA')?.text(); // Continue if it is schema without array argument if (isSchema(schemaName) && !isSchemaWithArrayArg(schemaName)) { // Get and process nodes const restText = getMultipleMatches('REST') .filter((node) => node.kind() !== ',') .map((node) => node.text()) .join(', '); const actionNodes = getMultipleMatches('ACTIONS'); // If pipe is not empty, rewrite it to new pipe method if (actionNodes.length) { // Continue searching continue_(); // Get and process nodes const actionsText = actionNodes .map((node) => node.text()) .join(' '); // Update imports if necessary if (!wildcardImport) { addImport(`import { pipe } from "valibot"`); directImports.push(`pipe`); } // Return rewritten code return `${wildcardPrefix}pipe(${schemaName}(${restText}), ${actionsText})`; } // Otherwise, remove pipe argument from schema return `${schemaName}(${restText})`; } } ) ); // Rewrite nested pipes await deepSearch((continue_) => astGrep`$METHOD1($METHOD2($$$ARGS), $$$REST)`.replace( ({ getMatch, getMultipleMatches }) => { // Get and process nodes const method1Name = getMatch('METHOD1')?.text(); const method2Name = getMatch('METHOD2')?.text(); // Continue if both methods are pipes if (isPipe(method1Name) && isPipe(method2Name)) { // Continue searching continue_(); // Get and process nodes const itemsText = [ ...getMultipleMatches('ARGS').filter( (node) => node.kind() !== ',' ), ...getMultipleMatches('REST').filter( (node) => node.kind() !== ',' ), ] .map((node) => node.text()) .join(', '); // Update imports if necessary if (!wildcardImport) { addImport(`import { pipe } from "valibot"`); directImports.push(`pipe`); } // Return rewritten code return `${wildcardPrefix}pipe(${itemsText})`; } } ) ); }); } ================================================ FILE: codemod/migrate-to-v0.31.0/tsconfig.json ================================================ { "compilerOptions": { "outDir": "./dist", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "isolatedModules": true, "module": "NodeNext", "skipLibCheck": true, "strict": true, "target": "ES6", "allowJs": true }, "include": [ "./src/**/*.ts", "./src/**/*.js", "./test/**/*.ts", "./test/**/*.js" ], "exclude": ["node_modules", "./dist/**/*"], "ts-node": { "transpileOnly": true } } ================================================ FILE: codemod/zod-to-valibot/.gitignore ================================================ __testfixtures__/*/_actual.ts ================================================ FILE: codemod/zod-to-valibot/CHANGELOG.md ================================================ # Changelog All notable changes to the library will be documented in this file. ## v0.1.2 (December 07, 2025) - Fix CLI usage to use scoped package name `@valibot/zod-to-valibot` ## v0.1.1 (December 06, 2025) - Fix CLI `jscodeshift` resolution when installed via `npx` ## v0.1.0 (December 06, 2025) - Initial release ================================================ FILE: codemod/zod-to-valibot/LICENSE.md ================================================ MIT License Copyright (c) Fabian Hiller and Elton Lobo Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: codemod/zod-to-valibot/README.md ================================================ # Zod to Valibot Codemod Official codemod for automatically converting Zod schemas to Valibot schemas. ## Usage ```bash npx @valibot/zod-to-valibot src/**/* ``` ## Options ```bash # Dry run (preview changes) npx @valibot/zod-to-valibot --dry src/**/* # Verbose output npx @valibot/zod-to-valibot --verbose=2 src/**/* # Use a different parser (default is --parser=ts) npx @valibot/zod-to-valibot --parser=babel src/**/* # Use different extensions (default is --extensions=ts,tsx,js,jsx) npx @valibot/zod-to-valibot --extensions=ts src/**/* ``` For all available options, see [jscodeshift documentation](https://github.com/facebook/jscodeshift#options). ## What Gets Converted The codemod converts Zod schemas to Valibot, including: - Basic schemas (`string`, `number`, `boolean`, `date`, `bigint`) - Validation rules (`email`, `min`, `max`, etc.) - Coercion (`z.coerce.*` → `v.pipe(v.unknown(), v.toX())`) - Objects, arrays, unions, optionals, and more ## Support For issues or questions, open an issue on the [Valibot repository](https://github.com/open-circle/valibot). ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/any-schema/input.ts ================================================ import { z } from "zod"; const Schema1 = z.any(); const Schema2 = z.any({message: "some message"}); const Schema3 = z.any({description: "some description"}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/any-schema/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.any(); const Schema2 = v.any(); const Schema3 = v.pipe(v.any(), v.description("some description")); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/array-element/input.ts ================================================ import { z } from "zod"; const Schema1 = z.array(z.string()); const Schema2 = Schema1.element; const Schema3 = z.array(z.number()).element; const Schema4 = Schema1.element.trim().email(); const Schema5 = z.array(z.string()).element.trim().email(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/array-element/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.array(v.string()); const Schema2 = Schema1.item; const Schema3 = v.array(v.number()).item; const Schema4 = v.pipe(Schema1.item, v.trim(), v.email()); const Schema5 = v.pipe(v.array(v.string()).item, v.trim(), v.email()); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/array-nonempty/input.ts ================================================ import { z } from "zod"; const Schema1 = z.array(z.string()); const Schema2 = Schema1.nonempty(); const Schema3 = z.array(z.number()).nonempty(); const Schema4 = z.array(z.boolean()).nonempty("cannot be empty"); const Schema5 = z.array(z.null()).nonempty({}); const Schema6 = z.array(z.unknown()).nonempty({message: "Cannot be empty."}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/array-nonempty/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.array(v.string()); const Schema2 = v.pipe(Schema1, v.nonEmpty()); const Schema3 = v.pipe(v.array(v.number()), v.nonEmpty()); const Schema4 = v.pipe(v.array(v.boolean()), v.nonEmpty("cannot be empty")); const Schema5 = v.pipe(v.array(v.null()), v.nonEmpty()); const Schema6 = v.pipe(v.array(v.unknown()), v.nonEmpty("Cannot be empty.")); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/array-schema/input.ts ================================================ import { z } from "zod"; const Schema1 = z.array(z.string()); const Schema2 = z.array(z.string().email()); const Schema3 = z.array(z.string(), {message: "some message"}); const Schema4 = z.array(z.string(), {description: "some description"}); const Schema5 = z.string().array(); const Schema6 = z.string(); const Schema7 = Schema6.array(); const Schema8 = z.string().email().array(); const Schema9 = z.string().email().optional().array(); const Schema10 = z.string().email().array().optional(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/array-schema/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.array(v.string()); const Schema2 = v.array(v.pipe(v.string(), v.email())); const Schema3 = v.array(v.string(), "some message"); const Schema4 = v.pipe(v.array(v.string()), v.description("some description")); const Schema5 = v.array(v.string()); const Schema6 = v.string(); const Schema7 = v.array(Schema6); const Schema8 = v.array(v.pipe(v.string(), v.email())); const Schema9 = v.array(v.optional(v.pipe(v.string(), v.email()))); const Schema10 = v.optional(v.array(v.pipe(v.string(), v.email()))); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/array-validation-methods/input.ts ================================================ import { z } from "zod"; const Schema1 = z.array(z.string()).min(2); const Schema2 = z.array(z.string()).max(3); const Schema3 = z.array(z.string()).length(4); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/array-validation-methods/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.pipe(v.array(v.string()), v.minLength(2)); const Schema2 = v.pipe(v.array(v.string()), v.maxLength(3)); const Schema3 = v.pipe(v.array(v.string()), v.length(4)); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/bigint-validation-methods/input.ts ================================================ import { z } from "zod"; const GteSchema = z.bigint().gte(1n); const MinSchema = z.bigint().min(2n); const GtSchema = z.bigint().gt(3n); const LteSchema = z.bigint().lte(4n); const MaxSchema = z.bigint().max(5n); const LtSchema = z.bigint().lt(6n); const MultipleOfSchema = z.bigint().multipleOf(7n); const PositiveSchema = z.bigint().positive(); const NegativeSchema = z.bigint().negative(); const NonPositiveSchema = z.bigint().nonpositive(); const NonNegativeSchema = z.bigint().nonnegative(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/bigint-validation-methods/output.ts ================================================ import * as v from "valibot"; const GteSchema = v.pipe(v.bigint(), v.minValue(1n)); const MinSchema = v.pipe(v.bigint(), v.minValue(2n)); const GtSchema = v.pipe(v.bigint(), v.gtValue(3n)); const LteSchema = v.pipe(v.bigint(), v.maxValue(4n)); const MaxSchema = v.pipe(v.bigint(), v.maxValue(5n)); const LtSchema = v.pipe(v.bigint(), v.ltValue(6n)); const MultipleOfSchema = v.pipe(v.bigint(), v.multipleOf(7n)); const PositiveSchema = v.pipe(v.bigint(), v.gtValue(0n)); const NegativeSchema = v.pipe(v.bigint(), v.ltValue(0n)); const NonPositiveSchema = v.pipe(v.bigint(), v.maxValue(0n)); const NonNegativeSchema = v.pipe(v.bigint(), v.minValue(0n)); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/coerce-bigint-schema/input.ts ================================================ import { z } from "zod"; const Schema1 = z.coerce.bigint(); const Schema2 = z.bigint({ coerce: true }); const Schema3 = z.coerce.bigint().gt(1n); const Schema4 = z.bigint({ coerce: true }).lt(2n); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/coerce-bigint-schema/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.pipe(v.unknown(), v.toBigint()); const Schema2 = v.pipe(v.unknown(), v.toBigint()); const Schema3 = v.pipe(v.unknown(), v.toBigint(), v.gtValue(1n)); const Schema4 = v.pipe(v.unknown(), v.toBigint(), v.ltValue(2n)); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/coerce-boolean-schema/input.ts ================================================ import { z } from "zod"; const Schema1 = z.coerce.boolean(); const Schema2 = z.boolean({ coerce: true }); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/coerce-boolean-schema/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.pipe(v.unknown(), v.toBoolean()); const Schema2 = v.pipe(v.unknown(), v.toBoolean()); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/coerce-date-schema/input.ts ================================================ import { z } from "zod"; const Schema1 = z.coerce.date(); const Schema2 = z.date({ coerce: true }); const Schema3 = z.coerce.date().min(new Date("1/10/23")); const Schema4 = z.date({ coerce: true }).max(new Date("2023-01-10")); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/coerce-date-schema/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.pipe(v.unknown(), v.toDate()); const Schema2 = v.pipe(v.unknown(), v.toDate()); const Schema3 = v.pipe(v.unknown(), v.toDate(), v.minValue(new Date("1/10/23"))); const Schema4 = v.pipe(v.unknown(), v.toDate(), v.maxValue(new Date("2023-01-10"))); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/coerce-number-schema/input.ts ================================================ import { z } from "zod"; const Schema1 = z.coerce.number(); const Schema2 = z.number({ coerce: true }); const Schema3 = z.coerce.number().finite(); const Schema4 = z.number({ coerce: true }).multipleOf(12); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/coerce-number-schema/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.pipe(v.unknown(), v.toNumber()); const Schema2 = v.pipe(v.unknown(), v.toNumber()); const Schema3 = v.pipe(v.unknown(), v.toNumber(), v.finite()); const Schema4 = v.pipe(v.unknown(), v.toNumber(), v.multipleOf(12)); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/coerce-string-schema/input.ts ================================================ import { z } from "zod"; const Schema1 = z.coerce.string(); const Schema2 = z.string({ coerce: true }); const Schema3 = z.coerce.string().email(); const Schema4 = z.string({ coerce: true }).url(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/coerce-string-schema/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.pipe(v.unknown(), v.toString()); const Schema2 = v.pipe(v.unknown(), v.toString()); const Schema3 = v.pipe(v.unknown(), v.toString(), v.email()); const Schema4 = v.pipe(v.unknown(), v.toString(), v.url()); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/custom-schema/input.ts ================================================ import { z } from "zod"; const Schema1 = z.custom<{value: string}>(); const Schema2 = z.custom<{value: string}>(input => input); const Schema3 = z.custom<{value: string}>(input => input, "some message"); const Schema4 = z.custom<{value: string}>(input => input, {message: "some message"}); const Schema5 = z.custom<{value: string}>(input => input, {fatal: true}); const Schema6 = z.custom<{value: string}>(input => input, {fatal: true, message: "some message"}); const Schema7 = z.custom<{value: string}>(input => input, {params: {key: "value"}}); const Schema8 = z.custom<{value: string}>(input => input, {path: ["key"]}); const Schema9 = z.custom<{value: string}>(input => input, input => ({fatal: Boolean(input)})); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/custom-schema/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.custom<{value: string}>(() => true); const Schema2 = v.custom<{value: string}>(input => input); const Schema3 = v.custom<{value: string}>(input => input, "some message"); const Schema4 = v.custom<{value: string}>(input => input, "some message"); const Schema5 = v.custom<{value: string}>(input => input, {fatal: true}); const Schema6 = v.custom<{value: string}>(input => input, {fatal: true, message: "some message"}); const Schema7 = v.custom<{value: string}>(input => input, {params: {key: "value"}}); const Schema8 = v.custom<{value: string}>(input => input, {path: ["key"]}); const Schema9 = v.custom<{value: string}>(input => input, input => ({fatal: Boolean(input)})); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/date-validation-methods/input.ts ================================================ import { z } from "zod"; const MinSchema = z.date().min(new Date("2025-04-04")); const MaxSchema = z.date().max(new Date("1999-02-03")); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/date-validation-methods/output.ts ================================================ import * as v from "valibot"; const MinSchema = v.pipe(v.date(), v.minValue(new Date("2025-04-04"))); const MaxSchema = v.pipe(v.date(), v.maxValue(new Date("1999-02-03"))); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/default/input.ts ================================================ import { z } from "zod"; const Schema1 = z.boolean().default(false); const Schema2 = z.number().default(() => Math.floor(Math.random() * 11)); const Schema3 = z.string().trim().email().default("valibot@example.com"); const Schema4 = z.number().min(0).max(5).default(() => Math.floor(Math.random() * 6)); const Schema5 = z.object({key: z.string().default("Valibot")}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/default/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.optional(v.boolean(), false); const Schema2 = v.optional(v.number(), () => Math.floor(Math.random() * 11)); const Schema3 = v.optional(v.pipe(v.string(), v.trim(), v.email()), "valibot@example.com"); const Schema4 = v.optional( v.pipe(v.number(), v.minValue(0), v.maxValue(5)), () => Math.floor(Math.random() * 6) ); const Schema5 = v.object({key: v.optional(v.string(), "Valibot")}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/default-import/input.ts ================================================ import someName from "zod"; const StringSchema = someName.string(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/default-import/output.ts ================================================ import * as someName from "valibot"; const StringSchema = someName.string(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/default-import-with-alias/input.ts ================================================ import { default as someName } from "zod"; const StringSchema = someName.string(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/default-import-with-alias/output.ts ================================================ import * as someName from "valibot"; const StringSchema = someName.string(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/default-import-with-specific-alias/input.ts ================================================ import { default as z } from "zod"; const StringSchema = z.string(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/default-import-with-specific-alias/output.ts ================================================ import * as v from "valibot"; const StringSchema = v.string(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/describe/input.ts ================================================ import { z } from "zod"; const Schema = z.string().describe("some description"); const description = Schema.description; ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/describe/output.ts ================================================ import * as v from "valibot"; const Schema = v.pipe(v.string(), v.description("some description")); const description = v.getDescription(Schema); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/discriminated-union-schema/input.ts ================================================ import { z } from "zod"; const ResultSchema1 = z.discriminatedUnion("status", [ z.object({ status: z.literal("success"), data: z.number() }), z.object({ status: z.literal("failed"), error: z.string() }), ]); const ResultSchema2 = z.discriminatedUnion("status", [ z.object({ status: z.literal("success"), data: z.number() }), z.object({ status: z.literal("failed"), error: z.string() }), ], {message: "some message"}); const StateSchema = z.discriminatedUnion("status", [...ResultSchema1.options, z.object({status: z.literal("loading")})]); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/discriminated-union-schema/output.ts ================================================ import * as v from "valibot"; const ResultSchema1 = v.variant("status", [ v.object({ status: v.literal("success"), data: v.number() }), v.object({ status: v.literal("failed"), error: v.string() }), ]); const ResultSchema2 = v.variant("status", [ v.object({ status: v.literal("success"), data: v.number() }), v.object({ status: v.literal("failed"), error: v.string() }), ], "some message"); const StateSchema = v.variant( "status", [...ResultSchema1.options, v.object({status: v.literal("loading")})] ); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/instanceof-schema/input.ts ================================================ import { z } from "zod"; const Schema = z.instanceof(Error); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/instanceof-schema/output.ts ================================================ import * as v from "valibot"; const Schema = v.instance(Error); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/intersection-schema/input.ts ================================================ import { z } from "zod"; const Person = z.object({ name: z.string(), }); const Employee = z.object({ role: z.string(), }); const Schema1 = z.intersection(Person, Employee); const Schema2 = z.intersection(Person, Employee, {message: "some message"}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/intersection-schema/output.ts ================================================ import * as v from "valibot"; const Person = v.object({ name: v.string(), }); const Employee = v.object({ role: v.string(), }); const Schema1 = v.intersect([Person, Employee]); const Schema2 = v.intersect([Person, Employee], "some message"); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/literal-schema/input.ts ================================================ import { z } from "zod"; const Schema1 = z.literal("valibot"); const Schema2 = z.literal("valibot", {message: 'should be "valibot"'}); const Schema3 = z.literal(123); const Schema4 = z.literal(Symbol("someSymbol")); const Schema5 = z.literal(321n); const Schema6 = z.literal(true); const Schema7 = z.literal(null); const Schema8 = z.literal(null, {message: "should be null"}); const Schema9 = z.literal(undefined); const Schema10 = z.literal(undefined, {message: "should be undefined"}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/literal-schema/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.literal("valibot"); const Schema2 = v.literal("valibot", 'should be "valibot"'); const Schema3 = v.literal(123); const Schema4 = v.literal(Symbol("someSymbol")); const Schema5 = v.literal(321n); const Schema6 = v.literal(true); const Schema7 = v.null(); const Schema8 = v.null("should be null"); const Schema9 = v.undefined(); const Schema10 = v.undefined("should be undefined"); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/map-schema/input.ts ================================================ import { z } from "zod"; const Schema1 = z.map(z.number(), z.boolean()); const Schema2 = z.map(z.number(), z.boolean(), {message: "some message"}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/map-schema/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.map(v.number(), v.boolean()); const Schema2 = v.map(v.number(), v.boolean(), "some message"); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/multiple-imports-from-zod/input.ts ================================================ import { z, ZodAnyType } from "zod"; const Schema1 = z.string(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/multiple-imports-from-zod/output.ts ================================================ /* @valibot-migrate: unable to transform imports from Zod to Valibot: Expected exactly one import specifier from "zod" or "zod/v4". */ import { z, ZodAnyType } from "zod"; const Schema1 = z.string(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/named-import/input.ts ================================================ import { z } from "zod"; const StringSchema = z.string(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/named-import/output.ts ================================================ import * as v from "valibot"; const StringSchema = v.string(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/named-import-with-alias/input.ts ================================================ import { z as someName } from "zod"; const StringSchema = someName.string(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/named-import-with-alias/output.ts ================================================ import * as someName from "valibot"; const StringSchema = someName.string(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/named-import-with-specific-alias/input.ts ================================================ import { z as z } from "zod"; const StringSchema = z.string(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/named-import-with-specific-alias/output.ts ================================================ import * as v from "valibot"; const StringSchema = v.string(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/namespace-import/input.ts ================================================ import * as someName from "zod"; const StringSchema = someName.string(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/namespace-import/output.ts ================================================ import * as someName from "valibot"; const StringSchema = someName.string(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/nan-schema/input.ts ================================================ import { z } from "zod"; const Schema1 = z.nan(); const Schema2 = z.nan({message: "some message"}); const Schema3 = z.nan({description: "some description"}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/nan-schema/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.nan(); const Schema2 = v.nan("some message"); const Schema3 = v.pipe(v.nan(), v.description("some description")); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/native-enum/input.ts ================================================ import { z } from "zod"; // TypeScript enum enum Fruit { Orange, Apple = "apple", Banana = "banana", } const FruitEnum = z.nativeEnum(Fruit); // object literal enum const FruitObj = { Orange: 0, Apple: "apple", Banana: "banana", } as const; const FruitObjEnum = z.nativeEnum(FruitObj); // access underlying object using `enum` property enum Answer { Yes = "Yes", No = "No", } const NativeAnswerEnum = z.nativeEnum(Answer); const AnswerEnum = NativeAnswerEnum.enum; ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/native-enum/output.ts ================================================ import * as v from "valibot"; // TypeScript enum enum Fruit { Orange, Apple = "apple", Banana = "banana", } const FruitEnum = v.enum(Fruit); // object literal enum const FruitObj = { Orange: 0, Apple: "apple", Banana: "banana", } as const; const FruitObjEnum = v.enum(FruitObj); // access underlying object using `enum` property enum Answer { Yes = "Yes", No = "No", } const NativeAnswerEnum = v.enum(Answer); const AnswerEnum = NativeAnswerEnum.enum; ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/never-schema/input.ts ================================================ import { z } from "zod"; const Schema1 = z.never(); const Schema2 = z.never({message: "some message"}); const Schema3 = z.never({description: "some description"}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/never-schema/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.never(); const Schema2 = v.never("some message"); const Schema3 = v.pipe(v.never(), v.description("some description")); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/null-schema/input.ts ================================================ import { z } from "zod"; const Schema1 = z.null(); const Schema2 = z.null({message: "some message"}); const Schema3 = z.null({description: "some description"}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/null-schema/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.null(); const Schema2 = v.null("some message"); const Schema3 = v.pipe(v.null(), v.description("some description")); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/nullable-schema/input.ts ================================================ import { z } from "zod"; // nullable outside object const Schema1 = z.string().nullable(); const Schema2 = z.nullable(z.string()); const Schema3 = z.string(); const Schema4 = Schema3.nullable(); // nullable inside object const Schema5 = z.object({key: z.string().nullable()}); const Schema6 = z.object({key: z.nullable(z.string())}); const Schema7 = z.object({key: z.string().email().nullable()}); const Schema8 = z.object({key: z.nullable(z.string().email())}); const Schema9 = z.object({key: z.number()}); // get the wrapped schema const Schema10 = z.number().nullable(); const Schema11 = Schema10.unwrap(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/nullable-schema/output.ts ================================================ import * as v from "valibot"; // nullable outside object const Schema1 = v.nullable(v.string()); const Schema2 = v.nullable(v.string()); const Schema3 = v.string(); const Schema4 = v.nullable(Schema3); // nullable inside object const Schema5 = v.object({key: v.nullable(v.string())}); const Schema6 = v.object({key: v.nullable(v.string())}); const Schema7 = v.object({key: v.nullable(v.pipe(v.string(), v.email()))}); const Schema8 = v.object({key: v.nullable(v.pipe(v.string(), v.email()))}); const Schema9 = v.object({key: v.number()}); // get the wrapped schema const Schema10 = v.nullable(v.number()); const Schema11 = v.unwrap(Schema10); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/nullish-schema/input.ts ================================================ import { z } from "zod"; // nullish outside object const Schema1 = z.string().nullish(); const Schema2 = z.string(); const Schema3 = Schema2.nullish(); // nullish inside object const Schema4 = z.object({key: z.string().nullish()}); const Schema5 = z.object({key: z.string().email().nullish()}); const Schema6 = z.object({key: z.number()}); // get the wrapped schema const Schema7 = z.number().nullish(); const Schema8 = Schema7.unwrap(); const Schema9 = Schema7.unwrap().unwrap(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/nullish-schema/output.ts ================================================ import * as v from "valibot"; // nullish outside object const Schema1 = v.optional(v.nullable(v.string())); const Schema2 = v.string(); const Schema3 = v.optional(v.nullable(Schema2)); // nullish inside object const Schema4 = v.object({key: v.optional(v.nullable(v.string()))}); const Schema5 = v.object({key: v.optional(v.nullable(v.pipe(v.string(), v.email())))}); const Schema6 = v.object({key: v.number()}); // get the wrapped schema const Schema7 = v.optional(v.nullable(v.number())); const Schema8 = v.unwrap(Schema7); const Schema9 = v.unwrap(v.unwrap(Schema7)); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/number-validation-methods/input.ts ================================================ import { z } from "zod"; const GteSchema = z.number().gte(1); const MinSchema = z.number().min(2); const GtSchema = z.number().gt(3); const LteSchema = z.number().lte(4); const MaxSchema = z.number().max(5); const LtSchema = z.number().lt(6); const IntSchema = z.number().int(); const PositiveSchema = z.number().positive(); const NegativeSchema = z.number().negative(); const NonPositiveSchema = z.number().nonpositive(); const NonNegativeSchema = z.number().nonnegative(); const MultipleOfSchema = z.number().multipleOf(3); const StepSchema = z.number().step(3); const FiniteSchema = z.number().finite(); const SafeSchema = z.number().safe(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/number-validation-methods/output.ts ================================================ import * as v from "valibot"; const GteSchema = v.pipe(v.number(), v.minValue(1)); const MinSchema = v.pipe(v.number(), v.minValue(2)); const GtSchema = v.pipe(v.number(), v.gtValue(3)); const LteSchema = v.pipe(v.number(), v.maxValue(4)); const MaxSchema = v.pipe(v.number(), v.maxValue(5)); const LtSchema = v.pipe(v.number(), v.ltValue(6)); const IntSchema = v.pipe(v.number(), v.integer()); const PositiveSchema = v.pipe(v.number(), v.gtValue(0)); const NegativeSchema = v.pipe(v.number(), v.ltValue(0)); const NonPositiveSchema = v.pipe(v.number(), v.maxValue(0)); const NonNegativeSchema = v.pipe(v.number(), v.minValue(0)); const MultipleOfSchema = v.pipe(v.number(), v.multipleOf(3)); const StepSchema = v.pipe(v.number(), v.multipleOf(3)); const FiniteSchema = v.pipe(v.number(), v.finite()); const SafeSchema = v.pipe(v.number(), v.safeInteger()); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-catchall/input.ts ================================================ import { z } from "zod"; const Schema1 = z.object({key: z.string()}).catchall(z.null()); const Schema2 = z.object({key: z.string()}, {message: "some message"}).catchall(z.null()); const Schema3 = z.object({key: z.string()}, {description: "some description"}).catchall(z.null()); const Schema4 = z.object({key: z.string()}); const Schema5 = Schema4.catchall(z.null()); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-catchall/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.objectWithRest({key: v.string()}, v.null()); const Schema2 = v.objectWithRest({key: v.string()}, v.null(), "some message"); const Schema3 = v.pipe( v.object({key: v.string()}), v.description("some description"), v.catchall(v.null()) ); const Schema4 = v.object({key: v.string()}); const Schema5 = v.pipe(Schema4, v.catchall(v.null())); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-deepPartial/input.ts ================================================ import { z } from "zod"; const Schema1 = z.object({k1: z.string(), k2: z.number(), k3: z.boolean()}); const Schema2 = Schema1.deepPartial(); const Schema3 = z.object({k1: z.string(), k2: z.number(), k3: z.boolean()}).deepPartial(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-deepPartial/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.object({k1: v.string(), k2: v.number(), k3: v.boolean()}); const Schema2 = v.deepPartial(Schema1); const Schema3 = v.deepPartial(v.object({k1: v.string(), k2: v.number(), k3: v.boolean()})); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-extend/input.ts ================================================ import { z } from "zod"; // plain const Schema1 = z.object({foo: z.string()}).extend({bar: z.number()}); const Schema2 = z.object({foo: z.number()}); const Schema3 = Schema2.extend({bar: z.string()}); // passthrough const Schema4 = z.object({foo: z.string()}).passthrough().extend({bar: z.number()}); const Schema5 = z.object({foo: z.number()}).passthrough(); const Schema6 = Schema5.extend({bar: z.string()}); const Schema7 = z.object({foo: z.string()}).extend({bar: z.number()}).passthrough(); const Schema8 = Schema2.extend({bar: z.string()}).passthrough(); // strict const Schema9 = z.object({foo: z.string()}).strict().extend({bar: z.number()}); const Schema10 = z.object({foo: z.number()}).strict(); const Schema11 = Schema10.extend({bar: z.string()}); const Schema12 = z.object({foo: z.string()}).extend({bar: z.number()}).strict(); const Schema13 = Schema2.extend({bar: z.string()}).strict(); // strip const Schema14 = z.object({foo: z.string()}).strict().strip().extend({bar: z.number()}); const Schema15 = z.object({foo: z.number()}).strict().strip(); const Schema16 = Schema15.extend({bar: z.string()}); const Schema17 = z.object({foo: z.string()}).extend({bar: z.number()}).strict().strip(); const Schema18 = Schema2.extend({bar: z.string()}).strict().strip(); // catchall const Schema19 = z.object({foo: z.string()}).catchall(z.null()).extend({bar: z.number()}); const Schema20 = z.object({foo: z.number()}).catchall(z.null()); const Schema21 = Schema20.extend({bar: z.string()}); const Schema22 = z.object({foo: z.string()}).extend({bar: z.number()}).catchall(z.null()); const Schema23 = Schema2.extend({bar: z.string()}).catchall(z.null()); // i don't know which crazy person would do this, but it is valid // and we support it so we might as well test it const Schema24 = Schema23.extend(...[Schema22.shape]); // ------------ Expected transform ------------ // // plain // const Schema1 = v.object({ // foo: v.string(), // bar: v.number() // }); // const Schema2 = v.object({foo: v.number()}); // const Schema3 = v.object({ // ...Schema2.entries, // bar: v.string() // }); // // passthrough // const Schema4 = v.object({ // ...v.looseObject({foo: v.string()}).entries, // bar: v.number() // }); // const Schema5 = v.looseObject({foo: v.number()}); // const Schema6 = v.object({ // ...Schema5.entries, // bar: v.string() // }); // const Schema7 = v.looseObject({ // ...v.looseObject({foo: v.string()}).entries, // bar: v.number() // }); // const Schema8 = v.looseObject({ // ...Schema2.entries, // bar: v.string() // }); // // strict // const Schema9 = v.object({ // ...v.strictObject({foo: v.string()}).entries, // bar: v.number() // }); // const Schema10 = v.strictObject({foo: v.number()}); // const Schema11 = v.object({ // ...Schema10.entries, // bar: v.string() // }); // const Schema12 = v.strictObject({ // ...v.strictObject({foo: v.string()}).entries, // bar: v.number() // }); // const Schema13 = v.strictObject({ // ...Schema2.entries, // bar: v.string() // }); // // strip // const Schema14 = v.object({ // foo: v.string(), // bar: v.number() // }); // const Schema15 = v.object({foo: v.number()}); // const Schema16 = v.object({ // ...Schema15.entries, // bar: v.string() // }); // const Schema17 = v.object({ // foo: v.string(), // bar: v.number() // }); // const Schema18 = v.object({ // ...Schema2.entries, // bar: v.string() // }); // // catchall // const Schema19 = v.object({ // ...v.objectWithRest({foo: v.string()}, v.null()).entries, // bar: v.number() // }); // const Schema20 = v.objectWithRest({foo: v.number()}, v.null()); // const Schema21 = v.object({ // ...Schema20.entries, // bar: v.string() // }); // const Schema22 = v.objectWithRest({ // foo: v.string(), // bar: v.number() // }, v.null()); // const Schema23 = v.objectWithRest({ // ...Schema2.entries, // bar: v.string() // }, v.null()); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-extend/output.ts ================================================ import * as v from "valibot"; // plain const Schema1 = v.object({ foo: v.string(), bar: v.number() }); const Schema2 = v.object({foo: v.number()}); const Schema3 = v.object({ .../*@valibot-migrate we can't detect if Schema2 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema2.entries, bar: v.string() }); // passthrough const Schema4 = v.object({ ...v.looseObject({foo: v.string()}).entries, bar: v.number() }); const Schema5 = v.looseObject({foo: v.number()}); const Schema6 = v.object({ .../*@valibot-migrate we can't detect if Schema5 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema5.entries, bar: v.string() }); const Schema7 = v.looseObject({ ...v.looseObject({foo: v.string()}).entries, bar: v.number() }); const Schema8 = v.looseObject({ .../*@valibot-migrate we can't detect if Schema2 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema2.entries, bar: v.string() }); // strict const Schema9 = v.object({ ...v.strictObject({foo: v.string()}).entries, bar: v.number() }); const Schema10 = v.strictObject({foo: v.number()}); const Schema11 = v.object({ .../*@valibot-migrate we can't detect if Schema10 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema10.entries, bar: v.string() }); const Schema12 = v.strictObject({ ...v.strictObject({foo: v.string()}).entries, bar: v.number() }); const Schema13 = v.strictObject({ .../*@valibot-migrate we can't detect if Schema2 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema2.entries, bar: v.string() }); // strip const Schema14 = v.object({ foo: v.string(), bar: v.number() }); const Schema15 = v.object({foo: v.number()}); const Schema16 = v.object({ .../*@valibot-migrate we can't detect if Schema15 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema15.entries, bar: v.string() }); const Schema17 = v.object({ foo: v.string(), bar: v.number() }); const Schema18 = v.object({ .../*@valibot-migrate we can't detect if Schema2 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema2.entries, bar: v.string() }); // catchall const Schema19 = v.object({ ...v.objectWithRest({foo: v.string()}, v.null()).entries, bar: v.number() }); const Schema20 = v.objectWithRest({foo: v.number()}, v.null()); const Schema21 = v.object({ .../*@valibot-migrate we can't detect if Schema20 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema20.entries, bar: v.string() }); const Schema22 = v.objectWithRest({ foo: v.string(), bar: v.number() }, v.null()); const Schema23 = v.objectWithRest({ .../*@valibot-migrate we can't detect if Schema2 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema2.entries, bar: v.string() }, v.null()); // i don't know which crazy person would do this, but it is valid // and we support it so we might as well test it const Schema24 = v.object({ .../*@valibot-migrate we can't detect if Schema23 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema23.entries, ...[Schema22.entries] }); // ------------ Expected transform ------------ // // plain // const Schema1 = v.object({ // foo: v.string(), // bar: v.number() // }); // const Schema2 = v.object({foo: v.number()}); // const Schema3 = v.object({ // ...Schema2.entries, // bar: v.string() // }); // // passthrough // const Schema4 = v.object({ // ...v.looseObject({foo: v.string()}).entries, // bar: v.number() // }); // const Schema5 = v.looseObject({foo: v.number()}); // const Schema6 = v.object({ // ...Schema5.entries, // bar: v.string() // }); // const Schema7 = v.looseObject({ // ...v.looseObject({foo: v.string()}).entries, // bar: v.number() // }); // const Schema8 = v.looseObject({ // ...Schema2.entries, // bar: v.string() // }); // // strict // const Schema9 = v.object({ // ...v.strictObject({foo: v.string()}).entries, // bar: v.number() // }); // const Schema10 = v.strictObject({foo: v.number()}); // const Schema11 = v.object({ // ...Schema10.entries, // bar: v.string() // }); // const Schema12 = v.strictObject({ // ...v.strictObject({foo: v.string()}).entries, // bar: v.number() // }); // const Schema13 = v.strictObject({ // ...Schema2.entries, // bar: v.string() // }); // // strip // const Schema14 = v.object({ // foo: v.string(), // bar: v.number() // }); // const Schema15 = v.object({foo: v.number()}); // const Schema16 = v.object({ // ...Schema15.entries, // bar: v.string() // }); // const Schema17 = v.object({ // foo: v.string(), // bar: v.number() // }); // const Schema18 = v.object({ // ...Schema2.entries, // bar: v.string() // }); // // catchall // const Schema19 = v.object({ // ...v.objectWithRest({foo: v.string()}, v.null()).entries, // bar: v.number() // }); // const Schema20 = v.objectWithRest({foo: v.number()}, v.null()); // const Schema21 = v.object({ // ...Schema20.entries, // bar: v.string() // }); // const Schema22 = v.objectWithRest({ // foo: v.string(), // bar: v.number() // }, v.null()); // const Schema23 = v.objectWithRest({ // ...Schema2.entries, // bar: v.string() // }, v.null()); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-keyof/input.ts ================================================ import { z } from "zod"; const ObjectSchema = z.object({apple: z.string(), banana: z.number(), orange: z.boolean()}); const FruitEnum1 = ObjectSchema.keyof(); const FruitEnum2 = z.object({apple: z.string(), banana: z.number(), orange: z.boolean()}).keyof(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-keyof/output.ts ================================================ import * as v from "valibot"; const ObjectSchema = v.object({apple: v.string(), banana: v.number(), orange: v.boolean()}); const FruitEnum1 = v.keyof(ObjectSchema); const FruitEnum2 = v.keyof(v.object({apple: v.string(), banana: v.number(), orange: v.boolean()})); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-merge/input.ts ================================================ import { z } from "zod"; // plain const Schema1 = z.object({foo: z.string()}).merge(z.object({bar: z.number()})); const Schema2 = z.object({foo: z.number()}); const Schema3 = Schema2.merge(z.object({bar: z.string()})); const Schema4 = z.object({bar: z.number()}); const Schema5 = z.object({foo: z.string()}).merge(Schema4); const Schema6 = Schema2.merge(Schema4); // passthrough const Schema7 = z.object({foo: z.string()}).merge(z.object({bar: z.number()}).passthrough()); const Schema8 = Schema2.merge(z.object({bar: z.string()}).passthrough()); const Schema9 = z.object({bar: z.number()}).passthrough(); const Schema10 = z.object({foo: z.string()}).merge(Schema9); const Schema11 = Schema2.merge(Schema9); // strict const Schema12 = z.object({foo: z.string()}).merge(z.object({bar: z.number()}).strict()); const Schema13 = Schema2.merge(z.object({bar: z.string()}).strict()); const Schema14 = z.object({bar: z.number()}).strict(); const Schema15 = z.object({foo: z.string()}).merge(Schema14); const Schema16 = Schema2.merge(Schema14); // strip const Schema17 = z.object({foo: z.string()}).merge(z.object({bar: z.number()}).strict().strip()); const Schema18 = Schema2.merge(z.object({bar: z.string()}).strict().strip()); const Schema19 = z.object({bar: z.number()}).strict().strip(); const Schema20 = z.object({foo: z.string()}).merge(Schema19); const Schema21 = Schema2.merge(Schema19); // catchall const Schema22 = z.object({foo: z.string()}).merge(z.object({bar: z.number()}).catchall(z.null())); const Schema23 = Schema2.merge(z.object({bar: z.string()}).catchall(z.null())); const Schema24 = z.object({bar: z.number()}).catchall(z.null()); const Schema25 = z.object({foo: z.string()}).merge(Schema24); const Schema26 = Schema2.merge(Schema24); // i don't know which crazy person would do this, but it is valid // and we support it so we might as well test it const Schema27 = Schema26.merge(...[Schema25]); // ------------ Expected transform ------------ // // plain // const Schema1 = v.object({ // foo: v.string(), // bar: v.number() // }); // const Schema2 = v.object({foo: v.number()}); // const Schema3 = v.object({ // ...Schema2.entries, // bar: v.string() // }); // const Schema4 = v.object({bar: v.number()}); // const Schema5 = v.object({ // foo: v.string(), // ...Schema4.entries // }); // const Schema6 = v.object({ // ...Schema2.entries, // ...Schema4.entries // }); // // passthrough // const Schema7 = v.object({ // foo: v.string(), // ...v.looseObject({bar: v.number()}).entries // }); // const Schema8 = v.object({ // ...Schema2.entries, // ...v.looseObject({bar: v.string()}).entries // }); // const Schema9 = v.looseObject({bar: v.number()}); // const Schema10 = v.object({ // foo: v.string(), // ...Schema9.entries // }); // const Schema11 = v.object({ // ...Schema2.entries, // ...Schema9.entries // }); // // strict // const Schema12 = v.object({ // foo: v.string(), // ...v.strictObject({bar: v.number()}).entries // }); // const Schema13 = v.object({ // ...Schema2.entries, // ...v.strictObject({bar: v.string()}).entries // }); // const Schema14 = v.strictObject({bar: v.number()}); // const Schema15 = v.object({ // foo: v.string(), // ...Schema14.entries // }); // const Schema16 = v.object({ // ...Schema2.entries, // ...Schema14.entries // }); // // strip // const Schema17 = v.object({ // foo: v.string(), // bar: v.number() // }); // const Schema18 = v.object({ // ...Schema2.entries, // bar: v.string() // }); // const Schema19 = v.object({bar: v.number()}); // const Schema20 = v.object({ // foo: v.string(), // ...Schema19.entries // }); // const Schema21 = v.object({ // ...Schema2.entries, // ...Schema19.entries // }); // // catchall // const Schema22 = v.object({ // foo: v.string(), // ...v.objectWithRest({bar: v.number()}, v.null()).entries // }); // const Schema23 = v.object({ // ...Schema2.entries, // ...v.objectWithRest({bar: v.string()}, v.null()).entries // }); // const Schema24 = v.objectWithRest({bar: v.number()}, v.null()); // const Schema25 = v.object({ // foo: v.string(), // ...Schema24.entries // }); // const Schema26 = v.object({ // ...Schema2.entries, // ...Schema24.entries // }); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-merge/output.ts ================================================ import * as v from "valibot"; // plain const Schema1 = v.object({ foo: v.string(), bar: v.number() }); const Schema2 = v.object({foo: v.number()}); const Schema3 = v.object({ .../*@valibot-migrate we can't detect if Schema2 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema2.entries, bar: v.string() }); const Schema4 = v.object({bar: v.number()}); const Schema5 = v.object({ foo: v.string(), .../*@valibot-migrate we can't detect if Schema4 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema4.entries }); const Schema6 = v.object({ .../*@valibot-migrate we can't detect if Schema2 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema2.entries, .../*@valibot-migrate we can't detect if Schema4 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema4.entries }); // passthrough const Schema7 = v.object({ foo: v.string(), ...v.looseObject({bar: v.number()}).entries }); const Schema8 = v.object({ .../*@valibot-migrate we can't detect if Schema2 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema2.entries, ...v.looseObject({bar: v.string()}).entries }); const Schema9 = v.looseObject({bar: v.number()}); const Schema10 = v.object({ foo: v.string(), .../*@valibot-migrate we can't detect if Schema9 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema9.entries }); const Schema11 = v.object({ .../*@valibot-migrate we can't detect if Schema2 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema2.entries, .../*@valibot-migrate we can't detect if Schema9 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema9.entries }); // strict const Schema12 = v.object({ foo: v.string(), ...v.strictObject({bar: v.number()}).entries }); const Schema13 = v.object({ .../*@valibot-migrate we can't detect if Schema2 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema2.entries, ...v.strictObject({bar: v.string()}).entries }); const Schema14 = v.strictObject({bar: v.number()}); const Schema15 = v.object({ foo: v.string(), .../*@valibot-migrate we can't detect if Schema14 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema14.entries }); const Schema16 = v.object({ .../*@valibot-migrate we can't detect if Schema2 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema2.entries, .../*@valibot-migrate we can't detect if Schema14 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema14.entries }); // strip const Schema17 = v.object({ foo: v.string(), bar: v.number() }); const Schema18 = v.object({ .../*@valibot-migrate we can't detect if Schema2 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema2.entries, bar: v.string() }); const Schema19 = v.object({bar: v.number()}); const Schema20 = v.object({ foo: v.string(), .../*@valibot-migrate we can't detect if Schema19 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema19.entries }); const Schema21 = v.object({ .../*@valibot-migrate we can't detect if Schema2 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema2.entries, .../*@valibot-migrate we can't detect if Schema19 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema19.entries }); // catchall const Schema22 = v.object({ foo: v.string(), ...v.objectWithRest({bar: v.number()}, v.null()).entries }); const Schema23 = v.object({ .../*@valibot-migrate we can't detect if Schema2 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema2.entries, ...v.objectWithRest({bar: v.string()}, v.null()).entries }); const Schema24 = v.objectWithRest({bar: v.number()}, v.null()); const Schema25 = v.object({ foo: v.string(), .../*@valibot-migrate we can't detect if Schema24 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema24.entries }); const Schema26 = v.object({ .../*@valibot-migrate we can't detect if Schema2 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema2.entries, .../*@valibot-migrate we can't detect if Schema24 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema24.entries }); // i don't know which crazy person would do this, but it is valid // and we support it so we might as well test it const Schema27 = v.object({ .../*@valibot-migrate we can't detect if Schema26 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema26.entries, ...[Schema25].entries }); // ------------ Expected transform ------------ // // plain // const Schema1 = v.object({ // foo: v.string(), // bar: v.number() // }); // const Schema2 = v.object({foo: v.number()}); // const Schema3 = v.object({ // ...Schema2.entries, // bar: v.string() // }); // const Schema4 = v.object({bar: v.number()}); // const Schema5 = v.object({ // foo: v.string(), // ...Schema4.entries // }); // const Schema6 = v.object({ // ...Schema2.entries, // ...Schema4.entries // }); // // passthrough // const Schema7 = v.object({ // foo: v.string(), // ...v.looseObject({bar: v.number()}).entries // }); // const Schema8 = v.object({ // ...Schema2.entries, // ...v.looseObject({bar: v.string()}).entries // }); // const Schema9 = v.looseObject({bar: v.number()}); // const Schema10 = v.object({ // foo: v.string(), // ...Schema9.entries // }); // const Schema11 = v.object({ // ...Schema2.entries, // ...Schema9.entries // }); // // strict // const Schema12 = v.object({ // foo: v.string(), // ...v.strictObject({bar: v.number()}).entries // }); // const Schema13 = v.object({ // ...Schema2.entries, // ...v.strictObject({bar: v.string()}).entries // }); // const Schema14 = v.strictObject({bar: v.number()}); // const Schema15 = v.object({ // foo: v.string(), // ...Schema14.entries // }); // const Schema16 = v.object({ // ...Schema2.entries, // ...Schema14.entries // }); // // strip // const Schema17 = v.object({ // foo: v.string(), // bar: v.number() // }); // const Schema18 = v.object({ // ...Schema2.entries, // bar: v.string() // }); // const Schema19 = v.object({bar: v.number()}); // const Schema20 = v.object({ // foo: v.string(), // ...Schema19.entries // }); // const Schema21 = v.object({ // ...Schema2.entries, // ...Schema19.entries // }); // // catchall // const Schema22 = v.object({ // foo: v.string(), // ...v.objectWithRest({bar: v.number()}, v.null()).entries // }); // const Schema23 = v.object({ // ...Schema2.entries, // ...v.objectWithRest({bar: v.string()}, v.null()).entries // }); // const Schema24 = v.objectWithRest({bar: v.number()}, v.null()); // const Schema25 = v.object({ // foo: v.string(), // ...Schema24.entries // }); // const Schema26 = v.object({ // ...Schema2.entries, // ...Schema24.entries // }); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-omit/input.ts ================================================ import { z } from "zod"; const Schema1 = z.object({k1: z.string(), k2: z.number(), k3: z.boolean()}); const Schema2 = Schema1.omit({k1: true, k3: true}); const Schema3 = z.object({k1: z.string(), k2: z.number(), k3: z.boolean()}).omit({k2: true}); const Schema4 = z.object({key: z.string()}).omit({}); const Schema5 = Schema1.omit({}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-omit/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.object({k1: v.string(), k2: v.number(), k3: v.boolean()}); const Schema2 = v.omit(Schema1, ["k1", "k3"]); const Schema3 = v.omit(v.object({k1: v.string(), k2: v.number(), k3: v.boolean()}), ["k2"]); const Schema4 = v.object({key: v.string()}); const Schema5 = Schema1; ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-partial/input.ts ================================================ import { z } from "zod"; // make all keys optional const Schema1 = z.object({k1: z.string(), k2: z.number(), k3: z.boolean()}); const Schema2 = Schema1.partial(); const Schema3 = z.object({k1: z.string(), k2: z.number(), k3: z.boolean()}).partial(); // make none of the keys optional const Schema4 = Schema1.partial({}); const Schema5 = z.object({key: z.string()}).partial({}); // make some keys optional const Schema6 = z.object({k1: z.string(), k2: z.number(), k3: z.boolean()}); const Schema7 = Schema6.partial({k1: true, k3: true}); const Schema8 = z.object({k1: z.string(), k2: z.number(), k3: z.boolean()}).partial({k2: true}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-partial/output.ts ================================================ import * as v from "valibot"; // make all keys optional const Schema1 = v.object({k1: v.string(), k2: v.number(), k3: v.boolean()}); const Schema2 = v.partial(Schema1); const Schema3 = v.partial(v.object({k1: v.string(), k2: v.number(), k3: v.boolean()})); // make none of the keys optional const Schema4 = Schema1; const Schema5 = v.object({key: v.string()}); // make some keys optional const Schema6 = v.object({k1: v.string(), k2: v.number(), k3: v.boolean()}); const Schema7 = v.partial(Schema6, ["k1", "k3"]); const Schema8 = v.partial(v.object({k1: v.string(), k2: v.number(), k3: v.boolean()}), ["k2"]); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-passthrough/input.ts ================================================ import { z } from "zod"; const Schema1 = z.object({key: z.string()}).passthrough(); const Schema2 = z.object({key: z.string()}, {message: "some message"}).passthrough(); const Schema3 = z.object({key: z.string()}, {description: "some description"}).passthrough(); const Schema4 = z.object({key: z.string()}); const Schema5 = Schema4.passthrough(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-passthrough/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.looseObject({key: v.string()}); const Schema2 = v.looseObject({key: v.string()}, "some message"); const Schema3 = v.pipe(v.looseObject({key: v.string()}), v.description("some description")); const Schema4 = v.object({key: v.string()}); const Schema5 = v.looseObject( /*@valibot-migrate we can't detect if Schema4 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema4.entries ); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-pick/input.ts ================================================ import { z } from "zod"; const Schema1 = z.object({k1: z.string(), k2: z.number(), k3: z.boolean()}); const Schema2 = Schema1.pick({k1: true, k3: true}); const Schema3 = z.object({k1: z.string(), k2: z.number(), k3: z.boolean()}).pick({k2: true}); // todo: const Schema4 = z.object({key: z.string()}).pick({}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-pick/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.object({k1: v.string(), k2: v.number(), k3: v.boolean()}); const Schema2 = v.pick(Schema1, ["k1", "k3"]); const Schema3 = v.pick(v.object({k1: v.string(), k2: v.number(), k3: v.boolean()}), ["k2"]); // todo: const Schema4 = z.object({key: z.string()}).pick({}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-required/input.ts ================================================ import { z } from "zod"; // make all keys required const Schema1 = z.object({k1: z.string(), k2: z.number(), k3: z.boolean()}).partial(); const Schema2 = Schema1.required(); const Schema3 = z.object({k1: z.string(), k2: z.number(), k3: z.boolean()}).partial().required(); // make none of the keys required const Schema4 = Schema1.partial().required({}); const Schema5 = z.object({key: z.string()}).partial().required({}); // make some keys required const Schema6 = z.object({k1: z.string(), k2: z.number(), k3: z.boolean()}).partial(); const Schema7 = Schema6.required({k1: true, k3: true}); const Schema8 = z.object({k1: z.string(), k2: z.number(), k3: z.boolean()}).partial().required({k2: true}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-required/output.ts ================================================ import * as v from "valibot"; // make all keys required const Schema1 = v.partial(v.object({k1: v.string(), k2: v.number(), k3: v.boolean()})); const Schema2 = v.required(Schema1); const Schema3 = v.required(v.partial(v.object({k1: v.string(), k2: v.number(), k3: v.boolean()}))); // make none of the keys required const Schema4 = v.partial(Schema1); const Schema5 = v.partial(v.object({key: v.string()})); // make some keys required const Schema6 = v.partial(v.object({k1: v.string(), k2: v.number(), k3: v.boolean()})); const Schema7 = v.required(Schema6, ["k1", "k3"]); const Schema8 = v.required( v.partial(v.object({k1: v.string(), k2: v.number(), k3: v.boolean()})), ["k2"] ); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-shape/input.ts ================================================ import { z } from "zod"; const ObjectSchema = z.object({key: z.string()}); const StringSchema = ObjectSchema.shape.key; ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-shape/output.ts ================================================ import * as v from "valibot"; const ObjectSchema = v.object({key: v.string()}); const StringSchema = ObjectSchema.entries.key; ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-strict/input.ts ================================================ import { z } from "zod"; const Schema1 = z.object({key: z.string()}).strict(); const Schema2 = z.object({key: z.string()}, {message: "some message"}).strict(); const Schema3 = z.object({key: z.string()}, {description: "some description"}).strict(); const Schema4 = z.object({key: z.string()}); const Schema5 = Schema4.strict(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-strict/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.strictObject({key: v.string()}); const Schema2 = v.strictObject({key: v.string()}, "some message"); const Schema3 = v.pipe(v.strictObject({key: v.string()}), v.description("some description")); const Schema4 = v.object({key: v.string()}); const Schema5 = v.strictObject( /*@valibot-migrate we can't detect if Schema4 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema4.entries ); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-strip/input.ts ================================================ import { z } from "zod"; // passthrough const Schema1 = z.object({key: z.string()}).passthrough().strip(); const Schema2 = z.object({key: z.string()}, {message: "some message"}).passthrough().strip(); const Schema3 = z.object({key: z.string()}, {description: "some description"}).passthrough().strip(); const Schema4 = z.object({key: z.string()}).passthrough(); const Schema5 = Schema4.strip(); const Schema6 = z.object({key: z.string()}); const Schema7 = Schema6.passthrough().strip(); // strict const Schema8 = z.object({key: z.string()}).strict().strip(); const Schema9 = z.object({key: z.string()}, {message: "some message"}).strict().strip(); const Schema10 = z.object({key: z.string()}, {description: "some description"}).strict().strip(); const Schema11 = z.object({key: z.string()}).strict(); const Schema12 = Schema11.strip(); const Schema13 = z.object({key: z.string()}); const Schema14 = Schema13.strict().strip(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/object-strip/output.ts ================================================ import * as v from "valibot"; // passthrough const Schema1 = v.object({key: v.string()}); const Schema2 = v.object({key: v.string()}, "some message"); const Schema3 = v.object( v.pipe(v.object({key: v.string()}), v.description("some description")).entries ); const Schema4 = v.looseObject({key: v.string()}); const Schema5 = v.pipe(Schema4, v.strip()); const Schema6 = v.object({key: v.string()}); const Schema7 = v.object( /*@valibot-migrate we can't detect if Schema6 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema6.entries ); // strict const Schema8 = v.object({key: v.string()}); const Schema9 = v.object({key: v.string()}, "some message"); const Schema10 = v.object( v.pipe(v.object({key: v.string()}), v.description("some description")).entries ); const Schema11 = v.strictObject({key: v.string()}); const Schema12 = v.pipe(Schema11, v.strip()); const Schema13 = v.object({key: v.string()}); const Schema14 = v.object( /*@valibot-migrate we can't detect if Schema13 has a `pipe` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline*/ Schema13.entries ); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/optional-schema/input.ts ================================================ import { z } from "zod"; // optional outside object const Schema1 = z.string().optional(); const Schema2 = z.optional(z.string()); const Schema3 = z.string(); const Schema4 = Schema3.optional(); // optional inside object const Schema5 = z.object({key: z.string().optional()}); const Schema6 = z.object({key: z.optional(z.string())}); const Schema7 = z.object({key: z.string().email().optional()}); const Schema8 = z.object({key: z.optional(z.string().email())}); const Schema9 = z.object({key: z.number()}); // get the wrapped schema const Schema10 = z.number().optional(); const Schema11 = Schema10.unwrap(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/optional-schema/output.ts ================================================ import * as v from "valibot"; // optional outside object const Schema1 = v.optional(v.string()); const Schema2 = v.optional(v.string()); const Schema3 = v.string(); const Schema4 = v.optional(Schema3); // optional inside object const Schema5 = v.object({key: v.optional(v.string())}); const Schema6 = v.object({key: v.optional(v.string())}); const Schema7 = v.object({key: v.optional(v.pipe(v.string(), v.email()))}); const Schema8 = v.object({key: v.optional(v.pipe(v.string(), v.email()))}); const Schema9 = v.object({key: v.number()}); // get the wrapped schema const Schema10 = v.optional(v.number()); const Schema11 = v.unwrap(Schema10); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/or/input.ts ================================================ import { z } from "zod"; const Schema1 = z.string().or(z.number()); const Schema2 = z.string().or(z.number()).or(z.boolean()); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/or/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.union([v.string(), v.number()]); const Schema2 = v.union([v.union([v.string(), v.number()]), v.boolean()]); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/parsing/input.ts ================================================ import { z } from "zod"; const Schema = z.string(); const output1 = Schema.parse("to parse"); const output2 = Schema.parseAsync("to parseAsync"); const result1 = Schema.safeParse("to safeParse"); if (result1.success) { const output = result1.data; } else { const errors = result1.error; } const result2 = await Schema.safeParseAsync("to safeParseAsync"); if (result2.success) { const output = result2.data; } else { const errors = result2.error; } const result3 = await Schema.spa("to spa"); if (result3.success) { const output = result3.data; } else { const errors = result3.error; } ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/parsing/output.ts ================================================ import * as v from "valibot"; const Schema = v.string(); const output1 = v.parse(Schema, "to parse"); const output2 = v.parseAsync(Schema, "to parseAsync"); const result1 = v.safeParse(Schema, "to safeParse"); if (result1.success) { const output = result1.output; } else { const errors = result1.issues; } const result2 = await v.safeParseAsync(Schema, "to safeParseAsync"); if (result2.success) { const output = result2.output; } else { const errors = result2.issues; } const result3 = await v.safeParseAsync(Schema, "to spa"); if (result3.success) { const output = result3.output; } else { const errors = result3.issues; } ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/readonly/input.ts ================================================ import { z } from "zod"; const Schema1 = z.array(z.string()).readonly(); const Schema2 = z.map(z.string(), z.date()).readonly(); const Schema3 = z.set(z.string()).min(3).readonly(); const Schema4 = z.object({key: z.string()}).readonly(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/readonly/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.pipe(v.array(v.string()), v.readonly()); const Schema2 = v.pipe(v.map(v.string(), v.date()), v.readonly()); const Schema3 = v.pipe(v.set(v.string()), v.minSize(3), v.readonly()); const Schema4 = v.pipe(v.object({key: v.string()}), v.readonly()); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/record-schema/input.ts ================================================ import { z } from "zod"; const Schema1 = z.record(z.number()); const Schema2 = z.record(z.number(), {message: "some message"}); const Schema3 = z.record(z.string(), z.boolean()); const Schema4 = z.record(z.string(), z.boolean(), {message: "some message"}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/record-schema/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.record(v.string(), v.number()); const Schema2 = v.record(v.string(), v.number(), "some message"); const Schema3 = v.record(v.string(), v.boolean()); const Schema4 = v.record(v.string(), v.boolean(), "some message"); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/refine/input.ts ================================================ import { z } from "zod"; // Basic refine const Schema1 = z.number().refine((val) => val < 100, "Must be less then 100"); // Refine with string schema const Schema2 = z.string().refine((val) => val.length > 0, "Required"); // Refine after validator const Schema3 = z.number().min(0).refine((val) => val % 2 === 0, "Must be even"); // Multiple refines const Schema4 = z.string().refine((val) => val.length > 3).refine((val) => val.includes("@")); // Refine with complex condition const Schema5 = z.object({ name: z.string() }).refine((data) => data.name !== "admin", { message: "Cannot use admin" }); // Refine on linked schema const BaseSchema = z.string(); const RefinedSchema = BaseSchema.refine((val) => val.trim().length > 0); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/refine/output.ts ================================================ import * as v from "valibot"; // Basic refine const Schema1 = v.pipe(v.number(), v.check((val) => val < 100, "Must be less then 100")); // Refine with string schema const Schema2 = v.pipe(v.string(), v.check((val) => val.length > 0, "Required")); // Refine after validator const Schema3 = v.pipe(v.number(), v.minValue(0), v.check((val) => val % 2 === 0, "Must be even")); // Multiple refines const Schema4 = v.pipe( v.string(), v.check((val) => val.length > 3), v.check((val) => val.includes("@")) ); // Refine with complex condition const Schema5 = v.pipe( v.object({ name: v.string() }), v.check((data) => data.name !== "admin", "Cannot use admin") ); // Refine on linked schema const BaseSchema = v.string(); const RefinedSchema = v.pipe(BaseSchema, v.check((val) => val.trim().length > 0)); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/schema-chain/input.ts ================================================ import { z } from "zod"; const Schema1 = z.string().trim().email(); const output1 = z.string().parse("valibot@example.com"); const output2 = z.string().trim().email().parse("valibot@example.com"); const Schema3 = z.string().optional(); const Schema4 = z.string().optional().nullable(); const Schema5 = z.string().email().optional(); const Schema6 = z.string().email().optional().nullable(); const Schema7 = z.string(); const Schema8 = Schema7.trim().email(); const output = Schema8.parse("valibot@example.com"); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/schema-chain/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.pipe(v.string(), v.trim(), v.email()); const output1 = v.parse(v.string(), "valibot@example.com"); const output2 = v.parse(v.pipe(v.string(), v.trim(), v.email()), "valibot@example.com"); const Schema3 = v.optional(v.string()); const Schema4 = v.nullable(v.optional(v.string())); const Schema5 = v.optional(v.pipe(v.string(), v.email())); const Schema6 = v.nullable(v.optional(v.pipe(v.string(), v.email()))); const Schema7 = v.string(); const Schema8 = v.pipe(Schema7, v.trim(), v.email()); const output = v.parse(Schema8, "valibot@example.com"); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/schema-options/input.ts ================================================ import { z } from "zod"; // ------------ single ------------ // invalid_type_error const Schema1 = z.string({invalid_type_error: "must be a string"}); const Schema2 = z.literal("valibot", {invalid_type_error: 'must be "valibot"'}); // message const Schema3 = z.string({message: "must be a string"}); const Schema4 = z.literal("foo", {message: 'must be "foo"'}); // required_error const Schema5 = z.string({required_error: "is required"}); const Schema6 = z.literal("bar", {required_error: '"bar" is required'}); // description const Schema7 = z.string({description: "some description"}); const schema7Description = Schema7.description; const Schema8 = z.literal("hello", {description: 'some description (literal "hello")'}); const schema8Description = Schema8.description; // coerce const Schema9 = z.string({coerce: true}); const Schema10 = z.string({coerce: false}); // errorMap - supported by Valibot but incompatible const Schema11 = z.string({errorMap: () => ({message: "some message"})}); const Schema12 = z.literal("world", {errorMap: () => ({message: 'some message (literal "world")'})}); // ------------ multiple ------------ // invalid_type_error + required_error const Schema13 = z.string({invalid_type_error: "must be a string", required_error: "is required"}); const Schema14 = z.literal("bot", {invalid_type_error: 'must be "bot"', required_error: '"bot" is required'}); // invalid_type_error + message const Schema15 = z.string({invalid_type_error: "must be a string", message: "must be a string (msg)"}); const Schema16 = z.literal("bot", {invalid_type_error: 'must be "bot"', message: 'must be "bot" (msg)'}); // required_error + message const Schema17 = z.string({required_error: "is required", message: "must be a string (msg)"}); const Schema18 = z.literal("bot", {required_error: '"bot" is required', message: 'must be "bot" (msg)'}); // invalid_type_error + required_error + message const Schema19 = z.string({invalid_type_error: "must be a string", required_error: "is required", message: "must be a string (msg)"}); const Schema20 = z.literal("bot", {invalid_type_error: 'must be "bot"', required_error: '"bot" is required', message: 'must be "bot" (msg)'}); // coerce + invalid_type_error const Schema21 = z.string({coerce: true, invalid_type_error: "must be a string"}); const Schema22 = z.string({coerce: false, invalid_type_error: "must be a string"}); // coerce + description const Schema23 = z.string({coerce: true, description: "some description"}); const schema23Description = Schema23.description; const Schema24 = z.string({coerce: false, description: "some description"}); const schema24Description = Schema24.description; // coerce + invalid_type_error + description const Schema25 = z.string({coerce: true, invalid_type_error: "must be a string", description: "some description"}); const schema25Description = Schema25.description; const Schema26 = z.string({coerce: false, invalid_type_error: "must be a string", description: "some description"}); const schema26Description = Schema26.description; ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/schema-options/output.ts ================================================ import * as v from "valibot"; // ------------ single ------------ // invalid_type_error const Schema1 = v.string("must be a string"); const Schema2 = v.literal("valibot", 'must be "valibot"'); // message const Schema3 = v.string("must be a string"); const Schema4 = v.literal("foo", 'must be "foo"'); // required_error const Schema5 = v.string(issue => issue.input === undefined ? "is required" : issue.message); const Schema6 = v.literal( "bar", issue => issue.input === undefined ? '"bar" is required' : issue.message ); // description const Schema7 = v.pipe(v.string(), v.description("some description")); const schema7Description = v.getDescription(Schema7); const Schema8 = v.pipe(v.literal("hello"), v.description('some description (literal "hello")')); const schema8Description = v.getDescription(Schema8); // coerce const Schema9 = v.pipe(v.unknown(), v.toString()); const Schema10 = v.string(); // errorMap - supported by Valibot but incompatible const Schema11 = v.string(); const Schema12 = v.literal("world"); // ------------ multiple ------------ // invalid_type_error + required_error const Schema13 = v.string(issue => issue.input === undefined ? "is required" : "must be a string"); const Schema14 = v.literal( "bot", issue => issue.input === undefined ? '"bot" is required' : 'must be "bot"' ); // invalid_type_error + message const Schema15 = v.string("must be a string (msg)"); const Schema16 = v.literal("bot", 'must be "bot" (msg)'); // required_error + message const Schema17 = v.string("must be a string (msg)"); const Schema18 = v.literal("bot", 'must be "bot" (msg)'); // invalid_type_error + required_error + message const Schema19 = v.string("must be a string (msg)"); const Schema20 = v.literal("bot", 'must be "bot" (msg)'); // coerce + invalid_type_error const Schema21 = v.pipe(v.unknown(), v.toString("must be a string")); const Schema22 = v.string("must be a string"); // coerce + description const Schema23 = v.pipe(v.unknown(), v.toString(), v.description("some description")); const schema23Description = v.getDescription(Schema23); const Schema24 = v.pipe(v.string(), v.description("some description")); const schema24Description = v.getDescription(Schema24); // coerce + invalid_type_error + description const Schema25 = v.pipe( v.unknown(), v.toString("must be a string"), v.description("some description") ); const schema25Description = v.getDescription(Schema25); const Schema26 = v.pipe(v.string("must be a string"), v.description("some description")); const schema26Description = v.getDescription(Schema26); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/set-schema/input.ts ================================================ import { z } from "zod"; const Schema1 = z.set(z.number()); const Schema2 = z.set(z.number(), {message: "some message"}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/set-schema/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.set(v.number()); const Schema2 = v.set(v.number(), "some message"); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/set-validation-methods/input.ts ================================================ import { z } from "zod"; const Schema1 = z.set(z.string()).nonempty(); const Schema2 = z.set(z.string()).nonempty("some message"); const Schema3 = z.set(z.string()).nonempty({message: "some message"}); const Schema4 = z.set(z.string()).min(5); const Schema5 = z.set(z.string()).min(5, "some message"); const Schema6 = z.set(z.string()).min(5, {message: "some message"}); const Schema7 = z.set(z.string()).max(6); const Schema8 = z.set(z.string()).max(6, "some message"); const Schema9 = z.set(z.string()).max(6, {message: "some message"}); const Schema10 = z.set(z.string()).size(7); const Schema11 = z.set(z.string()).size(7, "some message"); const Schema12 = z.set(z.string()).size(7, {message: "some message"}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/set-validation-methods/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.pipe(v.set(v.string()), v.minSize(1)); const Schema2 = v.pipe(v.set(v.string()), v.minSize(1, "some message")); const Schema3 = v.pipe(v.set(v.string()), v.minSize(1, "some message")); const Schema4 = v.pipe(v.set(v.string()), v.minSize(5)); const Schema5 = v.pipe(v.set(v.string()), v.minSize(5, "some message")); const Schema6 = v.pipe(v.set(v.string()), v.minSize(5, "some message")); const Schema7 = v.pipe(v.set(v.string()), v.maxSize(6)); const Schema8 = v.pipe(v.set(v.string()), v.maxSize(6, "some message")); const Schema9 = v.pipe(v.set(v.string()), v.maxSize(6, "some message")); const Schema10 = v.pipe(v.set(v.string()), v.size(7)); const Schema11 = v.pipe(v.set(v.string()), v.size(7, "some message")); const Schema12 = v.pipe(v.set(v.string()), v.size(7, "some message")); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/specific-default-import/input.ts ================================================ import z from "zod"; const StringSchema = z.string(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/specific-default-import/output.ts ================================================ import * as v from "valibot"; const StringSchema = v.string(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/specific-namespace-import/input.ts ================================================ import * as z from "zod"; const StringSchema = z.string(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/specific-namespace-import/output.ts ================================================ import * as v from "valibot"; const StringSchema = v.string(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/string-validation-methods/input.ts ================================================ import { z } from "zod"; const EmailSchema = z.string().email(); const UrlSchema = z.string().url(); const EmojiSchema = z.string().emoji(); const UUIDSchema = z.string().uuid(); const NanoIDSchema = z.string().nanoid(); const CUID2Schema = z.string().cuid2(); const ULIDSchema = z.string().ulid(); const Base64Schema = z.string().base64(); const IpSchema = z.string().ip(); const IpV4Schema = z.string().ip({ version: "v4" }); const IpV6Schema = z.string().ip({ version: "v6" }); const DateSchema = z.string().date(); const RegexSchema = z.string().regex(/valibot/iu); const StartsWithSchema = z.string().startsWith("foo"); const EndsWithSchema = z.string().endsWith("bar"); const MinLengthSchema = z.string().min(5); const MaxLengthSchema = z.string().max(10); const LengthSchema = z.string().length(12); const NonEmptySchema = z.string().nonempty(); const TrimSchema = z.string().trim(); const ToLowerSchema = z.string().toLowerCase(); const ToUpperSchema = z.string().toUpperCase(); const IncludesSchema = z.string().includes("foo"); // `position` is not supported by Valibot const IncludesWithPositionSchema = z.string().includes("bar", { position: 1 }); const TimeSchema = z.string().time(); // `precision` is not supported by Valibot const TimeWithPrecisionSchema = z.string().time({ precision: 3 }); const DateTimeSchema = z.string().datetime(); // none of the customizations are supported by Valibot const DateTimeWithCustomizatonsSchema = z.string().datetime({ offset: true, local: false, precision: 2 }); // validators that are not supported by Valibot const CUIDSchema = z.string().cuid(); const Base64UrlSchema = z.string().base64url(); const JWTSchema = z.string().jwt(); const CIDRSchema = z.string().cidr(); const DurationSchema = z.string().duration(); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/string-validation-methods/output.ts ================================================ import * as v from "valibot"; const EmailSchema = v.pipe(v.string(), v.email()); const UrlSchema = v.pipe(v.string(), v.url()); const EmojiSchema = v.pipe(v.string(), v.emoji()); const UUIDSchema = v.pipe(v.string(), v.uuid()); const NanoIDSchema = v.pipe(v.string(), v.nanoid()); const CUID2Schema = v.pipe(v.string(), v.cuid2()); const ULIDSchema = v.pipe(v.string(), v.ulid()); const Base64Schema = v.pipe(v.string(), v.base64()); const IpSchema = v.pipe(v.string(), v.ip()); const IpV4Schema = v.pipe(v.string(), v.ipv4()); const IpV6Schema = v.pipe(v.string(), v.ipv6()); const DateSchema = v.pipe(v.string(), v.isoDate()); const RegexSchema = v.pipe(v.string(), v.regex(/valibot/iu)); const StartsWithSchema = v.pipe(v.string(), v.startsWith("foo")); const EndsWithSchema = v.pipe(v.string(), v.endsWith("bar")); const MinLengthSchema = v.pipe(v.string(), v.minLength(5)); const MaxLengthSchema = v.pipe(v.string(), v.maxLength(10)); const LengthSchema = v.pipe(v.string(), v.length(12)); const NonEmptySchema = v.pipe(v.string(), v.nonEmpty()); const TrimSchema = v.pipe(v.string(), v.trim()); const ToLowerSchema = v.pipe(v.string(), v.toLowerCase()); const ToUpperSchema = v.pipe(v.string(), v.toUpperCase()); const IncludesSchema = v.pipe(v.string(), v.includes("foo")); // `position` is not supported by Valibot const IncludesWithPositionSchema = v.pipe(v.string(), v.includes("bar")); const TimeSchema = v.pipe(v.string(), v.isoTimeSecond()); // `precision` is not supported by Valibot const TimeWithPrecisionSchema = v.pipe(v.string(), v.isoTimeSecond()); const DateTimeSchema = v.pipe(v.string(), v.isoTimestamp()); // none of the customizations are supported by Valibot const DateTimeWithCustomizatonsSchema = v.pipe(v.string(), v.isoTimestamp()); // validators that are not supported by Valibot const CUIDSchema = v.pipe(v.string(), v.cuid()); const Base64UrlSchema = v.pipe(v.string(), v.base64url()); const JWTSchema = v.pipe(v.string(), v.jwt()); const CIDRSchema = v.pipe(v.string(), v.cidr()); const DurationSchema = v.pipe(v.string(), v.duration()); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/symbol-schema/input.ts ================================================ import { z } from "zod"; const Schema1 = z.symbol(); const Schema2 = z.symbol({message: "some message"}); const Schema3 = z.symbol({description: "some description"}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/symbol-schema/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.symbol(); const Schema2 = v.symbol("some message"); const Schema3 = v.pipe(v.symbol(), v.description("some description")); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/transform/input.ts ================================================ import { z } from "zod"; // Basic transform const Schema1 = z.number().transform((val) => val * 2); // Transform with string schema const Schema2 = z.string().transform((val) => val.toUpperCase()); // Chained transform with validator const Schema3 = z.number().min(0).transform((val) => val + 1); // Transform after validator chain const Schema4 = z.string().email().transform((val) => `Email: ${val}`); // Multiple transforms const Schema5 = z.number().transform((val) => val * 2).transform((val) => val + 10); // Transform with complex function const Schema6 = z.object({ name: z.string() }).transform((data) => ({ ...data, displayName: data.name.toUpperCase() })); // Transform on linked schema const BaseSchema = z.string(); const TransformedSchema = BaseSchema.transform((val) => val.trim()); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/transform/output.ts ================================================ import * as v from "valibot"; // Basic transform const Schema1 = v.pipe(v.number(), v.transform((val) => val * 2)); // Transform with string schema const Schema2 = v.pipe(v.string(), v.transform((val) => val.toUpperCase())); // Chained transform with validator const Schema3 = v.pipe(v.number(), v.minValue(0), v.transform((val) => val + 1)); // Transform after validator chain const Schema4 = v.pipe(v.string(), v.email(), v.transform((val) => `Email: ${val}`)); // Multiple transforms const Schema5 = v.pipe(v.number(), v.transform((val) => val * 2), v.transform((val) => val + 10)); // Transform with complex function const Schema6 = v.pipe(v.object({ name: v.string() }), v.transform((data) => ({ ...data, displayName: data.name.toUpperCase() }))); // Transform on linked schema const BaseSchema = v.string(); const TransformedSchema = v.pipe(BaseSchema, v.transform((val) => val.trim())); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/tuple-schema/input.ts ================================================ import { z } from "zod"; const Schema1 = z.tuple([z.string()]); const Schema2 = z.tuple([z.string()], {message: "some message"}); const Schema3 = z.tuple([z.string()]).rest(z.null()); const Schema4 = z.tuple([z.string()], {message: "some message"}).rest(z.null()); const Schema5 = z.tuple([z.string()], {description: "some description"}).rest(z.null()); const Schema6 = z.tuple([z.string()]); const Schema7 = Schema6.rest(z.null()); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/tuple-schema/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.tuple([v.string()]); const Schema2 = v.tuple([v.string()], "some message"); const Schema3 = v.tupleWithRest([v.string()], v.null()); const Schema4 = v.tupleWithRest([v.string()], v.null(), "some message"); const Schema5 = v.pipe(v.tuple([v.string()]), v.description("some description"), v.rest(v.null())); const Schema6 = v.tuple([v.string()]); const Schema7 = v.pipe(Schema6, v.rest(v.null())); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/type-inference/input.ts ================================================ import { z } from "zod"; const Schema = z.string(); type Input = z.input; type Output1 = z.output; type Output2 = z.infer; ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/type-inference/output.ts ================================================ import * as v from "valibot"; const Schema = v.string(); type Input = v.InferInput; type Output1 = v.InferOutput; type Output2 = v.InferOutput; ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/undefined-schema/input.ts ================================================ import { z } from "zod"; const Schema1 = z.undefined(); const Schema2 = z.undefined({message: "some message"}); const Schema3 = z.undefined({description: "some description"}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/undefined-schema/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.undefined(); const Schema2 = v.undefined("some message"); const Schema3 = v.pipe(v.undefined(), v.description("some description")); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/union-schema/input.ts ================================================ import { z } from "zod"; const Schema1 = z.union([z.string(), z.number(), z.boolean()]); const Schema2 = z.union([z.string(), z.number(), z.boolean()], {message: "some message"}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/union-schema/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.union([v.string(), v.number(), v.boolean()]); const Schema2 = v.union([v.string(), v.number(), v.boolean()], "some message"); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/unknown-schema/input.ts ================================================ import { z } from "zod"; const Schema1 = z.unknown(); const Schema2 = z.unknown({message: "some message"}); const Schema3 = z.unknown({description: "some description"}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/unknown-schema/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.unknown(); const Schema2 = v.unknown(); const Schema3 = v.pipe(v.unknown(), v.description("some description")); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/validation-error-msg/input.ts ================================================ import { z } from "zod"; const Schema1 = z.string().email("invalid email address"); const Schema2 = z.string().url({message: "invalid url"}); const Schema3 = z.string().length(5, "must be exactly 5 characters long"); const Schema4 = z.string().startsWith("https://", {message: "must provide secure url"}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/validation-error-msg/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.pipe(v.string(), v.email("invalid email address")); const Schema2 = v.pipe(v.string(), v.url("invalid url")); const Schema3 = v.pipe(v.string(), v.length(5, "must be exactly 5 characters long")); const Schema4 = v.pipe(v.string(), v.startsWith("https://", "must provide secure url")); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/void-schema/input.ts ================================================ import { z } from "zod"; const Schema1 = z.void(); const Schema2 = z.void({message: "some message"}); const Schema3 = z.void({description: "some description"}); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/void-schema/output.ts ================================================ import * as v from "valibot"; const Schema1 = v.void(); const Schema2 = v.void("some message"); const Schema3 = v.pipe(v.void(), v.description("some description")); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/zod-enum/input.ts ================================================ import { z } from "zod"; // enum creation // way #1 const FruitEnum = z.enum(["Apple", "Orange", "Banana"]); // way #2 const VALUES = ["Valibot", "ModularForms"] as const; const LibraryEnum = z.enum(VALUES); // the enum property, not supported by Valibot const AnswerEnum = z.enum(["Yes", "No"]); const AnswerObj = AnswerEnum.enum; // retrieve the list of options const BoolEnum = z.enum(["true", "false"]); const boolOptions = BoolEnum.options; // extract or exclude values const FishEnum = z.enum(["Salmon", "Tuna", "Trout"]); const SalmonAndTrout = FishEnum.extract(["Salmon", "Trout"]); // `exclude` is not supported by Valibot const SalmonOnly = FishEnum.exclude(["Tuna", "Trout"]); ================================================ FILE: codemod/zod-to-valibot/__testfixtures__/zod-enum/output.ts ================================================ import * as v from "valibot"; // enum creation // way #1 const FruitEnum = v.picklist(["Apple", "Orange", "Banana"]); // way #2 const VALUES = ["Valibot", "ModularForms"] as const; const LibraryEnum = v.picklist(VALUES); // the enum property, not supported by Valibot const AnswerEnum = v.picklist(["Yes", "No"]); const AnswerObj = AnswerEnum.enum; // retrieve the list of options const BoolEnum = v.picklist(["true", "false"]); const boolOptions = BoolEnum.options; // extract or exclude values const FishEnum = v.picklist(["Salmon", "Tuna", "Trout"]); const SalmonAndTrout = v.picklist(["Salmon", "Trout"]); // `exclude` is not supported by Valibot const SalmonOnly = v.exclude(FishEnum, ["Tuna", "Trout"]); ================================================ FILE: codemod/zod-to-valibot/cli.mjs ================================================ #!/usr/bin/env node import { execSync } from 'child_process'; import { createRequire } from 'module'; import path from 'path'; import { fileURLToPath } from 'url'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const transformPath = path.join(__dirname, 'dist', 'index.mjs'); const require = createRequire(import.meta.url); const jscodeshiftBin = require.resolve('jscodeshift/bin/jscodeshift.js'); const args = process.argv.slice(2); const hasParserArg = args.some( (arg) => arg === '--parser' || arg.startsWith('--parser=') ); const hasExtensionsArg = args.some((arg) => arg.startsWith('--extensions')); const finalArgs = [...args]; if (!hasParserArg) { finalArgs.unshift('--parser=ts'); } if (!hasExtensionsArg) { finalArgs.unshift('--extensions=ts,tsx,js,jsx'); } if (args.length === 0) { console.log(` Usage: @valibot/zod-to-valibot [options] Convert Zod schemas to Valibot schemas Examples: @valibot/zod-to-valibot src/**/*.ts @valibot/zod-to-valibot --dry src/schemas.ts @valibot/zod-to-valibot --no-babel src/**/*.{ts,tsx} Common jscodeshift options: --dry Run without making changes --print Print output --verbose=2 Increase verbosity --parser=ts Specify parser (default: ts) For all options, see: jscodeshift --help `); process.exit(0); } try { const command = `"${process.execPath}" "${jscodeshiftBin}" -t "${transformPath}" ${finalArgs.join(' ')}`; execSync(command, { stdio: 'inherit' }); } catch (error) { process.exit(1); } ================================================ FILE: codemod/zod-to-valibot/package.json ================================================ { "name": "@valibot/zod-to-valibot", "description": "Official codemod for converting Zod schemas to Valibot", "version": "0.1.2", "license": "MIT", "author": "Elton Lobo", "homepage": "https://valibot.dev", "repository": { "type": "git", "url": "https://github.com/open-circle/valibot" }, "keywords": [ "codemod", "zod", "valibot", "schema" ], "type": "module", "main": "./dist/index.mjs", "types": "./dist/index.d.mts", "bin": { "zod-to-valibot": "./cli.mjs" }, "files": [ "dist", "cli.mjs" ], "publishConfig": { "access": "public" }, "scripts": { "build": "tsdown", "codemod": "jscodeshift", "test": "vitest" }, "dependencies": { "jscodeshift": "^17.3.0" }, "devDependencies": { "@types/jscodeshift": "17.3.0", "@types/node": "^24.10.1", "tsdown": "^0.16.6", "typescript": "^5.9.3", "valibot": "workspace:*", "vite-plugin-node-polyfills": "^0.24.0", "vitest": "^4.0.13", "zod": "^3.25.76" } } ================================================ FILE: codemod/zod-to-valibot/src/test-setup.test.ts ================================================ import transform from './transform'; import { defineTests } from './utils'; // maintain the sorted order defineTests(transform, [ 'any-schema', 'array-element', 'array-nonempty', 'array-schema', 'array-validation-methods', 'bigint-validation-methods', 'coerce-bigint-schema', 'coerce-boolean-schema', 'coerce-date-schema', 'coerce-number-schema', 'coerce-string-schema', 'custom-schema', 'date-validation-methods', 'default', 'default-import', 'default-import-with-alias', 'default-import-with-specific-alias', 'describe', 'discriminated-union-schema', 'instanceof-schema', 'intersection-schema', 'literal-schema', 'map-schema', 'multiple-imports-from-zod', 'named-import', 'named-import-with-alias', 'named-import-with-specific-alias', 'namespace-import', 'nan-schema', 'native-enum', 'never-schema', 'null-schema', 'nullable-schema', 'nullish-schema', 'number-validation-methods', 'object-catchall', 'object-deepPartial', 'object-extend', 'object-keyof', 'object-merge', 'object-omit', 'object-partial', 'object-passthrough', 'object-pick', 'object-required', 'object-shape', 'object-strict', 'object-strip', 'optional-schema', 'or', 'parsing', 'readonly', 'record-schema', 'refine', 'schema-chain', 'schema-options', 'set-schema', 'set-validation-methods', 'specific-default-import', 'specific-namespace-import', 'string-validation-methods', 'symbol-schema', 'transform', 'tuple-schema', 'type-inference', 'undefined-schema', 'union-schema', 'unknown-schema', 'validation-error-msg', 'void-schema', 'zod-enum', ]); ================================================ FILE: codemod/zod-to-valibot/src/transform/imports/imports.ts ================================================ import j, { type Collection } from 'jscodeshift'; type TransformImportsReturn = | { conclusion: 'skip' | 'unsuccessful'; cause: string; valibotIdentifier?: undefined; } | { conclusion: 'successful'; valibotIdentifier: string }; export function transformImports( root: Collection ): TransformImportsReturn { // Find all Zod import statements const zodImports = root.find( j.ImportDeclaration, (name) => name.source.value === 'zod' || name.source.value === 'zod/v4' ); // Check the number of statements is exactly one const importNodes = zodImports.nodes(); if (importNodes.length !== 1) { return { conclusion: importNodes.length === 0 ? 'skip' : 'unsuccessful', cause: 'Expected exactly one import statement from "zod" or "zod/v4".', }; } // Check the number of specifiers is exactly one const importSpecifiers = importNodes[0].specifiers; if (importSpecifiers?.length !== 1) { return { conclusion: 'unsuccessful', cause: 'Expected exactly one import specifier from "zod" or "zod/v4".', }; } // Obtain the identifier const importSpecifier = importSpecifiers[0]; const zodIdentifier = importSpecifier.local?.name; if (typeof zodIdentifier !== 'string') { return { conclusion: 'unsuccessful', cause: 'Expected the import specifier to have a local name.', }; } const isZodIdentifierZ = zodIdentifier === 'z'; const valibotIdentifier = isZodIdentifierZ ? 'v' : zodIdentifier; // Transform the import statements zodImports.replaceWith( j.importDeclaration( [j.importNamespaceSpecifier(j.identifier(valibotIdentifier))], j.literal('valibot') ) ); // Transform member expression root if required if (isZodIdentifierZ) { root .find(j.MemberExpression, { object: { name: zodIdentifier } }) .replaceWith((p) => j.memberExpression(j.identifier(valibotIdentifier), p.node.property) ); root .find(j.TSTypeReference, { typeName: { type: 'TSQualifiedName', left: { type: 'Identifier', name: zodIdentifier }, }, }) .filter( (p) => p.value.typeName.type === 'TSQualifiedName' && p.value.typeName.right.type === 'Identifier' ) .replaceWith((p) => j.tsTypeReference( j.tsQualifiedName( j.identifier(valibotIdentifier), // todo: find a better way to get the identifier p.value.typeName.type === 'TSQualifiedName' && p.value.typeName.right.type === 'Identifier' ? p.value.typeName.right : j.identifier('bug') ), p.value.typeParameters ) ); } return { conclusion: 'successful', valibotIdentifier, }; } ================================================ FILE: codemod/zod-to-valibot/src/transform/imports/index.ts ================================================ export * from './imports'; ================================================ FILE: codemod/zod-to-valibot/src/transform/index.ts ================================================ import type { Transform } from 'jscodeshift'; import { transformImports } from './imports'; import { transformSchemasAndLinks } from './schemas-and-links'; const transform: Transform = (fileInfo, api) => { const j = api.jscodeshift; const root = j(fileInfo.source); // ------------ Imports ------------ const transformImportsResult = transformImports(root); if (transformImportsResult.conclusion !== 'successful') { if (transformImportsResult.conclusion === 'unsuccessful') { const node = root.get().node; // Add comment indicating unsuccessful transformation node.comments ??= []; node.comments.unshift( j.commentBlock( ` @valibot-migrate: unable to transform imports from Zod to Valibot: ${transformImportsResult.cause} `, true, false ) ); return root.toSource(); } return undefined; } const valibotIdentifier = transformImportsResult.valibotIdentifier; // ------------ Schemas and links ------------ transformSchemasAndLinks(root, valibotIdentifier); return root.toSource(); }; export default transform; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/constants.ts ================================================ import { ZodSchemaType } from './types'; export const ZOD_SCHEMAS = [ 'any', 'array', 'bigint', 'boolean', 'custom', 'date', 'discriminatedUnion', 'enum', 'instanceof', 'intersection', 'literal', 'nan', 'nativeEnum', 'null', 'nullable', 'record', 'map', 'never', 'number', 'object', 'optional', 'set', 'string', 'symbol', 'tuple', 'undefined', 'union', 'unknown', 'void', ] as const; export const ZOD_SCHEMA_TO_TYPE: Record< (typeof ZOD_SCHEMAS)[number], ZodSchemaType > = { any: 'none', array: 'length', bigint: 'value', boolean: 'value', custom: 'none', date: 'value', discriminatedUnion: 'none', enum: 'none', instanceof: 'none', intersection: 'none', literal: 'none', map: 'size', nan: 'none', nativeEnum: 'none', never: 'none', null: 'none', nullable: 'none', record: 'none', number: 'value', object: 'none', optional: 'none', set: 'size', string: 'length', symbol: 'none', tuple: 'none', undefined: 'none', union: 'none', unknown: 'none', void: 'none', }; export const ZOD_VALUE_TYPE_SCHEMAS: readonly (typeof ZOD_SCHEMAS)[number][] = [ 'bigint', 'date', 'number', ]; export const ZOD_VALIDATORS = [ 'base64', 'base64url', 'cidr', 'cuid', 'cuid2', 'date', 'datetime', 'describe', 'duration', 'email', 'emoji', 'endsWith', 'finite', 'includes', 'int', 'ip', 'length', 'jwt', 'max', 'min', 'step', 'multipleOf', 'nanoid', 'negative', 'nonempty', 'nonnegative', 'nonpositive', 'positive', 'readonly', 'regex', 'safe', 'size', 'startsWith', 'toLowerCase', 'toUpperCase', 'trim', 'url', 'gt', 'gte', 'lt', 'lte', 'time', 'ulid', 'uuid', ] as const; export const ZOD_SCHEMA_PROPERTIES = [ 'element', 'description', 'shape', ] as const; export const ZOD_RESULT_PROPERTIES = ['data', 'error'] as const; export const ZOD_PROPERTIES = [ ...ZOD_SCHEMA_PROPERTIES, ...ZOD_RESULT_PROPERTIES, ] as const; export const ZOD_METHODS = [ 'array', 'catchall', 'default', 'deepPartial', 'exclude', 'extend', 'extract', 'keyof', 'omit', 'optional', 'or', 'merge', 'nullable', 'nullish', 'parse', 'parseAsync', 'partial', 'passthrough', 'pick', 'refine', 'required', 'rest', 'safeParse', 'safeParseAsync', 'strict', 'strip', 'spa', 'transform', 'unwrap', ] as const; export const ZOD_TYPES = ['infer', 'input', 'output'] as const; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/helpers.ts ================================================ import j from 'jscodeshift'; export function splitLastArg( maxArgs: number, args: j.CallExpression['arguments'] ): { firstArgs: j.CallExpression['arguments']; lastArg: j.CallExpression['arguments'][number] | null; } { let firstArgs = args; let lastArg: j.CallExpression['arguments'][number] | null = null; if (args.length === maxArgs && maxArgs > 0) { firstArgs = args.slice(0, args.length - 1); lastArg = args[args.length - 1]; } return { firstArgs, lastArg }; } const isPipeSchemaExp = (callExp: j.CallExpression) => callExp.callee.type === 'MemberExpression' && callExp.callee.property.type === 'Identifier' && callExp.callee.property.name === 'pipe'; export function addToPipe( valibotIdentifier: string, addTo: j.CallExpression | j.MemberExpression | j.Identifier, add: j.CallExpression ): j.CallExpression { return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('pipe')), [ ...(addTo.type === 'CallExpression' && isPipeSchemaExp(addTo) ? addTo.arguments : [addTo]), add, ] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/index.ts ================================================ export * from './schemas-and-links'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/array/array.ts ================================================ import j from 'jscodeshift'; export function transformArray( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, args: j.CallExpression['arguments'] ) { return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('array')), [schemaExp, ...args] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/array/index.ts ================================================ export * from './array'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/catchall/catchall.ts ================================================ import j from 'jscodeshift'; import { addToPipe } from '../../helpers'; export function transformCatchall( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, args: j.CallExpression['arguments'] ) { if ( schemaExp.type === 'CallExpression' && schemaExp.callee.type === 'MemberExpression' && schemaExp.callee.object.type === 'Identifier' && schemaExp.callee.object.name === valibotIdentifier && schemaExp.callee.property.type === 'Identifier' && schemaExp.callee.property.name === 'object' ) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('objectWithRest') ), [schemaExp.arguments[0], ...args, ...schemaExp.arguments.slice(1)] ); } return addToPipe( valibotIdentifier, schemaExp, j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('catchall') ), [...args] ) ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/catchall/index.ts ================================================ export * from './catchall'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/deepPartial/deepPartial.ts ================================================ import j from 'jscodeshift'; export function transformDeepPartial( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, inputArgs: j.CallExpression['arguments'] ) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('deepPartial') ), [schemaExp, ...inputArgs] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/deepPartial/index.ts ================================================ export * from './deepPartial'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/default/default.ts ================================================ import j from 'jscodeshift'; export function transformDefault( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, args: j.CallExpression['arguments'] ) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('optional') ), [schemaExp, ...args] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/default/index.ts ================================================ export * from './default'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/exclude/exclude.ts ================================================ import j from 'jscodeshift'; export function transformExclude( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, args: j.CallExpression['arguments'] ) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('exclude') ), [schemaExp, ...args] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/exclude/index.ts ================================================ export * from './exclude'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/extend/extend.ts ================================================ import j from 'jscodeshift'; function isInlineObjectCall(exp: j.CallExpression): boolean { return ( exp.callee.type === 'MemberExpression' && exp.callee.property.type === 'Identifier' && exp.callee.property.name === 'object' ); } function extractObjectProperties( exp: j.CallExpression ): j.ObjectExpression['properties'] { const firstArg = exp.arguments[0]; if (firstArg && firstArg.type === 'ObjectExpression') { return firstArg.properties; } return []; } export function transformExtend( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, args: j.CallExpression['arguments'] ) { const extensionObject = args[0]; const objectProperties: j.ObjectExpression['properties'] = []; // Handle base schema if (schemaExp.type === 'CallExpression' && isInlineObjectCall(schemaExp)) { // Inline the properties from the base schema const baseSchemaProperties = extractObjectProperties(schemaExp); objectProperties.push(...baseSchemaProperties); } else { // Use spread with .entries for schema reference const schemaEntries = j.memberExpression( schemaExp, j.identifier('entries') ); if (schemaExp.type === 'Identifier') { schemaEntries.comments = [ j.block( `@valibot-migrate we can't detect if ${schemaExp.name} has a \`pipe\` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline`, true, false ), ]; } objectProperties.push(j.spreadElement(schemaEntries)); } // Handle extension object if (extensionObject.type === 'ObjectExpression') { // Inline the extension properties objectProperties.push(...extensionObject.properties); } else if (extensionObject.type !== 'SpreadElement') { // Spread the extension object objectProperties.push(j.spreadElement(extensionObject)); } else { objectProperties.push(j.spreadElement(extensionObject.argument)); } const extendedObject = j.objectExpression(objectProperties); return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('object')), [extendedObject] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/extend/index.ts ================================================ export * from './extend'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/extract/extract.ts ================================================ import j from 'jscodeshift'; export function transformExtract( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('picklist') ), [...args] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/extract/index.ts ================================================ export * from './extract'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/index.ts ================================================ export * from './array'; export * from './catchall'; export * from './default'; export * from './deepPartial'; export * from './exclude'; export * from './extend'; export * from './extract'; export * from './keyof'; export * from './merge'; export * from './nullable'; export * from './nullish'; export * from './omit'; export * from './optional'; export * from './or'; export * from './parse'; export * from './parseAsync'; export * from './partial'; export * from './passthrough'; export * from './pick'; export * from './refine'; export * from './required'; export * from './rest'; export * from './safeParse'; export * from './safeParseAsync'; export * from './strict'; export * from './strip'; export * from './transform'; export * from './unwrap'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/keyof/index.ts ================================================ export * from './keyof'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/keyof/keyof.ts ================================================ import j from 'jscodeshift'; export function transformKeyof( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, args: j.CallExpression['arguments'] ) { return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('keyof')), [schemaExp, ...args] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/merge/index.ts ================================================ export * from './merge'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/merge/merge.ts ================================================ import j from 'jscodeshift'; function isInlineObjectCall(exp: j.CallExpression): boolean { return ( exp.callee.type === 'MemberExpression' && exp.callee.property.type === 'Identifier' && exp.callee.property.name === 'object' ); } function extractObjectProperties( exp: j.CallExpression ): j.ObjectExpression['properties'] { const firstArg = exp.arguments[0]; if (firstArg && firstArg.type === 'ObjectExpression') { return firstArg.properties; } return []; } export function transformMerge( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, args: j.CallExpression['arguments'] ) { const secondSchema = args[0]; const objectProperties: j.ObjectExpression['properties'] = []; // Handle first schema if (schemaExp.type === 'CallExpression' && isInlineObjectCall(schemaExp)) { // Inline the properties from the first schema const firstSchemaProperties = extractObjectProperties(schemaExp); objectProperties.push(...firstSchemaProperties); } else { // Use spread with .entries for schema reference const firstSchemaEntries = j.memberExpression( schemaExp, j.identifier('entries') ); if (schemaExp.type === 'Identifier') { firstSchemaEntries.comments = [ j.block( `@valibot-migrate we can't detect if ${schemaExp.name} has a \`pipe\` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline`, true, false ), ]; } objectProperties.push(j.spreadElement(firstSchemaEntries)); } // Handle second schema if ( secondSchema.type === 'CallExpression' && isInlineObjectCall(secondSchema) ) { // Inline the properties from the second schema const secondSchemaProperties = extractObjectProperties( secondSchema as j.CallExpression ); objectProperties.push(...secondSchemaProperties); // this can technically never happen cause zod will yell at you if you spread the second element } else if (secondSchema.type !== 'SpreadElement') { // Use spread with .entries for schema reference const secondSchemaEntries = j.memberExpression( secondSchema, j.identifier('entries') ); if (secondSchema.type === 'Identifier') { secondSchemaEntries.comments = [ j.block( `@valibot-migrate we can't detect if ${secondSchema.name} has a \`pipe\` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline`, true, false ), ]; } objectProperties.push(j.spreadElement(secondSchemaEntries)); } else { const secondSchemaEntries = j.memberExpression( secondSchema.argument, j.identifier('entries') ); objectProperties.push(j.spreadElement(secondSchemaEntries)); } const mergedObject = j.objectExpression(objectProperties); return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('object')), [mergedObject] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/nullable/index.ts ================================================ export * from './nullable'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/nullable/nullable.ts ================================================ import j from 'jscodeshift'; export function transformNullable( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, args: j.CallExpression['arguments'] ) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('nullable') ), [schemaExp, ...args] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/nullish/index.ts ================================================ export * from './nullish'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/nullish/nullish.ts ================================================ import j from 'jscodeshift'; export function transformNullish( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, args: j.CallExpression['arguments'] ) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('optional') ), [ j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('nullable') ), [schemaExp, ...args] ), ] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/omit/index.ts ================================================ export * from './omit'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/omit/omit.ts ================================================ import j from 'jscodeshift'; function toValiOmitArg(omitArg: j.CallExpression['arguments'][number]) { if (omitArg.type !== 'ObjectExpression') { return null; } const selectedKeys = omitArg.properties .map((p) => p.type === 'ObjectProperty' && p.key.type === 'Identifier' ? j.stringLiteral(p.key.name) : null ) .filter((v) => v !== null); return selectedKeys.length > 0 ? j.arrayExpression(selectedKeys) : null; } export function transformOmit( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, inputArgs: j.CallExpression['arguments'] ) { const args: any[] = [schemaExp]; const valiOmitArg = toValiOmitArg(inputArgs[0]); if (valiOmitArg === null) { return schemaExp; } args.push(valiOmitArg); return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('omit')), args ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/optional/index.ts ================================================ export * from './optional'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/optional/optional.ts ================================================ import j from 'jscodeshift'; export function transformOptional( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, args: j.CallExpression['arguments'] ) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('optional') ), [schemaExp, ...args] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/or/index.ts ================================================ export * from './or'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/or/or.ts ================================================ import j from 'jscodeshift'; export function transformOr( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, inputArgs: j.CallExpression['arguments'] ) { return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('union')), [j.arrayExpression([schemaExp, ...inputArgs])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/parse/index.ts ================================================ export * from './parse'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/parse/parse.ts ================================================ import j from 'jscodeshift'; export function transformParse( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, args: j.CallExpression['arguments'] ) { return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('parse')), [schemaExp, ...args] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/parseAsync/index.ts ================================================ export * from './parseAsync'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/parseAsync/parseAsync.ts ================================================ import j from 'jscodeshift'; export function transformParseAsync( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, args: j.CallExpression['arguments'] ) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('parseAsync') ), [schemaExp, ...args] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/partial/index.ts ================================================ export * from './partial'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/partial/partial.ts ================================================ import j from 'jscodeshift'; function toValiPartialArg(partialArg: j.CallExpression['arguments'][number]) { if (partialArg.type !== 'ObjectExpression') { return null; } const selectedKeys = partialArg.properties .map((p) => p.type === 'ObjectProperty' && p.key.type === 'Identifier' ? j.stringLiteral(p.key.name) : null ) .filter((v) => v !== null); return j.arrayExpression(selectedKeys); } export function transformPartial( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, inputArgs: j.CallExpression['arguments'] ) { const args: any[] = [schemaExp]; const valiPartialArg = inputArgs.length > 0 ? toValiPartialArg(inputArgs[0]) : null; if (valiPartialArg !== null) { if (valiPartialArg.elements.length === 0) { return schemaExp; } args.push(valiPartialArg); } return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('partial') ), args ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/passthrough/index.ts ================================================ export * from './passthrough'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/passthrough/passthrough.ts ================================================ import j from 'jscodeshift'; import { addToPipe } from '../../helpers'; export function transformPassthrough( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier ) { // If the schema is already a looseObject, return it as-is (no-op) if ( schemaExp.type === 'CallExpression' && schemaExp.callee.type === 'MemberExpression' && schemaExp.callee.object.type === 'Identifier' && schemaExp.callee.object.name === valibotIdentifier && schemaExp.callee.property.type === 'Identifier' && schemaExp.callee.property.name === 'looseObject' ) { return schemaExp; } // If the schema is a pipe with looseObject, return it as-is (no-op) if ( schemaExp.type === 'CallExpression' && schemaExp.callee.type === 'MemberExpression' && schemaExp.callee.object.type === 'Identifier' && schemaExp.callee.object.name === valibotIdentifier && schemaExp.callee.property.type === 'Identifier' && schemaExp.callee.property.name === 'pipe' && schemaExp.arguments.length > 0 && schemaExp.arguments[0].type === 'CallExpression' && schemaExp.arguments[0].callee.type === 'MemberExpression' && schemaExp.arguments[0].callee.object.type === 'Identifier' && schemaExp.arguments[0].callee.object.name === valibotIdentifier && schemaExp.arguments[0].callee.property.type === 'Identifier' && schemaExp.arguments[0].callee.property.name === 'looseObject' ) { return schemaExp; } // Transform regular object to looseObject if ( schemaExp.type === 'CallExpression' && schemaExp.callee.type === 'MemberExpression' && schemaExp.callee.object.type === 'Identifier' && schemaExp.callee.object.name === valibotIdentifier && schemaExp.callee.property.type === 'Identifier' && schemaExp.callee.property.name === 'object' ) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('looseObject') ), schemaExp.arguments ); } const entries = j.memberExpression(schemaExp, j.identifier('entries')); if (schemaExp.type === 'Identifier') { entries.comments = [ j.block( `@valibot-migrate we can't detect if ${schemaExp.name} has a \`pipe\` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline`, true, false ), ]; } // Handle other cases (like previously defined schemas) return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('looseObject') ), [entries] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/pick/index.ts ================================================ export * from './pick'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/pick/pick.ts ================================================ import j from 'jscodeshift'; function toValiPickArg(pickArg: j.CallExpression['arguments'][number]) { if (pickArg.type !== 'ObjectExpression') { return null; } const pickedKeys = pickArg.properties .map((p) => p.type === 'ObjectProperty' && p.key.type === 'Identifier' ? j.stringLiteral(p.key.name) : null ) .filter((v) => v !== null); return pickedKeys.length > 0 ? j.arrayExpression(pickedKeys) : null; } export function transformPick( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, inputArgs: j.CallExpression['arguments'] ) { const args: any[] = [schemaExp]; const valiPickArg = toValiPickArg(inputArgs[0]); if (valiPickArg === null) { return schemaExp; } args.push(valiPickArg); return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('pick')), args ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/refine/index.ts ================================================ export * from './refine'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/refine/refine.ts ================================================ import j from 'jscodeshift'; import { addToPipe } from '../../helpers'; export function transformRefine( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, args: j.CallExpression['arguments'] ) { // Transform Zod's refine arguments to Valibot's check arguments const transformedArgs = args.map((arg) => { // If the argument is an object with { message: "..." }, extract the message if ( arg.type === 'ObjectExpression' && arg.properties.length === 1 && arg.properties[0].type === 'ObjectProperty' && arg.properties[0].key.type === 'Identifier' && arg.properties[0].key.name === 'message' ) { return arg.properties[0].value; } return arg; }) as typeof args; return addToPipe( valibotIdentifier, schemaExp, j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('check') ), transformedArgs ) ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/required/index.ts ================================================ export * from './required'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/required/required.ts ================================================ import j from 'jscodeshift'; function toValiRequiredArg(requiredArg: j.CallExpression['arguments'][number]) { if (requiredArg.type !== 'ObjectExpression') { return null; } const selectedKeys = requiredArg.properties .map((p) => p.type === 'ObjectProperty' && p.key.type === 'Identifier' ? j.stringLiteral(p.key.name) : null ) .filter((v) => v !== null); return j.arrayExpression(selectedKeys); } export function transformRequired( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, inputArgs: j.CallExpression['arguments'] ) { const args: any[] = [schemaExp]; const valiRequiredArg = inputArgs.length > 0 ? toValiRequiredArg(inputArgs[0]) : null; if (valiRequiredArg !== null) { if (valiRequiredArg.elements.length === 0) { return schemaExp; } args.push(valiRequiredArg); } return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('required') ), args ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/rest/index.ts ================================================ export * from './rest'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/rest/rest.ts ================================================ import j from 'jscodeshift'; import { addToPipe } from '../../helpers'; export function transformRest( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, args: j.CallExpression['arguments'] ) { if ( schemaExp.type === 'CallExpression' && schemaExp.callee.type === 'MemberExpression' && schemaExp.callee.object.type === 'Identifier' && schemaExp.callee.object.name === valibotIdentifier && schemaExp.callee.property.type === 'Identifier' && schemaExp.callee.property.name === 'tuple' ) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('tupleWithRest') ), [schemaExp.arguments[0], ...args, ...schemaExp.arguments.slice(1)] ); } return addToPipe( valibotIdentifier, schemaExp, j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('rest')), args ) ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/safeParse/index.ts ================================================ export * from './safeParse'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/safeParse/safeParse.ts ================================================ import j from 'jscodeshift'; export function transformSafeParse( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, args: j.CallExpression['arguments'] ) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('safeParse') ), [schemaExp, ...args] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/safeParseAsync/index.ts ================================================ export * from './safeParseAsync'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/safeParseAsync/safeParseAsync.ts ================================================ import j from 'jscodeshift'; export function transformSafeParseAsync( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, args: j.CallExpression['arguments'] ) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('safeParseAsync') ), [schemaExp, ...args] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/strict/index.ts ================================================ export * from './strict'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/strict/strict.ts ================================================ import j from 'jscodeshift'; import { addToPipe } from '../../helpers'; export function transformStrict( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier ) { // If the schema is already a strictObject, return it as-is (no-op) if ( schemaExp.type === 'CallExpression' && schemaExp.callee.type === 'MemberExpression' && schemaExp.callee.object.type === 'Identifier' && schemaExp.callee.object.name === valibotIdentifier && schemaExp.callee.property.type === 'Identifier' && schemaExp.callee.property.name === 'strictObject' ) { return schemaExp; } // If the schema is a pipe with strictObject, return it as-is (no-op) if ( schemaExp.type === 'CallExpression' && schemaExp.callee.type === 'MemberExpression' && schemaExp.callee.object.type === 'Identifier' && schemaExp.callee.object.name === valibotIdentifier && schemaExp.callee.property.type === 'Identifier' && schemaExp.callee.property.name === 'pipe' && schemaExp.arguments.length > 0 && schemaExp.arguments[0].type === 'CallExpression' && schemaExp.arguments[0].callee.type === 'MemberExpression' && schemaExp.arguments[0].callee.object.type === 'Identifier' && schemaExp.arguments[0].callee.object.name === valibotIdentifier && schemaExp.arguments[0].callee.property.type === 'Identifier' && schemaExp.arguments[0].callee.property.name === 'strictObject' ) { return schemaExp; } // Transform regular object to strictObject if ( schemaExp.type === 'CallExpression' && schemaExp.callee.type === 'MemberExpression' && schemaExp.callee.object.type === 'Identifier' && schemaExp.callee.object.name === valibotIdentifier && schemaExp.callee.property.type === 'Identifier' && schemaExp.callee.property.name === 'object' ) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('strictObject') ), schemaExp.arguments ); } const entries = j.memberExpression(schemaExp, j.identifier('entries')); if (schemaExp.type === 'Identifier') { entries.comments = [ j.block( `@valibot-migrate we can't detect if ${schemaExp.name} has a \`pipe\` operator, if it does you might need to migrate this by hand otherwise it will loose it's pipeline`, true, false ), ]; } // Handle other cases (like previously defined schemas) return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('strictObject') ), [entries] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/strip/index.ts ================================================ export * from './strip'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/strip/strip.ts ================================================ import j from 'jscodeshift'; import { addToPipe } from '../../helpers'; export function transformStrip( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier ) { if ( schemaExp.type === 'CallExpression' && schemaExp.callee.type === 'MemberExpression' && schemaExp.callee.object.type === 'Identifier' && schemaExp.callee.object.name === valibotIdentifier && schemaExp.callee.property.type === 'Identifier' && (schemaExp.callee.property.name === 'looseObject' || schemaExp.callee.property.name === 'strictObject') ) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('object') ), schemaExp.arguments ); } return addToPipe( valibotIdentifier, schemaExp, j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('strip') ), [] ) ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/transform/index.ts ================================================ export * from './transform'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/transform/transform.ts ================================================ import j from 'jscodeshift'; import { addToPipe } from '../../helpers'; export function transformTransform( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, args: j.CallExpression['arguments'] ) { return addToPipe( valibotIdentifier, schemaExp, j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('transform') ), args ) ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/unwrap/index.ts ================================================ export * from './unwrap'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/methods/unwrap/unwrap.ts ================================================ import j from 'jscodeshift'; export function transformUnwrap( valibotIdentifier: string, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, args: j.CallExpression['arguments'] ) { return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('unwrap')), [schemaExp, ...args] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/properties/description.ts ================================================ import j from 'jscodeshift'; export function transformDescription( valibotIdentifier: string, exp: j.CallExpression | j.MemberExpression | j.Identifier ) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('getDescription') ), [exp] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/properties/element.ts ================================================ import j from 'jscodeshift'; export function transformElement( exp: j.CallExpression | j.MemberExpression | j.Identifier ) { return j.memberExpression(exp, j.identifier('item')); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/properties/index.ts ================================================ export * from './element'; export * from './description'; export * from './shape'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/properties/shape.ts ================================================ import j from 'jscodeshift'; export function transformShape( exp: j.CallExpression | j.MemberExpression | j.Identifier ) { return j.memberExpression(exp, j.identifier('entries')); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/any/any.ts ================================================ import j from 'jscodeshift'; import { getSchemaComps, getSchemaWithOptionalDescription } from '../helpers'; export function transformAny( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { baseSchema, description } = getSchemaComps( valibotIdentifier, 'any', args, 1, false, false ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/any/index.ts ================================================ export * from './any'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/array/array.ts ================================================ import j from 'jscodeshift'; import { getSchemaComps, getSchemaWithOptionalDescription } from '../helpers'; export function transformArray( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { baseSchema, description } = getSchemaComps( valibotIdentifier, 'array', args, 2 ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/array/index.ts ================================================ export * from './array'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/bigint/bigint.ts ================================================ import j from 'jscodeshift'; import { getDescription, getOptions, getSchemaComps, getSchemaWithOptionalDescription, getTransformedMsgs, } from '../helpers'; export function transformBigint( valibotIdentifier: string, args: j.CallExpression['arguments'], coerceSchema: boolean ) { const { baseSchema, coerce, description } = getSchemaComps( valibotIdentifier, 'bigint', args, 1, coerceSchema ); if (coerce) { const optionsArg = args.length > 0 && args[args.length - 1]?.type === 'ObjectExpression' ? args[args.length - 1] : null; const msgs = getTransformedMsgs(getOptions(optionsArg)); return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('pipe')), [ j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('unknown') ), [] ), j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('toBigint') ), msgs.filter((m) => m !== null) ), ...(description ? [getDescription(valibotIdentifier, description)] : []), ] ); } return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/bigint/index.ts ================================================ export * from './bigint'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/boolean/boolean.ts ================================================ import j from 'jscodeshift'; import { getDescription, getOptions, getSchemaComps, getSchemaWithOptionalDescription, getTransformedMsgs, } from '../helpers'; export function transformBoolean( valibotIdentifier: string, args: j.CallExpression['arguments'], coerceSchema: boolean ) { const { baseSchema, coerce, description } = getSchemaComps( valibotIdentifier, 'boolean', args, 1, coerceSchema ); if (coerce) { const optionsArg = args.length > 0 && args[args.length - 1]?.type === 'ObjectExpression' ? args[args.length - 1] : null; const msgs = getTransformedMsgs(getOptions(optionsArg)); return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('pipe')), [ j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('unknown') ), [] ), j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('toBoolean') ), msgs.filter((m) => m !== null) ), ...(description ? [getDescription(valibotIdentifier, description)] : []), ] ); } return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/boolean/index.ts ================================================ export * from './boolean'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/custom/custom.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getOption } from '../helpers'; export function transformCustom( valibotIdentifier: string, args: j.CallExpression['arguments'], // no type definition found typeParameters: any ) { const { firstArgs, lastArg } = splitLastArg(2, args); const messageArg: any[] = []; let messageKeyVal: any = null; if (lastArg !== null) { if (lastArg.type === 'StringLiteral') { messageArg.push(lastArg); } else if ( lastArg.type === 'ObjectExpression' && lastArg.properties.length === 1 && (messageKeyVal = getOption(lastArg, 'message')) !== null ) { messageArg.push(messageKeyVal); } else { messageArg.push(lastArg); } } const transformedArgs = [...firstArgs, ...messageArg]; if (transformedArgs.length === 0) { transformedArgs.push(j.arrowFunctionExpression([], j.booleanLiteral(true))); } const res = j.callExpression.from({ callee: j.memberExpression( j.identifier(valibotIdentifier), j.identifier('custom') ), arguments: transformedArgs, }); // parser and types are not in sync // @ts-expect-error res.typeParameters = typeParameters; return res; } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/custom/index.ts ================================================ export * from './custom'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/date/date.ts ================================================ import j from 'jscodeshift'; import { getDescription, getOptions, getSchemaComps, getSchemaWithOptionalDescription, getTransformedMsgs, } from '../helpers'; export function transformDate( valibotIdentifier: string, args: j.CallExpression['arguments'], coerceSchema: boolean ) { const { baseSchema, coerce, description } = getSchemaComps( valibotIdentifier, 'date', args, 1, coerceSchema ); if (coerce) { const optionsArg = args.length > 0 && args[args.length - 1]?.type === 'ObjectExpression' ? args[args.length - 1] : null; const msgs = getTransformedMsgs(getOptions(optionsArg)); return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('pipe')), [ j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('unknown') ), [] ), j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('toDate') ), msgs.filter((m) => m !== null) ), ...(description ? [getDescription(valibotIdentifier, description)] : []), ] ); } return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/date/index.ts ================================================ export * from './date'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/discriminatedUnion/discriminatedUnion.ts ================================================ import j from 'jscodeshift'; import { getSchemaComps, getSchemaWithOptionalDescription } from '../helpers'; export function transformDiscriminatedUnion( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { baseSchema, description } = getSchemaComps( valibotIdentifier, 'variant', args, 3 ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/discriminatedUnion/index.ts ================================================ export * from './discriminatedUnion'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/enum/enum.ts ================================================ import j from 'jscodeshift'; import { getSchemaComps, getSchemaWithOptionalDescription } from '../helpers'; export function transformEnum( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { baseSchema, description } = getSchemaComps( valibotIdentifier, 'picklist', args, 2 ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/enum/index.ts ================================================ export * from './enum'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/helpers.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../helpers'; import type { SchemaOptionsToASTVal } from './types'; export function getTransformedMsgs(schemaOptions: SchemaOptionsToASTVal) { return schemaOptions.message ? [schemaOptions.message] : schemaOptions.required_error ? [ j.arrowFunctionExpression( [j.identifier('issue')], j.conditionalExpression( j.binaryExpression( '===', j.memberExpression( j.identifier('issue'), j.identifier('input') ), j.identifier('undefined') ), schemaOptions.required_error, schemaOptions.invalid_type_error ?? j.memberExpression( j.identifier('issue'), j.identifier('message') ) ), true ), ] : schemaOptions.invalid_type_error ? [schemaOptions.invalid_type_error] : []; } export function getOption( optionsArgs: j.CallExpression['arguments'][number] | null, optionName: string ) { if (!optionsArgs || optionsArgs.type !== 'ObjectExpression') { return null; } const optionVals = optionsArgs.properties .map((p) => p.type === 'ObjectProperty' && p.key.type === 'Identifier' && p.key.name === optionName ? p.value : null ) .filter((v) => v !== null); const optionVal = optionVals[0]; return optionVal === undefined || optionVal.type === 'RestElement' || optionVal.type === 'SpreadElementPattern' || optionVal.type === 'PropertyPattern' || optionVal.type === 'ObjectPattern' || optionVal.type === 'ArrayPattern' || optionVal.type === 'AssignmentPattern' || optionVal.type === 'SpreadPropertyPattern' || optionVal.type === 'TSParameterProperty' ? null : optionVal; } export function getOptions( optionsArgs: j.CallExpression['arguments'][number] | null ): Partial< Record< 'description' | 'invalid_type_error' | 'required_error' | 'message', ReturnType > & { coerce: boolean } > { const coerceOption = getOption(optionsArgs, 'coerce'); return { description: getOption(optionsArgs, 'description'), invalid_type_error: getOption(optionsArgs, 'invalid_type_error'), required_error: getOption(optionsArgs, 'required_error'), message: getOption(optionsArgs, 'message'), coerce: coerceOption?.type === 'BooleanLiteral' && coerceOption.value, }; } export function getSchemaComps( valibotIdentifier: string, schemaName: string, args: j.CallExpression['arguments'], maxArgs: number, coerce = false, addMsgArg = true ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(maxArgs, args); const options = lastArg !== null ? getOptions(lastArg) : {}; return { baseSchema: j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier(schemaName) ), [...argsExceptOptions, ...(addMsgArg ? getTransformedMsgs(options) : [])] ), coerce: coerce || options.coerce, description: options.description, }; } export function getDescription( valibotIdentifier: string, description: SchemaOptionsToASTVal['description'] & {} ) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('description') ), [description] ); } export function getSchemaWithOptionalDescription( valibotIdentifier: string, schema: j.CallExpression, description: SchemaOptionsToASTVal['description'] ) { return description ? j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('pipe') ), [schema, getDescription(valibotIdentifier, description)] ) : schema; } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/index.ts ================================================ export * from './any'; export * from './array'; export * from './bigint/bigint'; export * from './boolean'; export * from './custom'; export * from './date'; export * from './discriminatedUnion'; export * from './enum'; export * from './instanceof'; export * from './intersection'; export * from './nan'; export * from './nativeEnum'; export * from './never'; export * from './null'; export * from './nullable'; export * from './number'; export * from './object'; export * from './optional'; export * from './record'; export * from './set'; export * from './string'; export * from './symbol'; export * from './tuple'; export * from './literal'; export * from './map'; export * from './undefined'; export * from './union'; export * from './unknown'; export * from './void'; export type { SchemaOptionsToASTVal } from './types'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/instanceof/index.ts ================================================ export * from './instanceof'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/instanceof/instanceof.ts ================================================ import j from 'jscodeshift'; import { getSchemaComps, getSchemaWithOptionalDescription } from '../helpers'; export function transformInstanceof( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { baseSchema, description } = getSchemaComps( valibotIdentifier, 'instance', args, 2 ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/intersection/index.ts ================================================ export * from './intersection'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/intersection/intersection.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getOptions, getSchemaWithOptionalDescription, getTransformedMsgs, } from '../helpers'; export function transformIntersection( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(3, args); const options = lastArg !== null ? getOptions(lastArg) : {}; return getSchemaWithOptionalDescription( valibotIdentifier, j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('intersect') ), [j.arrayExpression(argsExceptOptions), ...getTransformedMsgs(options)] ), options.description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/literal/index.ts ================================================ export * from './literal'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/literal/literal.ts ================================================ import j from 'jscodeshift'; import { getSchemaComps, getSchemaWithOptionalDescription } from '../helpers'; export function transformLiteral( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { let schemaName: 'null' | 'undefined' | 'literal' = 'literal'; let maxArgs = 2; // The `literal` schema has at least one argument // todo: find a way to check the assumption is correct and bail out if required const [valArg] = args; if ( valArg.type === 'NullLiteral' || (valArg.type === 'Identifier' && valArg.name === 'undefined') ) { args = args.slice(1); maxArgs = 1; schemaName = valArg.type === 'NullLiteral' ? 'null' : 'undefined'; } const { baseSchema, description } = getSchemaComps( valibotIdentifier, schemaName, args, maxArgs ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/map/index.ts ================================================ export * from './map'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/map/map.ts ================================================ import j from 'jscodeshift'; import { getSchemaComps, getSchemaWithOptionalDescription } from '../helpers'; export function transformMap( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { baseSchema, description } = getSchemaComps( valibotIdentifier, 'map', args, 3 ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/nan/index.ts ================================================ export * from './nan'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/nan/nan.ts ================================================ import j from 'jscodeshift'; import { getSchemaComps, getSchemaWithOptionalDescription } from '../helpers'; export function transformNan( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { baseSchema, description } = getSchemaComps( valibotIdentifier, 'nan', args, 1 ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/nativeEnum/index.ts ================================================ export * from './nativeEnum'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/nativeEnum/nativeEnum.ts ================================================ import j from 'jscodeshift'; import { getSchemaComps, getSchemaWithOptionalDescription } from '../helpers'; export function transformNativeEnum( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { baseSchema, description } = getSchemaComps( valibotIdentifier, 'enum', args, 2 ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/never/index.ts ================================================ export * from './never'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/never/never.ts ================================================ import j from 'jscodeshift'; import { getSchemaComps, getSchemaWithOptionalDescription } from '../helpers'; export function transformNever( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { baseSchema, description } = getSchemaComps( valibotIdentifier, 'never', args, 1 ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/null/index.ts ================================================ export * from './null'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/null/null.ts ================================================ import j from 'jscodeshift'; import { getSchemaComps, getSchemaWithOptionalDescription } from '../helpers'; export function transformNull( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { baseSchema, description } = getSchemaComps( valibotIdentifier, 'null', args, 1 ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/nullable/index.ts ================================================ export * from './nullable'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/nullable/nullable.ts ================================================ import j from 'jscodeshift'; import { getSchemaComps, getSchemaWithOptionalDescription } from '../helpers'; export function transformNullable( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { baseSchema, description } = getSchemaComps( valibotIdentifier, 'nullable', args, 2 ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/number/index.ts ================================================ export * from './number'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/number/number.ts ================================================ import j from 'jscodeshift'; import { getDescription, getOptions, getSchemaComps, getSchemaWithOptionalDescription, getTransformedMsgs, } from '../helpers'; export function transformNumber( valibotIdentifier: string, args: j.CallExpression['arguments'], coerceSchema: boolean ) { const { baseSchema, coerce, description } = getSchemaComps( valibotIdentifier, 'number', args, 1, coerceSchema ); if (coerce) { const optionsArg = args.length > 0 && args[args.length - 1]?.type === 'ObjectExpression' ? args[args.length - 1] : null; const msgs = getTransformedMsgs(getOptions(optionsArg)); return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('pipe')), [ j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('unknown') ), [] ), j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('toNumber') ), msgs.filter((m) => m !== null) ), ...(description ? [getDescription(valibotIdentifier, description)] : []), ] ); } return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/object/index.ts ================================================ export * from './object'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/object/object.ts ================================================ import j from 'jscodeshift'; import { ObjectModifier } from '../../types'; import { getSchemaComps, getSchemaWithOptionalDescription } from '../helpers'; export function transformObject( valibotIdentifier: string, args: j.CallExpression['arguments'], modifier: ObjectModifier = null ) { let schemaName = 'object'; if (modifier === 'strict') { schemaName = 'strictObject'; } else if (modifier === 'passthrough') { schemaName = 'looseObject'; } const { baseSchema, description } = getSchemaComps( valibotIdentifier, schemaName, args, 2 ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/optional/index.ts ================================================ export * from './optional'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/optional/optional.ts ================================================ import j from 'jscodeshift'; import { getSchemaComps, getSchemaWithOptionalDescription } from '../helpers'; export function transformOptional( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { baseSchema, description } = getSchemaComps( valibotIdentifier, 'optional', args, 2 ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/record/index.ts ================================================ export * from './record'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/record/record.ts ================================================ import j from 'jscodeshift'; import { getSchemaComps, getSchemaWithOptionalDescription, } from '../../schemas/helpers'; export function transformRecord( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { baseSchema, description } = getSchemaComps( valibotIdentifier, 'record', args.length === 1 || (args.length === 2 && args[1].type === 'ObjectExpression') ? [ j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('string') ), [] ), ...args, ] : args, 3 ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/set/index.ts ================================================ export * from './set'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/set/set.ts ================================================ import j from 'jscodeshift'; import { getSchemaComps, getSchemaWithOptionalDescription } from '../helpers'; export function transformSet( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { baseSchema, description } = getSchemaComps( valibotIdentifier, 'set', args, 2 ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/string/index.ts ================================================ export * from './string'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/string/string.ts ================================================ import j from 'jscodeshift'; import { getDescription, getOptions, getSchemaComps, getSchemaWithOptionalDescription, getTransformedMsgs, } from '../helpers'; export function transformString( valibotIdentifier: string, args: j.CallExpression['arguments'], coerceSchema: boolean ) { const { baseSchema, coerce, description } = getSchemaComps( valibotIdentifier, 'string', args, 1, coerceSchema ); if (coerce) { const optionsArg = args.length > 0 && args[args.length - 1]?.type === 'ObjectExpression' ? args[args.length - 1] : null; const msgs = getTransformedMsgs(getOptions(optionsArg)); return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('pipe')), [ j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('unknown') ), [] ), j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('toString') ), msgs.filter((m) => m !== null) ), ...(description ? [getDescription(valibotIdentifier, description)] : []), ] ); } return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/symbol/index.ts ================================================ export * from './symbol'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/symbol/symbol.ts ================================================ import j from 'jscodeshift'; import { getSchemaComps, getSchemaWithOptionalDescription } from '../helpers'; export function transformSymbol( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { baseSchema, description } = getSchemaComps( valibotIdentifier, 'symbol', args, 1 ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/tuple/index.ts ================================================ export * from './tuple'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/tuple/tuple.ts ================================================ import j from 'jscodeshift'; import { getSchemaComps, getSchemaWithOptionalDescription } from '../helpers'; export function transformTuple( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { baseSchema, description } = getSchemaComps( valibotIdentifier, 'tuple', args, 2 ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/types.ts ================================================ import type { getOption } from './helpers'; type SchemaOptionASTVal = ReturnType; export type SchemaOptionsToASTVal = Partial< Record< 'invalid_type_error' | 'required_error' | 'message' | 'description', SchemaOptionASTVal > >; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/undefined/index.ts ================================================ export * from './undefined'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/undefined/undefined.ts ================================================ import j from 'jscodeshift'; import { getSchemaComps, getSchemaWithOptionalDescription } from '../helpers'; export function transformUndefined( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { baseSchema, description } = getSchemaComps( valibotIdentifier, 'undefined', args, 1 ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/union/index.ts ================================================ export * from './union'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/union/union.ts ================================================ import j from 'jscodeshift'; import { getSchemaComps, getSchemaWithOptionalDescription } from '../helpers'; export function transformUnion( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { baseSchema, description } = getSchemaComps( valibotIdentifier, 'union', args, 2 ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/unknown/index.ts ================================================ export * from './unknown'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/unknown/unknown.ts ================================================ import j from 'jscodeshift'; import { getSchemaComps, getSchemaWithOptionalDescription } from '../helpers'; export function transformUnknown( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { baseSchema, description } = getSchemaComps( valibotIdentifier, 'unknown', args, 1, false, false ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/void/index.ts ================================================ export * from './void'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas/void/void.ts ================================================ import j from 'jscodeshift'; import { getSchemaComps, getSchemaWithOptionalDescription } from '../helpers'; export function transformVoid( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { baseSchema, description } = getSchemaComps( valibotIdentifier, 'void', args, 1 ); return getSchemaWithOptionalDescription( valibotIdentifier, baseSchema, description ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/schemas-and-links.ts ================================================ import j from 'jscodeshift'; import { assertNever, getIsTypeFn } from '../../utils'; import { ZOD_METHODS, ZOD_PROPERTIES, ZOD_SCHEMA_TO_TYPE, ZOD_SCHEMAS, ZOD_TYPES, ZOD_VALIDATORS, } from './constants'; import { addToPipe } from './helpers'; import { transformArray as transformArrayMethod, transformCatchall, transformDeepPartial, transformDefault, transformExclude, transformExtend, transformExtract, transformKeyof, transformMerge, transformNullable as transformNullableMethod, transformNullish, transformOmit, transformOptional as transformOptionalMethod, transformOr, transformParse, transformParseAsync, transformPartial, transformPassthrough, transformPick, transformRefine, transformRequired, transformRest, transformSafeParse, transformSafeParseAsync, transformStrict, transformStrip, transformTransform, transformUnwrap, } from './methods'; import { transformDescription, transformElement, transformShape, } from './properties'; import { transformAny, transformArray, transformBigint, transformBoolean, transformCustom, transformDate, transformDiscriminatedUnion, transformEnum, transformInstanceof, transformIntersection, transformLiteral, transformMap, transformNan, transformNativeEnum, transformNever, transformNull, transformNullable, transformNumber, transformObject, transformOptional, transformRecord, transformSet, transformString, transformSymbol, transformTuple, transformUndefined, transformUnion, transformUnknown, transformVoid, } from './schemas'; import { ObjectModifier, ZodSchemaType } from './types'; import { transformBase64, transformCUID2, transformDateTime, transformDate as transformDateValidator, transformDescribe, transformEmail, transformEmoji, transformEndsWith, transformFinite, transformGt, transformGte, transformIncludes, transformInt, transformIp, transformLength, transformLt, transformLte, transformMax, transformMin, transformMultipleOf, transformNanoid, transformNegative, transformNonEmpty, transformNonNegative, transformNonPositive, transformPositive, transformReadonly, transformRegex, transformSafe, transformSize, transformStartsWith, transformTime, transformToLowerCase, transformToUpperCase, transformTrim, transformULID, transformUnimplemented, transformUrl, transformUUID, } from './validators'; type UnknownPath = j.ASTPath<{ type: unknown }>; type ZodSchemaName = (typeof ZOD_SCHEMAS)[number]; type ZodValidatorName = (typeof ZOD_VALIDATORS)[number]; type ZodMethodName = (typeof ZOD_METHODS)[number]; type ZodPropertyName = (typeof ZOD_PROPERTIES)[number]; type ZodTypeName = (typeof ZOD_TYPES)[number]; function isCallExp(path: UnknownPath): path is j.ASTPath { return path.value.type === 'CallExpression'; } function isMemberExp(path: UnknownPath): path is j.ASTPath { return path.value.type === 'MemberExpression'; } const isZodSchemaName = getIsTypeFn(ZOD_SCHEMAS); const isZodValidatorName = getIsTypeFn(ZOD_VALIDATORS); const isZodMethodName = getIsTypeFn(ZOD_METHODS); const isZodPropertyName = getIsTypeFn(ZOD_PROPERTIES); const isZodTypeName = getIsTypeFn(ZOD_TYPES); function checkForObjectModifierInChain( cur: j.ASTPath ): ObjectModifier { let parent = cur.parentPath; let latestModifier: ObjectModifier = null; while (parent) { if ( parent.value.type === 'CallExpression' && parent.value.callee.type === 'MemberExpression' && parent.value.callee.property.type === 'Identifier' ) { const methodName = parent.value.callee.property.name; if (methodName === 'strict' || methodName === 'passthrough' || methodName === 'strip') { latestModifier = methodName; } } if ( parent.value.type === 'MemberExpression' && parent.value.property.type === 'Identifier' && parent.parentPath?.value.type === 'CallExpression' ) { const methodName = parent.value.property.name; if (methodName === 'strict' || methodName === 'passthrough' || methodName === 'strip') { latestModifier = methodName; } } parent = parent.parentPath; } return latestModifier; } function toValibotSchemaExp( valibotIdentifier: string, zodSchemaName: ZodSchemaName, inputArgs: j.CallExpression['arguments'], // no type definition found typeParameters: any, coerceOption = false, objectModifier: ObjectModifier = null ): j.CallExpression { const args = [valibotIdentifier, inputArgs] as const; const argsWithCoerce = [...args, coerceOption] as const; switch (zodSchemaName) { case 'any': return transformAny(...args); case 'array': return transformArray(...args); case 'string': return transformString(...argsWithCoerce); case 'boolean': return transformBoolean(...argsWithCoerce); case 'custom': return transformCustom(...args, typeParameters); case 'discriminatedUnion': return transformDiscriminatedUnion(...args); case 'instanceof': return transformInstanceof(...args); case 'intersection': return transformIntersection(...args); case 'map': return transformMap(...args); case 'nan': return transformNan(...args); case 'nativeEnum': return transformNativeEnum(...args); case 'never': return transformNever(...args); case 'null': return transformNull(...args); case 'nullable': return transformNullable(...args); case 'number': return transformNumber(...argsWithCoerce); case 'bigint': return transformBigint(...argsWithCoerce); case 'date': return transformDate(...argsWithCoerce); case 'enum': return transformEnum(...args); case 'literal': return transformLiteral(...args); case 'object': return transformObject(...args, objectModifier); case 'optional': return transformOptional(...args); case 'record': return transformRecord(...args); case 'set': return transformSet(...args); case 'symbol': return transformSymbol(...args); case 'undefined': return transformUndefined(...args); case 'union': return transformUnion(...args); case 'unknown': return transformUnknown(...args); case 'tuple': return transformTuple(...args); case 'void': return transformVoid(...args); default: { assertNever(zodSchemaName); } } } function toValibotActionExp( valibotIdentifier: string, zodValidatorName: ZodValidatorName, inputArgs: j.CallExpression['arguments'], schemaType: ZodSchemaType, useBigInt: boolean ) { const args = [valibotIdentifier, inputArgs] as const; switch (zodValidatorName) { case 'base64': return transformBase64(...args); case 'base64url': return transformUnimplemented(...args, 'base64url'); case 'cidr': return transformUnimplemented(...args, 'cidr'); case 'cuid': return transformUnimplemented(...args, 'cuid'); case 'cuid2': return transformCUID2(...args); case 'date': return transformDateValidator(...args); case 'datetime': return transformDateTime(...args); case 'describe': return transformDescribe(...args); case 'duration': return transformUnimplemented(...args, 'duration'); case 'email': return transformEmail(...args); case 'emoji': return transformEmoji(...args); case 'endsWith': return transformEndsWith(...args); case 'finite': return transformFinite(...args); case 'includes': return transformIncludes(...args); case 'int': return transformInt(...args); case 'ip': return transformIp(...args); case 'jwt': return transformUnimplemented(...args, 'jwt'); case 'length': return transformLength(...args); case 'max': return transformMax(...args, schemaType); case 'min': return transformMin(...args, schemaType); case 'step': case 'multipleOf': return transformMultipleOf(...args); case 'nanoid': return transformNanoid(...args); case 'negative': return transformNegative(...args, useBigInt); case 'nonempty': return transformNonEmpty(...args, schemaType === 'size'); case 'nonnegative': return transformNonNegative(...args, useBigInt); case 'nonpositive': return transformNonPositive(...args, useBigInt); case 'positive': return transformPositive(...args, useBigInt); case 'readonly': return transformReadonly(valibotIdentifier); case 'regex': return transformRegex(...args); case 'safe': return transformSafe(...args); case 'size': return transformSize(...args); case 'startsWith': return transformStartsWith(...args); case 'toLowerCase': return transformToLowerCase(...args); case 'toUpperCase': return transformToUpperCase(...args); case 'trim': return transformTrim(...args); case 'url': return transformUrl(...args); case 'gt': return transformGt(...args); case 'gte': return transformGte(...args); case 'lt': return transformLt(...args); case 'lte': return transformLte(...args); case 'time': return transformTime(...args); case 'ulid': return transformULID(...args); case 'uuid': return transformUUID(...args); default: assertNever(zodValidatorName); } } function toValiPropExp( valibotIdentifier: string, exp: j.CallExpression | j.MemberExpression | j.Identifier, propertyName: ZodPropertyName ) { switch (propertyName) { case 'data': return j.memberExpression(exp, j.identifier('output')); case 'description': return transformDescription(valibotIdentifier, exp); case 'element': return transformElement(exp); case 'error': return j.memberExpression(exp, j.identifier('issues')); case 'shape': return transformShape(exp); default: assertNever(propertyName); } } function toValibotMethodExp( valibotIdentifier: string, zodMethodName: ZodMethodName, schemaExp: j.CallExpression | j.MemberExpression | j.Identifier, inputArgs: j.CallExpression['arguments'] ) { const args = [valibotIdentifier, schemaExp, inputArgs] as const; switch (zodMethodName) { case 'array': return transformArrayMethod(...args); case 'catchall': return transformCatchall(valibotIdentifier, schemaExp, inputArgs); case 'default': return transformDefault(...args); case 'deepPartial': return transformDeepPartial(...args); case 'exclude': return transformExclude(...args); case 'extend': return transformExtend(...args); case 'extract': return transformExtract(valibotIdentifier, inputArgs); case 'keyof': return transformKeyof(...args); case 'omit': return transformOmit(...args); case 'or': return transformOr(...args); case 'optional': return transformOptionalMethod(...args); case 'merge': return transformMerge(...args); case 'nullable': return transformNullableMethod(...args); case 'parse': return transformParse(...args); case 'parseAsync': return transformParseAsync(...args); case 'partial': return transformPartial(...args); case 'passthrough': return transformPassthrough(valibotIdentifier, schemaExp); case 'pick': return transformPick(...args); case 'refine': return transformRefine(...args); case 'required': return transformRequired(...args); case 'rest': return transformRest(...args); case 'safeParse': return transformSafeParse(...args); case 'safeParseAsync': case 'spa': return transformSafeParseAsync(...args); case 'strict': return transformStrict(valibotIdentifier, schemaExp); case 'strip': return transformStrip(valibotIdentifier, schemaExp); case 'transform': return transformTransform(...args); case 'unwrap': return transformUnwrap(...args); case 'nullish': return transformNullish(...args); default: assertNever(zodMethodName); } } function getValiType( valibotIdentifier: string, typeName: string, typeParameters: j.TSTypeParameterInstantiation | null | undefined ) { return j.tsTypeReference( j.tsQualifiedName(j.identifier(valibotIdentifier), j.identifier(typeName)), typeParameters ); } function toValiTypeExp( valibotIdentifier: string, typeParameters: j.TSTypeParameterInstantiation | null | undefined, zodTypeName: ZodTypeName ) { switch (zodTypeName) { case 'infer': case 'output': return getValiType(valibotIdentifier, 'InferOutput', typeParameters); case 'input': return getValiType(valibotIdentifier, 'InferInput', typeParameters); default: assertNever(zodTypeName); } } function transformSchemasAndLinksHelper( root: j.Collection, valibotIdentifier: string, identifier: string, schemaType: ZodSchemaType | null ) { const relevantExps = [ ...root .find(j.MemberExpression, { object: { name: identifier }, }) .paths(), ...root.find(j.TSTypeReference).paths(), ] // to make sure nested schemas are transformed first .reverse(); main: for (const relevantExp of relevantExps) { if ( relevantExp.value.type === 'TSTypeReference' && relevantExp.value.typeName.type === 'TSQualifiedName' && relevantExp.value.typeName.left.type === 'Identifier' && relevantExp.value.typeName.left.name === valibotIdentifier ) { if ( relevantExp.value.typeName.right.type === 'Identifier' && isZodTypeName(relevantExp.value.typeName.right.name) ) { relevantExp.replace( toValiTypeExp( valibotIdentifier, relevantExp.value.typeParameters, relevantExp.value.typeName.right.name ) ); } continue; } let transformedExp: | j.CallExpression | j.MemberExpression | j.Identifier | null = null; let transformLinks = true; let coerce = false; let useBigInt = false; let curSchemaType = schemaType; let cur: UnknownPath = relevantExp; let rootExp: | j.ASTPath | j.ASTPath | null = null; let knownRootExp: | j.ASTPath | j.ASTPath | null = null; while (isMemberExp(cur) || isCallExp(cur)) { rootExp = cur; if (isMemberExp(cur)) { if (cur.value.property.type !== 'Identifier') { // the property name must always be an indentifier as // extracting the property name might get tricky otherwise transformLinks = false; break; } const propertyName = cur.value.property.name; // `coerce` is a special case if (propertyName === 'coerce') { coerce = true; } else if (isZodPropertyName(propertyName)) { coerce = false; transformedExp = toValiPropExp( valibotIdentifier, transformedExp ?? j.identifier(identifier), propertyName ); } else if (!isCallExp(cur.parentPath)) { // unknown property name transformLinks = false; break; } knownRootExp = cur; cur = cur.parentPath; continue; } // `cur` is a CallExpression if ( cur.value.callee.type !== 'MemberExpression' || cur.value.callee.property.type !== 'Identifier' ) { // the property name must always be an indentifier as // extracting the property name might get tricky otherwise transformLinks = false; break; } const propertyName = cur.value.callee.property.name; if (curSchemaType === null && isZodSchemaName(propertyName)) { curSchemaType = ZOD_SCHEMA_TO_TYPE[propertyName]; useBigInt = propertyName === 'bigint'; // Check if there's a modifier call in the chain for object schemas let objectModifier: ObjectModifier = null; if (propertyName === 'object') { objectModifier = checkForObjectModifierInChain(cur); } transformedExp = toValibotSchemaExp( valibotIdentifier, propertyName, cur.value.arguments, // parser and types are not in sync // @ts-expect-error cur.value.typeParameters, coerce, objectModifier ); } else if (isZodMethodName(propertyName)) { transformedExp = toValibotMethodExp( valibotIdentifier, propertyName, transformedExp ?? j.identifier(identifier), cur.value.arguments ); } else if (isZodValidatorName(propertyName)) { if (curSchemaType === null) { // validators can only be applied to parsed schemas transformLinks = false; break; } transformedExp = addToPipe( valibotIdentifier, transformedExp ?? j.identifier(identifier), toValibotActionExp( valibotIdentifier, propertyName, cur.value.arguments, curSchemaType, useBigInt ) ); } else { // `propertyName` is not a schema, validator, or method name // it's not safe to transform the chain transformLinks = false; break; } coerce = false; knownRootExp = cur; cur = cur.parentPath; } if (transformedExp !== null) { knownRootExp?.replace(transformedExp); } if (transformLinks && rootExp !== null) { const nxtPath = j.AwaitExpression.check(rootExp.parentPath.value) ? rootExp.parentPath : rootExp; if ( j.VariableDeclarator.check(nxtPath.parentPath.value) && j.Identifier.check(nxtPath.parentPath.value.id) ) { // transform links transformSchemasAndLinksHelper( root, valibotIdentifier, nxtPath.parentPath.value.id.name, curSchemaType ); } } } } export function transformSchemasAndLinks( root: j.Collection, valibotIdentifier: string ) { transformSchemasAndLinksHelper( root, valibotIdentifier, valibotIdentifier, null ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/types.ts ================================================ export type ZodSchemaType = 'value' | 'length' | 'size' | 'none'; export type ObjectModifier = 'strict' | 'passthrough' | null; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/base64/base64.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformBase64( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(1, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('base64')), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/base64/index.ts ================================================ export * from './base64'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/cuid2/cuid2.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformCUID2( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(1, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('cuid2')), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/cuid2/index.ts ================================================ export * from './cuid2'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/date/date.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformDate( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(1, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('isoDate') ), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/date/index.ts ================================================ export * from './date'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/datetime/datetime.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformDateTime( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(1, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('isoTimestamp') ), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/datetime/index.ts ================================================ export * from './datetime'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/describe/describe.ts ================================================ import j from 'jscodeshift'; export function transformDescribe( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('description') ), args ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/describe/index.ts ================================================ export * from './describe'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/email/email.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformEmail( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(1, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('email')), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/email/index.ts ================================================ export * from './email'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/emoji/emoji.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformEmoji( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(1, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('emoji')), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/emoji/index.ts ================================================ export * from './emoji'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/endsWith/endsWith.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformEndsWith( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(2, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('endsWith') ), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/endsWith/index.ts ================================================ export * from './endsWith'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/finite/finite.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformFinite( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(1, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('finite')), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/finite/index.ts ================================================ export * from './finite'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/gt/gt.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformGt( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(2, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('gtValue') ), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/gt/index.ts ================================================ export * from './gt'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/gte/gte.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformGte( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(2, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('minValue') ), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/gte/index.ts ================================================ export * from './gte'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/helpers.ts ================================================ import j from 'jscodeshift'; export function getValidatorMsg( msgArg: j.CallExpression['arguments'][number] | null ) { if (msgArg === null) { return null; } if (msgArg.type !== 'ObjectExpression') { return msgArg; } const msgVals = msgArg.properties .map((p) => p.type === 'ObjectProperty' && p.key.type === 'Identifier' && p.key.name === 'message' ? p.value : null ) .filter((v) => v !== null); const msgVal = msgVals.at(0); return msgVal === undefined || msgVal.type === 'RestElement' || msgVal.type === 'SpreadElementPattern' || msgVal.type === 'PropertyPattern' || msgVal.type === 'ObjectPattern' || msgVal.type === 'ArrayPattern' || msgVal.type === 'AssignmentPattern' || msgVal.type === 'SpreadPropertyPattern' || msgVal.type === 'TSParameterProperty' ? null : msgVal; } export function transformUnimplemented( valibotIdentifier: string, args: j.CallExpression['arguments'], validatorName: string ) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier(validatorName) ), args ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/includes/includes.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformIncludes( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(2, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('includes') ), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/includes/index.ts ================================================ export * from './includes'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/index.ts ================================================ export * from './base64'; export * from './cuid2'; export * from './date'; export * from './datetime'; export * from './describe'; export * from './email'; export * from './emoji'; export * from './endsWith'; export * from './finite'; export * from './includes'; export * from './int'; export * from './ip'; export * from './length'; export * from './max'; export * from './min'; export * from './multipleOf'; export * from './nanoid'; export * from './negative'; export * from './nonempty'; export * from './nonnegative'; export * from './nonpositive'; export * from './positive'; export * from './readonly'; export * from './regex'; export * from './safe'; export * from './size'; export * from './startsWith'; export * from './toLowerCase'; export * from './toUpperCase'; export * from './trim'; export * from './url'; export * from './gt'; export * from './gte'; export * from './lt'; export * from './lte'; export * from './time'; export * from './ulid'; export * from './uuid'; export { transformUnimplemented } from './helpers'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/int/index.ts ================================================ export * from './int'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/int/int.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformInt( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(1, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('integer') ), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/ip/index.ts ================================================ export * from './ip'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/ip/ip.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function getVersion( arg: j.CallExpression['arguments'][number] | null ): 'ipv4' | 'ipv6' | null { if (arg === null || arg.type !== 'ObjectExpression') { return null; } const vals = arg.properties .map((p) => p.type === 'ObjectProperty' && p.key.type === 'Identifier' && p.key.name === 'version' ? p.value : null ) .filter((v) => v !== null); const val = vals.at(0); // todo: handle cases where the version is not a string literal return val?.type === 'StringLiteral' ? val.value === 'v4' ? 'ipv4' : 'ipv6' : null; } export function transformIp( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { lastArg } = splitLastArg(1, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier(getVersion(lastArg) ?? 'ip') ), msgArg !== null ? [msgArg] : [] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/length/index.ts ================================================ export * from './length'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/length/length.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformLength( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(2, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('length')), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/lt/index.ts ================================================ export * from './lt'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/lt/lt.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformLt( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(2, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('ltValue') ), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/lte/index.ts ================================================ export * from './lte'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/lte/lte.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformLte( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(2, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('maxValue') ), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/max/index.ts ================================================ export * from './max'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/max/max.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { ZodSchemaType } from '../../types'; import { getValidatorMsg } from '../helpers'; export function transformMax( valibotIdentifier: string, args: j.CallExpression['arguments'], schemaType: ZodSchemaType ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(2, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier( `max${schemaType === 'value' ? 'Value' : schemaType === 'size' ? 'Size' : 'Length'}` ) ), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/min/index.ts ================================================ export * from './min'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/min/min.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { ZodSchemaType } from '../../types'; import { getValidatorMsg } from '../helpers'; export function transformMin( valibotIdentifier: string, args: j.CallExpression['arguments'], schemaType: ZodSchemaType ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(2, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier( `min${schemaType === 'value' ? 'Value' : schemaType === 'size' ? 'Size' : 'Length'}` ) ), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/multipleOf/index.ts ================================================ export * from './multipleOf'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/multipleOf/multipleOf.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformMultipleOf( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(2, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('multipleOf') ), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/nanoid/index.ts ================================================ export * from './nanoid'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/nanoid/nanoid.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformNanoid( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(1, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('nanoid')), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/negative/index.ts ================================================ export * from './negative'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/negative/negative.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformNegative( valibotIdentifier: string, args: j.CallExpression['arguments'], useBigInt: boolean ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(1, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('ltValue') ), [ useBigInt ? j.bigIntLiteral('0') : j.numericLiteral(0), ...argsExceptOptions, ...(msgArg !== null ? [msgArg] : []), ] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/nonempty/index.ts ================================================ export * from './nonempty'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/nonempty/nonempty.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformNonEmpty( valibotIdentifier: string, args: j.CallExpression['arguments'], isSizeSchemaType: boolean ) { const { lastArg } = splitLastArg(1, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier(isSizeSchemaType ? 'minSize' : 'nonEmpty') ), [ ...(isSizeSchemaType ? [j.numericLiteral(1)] : []), ...(msgArg !== null ? [msgArg] : []), ] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/nonnegative/index.ts ================================================ export * from './nonnegative'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/nonnegative/nonnegative.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformNonNegative( valibotIdentifier: string, args: j.CallExpression['arguments'], useBigInt: boolean ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(1, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('minValue') ), [ useBigInt ? j.bigIntLiteral('0') : j.numericLiteral(0), ...argsExceptOptions, ...(msgArg !== null ? [msgArg] : []), ] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/nonpositive/index.ts ================================================ export * from './nonpositive'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/nonpositive/nonpositive.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformNonPositive( valibotIdentifier: string, args: j.CallExpression['arguments'], useBigInt: boolean ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(1, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('maxValue') ), [ useBigInt ? j.bigIntLiteral('0') : j.numericLiteral(0), ...argsExceptOptions, ...(msgArg !== null ? [msgArg] : []), ] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/positive/index.ts ================================================ export * from './positive'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/positive/positive.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformPositive( valibotIdentifier: string, args: j.CallExpression['arguments'], useBigInt: boolean ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(1, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('gtValue') ), [ useBigInt ? j.bigIntLiteral('0') : j.numericLiteral(0), ...argsExceptOptions, ...(msgArg !== null ? [msgArg] : []), ] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/readonly/index.ts ================================================ export * from './readonly'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/readonly/readonly.ts ================================================ import j from 'jscodeshift'; export function transformReadonly(valibotIdentifier: string) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('readonly') ), [] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/regex/index.ts ================================================ export * from './regex'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/regex/regex.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformRegex( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(2, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('regex')), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/safe/index.ts ================================================ export * from './safe'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/safe/safe.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformSafe( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(1, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('safeInteger') ), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/size/index.ts ================================================ export * from './size'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/size/size.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformSize( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(2, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('size')), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/startsWith/index.ts ================================================ export * from './startsWith'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/startsWith/startsWith.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformStartsWith( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(2, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('startsWith') ), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/time/index.ts ================================================ export * from './time'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/time/time.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformTime( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(1, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('isoTimeSecond') ), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/toLowerCase/index.ts ================================================ export * from './toLowerCase'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/toLowerCase/toLowerCase.ts ================================================ import j from 'jscodeshift'; export function transformToLowerCase( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('toLowerCase') ), args ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/toUpperCase/index.ts ================================================ export * from './toUpperCase'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/toUpperCase/toUpperCase.ts ================================================ import j from 'jscodeshift'; export function transformToUpperCase( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { return j.callExpression( j.memberExpression( j.identifier(valibotIdentifier), j.identifier('toUpperCase') ), args ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/trim/index.ts ================================================ export * from './trim'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/trim/trim.ts ================================================ import j from 'jscodeshift'; export function transformTrim( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('trim')), args ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/ulid/index.ts ================================================ export * from './ulid'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/ulid/ulid.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformULID( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(1, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('ulid')), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/url/index.ts ================================================ export * from './url'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/url/url.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformUrl( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(1, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('url')), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/uuid/index.ts ================================================ export * from './uuid'; ================================================ FILE: codemod/zod-to-valibot/src/transform/schemas-and-links/validators/uuid/uuid.ts ================================================ import j from 'jscodeshift'; import { splitLastArg } from '../../helpers'; import { getValidatorMsg } from '../helpers'; export function transformUUID( valibotIdentifier: string, args: j.CallExpression['arguments'] ) { const { firstArgs: argsExceptOptions, lastArg } = splitLastArg(1, args); const msgArg = getValidatorMsg(lastArg); return j.callExpression( j.memberExpression(j.identifier(valibotIdentifier), j.identifier('uuid')), [...argsExceptOptions, ...(msgArg !== null ? [msgArg] : [])] ); } ================================================ FILE: codemod/zod-to-valibot/src/utils.ts ================================================ import jscodeshift, { type Transform } from 'jscodeshift'; import fs from 'node:fs'; import path from 'node:path'; import { expect, test } from 'vitest'; const ALLOWED_EXTENSIONS = ['.ts', '.tsx']; export type ElementFrom = T[number]; export function defineTests(transform: Transform, selectedTests?: string[]) { const testFixturesPath = path.join(process.cwd(), '__testfixtures__'); const testsFromDir = fs.readdirSync(testFixturesPath); if (typeof selectedTests === 'undefined') { selectedTests = testsFromDir; } else { const testsFromDirSt = new Set(testsFromDir); const selectedTestsInDir: string[] = []; for (const selectedTest of selectedTests) { if (!testsFromDirSt.has(selectedTest)) { console.warn( `Test "${selectedTest}" was not found in the test directory` ); continue; } selectedTestsInDir.push(selectedTest); } selectedTests = selectedTestsInDir; } for (const selectedTest of selectedTests) { const testPath = path.join(testFixturesPath, selectedTest); const testFiles = fs.readdirSync(testPath); if (testFiles.length === 0) { console.error(`No test files found for "${selectedTest}" test`); continue; } let inputFile = ''; let outputFile = ''; for (const testFile of testFiles) { if (testFile.startsWith('input') && inputFile === '') { inputFile = testFile; } if (testFile.startsWith('output') && outputFile === '') { outputFile = testFile; } if (inputFile !== '' && outputFile !== '') { break; } } if (inputFile === '' || outputFile === '') { console.error(`Invalid test file structure for "${selectedTest}" test`); continue; } const inputFileExt = path.extname(inputFile); if (!ALLOWED_EXTENSIONS.includes(inputFileExt)) { console.error(`Invalid input file extension for "${selectedTest}" test`); continue; } const j = jscodeshift.withParser(inputFileExt.slice(1)); const source = fs.readFileSync(path.join(testPath, inputFile), 'utf8'); const expectedOutput = fs.readFileSync( path.join(testPath, outputFile), 'utf8' ); test(selectedTest, async () => { const output = await transform( { path: inputFile, source }, { j, jscodeshift: j, stats: () => {}, report: () => {} }, {} ); fs.writeFile( path.join(testPath, '_actual.ts'), output?.trim() ?? '', () => {} ); expect(output?.trim()).toBe(expectedOutput.trim()); }); } } export function getIsTypeFn( allowedValues: readonly [...T] ): (arg: string) => arg is T[number] { const st = new Set(allowedValues); return (arg: string): arg is T[number] => st.has(arg); } export function assertNever(x: never): never { throw new Error(`this should be unreachable. received: ${x}`); } ================================================ FILE: codemod/zod-to-valibot/tsconfig.json ================================================ { "compilerOptions": { "outDir": "./dist", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "isolatedModules": true, "module": "ESNext", "moduleResolution": "node", "skipLibCheck": true, "strict": true, "target": "ES6", "allowJs": true }, "include": ["./src/**/*.ts"], "exclude": ["node_modules", "./dist/**/*", "./__testfixtures__/**/*"] } ================================================ FILE: codemod/zod-to-valibot/tsdown.config.ts ================================================ import { defineConfig } from 'tsdown'; export default defineConfig([ { entry: ['./src/transform/index.ts'], clean: true, format: ['es'], minify: false, dts: true, outDir: './dist', }, ]); ================================================ FILE: library/CHANGELOG.md ================================================ # Changelog All notable changes to the library will be documented in this file. ## v1.3.1 (March 18, 2026) - Change `MAC48_REGEX`, `MAC64_REGEX` and `MAC_REGEX` to drop the `i` flag for better JSON Schema compatibility (pull request #1430) - Change `hash` action to use case-expanded character classes instead of the `i` flag (pull request #1430) ## v1.3.0 (March 17, 2026) - Add `guard` transformation action to narrow types using type predicates (pull request #1204) - Add `parseBoolean` transformation action to parse boolean values from strings and other types (pull request #1251) - Add `isrc` validation action to validate ISRC codes (pull request #1373) - Add `cache` method for caching schema output by input (pull request #1170) - Add `domain` validation action to validate domain names (pull request #1284) - Add `jwsCompact` validation action to validate JWS compact strings (pull request #1348) - Fix `creditCard` validation action to allow 13-digit Visa card numbers (pull request #1347) - Fix `isoTimestamp` validation action to allow optional space before UTC offset for PostgreSQL `timestamptz` compatibility (pull request #1195) - Fix types for deeply readonly default and fallback values ## v1.2.0 (November 24, 2025) - Add `toBigint`, `toBoolean`, `toDate`, `toNumber` and `toString` transformation actions (pull request #1212) - Add `examples` action to add example values to a schema (pull request #1199) - Add `getExamples` method to extract example values from a schema (pull request #1199) - Add `isbn` validation action to validate ISBN-10 and ISBN-13 strings (pull request #1097) - Add exports for `RawCheckAddIssue`, `RawCheckContext`, `RawCheckIssueInfo`, `RawTransformAddIssue`, `RawTransformContext` and `RawTransformIssueInfo` types for better developer experience with `rawCheck` and `rawTransform` actions (pull request #1359) - Change build step to tsdown - Fix ReDoS vulnerability in `EMOJI_REGEX` used by `emoji` action ## v1.1.0 (May 06, 2025) - Add `message` method to overwrite local error message configuration of a schema (pull request #1103) - Add `summarize` method to summarize issues into a pretty-printable multi-line string (pull request #1158) - Add `getTitle`, `getDescription` and `getMetadata` methods to extract metadata of a schema (pull request #1154) - Add `minEntries` and `maxEntries` validation action to validate number of object entries (pull request #1100) - Add `entries` and `notEntries` validation action to validate number of object entries (pull request #1156) - Add `parseJson` and `stringifyJson` transformation action to parse and stringify JSON (pull request #1137) - Add `flavor` transformation action to flavor the output type of a schema (pull request #950) - Add support for bigints to `multipleOf` validation action (pull request #1164) - Change implementation of `variant` and `variantAsync` schema to improve performance by aborting validation of discriminators early (pull request #1110) - Change name of `NanoIDAction` and `NanoIDIssue` interface to `NanoIdAction` and `NanoIdIssue` (pull request #1171) - Fix internal `MarkOptional` type to fix input and output type of objects in edge cases (issue #1176) ## v1.0.0 (March 18, 2025) - Add `assert` method to assert values (issue #862) - Add `checkItemsAsync` action (pull request #856) - Add `graphemes`, `maxGraphemes`, `minGraphemes` and `notGraphemes` action (pull request #853) - Add `words`, `maxWords`, `minWords` and `notWords` action - Add `args` and `returns` action to transform functions (issue #243) - Add `rfcEmail` action to validate RFC 5322 email addresses (pull request #912) - Add `gtValue` and `ltValue` action for greater than and less than validation (pull request #978, #985) - Add `values` and `notValues` action for easier multi-value validation (pull request #919) - Add `slug` action to validate URL slugs (pull request #910) - Add support for `ReadonlyMap` and `ReadonlySet` to `readonly` action (issue #1059) - Add `entriesFromObjects` util to improve tree shaking (pull request #1023) - Add new overload signature to `pipe` and `pipeAync` method to support unlimited pipe items of same input and output type (issue #852) - Add `@__NO_SIDE_EFFECTS__` notation to improve tree shaking (pull request #995) - Add `exactOptional` and `exactOptionalAsync` schema (PR #1013) - Change types and implementation to support Standard Schema - Change behaviour of `minValue` and `maxValue` for `NaN` (pull request #843) - Change type and behaviour of `nullable`, `nullableAsync`, `nullish`, `nullishAsync`, `optional`, `optionalAsync`, `undefinedable` and `undefinedableAsync` for undefined default value (issue #878) - Change type signature of `partialCheck` and `partialCheckAsync` action to add `.pathList` property in a type-safe way - Change type signature of `findItem` action to support type predicates (issue #867) - Change validation of missing object entries in `looseObject`, `looseObjectAsync`, `object`, `objectAsync`, `objectWithRest`, `objectWithRestAsync`, `strictObject` and `strictObject` (PR #1013) - Change type signature of `optional` and `optionalAsync` when used within an object schema (PR #1013) - Change `MarkOptional` type to fix order of entries and TS error when using generic schemas (issue #1021) - Change `VariantOption` and `VariantOptionAsync` type to fix TS error when using generic schemas (issue #842) - Change implementation of `variant` and `variantAsync` to support optional discriminators using `exactOptional`, `exactOptionalAsync`, `optional`, `optionalAsync`, `nullish` or `nullishAsync` - Change `_addIssue` to not ignore empty strings as error message (pull request #1065) - Change `ISO_DATE_TIME_REGEX` and `ISO_TIMESTAMP_REGEX` to support space as separator (pull request #1064) - Change pipe tuple of `pipe` and `pipeAsync` to be readonly by default - Change `forward`, `forwardCheck`, `partialCheck` and `partialCheckAsync` to improve TypeScript performance (issue #987) - Change `DECIMAL_REGEX` to support floats that start with a dot (pull request #1086) - Change exports to export only public types to reduce noise - Refactor `bytes`, `maxBytes`, `minBytes` and `notBytes` action - Fix implementation of `nonOptional`, `nonOptionalAsync`, `nonNullable`, `nonNullableAsync`, `nonNullish` and `nonNullishAsync` schema in edge cases (issue #909) - Fix instantiation error for `any` in `PathKeys` type (issue #929) - Fix TypeScript error of `keyof` method for objects with many keys (pull request #988) - Fix options filtering in `enum_` schema (pull request #941) - Fix `partialCheck` and `partialCheckAsync` action for typed data with issues ## v0.42.1 (September 20, 2024) - Fix function type declaration of `_run` property ## v0.42.0 (September 15, 2024) - Add `metadata` action to add custom metadata to a schema - Add `title` metadata action to add a title to a schema (discussion #826) - Add `decimal` action to validate integer and float strings (pull request #823) - Rename `decimal` action to `digits` (pull request #823) - Rename `NoPipe` type to `SchemaWithoutPipe` - Fix inference of generics in `IssueDotPath` type (issue #814) ## v0.41.0 (September 01, 2024) - Change `reference` property of all action base types to be less strict (issue #799) - Change implementation of `variant` and `variantAsync` to improve performance and issues generation for nested variants with different discriminators (pull request #809) ## v0.40.0 (August 29, 2024) - Add `nanoid` action to validate Nano IDs (pull request #789) - Add `undefinedable` and `undefinedableAsync` schema (issue #385) - Fix invalid output type for transformed optional object entries (issue #806) ## v0.39.0 (August 24, 2024) - Add support for `exactOptionalPropertyTypes` config (issue #385) - Fix `IssueDotPath` type for `pipe` and `pipeAsync` method (issue #793) - Fix `IssueDotPath` type for `variant` and `variantAsync` schema (issue #700) ## v0.38.0 (August 20, 2024) - Change `expects` and `expected` property by enclosing combined values in parentheses - Change question mark handling for `optional`, `optionalAsync`, `nullish` and `nullishAsync` schemas in objects - Fix TypeScript errors in `TuplePath` and `QuestionMarkSchema` type (issue #659, #776) - Fix missing TypeScript errors in `pipe` and `pipeAsync` method (pull request #785) ## v0.37.0 (July 30, 2024) - Add `base64` action to validate Base64 strings (pull request #644) - Add `description` metadata action (pull request #747) - Add metadata feature to `pipe` and `pipeAsync` method (pull request #747) - Refactor `HEXADECIMAL_REGEX` (pull request #666) - Change `unknown[]` in `LengthInput` type to `ArrayLike` - Change `ArrayInput` and `ContentInput` type to use `MaybeReadonly` - Change `EMOJI_REGEX` to be more accurate and strict (pull request #666) - Fix bug in `fallback` and `fallbackAsync` method for specific schemas (pull request #752) - Fix bug in `fallbackAsync` method for async schemas (pull request #732) ## v0.36.0 (July 05, 2024) - Add `normalize` action to normalize strings (issue #691) - Add support for async schemas to `entriesFromList` util - Add support for numbers and symbols to `entriesFromList` util (issue #492) - Add `key` property to `SetPathItem` type to improve DX (issue #693, #694) - Remove `FunctionReference` type and refactor code ## v0.35.0 (June 25, 2024) - Increase argument limit of `pipe` and `pipeAsync` method (issue #643) ## v0.34.0 (June 24, 2024) - Add `file`, `function` and `promise` schema - Add `awaitAsync` action to await promise in pipeline - Add `operation` property to `filterItems`, `findItem`, `mapItems`, `reduceItems` and `sortItem` action - Rename `action` argument of `filterItems`, `findItem`, `mapItems`, `reduceItems` and `sortItem` action to `operation` - Rename `action` argument and property of `transform` and `transformAsync` action to `operation` - Change and improve implementation of `_stringify` util ## v0.33.3 (June 19, 2024) - Fix `_isPartiallyTyped` util of `partialCheck` and `partialCheckAsync` action ## v0.33.2 (June 19, 2024) - Fix type exports for JSR and Deno (pull request #663) ## v0.33.1 (June 18, 2024) - Fix types of `partialCheck` and `partialCheckAsync` action ## v0.33.0 (June 18, 2024) - Add export alias with reserved keywords for functions with underscore suffix - Add `partialCheck` and `partialCheckAsync` action (issue #76, #145, #260) - Add `checkItems`, `filterItems`, `findItem`, `mapItems`, `reduceItems` and `sortItem` action (issue #595) - Rename `every` and `some` action to `everyItem` and `someItem` - Rename `_isAllowedObjectKey` to `_isValidObjectKey` and add check for inherited properties - Remove `RecordPathItem` and `TuplePathItem` type and refactor code - Fix `received` property of issue in `date` schema for invalid dates (issue #654) ## v0.32.0 (June 14, 2024) - Add `rawCheck`, `rawCheckAsync`, `rawTransform` and `rawTransformAsync` action (issue #597) - Change `FlatErrors` type for better developer experience (discussion #640) - Change `pipe` and `pipeAsync` method to mark output as untyped only when necessary (discussion #613) - Remove unused `skipPipe` option from `Config` type and refactor library - Fix `this` reference in `looseTuple`, `looseTupleAsync`, `strictTuple`, `strictTupleAsync`, `tuple`, `tupleAsync`, `tupleWithRest` and `tupleWithRestAsync` schema (pull request #649) - Fix type of `options` key in `EnumSchema` interface ## v0.31.1 (June 08, 2024) - Fix missing file extension for Deno (pull request #637) ## v0.31.0 (June 06, 2024) > To migrate from an older version, please see the official [migration guide](https://valibot.dev/guides/migrate-to-v0.31.0/) and our [announcement post](https://valibot.dev/blog/valibot-v0.31.0-is-finally-available/). ## v0.30.0 (March 06, 2024) - Add `Default` and `DefaultAsync` type and refactor codebase - Add `Fallback` and `FallbackAsync` type and refactor codebase - Add `isOfType` type guard util to check the type of an object - Refactor `getDefaults` and `getDefaultsAsync` method (pull request #259) - Refactor `getFallbacks` and `getFallbacksAsync` method (pull request #259) - Change type definitions from `type` to `interface` (pull request #259, #451) - Remove deprecated properties of `safeParse` and `safeParseAsync` method - Remove any deprecated method, schema and validation functions - Fix `NestedPath` type of `flatten` for async schemas (issue #456) - Fix implementation of `DefaultValue` type for transformed values ## v0.29.0 (February 19, 2024) - Add `every` and `some` pipeline validation action - Add `input` of schema to `getter` function of `recursive` and `recursiveAsync` schema (pull request #441) - Change implementation of `transform` and `transformAsync` method to only run transformations if there are no issues (issue #436) - Rename `recursive` and `recursiveAsync` schema to `lazy` and `lazyAsync` (issue #440) - Fix bug in `i18n` util when using `setSchemaMessage` ## v0.28.1 (February 06, 2024) - Fix bug in `union` and `unionAsync` schema for transformed inputs (issue #420) ## v0.28.0 (February 05, 2024) > Note: The library has been revised and refactored. Therefore, not every change is listed in detail. - Add i18n feature, global configurations and improve error messages (pull request #397) - Add `number` and `bigint` to `PicklistOptions` type (issue #378) - Fix missing export of `forwardAsync` method (issue #412) ## v0.27.1 (January 28, 2024) - Fix missing file extension for Deno (pull request #387) ## v0.27.0 (January 24, 2024) - Remove `NonNullable`, `NonNullish` and `NonOptional` type - Add `NonNullableInput`, `NonNullableOutput`, `NonNullishInput`, `NonNullishOutput`, `NonOptionalInput` and `NonOptionalOutput` type - Improve type signature of `omit`, `omitAsync`, `pick` and `pickAsync` schema to also allow read-only object keys (issue #380) - Fix type of `pipe` argument at `intersect` and `intersectAsync` schema ## v0.26.0 (January 16, 2024) - Improve performance of `enum_` and `enumAsync` schema by caching values - Change ISO timestamp regex to support timestamps with lower and higher millisecond accuracy (pull request #353) - Change issue handling of `union`, `unionAsync`, `variant` and `variantAsync` schema to improve developer experience - Fix bug in `getDefaults`, `getDefaultsAsync`, `getFallbacks` and `getFallbacksAsync` schema for falsy but not `undefined` values (issue #356) - Fix type of `pipe` argument at `union`, `unionAsync`, `variant` and `variantAsync` schema - Fix bug that broke pipeline execution in `union`, `unionAsync`, `variant` and `variantAsync` schema (issue #364) - Fix typo in type name of `startsWith` validation action (pull request #375) ## v0.25.0 (December 26, 2023) - Add `creditCard`, `decimal`, `hash`, `hexadecimal`, `hexColor` and `octal` pipeline validation action (pull request #292, #304, #307, #308, #309) - Add `pipe` parameter to `intersect`, `intersectAsync`, `union`, `unionAsync`, `variant` and `variantAsync` schema (discussion #297) - Add support for multiple variant options with same discriminator key to `variant` and `variantAsync` schema (issue #310) - Add path to issues if discriminator key of `variant` and `variantAsync` schema is missing (issue #235, #303) - Change `PicklistOptions` type and generics of `picklist` and `picklistAsync` schema ## v0.24.1 (December 11, 2023) - Fix output type of optional `object` and `objectAsync` entries with default value (issue #286) - Fix output type of `nullable`, `nullableAsync`, `nullish`, `nullishAsync`, `optional` and `optionalAsync` schema with default value (issue #286) ## v0.24.0 (December 10, 2023) - Add support for `special` schema as key of `record` schema (issue #291) - Add support for `special` and `specialAsync` schema as key of `recordAsync` schema (issue #291) - Fix input and output type of optional `object` and `objectAsync` entries with default value (issue #286) ## v0.23.0 (December 08, 2023) - Add `bic` validation function (pull request #284) - Add `mac`, `mac48` and `mac64` validation function (pull request #270) - Change `PicklistOptions`, `UnionOptions` and `UnionOptionsAsync` type from tuple to array (issue #279) - Change `IntersectOptions`, `IntersectOptionsAsync`, `UnionOptions` and `UnionOptionsAsync` type to support readonly values (issue #279) - Fix optional keys of `ObjectInput` and `ObjectOutput` type (issue #242) ## v0.22.0 (December 03, 2023) - Add support for boolean to `notValue` validation (pull request #261) - Add `.typed` to schema validation result and execute pipeline of complex schemas if output is typed (issue #76, #145) - Add `forward` method that forwards issues of pipelines to nested fields (issue #76, #145) - Add `skipPipe` option to `is` type guard method (pull request #166) - Change return type of `safeParse` and `safeParseAsync` method - Rename and change util functions and refactor codebase - Fix `RecordInput` and `RecordOuput` type when using `unionAsync` as key - Fix output type for `nullable`, `nullableAsync`, `nullish`, `nullishAsync`, `optional` and `optionalAsync` when using a default value (issue #271) ## v0.21.0 (November 19, 2023) - Change structure of schemas, validations and transformations to make properties accessible (pull request #211) - Fix errors in JSDoc comments and add JSDoc ESLint plugin (pull request #205) - Fix missing file extension for Deno (pull request #249) ## v0.20.1 (November 2, 2023) - Remove `never` from type signatur of strict objects and tuples (issue #234) ## v0.20.0 (October 31, 2023) > Note: The library has been revised and refactored. There is a migration guide in the [release notes](https://github.com/open-circle/valibot/releases/tag/v0.20.0). - Add `getRestAndDefaultArgs` utility function - Add `rest` argument to `object` and `objectAsync` schema - Add `variant` and `variantAsync` schema (issue #90, #216) - Add `getFallback` property to schema in `fallback` method (pull request #177) - Add `PartialObjectEntries` and `PartialObjectEntriesAsync` type (issue #217) - Add export for any validation regex (pull request #219) - Add `getDefaultAsync`, `getDefaults` and `getDefaultsAsync`, `getFallback`, `getFallbackAsync`, `getFallbacks`, `getFallbacksAsync` method (issue #155) - Add support for schema validation to `transform` and `transformAsync` - Fix type check in `date` and `dateAsync` for invalid dates (pull request #214) - Improve security of regular expressions (pull request #202) - Improve `optional`, `optionalAsync`, `nullable`, `nullableAsync`, `nullish` and `nullishAsync` schema - Change `ObjectSchema` and `ObjectSchemaAsync` type - Change type check in `tuple` and `tupleAsync` to be less strict - Change return type of `action` argument in `coerce` and `coerceAsync` to `unknown` - Change type of `brand`, `getDefault`, `transform` and `transformAsync` method - Change type of `array`, `arrayAsync`, `intersection`, `intersectionAsync`, `map`, `mapAsync`, `object`, `objectAsync`, `union`, `unionAsync`, `record`, `recordAsync`, `set`, `setAsync`, `tuple` and `tupleAsync` schema - Rename `schema` property of every schema type to `type` - Rename `intersection` and `intersectionAsync` schema to `intersect` and `intersectAsync` - Rename `enumType` and `enumTypeAsync` schema to `picklist` and `picklistAsync` - Rename `nativeEnum` and `nativeEnumAsync` schema to `enum_` and `enumAsync` - Rename `nullType` and `nullTypeAsync` schema to `null_` and `nullAsync` - Rename `undefinedType` and `undefinedTypeAsync` schema to `undefined_` and `undefinedAsync` - Rename `voidType` and `voidTypeAsync` schema to `void_` and `voidAsync` - Rename `default` property of `optional`, `optionalAsync`, `nullable`, `nullableAsync`, `nullish` and `nullishAsync` schema to `getDefault` - Rename `ObjectShape` and `ObjectShapeAsync` types to `ObjectEntries` and `ObjectEntriesAsync` - Rename `TupleShape` and `TupleShapeAsync` types to `TupleItems` and `TupleItemsAsync` - Deprecate `passthrough`, `strict` and `strip` method in favor of `object` schema with `rest` argument ## v0.19.0 (October 08, 2023) - Add `notBytes`, `notLength`, `notSize` and `notValue` validation function (pull request #194) - Add support for unions as key of `record` and `recordAsync` schema (issue #201) - Add support for pipeline validation to `transform` and `transformAsync` (issue #197) - Change regex of `email` validation to improve performance and security (pull request #180) - Change `object` and `objectAsync` schema to exclude non-existing keys (issue #199) - Fix types at `brand`, `transform` and `unwrap` method (issue #195) - Deprecate `equal` validation function in favor of `value` (issue #192) ## v0.18.0 (September 30, 2023) - Add `intersection` and `intersectionAsync` schema (pull request #117) - Fix `RecordInput` and `RecordOutput` type (pull request #184) - Change `RecordSchema` and `RecordSchemaAsync` type - Change `flatten` function and improve types ## v0.17.1 (September 25, 2023) - Fix missing file extensions for Deno (pull request #178, #181) ## v0.17.0 (September 17, 2023) - Add support for multiple branding of a value (pull request #88) - Add support for dynamic error messages via functions (pull request #136) - Add `skipPipe` option to skip execution of pipelines (pull request #164) ## v0.16.0 (September 16, 2023) - Add `ulid` validation (pull request #151) - Add `getIssues`, `getOutput` and `getPipeIssues` util and refactor code - Fix type check in `number` and `numberAsync` schema (issue #157) - Change `PipeResult` type to allow multiple issues (issue #161) - Rename previous `getIssues` util to `getSchemaIssues` ## v0.15.0 (September 10, 2023) - Add possibility to define path of pipeline issue (issue #5) - Add `getDefault` method to get default value of schema (issue #105) - Add support for enums as key of `record` and `recordAsync` schema (issue #134) - Add support for default values to `optional`, `optionalAsync`, `nullable`, `nullableAsync`, `nullish` and `nullishAsync` schema (issue #96, #118) - Deprecate `withDefault` method in favor of `optional` schema ## v0.14.0 (September 08, 2023) - Add `cuid2` validation (pull request #130) - Add `passthrough`, `passthroughAsync`, `strip` and `stripAsync` method - Add `InstanceSchemaAsync` overload to `transformAsync` method (pull request #138) - Fix bug in `strict` and `strictAsync` method for optional keys (issue #131) ## v0.13.1 (August 23, 2023) - Change object type check in `object` and `record` schema ## v0.13.0 (August 23, 2023) > Note: The library has been revised and refactored. There is a migration guide in the [release notes](https://github.com/open-circle/valibot/releases/tag/v0.13.0). - Add `fallback` and `fallbackAsync` method (pull request #103) - Add `excludes` validation as negation of `includes` - Add support for more primitives to `literal` schema (pull request #102) - Add support for dynamic values to `withDefault` method - Change `flatten` function so that issues are also accepted as argument - Change return type of `safeParse` and `safeParseAsync` method - Change error handling and refactor library to improve performance - Rename `.parse` to `._parse` and `.types` to `._types` to mark it as internal ## v0.12.0 (August 11, 2023) - Change input type of `mimeType` validation to `Blob` - Rename `useDefault` method to `withDefault` (issue #80) - Add `brand` method to support branded types (pull request #85) ## v0.11.1 (August 07, 2023) - Fix types of `enumType` and `enumTypeAsync` schema (issue #70) - Improve performance of loops with for...of (pull request #68) ## v0.11.0 (August 06, 2023) - Fix prototype pollution vulnerability of `record` and `recordAsync` (pull request #67) - Add `finite`, `safeInteger` and `multipleOf` validation (pull request #64, #65, #66) ## v0.10.0 (August 05, 2023) - Add `integer` validation (pull request #62) ## v0.9.0 (August 04, 2023) - Add `imei` validation and `isLuhnAlgo` util (pull request #37) - Fix `isoDateTime`, `isoTime`, `isoTimeSecond` and `isoTimestamp` validation (pull request #42) ## v0.8.0 (July 31, 2023) - Fix infered `object` and `record` types (issue #9, #10, #34) - Add `strict` and `strictAsync` method to detect unknown object keys ## v0.7.0 (July 30, 2023) - Add `is` method which can be used as a type guard (pull request #13) - Throw all validation issues of a pipeline by default (issue #18) - Add `abortPipeEarly` option to abort pipe on first error (issue #18) - Add `abortEarly` option to abort on first error ## v0.6.0 (July 30, 2023) - Add `toMinValue` and `toMaxValue` transformation ## v0.5.0 (July 28, 2023) - Fix invalid `comparable` import when using Deno - Add util functions to exports of library - Rename `minRange` and `maxRange` to `minValue` and `maxValue` (issue #20) - Add `value` validation function ## v0.4.0 (July 27, 2023) - Add `instance` and `instanceAsync` schema - Refactor library to work with Deno ## v0.3.0 (July 27, 2023) - Add `bytes`, `minBytes` and `maxBytes` validation (pull request #1) - Change build step to tsup and exports in package.json (issue #7) ## v0.2.1 (July 26, 2023) - Change order of exports in package.json (issue #7) ## v0.2.0 (July 25, 2023) - Add `blob` and `blobAsync` schema ## v0.1.0 (July 12, 2023) - Initial release ================================================ FILE: library/LICENSE.md ================================================ MIT License Copyright (c) Fabian Hiller Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: library/README.md ================================================ ![Valibot Logo](https://github.com/open-circle/valibot/blob/main/valibot.jpg?raw=true) # Valibot [![License: MIT][license-image]][license-url] [![CI][ci-image]][ci-url] [![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![JSR version][jsr-image]][jsr-url] [![Discord][discord-image]][discord-url] Hello, I am Valibot and I would like to help you validate data easily using a schema. No matter if it is incoming data on a server, a form or even configuration files. I have no dependencies and can run in any JavaScript environment. > I highly recommend you read the [announcement post](https://www.builder.io/blog/introducing-valibot), and if you are a nerd like me, the [bachelor's thesis](https://valibot.dev/thesis.pdf) I am based on. ## Highlights - Fully type safe with static type inference - Small bundle size starting at less than 700 bytes - Validate everything from strings to complex objects - Open source and fully tested with 100 % coverage - Many transformation and validation actions included - Well structured source code without dependencies - Minimal, readable and well thought out API ## Example First you create a schema that describes a structured data set. A schema can be compared to a type definition in TypeScript. The big difference is that TypeScript types are "not executed" and are more or less a DX feature. A schema on the other hand, apart from the inferred type definition, can also be executed at runtime to guarantee the type safety of unknown data. ```ts import * as v from 'valibot'; // 1.31 kB // Create login schema with email and password const LoginSchema = v.object({ email: v.pipe(v.string(), v.email()), password: v.pipe(v.string(), v.minLength(8)), }); // Infer output TypeScript type of login schema as // { email: string; password: string } type LoginData = v.InferOutput; // Throws error for email and password const output1 = v.parse(LoginSchema, { email: '', password: '' }); // Returns data as { email: string; password: string } const output2 = v.parse(LoginSchema, { email: 'jane@example.com', password: '12345678', }); ``` Apart from `parse` I also offer a non-exception-based API with `safeParse` and a type guard function with `is`. You can read more about it [here](https://valibot.dev/guides/parse-data/). ## Comparison Instead of relying on a few large functions with many methods, my API design and source code is based on many small and independent functions, each with just a single task. This modular design has several advantages. For example, this allows a bundler to use the import statements to remove code that is not needed. This way, only the code that is actually used gets into your production build. This can reduce the bundle size by up to 95 % compared to [Zod](https://zod.dev/). In addition, it allows you to easily extend my functionality with external code and makes my source code more robust and secure because the functionality of the individual functions can be tested much more easily through unit tests. ## Partners Thanks to our partners who support my development! [Join them](https://github.com/sponsors/fabian-hiller) and contribute to the sustainability of open source software! ![Partners of Valibot](https://github.com/open-circle/valibot/blob/main/partners.webp?raw=true) ## Credits My friend [Fabian](https://github.com/fabian-hiller) created me as part of his [bachelor thesis](https://valibot.dev/thesis.pdf) at [Stuttgart Media University](https://www.hdm-stuttgart.de/en/), supervised by Walter Kriha, [Miško Hevery](https://github.com/mhevery) and [Ryan Carniato](https://github.com/ryansolid). My role models also include [Colin McDonnell](https://github.com/colinhacks), who had a big influence on my API design with [Zod](https://zod.dev/). ## Feedback Find a bug or have an idea how to improve my code? Please fill out an [issue](https://github.com/open-circle/valibot/issues/new). Together we can make the library even better! ## License I am completely free and licensed under the [MIT license](https://github.com/open-circle/valibot/blob/main/LICENSE.md). But if you like, you can feed me with a star on [GitHub](https://github.com/open-circle/valibot). [license-image]: https://img.shields.io/badge/License-MIT-brightgreen.svg?style=flat-square [license-url]: https://opensource.org/licenses/MIT [ci-image]: https://img.shields.io/github/actions/workflow/status/open-circle/valibot/ci.yml?branch=main&logo=github&style=flat-square [ci-url]: https://github.com/open-circle/valibot/actions/workflows/ci.yml [npm-image]: https://img.shields.io/npm/v/valibot.svg?style=flat-square [npm-url]: https://npmjs.org/package/valibot [downloads-image]: https://img.shields.io/npm/dm/valibot.svg?style=flat-square [jsr-image]: https://jsr.io/badges/@valibot/valibot?style=flat-square [jsr-url]: https://jsr.io/@valibot/valibot [discord-image]: https://img.shields.io/discord/1252985447273992222?label=Discord&style=flat-square [discord-url]: https://discord.gg/tkMjQACf2P ================================================ FILE: library/eslint.config.js ================================================ import eslint from '@eslint/js'; import importPlugin from 'eslint-plugin-import'; import jsdoc from 'eslint-plugin-jsdoc'; import redosDetector from 'eslint-plugin-redos-detector'; import regexpPlugin from 'eslint-plugin-regexp'; import pluginSecurity from 'eslint-plugin-security'; import tseslint from 'typescript-eslint'; export default tseslint.config( { ignores: [ 'eslint.config.js', 'tsdown.config.ts', 'vitest.config.ts', 'mod.ts', 'playground.ts', ], }, eslint.configs.recommended, tseslint.configs.strict, tseslint.configs.stylistic, jsdoc.configs['flat/recommended'], pluginSecurity.configs.recommended, regexpPlugin.configs['flat/recommended'], { files: ['src/**/*.ts'], extends: [importPlugin.flatConfigs.recommended], languageOptions: { parserOptions: { project: './tsconfig.json', tsconfigRootDir: import.meta.dirname, }, }, plugins: { jsdoc, 'redos-detector': redosDetector }, languageOptions: { parserOptions: { projectService: true, tsconfigRootDir: import.meta.dirname, }, }, rules: { // Enable rules ----------------------------------------------------------- // TypeScript '@typescript-eslint/consistent-type-definitions': 'error', // Enforce declaring types using `interface` keyword for better TS performance. '@typescript-eslint/consistent-type-imports': 'warn', // Import 'import/extensions': ['error', 'always'], // Require file extensions // JSDoc 'jsdoc/tag-lines': ['error', 'any', { startLines: 1 }], 'jsdoc/sort-tags': [ 'error', { linesBetween: 1, tagSequence: [ { tags: ['deprecated'] }, { tags: ['param'] }, { tags: ['returns'] }, ], }, ], // NOTE: For overloads functions, we only require a JSDoc at the top // SEE: https://github.com/gajus/eslint-plugin-jsdoc/issues/666 'jsdoc/require-jsdoc': [ 'error', { contexts: [ 'ExportNamedDeclaration[declaration.type="TSDeclareFunction"]:not(ExportNamedDeclaration[declaration.type="TSDeclareFunction"] + ExportNamedDeclaration[declaration.type="TSDeclareFunction"])', 'ExportNamedDeclaration[declaration.type="FunctionDeclaration"]:not(ExportNamedDeclaration[declaration.type="TSDeclareFunction"] + ExportNamedDeclaration[declaration.type="FunctionDeclaration"])', ], require: { FunctionDeclaration: false, }, }, ], 'jsdoc/check-tag-names': [ 'error', { definedTags: ['alpha', 'beta', '__NO_SIDE_EFFECTS__'], }, ], // RegExp 'regexp/no-super-linear-move': 'error', // Prevent DoS regexps 'regexp/no-control-character': 'error', // Avoid unneeded regexps characters 'regexp/no-octal': 'error', // Avoid unneeded regexps characters 'regexp/no-standalone-backslash': 'error', // Avoid unneeded regexps characters 'regexp/prefer-escape-replacement-dollar-char': 'error', // Avoid unneeded regexps characters 'regexp/prefer-quantifier': 'error', // Avoid unneeded regexps characters 'regexp/hexadecimal-escape': ['error', 'always'], // Avoid unneeded regexps characters 'regexp/sort-alternatives': 'error', // Avoid unneeded regexps characters 'regexp/require-unicode-regexp': 'error', // /u flag is faster and enables regexp strict mode 'regexp/prefer-regexp-exec': 'error', // Enforce that RegExp#exec is used instead of String#match if no global flag is provided, as exec is faster // Redos detector 'redos-detector/no-unsafe-regex': ['error', { ignoreError: true }], // Prevent DoS regexps // Disable rules ---------------------------------------------------------- // TypeScript '@typescript-eslint/ban-ts-comment': 'off', '@typescript-eslint/no-non-null-assertion': 'off', '@typescript-eslint/consistent-indexed-object-style': 'off', '@typescript-eslint/no-inferrable-types': 'off', // Imports 'no-duplicate-imports': 'off', // JSDoc 'jsdoc/require-param-type': 'off', 'jsdoc/require-returns-type': 'off', // RegExp 'regexp/use-ignore-case': 'off', // We sometimes don't use the i flag for a better JSON Schema compatibility // Security 'security/detect-object-injection': 'off', // Too many false positives 'security/detect-unsafe-regex': 'off', // Too many false positives, see https://github.com/eslint-community/eslint-plugin-security/issues/28 - we use the redos-detector plugin instead }, } ); ================================================ FILE: library/jsr.json ================================================ { "name": "@valibot/valibot", "version": "1.3.1", "exports": "./src/index.ts", "publish": { "include": ["src/**/*.ts", "README.md"], "exclude": ["src/**/*.test.ts", "src/**/*.test-d.ts", "src/vitest/**/*.ts"] } } ================================================ FILE: library/mod.ts ================================================ export * from './src/index.ts'; ================================================ FILE: library/package.json ================================================ { "name": "valibot", "description": "The modular and type safe schema library for validating structural data", "version": "1.3.1", "license": "MIT", "author": "Fabian Hiller", "homepage": "https://valibot.dev", "repository": { "type": "git", "url": "https://github.com/open-circle/valibot" }, "keywords": [ "modular", "typescript", "schema", "validation", "parsing", "bundle-size", "type-safe", "runtime" ], "type": "module", "main": "./dist/index.mjs", "types": "./dist/index.d.mts", "exports": { ".": { "import": { "types": "./dist/index.d.mts", "default": "./dist/index.mjs" }, "require": { "types": "./dist/index.d.cts", "default": "./dist/index.cjs" } } }, "sideEffects": false, "files": [ "dist" ], "publishConfig": { "access": "public" }, "scripts": { "play": "tsm ./playground.ts", "test": "vitest --typecheck", "coverage": "vitest run --coverage --isolate", "lint": "eslint \"src/**/*.ts*\" && tsc --noEmit && deno check ./src/index.ts", "lint.fix": "eslint \"src/**/*.ts*\" --fix", "format": "prettier --write ./src", "format.check": "prettier --check ./src", "build": "tsdown" }, "devDependencies": { "@eslint/js": "^9.39.1", "@vitest/coverage-v8": "^4.0.13", "eslint": "^9.39.1", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsdoc": "^61.4.0", "eslint-plugin-redos-detector": "^3.1.1", "eslint-plugin-regexp": "^2.10.0", "eslint-plugin-security": "^3.0.1", "jsdom": "^27.2.0", "tsdown": "^0.16.6", "tsm": "^2.3.0", "typescript": "^5.9.3", "typescript-eslint": "^8.47.0", "vite": "^7.2.4", "vitest": "4.0.13" }, "peerDependencies": { "typescript": ">=5" }, "peerDependenciesMeta": { "typescript": { "optional": true } } } ================================================ FILE: library/playground.ts ================================================ // eslint-disable-next-line @typescript-eslint/no-unused-vars import * as v from './dist/index.mjs'; ================================================ FILE: library/src/actions/args/args.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { boolean, number, string, tupleWithRest } from '../../schemas/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { args, type ArgsAction } from './args.ts'; describe('args', () => { type Input = (...args: unknown[]) => number; const schema = tupleWithRest([string(), number()], boolean()); type Schema = typeof schema; type Action = ArgsAction; test('should return action object', () => { expectTypeOf(args(schema)).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< (arg1: string, arg2: number, ...rest: boolean[]) => number >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/args/args.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { boolean, number, string, tupleWithRest } from '../../schemas/index.ts'; import { args, type ArgsAction } from './args.ts'; describe('args', () => { type Input = (...args: unknown[]) => number; const schema = tupleWithRest([string(), number()], boolean()); type Schema = typeof schema; const action = args(schema); test('should return action object', () => { expect(action).toStrictEqual({ kind: 'transformation', type: 'args', reference: args, async: false, schema, '~run': expect.any(Function), } satisfies ArgsAction); }); const func = () => 123; const dataset = action['~run']({ typed: true, value: func }, {}); test('should return new function', () => { expect(dataset).toStrictEqual({ typed: true, value: expect.any(Function), }); expect(dataset.value).not.toBe(func); }); test('should not throw error for valid args', () => { if (dataset.typed) { expect(() => dataset.value('foo', 123)).not.toThrowError(); expect(() => dataset.value('foo', 123, true)).not.toThrowError(); expect(() => dataset.value('foo', 123, true, false)).not.toThrowError(); expect(() => dataset.value('foo', 123, true, false, true) ).not.toThrowError(); } }); test('should throw error for invalid args', () => { if (dataset.typed) { // @ts-expect-error expect(() => dataset.value()).toThrowError(); // @ts-expect-error expect(() => dataset.value('foo')).toThrowError(); // @ts-expect-error expect(() => dataset.value(null, 123)).toThrowError(); // @ts-expect-error expect(() => dataset.value('foo', null)).toThrowError(); // @ts-expect-error expect(() => dataset.value(123, 'foo')).toThrowError(); // @ts-expect-error expect(() => dataset.value('foo', 123, null)).toThrowError(); } }); }); ================================================ FILE: library/src/actions/args/args.ts ================================================ import type { LooseTupleIssue, LooseTupleSchema, StrictTupleIssue, StrictTupleSchema, TupleIssue, TupleSchema, TupleWithRestIssue, TupleWithRestSchema, } from '../../schemas/index.ts'; import type { BaseIssue, BaseSchema, BaseTransformation, ErrorMessage, InferInput, TupleItems, } from '../../types/index.ts'; import { ValiError } from '../../utils/index.ts'; /** * Schema type. */ type Schema = | LooseTupleSchema | undefined> | StrictTupleSchema | undefined> | TupleSchema | undefined> | TupleWithRestSchema< TupleItems, BaseSchema>, ErrorMessage | undefined >; /** * Args action type. */ export interface ArgsAction< // eslint-disable-next-line @typescript-eslint/no-explicit-any TInput extends (...args: any[]) => unknown, TSchema extends Schema, > extends BaseTransformation< TInput, (...args: InferInput) => ReturnType, never > { /** * The action type. */ readonly type: 'args'; /** * The action reference. */ readonly reference: typeof args; /** * The arguments schema. */ readonly schema: TSchema; } /** * Creates a function arguments transformation action. * * @param schema The arguments schema. * * @returns An args action. */ export function args< // eslint-disable-next-line @typescript-eslint/no-explicit-any TInput extends (...args: any[]) => unknown, TSchema extends Schema, >(schema: TSchema): ArgsAction; // @__NO_SIDE_EFFECTS__ export function args( schema: Schema ): ArgsAction<(...args: unknown[]) => unknown, Schema> { return { kind: 'transformation', type: 'args', reference: args, async: false, schema, '~run'(dataset, config) { const func = dataset.value; dataset.value = (...args_) => { const argsDataset = this.schema['~run']({ value: args_ }, config); if (argsDataset.issues) { throw new ValiError(argsDataset.issues); } return func(...argsDataset.value); }; return dataset; }, }; } ================================================ FILE: library/src/actions/args/argsAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { boolean, number, string, tupleWithRestAsync, } from '../../schemas/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { type ArgsActionAsync, argsAsync } from './argsAsync.ts'; describe('argsAsync', () => { type Input = (...args: unknown[]) => Promise; const schema = tupleWithRestAsync([string(), number()], boolean()); type Schema = typeof schema; type Action = ArgsActionAsync; test('should return action object', () => { expectTypeOf(argsAsync(schema)).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< (arg1: string, arg2: number, ...rest: boolean[]) => Promise >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/args/argsAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { boolean, number, string, tupleWithRestAsync, } from '../../schemas/index.ts'; import { type ArgsActionAsync, argsAsync } from './argsAsync.ts'; describe('argsAsync', () => { type Input = (...args: unknown[]) => Promise; const schema = tupleWithRestAsync([string(), number()], boolean()); type Schema = typeof schema; const action = argsAsync(schema); test('should return action object', () => { expect(action).toStrictEqual({ kind: 'transformation', type: 'args', reference: argsAsync, async: false, schema, '~run': expect.any(Function), } satisfies ArgsActionAsync); }); const func = async () => 123; const dataset = action['~run']({ typed: true, value: func }, {}); test('should return new function', () => { expect(dataset).toStrictEqual({ typed: true, value: expect.any(Function), }); expect(dataset.value).not.toBe(func); }); test('should not throw error for valid args', async () => { if (dataset.typed) { await expect(dataset.value('foo', 123)).resolves.not.toThrowError(); await expect(dataset.value('foo', 123, true)).resolves.not.toThrowError(); await expect( dataset.value('foo', 123, true, false) ).resolves.not.toThrowError(); await expect( dataset.value('foo', 123, true, false, true) ).resolves.not.toThrowError(); } }); test('should throw error for invalid args', async () => { if (dataset.typed) { // @ts-expect-error await expect(dataset.value()).rejects.toThrowError(); // @ts-expect-error await expect(dataset.value('foo')).rejects.toThrowError(); // @ts-expect-error await expect(dataset.value(null, 123)).rejects.toThrowError(); // @ts-expect-error await expect(dataset.value('foo', null)).rejects.toThrowError(); // @ts-expect-error await expect(dataset.value(123, 'foo')).rejects.toThrowError(); await expect( // @ts-expect-error dataset.value('foo', 123, null) ).rejects.toThrowError(); } }); }); ================================================ FILE: library/src/actions/args/argsAsync.ts ================================================ import type { LooseTupleIssue, LooseTupleSchema, LooseTupleSchemaAsync, StrictTupleIssue, StrictTupleSchema, StrictTupleSchemaAsync, TupleIssue, TupleSchema, TupleSchemaAsync, TupleWithRestIssue, TupleWithRestSchema, TupleWithRestSchemaAsync, } from '../../schemas/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, BaseTransformation, ErrorMessage, InferInput, SuccessDataset, TupleItems, TupleItemsAsync, } from '../../types/index.ts'; import { ValiError } from '../../utils/index.ts'; /** * Schema type. */ type Schema = | LooseTupleSchema | undefined> | LooseTupleSchemaAsync< TupleItemsAsync, ErrorMessage | undefined > | StrictTupleSchema | undefined> | StrictTupleSchemaAsync< TupleItemsAsync, ErrorMessage | undefined > | TupleSchema | undefined> | TupleSchemaAsync | undefined> | TupleWithRestSchema< TupleItems, BaseSchema>, ErrorMessage | undefined > | TupleWithRestSchemaAsync< TupleItemsAsync, | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined >; /** * Args action async type. */ export interface ArgsActionAsync< // eslint-disable-next-line @typescript-eslint/no-explicit-any TInput extends (...args: any[]) => unknown, TSchema extends Schema, > extends BaseTransformation< TInput, (...args: InferInput) => Promise>>, never > { /** * The action type. */ readonly type: 'args'; /** * The action reference. */ readonly reference: typeof argsAsync; /** * The arguments schema. */ readonly schema: TSchema; } /** * Creates a function arguments transformation action. * * @param schema The arguments schema. * * @returns An args action. */ export function argsAsync< // eslint-disable-next-line @typescript-eslint/no-explicit-any TInput extends (...args: any[]) => unknown, TSchema extends Schema, >(schema: TSchema): ArgsActionAsync; // @__NO_SIDE_EFFECTS__ export function argsAsync( schema: Schema ): ArgsActionAsync<(...args: unknown[]) => unknown, Schema> { return { kind: 'transformation', type: 'args', reference: argsAsync, async: false, schema, '~run'(dataset, config) { const func = dataset.value; dataset.value = async (...args) => { const argsDataset = await schema['~run']({ value: args }, config); if (argsDataset.issues) { throw new ValiError(argsDataset.issues); } return func(...argsDataset.value); }; return dataset as SuccessDataset< (...args: unknown[]) => Promise >; }, }; } ================================================ FILE: library/src/actions/args/index.ts ================================================ export * from './args.ts'; export * from './argsAsync.ts'; ================================================ FILE: library/src/actions/await/awaitAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { type AwaitActionAsync, awaitAsync } from './awaitAsync.ts'; describe('awaitAsync', () => { type Input = Promise; type Action = AwaitActionAsync>; test('should return action object', () => { expectTypeOf(awaitAsync()).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/await/awaitAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { type AwaitActionAsync, awaitAsync } from './awaitAsync.ts'; describe('awaitAsync', () => { type Input = Promise; const action = awaitAsync(); test('should return action object', () => { expect(action).toStrictEqual({ kind: 'transformation', type: 'await', reference: awaitAsync, async: true, '~run': expect.any(Function), } satisfies AwaitActionAsync); }); test('should await promise', async () => { expect( await action['~run']({ typed: true, value: Promise.resolve('foo') }, {}) ).toStrictEqual({ typed: true, value: 'foo', }); }); }); ================================================ FILE: library/src/actions/await/awaitAsync.ts ================================================ import type { BaseTransformationAsync, SuccessDataset, } from '../../types/index.ts'; /** * Await action async interface. */ export interface AwaitActionAsync> extends BaseTransformationAsync, never> { /** * The action type. */ readonly type: 'await'; /** * The action reference. */ readonly reference: typeof awaitAsync; } /** * Creates an await transformation action. * * @returns An await action. */ // @__NO_SIDE_EFFECTS__ export function awaitAsync< TInput extends Promise, >(): AwaitActionAsync { return { kind: 'transformation', type: 'await', reference: awaitAsync, async: true, async '~run'(dataset) { dataset.value = await dataset.value; return dataset as SuccessDataset>; }, }; } ================================================ FILE: library/src/actions/await/index.ts ================================================ export * from './awaitAsync.ts'; ================================================ FILE: library/src/actions/base64/base64.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { base64, type Base64Action, type Base64Issue } from './base64.ts'; describe('base64', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = Base64Action; expectTypeOf(base64()).toEqualTypeOf(); expectTypeOf( base64(undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(base64('message')).toEqualTypeOf< Base64Action >(); }); test('with function message', () => { expectTypeOf(base64 string>(() => 'message')).toEqualTypeOf< Base64Action string> >(); }); }); describe('should infer correct types', () => { type Action = Base64Action; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/base64/base64.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { BASE64_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { base64, type Base64Action, type Base64Issue } from './base64.ts'; describe('base64', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'base64', reference: base64, expects: null, requirement: BASE64_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: Base64Action = { ...baseAction, message: undefined, }; expect(base64()).toStrictEqual(action); expect(base64(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(base64('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies Base64Action); }); test('with function message', () => { const message = () => 'message'; expect(base64(message)).toStrictEqual({ ...baseAction, message, } satisfies Base64Action); }); }); describe('should return dataset without issues', () => { const action = base64(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for empty string', () => { expectNoActionIssue(action, ['']); }); test('for Base64 strings', () => { expectNoActionIssue(action, [ // Test vectors from https://datatracker.ietf.org/doc/html/rfc4648#section-10 '', // '' 'Zg==', // 'f' 'Zm8=', // 'fo' 'Zm9v', // 'foo' 'Zm9vYg==', // 'foob' 'Zm9vYmE=', // 'fooba' 'Zm9vYmFy', // 'foobar' // Other custom tests 'dmFsaWJvdA==', // 'valibot' 'SGVsbG8sIEkgYW0gVmFsaWJvdCBhbmQgSSB3b3VsZCBsaWtlIHRvIGhlbHAgeW91IHZhbGlkYXRlIGRhdGEgZWFzaWx5IHVzaW5nIGEgc2NoZW1hLg==', // 'Hello, I am Valibot and I would like to help you validate data easily using a schema.' '8J+Mrg==', // '🌮' ]); }); }); describe('should return dataset with issues', () => { const action = base64('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'base64', expected: null, message: 'message', requirement: BASE64_REGEX, }; test('for blank strings', () => { expectActionIssue(action, baseIssue, [' ', '\n']); }); test('for invalid chars', () => { expectActionIssue(action, baseIssue, [ 'foo`', // ` 'foo~', // ~ 'foo!', // ! 'foo@', // @ 'foo#', // # 'foo$', // $ 'foo%', // % 'foo^', // ^ 'foo&', // & 'foo*', // * 'foo(', // ( 'foo)', // ) 'foo-', // - 'foo_', // _ 'foo[', // [ 'foo]', // ] 'foo{', // { 'foo}', // } 'foo\\', // \ 'foo|', // | 'foo;', // ; 'foo:', // : "foo'", // ' 'foo"', // " 'foo,', // , 'foo.', // . 'foo<', // < 'foo>', // > 'foo?', // ? ]); }); test('for invalid padding', () => { expectActionIssue(action, baseIssue, [ 'dmFsaWJvdA', // == missing 'dmFsaWJvdA=', // = missing 'dmFsaWJvdA===', // = extra 'Zm9vYmE', // = missing 'Zm9vYmE==', // = extra ]); }); }); }); ================================================ FILE: library/src/actions/base64/base64.ts ================================================ import { BASE64_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Base64 issue interface. */ export interface Base64Issue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'base64'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The Base64 regex. */ readonly requirement: RegExp; } /** * Base64 action interface. */ export interface Base64Action< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'base64'; /** * The action reference. */ readonly reference: typeof base64; /** * The expected property. */ readonly expects: null; /** * The Base64 regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates a [Base64](https://en.wikipedia.org/wiki/Base64) validation action. * * @returns A Base64 action. */ export function base64(): Base64Action< TInput, undefined >; /** * Creates a [Base64](https://en.wikipedia.org/wiki/Base64) validation action. * * @param message The error message. * * @returns A Base64 action. */ export function base64< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): Base64Action; // @__NO_SIDE_EFFECTS__ export function base64( message?: ErrorMessage> ): Base64Action> | undefined> { return { kind: 'validation', type: 'base64', reference: base64, async: false, expects: null, requirement: BASE64_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'Base64', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/base64/index.ts ================================================ export * from './base64.ts'; ================================================ FILE: library/src/actions/bic/bic.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { bic, type BicAction, type BicIssue } from './bic.ts'; describe('bic', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = BicAction; expectTypeOf(bic()).toEqualTypeOf(); expectTypeOf(bic(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(bic('message')).toEqualTypeOf< BicAction >(); }); test('with function message', () => { expectTypeOf(bic string>(() => 'message')).toEqualTypeOf< BicAction string> >(); }); }); describe('should infer correct types', () => { type Action = BicAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/bic/bic.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { BIC_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue } from '../../vitest/expectActionIssue.ts'; import { expectNoActionIssue } from '../../vitest/expectNoActionIssue.ts'; import { bic, type BicAction, type BicIssue } from './bic.ts'; describe('bic', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'bic', reference: bic, expects: null, requirement: BIC_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: BicAction = { ...baseAction, message: undefined, }; expect(bic()).toStrictEqual(action); expect(bic(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(bic('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies BicAction); }); test('with function message', () => { const message = () => 'message'; expect(bic(message)).toStrictEqual({ ...baseAction, message, } satisfies BicAction); }); }); describe('should return dataset without issues', () => { const action = bic(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid BICs', () => { expectNoActionIssue(action, [ 'DEUTDEFF', 'DEUTDEFF400', 'NEDSZAJJXXX', 'MLCOUS33', 'EBATFRPPEB1', ]); }); }); describe('should return dataset with issues', () => { const action = bic('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'bic', expected: null, message: 'message', requirement: BIC_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for lowercase letters', () => { expectActionIssue(action, baseIssue, [ 'deutdeff', 'DEUtDEFF400', 'nEDSZAJJXXX', 'MLcouS33', 'EBATFRPPEb1', ]); }); test('for digit in first 6 chars', () => { expectActionIssue(action, baseIssue, [ 'DE8TDEFF', '3EUTDEFF400', 'NEDSZ8JJXXX', 'M2COUS33', 'EBAT4RPPEB1', ]); }); test('for too short BICs', () => { expectActionIssue(action, baseIssue, ['DEUTDEF', 'MLCOUS']); }); test('for too long BICs', () => { expectActionIssue(action, baseIssue, [ 'DEUTDEFF4000', 'NEDSZAJJXXXX', 'EBATFRPPEB123', ]); }); test('for test BICs', () => { expectActionIssue(action, baseIssue, ['DEUTDE00', 'NEDSZA00XXX']); }); test('for special chars', () => { expectActionIssue(action, baseIssue, [ 'DEU@DEFF', 'DEUTDEFF$00', 'NEDSZAJJXX%', 'MLCOU€33', 'EB#TFRPPEB1', ]); }); }); }); ================================================ FILE: library/src/actions/bic/bic.ts ================================================ import { BIC_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * BIC issue interface. */ export interface BicIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'bic'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The BIC regex. */ readonly requirement: RegExp; } /** * BIC action interface. */ export interface BicAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'bic'; /** * The action reference. */ readonly reference: typeof bic; /** * The expected property. */ readonly expects: null; /** * The BIC regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates a [BIC](https://en.wikipedia.org/wiki/ISO_9362) validation action. * * @returns A BIC action. */ export function bic(): BicAction; /** * Creates a [BIC](https://en.wikipedia.org/wiki/ISO_9362) validation action. * * @param message The error message. * * @returns A BIC action. */ export function bic< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): BicAction; // @__NO_SIDE_EFFECTS__ export function bic( message?: ErrorMessage> ): BicAction> | undefined> { return { kind: 'validation', type: 'bic', reference: bic, async: false, expects: null, requirement: BIC_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'BIC', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/bic/index.ts ================================================ export * from './bic.ts'; ================================================ FILE: library/src/actions/brand/brand.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { type Brand, brand, type BrandAction } from './brand.ts'; describe('brand', () => { type Action = BrandAction; test('should return action object', () => { expectTypeOf(brand('foo')).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< string & Brand<'foo'> >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); describe('should only match specific types', () => { type Output = InferOutput; test('should not match unbranded types', () => { expectTypeOf().not.toMatchTypeOf(); }); test('should match types with same brand', () => { expectTypeOf< InferOutput> >().toMatchTypeOf(); }); test('should not match types with different brand', () => { expectTypeOf< InferOutput> >().not.toMatchTypeOf(); }); }); }); ================================================ FILE: library/src/actions/brand/brand.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { brand, type BrandAction } from './brand.ts'; describe('brand', () => { test('should return action object', () => { expect(brand('foo')).toStrictEqual({ kind: 'transformation', type: 'brand', reference: brand, name: 'foo', async: false, '~run': expect.any(Function), } satisfies BrandAction); }); test('should return same dataset', () => { const dataset = { typed: true, value: 'foo' } as const; expect(brand('foo')['~run'](dataset, {})).toStrictEqual(dataset); }); }); ================================================ FILE: library/src/actions/brand/brand.ts ================================================ import type { BaseTransformation, SuccessDataset } from '../../types/index.ts'; /** * Brand symbol. */ export declare const BrandSymbol: unique symbol; /** * Brand name type. */ export type BrandName = string | number | symbol; /** * Brand interface. */ export interface Brand { [BrandSymbol]: { [TValue in TName]: TValue }; } /** * Brand action interface. */ export interface BrandAction extends BaseTransformation, never> { /** * The action type. */ readonly type: 'brand'; /** * The action reference. */ readonly reference: typeof brand; /** * The brand name. */ readonly name: TName; } /** * Creates a brand transformation action. * * @param name The brand name. * * @returns A brand action. */ // @__NO_SIDE_EFFECTS__ export function brand( name: TName ): BrandAction { return { kind: 'transformation', type: 'brand', reference: brand, async: false, name, '~run'(dataset) { return dataset as SuccessDataset>; }, }; } ================================================ FILE: library/src/actions/brand/index.ts ================================================ export * from './brand.ts'; ================================================ FILE: library/src/actions/bytes/bytes.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { bytes, type BytesAction, type BytesIssue } from './bytes.ts'; describe('bytes', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = BytesAction; expectTypeOf(bytes(10)).toEqualTypeOf(); expectTypeOf( bytes(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(bytes(10, 'message')).toEqualTypeOf< BytesAction >(); }); test('with function message', () => { expectTypeOf( bytes string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = BytesAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< BytesIssue >(); }); }); }); ================================================ FILE: library/src/actions/bytes/bytes.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { bytes, type BytesAction, type BytesIssue } from './bytes.ts'; describe('bytes', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'bytes', reference: bytes, expects: '5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: BytesAction = { ...baseAction, message: undefined, }; expect(bytes(5)).toStrictEqual(action); expect(bytes(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(bytes(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies BytesAction); }); test('with function message', () => { const message = () => 'message'; expect(bytes(5, message)).toStrictEqual({ ...baseAction, message, } satisfies BytesAction); }); }); describe('should return dataset without issues', () => { const action = bytes(5); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid strings', () => { expectNoActionIssue(action, ['12345', 'abcde']); }); test('for valid chars', () => { expectNoActionIssue(action, [ '12あ', // 'あ' is 3 bytes '🤖!', // '🤖' is 4 bytes ]); }); }); describe('should return dataset with issues', () => { const action = bytes(5, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'bytes', expected: '5', message: 'message', requirement: 5, }; const getReceived = (value: string) => `${new TextEncoder().encode(value).length}`; test('for invalid strings', () => { expectActionIssue( action, baseIssue, ['', '1234', '123456', '123456789'], getReceived ); }); test('for invalid chars', () => { expectActionIssue( action, baseIssue, [ 'あ', // 'あ' is 3 bytes '🤖', // '🤖' is 4 bytes 'あい', // 'あい' is 6 bytes ], getReceived ); }); }); }); ================================================ FILE: library/src/actions/bytes/bytes.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _getByteCount } from '../../utils/index.ts'; /** * Bytes issue interface. */ export interface BytesIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'bytes'; /** * The expected property. */ readonly expected: `${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The required bytes. */ readonly requirement: TRequirement; } /** * Bytes action interface. */ export interface BytesAction< TInput extends string, TRequirement extends number, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'bytes'; /** * The action reference. */ readonly reference: typeof bytes; /** * The expected property. */ readonly expects: `${TRequirement}`; /** * The required bytes. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a [bytes](https://en.wikipedia.org/wiki/Byte) validation action. * * @param requirement The required bytes. * * @returns A bytes action. */ export function bytes( requirement: TRequirement ): BytesAction; /** * Creates a [bytes](https://en.wikipedia.org/wiki/Byte) validation action. * * @param requirement The required bytes. * @param message The error message. * * @returns A bytes action. */ export function bytes< TInput extends string, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): BytesAction; // @__NO_SIDE_EFFECTS__ export function bytes( requirement: number, message?: ErrorMessage> ): BytesAction< string, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'bytes', reference: bytes, async: false, expects: `${requirement}`, requirement, message, '~run'(dataset, config) { if (dataset.typed) { const length = _getByteCount(dataset.value); if (length !== this.requirement) { _addIssue(this, 'bytes', dataset, config, { received: `${length}`, }); } } return dataset; }, }; } ================================================ FILE: library/src/actions/bytes/index.ts ================================================ export * from './bytes.ts'; ================================================ FILE: library/src/actions/check/check.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { check, type CheckAction } from './check.ts'; import type { CheckIssue } from './types.ts'; describe('check', () => { describe('should return action object', () => { const requirement = (input: string) => Boolean(input); test('with undefined message', () => { type Action = CheckAction; expectTypeOf(check(requirement)).toEqualTypeOf(); expectTypeOf( check(requirement, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( check(requirement, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( check string>(requirement, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Input = ['foo', 123, true]; type Action = CheckAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/check/check.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { check, type CheckAction } from './check.ts'; import type { CheckIssue } from './types.ts'; describe('check', () => { describe('should return action object', () => { const requirement = (input: string) => input.includes('foo'); const baseAction: Omit, 'message'> = { kind: 'validation', type: 'check', reference: check, expects: null, requirement, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: CheckAction = { ...baseAction, message: undefined, }; expect(check(requirement)).toStrictEqual(action); expect(check(requirement, undefined)).toStrictEqual( action ); }); test('with string message', () => { const message = 'message'; expect(check(requirement, message)).toStrictEqual({ ...baseAction, message, } satisfies CheckAction); }); test('with function message', () => { const message = () => 'message'; expect(check(requirement, message)).toStrictEqual( { ...baseAction, message, } satisfies CheckAction ); }); }); describe('should return dataset without issues', () => { const action = check((input) => input > 0); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid inputs', () => { expectNoActionIssue(action, [1, 12345, Infinity]); }); }); describe('should return dataset with issues', () => { const requirement = (input: number) => input > 0; const action = check(requirement, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'check', expected: null, message: 'message', requirement, }; test('for invalid inputs', () => { expectActionIssue(action, baseIssue, [0, -1, -12345, -Infinity]); }); }); }); ================================================ FILE: library/src/actions/check/check.ts ================================================ import type { BaseValidation, ErrorMessage } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { CheckIssue } from './types.ts'; /** * Check action interface. */ export interface CheckAction< TInput, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'check'; /** * The action reference. */ readonly reference: typeof check; /** * The expected property. */ readonly expects: null; /** * The validation function. */ readonly requirement: (input: TInput) => boolean; /** * The error message. */ readonly message: TMessage; } /** * Creates a check validation action. * * @param requirement The validation function. * * @returns A check action. */ export function check( requirement: (input: TInput) => boolean ): CheckAction; /** * Creates a check validation action. * * @param requirement The validation function. * @param message The error message. * * @returns A check action. */ export function check< TInput, const TMessage extends ErrorMessage> | undefined, >( requirement: (input: TInput) => boolean, message: TMessage ): CheckAction; // @__NO_SIDE_EFFECTS__ export function check( requirement: (input: unknown) => boolean, message?: ErrorMessage> ): CheckAction> | undefined> { return { kind: 'validation', type: 'check', reference: check, async: false, expects: null, requirement, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement(dataset.value)) { _addIssue(this, 'input', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/check/checkAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { type CheckActionAsync, checkAsync } from './checkAsync.ts'; import type { CheckIssue } from './types.ts'; describe('checkAsync', () => { describe('should return action object', () => { const requirement = async (input: string) => Boolean(input); test('with undefined message', () => { type Action = CheckActionAsync; expectTypeOf(checkAsync(requirement)).toEqualTypeOf(); expectTypeOf( checkAsync(requirement, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( checkAsync(requirement, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( checkAsync string>(requirement, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Input = ['foo', 123, true]; type Action = CheckActionAsync; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/check/checkAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssueAsync, expectNoActionIssueAsync, } from '../../vitest/index.ts'; import { type CheckActionAsync, checkAsync } from './checkAsync.ts'; import type { CheckIssue } from './types.ts'; describe('checkAsync', () => { describe('should return action object', () => { const requirement = async (input: string) => input.includes('foo'); const baseAction: Omit, 'message'> = { kind: 'validation', type: 'check', reference: checkAsync, expects: null, requirement, async: true, '~run': expect.any(Function), }; test('with undefined message', () => { const action: CheckActionAsync = { ...baseAction, message: undefined, }; expect(checkAsync(requirement)).toStrictEqual(action); expect( checkAsync(requirement, undefined) ).toStrictEqual(action); }); test('with string message', () => { const message = 'message'; expect(checkAsync(requirement, message)).toStrictEqual( { ...baseAction, message, } satisfies CheckActionAsync ); }); test('with function message', () => { const message = () => 'message'; expect( checkAsync(requirement, message) ).toStrictEqual({ ...baseAction, message, } satisfies CheckActionAsync); }); }); describe('should return dataset without issues', () => { const action = checkAsync(async (input) => input > 0); test('for untyped inputs', async () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( await action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid inputs', async () => { await expectNoActionIssueAsync(action, [1, 12345, Infinity]); }); }); describe('should return dataset with issues', () => { const requirement = async (input: number) => input > 0; const action = checkAsync(requirement, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'check', expected: null, message: 'message', requirement, }; test('for invalid inputs', async () => { await expectActionIssueAsync(action, baseIssue, [ 0, -1, -12345, -Infinity, ]); }); }); }); ================================================ FILE: library/src/actions/check/checkAsync.ts ================================================ import type { BaseValidationAsync, ErrorMessage, MaybePromise, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { CheckIssue } from './types.ts'; /** * Check action async interface. */ export interface CheckActionAsync< TInput, TMessage extends ErrorMessage> | undefined, > extends BaseValidationAsync> { /** * The action type. */ readonly type: 'check'; /** * The action reference. */ readonly reference: typeof checkAsync; /** * The expected property. */ readonly expects: null; /** * The validation function. */ readonly requirement: (input: TInput) => MaybePromise; /** * The error message. */ readonly message: TMessage; } /** * Creates a check validation action. * * @param requirement The validation function. * * @returns A check action. */ export function checkAsync( requirement: (input: TInput) => MaybePromise ): CheckActionAsync; /** * Creates a check validation action. * * @param requirement The validation function. * @param message The error message. * * @returns A check action. */ export function checkAsync< TInput, const TMessage extends ErrorMessage> | undefined, >( requirement: (input: TInput) => MaybePromise, message: TMessage ): CheckActionAsync; // @__NO_SIDE_EFFECTS__ export function checkAsync( requirement: (input: unknown) => MaybePromise, message?: ErrorMessage> ): CheckActionAsync> | undefined> { return { kind: 'validation', type: 'check', reference: checkAsync, async: true, expects: null, requirement, message, async '~run'(dataset, config) { if (dataset.typed && !(await this.requirement(dataset.value))) { _addIssue(this, 'input', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/check/index.ts ================================================ export * from './check.ts'; export * from './checkAsync.ts'; export * from './types.ts'; ================================================ FILE: library/src/actions/check/types.ts ================================================ import type { BaseIssue, MaybePromise } from '../../types/index.ts'; /** * Check issue interface. */ export interface CheckIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'check'; /** * The expected property. */ readonly expected: null; /** * The validation function. */ readonly requirement: (input: TInput) => MaybePromise; } ================================================ FILE: library/src/actions/checkItems/checkItems.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { checkItems, type CheckItemsAction } from './checkItems.ts'; import type { CheckItemsIssue } from './types.ts'; describe('checkItems', () => { describe('should return action object', () => { const requirement = (item: string) => Boolean(item); test('with undefined message', () => { type Action = CheckItemsAction; expectTypeOf(checkItems(requirement)).toEqualTypeOf(); expectTypeOf( checkItems(requirement, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( checkItems(requirement, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( checkItems string>(requirement, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Input = ['foo', 123, true]; type Action = CheckItemsAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< CheckItemsIssue >(); }); }); }); ================================================ FILE: library/src/actions/checkItems/checkItems.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import type { PartialDataset } from '../../types/dataset.ts'; import { expectNoActionIssue } from '../../vitest/index.ts'; import { checkItems, type CheckItemsAction } from './checkItems.ts'; import type { CheckItemsIssue } from './types.ts'; describe('checkItems', () => { describe('should return action object', () => { const requirement = (item: string) => item.startsWith('DE'); const baseAction: Omit, 'message'> = { kind: 'validation', type: 'check_items', reference: checkItems, expects: null, requirement, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: CheckItemsAction = { ...baseAction, message: undefined, }; expect(checkItems(requirement)).toStrictEqual(action); expect( checkItems(requirement, undefined) ).toStrictEqual(action); }); test('with string message', () => { const message = 'message'; expect( checkItems(requirement, message) ).toStrictEqual({ ...baseAction, message, } satisfies CheckItemsAction); }); test('with function message', () => { const message = () => 'message'; expect( checkItems(requirement, message) ).toStrictEqual({ ...baseAction, message, } satisfies CheckItemsAction); }); }); describe('should return dataset without issues', () => { const action = checkItems((item: number) => item > 9); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for empty array', () => { expectNoActionIssue(action, [[]]); }); test('for valid content', () => { expectNoActionIssue(action, [[10, 11, 12, 13, 99]]); }); }); describe('should return dataset with issues', () => { const requirement = (item: number) => item > 9; const action = checkItems(requirement, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'check_items', expected: null, message: 'message', requirement, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for invalid content', () => { const input = [-12, 345, 6, 10]; expect(action['~run']({ typed: true, value: input }, {})).toStrictEqual({ typed: true, value: input, issues: [ { ...baseIssue, input: input[0], received: `${input[0]}`, path: [ { type: 'array', origin: 'value', input, key: 0, value: input[0], }, ], }, { ...baseIssue, input: input[2], received: `${input[2]}`, path: [ { type: 'array', origin: 'value', input, key: 2, value: input[2], }, ], }, ], } satisfies PartialDataset>); }); }); }); ================================================ FILE: library/src/actions/checkItems/checkItems.ts ================================================ import type { BaseValidation, ErrorMessage } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { ArrayInput, ArrayRequirement } from '../types.ts'; import type { CheckItemsIssue } from './types.ts'; /** * Check items action interface. */ export interface CheckItemsAction< TInput extends ArrayInput, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'check_items'; /** * The action reference. */ readonly reference: typeof checkItems; /** * The expected property. */ readonly expects: null; /** * The validation function. */ readonly requirement: ArrayRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates an check items validation action. * * @param requirement The validation function. * * @returns An check items action. */ export function checkItems( requirement: ArrayRequirement ): CheckItemsAction; /** * Creates an check items validation action. * * @param requirement The validation function. * @param message The error message. * * @returns An check items action. */ export function checkItems< TInput extends ArrayInput, const TMessage extends ErrorMessage> | undefined, >( requirement: ArrayRequirement, message: TMessage ): CheckItemsAction; // @__NO_SIDE_EFFECTS__ export function checkItems( requirement: ArrayRequirement, message?: ErrorMessage> ): CheckItemsAction< unknown[], ErrorMessage> | undefined > { return { kind: 'validation', type: 'check_items', reference: checkItems, async: false, expects: null, requirement, message, '~run'(dataset, config) { if (dataset.typed) { for (let index = 0; index < dataset.value.length; index++) { const item = dataset.value[index]; if (!this.requirement(item, index, dataset.value)) { _addIssue(this, 'item', dataset, config, { input: item, path: [ { type: 'array', origin: 'value', input: dataset.value, key: index, value: item, }, ], }); } } } return dataset; }, }; } ================================================ FILE: library/src/actions/checkItems/checkItemsAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { type CheckItemsActionAsync, checkItemsAsync, } from './checkItemsAsync.ts'; import type { CheckItemsIssue } from './types.ts'; describe('checkItemsAsync', () => { describe('should return action object', () => { const requirement = async (item: string) => Boolean(item); test('with undefined message', () => { type Action = CheckItemsActionAsync; expectTypeOf( checkItemsAsync(requirement) ).toEqualTypeOf(); expectTypeOf( checkItemsAsync(requirement, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( checkItemsAsync(requirement, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( checkItemsAsync string>(requirement, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Input = ['foo', 123, true]; type Action = CheckItemsActionAsync; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< CheckItemsIssue >(); }); }); }); ================================================ FILE: library/src/actions/checkItems/checkItemsAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import type { PartialDataset } from '../../types/dataset.ts'; import { expectNoActionIssueAsync } from '../../vitest/index.ts'; import { type CheckItemsActionAsync, checkItemsAsync, } from './checkItemsAsync.ts'; import type { CheckItemsIssue } from './types.ts'; describe('checkItemsAsync', () => { describe('should return action object', () => { const requirement = async (item: string) => item.startsWith('DE'); const baseAction: Omit< CheckItemsActionAsync, 'message' > = { kind: 'validation', type: 'check_items', reference: checkItemsAsync, expects: null, requirement, async: true, '~run': expect.any(Function), }; test('with undefined message', () => { const action: CheckItemsActionAsync = { ...baseAction, message: undefined, }; expect(checkItemsAsync(requirement)).toStrictEqual(action); expect( checkItemsAsync(requirement, undefined) ).toStrictEqual(action); }); test('with string message', () => { const message = 'message'; expect( checkItemsAsync(requirement, message) ).toStrictEqual({ ...baseAction, message, } satisfies CheckItemsActionAsync); }); test('with function message', () => { const message = () => 'message'; expect( checkItemsAsync(requirement, message) ).toStrictEqual({ ...baseAction, message, } satisfies CheckItemsActionAsync); }); }); describe('should return dataset without issues', () => { const action = checkItemsAsync(async (item: number) => item > 9); test('for untyped inputs', async () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( await action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for empty array', async () => { await expectNoActionIssueAsync(action, [[]]); }); test('for valid content', async () => { await expectNoActionIssueAsync(action, [[10, 11, 12, 13, 99]]); }); }); describe('should return dataset with issues', () => { const requirement = async (item: number) => item > 9; const action = checkItemsAsync(requirement, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'check_items', expected: null, message: 'message', requirement, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for invalid content', async () => { const input = [-12, 345, 6, 10]; expect( await action['~run']({ typed: true, value: input }, {}) ).toStrictEqual({ typed: true, value: input, issues: [ { ...baseIssue, input: input[0], received: `${input[0]}`, path: [ { type: 'array', origin: 'value', input, key: 0, value: input[0], }, ], }, { ...baseIssue, input: input[2], received: `${input[2]}`, path: [ { type: 'array', origin: 'value', input, key: 2, value: input[2], }, ], }, ], } satisfies PartialDataset>); }); }); }); ================================================ FILE: library/src/actions/checkItems/checkItemsAsync.ts ================================================ import type { BaseValidationAsync, ErrorMessage } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { ArrayInput, ArrayRequirementAsync } from '../types.ts'; import type { CheckItemsIssue } from './types.ts'; /** * Check items action async interface. */ export interface CheckItemsActionAsync< TInput extends ArrayInput, TMessage extends ErrorMessage> | undefined, > extends BaseValidationAsync> { /** * The action type. */ readonly type: 'check_items'; /** * The action reference. */ readonly reference: typeof checkItemsAsync; /** * The expected property. */ readonly expects: null; /** * The validation function. */ readonly requirement: ArrayRequirementAsync; /** * The error message. */ readonly message: TMessage; } /** * Creates a check items validation action. * * @param requirement The validation function. * * @returns A check items action. */ export function checkItemsAsync( requirement: ArrayRequirementAsync ): CheckItemsActionAsync; /** * Creates a check items validation action. * * @param requirement The validation function. * @param message The error message. * * @returns A check items action. */ export function checkItemsAsync< TInput extends ArrayInput, const TMessage extends ErrorMessage> | undefined, >( requirement: ArrayRequirementAsync, message: TMessage ): CheckItemsActionAsync; // @__NO_SIDE_EFFECTS__ export function checkItemsAsync( requirement: ArrayRequirementAsync, message?: ErrorMessage> ): CheckItemsActionAsync< unknown[], ErrorMessage> | undefined > { return { kind: 'validation', type: 'check_items', reference: checkItemsAsync, async: true, expects: null, requirement, message, async '~run'(dataset, config) { if (dataset.typed) { const requirementResults = await Promise.all( dataset.value.map(this.requirement) ); for (let index = 0; index < dataset.value.length; index++) { if (!requirementResults[index]) { const item = dataset.value[index]; _addIssue(this, 'item', dataset, config, { input: item, path: [ { type: 'array', origin: 'value', input: dataset.value, key: index, value: item, }, ], }); } } } return dataset; }, }; } ================================================ FILE: library/src/actions/checkItems/index.ts ================================================ export * from './checkItems.ts'; export * from './checkItemsAsync.ts'; export * from './types.ts'; ================================================ FILE: library/src/actions/checkItems/types.ts ================================================ import type { BaseIssue } from '../../types/index.ts'; import type { ArrayInput, ArrayRequirementAsync } from '../types.ts'; /** * Check items issue interface. */ export interface CheckItemsIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'check_items'; /** * The expected input. */ readonly expected: null; /** * The validation function. */ readonly requirement: ArrayRequirementAsync; } ================================================ FILE: library/src/actions/creditCard/creditCard.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { creditCard, type CreditCardAction, type CreditCardIssue, } from './creditCard.ts'; describe('creditCard', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = CreditCardAction; expectTypeOf(creditCard()).toEqualTypeOf(); expectTypeOf( creditCard(undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(creditCard('message')).toEqualTypeOf< CreditCardAction >(); }); test('with function message', () => { expectTypeOf( creditCard string>(() => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = CreditCardAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< CreditCardIssue >(); }); }); }); ================================================ FILE: library/src/actions/creditCard/creditCard.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { creditCard, type CreditCardAction, type CreditCardIssue, } from './creditCard.ts'; describe('creditCard', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'credit_card', reference: creditCard, expects: null, requirement: expect.any(Function), async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: CreditCardAction = { ...baseAction, message: undefined, }; expect(creditCard()).toStrictEqual(action); expect(creditCard(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(creditCard('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies CreditCardAction); }); test('with function message', () => { const message = () => 'message'; expect(creditCard(message)).toStrictEqual({ ...baseAction, message, } satisfies CreditCardAction); }); }); describe('should return dataset without issues', () => { const action = creditCard(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for American Express', () => { expectNoActionIssue(action, ['378282246310005', '371449635398431']); }); test('for Diners Club', () => { expectNoActionIssue(action, ['3056930009020004', '36227206271667']); }); test('for Discover', () => { expectNoActionIssue(action, [ '6011111111111117', '6011000990139424', '6011981111111113', ]); }); test('for JCB', () => { expectNoActionIssue(action, ['3530111333300000', '3566002020360505']); }); test('for Mastercard', () => { expectNoActionIssue(action, [ '5555555555554444', '2223003122003222', '5200828282828210', '5105105105105100', ]); }); test('for UnionPay', () => { expectNoActionIssue(action, [ '6200000000000005', '6200000000000047', '6205500000000000004', ]); }); test('for Visa', () => { expectNoActionIssue(action, [ '4242424242424242', '4000056655665556', '4007000000027', ]); }); test('with space dividers', () => { expectNoActionIssue(action, [ '4000 0025 0000 1001', '5555 5525 0000 1001', '4007 000 000 027', ]); }); test('with dashe dividers', () => { expectNoActionIssue(action, [ '4000-0503-6000-0001', '5555-0503-6000-0080', '4007-000-000-027', ]); }); }); describe('should return dataset with issues', () => { const action = creditCard('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'credit_card', expected: null, message: 'message', requirement: expect.any(Function), }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for included letters', () => { expectActionIssue(action, baseIssue, [ 'DE6200000000000005', '6011000A90139424', '37828224631000E', ]); }); test('for mixed divider', () => { expectActionIssue(action, baseIssue, [ '40000025 0000-1001', '5555-55250000 1001', '5555 55555555-4444', ]); }); test('for double divider', () => { expectActionIssue(action, baseIssue, [ '4000 0025 0000 1001', '5555-0503--6000-0080', ]); }); test('for too short numbers', () => { expectActionIssue(action, baseIssue, ['3782822463100', '3622720627166']); }); test('for too long numbers', () => { expectActionIssue(action, baseIssue, ['62055000000000000040']); }); test('for invalid providers', () => { expectActionIssue(action, baseIssue, [ '7530111333300000', '1105105105105100', '9000056655665556', ]); }); test('for invalid checksum', () => { expectActionIssue(action, baseIssue, [ '5200828282828211', '371449635398434', ]); }); }); }); ================================================ FILE: library/src/actions/creditCard/creditCard.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _isLuhnAlgo } from '../../utils/index.ts'; /** * Credit card issue interface. */ export interface CreditCardIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'credit_card'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The validation function. */ readonly requirement: (input: string) => boolean; } /** * Credit card action interface. */ export interface CreditCardAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'credit_card'; /** * The action reference. */ readonly reference: typeof creditCard; /** * The expected property. */ readonly expects: null; /** * The validation function. */ readonly requirement: (input: string) => boolean; /** * The error message. */ readonly message: TMessage; } /** * Credit card regex. */ const CREDIT_CARD_REGEX = /^(?:\d{13,19}|\d{4}(?: \d{3,6}){2,4}|\d{4}(?:-\d{3,6}){2,4})$/u; /** * Sanitize regex. */ const SANITIZE_REGEX = /[- ]/gu; /** * Provider regex list. */ const PROVIDER_REGEX_LIST = [ // American Express /^3[47]\d{13}$/u, // Diners Club /^3(?:0[0-5]|[68]\d)\d{11,13}$/u, // Discover /^6(?:011|5\d{2})\d{12,15}$/u, // JCB /^(?:2131|1800|35\d{3})\d{11}$/u, // Mastercard // eslint-disable-next-line redos-detector/no-unsafe-regex /^5[1-5]\d{2}|(?:222\d|22[3-9]\d|2[3-6]\d{2}|27[01]\d|2720)\d{12}$/u, // UnionPay /^(?:6[27]\d{14,17}|81\d{14,17})$/u, // Visa /^4\d{12}(?:\d{3,6})?$/u, ]; /** * Creates a [credit card](https://en.wikipedia.org/wiki/Payment_card_number) validation action. * * @returns A Credit card action. */ export function creditCard(): CreditCardAction< TInput, undefined >; /** * Creates a [credit card](https://en.wikipedia.org/wiki/Payment_card_number) validation action. * * @param message The error message. * * @returns A credit card action. */ export function creditCard< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): CreditCardAction; // @__NO_SIDE_EFFECTS__ export function creditCard( message?: ErrorMessage> ): CreditCardAction> | undefined> { return { kind: 'validation', type: 'credit_card', reference: creditCard, async: false, expects: null, requirement(input) { let sanitized: string | undefined; return (CREDIT_CARD_REGEX.test(input) && // Remove any hyphens and blanks (sanitized = input.replace(SANITIZE_REGEX, '')) && // Check if it matches a provider PROVIDER_REGEX_LIST.some((regex) => regex.test(sanitized!)) && // Check if passes luhn algorithm _isLuhnAlgo(sanitized)) as boolean; }, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement(dataset.value)) { _addIssue(this, 'credit card', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/creditCard/index.ts ================================================ export * from './creditCard.ts'; ================================================ FILE: library/src/actions/cuid2/cuid2.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { cuid2, type Cuid2Action, type Cuid2Issue } from './cuid2.ts'; describe('cuid2', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = Cuid2Action; expectTypeOf(cuid2()).toEqualTypeOf(); expectTypeOf(cuid2(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(cuid2('message')).toEqualTypeOf< Cuid2Action >(); }); test('with function message', () => { expectTypeOf(cuid2 string>(() => 'message')).toEqualTypeOf< Cuid2Action string> >(); }); }); describe('should infer correct types', () => { type Action = Cuid2Action; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/cuid2/cuid2.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { CUID2_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { cuid2, type Cuid2Action, type Cuid2Issue } from './cuid2.ts'; describe('cuid2', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'cuid2', reference: cuid2, expects: null, requirement: CUID2_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: Cuid2Action = { ...baseAction, message: undefined, }; expect(cuid2()).toStrictEqual(action); expect(cuid2(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(cuid2('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies Cuid2Action); }); test('with function message', () => { const message = () => 'message'; expect(cuid2(message)).toStrictEqual({ ...baseAction, message, } satisfies Cuid2Action); }); }); describe('should return dataset without issues', () => { const action = cuid2(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for single lowercase letters', () => { expectNoActionIssue(action, ['a', 'b', 'y', 'z']); }); test('for two lowercase letters', () => { expectNoActionIssue(action, ['ab', 'cd', 'wx', 'yz']); }); test('for letter plus digit', () => { expectNoActionIssue(action, ['a1', 'b2', 'y8', 'z9']); }); test('for very long Cuid2s', () => { expectNoActionIssue(action, [ 'o2dyrckf0vbqhftbcx8ex7r8', 'pj17j4wheabtydu00x2yuo8s', 'vkydd2qpoediyioixyeh8zyo', 'ja3j1arc87i80ys1zxk8iyiv', 'pbe6zw7wikj83vv5knjk1wx8', ]); }); }); describe('should return dataset with issues', () => { const action = cuid2('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'cuid2', expected: null, message: 'message', requirement: CUID2_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for string with spaces', () => { expectActionIssue(action, baseIssue, [' o2dyr', 'o2dyr ', 'o2d yr']); }); test('for digit as first char', () => { expectActionIssue(action, baseIssue, ['1', '9', '1a', '9z']); }); test('for uppercase letters', () => { expectActionIssue(action, baseIssue, ['A', 'Bc', 'De', 'F1', 'o2Dyr']); }); test('for special chars', () => { expectActionIssue(action, baseIssue, ['@', '#', '$', '%', '&']); expectActionIssue(action, baseIssue, ['a@', 'b#', 'x$', 'z%', 'y&']); }); }); }); ================================================ FILE: library/src/actions/cuid2/cuid2.ts ================================================ import { CUID2_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Cuid2 issue interface. */ export interface Cuid2Issue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'cuid2'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The Cuid2 regex. */ readonly requirement: RegExp; } /** * Cuid2 action interface. */ export interface Cuid2Action< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'cuid2'; /** * The action reference. */ readonly reference: typeof cuid2; /** * The expected property. */ readonly expects: null; /** * The Cuid2 regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates a [Cuid2](https://github.com/paralleldrive/cuid2) validation action. * * @returns A Cuid2 action. */ export function cuid2(): Cuid2Action; /** * Creates a [Cuid2](https://github.com/paralleldrive/cuid2) validation action. * * @param message The error message. * * @returns A Cuid2 action. */ export function cuid2< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): Cuid2Action; // @__NO_SIDE_EFFECTS__ export function cuid2( message?: ErrorMessage> ): Cuid2Action> | undefined> { return { kind: 'validation', type: 'cuid2', reference: cuid2, async: false, expects: null, requirement: CUID2_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'Cuid2', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/cuid2/index.ts ================================================ export * from './cuid2.ts'; ================================================ FILE: library/src/actions/decimal/decimal.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { decimal, type DecimalAction, type DecimalIssue } from './decimal.ts'; describe('decimal', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = DecimalAction; expectTypeOf(decimal()).toEqualTypeOf(); expectTypeOf(decimal(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(decimal('message')).toEqualTypeOf< DecimalAction >(); }); test('with function message', () => { expectTypeOf(decimal(() => 'message')).toEqualTypeOf< DecimalAction string> >(); }); }); describe('should infer correct types', () => { type Action = DecimalAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/decimal/decimal.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { DECIMAL_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { decimal, type DecimalAction, type DecimalIssue } from './decimal.ts'; describe('decimal', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'decimal', reference: decimal, expects: null, requirement: DECIMAL_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: DecimalAction = { ...baseAction, message: undefined, }; expect(decimal()).toStrictEqual(action); expect(decimal(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(decimal('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies DecimalAction); }); test('with function message', () => { const message = () => 'message'; expect(decimal(message)).toStrictEqual({ ...baseAction, message, } satisfies DecimalAction); }); }); describe('should return dataset without issues', () => { const action = decimal(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for a single digit', () => { const values = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; expectNoActionIssue(action, values); }); test('for two digits', () => { expectNoActionIssue(action, ['00', '01', '12', '99']); }); test('for multiple digits', () => { expectNoActionIssue(action, ['1234', '0123456789']); }); test('for float numbers', () => { expectNoActionIssue(action, ['0.1', '123.456']); }); test('for number signs', () => { expectNoActionIssue(action, ['+1', '-1', '+123', '-123', '+001', '-001']); }); test('for floats with a number sign', () => { expectNoActionIssue(action, ['-2.0', '-52.61', '+4.0', '-11.31']); }); test('for floats starting with a dot', () => { expectNoActionIssue(action, ['.6', '.763']); }); test('for floats starting with number sign followed by a dot', () => { expectNoActionIssue(action, ['-.2', '-.922', '+.5', '+.452']); }); test('for numbers with leading 0s', () => { expectNoActionIssue(action, ['000', '000123', '000.123', '00012.3']); }); }); describe('should return dataset with issues', () => { const action = decimal('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'decimal', expected: null, message: 'message', requirement: DECIMAL_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for blank spaces', () => { expectActionIssue(action, baseIssue, [' 1', '1 ', ' 1 ', '1 2']); }); test('for invalid separators', () => { expectActionIssue(action, baseIssue, ['1,000', '1_000', '1 000']); }); test('for scientific notation', () => { expectActionIssue(action, baseIssue, ['1e3', '1e-3', '1e+3']); }); test('for floats ending with a dot', () => { expectActionIssue(action, baseIssue, ['1.', '342.']); }); test('for floats with multiple dots', () => { expectActionIssue(action, baseIssue, [ '1.2.3', '1..23', '12..3', '12.3.4', '1.23.4', '1.2.34', ]); }); test('for word chars', () => { expectActionIssue(action, baseIssue, ['a', 'A', 'abc', 'ABC']); }); test('for special chars', () => { expectActionIssue(action, baseIssue, [ '-', '+', '#', '#1', '$', '$1', '%', '1%', ]); }); }); }); ================================================ FILE: library/src/actions/decimal/decimal.ts ================================================ import { DECIMAL_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Decimal issue interface. */ export interface DecimalIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'decimal'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The decimal regex. */ readonly requirement: RegExp; } /** * Decimal action interface. */ export interface DecimalAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'decimal'; /** * The action reference. */ readonly reference: typeof decimal; /** * The expected property. */ readonly expects: null; /** * The decimal regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates a [decimal](https://en.wikipedia.org/wiki/Decimal) validation action. * * The difference between `decimal` and `digits` is that `decimal` accepts * floating point numbers and negative numbers, while `digits` accepts only the * digits 0-9. * * @returns An decimal action. */ export function decimal(): DecimalAction< TInput, undefined >; /** * Creates a [decimal](https://en.wikipedia.org/wiki/Decimal) validation action. * * The difference between `decimal` and `digits` is that `decimal` accepts * floating point numbers and negative numbers, while `digits` accepts only the * digits 0-9. * * @param message The error message. * * @returns An decimal action. */ export function decimal< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): DecimalAction; // @__NO_SIDE_EFFECTS__ export function decimal( message?: ErrorMessage> ): DecimalAction> | undefined> { return { kind: 'validation', type: 'decimal', reference: decimal, async: false, expects: null, requirement: DECIMAL_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'decimal', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/decimal/index.ts ================================================ export * from './decimal.ts'; ================================================ FILE: library/src/actions/description/description.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { description, type DescriptionAction } from './description.ts'; describe('description', () => { type Action = DescriptionAction; test('should return action object', () => { expectTypeOf(description('text')).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/description/description.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { description, type DescriptionAction } from './description.ts'; describe('description', () => { test('should return action object', () => { expect(description('text')).toStrictEqual({ kind: 'metadata', type: 'description', reference: description, description: 'text', } satisfies DescriptionAction); }); }); ================================================ FILE: library/src/actions/description/description.ts ================================================ import type { BaseMetadata } from '../../types/index.ts'; /** * Description action interface. */ export interface DescriptionAction extends BaseMetadata { /** * The action type. */ readonly type: 'description'; /** * The action reference. */ readonly reference: typeof description; /** * The description text. */ readonly description: TDescription; } /** * Creates a description metadata action. * * @param description_ The description text. * * @returns A description action. */ // @__NO_SIDE_EFFECTS__ export function description( description_: TDescription ): DescriptionAction { return { kind: 'metadata', type: 'description', reference: description, description: description_, }; } ================================================ FILE: library/src/actions/description/index.ts ================================================ export * from './description.ts'; ================================================ FILE: library/src/actions/digits/digits.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { digits, type DigitsAction, type DigitsIssue } from './digits.ts'; describe('digits', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = DigitsAction; expectTypeOf(digits()).toEqualTypeOf(); expectTypeOf(digits(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(digits('message')).toEqualTypeOf< DigitsAction >(); }); test('with function message', () => { expectTypeOf(digits(() => 'message')).toEqualTypeOf< DigitsAction string> >(); }); }); describe('should infer correct types', () => { type Action = DigitsAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/digits/digits.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { DIGITS_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { digits, type DigitsAction, type DigitsIssue } from './digits.ts'; describe('digits', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'digits', reference: digits, expects: null, requirement: DIGITS_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: DigitsAction = { ...baseAction, message: undefined, }; expect(digits()).toStrictEqual(action); expect(digits(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(digits('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies DigitsAction); }); test('with function message', () => { const message = () => 'message'; expect(digits(message)).toStrictEqual({ ...baseAction, message, } satisfies DigitsAction); }); }); describe('should return dataset without issues', () => { const action = digits(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for a single digit', () => { const values = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; expectNoActionIssue(action, values); }); test('for two digits', () => { expectNoActionIssue(action, ['00', '01', '12', '99']); }); test('for multiple digits', () => { expectNoActionIssue(action, ['0123456789']); }); }); describe('should return dataset with issues', () => { const action = digits('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'digits', expected: null, message: 'message', requirement: DIGITS_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for blank spaces', () => { expectActionIssue(action, baseIssue, [' 1', '1 ', ' 1 ', '1 2']); }); test('for number separators', () => { expectActionIssue(action, baseIssue, ['1,000', '1_000', '1 000']); }); test('for number signs', () => { expectActionIssue(action, baseIssue, ['+1', '-1', '+123', '-123']); }); test('for float numbers', () => { expectActionIssue(action, baseIssue, ['0.1', '123.456']); }); test('for exponential numbers', () => { expectActionIssue(action, baseIssue, ['1e3', '1e-3', '1e+3']); }); test('for word chars', () => { expectActionIssue(action, baseIssue, ['a', 'A', 'abc', 'ABC']); }); test('for special chars', () => { expectActionIssue(action, baseIssue, [ '-', '-1', '+', '+1', '#', '#1', '$', '$1', '%', '1%', ]); }); }); }); ================================================ FILE: library/src/actions/digits/digits.ts ================================================ import { DIGITS_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Digits issue interface. */ export interface DigitsIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'digits'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The digits regex. */ readonly requirement: RegExp; } /** * Digits action interface. */ export interface DigitsAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'digits'; /** * The action reference. */ readonly reference: typeof digits; /** * The expected property. */ readonly expects: null; /** * The digits regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates a [digits](https://en.wikipedia.org/wiki/Numerical_digit) validation action. * * The difference between `digits` and `decimal` is that `digits` accepts only * the digits 0-9, while `decimal` accepts floating point numbers and negative * numbers. * * @returns An digits action. */ export function digits(): DigitsAction< TInput, undefined >; /** * Creates a [digits](https://en.wikipedia.org/wiki/Numerical_digit) validation action. * * The difference between `digits` and `decimal` is that `digits` accepts only * the digits 0-9, while `decimal` accepts floating point numbers and negative * numbers. * * @param message The error message. * * @returns An digits action. */ export function digits< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): DigitsAction; // @__NO_SIDE_EFFECTS__ export function digits( message?: ErrorMessage> ): DigitsAction> | undefined> { return { kind: 'validation', type: 'digits', reference: digits, async: false, expects: null, requirement: DIGITS_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'digits', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/digits/index.ts ================================================ export * from './digits.ts'; ================================================ FILE: library/src/actions/domain/domain.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { domain, type DomainAction, type DomainIssue } from './domain.ts'; describe('domain', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = DomainAction; expectTypeOf(domain()).toEqualTypeOf(); expectTypeOf(domain(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(domain('message')).toEqualTypeOf< DomainAction >(); }); test('with function message', () => { expectTypeOf(domain(() => 'message')).toEqualTypeOf< DomainAction string> >(); }); }); describe('should infer correct types', () => { type Action = DomainAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/domain/domain.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { DOMAIN_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { domain, type DomainAction, type DomainIssue } from './domain.ts'; describe('domain', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'domain', reference: domain, expects: null, requirement: DOMAIN_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: DomainAction = { ...baseAction, message: undefined, }; expect(domain()).toStrictEqual(action); expect(domain(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(domain('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies DomainAction); }); test('with function message', () => { const message = () => 'message'; expect(domain(message)).toStrictEqual({ ...baseAction, message, } satisfies DomainAction); }); }); describe('should return dataset without issues', () => { const action = domain(); // General tests test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for common domains', () => { expectNoActionIssue(action, [ 'example.com', 'EXAMPLE.COM', 'sub.example.com', 'sub.sub2.example.co.uk', 'a.example', ]); }); }); describe('should return dataset with issues', () => { const action = domain('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'domain', expected: null, message: 'message', requirement: DOMAIN_REGEX, }; test('too long label (max 63 chars)', () => { const tooLongLabel = 'a'.repeat(64); const domainWithTooLongLabel = tooLongLabel + '.com'; expect(domainWithTooLongLabel.length).toBeGreaterThan(63); expectActionIssue(action, baseIssue, ['a'.repeat(64) + '.com']); }); test('too long TLD (max 63 chars)', () => { const tooLongTLD = 'a'.repeat(64); const domainWithTooLongTLD = `example.${tooLongTLD}`; expect(domainWithTooLongTLD.length).toBeGreaterThan(63); expectActionIssue(action, baseIssue, [domainWithTooLongTLD]); }); test('too long domain (max 253 chars)', () => { const label = 'a'.repeat(63); const tooLongDomain = `${label}.${label}.${label}.${label}.${label}.com`; expect(tooLongDomain.length).toBeGreaterThan(253); expectActionIssue(action, baseIssue, [tooLongDomain]); }); test('for empty or whitespace strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n', '\t']); }); test('for missing TLD or single label', () => { expectActionIssue(action, baseIssue, [ 'localhost', 'intranet', 'example', ]); }); test('for invalid label starts/ends', () => { expectActionIssue(action, baseIssue, [ '-example.com', 'example-.com', '.example.com', 'example..com', 'example.com.', 'example.c', ]); }); test('for invalid characters and formats', () => { expectActionIssue(action, baseIssue, [ 'exa mple.com', 'example!.com', 'exa*mple.com', 'ex_amp.le.com', '*.example.com', 'http://example.com', '127.0.0.1', 'example.123', ]); }); test('for IDN and Punycode domains', () => { expectActionIssue(action, baseIssue, [ 'bücher.example', 'почта.рф', 'xn--bcher-kva.example', 'xn--80a1acny.xn--p1ai', ]); }); }); }); ================================================ FILE: library/src/actions/domain/domain.ts ================================================ import { DOMAIN_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Domain issue interface. * * @beta */ export interface DomainIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'domain'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The domain regex. */ readonly requirement: RegExp; } /** * Domain action interface. * * @beta */ export interface DomainAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'domain'; /** * The action reference. */ readonly reference: typeof domain; /** * The expected property. */ readonly expects: null; /** * The domain regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates a [domain name](https://en.wikipedia.org/wiki/Domain_name) validation * action. * * Hint: ASCII-only validation. Internationalized domain names (IDNs) are not * supported, including Punycode-encoded labels. * * @returns A domain action. * * @beta */ export function domain(): DomainAction< TInput, undefined >; /** * Creates a [domain name](https://en.wikipedia.org/wiki/Domain_name) validation * action. * * Hint: ASCII-only validation. Internationalized domain names (IDNs) are not * supported, including Punycode-encoded labels. * * @param message The error message. * * @returns A domain action. * * @beta */ export function domain< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): DomainAction; // @__NO_SIDE_EFFECTS__ export function domain( message?: ErrorMessage> ): DomainAction> | undefined> { return { kind: 'validation', type: 'domain', reference: domain, expects: null, async: false, requirement: DOMAIN_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'domain', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/domain/index.ts ================================================ export * from './domain.ts'; ================================================ FILE: library/src/actions/email/email.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { email, type EmailAction, type EmailIssue } from './email.ts'; describe('email', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = EmailAction; expectTypeOf(email()).toEqualTypeOf(); expectTypeOf(email(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(email('message')).toEqualTypeOf< EmailAction >(); }); test('with function message', () => { expectTypeOf(email(() => 'message')).toEqualTypeOf< EmailAction string> >(); }); }); describe('should infer correct types', () => { type Action = EmailAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/email/email.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { EMAIL_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { email, type EmailAction, type EmailIssue } from './email.ts'; describe('email', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'email', reference: email, expects: null, requirement: EMAIL_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: EmailAction = { ...baseAction, message: undefined, }; expect(email()).toStrictEqual(action); expect(email(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(email('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies EmailAction); }); test('with function message', () => { const message = () => 'message'; expect(email(message)).toStrictEqual({ ...baseAction, message, } satisfies EmailAction); }); }); describe('should return dataset without issues', () => { const action = email(); // General tests test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for simple email', () => { expectNoActionIssue(action, ['email@example.com']); }); test('for very short email', () => { expectNoActionIssue(action, ['a@b.cd']); }); // Start of local part test('for underscore in beginning of local part', () => { expectNoActionIssue(action, ['_email@example.com']); }); test('for hyphen in beginning of local part', () => { expectNoActionIssue(action, ['-email@example.com']); }); test('for plus in beginning of local part', () => { expectNoActionIssue(action, ['+email@example.com']); }); // End of local part test('for underscore in end of local part', () => { expectNoActionIssue(action, ['email_@example.com']); }); test('for hyphen in end of local part', () => { expectNoActionIssue(action, ['email-@example.com']); }); test('for plus in end of local part', () => { expectNoActionIssue(action, ['email+@example.com']); }); // Middle of local part test('for dot in local part', () => { expectNoActionIssue(action, ['firstname.lastname@example.com']); }); test('for underscore in local part', () => { expectNoActionIssue(action, ['firstname_lastname@example.com']); }); test('for hyphen in local part', () => { expectNoActionIssue(action, ['firstname-lastname@example.com']); }); test('for plus in local part', () => { expectNoActionIssue(action, ['firstname+lastname@example.com']); }); // Special local parts test('for numerical local part', () => { expectNoActionIssue(action, ['1234567890@example.com']); }); test('for underscore local part', () => { expectNoActionIssue(action, ['_______@example.com']); }); // Domain part variations test('for hyphen in domain part', () => { expectNoActionIssue(action, ['email@example-domain.com']); }); test('for domain with subdomain', () => { expectNoActionIssue(action, ['email@subdomain.example.com']); }); test('for subdomain and hyphen in domain', () => { expectNoActionIssue(action, ['email@subdomain.example-domain.com']); }); test('for long top level domain', () => { expectNoActionIssue(action, ['email@example.technology']); }); test('for country code TLD', () => { expectNoActionIssue(action, ['email@example.co.uk']); }); test('for subdomain and country code TLD', () => { expectNoActionIssue(action, ['email@subdomain.example.co.uk']); }); test('for numerical domain', () => { expectNoActionIssue(action, ['email@123.com']); }); }); describe('should return dataset with issues', () => { const action = email('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'email', expected: null, message: 'message', requirement: EMAIL_REGEX, }; // General tests test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for simple strings', () => { expectActionIssue(action, baseIssue, ['email', 'emailexamplecom']); }); test('for email with spaces', () => { expectActionIssue(action, baseIssue, [ ' email@example.com', 'e mail@example.com', 'email @example.com', 'email@ example.com', 'email@exa mple.com', 'email@example. com', 'email@example.com ', ]); }); // Missing parts test('for missing local part', () => { expectActionIssue(action, baseIssue, ['@example.com']); }); test('for missing @ symbol', () => { expectActionIssue(action, baseIssue, [ 'example.com', 'email.example.com', ]); }); test('for missing domain part', () => { expectActionIssue(action, baseIssue, ['email@']); }); test('for missing domain name', () => { expectActionIssue(action, baseIssue, ['email@.com']); }); test('for missing TLD', () => { expectActionIssue(action, baseIssue, ['email@example']); }); // Invalid repeated chars test('for two following dots in local part', () => { expectActionIssue(action, baseIssue, ['email..email@example.com']); }); test('for two following @ symbols', () => { expectActionIssue(action, baseIssue, ['email@@example.com']); }); test('for dot in end of domain name', () => { expectActionIssue(action, baseIssue, ['email@example..com']); }); // Beginning and end of local part test('for dot in beginning of local part', () => { expectActionIssue(action, baseIssue, ['.email@example.com']); }); test('for dot in end of local part', () => { expectActionIssue(action, baseIssue, ['email.@example.com']); }); // Beginning and end of domain part test('for underscore in beginning of domain part', () => { expectActionIssue(action, baseIssue, ['email@_example.com']); }); test('for hypen in beginning of domain part', () => { expectActionIssue(action, baseIssue, ['email@-example.com']); }); test('for plus in beginning of domain part', () => { expectActionIssue(action, baseIssue, ['email@+example.com']); }); test('for dot in beginning of domain part', () => { expectActionIssue(action, baseIssue, ['email@.example.com']); }); test('for underscore in end of domain name', () => { expectActionIssue(action, baseIssue, ['email@example_.com']); }); test('for hypen in end of domain name', () => { expectActionIssue(action, baseIssue, ['email@example-.com']); }); test('for plus in end of domain name', () => { expectActionIssue(action, baseIssue, ['email@example+.com']); }); test('for numerical TLD', () => { expectActionIssue(action, baseIssue, ['email@example.123']); }); test('for single char TLD', () => { expectActionIssue(action, baseIssue, ['email@example.a']); }); // Other special cases test('for repeated domain part', () => { expectActionIssue(action, baseIssue, ['email@example@example.com']); }); test('for special chars', () => { expectActionIssue(action, baseIssue, [ '#$&%@example.com', 'email@#$&%.com', 'email@example.#$&%', ]); }); test('for non ASCII chars', () => { expectActionIssue(action, baseIssue, [ 'あいうえお@example.com', 'email@あいうえお.com', 'email@example.あいう', ]); }); test('for email username', () => { expectActionIssue(action, baseIssue, [ 'Joe Smith ', 'email@example.com (Joe Smith)', ]); }); }); }); ================================================ FILE: library/src/actions/email/email.ts ================================================ import { EMAIL_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Email issue interface. */ export interface EmailIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'email'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The email regex. */ readonly requirement: RegExp; } /** * Email action interface. */ export interface EmailAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'email'; /** * The action reference. */ readonly reference: typeof email; /** * The expected property. */ readonly expects: null; /** * The email regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates an [email](https://en.wikipedia.org/wiki/Email_address) validation * action. * * Hint: This validation action intentionally only validates common email * addresses. If you are interested in an action that covers the entire * specification, please use the `rfcEmail` action instead. * * @returns An email action. */ export function email(): EmailAction; /** * Creates an [email](https://en.wikipedia.org/wiki/Email_address) validation * action. * * Hint: This validation action intentionally only validates common email * addresses. If you are interested in an action that covers the entire * specification, please use the `rfcEmail` action instead. * * @param message The error message. * * @returns An email action. */ export function email< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): EmailAction; // @__NO_SIDE_EFFECTS__ export function email( message?: ErrorMessage> ): EmailAction> | undefined> { return { kind: 'validation', type: 'email', reference: email, expects: null, async: false, requirement: EMAIL_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'email', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/email/index.ts ================================================ export * from './email.ts'; ================================================ FILE: library/src/actions/emoji/emoji.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { emoji, type EmojiAction, type EmojiIssue } from './emoji.ts'; describe('emoji', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = EmojiAction; expectTypeOf(emoji()).toEqualTypeOf(); expectTypeOf(emoji(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(emoji('message')).toEqualTypeOf< EmojiAction >(); }); test('with function message', () => { expectTypeOf(emoji(() => 'message')).toEqualTypeOf< EmojiAction string> >(); }); }); describe('should infer correct types', () => { type Action = EmojiAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/emoji/emoji.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { EMOJI_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { emoji, type EmojiAction, type EmojiIssue } from './emoji.ts'; describe('emoji', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'emoji', reference: emoji, expects: null, requirement: EMOJI_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: EmojiAction = { ...baseAction, message: undefined, }; expect(emoji()).toStrictEqual(action); expect(emoji(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(emoji('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies EmojiAction); }); test('with function message', () => { const message = () => 'message'; expect(emoji(message)).toStrictEqual({ ...baseAction, message, } satisfies EmojiAction); }); }); describe('should return dataset without issues', () => { const action = emoji(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for emoji chars (not exhaustive)', () => { expectNoActionIssue(action, [ '🙂', '🤖', '\uD83D\uDE0D', // 😍 '🔥', '💯', '2️⃣', '🔟', '🇺🇸', '👋🏼', '🫨', '✈️', ]); }); test('for two chars', () => { expectNoActionIssue(action, [ '🙂🤖', '\uD83D\uDE0D🔥', // 😍🔥 '2️⃣🔟', '🇺🇸👋🏼', ]); }); test('for multiple chars', () => { expectNoActionIssue(action, [ '🧩🙌🏁💅🎬', '🤖\uD83D\uDE0D🔥💯', '🤖😍🔥💯', ]); }); }); describe('should return dataset with issues', () => { const action = emoji('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'emoji', expected: null, message: 'message', requirement: EMOJI_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for blank spaces', () => { expectActionIssue(action, baseIssue, [' 🤖', '🤖 ', ' 🤖 ', '🤖 😍']); }); test('for word chars', () => { expectActionIssue(action, baseIssue, [ 'emoji', '😀emoji', 'emoji😀', 'hi', 'hi👋🏼', '👋🏼hi', ]); }); test('for numbers', () => { expectActionIssue(action, baseIssue, [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0123456789', ]); }); test('for special chars', () => { expectActionIssue(action, baseIssue, [ '#', '*', '!', '@', '$', '%', '^', '&', '-', '+', '~', ]); }); test('for escape chars', () => { expectActionIssue(action, baseIssue, [ '\n', '\t', '\r', '\\', '\v', '\f', '\b', ]); }); test('for format and mark chars', () => { expectActionIssue(action, baseIssue, [ '\u200D', '\u20E3', '\uFE0F', '\u{E007F}', ]); }); test('for tag digit and tag small letter chars', () => { expectActionIssue(action, baseIssue, [ '\u{E0030}', '\u{E0039}', '\u{E0061}', '\u{E007A}', ]); }); test('for non-emoji symbol chars', () => { expectActionIssue(action, baseIssue, [ '\u2642', // ♂ '\u2708', // ✈ '\u{1F3F3}', // 🏳 '\u{1F441}', // 👁 ]); }); test('for composite chars', () => { expectActionIssue(action, baseIssue, [ 'S\u0307', // Ṡ 'S\u0307\u0323', // Ṩ '\u1e68', // Ṩ ]); }); test('for surrogate code points', () => { // 😍 '\u{1F60D}' can be represented with surrogate pair '\uD83D\uDE0D' expectActionIssue(action, baseIssue, [ '\uD83D', // Lone high surrogate '\uDE0D', // Lone low surrogate '\uDE0D\uD83D', // Reversed surrogate order for 😍 ]); }); }); }); ================================================ FILE: library/src/actions/emoji/emoji.ts ================================================ import { EMOJI_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Emoji issue interface. */ export interface EmojiIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'emoji'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The emoji regex. */ readonly requirement: RegExp; } /** * Emoji action interface. */ export interface EmojiAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'emoji'; /** * The action reference. */ readonly reference: typeof emoji; /** * The expected property. */ readonly expects: null; /** * The emoji regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates an [emoji](https://en.wikipedia.org/wiki/Emoji) validation action. * * @returns An emoji action. */ export function emoji(): EmojiAction; /** * Creates an [emoji](https://en.wikipedia.org/wiki/Emoji) validation action. * * @param message The error message. * * @returns An emoji action. */ export function emoji< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): EmojiAction; // @__NO_SIDE_EFFECTS__ export function emoji( message?: ErrorMessage> ): EmojiAction> | undefined> { return { kind: 'validation', type: 'emoji', reference: emoji, async: false, expects: null, requirement: EMOJI_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'emoji', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/emoji/index.ts ================================================ export * from './emoji.ts'; ================================================ FILE: library/src/actions/empty/empty.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { empty, type EmptyAction, type EmptyIssue } from './empty.ts'; describe('empty', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = EmptyAction; expectTypeOf(empty()).toEqualTypeOf(); expectTypeOf(empty(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(empty('message')).toEqualTypeOf< EmptyAction >(); }); test('with function message', () => { expectTypeOf(empty string>(() => 'message')).toEqualTypeOf< EmptyAction string> >(); }); }); describe('should infer correct types', () => { type Action = EmptyAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/empty/empty.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { empty, type EmptyAction, type EmptyIssue } from './empty.ts'; describe('empty', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'empty', reference: empty, expects: '0', async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: EmptyAction = { ...baseAction, message: undefined, }; expect(empty()).toStrictEqual(action); expect(empty(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(empty('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies EmptyAction); }); test('with function message', () => { const message = () => 'message'; expect(empty(message)).toStrictEqual({ ...baseAction, message, } satisfies EmptyAction); }); }); describe('should return dataset without issues', () => { const action = empty(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid strings', () => { expectNoActionIssue(action, ['']); }); test('for valid arrays', () => { expectNoActionIssue(action, [[]]); }); }); describe('should return dataset with issues', () => { const action = empty('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'empty', expected: '0', message: 'message', }; test('for invalid strings', () => { expectActionIssue( action, baseIssue, [' ', '\n', 'foo', 'foobarbaz123'], (input) => `${input.length}` ); }); test('for invalid arrays', () => { expectActionIssue( action, baseIssue, [[null], [1, 2, 3, 4, 6], Array(999)], (input) => `${input.length}` ); }); }); }); ================================================ FILE: library/src/actions/empty/empty.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { LengthInput } from '../types.ts'; /** * Empty issue interface. */ export interface EmptyIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'empty'; /** * The expected input. */ readonly expected: '0'; /** * The received input. */ readonly received: `${number}`; } /** * Empty action interface. */ export interface EmptyAction< TInput extends LengthInput, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'empty'; /** * The action reference. */ readonly reference: typeof empty; /** * The expected property. */ readonly expects: '0'; /** * The error message. */ readonly message: TMessage; } /** * Creates an empty validation action. * * @returns An empty action. */ export function empty(): EmptyAction< TInput, undefined >; /** * Creates an empty validation action. * * @param message The error message. * * @returns An empty action. */ export function empty< TInput extends LengthInput, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): EmptyAction; // @__NO_SIDE_EFFECTS__ export function empty( message?: ErrorMessage> ): EmptyAction> | undefined> { return { kind: 'validation', type: 'empty', reference: empty, async: false, expects: '0', message, '~run'(dataset, config) { if (dataset.typed && dataset.value.length > 0) { _addIssue(this, 'length', dataset, config, { received: `${dataset.value.length}`, }); } return dataset; }, }; } ================================================ FILE: library/src/actions/empty/index.ts ================================================ export * from './empty.ts'; ================================================ FILE: library/src/actions/endsWith/endsWith.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { endsWith, type EndsWithAction, type EndsWithIssue, } from './endsWith.ts'; describe('endsWith', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = EndsWithAction; expectTypeOf(endsWith('foo')).toEqualTypeOf(); expectTypeOf( endsWith('foo', undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( endsWith('foo', 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( endsWith string>('foo', () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = EndsWithAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< EndsWithIssue >(); }); }); }); ================================================ FILE: library/src/actions/endsWith/endsWith.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { endsWith, type EndsWithAction, type EndsWithIssue, } from './endsWith.ts'; describe('endsWith', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'ends_with', reference: endsWith, expects: '"abc"', requirement: 'abc', async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: EndsWithAction = { ...baseAction, message: undefined, }; expect(endsWith('abc')).toStrictEqual(action); expect(endsWith('abc', undefined)).toStrictEqual(action); }); test('with string message', () => { expect(endsWith('abc', 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies EndsWithAction); }); test('with function message', () => { const message = () => 'message'; expect(endsWith('abc', message)).toStrictEqual({ ...baseAction, message, } satisfies EndsWithAction); }); }); describe('should return dataset without issues', () => { const action = endsWith('abc'); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid inputs', () => { expectNoActionIssue(action, ['abc', '123abc', 'xyzabc', 'xyz123abc']); }); }); describe('should return dataset with issues', () => { const action = endsWith('abc', 'message'); const baseIssue: Omit< EndsWithIssue, 'input' | 'received' > = { kind: 'validation', type: 'ends_with', expected: '"abc"', message: 'message', requirement: 'abc', }; test('for invalid inputs', () => { expectActionIssue( action, baseIssue, [ '', 'c', 'bc', 'abc ', 'abC', '123a', '123ab', 'xyzab', 'abcc', 'abcz', 'zabcdef', ], (value) => `"${value.slice(-'abc'.length)}"` ); }); }); }); ================================================ FILE: library/src/actions/endsWith/endsWith.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Ends with issue interface. */ export interface EndsWithIssue< TInput extends string, TRequirement extends string, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'ends_with'; /** * The expected property. */ readonly expected: `"${TRequirement}"`; /** * The received property. */ readonly received: `"${string}"`; /** * The end string. */ readonly requirement: TRequirement; } /** * Ends with action interface. */ export interface EndsWithAction< TInput extends string, TRequirement extends string, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'ends_with'; /** * The action reference. */ readonly reference: typeof endsWith; /** * The expected property. */ readonly expects: `"${TRequirement}"`; /** * The end string. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates an ends with validation action. * * @param requirement The end string. * * @returns An ends with action. */ export function endsWith< TInput extends string, const TRequirement extends string, >(requirement: TRequirement): EndsWithAction; /** * Creates an ends with validation action. * * @param requirement The end string. * @param message The error message. * * @returns An ends with action. */ export function endsWith< TInput extends string, const TRequirement extends string, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): EndsWithAction; // @__NO_SIDE_EFFECTS__ export function endsWith( requirement: string, message?: ErrorMessage> ): EndsWithAction< string, string, ErrorMessage> | undefined > { return { kind: 'validation', type: 'ends_with', reference: endsWith, async: false, expects: `"${requirement}"`, requirement, message, '~run'(dataset, config) { if (dataset.typed && !dataset.value.endsWith(this.requirement)) { _addIssue(this, 'end', dataset, config, { received: `"${dataset.value.slice(-this.requirement.length)}"`, }); } return dataset; }, }; } ================================================ FILE: library/src/actions/endsWith/index.ts ================================================ export * from './endsWith.ts'; ================================================ FILE: library/src/actions/entries/entries.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { entries, type EntriesAction, type EntriesIssue } from './entries.ts'; describe('entries', () => { type Input = Record; describe('should return action object', () => { test('with undefined message', () => { type Action = EntriesAction; expectTypeOf(entries(10)).toEqualTypeOf(); expectTypeOf( entries(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(entries(10, 'message')).toEqualTypeOf< EntriesAction >(); }); test('with function message', () => { expectTypeOf( entries string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = EntriesAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< EntriesIssue >(); }); }); }); ================================================ FILE: library/src/actions/entries/entries.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { RecordIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { entries, type EntriesAction, type EntriesIssue } from './entries.ts'; describe('entries', () => { type Input = Record; describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'entries', reference: entries, expects: '3', requirement: 3, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: EntriesAction = { ...baseAction, message: undefined, }; expect(entries(3)).toStrictEqual(action); expect(entries(3, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(entries(3, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies EntriesAction); }); test('with function message', () => { const message = () => 'message'; expect(entries(3, message)).toStrictEqual({ ...baseAction, message, } satisfies EntriesAction); }); }); describe('should return dataset without issues', () => { const action = entries(3); test('for untyped inputs', () => { const issues: [RecordIssue] = [ { kind: 'schema', type: 'record', input: null, expected: 'Object', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid objects', () => { expectNoActionIssue(action, [{ foo: 1, bar: 2, baz: 3 }]); }); }); describe('should return dataset with issues', () => { const action = entries(3, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'entries', expected: '3', message: 'message', requirement: 3, }; test('for invalid objects', () => { expectActionIssue( action, baseIssue, [ {}, { foo: 1 }, { foo: 1, bar: 2 }, { foo: 1, bar: 2, baz: 3, qux: 4 }, { foo: 1, bar: 2, baz: 3, qux: 4, quux: 5 }, ], (value) => `${Object.keys(value).length}` ); }); }); }); ================================================ FILE: library/src/actions/entries/entries.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { EntriesInput } from '../types.ts'; /** * Entries issue interface. * * @beta */ export interface EntriesIssue< TInput extends EntriesInput, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'entries'; /** * The expected property. */ readonly expected: `${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The required entries. */ readonly requirement: TRequirement; } /** * Entries action interface. * * @beta */ export interface EntriesAction< TInput extends EntriesInput, TRequirement extends number, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'entries'; /** * The action reference. */ readonly reference: typeof entries; /** * The expected property. */ readonly expects: `${TRequirement}`; /** * The required entries. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates an entries validation action. * * @param requirement The required entries. * * @returns An entries action. * * @beta */ export function entries< TInput extends EntriesInput, const TRequirement extends number, >(requirement: TRequirement): EntriesAction; /** * Creates an entries validation action. * * @param requirement The required entries. * @param message The error message. * * @returns An entries action. * * @beta */ export function entries< TInput extends EntriesInput, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): EntriesAction; // @__NO_SIDE_EFFECTS__ export function entries( requirement: number, message?: ErrorMessage> ): EntriesAction< EntriesInput, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'entries', reference: entries, async: false, expects: `${requirement}`, requirement, message, '~run'(dataset, config) { if (!dataset.typed) return dataset; const count = Object.keys(dataset.value).length; if (dataset.typed && count !== this.requirement) { _addIssue(this, 'entries', dataset, config, { received: `${count}`, }); } return dataset; }, }; } ================================================ FILE: library/src/actions/entries/index.ts ================================================ export * from './entries.ts'; ================================================ FILE: library/src/actions/everyItem/everyItem.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { everyItem, type EveryItemAction, type EveryItemIssue, } from './everyItem.ts'; describe('everyItem', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = EveryItemAction; expectTypeOf( everyItem((item: string) => Boolean(item)) ).toEqualTypeOf(); expectTypeOf( everyItem( (item: string) => Boolean(item), undefined ) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( everyItem( (item: string) => Boolean(item), 'message' ) ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( everyItem string>( (item: string) => Boolean(item), () => 'message' ) ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Input = ['foo', 123, true]; type Action = EveryItemAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/everyItem/everyItem.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { ArrayIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { everyItem, type EveryItemAction, type EveryItemIssue, } from './everyItem.ts'; describe('everyItem', () => { describe('should return action object', () => { const requirement = (item: string) => item.startsWith('DE'); const baseAction: Omit, 'message'> = { kind: 'validation', type: 'every_item', reference: everyItem, expects: null, requirement, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: EveryItemAction = { ...baseAction, message: undefined, }; expect(everyItem(requirement)).toStrictEqual(action); expect( everyItem(requirement, undefined) ).toStrictEqual(action); }); test('with string message', () => { const message = 'message'; expect( everyItem(requirement, message) ).toStrictEqual({ ...baseAction, message, } satisfies EveryItemAction); }); test('with function message', () => { const message = () => 'message'; expect( everyItem(requirement, message) ).toStrictEqual({ ...baseAction, message, } satisfies EveryItemAction); }); }); describe('should return dataset without issues', () => { const action = everyItem((item: number) => item > 9); test('for untyped inputs', () => { const issues: [ArrayIssue] = [ { kind: 'schema', type: 'array', input: null, expected: 'Array', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for empty array', () => { expectNoActionIssue(action, [[]]); }); test('for valid content', () => { expectNoActionIssue(action, [[10, 11, 12, 13, 99]]); }); }); describe('should return dataset with issues', () => { const requirement = (item: number) => item > 9; const action = everyItem(requirement, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'every_item', expected: null, message: 'message', requirement, }; test('for invalid content', () => { expectActionIssue(action, baseIssue, [ [9], [1, 2, 3], [10, 11, -12, 13, 99], ]); }); }); }); ================================================ FILE: library/src/actions/everyItem/everyItem.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { ArrayInput, ArrayRequirement } from '../types.ts'; /** * Every item issue interface. */ export interface EveryItemIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'every_item'; /** * The expected property. */ readonly expected: null; /** * The validation function. */ readonly requirement: ArrayRequirement; } /** * Every item action interface. */ export interface EveryItemAction< TInput extends ArrayInput, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'every_item'; /** * The action reference. */ readonly reference: typeof everyItem; /** * The expected property. */ readonly expects: null; /** * The validation function. */ readonly requirement: ArrayRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates an every item validation action. * * @param requirement The validation function. * * @returns An every item action. */ export function everyItem( requirement: ArrayRequirement ): EveryItemAction; /** * Creates an every item validation action. * * @param requirement The validation function. * @param message The error message. * * @returns An every item action. */ export function everyItem< TInput extends ArrayInput, const TMessage extends ErrorMessage> | undefined, >( requirement: ArrayRequirement, message: TMessage ): EveryItemAction; // @__NO_SIDE_EFFECTS__ export function everyItem( requirement: ArrayRequirement, message?: ErrorMessage> ): EveryItemAction< unknown[], ErrorMessage> | undefined > { return { kind: 'validation', type: 'every_item', reference: everyItem, async: false, expects: null, requirement, message, '~run'(dataset, config) { if (dataset.typed && !dataset.value.every(this.requirement)) { _addIssue(this, 'item', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/everyItem/index.ts ================================================ export * from './everyItem.ts'; ================================================ FILE: library/src/actions/examples/examples.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { pipe } from '../../methods/index.ts'; import { string } from '../../schemas/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { examples, type ExamplesAction } from './examples.ts'; describe('examples', () => { test('should return action object', () => { type Action = ExamplesAction; expectTypeOf( examples(['foo', 'bar']) ).toEqualTypeOf(); }); test("should error if example doesn't match input", () => { pipe( string(), examples([ 'foo', // @ts-expect-error 123, ]) ); }); describe('should infer correct types', () => { type Input = 'foo' | 'bar'; type Action = ExamplesAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/examples/examples.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { examples, type ExamplesAction } from './examples.ts'; describe('examples', () => { test('should return action object', () => { expect(examples(['foo', 'bar'])).toStrictEqual({ kind: 'metadata', type: 'examples', reference: examples, examples: ['foo', 'bar'], } satisfies ExamplesAction); }); }); ================================================ FILE: library/src/actions/examples/examples.ts ================================================ import type { BaseMetadata } from '../../types/index.ts'; /** * Examples action interface. */ export interface ExamplesAction extends BaseMetadata { /** * The action type. */ readonly type: 'examples'; /** * The action reference. */ readonly reference: typeof examples; /** * The examples. */ readonly examples: TExamples; } /** * Creates an examples metadata action. * * @param examples_ The examples. * * @returns An examples action. * * @beta */ // @__NO_SIDE_EFFECTS__ export function examples( examples_: TExamples ): ExamplesAction { return { kind: 'metadata', type: 'examples', reference: examples, examples: examples_, }; } ================================================ FILE: library/src/actions/examples/index.ts ================================================ export * from './examples.ts'; ================================================ FILE: library/src/actions/excludes/excludes.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { excludes, type ExcludesAction, type ExcludesIssue, } from './excludes.ts'; describe('excludes', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = ExcludesAction; expectTypeOf(excludes('foo')).toEqualTypeOf(); expectTypeOf( excludes('foo', undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( excludes('foo', 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( excludes string>('foo', () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Input = ['foo', 123, true]; type Action = ExcludesAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< ExcludesIssue >(); }); }); }); ================================================ FILE: library/src/actions/excludes/excludes.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { excludes, type ExcludesAction, type ExcludesIssue, } from './excludes.ts'; describe('excludes', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'excludes', reference: excludes, expects: `!"foo"`, requirement: 'foo', async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: ExcludesAction = { ...baseAction, message: undefined, }; expect(excludes('foo')).toStrictEqual(action); expect(excludes('foo', undefined)).toStrictEqual(action); }); test('with string message', () => { const message = 'message'; expect(excludes('foo', message)).toStrictEqual({ ...baseAction, message, } satisfies ExcludesAction); }); test('with function message', () => { const message = () => 'message'; expect(excludes('foo', message)).toStrictEqual({ ...baseAction, message, } satisfies ExcludesAction); }); }); describe('should return dataset without issues', () => { const action = excludes('foo'); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid strings', () => { expectNoActionIssue(action, ['', 'fo', 'fobar', '123fo']); }); test('for valid arrays', () => { expectNoActionIssue(action, [ [], ['fo'], [123, 'fobar'], [null, 123, true], ]); }); }); describe('should return dataset with issues', () => { const action = excludes('foo', 'message'); const baseIssue: Omit< ExcludesIssue, 'input' | 'received' > = { kind: 'validation', type: 'excludes', expected: `!"foo"`, message: 'message', requirement: 'foo', }; test('for invalid strings', () => { expectActionIssue( action, baseIssue, ['foo', 'foobar', '123foo'], () => '"foo"' ); }); test('for invalid arrays', () => { expectActionIssue( action, baseIssue, [['foo'], [123, 'foo'], [null, 123, 'foo', true, 'foo']], () => '"foo"' ); }); }); }); ================================================ FILE: library/src/actions/excludes/excludes.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _stringify } from '../../utils/index.ts'; import type { ContentInput, ContentRequirement } from '../types.ts'; /** * Excludes issue interface. */ export interface ExcludesIssue< TInput extends ContentInput, TRequirement extends ContentRequirement, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'excludes'; /** * The expected property. */ readonly expected: string; /** * The content to be excluded. */ readonly requirement: TRequirement; } /** * Excludes action interface. */ export interface ExcludesAction< TInput extends ContentInput, TRequirement extends ContentRequirement, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'excludes'; /** * The action reference. */ readonly reference: typeof excludes; /** * The expected property. */ readonly expects: string; /** * The content to be excluded. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates an excludes validation action. * * @param requirement The content to be excluded. * * @returns An excludes action. */ export function excludes< TInput extends ContentInput, const TRequirement extends ContentRequirement, >(requirement: TRequirement): ExcludesAction; /** * Creates an excludes validation action. * * @param requirement The content to be excluded. * @param message The error message. * * @returns An excludes action. */ export function excludes< TInput extends ContentInput, const TRequirement extends ContentRequirement, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): ExcludesAction; // @__NO_SIDE_EFFECTS__ export function excludes( requirement: ContentRequirement, message?: ErrorMessage< ExcludesIssue> > ): ExcludesAction< ContentInput, ContentRequirement, | ErrorMessage>> | undefined > { const received = _stringify(requirement); return { kind: 'validation', type: 'excludes', reference: excludes, async: false, expects: `!${received}`, requirement, message, '~run'(dataset, config) { // @ts-expect-error if (dataset.typed && dataset.value.includes(this.requirement)) { _addIssue(this, 'content', dataset, config, { received }); } return dataset; }, }; } ================================================ FILE: library/src/actions/excludes/index.ts ================================================ export * from './excludes.ts'; ================================================ FILE: library/src/actions/filterItems/filterItems.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { filterItems, type FilterItemsAction } from './filterItems.ts'; describe('filterItems', () => { test('should return action object', () => { expectTypeOf(filterItems((item) => item > 9)).toEqualTypeOf< FilterItemsAction >(); }); describe('should infer correct types', () => { type Input = (string | number)[]; type Action = FilterItemsAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/filterItems/filterItems.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { filterItems, type FilterItemsAction } from './filterItems.ts'; describe('filterItems', () => { const operation = (item: number) => item > 9; const action = filterItems(operation); test('should return action object', () => { expect(action).toStrictEqual({ kind: 'transformation', type: 'filter_items', reference: filterItems, async: false, operation, '~run': expect.any(Function), } satisfies FilterItemsAction); }); test('should transform input', () => { expect( action['~run']({ typed: true, value: [-12, 345, 0, 9, 10, 999] }, {}) ).toStrictEqual({ typed: true, value: [345, 10, 999], }); }); }); ================================================ FILE: library/src/actions/filterItems/filterItems.ts ================================================ import type { BaseTransformation } from '../../types/index.ts'; import type { ArrayInput, ArrayRequirement } from '../types.ts'; /** * Filter items action interface. */ export interface FilterItemsAction extends BaseTransformation { /** * The action type. */ readonly type: 'filter_items'; /** * The action reference. */ readonly reference: typeof filterItems; /** * The filter items operation. */ readonly operation: ArrayRequirement; } /** * Creates a filter items transformation action. * * @param operation The filter items operation. * * @returns A filter items action. */ export function filterItems( operation: ArrayRequirement ): FilterItemsAction; // @__NO_SIDE_EFFECTS__ export function filterItems( operation: ArrayRequirement ): FilterItemsAction { return { kind: 'transformation', type: 'filter_items', reference: filterItems, async: false, operation, '~run'(dataset) { dataset.value = dataset.value.filter(this.operation); return dataset; }, }; } ================================================ FILE: library/src/actions/filterItems/index.ts ================================================ export * from './filterItems.ts'; ================================================ FILE: library/src/actions/findItem/findItem.test-d.ts ================================================ /* eslint-disable @typescript-eslint/consistent-type-definitions */ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { findItem, type FindItemAction } from './findItem.ts'; describe('findItem', () => { type Dog = { type: 'dog' }; type Cat = { type: 'cat' }; type Animal = Dog | Cat; type Input = Animal[]; type Action1 = FindItemAction; type Action2 = FindItemAction; test('should return action object', () => { expectTypeOf( findItem((item): boolean => item.type === 'dog') ).toEqualTypeOf(); expectTypeOf( findItem((item): item is Dog => item.type === 'dog') ).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/findItem/findItem.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { findItem, type FindItemAction } from './findItem.ts'; describe('findItem', () => { const operation = (item: number) => item > 9; const action = findItem(operation); test('should return action object', () => { expect(action).toStrictEqual({ kind: 'transformation', type: 'find_item', reference: findItem, async: false, operation, '~run': expect.any(Function), } satisfies FindItemAction); }); describe('should transform input', () => { test('to searched item', () => { expect( action['~run']({ typed: true, value: [-12, 9, 345, 10, 0, 999] }, {}) ).toStrictEqual({ typed: true, value: 345, }); }); test('to undefined', () => { expect( action['~run']({ typed: true, value: [-12, 9, 0] }, {}) ).toStrictEqual({ typed: true, value: undefined, }); }); }); }); ================================================ FILE: library/src/actions/findItem/findItem.ts ================================================ import type { BaseTransformation, SuccessDataset } from '../../types/index.ts'; import type { ArrayInput } from '../types.ts'; /** * Array requirement type. */ type ArrayRequirement< TInput extends ArrayInput, TOuput extends TInput[number], > = | ((item: TInput[number], index: number, array: TInput) => item is TOuput) | ((item: TInput[number], index: number, array: TInput) => boolean); /** * Find item action interface. */ export interface FindItemAction< TInput extends ArrayInput, TOuput extends TInput[number], > extends BaseTransformation { /** * The action type. */ readonly type: 'find_item'; /** * The action reference. */ readonly reference: typeof findItem; /** * The find item operation. */ readonly operation: ArrayRequirement; } /** * Creates a find item transformation action. * * @param operation The find item operation. * * @returns A find item action. */ export function findItem< TInput extends ArrayInput, TOuput extends TInput[number], >(operation: ArrayRequirement): FindItemAction; // @__NO_SIDE_EFFECTS__ export function findItem( operation: ArrayRequirement ): FindItemAction { return { kind: 'transformation', type: 'find_item', reference: findItem, async: false, operation, '~run'(dataset) { // @ts-expect-error dataset.value = dataset.value.find(this.operation); return dataset as SuccessDataset; }, }; } ================================================ FILE: library/src/actions/findItem/index.ts ================================================ export * from './findItem.ts'; ================================================ FILE: library/src/actions/finite/finite.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { finite, type FiniteAction, type FiniteIssue } from './finite.ts'; describe('finite', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = FiniteAction; expectTypeOf(finite()).toEqualTypeOf(); expectTypeOf(finite(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(finite('message')).toEqualTypeOf< FiniteAction >(); }); test('with function message', () => { expectTypeOf(finite(() => 'message')).toEqualTypeOf< FiniteAction string> >(); }); }); describe('should infer correct types', () => { type Action = FiniteAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/finite/finite.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { NumberIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { finite, type FiniteAction, type FiniteIssue } from './finite.ts'; describe('finite', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'finite', reference: finite, expects: null, requirement: expect.any(Function), async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: FiniteAction = { ...baseAction, message: undefined, }; expect(finite()).toStrictEqual(action); expect(finite(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(finite('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies FiniteAction); }); test('with function message', () => { const message = () => 'message'; expect(finite(message)).toStrictEqual({ ...baseAction, message, } satisfies FiniteAction); }); }); describe('should return dataset without issues', () => { const action = finite(); test('for untyped inputs', () => { const issues: [NumberIssue] = [ { kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for finite numbers', () => { expectNoActionIssue(action, [ 0, 1234, 12.34, Number.MAX_VALUE, Number.MIN_VALUE, ]); }); }); describe('should return dataset with issues', () => { const action = finite('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'finite', expected: null, message: 'message', requirement: expect.any(Function), }; test('for infinite numbers', () => { expectActionIssue(action, baseIssue, [Infinity, -Infinity]); }); test('for not a number', () => { expectActionIssue(action, baseIssue, [NaN]); }); }); }); ================================================ FILE: library/src/actions/finite/finite.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Finite issue interface. */ export interface FiniteIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'finite'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `${number}`; /** * The validation function. */ readonly requirement: (input: number) => boolean; } /** * Finite action interface. */ export interface FiniteAction< TInput extends number, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'finite'; /** * The action reference. */ readonly reference: typeof finite; /** * The expected property. */ readonly expects: null; /** * The validation function. */ readonly requirement: (input: number) => boolean; /** * The error message. */ readonly message: TMessage; } /** * Creates a [finite](https://en.wikipedia.org/wiki/Finite) validation action. * * @returns A finite action. */ export function finite(): FiniteAction< TInput, undefined >; /** * Creates a [finite](https://en.wikipedia.org/wiki/Finite) validation action. * * @param message The error message. * * @returns A finite action. */ export function finite< TInput extends number, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): FiniteAction; // @__NO_SIDE_EFFECTS__ export function finite( message?: ErrorMessage> ): FiniteAction> | undefined> { return { kind: 'validation', type: 'finite', reference: finite, async: false, expects: null, requirement: Number.isFinite, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement(dataset.value)) { _addIssue(this, 'finite', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/finite/index.ts ================================================ export * from './finite.ts'; ================================================ FILE: library/src/actions/flavor/flavor.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { type Flavor, flavor, type FlavorAction } from './flavor.ts'; describe('flavor', () => { type Action = FlavorAction; test('should return action object', () => { expectTypeOf(flavor('foo')).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< string & Flavor<'foo'> >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); describe('should only match specific types', () => { type Output = InferOutput; test('should match unflavored types', () => { expectTypeOf().toMatchTypeOf(); }); test('should match types with same flavor', () => { expectTypeOf< InferOutput> >().toMatchTypeOf(); }); test('should not match types with different flavor', () => { expectTypeOf< InferOutput> >().not.toMatchTypeOf(); }); }); }); ================================================ FILE: library/src/actions/flavor/flavor.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { flavor, type FlavorAction } from './flavor.ts'; describe('flavor', () => { test('should return action object', () => { expect(flavor('foo')).toStrictEqual({ kind: 'transformation', type: 'flavor', reference: flavor, name: 'foo', async: false, '~run': expect.any(Function), } satisfies FlavorAction); }); test('should return same dataset', () => { const dataset = { typed: true, value: 'foo' } as const; expect(flavor('foo')['~run'](dataset, {})).toStrictEqual(dataset); }); }); ================================================ FILE: library/src/actions/flavor/flavor.ts ================================================ import type { BaseTransformation, SuccessDataset } from '../../types/index.ts'; /** * Flavor symbol. * * @beta */ export declare const FlavorSymbol: unique symbol; /** * Flavor name type. * * @beta */ export type FlavorName = string | number | symbol; /** * Flavor interface. * * @beta */ export interface Flavor { [FlavorSymbol]?: { [TValue in TName]: TValue }; } /** * Flavor action interface. * * @beta */ export interface FlavorAction extends BaseTransformation, never> { /** * The action type. */ readonly type: 'flavor'; /** * The action reference. */ readonly reference: typeof flavor; /** * The flavor name. */ readonly name: TName; } /** * Creates a flavor transformation action. * * @param name The flavor name. * * @returns A flavor action. * * @beta */ // @__NO_SIDE_EFFECTS__ export function flavor( name: TName ): FlavorAction { return { kind: 'transformation', type: 'flavor', reference: flavor, async: false, name, '~run'(dataset) { return dataset as SuccessDataset>; }, }; } ================================================ FILE: library/src/actions/flavor/index.ts ================================================ export * from './flavor.ts'; ================================================ FILE: library/src/actions/graphemes/graphemes.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { graphemes, type GraphemesAction, type GraphemesIssue, } from './graphemes.ts'; describe('graphemes', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = GraphemesAction; expectTypeOf(graphemes(10)).toEqualTypeOf(); expectTypeOf( graphemes(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( graphemes(10, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( graphemes string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Input = 'example string'; type Action = GraphemesAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< GraphemesIssue >(); }); }); }); ================================================ FILE: library/src/actions/graphemes/graphemes.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { _getGraphemeCount } from '../../utils/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { graphemes, type GraphemesAction, type GraphemesIssue, } from './graphemes.ts'; describe('graphemes', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'graphemes', reference: graphemes, expects: '5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: GraphemesAction = { ...baseAction, message: undefined, }; expect(graphemes(5)).toStrictEqual(action); expect(graphemes(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(graphemes(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies GraphemesAction); }); test('with function message', () => { const message = () => 'message'; expect(graphemes(5, message)).toStrictEqual({ ...baseAction, message, } satisfies GraphemesAction); }); }); describe('should return dataset without issues', () => { const action = graphemes(5); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid strings', () => { expectNoActionIssue(action, ['12345', '12 45', '1234 ', 'hello']); }); test('for valid emoji', () => { expectNoActionIssue(action, ['😀👋🏼🧩👩🏻‍🏫🫥']); }); }); describe('should return dataset with issues', () => { const action = graphemes(5, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'graphemes', expected: '5', message: 'message', requirement: 5, }; test('for invalid strings', () => { expectActionIssue( action, baseIssue, ['', ' ', '1', '1234', '123 ', '123456', '12 456', '123456789'], (value) => `${_getGraphemeCount(value)}` ); }); test('for invalid emoji', () => { expectActionIssue( action, baseIssue, ['😀', '😀👋🏼🧩👩🏻‍🏫', '😀👋🏼🧩👩🏻‍🏫🫥🫠', '😀👋🏼🧩👩🏻‍🏫🫥🫠🧑‍💻👻🥎'], (value) => `${_getGraphemeCount(value)}` ); }); }); }); ================================================ FILE: library/src/actions/graphemes/graphemes.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _getGraphemeCount } from '../../utils/index.ts'; /** * Graphemes issue interface. */ export interface GraphemesIssue< TInput extends string, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'graphemes'; /** * The expected property. */ readonly expected: `${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The required graphemes. */ readonly requirement: TRequirement; } /** * Graphemes action interface. */ export interface GraphemesAction< TInput extends string, TRequirement extends number, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'graphemes'; /** * The action reference. */ readonly reference: typeof graphemes; /** * The expected property. */ readonly expects: `${TRequirement}`; /** * The required graphemes. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a graphemes validation action. * * @param requirement The required graphemes. * * @returns A graphemes action. */ export function graphemes< TInput extends string, const TRequirement extends number, >(requirement: TRequirement): GraphemesAction; /** * Creates a graphemes validation action. * * @param requirement The required graphemes. * @param message The error message. * * @returns A graphemes action. */ export function graphemes< TInput extends string, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): GraphemesAction; // @__NO_SIDE_EFFECTS__ export function graphemes( requirement: number, message?: ErrorMessage> ): GraphemesAction< string, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'graphemes', reference: graphemes, async: false, expects: `${requirement}`, requirement, message, '~run'(dataset, config) { if (dataset.typed) { const count = _getGraphemeCount(dataset.value); if (count !== this.requirement) { _addIssue(this, 'graphemes', dataset, config, { received: `${count}`, }); } } return dataset; }, }; } ================================================ FILE: library/src/actions/graphemes/index.ts ================================================ export * from './graphemes.ts'; ================================================ FILE: library/src/actions/gtValue/gtValue.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { NumberIssue } from '../../schemas/index.ts'; import { _stringify } from '../../utils/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { gtValue, type GtValueAction } from './gtValue.ts'; describe('gtValue', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'gt_value', reference: gtValue, expects: '>5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: GtValueAction = { ...baseAction, message: undefined, }; expect(gtValue(5)).toStrictEqual(action); expect(gtValue(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(gtValue(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies GtValueAction); }); test('with function message', () => { const message = () => 'message'; expect(gtValue(5, message)).toStrictEqual({ ...baseAction, message, } satisfies GtValueAction); }); }); describe('should return dataset without issues', () => { test('for untyped inputs', () => { const issues: [NumberIssue] = [ { kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', message: 'message', }, ]; expect( gtValue(1)['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues }); }); test('for valid bigints', () => { expectNoActionIssue(gtValue(1n), [2n, 9999n]); }); test('for valid non-bigints', () => { expectNoActionIssue(gtValue(10n), [ ' 11 ', '+11', '11', 10.5, 11, 11.0, Infinity, new Date(11), new Date(11.5), ]); expectNoActionIssue(gtValue(1n), [ ' 2 ', '+2', '2', 1.5, 2, 2.0, Infinity, new Date(2), new Date(2.5), ]); expectNoActionIssue(gtValue(0n), [ ' 1 ', '+1', '1', 0.5, 1, 1.5, Infinity, true, new Date(1), ]); expectNoActionIssue(gtValue(-1n), [ ' 0 ', '+0', '0', -0.5, 0, 0.5, Infinity, true, false, new Date(0), ]); }); test('for valid booleans', () => { expectNoActionIssue(gtValue(false), [true]); }); test('for valid non-booleans', () => { expectNoActionIssue(gtValue(true), [ '1.5', '2', '99', '+1.5', '+2', '+99', '1.5', '2.0', '99.9', ' 1.5 ', ' 2 ', ' 99 ', 1.5, 2, 99, Infinity, new Date(2), new Date(99), 2n, 99n, ]); expectNoActionIssue(gtValue(false), [ '0.5', '1', '99', '+0.5', '+1', '+99', '0.5', '1.0', '99.9', ' 0.5 ', ' 1 ', ' 99 ', 0.5, 1, 99, Infinity, new Date(1), new Date(99), 1n, 99n, ]); }); test('for valid dates', () => { const date = new Date(); expectNoActionIssue(gtValue(date), [ new Date(+date + 1), new Date(+date + 999999), ]); }); test('for valid non-dates', () => { expectNoActionIssue(gtValue(new Date(10)), [ ' 10.5 ', '+10.5', '10.5', '11', '11.0', 10.5, 11, 11.0, Infinity, 11n, ]); expectNoActionIssue(gtValue(new Date(1)), [ ' 1.5 ', '+1.5 ', '1.5', '2', '2.0', 1.5, 2, 2.0, Infinity, 2n, ]); expectNoActionIssue(gtValue(new Date(0)), [ ' 0.5 ', '+0.5', '0.5', '1', '+1', '1.0', ' 1 ', 0.5, 1, 1.0, Infinity, true, 1n, ]); expectNoActionIssue(gtValue(new Date(-1)), [ '', ' ', '0', '1', '-0.5', '0.0', '1.0', ' -0.5 ', ' 0 ', ' 1 ', 0, -0, 1, -0.5, 0.0, 1.0, Infinity, false, true, 0n, 1n, ]); }); test('for valid numbers', () => { expectNoActionIssue(gtValue(10), [10.5, 11, 9999, Number.MAX_VALUE]); }); test('for valid non-numbers', () => { expectNoActionIssue(gtValue(10), [ ' 10.5 ', '+10.5', '10.5', '11', '99.99', new Date(11), new Date(99), 11n, 99n, ]); expectNoActionIssue(gtValue(1), [ ' 1.5 ', '+1.5 ', '1.5', '2', '2.0', new Date(2), 2n, ]); expectNoActionIssue(gtValue(0), [ ' 0.5 ', '+0.5', '0.5', '1', '+1', '1.0', ' 1 ', true, new Date(1), 1n, ]); expectNoActionIssue(gtValue(-1), [ '', ' ', ' -0.5 ', '-0.5', '-0', '0', '+0', '0.0', ' 0 ', true, false, new Date(0), 0n, ]); }); test('for valid strings', () => { expectNoActionIssue(gtValue('2024'), ['2024.', '2025', '9999', 'XYZ']); }); test('for valid non-strings', () => { expectNoActionIssue(gtValue('10'), [ 10.5, 11, 99.99, Infinity, new Date(11), new Date(99), 11n, 99n, ]); expectNoActionIssue(gtValue('1'), [ 1.5, 2, 2.0, Infinity, new Date(2), 2n, ]); expectNoActionIssue(gtValue('0'), [ 0.5, 1, 1.0, Infinity, true, new Date(1), 1n, ]); expectNoActionIssue(gtValue('-1'), [ -0.5, 0, 0.0, Infinity, true, false, new Date(0), 0n, ]); }); }); describe('should return dataset with issues', () => { const baseInfo = { kind: 'validation', type: 'gt_value', message: 'message', } as const; const getReceived = (value: unknown): string => value instanceof Date ? value.toJSON() : _stringify(value); test('for invalid bigints', () => { expectActionIssue( gtValue(10n, 'message'), { ...baseInfo, expected: '>10', requirement: 10n }, [-9999n, 0n, 9n, 10n] ); }); test('for invalid non-bigints', () => { expectActionIssue( gtValue(123n, 'message'), { ...baseInfo, expected: '>123', requirement: 123n }, [ 'nan', '124px', '+ 124', '-124', '', ' ', '0.0', '123', ' 123 ', '123.4', -123, 0, 123, 123.0, NaN, false, true, new Date(-123), new Date(0), new Date(123), ], getReceived ); expectActionIssue( gtValue(1n, 'message'), { ...baseInfo, expected: '>1', requirement: 1n }, [ 'nan', '2px', '+ 2', '-1', '', '0', '1', '1.0', '1.5', -1, 1, 1.0, NaN, false, true, new Date(-1), new Date(0), new Date(1), ], getReceived ); expectActionIssue( gtValue(0n, 'message'), { ...baseInfo, expected: '>0', requirement: 0n }, [ 'nan', '1px', '+ 1', '-1', '', '0', '0.0', '0.5', -1, 0, 0.0, NaN, false, new Date(-1), new Date(0), ], getReceived ); }); test('for invalid booleans', () => { expectActionIssue( gtValue(false, 'message'), { ...baseInfo, expected: '>false', requirement: false }, [false] ); expectActionIssue( gtValue(true, 'message'), { ...baseInfo, expected: '>true', requirement: true }, [false, true] ); }); test('for invalid non-booleans', () => { expectActionIssue( gtValue(false, 'message'), { ...baseInfo, expected: '>false', requirement: false }, [ 'nan', '1px', '+ 1', '-1', '', '0', '0.0', -1, 0, 0.0, NaN, new Date(-1), new Date(0), -1n, 0n, ], getReceived ); expectActionIssue( gtValue(true, 'message'), { ...baseInfo, expected: '>true', requirement: true }, [ 'nan', '2px', '+ 2', '-2', '', '0', '1', '1.0', -1, 1, 1.0, NaN, new Date(-1), new Date(0), new Date(1), -1n, 0n, 1n, ], getReceived ); }); test('for invalid dates', () => { const date = new Date(); expectActionIssue( gtValue(date, 'message'), { ...baseInfo, expected: `>${date.toJSON()}`, requirement: date }, [date, new Date(0), new Date(+date - 999999), new Date(+date - 1)], (value) => value.toJSON() ); }); test('for invalid non-dates', () => { const date1 = new Date(123); expectActionIssue( gtValue(date1, 'message'), { ...baseInfo, expected: `>${date1.toJSON()}`, requirement: date1 }, [ 'nan', '124px', '+ 124', '-124', '', '123', '123.0', -124, 0, 123, 123.0, NaN, false, true, -124n, 0n, 123n, ], getReceived ); const date2 = new Date(1); expectActionIssue( gtValue(date2, 'message'), { ...baseInfo, expected: `>${date2.toJSON()}`, requirement: date2 }, [ 'nan', '2px', '+ 2', '-2', '', '0', '1', '1.0', -2, 1, 1.0, NaN, false, true, -2n, 0n, 1n, ], getReceived ); const date3 = new Date(0); expectActionIssue( gtValue(date3, 'message'), { ...baseInfo, expected: `>${date3.toJSON()}`, requirement: date3 }, [ 'nan', '1px', '+ 1', '-1', '', '0', '0.0', -1, 0, 0.0, NaN, false, -1n, 0n, ], getReceived ); }); test('for invalid numbers', () => { expectActionIssue( gtValue(10, 'message'), { ...baseInfo, expected: '>10', requirement: 10 }, [Number.MIN_VALUE, 0, 9, 10, NaN] ); }); test('for invalid non-numbers', () => { expectActionIssue( gtValue(123, 'message'), { ...baseInfo, expected: '>123', requirement: 123 }, [ 'nan', '124px', '+ 124', '-124', '', '123', '123.0', false, true, new Date(-123), new Date(0), new Date(123), -123n, 0n, 123n, ], getReceived ); expectActionIssue( gtValue(1, 'message'), { ...baseInfo, expected: '>1', requirement: 1 }, [ 'nan', '2px', '+ 2', '-1', '', '0', '1', '1.0', false, true, new Date(-1), new Date(0), new Date(1), -1n, 0n, 1n, ], getReceived ); expectActionIssue( gtValue(0, 'message'), { ...baseInfo, expected: '>0', requirement: 0 }, [ 'nan', '1px', '+ 1', '-1', '', ' ', '0', '0.0', false, new Date(-1), new Date(0), -1n, 0n, ], getReceived ); }); test('for invalid strings', () => { expectActionIssue( gtValue('2024', 'message'), { ...baseInfo, expected: '>"2024"', requirement: '2024' }, ['', '1234', '2024'] ); }); test('for invalid non-strings', () => { expectActionIssue( gtValue('123', 'message'), { ...baseInfo, expected: '>"123"', requirement: '123' }, [ -123, 0, 123, 123.0, NaN, false, true, new Date(-123), new Date(0), new Date(123), -123n, 0n, 123n, ], getReceived ); expectActionIssue( gtValue('1', 'message'), { ...baseInfo, expected: '>"1"', requirement: '1' }, [ -1, 1, 1.0, NaN, false, true, new Date(-1), new Date(0), new Date(1), new Date(1.5), -1n, 0n, 1n, ], getReceived ); expectActionIssue( gtValue('0', 'message'), { ...baseInfo, expected: '>"0"', requirement: '0' }, [ -1, 0, 0.0, NaN, false, new Date(-1), new Date(0), new Date(0.5), -1n, 0n, ], getReceived ); }); }); }); ================================================ FILE: library/src/actions/gtValue/gtValue.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _stringify } from '../../utils/index.ts'; import type { ValueInput } from '../types.ts'; /** * Greater than value issue type. */ export interface GtValueIssue< TInput extends ValueInput, TRequirement extends TInput, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'gt_value'; /** * The expected property. */ readonly expected: `>${string}`; /** * The greater than value. */ readonly requirement: TRequirement; } /** * Greater than value action type. */ export interface GtValueAction< TInput extends ValueInput, TRequirement extends TInput, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'gt_value'; /** * The action reference. */ readonly reference: typeof gtValue; /** * The expected property. */ readonly expects: `>${string}`; /** * The greater than value. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a greater than value validation action. * * @param requirement The greater than value. * * @returns A greater than value action. */ export function gtValue< TInput extends ValueInput, const TRequirement extends TInput, >(requirement: TRequirement): GtValueAction; /** * Creates a greater than value validation action. * * @param requirement The greater than value. * @param message The error message. * * @returns A greater than value action. */ export function gtValue< TInput extends ValueInput, const TRequirement extends TInput, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): GtValueAction; // @__NO_SIDE_EFFECTS__ export function gtValue( requirement: ValueInput, message?: ErrorMessage> ): GtValueAction< ValueInput, ValueInput, ErrorMessage> | undefined > { return { kind: 'validation', type: 'gt_value', reference: gtValue, async: false, expects: `>${ requirement instanceof Date ? requirement.toJSON() : _stringify(requirement) }`, requirement, message, '~run'(dataset, config) { if (dataset.typed && !(dataset.value > this.requirement)) { _addIssue(this, 'value', dataset, config, { received: dataset.value instanceof Date ? dataset.value.toJSON() : _stringify(dataset.value), }); } return dataset; }, }; } ================================================ FILE: library/src/actions/gtValue/gtValues.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { gtValue, type GtValueAction, type GtValueIssue } from './gtValue.ts'; describe('gtValue', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = GtValueAction; expectTypeOf(gtValue(10)).toEqualTypeOf(); expectTypeOf( gtValue(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(gtValue(10, 'message')).toEqualTypeOf< GtValueAction >(); }); test('with function message', () => { expectTypeOf( gtValue string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = GtValueAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< GtValueIssue >(); }); }); }); ================================================ FILE: library/src/actions/gtValue/index.ts ================================================ export * from './gtValue.ts'; ================================================ FILE: library/src/actions/guard/guard.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { pipe } from '../../methods/index.ts'; import { literal, number, string } from '../../schemas/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { GuardAction, GuardIssue } from './guard.ts'; import { guard } from './guard.ts'; describe('guard', () => { type PixelString = `${number}px`; const isPixelString = (input: string): input is PixelString => /^\d+px$/u.test(input); describe('should return action object', () => { test('with no message', () => { expectTypeOf(guard(isPixelString)).toEqualTypeOf< GuardAction >(); }); test('with string message', () => { expectTypeOf(guard(isPixelString, 'message')).toEqualTypeOf< GuardAction >(); }); test('with function message', () => { expectTypeOf(guard(isPixelString, () => 'message')).toEqualTypeOf< GuardAction string> >(); }); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf< InferInput> >().toEqualTypeOf(); }); test('of output', () => { expectTypeOf< InferOutput> >().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf< InferIssue> >().toEqualTypeOf>(); }); }); test('should infer correct type in pipe', () => { // eslint-disable-next-line @typescript-eslint/no-unused-vars const schema = pipe( string(), guard((input) => { expectTypeOf(input).toEqualTypeOf(); return isPixelString(input); }) ); expectTypeOf>().toEqualTypeOf(); }); test("should error if pipe input doesn't match", () => { pipe( number(), // @ts-expect-error guard(isPixelString) ); }); test('should allow narrower input or wider output', () => { // eslint-disable-next-line @typescript-eslint/no-unused-vars const narrowInput = pipe( string(), // guard allows wider input than current pipe guard( (input: unknown) => typeof input === 'string' && isPixelString(input) ) ); expectTypeOf< InferOutput >().toEqualTypeOf(); // guarded type is wider than current pipe // so we keep the narrower type // eslint-disable-next-line @typescript-eslint/no-unused-vars const wideOutput = pipe(literal('123px'), guard(isPixelString)); expectTypeOf>().toEqualTypeOf<'123px'>(); }); }); ================================================ FILE: library/src/actions/guard/guard.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { FailureDataset } from '../../types/dataset.ts'; import type { GuardAction, GuardIssue } from './guard.ts'; import { guard } from './guard.ts'; describe('guard', () => { type PixelString = `${number}px`; const isPixelString = (input: string): input is PixelString => /^\d+px$/u.test(input); const baseAction: Omit< GuardAction, 'message' > = { kind: 'transformation', type: 'guard', reference: guard, requirement: isPixelString, async: false, '~run': expect.any(Function), }; describe('should return action object', () => { test('with undefined message', () => { const action: GuardAction = { ...baseAction, message: undefined, }; expect(guard(isPixelString)).toStrictEqual(action); expect(guard(isPixelString, undefined)).toStrictEqual(action); }); test('with string message', () => { const action: GuardAction = { ...baseAction, message: 'message', }; expect(guard(isPixelString, 'message')).toStrictEqual(action); }); test('with function message', () => { const message = () => 'message'; const action: GuardAction = { ...baseAction, message, }; expect(guard(isPixelString, message)).toStrictEqual(action); }); }); test('should return dataset without issues', () => { const action = guard(isPixelString); const outputDataset = { typed: true, value: '123px' }; expect(action['~run']({ typed: true, value: '123px' }, {})).toStrictEqual( outputDataset ); }); test('should return dataset with issues', () => { const action = guard(isPixelString, 'message'); const baseIssue: Omit< GuardIssue, 'input' | 'received' > = { kind: 'transformation', type: 'guard', expected: null, message: 'message', requirement: isPixelString, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; expect(action['~run']({ typed: true, value: '123' }, {})).toStrictEqual({ typed: false, value: '123', issues: [ { ...baseIssue, input: '123', received: '"123"', }, ], } satisfies FailureDataset>); }); }); ================================================ FILE: library/src/actions/guard/guard.ts ================================================ import type { BaseIssue, BaseTransformation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Guard function type. * * @beta */ export type GuardFunction = ( input: TInput // eslint-disable-next-line @typescript-eslint/no-explicit-any ) => input is any; /** * Infer guard output type. * * @beta */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export type InferGuardOutput> = // eslint-disable-next-line @typescript-eslint/no-explicit-any TGuard extends (input: any) => input is infer TOutput ? TOutput : unknown; /** * Guard issue interface. * * @beta */ export interface GuardIssue> extends BaseIssue { /** * The issue kind. */ readonly kind: 'transformation'; /** * The issue type. */ readonly type: 'guard'; /** * The guard function. */ readonly requirement: TGuard; } /** * Guard action interface. * * @beta */ export interface GuardAction< TInput, TGuard extends GuardFunction, TMessage extends ErrorMessage> | undefined, > extends BaseTransformation< TInput, // intersect in case guard is actually wider TInput & InferGuardOutput, GuardIssue > { /** * The action type. */ readonly type: 'guard'; /** * The action reference. */ readonly reference: typeof guard; /** * The guard function. */ readonly requirement: TGuard; /** * The error message. */ readonly message: TMessage; } /** * Creates a guard transformation action. * * @param requirement The guard function. * * @returns A guard action. * * @beta */ // known input from pipe export function guard>( requirement: TGuard ): GuardAction; /** * Creates a guard transformation action. * * @param requirement The guard function. * * @returns A guard action. * * @beta */ // unknown input, e.g. standalone // eslint-disable-next-line @typescript-eslint/no-explicit-any export function guard>( requirement: TGuard ): GuardAction[0], TGuard, undefined>; /** * Creates a guard transformation action. * * @param requirement The guard function. * @param message The error message. * * @returns A guard action. * * @beta */ // known input from pipe export function guard< TInput, const TGuard extends GuardFunction, const TMessage extends ErrorMessage> | undefined, >( requirement: TGuard, message: TMessage ): GuardAction; /** * Creates a guard transformation action. * * @param requirement The guard function. * @param message The error message. * * @returns A guard action. * * @beta */ // unknown input, e.g. standalone export function guard< // eslint-disable-next-line @typescript-eslint/no-explicit-any const TGuard extends GuardFunction, const TMessage extends | ErrorMessage[0], TGuard>> | undefined, >( requirement: TGuard, message: TMessage ): GuardAction[0], TGuard, TMessage>; // @__NO_SIDE_EFFECTS__ export function guard( requirement: GuardFunction, message?: ErrorMessage>> ): GuardAction< unknown, GuardFunction, ErrorMessage>> | undefined > { return { kind: 'transformation', type: 'guard', reference: guard, async: false, requirement, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement(dataset.value)) { _addIssue(this, 'input', dataset, config); // @ts-expect-error dataset.typed = false; } return dataset; }, }; } ================================================ FILE: library/src/actions/guard/index.ts ================================================ export * from './guard.ts'; ================================================ FILE: library/src/actions/hash/hash.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { hash, type HashAction, type HashIssue } from './hash.ts'; describe('hash', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = HashAction; expectTypeOf(hash(['md5'])).toEqualTypeOf(); expectTypeOf(hash(['md5'], undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(hash(['md5'], 'message')).toEqualTypeOf< HashAction >(); }); test('with function message', () => { expectTypeOf(hash(['md5'], () => 'message')).toEqualTypeOf< HashAction string> >(); }); }); describe('should infer correct types', () => { type Action = HashAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/hash/hash.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { hash, type HashAction, type HashIssue } from './hash.ts'; describe('hash', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'hash', reference: hash, expects: null, requirement: expect.any(RegExp), async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: HashAction = { ...baseAction, message: undefined, }; expect(hash(['md5'])).toStrictEqual(action); expect(hash(['md5'], undefined)).toStrictEqual(action); }); test('with string message', () => { expect(hash(['md5'], 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies HashAction); }); test('with function message', () => { const message = () => 'message'; expect(hash(['md5'], message)).toStrictEqual({ ...baseAction, message, } satisfies HashAction); }); }); describe('should return dataset without issues', () => { test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( hash(['md5'])['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for md4 hashes', () => { expectNoActionIssue(hash(['md4']), [ 'c93d3bf7a7c4afe94b64e30c2ce39f4f', '16360e57b209fb9d07f725aa796789ac', 'fbe550055d737a0cd3a4325df5dfdc79', ]); }); test('for md5 hashes', () => { expectNoActionIssue(hash(['md5']), [ 'd41d8cd98f00b204e9800998ecf8427e', '52f3810691030a673b1d060a98b31d09', '8a00ee7faa357ad736a5832a56c03c73', ]); }); test('for sha1 hashes', () => { expectNoActionIssue(hash(['sha1']), [ 'd033e22ae348aeb5660fc2140aec35850c4da997', '6a382c838f2d4b656062a55e69e3755ae267c254', 'ed8bda3e9fba8a9341fc1267926389bdac60df33', ]); }); test('for sha256 hashes', () => { expectNoActionIssue(hash(['sha256']), [ '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08', '03b04c0f41234a184ddb0f6dd5f85a63e7f40b4bbad056160954306922f12d57', '86f5b2c8a75e3f359e588debdd10a076b839a9c9f47db2edf903c0b908dea46f', ]); }); test('for sha384 hashes', () => { expectNoActionIssue(hash(['sha384']), [ '38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b', 'e1c83876fcf6991b54fb249d79c6a75dc85643385d3727a9801413a86087fd177ae09b3a63a7991d5631836dc1cdffd1', 'b6b6b75130ad75944c39b2e347362446c009f7ba57eb16693c86129983c692ce82d94b4b0f4bb5a408dd76e59fdf4fef', ]); }); test('for sha512 hashes', () => { expectNoActionIssue(hash(['sha512']), [ 'a8cdec07e13c3af4a7a992db4a352efe3699fe95b470ee503940b7198c4b0ddc8ba0eda677be76bcf638c27ac837c779cd924de0726a1fc137a88ae8a208ef28', '6c3fa2fd93b9615fb138973c37f13df3de43bd6917a29c75ed9870cc7882fee2fb89706209abc05d39c3cff220f36ea94e4e3ce900d2204d99e20315c2702a55', 'c2529f7fe73e78b926d44c76270a1dbb22239da068ecfcef7a6dec99be5fb8e083fb34eb4f79cdf97c559ccad4deb61869ac17aa651a23f254db35ecc9fca5d5', ]); }); test('for ripemd128 hashes', () => { expectNoActionIssue(hash(['ripemd128']), [ 'c766f912a89d4ccda88e0cce6a713ef7', '350de5ee5242d93e23a98966ad7ea3ce', '3fa9692610626962c2c9a12adbb2b264', ]); }); test('for ripemd160 hashes', () => { expectNoActionIssue(hash(['ripemd160']), [ '9c1185a5c5e9fc54612808977ee8f548b2258d31', 'e5075950e0b90e426ef7474e4993abb724aef047', 'a04fefb2f2b664fd10cdb8b17b1ec974db299529', ]); }); test('for tiger128 hashes', () => { expectNoActionIssue(hash(['tiger128']), [ '7ab383fc29d81f8d0d68e87c69bae5f1', 'c914df7857ee41f7d6bebe131a902723', 'b971739819c2475c757f6e2d7a3309f8', ]); }); test('for tiger160 hashes', () => { expectNoActionIssue(hash(['tiger160']), [ '7ab383fc29d81f8d0d68e87c69bae5f1f18266d7', 'f741ee5778df14c92327901a13bebed617fc3968', '5c47c219987371b9f809337a2d6e7f753d7d0f84', ]); }); test('for tiger192 hashes', () => { expectNoActionIssue(hash(['tiger192']), [ '4dd00f9e8e8a6a8e3883af1051237c4b47bd2a329b1de1a3', 'f741ee5778df14c92327901a13bebed617fc3968d42eee4c', '5c47c219987371b9f809337a2d6e7f753d7d0f8420fdd8bf', ]); }); test('for crc32 hashes', () => { expectNoActionIssue(hash(['crc32']), [ '3d08bb77', 'd87f7e0c', '35ce1956', 'fb57a171', ]); }); test('for crc32b hashes', () => { expectNoActionIssue(hash(['crc32b']), [ '7d4da703', '35ce1956', 'fb57a171', ]); }); test('for adler32 hashes', () => { expectNoActionIssue(hash(['adler32']), [ '045d01c1', '0bbf02f2', '66b108b6', ]); }); test('for md5 or adler32 hashes', () => { expectNoActionIssue(hash(['md5', 'adler32']), [ '045d01c1', 'd41d8cd98f00b204e9800998ecf8427e', '52f3810691030a673b1d060a98b31d09', '0bbf02f2', '8a00ee7faa357ad736a5832a56c03c73', '66b108b6', ]); }); test('for md4, sha256 or tiger128 hashes', () => { expectNoActionIssue(hash(['md4', 'sha256', 'tiger128']), [ 'c93d3bf7a7c4afe94b64e30c2ce39f4f', '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08', '7ab383fc29d81f8d0d68e87c69bae5f1', 'c914df7857ee41f7d6bebe131a902723', '16360e57b209fb9d07f725aa796789ac', '03b04c0f41234a184ddb0f6dd5f85a63e7f40b4bbad056160954306922f12d57', 'b971739819c2475c757f6e2d7a3309f8', 'fbe550055d737a0cd3a4325df5dfdc79', '86f5b2c8a75e3f359e588debdd10a076b839a9c9f47db2edf903c0b908dea46f', ]); }); }); describe('should return dataset with issues', () => { const baseIssue: Omit< HashIssue, 'input' | 'received' | 'requirement' > = { kind: 'validation', type: 'hash', expected: null, message: 'message', }; test('for invalid md4 hashes', () => { expectActionIssue( hash(['md4'], 'message'), { ...baseIssue, requirement: /^[a-fA-F0-9]{32}$/u }, [ '', ' ', '12345', 'c93d3bf7a7c4afe94b64e+0c2ce39f4f', 'd033e22ae348aeb5660fc2140aec35850c4da997', ] ); }); test('for invalid md5 hashes', () => { expectActionIssue( hash(['md5'], 'message'), { ...baseIssue, requirement: /^[a-fA-F0-9]{32}$/u }, [ '', ' ', '12345', 'd41d8cd98f00b204g9800998ecf8427e', '38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b', ] ); }); test('for invalid sha1 hashes', () => { expectActionIssue( hash(['sha1'], 'message'), { ...baseIssue, requirement: /^[a-fA-F0-9]{40}$/u }, [ '', ' ', '12345', 'ed8bda3e9fba8a9341fc12679263h9bdac60df33', '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08', ] ); }); test('for invalid sha256 hashes', () => { expectActionIssue( hash(['sha256'], 'message'), { ...baseIssue, requirement: /^[a-fA-F0-9]{64}$/u }, [ '', ' ', '12345', '9f86d081884c7d659a2feaa0c5iad015a3bf4f1b2b0b822cd15d6c15b0f00a08', 'a8cdec07e13c3af4a7a992db4a352efe3699fe95b470ee503940b7198c4b0ddc8ba0eda677be76bcf638c27ac837c779cd924de0726a1fc137a88ae8a208ef28', ] ); }); test('for invalid sha384 hashes', () => { expectActionIssue( hash(['sha384'], 'message'), { ...baseIssue, requirement: /^[a-fA-F0-9]{96}$/u }, [ '', ' ', '12345', '38b060a751ac96384cd9327eb1b1e36a21fdb711k4be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b', 'c2529f7fe73e78b926d44c76270a1dbb22239da068ecfcef7a6dec99be5fb8e083fb34eb4f79cdf97c559ccad4deb61869ac17aa651a23f254db35ecc9fca5d5', ] ); }); test('for invalid sha512 hashes', () => { expectActionIssue( hash(['sha512'], 'message'), { ...baseIssue, requirement: /^[a-fA-F0-9]{128}$/u }, [ '', ' ', '12345', 'a8cdec07e13c3af4a7a992db4a352efe3699fe95b470ee5j3940b7198c4b0ddc8ba0eda677be76bcf638c27ac837c779cd924de0726a1fc137a88ae8a208ef28', 'd41d8cd98f00b204e9800998ecf8427e', ] ); }); test('for invalid ripemd128 hashes', () => { expectActionIssue( hash(['ripemd128'], 'message'), { ...baseIssue, requirement: /^[a-fA-F0-9]{32}$/u }, [ '', ' ', '12345', 'c766f912a89d4ccdal8e0cce6a713ef7', 'e5075950e0b90e426ef7474e4993abb724aef047', ] ); }); test('for invalid ripemd160 hashes', () => { expectActionIssue( hash(['ripemd160'], 'message'), { ...baseIssue, requirement: /^[a-fA-F0-9]{40}$/u }, [ '', ' ', '12345', '350de5ee5242d93e23a98966ad7ea3ce', '9c1185a5c5e9fc54612m08977ee8f548b2258d31', ] ); }); test('for invalid tiger128 hashes', () => { expectActionIssue( hash(['tiger128'], 'message'), { ...baseIssue, requirement: /^[a-fA-F0-9]{32}$/u }, [ '', ' ', '12345', '7ab383fc29d81f8d0dn8e87c69bae5f1', 'f741ee5778df14c92327901a13bebed617fc3968', ] ); }); test('for invalid tiger160 hashes', () => { expectActionIssue( hash(['tiger160'], 'message'), { ...baseIssue, requirement: /^[a-fA-F0-9]{40}$/u }, [ '', ' ', '12345', '7ab383fc29d81f8d0d68eo7c69bae5f1f18266d7', 'f741ee5778df14c92327901a13bebed617fc3968d42eee4c', ] ); }); test('for invalid tiger192 hashes', () => { expectActionIssue( hash(['tiger192'], 'message'), { ...baseIssue, requirement: /^[a-fA-F0-9]{48}$/u }, [ '', ' ', '12345', '4dd00f9e8e8a6a8e3883af1051237p4b47bd2a329b1de1a3', '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08', ] ); }); test('for invalid crc32 hashes', () => { expectActionIssue( hash(['crc32'], 'message'), { ...baseIssue, requirement: /^[a-fA-F0-9]{8}$/u }, ['', ' ', '12345', '3d08bq77', 'c93d3bf7a7c4afe94b64e30c2ce39f4f'] ); }); test('for invalid crc32b hashes', () => { expectActionIssue( hash(['crc32b'], 'message'), { ...baseIssue, requirement: /^[a-fA-F0-9]{8}$/u }, ['', ' ', '12345', '35cer956', 'fbe550055d737a0cd3a4325df5dfdc79'] ); }); test('for invalid adler32 hashes', () => { expectActionIssue( hash(['adler32'], 'message'), { ...baseIssue, requirement: /^[a-fA-F0-9]{8}$/u }, ['', ' ', '12345', '045dx1c1', '16360e57b209fb9d07f725aa796789ac'] ); }); test('for invalid md5 and adler32 hashes', () => { expectActionIssue( hash(['adler32', 'md5'], 'message'), { ...baseIssue, requirement: /^[a-fA-F0-9]{8}$|^[a-fA-F0-9]{32}$/u }, [ '', ' ', '12345', '045d0yc1', 'd41d8zd98f00b204e9800998ecf8427e', '52f38#0691030a673b1d060a98b31d09', '9f86d081884c7d659a2feaa0c5iad015a3bf4f1b2b0b822cd15d6c15b0f00a08', ] ); }); test('for invalid crc32, ripemd128 and sha1 hashes', () => { expectActionIssue( hash(['crc32', 'ripemd128', 'sha1'], 'message'), { ...baseIssue, requirement: /^[a-fA-F0-9]{8}$|^[a-fA-F0-9]{32}$|^[a-fA-F0-9]{40}$/u, }, [ '', ' ', '1234', 'fbx7a171', '350de5ee5242d93ez3a98966ad7ea3ce', '6a382c838f2d4b65y062a55e69e3755ae267c254', 'c2529f7fe73e78b926d44c76270a1dbb22239da068ecfcef7a6dec99be5fb8e083fb34eb4f79cdf97c559ccad4deb61869ac17aa651a23f254db35ecc9fca5d5', ] ); }); }); }); ================================================ FILE: library/src/actions/hash/hash.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Hash lengths object. */ const HASH_LENGTHS = { md4: 32, md5: 32, sha1: 40, sha256: 64, sha384: 96, sha512: 128, ripemd128: 32, ripemd160: 40, tiger128: 32, tiger160: 40, tiger192: 48, crc32: 8, crc32b: 8, adler32: 8, } as const; /** * Hash type type. */ export type HashType = keyof typeof HASH_LENGTHS; /** * Hash issue interface. */ export interface HashIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'hash'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The hash regex. */ readonly requirement: RegExp; } /** * Hash action interface. */ export interface HashAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'hash'; /** * The action reference. */ readonly reference: typeof hash; /** * The expected property. */ readonly expects: null; /** * The hash regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates a [hash](https://en.wikipedia.org/wiki/Hash_function) validation action. * * @param types The hash types. * * @returns A hash action. */ export function hash( types: [HashType, ...HashType[]] ): HashAction; /** * Creates a [hash](https://en.wikipedia.org/wiki/Hash_function) validation action. * * @param types The hash types. * @param message The error message. * * @returns A hash action. */ export function hash< TInput extends string, const TMessage extends ErrorMessage> | undefined, >( types: [HashType, ...HashType[]], message: TMessage ): HashAction; // @__NO_SIDE_EFFECTS__ export function hash( types: [HashType, ...HashType[]], message?: ErrorMessage> ): HashAction> | undefined> { return { kind: 'validation', type: 'hash', reference: hash, expects: null, async: false, requirement: RegExp( types.map((type) => `^[a-fA-F0-9]{${HASH_LENGTHS[type]}}$`).join('|'), 'u' ), message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'hash', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/hash/index.ts ================================================ export * from './hash.ts'; ================================================ FILE: library/src/actions/hexColor/hexColor.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { hexColor, type HexColorAction, type HexColorIssue, } from './hexColor.ts'; describe('hexColor', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = HexColorAction; expectTypeOf(hexColor()).toEqualTypeOf(); expectTypeOf(hexColor(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(hexColor('message')).toEqualTypeOf< HexColorAction >(); }); test('with function message', () => { expectTypeOf(hexColor(() => 'message')).toEqualTypeOf< HexColorAction string> >(); }); }); describe('should infer correct types', () => { type Action = HexColorAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/hexColor/hexColor.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { HEX_COLOR_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { hexColor, type HexColorAction, type HexColorIssue, } from './hexColor.ts'; describe('hexColor', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'hex_color', reference: hexColor, expects: null, requirement: HEX_COLOR_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: HexColorAction = { ...baseAction, message: undefined, }; expect(hexColor()).toStrictEqual(action); expect(hexColor(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(hexColor('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies HexColorAction); }); test('with function message', () => { const message = () => 'message'; expect(hexColor(message)).toStrictEqual({ ...baseAction, message, } satisfies HexColorAction); }); }); describe('should return dataset without issues', () => { const action = hexColor(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for 3 digits', () => { expectNoActionIssue(action, [ '#000', '#FFF', '#F00', '#0F0', '#00F', '#123', '#abc', ]); }); test('for 4 digits', () => { expectNoActionIssue(action, [ '#0000', '#FFFF', '#F00F', '#0F0F', '#00FF', '#1234', '#abcd', ]); }); test('for 6 digits', () => { expectNoActionIssue(action, [ '#000000', '#FFFFFF', '#FF0000', '#00FF00', '#0000FF', '#123456', '#abcdef', ]); }); test('for 8 digits', () => { expectNoActionIssue(action, [ '#00000000', '#FFFFFFFF', '#FF0000FF', '#00FF00FF', '#0000FFFF', '#12345678', '#abcdefab', ]); }); }); describe('should return dataset with issues', () => { const action = hexColor('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'hex_color', expected: null, message: 'message', requirement: HEX_COLOR_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for missing # symbol', () => { expectActionIssue(action, baseIssue, [ 'FFF', 'FFFF', 'FFFFFF', 'FFFFFFFF', ]); }); test('for two # symbols', () => { expectActionIssue(action, baseIssue, [ '##FFF', '##FFFF', '##FFFFFF', '##FFFFFFFF', ]); }); test('for missing digits', () => { expectActionIssue(action, baseIssue, ['#']); }); test('for blank spaces', () => { expectActionIssue(action, baseIssue, [' #FFF', '#FFF ', '#FFF FFF']); }); test('for 1 digit', () => { expectActionIssue(action, baseIssue, ['#0', '#F', '#1', '#a']); }); test('for 2 digits', () => { expectActionIssue(action, baseIssue, ['#00', '#FF', '#12', '#ab']); }); test('for 5 digits', () => { expectActionIssue(action, baseIssue, [ '#00000', '#FFFFF', '#12345', '#abcde', ]); }); test('for 7 digits', () => { expectActionIssue(action, baseIssue, [ '#0000000', '#FFFFFFF', '#1234567', '#abcdefa', ]); }); test('for 9 digits', () => { expectActionIssue(action, baseIssue, [ '#000000000', '#FFFFFFFFF', '#123456789', '#abcdefabc', ]); }); test('for non hex chars', () => { expectActionIssue(action, baseIssue, [ '#GGG', '#zzz', '#GGGG', '#zzzz', '#GGGGGG', '#zzzzzz', '#GGGGGGGG', '#zzzzzzzz', ]); }); }); }); ================================================ FILE: library/src/actions/hexColor/hexColor.ts ================================================ import { HEX_COLOR_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Hex color issue interface. */ export interface HexColorIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'hex_color'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The hex color regex. */ readonly requirement: RegExp; } /** * Hex color action interface. */ export interface HexColorAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'hex_color'; /** * The action reference. */ readonly reference: typeof hexColor; /** * The expected property. */ readonly expects: null; /** * The hex color regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates a [hex color](https://en.wikipedia.org/wiki/Web_colors#Hex_triplet) validation action. * * @returns A hex color action. */ export function hexColor(): HexColorAction< TInput, undefined >; /** * Creates a [hex color](https://en.wikipedia.org/wiki/Web_colors#Hex_triplet) validation action. * * @param message The error message. * * @returns A hex color action. */ export function hexColor< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): HexColorAction; // @__NO_SIDE_EFFECTS__ export function hexColor( message?: ErrorMessage> ): HexColorAction> | undefined> { return { kind: 'validation', type: 'hex_color', reference: hexColor, async: false, expects: null, requirement: HEX_COLOR_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'hex color', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/hexColor/index.ts ================================================ export * from './hexColor.ts'; ================================================ FILE: library/src/actions/hexadecimal/hexadecimal.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { hexadecimal, type HexadecimalAction, type HexadecimalIssue, } from './hexadecimal.ts'; describe('hexadecimal', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = HexadecimalAction; expectTypeOf(hexadecimal()).toEqualTypeOf(); expectTypeOf(hexadecimal(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(hexadecimal('message')).toEqualTypeOf< HexadecimalAction >(); }); test('with function message', () => { expectTypeOf(hexadecimal(() => 'message')).toEqualTypeOf< HexadecimalAction string> >(); }); }); describe('should infer correct types', () => { type Action = HexadecimalAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< HexadecimalIssue >(); }); }); }); ================================================ FILE: library/src/actions/hexadecimal/hexadecimal.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { HEXADECIMAL_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { hexadecimal, type HexadecimalAction, type HexadecimalIssue, } from './hexadecimal.ts'; describe('hexadecimal', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'hexadecimal', reference: hexadecimal, expects: null, requirement: HEXADECIMAL_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: HexadecimalAction = { ...baseAction, message: undefined, }; expect(hexadecimal()).toStrictEqual(action); expect(hexadecimal(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(hexadecimal('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies HexadecimalAction); }); test('with function message', () => { const message = () => 'message'; expect(hexadecimal(message)).toStrictEqual({ ...baseAction, message, } satisfies HexadecimalAction); }); }); describe('should return dataset without issues', () => { const action = hexadecimal(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for hexadecimal chars', () => { expectNoActionIssue(action, [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F', ]); }); test('for two chars', () => { expectNoActionIssue(action, ['00', '12', 'FF']); }); test('for multiple chars', () => { expectNoActionIssue(action, [ '000000000000000', '123456789abcdef', '123456789ABCDEF', 'FFFFFFFFFFFFFFF', ]); }); test('for 0h prefix', () => { expectNoActionIssue(action, [ '0h000000000000000', '0h123456789abcdef', '0h123456789ABCDEF', '0hFFFFFFFFFFFFFFF', ]); }); test('for 0x prefix', () => { expectNoActionIssue(action, [ '0x000000000000000', '0x123456789abcdef', '0x123456789ABCDEF', '0xFFFFFFFFFFFFFFF', ]); }); }); describe('should return dataset with issues', () => { const action = hexadecimal('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'hexadecimal', expected: null, message: 'message', requirement: HEXADECIMAL_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for blank spaces', () => { expectActionIssue(action, baseIssue, [' 1', '1 ', ' 1 ', '1 2']); }); test('for number signs', () => { expectActionIssue(action, baseIssue, ['+1', '-1', '+123', '-123']); }); test('for float numbers', () => { expectActionIssue(action, baseIssue, ['0.1', '123.456']); }); test('for exponential numbers', () => { expectActionIssue(action, baseIssue, ['1e-3', '1e+3']); }); test('for invalid letters', () => { expectActionIssue(action, baseIssue, [ 'g', 'G', 'z', 'Z', '123456789abcdefg', '123456789ABCDEFG', '123456789abcdefghijklmnopqrstuvwxyz', '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', ]); }); test('for special chars', () => { expectActionIssue(action, baseIssue, [ '-', '-1', '+', '+1', '#', '#1', '$', '$1', '%', '1%', ]); }); }); }); ================================================ FILE: library/src/actions/hexadecimal/hexadecimal.ts ================================================ import { HEXADECIMAL_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Hexadecimal issue interface. */ export interface HexadecimalIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'hexadecimal'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The hexadecimal regex. */ readonly requirement: RegExp; } /** * Hexadecimal action interface. */ export interface HexadecimalAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'hexadecimal'; /** * The action reference. */ readonly reference: typeof hexadecimal; /** * The expected property. */ readonly expects: null; /** * The hexadecimal regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates a [hexadecimal](https://en.wikipedia.org/wiki/Hexadecimal) validation action. * * @returns A hexadecimal action. */ export function hexadecimal(): HexadecimalAction< TInput, undefined >; /** * Creates a [hexadecimal](https://en.wikipedia.org/wiki/Hexadecimal) validation action. * * @param message The error message. * * @returns A hexadecimal action. */ export function hexadecimal< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): HexadecimalAction; // @__NO_SIDE_EFFECTS__ export function hexadecimal( message?: ErrorMessage> ): HexadecimalAction< string, ErrorMessage> | undefined > { return { kind: 'validation', type: 'hexadecimal', reference: hexadecimal, async: false, expects: null, requirement: HEXADECIMAL_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'hexadecimal', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/hexadecimal/index.ts ================================================ export * from './hexadecimal.ts'; ================================================ FILE: library/src/actions/imei/imei.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { imei, type ImeiAction, type ImeiIssue } from './imei.ts'; describe('imei', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = ImeiAction; expectTypeOf(imei()).toEqualTypeOf(); expectTypeOf(imei(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(imei('message')).toEqualTypeOf< ImeiAction >(); }); test('with function message', () => { expectTypeOf(imei(() => 'message')).toEqualTypeOf< ImeiAction string> >(); }); }); describe('should infer correct types', () => { type Action = ImeiAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/imei/imei.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { imei, type ImeiAction, type ImeiIssue } from './imei.ts'; describe('imei', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'imei', reference: imei, expects: null, requirement: expect.any(Function), async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: ImeiAction = { ...baseAction, message: undefined, }; expect(imei()).toStrictEqual(action); expect(imei(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(imei('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies ImeiAction); }); test('with function message', () => { const message = () => 'message'; expect(imei(message)).toStrictEqual({ ...baseAction, message, } satisfies ImeiAction); }); }); describe('should return dataset without issues', () => { const action = imei(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid IMEI without separators', () => { expectNoActionIssue(action, [ '861812069402168', '536498459191226', '454438576454550', '356741089396021', ]); }); test('for valid IMEI with separators', () => { expectNoActionIssue(action, [ '86-181206-940216-8', '53-649845-919122-6', '45-443857-645455-0', '35-674108-939602-1', ]); }); }); describe('should return dataset with issues', () => { const action = imei('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'imei', expected: null, message: 'message', requirement: expect.any(Function), }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for blank spaces', () => { expectActionIssue(action, baseIssue, [ ' 861812069402168', '861812069402168 ', ' 861812069402168 ', ]); }); test('for missing separators', () => { expectActionIssue(action, baseIssue, [ '86181206-940216-8', '86-181206940216-8', '86-181206-9402168', ]); }); test('for double separators', () => { expectActionIssue(action, baseIssue, [ '86--181206-940216-8', '86-181206--940216-8', '86-181206-940216--8', '86--181206--940216--8', ]); }); test('for invalid separators', () => { expectActionIssue(action, baseIssue, [ '86 181206 940216 8', '86/181206/940216/8', '86_181206_940216_8', '86–181206–940216–8', ]); }); test('for invalid digit count', () => { expectActionIssue(action, baseIssue, [ '86181206940216', // 14 digits '8618120694021683', // 16 digits '8-181206-940216-8', // missing A digit '862-181206-940216-8', // extra A digit '86-11206-940216-8', // missing B digit '86-1817206-940216-8', // extra B digit '86-181206-94216-8', // missing C digit '86-181206-9408216-8', // extra C digit '86-181206-940216', // missing D digit '86-181206-940216-', // missing D digit '86-181206-940216-82', // extra D digit ]); }); test('for non digit chars', () => { expectActionIssue(action, baseIssue, [ '861812A69402168', // A digit '8A-181206-940216-8', // A digit '861812a69402168', // a digit '86-1a1206-940216-8', // a digit '86181206Z402168', // Z digit '86-181206-9402Z6-8', // Z digit '86181206z402168', // z digit '86-181206-940216-z', // z digit '861812069$02168', // $ digit '86-18$206-940216-8', // $ digit '861@12069402168', // @ digit '86-181206-94@216-8', // @ digit ]); }); test('for invalid check digit', () => { expectActionIssue(action, baseIssue, [ '861812069402163', '536498459191225', '454438576454552', '356741089396029', ]); }); }); }); ================================================ FILE: library/src/actions/imei/imei.ts ================================================ import { IMEI_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _isLuhnAlgo } from '../../utils/index.ts'; /** * IMEI issue interface. */ export interface ImeiIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'imei'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The validation function. */ readonly requirement: (input: string) => boolean; } /** * IMEI action interface. */ export interface ImeiAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'imei'; /** * The action reference. */ readonly reference: typeof imei; /** * The expected property. */ readonly expects: null; /** * The validation function. */ readonly requirement: (input: string) => boolean; /** * The error message. */ readonly message: TMessage; } /** * Creates an [IMEI](https://en.wikipedia.org/wiki/International_Mobile_Equipment_Identity) validation action. * * Formats: * - AABBBBBBCCCCCCD * - AA-BBBBBB-CCCCCC-D * * @returns An IMEI action. */ export function imei(): ImeiAction; /** * Creates an [IMEI](https://en.wikipedia.org/wiki/International_Mobile_Equipment_Identity) validation action. * * Formats: * - AABBBBBBCCCCCCD * - AA-BBBBBB-CCCCCC-D * * @param message The error message. * * @returns An IMEI action. */ export function imei< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): ImeiAction; // @__NO_SIDE_EFFECTS__ export function imei( message?: ErrorMessage> ): ImeiAction> | undefined> { return { kind: 'validation', type: 'imei', reference: imei, async: false, expects: null, requirement(input) { return IMEI_REGEX.test(input) && _isLuhnAlgo(input); }, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement(dataset.value)) { _addIssue(this, 'IMEI', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/imei/index.ts ================================================ export * from './imei.ts'; ================================================ FILE: library/src/actions/includes/includes.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { includes, type IncludesAction, type IncludesIssue, } from './includes.ts'; describe('includes', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = IncludesAction; expectTypeOf(includes('foo')).toEqualTypeOf(); expectTypeOf( includes('foo', undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( includes('foo', 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( includes string>('foo', () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Input = ['foo', 123, true]; type Action = IncludesAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< IncludesIssue >(); }); }); }); ================================================ FILE: library/src/actions/includes/includes.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { includes, type IncludesAction, type IncludesIssue, } from './includes.ts'; describe('includes', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'includes', reference: includes, expects: '"foo"', requirement: 'foo', async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: IncludesAction = { ...baseAction, message: undefined, }; expect(includes('foo')).toStrictEqual(action); expect(includes('foo', undefined)).toStrictEqual(action); }); test('with string message', () => { const message = 'message'; expect(includes('foo', message)).toStrictEqual({ ...baseAction, message, } satisfies IncludesAction); }); test('with function message', () => { const message = () => 'message'; expect(includes('foo', message)).toStrictEqual({ ...baseAction, message, } satisfies IncludesAction); }); }); describe('should return dataset without issues', () => { const action = includes('foo'); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid strings', () => { expectNoActionIssue(action, ['foo', 'foobar', '123foo']); }); test('for valid arrays', () => { expectNoActionIssue(action, [ ['foo'], [123, 'foo'], [null, 123, 'foo', true, 'foo'], ]); }); }); describe('should return dataset with issues', () => { const action = includes('foo', 'message'); const baseIssue: Omit< IncludesIssue, 'input' | 'received' > = { kind: 'validation', type: 'includes', expected: '"foo"', message: 'message', requirement: 'foo', }; test('for invalid strings', () => { expectActionIssue( action, baseIssue, ['', 'fo', 'fobar', '123fo'], () => '!"foo"' ); }); test('for invalid arrays', () => { expectActionIssue( action, baseIssue, [[], ['fo'], [123, 'fobar'], [null, 123, true]], () => '!"foo"' ); }); }); }); ================================================ FILE: library/src/actions/includes/includes.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _stringify } from '../../utils/index.ts'; import type { ContentInput, ContentRequirement } from '../types.ts'; /** * Includes issue interface. */ export interface IncludesIssue< TInput extends ContentInput, TRequirement extends ContentRequirement, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'includes'; /** * The expected property. */ readonly expected: string; /** * The content to be included. */ readonly requirement: TRequirement; } /** * Includes action interface. */ export interface IncludesAction< TInput extends ContentInput, TRequirement extends ContentRequirement, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'includes'; /** * The action reference. */ readonly reference: typeof includes; /** * The expected property. */ readonly expects: string; /** * The content to be included. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates an includes validation action. * * @param requirement The content to be included. * * @returns An includes action. */ export function includes< TInput extends ContentInput, const TRequirement extends ContentRequirement, >(requirement: TRequirement): IncludesAction; /** * Creates an includes validation action. * * @param requirement The content to be included. * @param message The error message. * * @returns An includes action. */ export function includes< TInput extends ContentInput, const TRequirement extends ContentRequirement, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): IncludesAction; // @__NO_SIDE_EFFECTS__ export function includes( requirement: ContentRequirement, message?: ErrorMessage< IncludesIssue> > ): IncludesAction< ContentInput, ContentRequirement, | ErrorMessage>> | undefined > { const expects = _stringify(requirement); return { kind: 'validation', type: 'includes', reference: includes, async: false, expects, requirement, message, '~run'(dataset, config) { // @ts-expect-error if (dataset.typed && !dataset.value.includes(this.requirement)) { _addIssue(this, 'content', dataset, config, { received: `!${expects}`, }); } return dataset; }, }; } ================================================ FILE: library/src/actions/includes/index.ts ================================================ export * from './includes.ts'; ================================================ FILE: library/src/actions/index.ts ================================================ export * from './args/index.ts'; export * from './await/index.ts'; export * from './base64/index.ts'; export * from './bic/index.ts'; export * from './brand/index.ts'; export * from './bytes/index.ts'; export * from './check/index.ts'; export * from './checkItems/index.ts'; export * from './creditCard/index.ts'; export * from './cuid2/index.ts'; export * from './decimal/index.ts'; export * from './description/index.ts'; export * from './digits/index.ts'; export * from './domain/index.ts'; export * from './email/index.ts'; export * from './emoji/index.ts'; export * from './empty/index.ts'; export * from './endsWith/index.ts'; export * from './entries/index.ts'; export * from './everyItem/index.ts'; export * from './examples/index.ts'; export * from './excludes/index.ts'; export * from './filterItems/index.ts'; export * from './findItem/index.ts'; export * from './finite/index.ts'; export * from './flavor/index.ts'; export * from './graphemes/index.ts'; export * from './gtValue/index.ts'; export * from './guard/index.ts'; export * from './hash/index.ts'; export * from './hexadecimal/index.ts'; export * from './hexColor/index.ts'; export * from './imei/index.ts'; export * from './includes/index.ts'; export * from './integer/index.ts'; export * from './ip/index.ts'; export * from './ipv4/index.ts'; export * from './ipv6/index.ts'; export * from './isbn/index.ts'; export * from './isrc/index.ts'; export * from './isoDate/index.ts'; export * from './isoDateTime/index.ts'; export * from './isoTime/index.ts'; export * from './isoTimeSecond/index.ts'; export * from './isoTimestamp/index.ts'; export * from './isoWeek/index.ts'; export * from './jwsCompact/index.ts'; export * from './length/index.ts'; export * from './ltValue/index.ts'; export * from './mac/index.ts'; export * from './mac48/index.ts'; export * from './mac64/index.ts'; export * from './mapItems/index.ts'; export * from './maxBytes/index.ts'; export * from './maxEntries/index.ts'; export * from './maxGraphemes/index.ts'; export * from './maxLength/index.ts'; export * from './maxSize/index.ts'; export * from './maxValue/index.ts'; export * from './maxWords/index.ts'; export * from './metadata/index.ts'; export * from './mimeType/index.ts'; export * from './minBytes/index.ts'; export * from './minEntries/index.ts'; export * from './minGraphemes/index.ts'; export * from './minLength/index.ts'; export * from './minSize/index.ts'; export * from './minValue/index.ts'; export * from './minWords/index.ts'; export * from './multipleOf/index.ts'; export * from './nanoid/index.ts'; export * from './nonEmpty/index.ts'; export * from './normalize/index.ts'; export * from './notBytes/index.ts'; export * from './notEntries/index.ts'; export * from './notGraphemes/index.ts'; export * from './notLength/index.ts'; export * from './notSize/index.ts'; export * from './notValue/index.ts'; export * from './notValues/index.ts'; export * from './notWords/index.ts'; export * from './octal/index.ts'; export * from './parseBoolean/index.ts'; export * from './parseJson/index.ts'; export * from './partialCheck/index.ts'; export * from './rawCheck/index.ts'; export * from './rawTransform/index.ts'; export * from './readonly/index.ts'; export * from './reduceItems/index.ts'; export * from './regex/index.ts'; export * from './returns/index.ts'; export * from './rfcEmail/index.ts'; export * from './safeInteger/index.ts'; export * from './size/index.ts'; export * from './slug/index.ts'; export * from './someItem/index.ts'; export * from './sortItems/index.ts'; export * from './startsWith/index.ts'; export * from './stringifyJson/index.ts'; export * from './title/index.ts'; export * from './toBigint/index.ts'; export * from './toBoolean/index.ts'; export * from './toDate/index.ts'; export * from './toLowerCase/index.ts'; export * from './toMaxValue/index.ts'; export * from './toMinValue/index.ts'; export * from './toNumber/index.ts'; export * from './toString/index.ts'; export * from './toUpperCase/index.ts'; export * from './transform/index.ts'; export * from './trim/index.ts'; export * from './trimEnd/index.ts'; export * from './trimStart/index.ts'; export * from './types.ts'; export * from './ulid/index.ts'; export * from './url/index.ts'; export * from './uuid/index.ts'; export * from './value/index.ts'; export * from './values/index.ts'; export * from './words/index.ts'; ================================================ FILE: library/src/actions/integer/index.ts ================================================ export * from './integer.ts'; ================================================ FILE: library/src/actions/integer/integer.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { integer, type IntegerAction, type IntegerIssue } from './integer.ts'; describe('integer', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = IntegerAction; expectTypeOf(integer()).toEqualTypeOf(); expectTypeOf(integer(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(integer('message')).toEqualTypeOf< IntegerAction >(); }); test('with function message', () => { expectTypeOf(integer(() => 'message')).toEqualTypeOf< IntegerAction string> >(); }); }); describe('should infer correct types', () => { type Action = IntegerAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/integer/integer.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { NumberIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { integer, type IntegerAction, type IntegerIssue } from './integer.ts'; describe('integer', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'integer', reference: integer, expects: null, requirement: expect.any(Function), async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: IntegerAction = { ...baseAction, message: undefined, }; expect(integer()).toStrictEqual(action); expect(integer(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(integer('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies IntegerAction); }); test('with function message', () => { const message = () => 'message'; expect(integer(message)).toStrictEqual({ ...baseAction, message, } satisfies IntegerAction); }); }); describe('should return dataset without issues', () => { const action = integer(); test('for untyped inputs', () => { const issues: [NumberIssue] = [ { kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for integer numbers', () => { expectNoActionIssue(action, [ 0, 123456789, -123456789, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER, ]); }); }); describe('should return dataset with issues', () => { const action = integer('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'integer', expected: null, message: 'message', requirement: expect.any(Function), }; test('for floating point numbers', () => { expectActionIssue(action, baseIssue, [0.1, 12.34, -1 / 3, Math.PI]); }); test('for infinite numbers', () => { expectActionIssue(action, baseIssue, [Infinity, -Infinity]); }); test('for not a number', () => { expectActionIssue(action, baseIssue, [NaN]); }); }); }); ================================================ FILE: library/src/actions/integer/integer.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Integer issue interface. */ export interface IntegerIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'integer'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `${number}`; /** * The validation function. */ readonly requirement: (input: number) => boolean; } /** * Integer action interface. */ export interface IntegerAction< TInput extends number, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'integer'; /** * The action reference. */ readonly reference: typeof integer; /** * The expected property. */ readonly expects: null; /** * The validation function. */ readonly requirement: (input: number) => boolean; /** * The error message. */ readonly message: TMessage; } /** * Creates an [integer](https://en.wikipedia.org/wiki/Integer) validation action. * * @returns An integer action. */ export function integer(): IntegerAction< TInput, undefined >; /** * Creates an [integer](https://en.wikipedia.org/wiki/Integer) validation action. * * @param message The error message. * * @returns An integer action. */ export function integer< TInput extends number, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): IntegerAction; // @__NO_SIDE_EFFECTS__ export function integer( message?: ErrorMessage> ): IntegerAction> | undefined> { return { kind: 'validation', type: 'integer', reference: integer, async: false, expects: null, requirement: Number.isInteger, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement(dataset.value)) { _addIssue(this, 'integer', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/ip/index.ts ================================================ export * from './ip.ts'; ================================================ FILE: library/src/actions/ip/ip.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { ip, type IpAction, type IpIssue } from './ip.ts'; describe('ip', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = IpAction; expectTypeOf(ip()).toEqualTypeOf(); expectTypeOf(ip(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(ip('message')).toEqualTypeOf< IpAction >(); }); test('with function message', () => { expectTypeOf(ip string>(() => 'message')).toEqualTypeOf< IpAction string> >(); }); }); describe('should infer correct types', () => { type Action = IpAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/ip/ip.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { IP_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { ip, type IpAction, type IpIssue } from './ip.ts'; // TODO: Improve tests to cover all possible scenarios based on the regex used. describe('ip', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'ip', reference: ip, expects: null, requirement: IP_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: IpAction = { ...baseAction, message: undefined, }; expect(ip()).toStrictEqual(action); expect(ip(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(ip('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies IpAction); }); test('with function message', () => { const message = () => 'message'; expect(ip(message)).toStrictEqual({ ...baseAction, message, } satisfies IpAction); }); }); describe('should return dataset without issues', () => { const action = ip(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for IPv4 address', () => { expectNoActionIssue(action, [ '192.168.1.1', '127.0.0.1', '0.0.0.0', '255.255.255.255', ]); }); test('for IPv6 address', () => { expectNoActionIssue(action, [ '2001:0db8:85a3:0000:0000:8a2e:0370:7334', 'FE80:0000:0000:0000:0202:B3FF:FE1E:8329', 'fe80::1ff:fe23:4567:890a', '2001:db8:85a3:8d3:1319:8a2e:370:7348', ]); }); }); describe('should return dataset with issues', () => { const action = ip('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'ip', expected: null, message: 'message', requirement: IP_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for invalid IPv4 address', () => { expectActionIssue(action, baseIssue, [ '1', '-1.0.0.0', '0..0.0.0', '1234.0.0.0', '256.256.256.256', '1.2.3', '0.0.0.0.0', 'a.a.a.a', ]); }); test('for invalid IPv6 address', () => { expectActionIssue(action, baseIssue, [ 'd329:1be4:25b4:db47:a9d1:dc71:4926:992c:14af', 'd5e7:7214:2b78::3906:85e6:53cc:709:32ba', '8f69::c757:395e:976e::3441', '54cb::473f:d516:0.255.256.22', '54cb::473f:d516:192.168.1', 'test:test:test:test:test:test:test:test', ]); }); }); }); ================================================ FILE: library/src/actions/ip/ip.ts ================================================ import { IP_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * IP issue interface. */ export interface IpIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'ip'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The IP regex. */ readonly requirement: RegExp; } /** * IP action interface. */ export interface IpAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'ip'; /** * The action reference. */ readonly reference: typeof ip; /** * The expected property. */ readonly expects: null; /** * The IP regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates an [IP address](https://en.wikipedia.org/wiki/IP_address) validation action. * * @returns An IP action. */ export function ip(): IpAction; /** * Creates an [IP address](https://en.wikipedia.org/wiki/IP_address) validation action. * * @param message The error message. * * @returns An IP action. */ export function ip< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): IpAction; // @__NO_SIDE_EFFECTS__ export function ip( message?: ErrorMessage> ): IpAction> | undefined> { return { kind: 'validation', type: 'ip', reference: ip, async: false, expects: null, requirement: IP_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'IP', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/ipv4/index.ts ================================================ export * from './ipv4.ts'; ================================================ FILE: library/src/actions/ipv4/ipv4.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { ipv4, type Ipv4Action, type Ipv4Issue } from './ipv4.ts'; describe('ipv4', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = Ipv4Action; expectTypeOf(ipv4()).toEqualTypeOf(); expectTypeOf(ipv4(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(ipv4('message')).toEqualTypeOf< Ipv4Action >(); }); test('with function message', () => { expectTypeOf(ipv4 string>(() => 'message')).toEqualTypeOf< Ipv4Action string> >(); }); }); describe('should infer correct types', () => { type Action = Ipv4Action; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/ipv4/ipv4.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { IPV4_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { ipv4, type Ipv4Action, type Ipv4Issue } from './ipv4.ts'; describe('ipv4', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'ipv4', reference: ipv4, expects: null, requirement: IPV4_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: Ipv4Action = { ...baseAction, message: undefined, }; expect(ipv4()).toStrictEqual(action); expect(ipv4(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(ipv4('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies Ipv4Action); }); test('with function message', () => { const message = () => 'message'; expect(ipv4(message)).toStrictEqual({ ...baseAction, message, } satisfies Ipv4Action); }); }); describe('should return dataset without issues', () => { const action = ipv4(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for IPv4 address', () => { expectNoActionIssue(action, [ '192.168.1.1', '127.0.0.1', '10.10.10.10', '90.90.90.90', '50.60.70.80', '100.100.100.100', '190.190.190.190', '150.150.150.150', '200.200.200.200', '240.240.240.240', '0.0.0.0', '9.9.9.9', '5.5.5.5', '250.250.250.250', '255.255.255.255', '19.19.19.19', '99.99.99.99', '59.69.79.89', '109.109.109.109', '199.199.199.199', '159.159.159.159', '209.209.209.209', '249.249.249.249', '15.15.15.15', '95.95.95.95', '55.65.75.85', '105.105.105.105', '195.195.195.195', '155.155.155.155', '205.205.205.205', '245.245.245.245', ]); }); }); describe('should return dataset with issues', () => { const action = ipv4('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'ipv4', expected: null, message: 'message', requirement: IPV4_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', ' ', '\n', '\t']); }); test('for invalid IPv4 address', () => { expectActionIssue(action, baseIssue, [ '1', '-1.0.0.0', '0..0.0.0', '1234.0.0.0', '1.2.3', '0.0.0.0.0', 'a.a.a.a', '+1.2.3.4', ' 0.0.0.0', '0.0.0.0 ', '0.0 0.0', '0-0-0-0', '00.00.00.00', '256.256.256.256', '-1.-1.-1.-1', '259.259.259.259', '09.09.09.09', '05.05.05.05', ]); }); test('for IPv6 address', () => { expectActionIssue(action, baseIssue, [ '2001:0db8:85a3:0000:0000:8a2e:0370:7334', 'FE80:0000:0000:0000:0202:B3FF:FE1E:8329', 'fe80::1ff:fe23:4567:890a', '2001:db8:85a3:8d3:1319:8a2e:370:7348', // IPv4-mapped IPv6 '::ffff:192.168.1.1', '::ffff:0.0.0.0', '::ffff:255.255.255.255', ]); }); }); }); ================================================ FILE: library/src/actions/ipv4/ipv4.ts ================================================ import { IPV4_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * IPv4 issue interface. */ export interface Ipv4Issue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'ipv4'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The IPv4 regex. */ readonly requirement: RegExp; } /** * IPv4 action interface. */ export interface Ipv4Action< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'ipv4'; /** * The action reference. */ readonly reference: typeof ipv4; /** * The expected property. */ readonly expects: null; /** * The IPv4 regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates an [IPv4](https://en.wikipedia.org/wiki/IPv4) address validation action. * * @returns An IPv4 action. */ export function ipv4(): Ipv4Action; /** * Creates an [IPv4](https://en.wikipedia.org/wiki/IPv4) address validation action. * * @param message The error message. * * @returns An IPv4 action. */ export function ipv4< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): Ipv4Action; // @__NO_SIDE_EFFECTS__ export function ipv4( message?: ErrorMessage> ): Ipv4Action> | undefined> { return { kind: 'validation', type: 'ipv4', reference: ipv4, async: false, expects: null, requirement: IPV4_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'IPv4', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/ipv6/index.ts ================================================ export * from './ipv6.ts'; ================================================ FILE: library/src/actions/ipv6/ipv6.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { ipv6, type Ipv6Action, type Ipv6Issue } from './ipv6.ts'; describe('ipv6', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = Ipv6Action; expectTypeOf(ipv6()).toEqualTypeOf(); expectTypeOf(ipv6(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(ipv6('message')).toEqualTypeOf< Ipv6Action >(); }); test('with function message', () => { expectTypeOf(ipv6 string>(() => 'message')).toEqualTypeOf< Ipv6Action string> >(); }); }); describe('should infer correct types', () => { type Action = Ipv6Action; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/ipv6/ipv6.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { IPV6_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { ipv6, type Ipv6Action, type Ipv6Issue } from './ipv6.ts'; // TODO: Improve tests to cover all possible scenarios based on the regex used. describe('ipv6', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'ipv6', reference: ipv6, expects: null, requirement: IPV6_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: Ipv6Action = { ...baseAction, message: undefined, }; expect(ipv6()).toStrictEqual(action); expect(ipv6(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(ipv6('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies Ipv6Action); }); test('with function message', () => { const message = () => 'message'; expect(ipv6(message)).toStrictEqual({ ...baseAction, message, } satisfies Ipv6Action); }); }); describe('should return dataset without issues', () => { const action = ipv6(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for IPv6 address', () => { expectNoActionIssue(action, [ '2001:0db8:85a3:0000:0000:8a2e:0370:7334', 'FE80:0000:0000:0000:0202:B3FF:FE1E:8329', 'fe80::1ff:fe23:4567:890a', '2001:db8:85a3:8d3:1319:8a2e:370:7348', ]); }); }); describe('should return dataset with issues', () => { const action = ipv6('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'ipv6', expected: null, message: 'message', requirement: IPV6_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for invalid IPv6 address', () => { expectActionIssue(action, baseIssue, [ 'd329:1be4:25b4:db47:a9d1:dc71:4926:992c:14af', 'd5e7:7214:2b78::3906:85e6:53cc:709:32ba', '8f69::c757:395e:976e::3441', '54cb::473f:d516:0.255.256.22', '54cb::473f:d516:192.168.1', 'test:test:test:test:test:test:test:test', ]); }); test('for IPv4 address', () => { expectActionIssue(action, baseIssue, [ '192.168.1.1', '127.0.0.1', '0.0.0.0', '255.255.255.255', ]); }); }); }); ================================================ FILE: library/src/actions/ipv6/ipv6.ts ================================================ import { IPV6_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * IPv6 issue interface. */ export interface Ipv6Issue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'ipv6'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The IPv6 regex. */ readonly requirement: RegExp; } /** * IPv6 action interface. */ export interface Ipv6Action< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'ipv6'; /** * The action reference. */ readonly reference: typeof ipv6; /** * The expected property. */ readonly expects: null; /** * The IPv6 regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates an [IPv6](https://en.wikipedia.org/wiki/IPv6) address validation action. * * @returns An IPv6 action. */ export function ipv6(): Ipv6Action; /** * Creates an [IPv6](https://en.wikipedia.org/wiki/IPv6) address validation action. * * @param message The error message. * * @returns An IPv6 action. */ export function ipv6< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): Ipv6Action; // @__NO_SIDE_EFFECTS__ export function ipv6( message?: ErrorMessage> ): Ipv6Action> | undefined> { return { kind: 'validation', type: 'ipv6', reference: ipv6, async: false, expects: null, requirement: IPV6_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'IPv6', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/isbn/index.ts ================================================ export * from './isbn.ts'; ================================================ FILE: library/src/actions/isbn/isbn.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { isbn, type IsbnAction, type IsbnIssue } from './isbn.ts'; describe('isbn', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = IsbnAction; expectTypeOf(isbn()).toEqualTypeOf(); expectTypeOf(isbn(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(isbn('message')).toEqualTypeOf< IsbnAction >(); }); test('with function message', () => { expectTypeOf(isbn string>(() => 'message')).toEqualTypeOf< IsbnAction string> >(); }); }); describe('should infer correct types', () => { type Action = IsbnAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/isbn/isbn.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { isbn, type IsbnAction, type IsbnIssue } from './isbn.ts'; describe('ISBN', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'isbn', reference: isbn, expects: null, requirement: expect.any(Function), async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: IsbnAction = { ...baseAction, message: undefined, }; expect(isbn()).toStrictEqual(action); expect(isbn(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(isbn('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies IsbnAction); }); test('with function message', () => { const message = () => 'message'; expect(isbn(message)).toStrictEqual({ ...baseAction, message, } satisfies IsbnAction); }); }); describe('should return dataset without issues', () => { const action = isbn(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for ISBN-10', () => { expectNoActionIssue(action, [ '4873118735', '4-87311-873-5', '4 87311 873 5', '020530902X', '0-205-30902-X', '0471958697', // check digit 0 '0-306 40615-2', // mixed separators ]); }); test('for ISBN-13', () => { expectNoActionIssue(action, [ '978-4873118734', '9784873118734', '978-4-87311-873-4', '978 4 87311 873 4', '9790000000001', // 979 prefix '9791843123391', // 979 prefix '9783161484100', // check digit 0 '978-0 306 40615-7', // mixed separators ]); }); }); describe('should return dataset with issues', () => { const action = isbn('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'isbn', expected: null, message: 'message', requirement: expect.any(Function), }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for ISBN-10', () => { expectActionIssue(action, baseIssue, [ '4873118736', // invalid check digit '4 87311 873 6', // invalid check digit '020530902x', // lowercase 'x' '020530902 x', // lowercase 'x' '020530902', // too short '020530902XX', // too long 'X234567890', // X in wrong position '12345X7890', // X in middle ]); }); test('for ISBN-13', () => { expectActionIssue(action, baseIssue, [ '9784873118735', // invalid check digit '978 4873118735', // invalid check digit '978487311873', // too short '97848731187345', // too long '978030640615X', // X not allowed '9770000000001', // invalid prefix '9800000000002', // invalid prefix ]); }); test('for other invalid formats', () => { expectActionIssue(action, baseIssue, [ 'abc1234567890', // letters '978abc0000000', // letters in ISBN-13 '12345', // too short for both '97804739123456', // too long (14 digits) ]); }); }); }); ================================================ FILE: library/src/actions/isbn/isbn.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import { _isIsbn10, _isIsbn13 } from './utils/index.ts'; /** * ISBN issue interface. */ export interface IsbnIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'isbn'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The validation function. */ readonly requirement: (input: string) => boolean; } /** * ISBN action interface. */ export interface IsbnAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'isbn'; /** * The action reference. */ readonly reference: typeof isbn; /** * The expected property. */ readonly expects: null; /** * The validation function. */ readonly requirement: (input: string) => boolean; /** * The error message. */ readonly message: TMessage; } /** * ISBN separator regex. */ const ISBN_SEPARATOR_REGEX = /[- ]/gu; /** * ISBN-10 detection regex. */ const ISBN_10_DETECTION_REGEX = /^\d{9}[\dX]$/u; /** * ISBN-13 detection regex. */ const ISBN_13_DETECTION_REGEX = /^\d{13}$/u; /** * Creates an [ISBN](https://en.wikipedia.org/wiki/ISBN) action. * * @returns An ISBN action. * * @beta */ export function isbn(): IsbnAction; /** * Creates an [ISBN](https://en.wikipedia.org/wiki/ISBN) action. * * @param message The error message. * * @returns An ISBN action. * * @beta */ export function isbn< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): IsbnAction; // @__NO_SIDE_EFFECTS__ export function isbn( message?: ErrorMessage> ): IsbnAction> | undefined> { return { kind: 'validation', type: 'isbn', reference: isbn, async: false, expects: null, requirement(input) { const replacedInput = input.replace(ISBN_SEPARATOR_REGEX, ''); if (ISBN_10_DETECTION_REGEX.test(replacedInput)) { return _isIsbn10(replacedInput); } else if (ISBN_13_DETECTION_REGEX.test(replacedInput)) { return _isIsbn13(replacedInput); } return false; }, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement(dataset.value)) { _addIssue(this, 'ISBN', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/isbn/utils/_isIsbn10.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { _isIsbn10 } from './_isIsbn10.ts'; describe('_isIsbn10', () => { test('should return true', () => { expect(_isIsbn10('0306406152')).toBe(true); expect(_isIsbn10('0451526538')).toBe(true); expect(_isIsbn10('0007149689')).toBe(true); expect(_isIsbn10('043942089X')).toBe(true); expect(_isIsbn10('097522980X')).toBe(true); expect(_isIsbn10('0684843285')).toBe(true); expect(_isIsbn10('1566199093')).toBe(true); }); test('should return false', () => { expect(_isIsbn10('0306406153')).toBe(false); expect(_isIsbn10('0451526539')).toBe(false); expect(_isIsbn10('0007149680')).toBe(false); expect(_isIsbn10('0439420891')).toBe(false); expect(_isIsbn10('0975229801')).toBe(false); expect(_isIsbn10('0684843286')).toBe(false); expect(_isIsbn10('1566199094')).toBe(false); }); }); ================================================ FILE: library/src/actions/isbn/utils/_isIsbn10.ts ================================================ /** * [Validates an ISBN-10](https://en.wikipedia.org/wiki/ISBN#ISBN-10_check_digits). * * @param input The input value. * * @returns `true` if the input is a valid ISBN-10, `false` otherwise. * * @internal */ export function _isIsbn10(input: string): boolean { const digits = input.split('').map((c) => (c === 'X' ? 10 : parseInt(c))); let sum = 0; for (let i = 0; i < 10; i++) { sum += digits[i] * (10 - i); } return sum % 11 === 0; } ================================================ FILE: library/src/actions/isbn/utils/_isIsbn13.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { _isIsbn13 } from './_isIsbn13.ts'; describe('_isIsbn13', () => { test('should return true', () => { expect(_isIsbn13('9780306406157')).toBe(true); expect(_isIsbn13('9780451526533')).toBe(true); expect(_isIsbn13('9780007149681')).toBe(true); expect(_isIsbn13('9780439420891')).toBe(true); expect(_isIsbn13('9780975229804')).toBe(true); expect(_isIsbn13('9780684843285')).toBe(true); expect(_isIsbn13('9781566199094')).toBe(true); }); test('should return false', () => { expect(_isIsbn13('9780306406158')).toBe(false); expect(_isIsbn13('9780451526534')).toBe(false); expect(_isIsbn13('9780007149682')).toBe(false); expect(_isIsbn13('9780439420892')).toBe(false); expect(_isIsbn13('9780975229805')).toBe(false); expect(_isIsbn13('9780684843286')).toBe(false); expect(_isIsbn13('9781566199095')).toBe(false); }); }); ================================================ FILE: library/src/actions/isbn/utils/_isIsbn13.ts ================================================ /** * [Validates an ISBN-13](https://en.wikipedia.org/wiki/ISBN#ISBN-13_check_digit_calculation). * * @param input The input value. * * @returns `true` if the input is a valid ISBN-13, `false` otherwise. * * @internal */ export function _isIsbn13(input: string): boolean { const digits = input.split('').map((c) => parseInt(c)); let sum = 0; for (let i = 0; i < 13; i++) { sum += digits[i] * (i % 2 === 0 ? 1 : 3); } return sum % 10 === 0; } ================================================ FILE: library/src/actions/isbn/utils/index.ts ================================================ export * from './_isIsbn10.ts'; export * from './_isIsbn13.ts'; ================================================ FILE: library/src/actions/isoDate/index.ts ================================================ export * from './isoDate.ts'; ================================================ FILE: library/src/actions/isoDate/isoDate.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { isoDate, type IsoDateAction, type IsoDateIssue } from './isoDate.ts'; describe('isoDate', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = IsoDateAction; expectTypeOf(isoDate()).toEqualTypeOf(); expectTypeOf( isoDate(undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(isoDate('message')).toEqualTypeOf< IsoDateAction >(); }); test('with function message', () => { expectTypeOf( isoDate string>(() => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = IsoDateAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/isoDate/isoDate.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { ISO_DATE_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue } from '../../vitest/expectActionIssue.ts'; import { expectNoActionIssue } from '../../vitest/expectNoActionIssue.ts'; import { isoDate, type IsoDateAction, type IsoDateIssue } from './isoDate.ts'; describe('isoDate', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'iso_date', reference: isoDate, expects: null, requirement: ISO_DATE_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: IsoDateAction = { ...baseAction, message: undefined, }; expect(isoDate()).toStrictEqual(action); expect(isoDate(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(isoDate('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies IsoDateAction); }); test('with function message', () => { const message = () => 'message'; expect(isoDate(message)).toStrictEqual({ ...baseAction, message, } satisfies IsoDateAction); }); }); describe('should return dataset without issues', () => { const action = isoDate(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid ISO dates', () => { expectNoActionIssue(action, ['0000-01-01', '9999-12-31', '2024-05-06']); }); }); describe('should return dataset with issues', () => { const action = isoDate('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'iso_date', expected: null, message: 'message', requirement: ISO_DATE_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for blank spaces', () => { expectActionIssue(action, baseIssue, [ ' 0000-01-01', '0000-01-01 ', ' 0000-01-01 ', ]); }); test('for missing separator', () => { expectActionIssue(action, baseIssue, [ '0000-0101', '000001-01', '00000101', ]); }); test('for double separators', () => { expectActionIssue(action, baseIssue, [ '0000--01-01', '0000-01--01', '0000--01--01', ]); }); test('for wrong separators', () => { expectActionIssue(action, baseIssue, [ '0000 01 01', '0000_01_01', '0000/01/01', '0000–01–01', '0000:01:01', ]); }); test('for invalid year', () => { expectActionIssue(action, baseIssue, [ '-01-01', // missing digits '0-01-01', // 1 digit '00-01-01', // 2 digit '000-01-01', // 3 digits '00000-01-01', // 5 digits ]); }); test('for invalid month', () => { expectActionIssue(action, baseIssue, [ '0000-01', // missing digits '0000-1-01', // 1 digit '0000-010-01', // 3 digits '0000-00-01', // 00 '0000-13-01', // 13 '0000-99-01', // 99 ]); }); test('for invalid day', () => { expectActionIssue(action, baseIssue, [ '0000-01', // missing digits '0000-01-1', // 1 digit '0000-01-010', // 3 digits '0000-01-00', // 00 '0000-01-32', // 32 '0000-01-99', // 99 ]); }); }); }); ================================================ FILE: library/src/actions/isoDate/isoDate.ts ================================================ import { ISO_DATE_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * ISO date issue interface. */ export interface IsoDateIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'iso_date'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The ISO date regex. */ readonly requirement: RegExp; } /** * ISO date action interface. */ export interface IsoDateAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'iso_date'; /** * The action reference. */ readonly reference: typeof isoDate; /** * The expected property. */ readonly expects: null; /** * The ISO date regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates an [ISO date](https://en.wikipedia.org/wiki/ISO_8601) validation action. * * Format: yyyy-mm-dd * * Hint: The regex used cannot validate the maximum number of days based on * year and month. For example, "2023-06-31" is valid although June has only * 30 days. * * @returns An ISO date action. */ export function isoDate(): IsoDateAction< TInput, undefined >; /** * Creates an [ISO date](https://en.wikipedia.org/wiki/ISO_8601) validation action. * * Format: yyyy-mm-dd * * Hint: The regex used cannot validate the maximum number of days based on * year and month. For example, "2023-06-31" is valid although June has only * 30 days. * * @param message The error message. * * @returns An ISO date action. */ export function isoDate< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): IsoDateAction; // @__NO_SIDE_EFFECTS__ export function isoDate( message?: ErrorMessage> ): IsoDateAction> | undefined> { return { kind: 'validation', type: 'iso_date', reference: isoDate, async: false, expects: null, requirement: ISO_DATE_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'date', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/isoDateTime/index.ts ================================================ export * from './isoDateTime.ts'; ================================================ FILE: library/src/actions/isoDateTime/isoDateTime.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { isoDateTime, type IsoDateTimeAction, type IsoDateTimeIssue, } from './isoDateTime.ts'; describe('isoDateTime', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = IsoDateTimeAction; expectTypeOf(isoDateTime()).toEqualTypeOf(); expectTypeOf( isoDateTime(undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(isoDateTime('message')).toEqualTypeOf< IsoDateTimeAction >(); }); test('with function message', () => { expectTypeOf( isoDateTime string>(() => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = IsoDateTimeAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< IsoDateTimeIssue >(); }); }); }); ================================================ FILE: library/src/actions/isoDateTime/isoDateTime.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { ISO_DATE_TIME_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue } from '../../vitest/expectActionIssue.ts'; import { expectNoActionIssue } from '../../vitest/expectNoActionIssue.ts'; import { isoDateTime, type IsoDateTimeAction, type IsoDateTimeIssue, } from './isoDateTime.ts'; describe('isoDateTime', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'iso_date_time', reference: isoDateTime, expects: null, requirement: ISO_DATE_TIME_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: IsoDateTimeAction = { ...baseAction, message: undefined, }; expect(isoDateTime()).toStrictEqual(action); expect(isoDateTime(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(isoDateTime('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies IsoDateTimeAction); }); test('with function message', () => { const message = () => 'message'; expect(isoDateTime(message)).toStrictEqual({ ...baseAction, message, } satisfies IsoDateTimeAction); }); }); describe('should return dataset without issues', () => { const action = isoDateTime(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for normal date times', () => { expectNoActionIssue(action, [ '0000-01-01T00:00', '9999-12-31T23:59', '2023-07-11T19:34', ]); }); test('for space as separator', () => { expectNoActionIssue(action, [ '0000-01-01 00:00', '2023-07-11 17:26', '9999-12-31 23:59', ]); }); }); describe('should return dataset with issues', () => { const action = isoDateTime('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'iso_date_time', expected: null, message: 'message', requirement: ISO_DATE_TIME_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for blank spaces', () => { expectActionIssue(action, baseIssue, [ ' 0000-01-01T00:00', '0000-01-01T00:00 ', ' 0000-01-01T00:00 ', ]); }); test('for missing separators', () => { expectActionIssue(action, baseIssue, [ '000001-01T00:00', '0000-0101T00:00', '0000-01-0100:00', '0000-01-01T0000', ]); }); test('for wrong separators', () => { expectActionIssue(action, baseIssue, [ // Date separators '0000 01 01T00:00', '0000–01–01T00:00', '0000/01/01T00:00', '0000_01_01T00:00', '0000:01:01T00:00', // Date/time delimiter '0000-01-01A00:00', '0000-01-01U00:00', '0000-01-01Z00:00', '0000-01-01_00:00', '0000-01-01-00:00', // Time separators '0000-01-01T00 00', '0000-01-01T00-00', '0000-01-01T00_00', '0000-01-01T00–00', '0000-01-01T00/00', '0000-01-01T00.00', ]); }); test('for invalid year', () => { expectActionIssue(action, baseIssue, [ '-01-01T00:00', // missing digits '0-01-01T00:00', // 1 digit '00-01-01T00:00', // 2 digit '000-01-01T00:00', // 3 digits '00000-01-01T00:00', // 5 digits ]); }); test('for invalid month', () => { expectActionIssue(action, baseIssue, [ '0000-01T00:00', // missing digits '0000-1-01T00:00', // 1 digit '0000-010-01T00:00', // 3 digits '0000-00-01T00:00', // 00 '0000-13-01T00:00', // 13 '0000-99-01T00:00', // 99 ]); }); test('for invalid day', () => { expectActionIssue(action, baseIssue, [ '0000-01T00:00', // missing digits '0000-01-1T00:00', // 1 digit '0000-01-010T00:00', // 3 digits '0000-01-00T00:00', // 00 '0000-01-32T00:00', // 32 '0000-01-99T00:00', // 99 ]); }); test('for invalid hour', () => { expectActionIssue(action, baseIssue, [ '0000-01-01T:00', // missing digits '0000-01-01T00', // missing digits '0000-01-01T0:00', // 1 digit '0000-01-01T000:00', // 3 digits '0000-01-01T24:00', // 24 '0000-01-01T99:00', // 99 ]); }); test('for invalid minute', () => { expectActionIssue(action, baseIssue, [ '0000-01-01T00', // missing digits '0000-01-01T00:0', // 1 digit '0000-01-01T00:000', // 3 digits '0000-01-01T00:60', // 60 '0000-01-01T00:99', // 99 ]); }); }); }); ================================================ FILE: library/src/actions/isoDateTime/isoDateTime.ts ================================================ import { ISO_DATE_TIME_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * ISO date time issue interface. */ export interface IsoDateTimeIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'iso_date_time'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The ISO date time regex. */ readonly requirement: RegExp; } /** * ISO date time action interface. */ export interface IsoDateTimeAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'iso_date_time'; /** * The action reference. */ readonly reference: typeof isoDateTime; /** * The expected property. */ readonly expects: null; /** * The ISO date time regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates an [ISO date time](https://en.wikipedia.org/wiki/ISO_8601) validation action. * * Format: yyyy-mm-ddThh:mm * * Hint: The regex used cannot validate the maximum number of days based on * year and month. For example, "2023-06-31T00:00" is valid although June has only * 30 days. * * Hint: The regex also allows a space as a separator between the date and time * parts instead of the "T" character. * * @returns An ISO date time action. */ export function isoDateTime(): IsoDateTimeAction< TInput, undefined >; /** * Creates an [ISO date time](https://en.wikipedia.org/wiki/ISO_8601) validation action. * * Format: yyyy-mm-ddThh:mm * * Hint: The regex used cannot validate the maximum number of days based on * year and month. For example, "2023-06-31T00:00" is valid although June has only * 30 days. * * Hint: The regex also allows a space as a separator between the date and time * parts instead of the "T" character. * * @param message The error message. * * @returns An ISO date time action. */ export function isoDateTime< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): IsoDateTimeAction; // @__NO_SIDE_EFFECTS__ export function isoDateTime( message?: ErrorMessage> ): IsoDateTimeAction< string, ErrorMessage> | undefined > { return { kind: 'validation', type: 'iso_date_time', reference: isoDateTime, async: false, expects: null, requirement: ISO_DATE_TIME_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'date-time', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/isoTime/index.ts ================================================ export * from './isoTime.ts'; ================================================ FILE: library/src/actions/isoTime/isoTime.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { isoTime, type IsoTimeAction, type IsoTimeIssue } from './isoTime.ts'; describe('isoTime', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = IsoTimeAction; expectTypeOf(isoTime()).toEqualTypeOf(); expectTypeOf( isoTime(undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(isoTime('message')).toEqualTypeOf< IsoTimeAction >(); }); test('with function message', () => { expectTypeOf( isoTime string>(() => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = IsoTimeAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/isoTime/isoTime.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { ISO_TIME_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue } from '../../vitest/expectActionIssue.ts'; import { expectNoActionIssue } from '../../vitest/expectNoActionIssue.ts'; import { isoTime, type IsoTimeAction, type IsoTimeIssue } from './isoTime.ts'; describe('isoTime', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'iso_time', reference: isoTime, expects: null, requirement: ISO_TIME_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: IsoTimeAction = { ...baseAction, message: undefined, }; expect(isoTime()).toStrictEqual(action); expect(isoTime(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(isoTime('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies IsoTimeAction); }); test('with function message', () => { const message = () => 'message'; expect(isoTime(message)).toStrictEqual({ ...baseAction, message, } satisfies IsoTimeAction); }); }); describe('should return dataset without issues', () => { const action = isoTime(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid ISO times', () => { expectNoActionIssue(action, ['00:00', '12:34', '23:59']); }); }); describe('should return dataset with issues', () => { const action = isoTime('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'iso_time', expected: null, message: 'message', requirement: ISO_TIME_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for blank spaces', () => { expectActionIssue(action, baseIssue, [' 00:00', '00:00 ', ' 00:00 ']); }); test('for missing separator', () => { expectActionIssue(action, baseIssue, ['0000', '1234', '2359']); }); test('for invalid separators', () => { expectActionIssue(action, baseIssue, [ '00 00', '00-00', '00_00', '00–00', '00/00', '00.00', ]); }); test('for mathematical signs', () => { expectActionIssue(action, baseIssue, ['+00:00', '-12:34', '+23:59']); }); test('for invalid hour', () => { expectActionIssue(action, baseIssue, [ ':00', // missing digits '0:00', // 1 digit '000:00', // 3 digits '24:00', // 24 '99:00', // 99 ]); }); test('for invalid minute', () => { expectActionIssue(action, baseIssue, [ '00:', // missing digits '00:0', // 1 digit '00:000', // 3 digits '00:60', // 60 '00:99', // 99 ]); }); }); }); ================================================ FILE: library/src/actions/isoTime/isoTime.ts ================================================ import { ISO_TIME_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * ISO time issue interface. */ export interface IsoTimeIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'iso_time'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The ISO time regex. */ readonly requirement: RegExp; } /** * ISO time action interface. */ export interface IsoTimeAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'iso_time'; /** * The action reference. */ readonly reference: typeof isoTime; /** * The expected property. */ readonly expects: null; /** * The ISO time regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates an [ISO time](https://en.wikipedia.org/wiki/ISO_8601) validation action. * * Format: hh:mm * * @returns An ISO time action. */ export function isoTime(): IsoTimeAction< TInput, undefined >; /** * Creates an [ISO time](https://en.wikipedia.org/wiki/ISO_8601) validation action. * * Format: hh:mm * * @param message The error message. * * @returns An ISO time action. */ export function isoTime< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): IsoTimeAction; // @__NO_SIDE_EFFECTS__ export function isoTime( message?: ErrorMessage> ): IsoTimeAction> | undefined> { return { kind: 'validation', type: 'iso_time', reference: isoTime, async: false, expects: null, requirement: ISO_TIME_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'time', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/isoTimeSecond/index.ts ================================================ export * from './isoTimeSecond.ts'; ================================================ FILE: library/src/actions/isoTimeSecond/isoTimeSecond.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { isoTimeSecond, type IsoTimeSecondAction, type IsoTimeSecondIssue, } from './isoTimeSecond.ts'; describe('isoTimeSecond', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = IsoTimeSecondAction; expectTypeOf(isoTimeSecond()).toEqualTypeOf(); expectTypeOf( isoTimeSecond(undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(isoTimeSecond('message')).toEqualTypeOf< IsoTimeSecondAction >(); }); test('with function message', () => { expectTypeOf( isoTimeSecond string>(() => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = IsoTimeSecondAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< IsoTimeSecondIssue >(); }); }); }); ================================================ FILE: library/src/actions/isoTimeSecond/isoTimeSecond.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { ISO_TIME_SECOND_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue } from '../../vitest/expectActionIssue.ts'; import { expectNoActionIssue } from '../../vitest/expectNoActionIssue.ts'; import { isoTimeSecond, type IsoTimeSecondAction, type IsoTimeSecondIssue, } from './isoTimeSecond.ts'; describe('isoTimeSecond', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'iso_time_second', reference: isoTimeSecond, expects: null, requirement: ISO_TIME_SECOND_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: IsoTimeSecondAction = { ...baseAction, message: undefined, }; expect(isoTimeSecond()).toStrictEqual(action); expect(isoTimeSecond(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(isoTimeSecond('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies IsoTimeSecondAction); }); test('with function message', () => { const message = () => 'message'; expect(isoTimeSecond(message)).toStrictEqual({ ...baseAction, message, } satisfies IsoTimeSecondAction); }); }); describe('should return dataset without issues', () => { const action = isoTimeSecond(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid ISO time seconds', () => { expectNoActionIssue(action, ['00:00:00', '12:34:56', '23:59:59']); }); }); describe('should return dataset with issues', () => { const action = isoTimeSecond('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'iso_time_second', expected: null, message: 'message', requirement: ISO_TIME_SECOND_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for blank spaces', () => { expectActionIssue(action, baseIssue, [ ' 00:00:00', '00:00:00 ', ' 00:00:00 ', ]); }); test('for missing separators', () => { expectActionIssue(action, baseIssue, ['0000:00', '00:0000', '000000']); }); test('for double separators', () => { expectActionIssue(action, baseIssue, [ '00::00:00', '00:00::00', '00::00::00', ]); }); test('for wrong separators', () => { expectActionIssue(action, baseIssue, [ '00 00 00', '00/00/00', '00H00M00', '00_00_00', '00.00.00', ]); }); test('for mathematical signs', () => { expectActionIssue(action, baseIssue, [ '+00:00:00', '-12:34:56', '+23:59:59', ]); }); test('for invalid hour', () => { expectActionIssue(action, baseIssue, [ ':00:00', // missing digits '0:00:00', // 1 digit '000:00:00', // 3 digits '24:00:00', // 24 '99:00:00', // 99 ]); }); test('for invalid minute', () => { expectActionIssue(action, baseIssue, [ '00::00', // missing digits '00:0:00', // 1 digit '00:000:00', // 3 digits '00:60:00', // 60 '00:99:00', // 99 ]); }); test('for invalid second', () => { expectActionIssue(action, baseIssue, [ '00:00:', // missing digits '00:00:0', // 1 digit '00:00:000', // 3 digits '00:00:60', // 60 '00:00:99', // 99 ]); }); }); }); ================================================ FILE: library/src/actions/isoTimeSecond/isoTimeSecond.ts ================================================ import { ISO_TIME_SECOND_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * ISO time second issue interface. */ export interface IsoTimeSecondIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'iso_time_second'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The ISO time with seconds regex. */ readonly requirement: RegExp; } /** * ISO time second action interface. */ export interface IsoTimeSecondAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'iso_time_second'; /** * The action reference. */ readonly reference: typeof isoTimeSecond; /** * The expected property. */ readonly expects: null; /** * The ISO time second regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates an [ISO time second](https://en.wikipedia.org/wiki/ISO_8601) validation action. * * Format: hh:mm:ss * * @returns An ISO time second action. */ export function isoTimeSecond(): IsoTimeSecondAction< TInput, undefined >; /** * Creates an [ISO time second](https://en.wikipedia.org/wiki/ISO_8601) validation action. * * Format: hh:mm:ss * * @param message The error message. * * @returns An ISO time second action. */ export function isoTimeSecond< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): IsoTimeSecondAction; // @__NO_SIDE_EFFECTS__ export function isoTimeSecond( message?: ErrorMessage> ): IsoTimeSecondAction< string, ErrorMessage> | undefined > { return { kind: 'validation', type: 'iso_time_second', reference: isoTimeSecond, async: false, expects: null, requirement: ISO_TIME_SECOND_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'time-second', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/isoTimestamp/index.ts ================================================ export * from './isoTimestamp.ts'; ================================================ FILE: library/src/actions/isoTimestamp/isoTimestamp.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { IsoTimestampAction, IsoTimestampIssue } from './isoTimestamp.ts'; import { isoTimestamp } from './isoTimestamp.ts'; describe('isoTimestamp', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = IsoTimestampAction; expectTypeOf(isoTimestamp()).toEqualTypeOf(); expectTypeOf( isoTimestamp(undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(isoTimestamp('message')).toEqualTypeOf< IsoTimestampAction >(); }); test('with function message', () => { expectTypeOf( isoTimestamp string>(() => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = IsoTimestampAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< IsoTimestampIssue >(); }); }); }); ================================================ FILE: library/src/actions/isoTimestamp/isoTimestamp.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { ISO_TIMESTAMP_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue } from '../../vitest/expectActionIssue.ts'; import { expectNoActionIssue } from '../../vitest/expectNoActionIssue.ts'; import type { IsoTimestampAction, IsoTimestampIssue } from './isoTimestamp.ts'; import { isoTimestamp } from './isoTimestamp.ts'; describe('isoTimestamp', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'iso_timestamp', reference: isoTimestamp, expects: null, requirement: ISO_TIMESTAMP_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: IsoTimestampAction = { ...baseAction, message: undefined, }; expect(isoTimestamp()).toStrictEqual(action); expect(isoTimestamp(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(isoTimestamp('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies IsoTimestampAction); }); test('with function message', () => { const message = () => 'message'; expect(isoTimestamp(message)).toStrictEqual({ ...baseAction, message, } satisfies IsoTimestampAction); }); }); describe('should return dataset without issues', () => { const action = isoTimestamp(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for zero UTC offset', () => { expectNoActionIssue(action, [ '0000-01-01T00:00:00.000Z', '2023-07-11T17:26:27.243Z', '9999-12-31T23:59:59.999Z', ]); }); test('for specific UTC offset', () => { expectNoActionIssue(action, [ // '+hh:mm' '0000-01-01T00:00:00.000+00:00', '2023-07-11T17:26:27.243+12:34', '9999-12-31T23:59:59.999+23:59', // '+hhmm' '0000-01-01T00:00:00.000+0000', '2023-07-11T17:26:27.243+1234', '9999-12-31T23:59:59.999+2359', // '+hh' '0000-01-01T00:00:00.000+00', '2023-07-11T17:26:27.243+12', '9999-12-31T23:59:59.999+23', // '-hh:mm' '0000-01-01T00:00:00.000-00:00', '2023-07-11T17:26:27.243-12:34', '9999-12-31T23:59:59.999-23:59', // '-hhmm' '0000-01-01T00:00:00.000-0000', '2023-07-11T17:26:27.243-1234', '9999-12-31T23:59:59.999-2359', // '-hh' '0000-01-01T00:00:00.000-00', '2023-07-11T17:26:27.243-12', '9999-12-31T23:59:59.999-23', ]); }); test('for without milliseconds', () => { expectNoActionIssue(action, [ '0000-01-01T00:00:00Z', '2023-07-11T17:26:27Z', '9999-12-31T23:59:59Z', ]); }); test('for 9 milliseconds digits', () => { expectNoActionIssue(action, [ '0000-01-01T00:00:00.000000000Z', '2023-07-11T17:26:27.184618592Z', '9999-12-31T23:59:59.999999999Z', ]); }); test('for space as separator', () => { expectNoActionIssue(action, [ '0000-01-01 00:00:00.000Z', '2023-07-11 17:26:27.243Z', '9999-12-31 23:59:59.999Z', ]); }); test('for space before UTC offset', () => { expectNoActionIssue(action, [ // Space date/time separator + space before offset '0000-01-01 00:00:00.000 +00:00', '0000-01-01 00:00:00.000 -00:00', '2023-07-11 17:26:27.243 +0000', '2023-07-11 17:26:27.243 -0000', '9999-12-31 23:59:59.999 +00', '9999-12-31 23:59:59.999 -00', // T date/time separator + space before offset '0000-01-01T00:00:00.000 +00:00', '0000-01-01T00:00:00.000 -00:00', '2023-07-11T17:26:27.243 +0000', '2023-07-11T17:26:27.243 -0000', '9999-12-31T23:59:59.999 +00', '9999-12-31T23:59:59.999 -00', ]); }); }); describe('should return dataset with issues', () => { const action = isoTimestamp('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'iso_timestamp', expected: null, message: 'message', requirement: ISO_TIMESTAMP_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for blank spaces', () => { expectActionIssue(action, baseIssue, [ ' 0000-01-01T00:00:00.000Z', '0000-01-01T00:00:00.000Z ', ' 0000-01-01T00:00:00.000Z ', ]); }); test('for missing separators', () => { expectActionIssue(action, baseIssue, [ '000001-01T00:00:00.000Z', '0000-0101T00:00:00.000Z', '0000-01-0100:00:00.000Z', '0000-01-01T0000:00.000Z', '0000-01-01T00:0000.000Z', '0000-01-01T00:00:00000Z', '0000-01-01T00:00:00.000', '0000-01-01T00:00:00.00000:00', ]); }); test('for double separators', () => { expectActionIssue(action, baseIssue, [ '0000--01-01T00:00:00.000Z', '0000-01--01T00:00:00.000Z', '0000-01-01TT00:00:00.000Z', '0000-01-01T00::00:00.000Z', '0000-01-01T00:00::00.000Z', '0000-01-01T00:00:00..000Z', '0000-01-01T00:00:00.000ZZ', '0000-01-01T00:00:00.000++00:00', '0000-01-01T00:00:00.000--00:00', '0000-01-01T00:00:00.000+00::00', '0000-01-01T00:00:00.000 +00:00', '0000-01-01 00:00:00.000 +00:00', ]); }); test('for wrong separators', () => { expectActionIssue(action, baseIssue, [ // Date separators '0000 01 01T00:00:00.000Z', '0000–01–01T00:00:00.000Z', '0000/01/01T00:00:00.000Z', '0000_01_01T00:00:00.000Z', '0000:01:01T00:00:00.000Z', // Date/time delimiter '0000-01-01A00:00:00.000Z', '0000-01-01U00:00:00.000Z', '0000-01-01Z00:00:00.000Z', '0000-01-01_00:00:00.000Z', '0000-01-01-00:00:00.000Z', // Time separators '0000-01-01T00 00 00.000Z', '0000-01-01T00-00-00.000Z', '0000-01-01T00_00_00.000Z', '0000-01-01T00–00–00.000Z', '0000-01-01T00/00/00.000Z', '0000-01-01T00.00.00.000Z', // Milliseconds separator '0000-01-01T00:00:00 000Z', '0000-01-01T00:00:00-000Z', '0000-01-01T00:00:00_000Z', '0000-01-01T00:00:00–000Z', '0000-01-01T00:00:00/000Z', '0000-01-01T00:00:00:000Z', ]); }); test('for invalid year', () => { expectActionIssue(action, baseIssue, [ '-01-01T00:00:00.000Z', // missing digits '0-01-01T00:00:00.000Z', // 1 digit '00-01-01T00:00:00.000Z', // 2 digit '000-01-01T00:00:00.000Z', // 3 digits '00000-01-01T00:00:00.000Z', // 5 digits ]); }); test('for invalid month', () => { expectActionIssue(action, baseIssue, [ '0000-01T00:00:00.000Z', // missing digits '0000-1-01T00:00:00.000Z', // 1 digit '0000-010-01T00:00:00.000Z', // 3 digits '0000-00-01T00:00:00.000Z', // 00 '0000-13-01T00:00:00.000Z', // 13 '0000-99-01T00:00:00.000Z', // 99 ]); }); test('for invalid day', () => { expectActionIssue(action, baseIssue, [ '0000-01T00:00:00.000Z', // missing digits '0000-01-1T00:00:00.000Z', // 1 digit '0000-01-010T00:00:00.000Z', // 3 digits '0000-01-00T00:00:00.000Z', // 00 '0000-01-32T00:00:00.000Z', // 32 '0000-01-99T00:00:00.000Z', // 99 ]); }); test('for invalid hour', () => { expectActionIssue(action, baseIssue, [ '0000-01-01T:00:00.000Z', // missing digits '0000-01-01T00:00.000Z', // missing digits '0000-01-01T0:00:00.000Z', // 1 digit '0000-01-01T000:00:00.000Z', // 3 digits '0000-01-01T24:00:00.000Z', // 24 '0000-01-01T99:00:00.000Z', // 99 ]); }); test('for invalid minute', () => { expectActionIssue(action, baseIssue, [ '0000-01-01T00:00.000Z', // missing digits '0000-01-01T00:0:00.000Z', // 1 digit '0000-01-01T00:000:00.000Z', // 3 digits '0000-01-01T00:60:00.000Z', // 60 '0000-01-01T00:99:00.000Z', // 99 ]); }); test('for invalid second', () => { expectActionIssue(action, baseIssue, [ '0000-01-01T00:00:.000Z', // missing digits '0000-01-01T00:00.000Z', // missing digits '0000-01-01T00:00:0.000Z', // 1 digit '0000-01-01T00:00:000.000Z', // 3 digits '0000-01-01T00:00:60.000Z', // 60 '0000-01-01T00:00:99.000Z', // 99 ]); }); test('for invalid milliseconds', () => { expectActionIssue(action, baseIssue, [ '0000-01-01T00:00:00.Z', // 0 digits '0000-01-01T00:00:00.0000000000Z', // 10 digits ]); }); test('for missing offsets', () => { expectActionIssue(action, baseIssue, [ '0000-01-01T00:00:00.000', '0000-01-01T00:00:00.000+', '0000-01-01T00:00:00.000-', ]); }); test('for invalid hour offset', () => { expectActionIssue(action, baseIssue, [ '0000-01-01T00:00:00.000+:00', // missing digits '0000-01-01T00:00:00.000+0:00', // 1 digit '0000-01-01T00:00:00.000+000:00', // 3 digits '0000-01-01T00:00:00.000+24:00', // 24 '0000-01-01T00:00:00.000+2400', // 24 '0000-01-01T00:00:00.000+24', // 24 '0000-01-01T00:00:00.000+99:00', // 99 '0000-01-01T00:00:00.000+9900', // 99 '0000-01-01T00:00:00.000+99', // 99 ]); }); test('for invalid minute offset', () => { expectActionIssue(action, baseIssue, [ '0000-01-01T00:00:00.000+00:', // missing digits '0000-01-01T00:00:00.000+00:0', // 1 digit '0000-01-01T00:00:00.000+000', // 1 digit '0000-01-01T00:00:00.000+00:000', // 3 digits '0000-01-01T00:00:00.000+00000', // 3 digits '0000-01-01T00:00:00.000+00:60', // 60 '0000-01-01T00:00:00.000+0060', // 60 '0000-01-01T00:00:00.000+00:99', // 99 '0000-01-01T00:00:00.000+0099', // 99 ]); }); }); }); ================================================ FILE: library/src/actions/isoTimestamp/isoTimestamp.ts ================================================ import { ISO_TIMESTAMP_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * ISO timestamp issue interface. */ export interface IsoTimestampIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'iso_timestamp'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The ISO timestamp regex. */ readonly requirement: RegExp; } /** * ISO timestamp action interface. */ export interface IsoTimestampAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'iso_timestamp'; /** * The action reference. */ readonly reference: typeof isoTimestamp; /** * The expected property. */ readonly expects: null; /** * The ISO timestamp regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates an [ISO timestamp](https://en.wikipedia.org/wiki/ISO_8601) validation * action. * * Formats: * - yyyy-mm-ddThh:mm:ss.sssZ * - yyyy-mm-ddThh:mm:ss.sss±hh:mm * - yyyy-mm-ddThh:mm:ss.sss±hhmm * * Hint: To support timestamps with lower or higher accuracy, the millisecond * specification can be removed or contain up to 9 digits. * * Hint: The regex used cannot validate the maximum number of days based on * year and month. For example, "2023-06-31T00:00:00.000Z" is valid although * June has only 30 days. * * Hint: The regex also allows a space as a separator between the date and time * parts instead of the "T" character. * * Hint: The regex also allows a space before the UTC offset (e.g., " +00:00") * to support PostgreSQL's `timestamptz` output format. * * @returns An ISO timestamp action. */ export function isoTimestamp(): IsoTimestampAction< TInput, undefined >; /** * Creates an [ISO timestamp](https://en.wikipedia.org/wiki/ISO_8601) validation * action. * * Formats: * - yyyy-mm-ddThh:mm:ss.sssZ * - yyyy-mm-ddThh:mm:ss.sss±hh:mm * - yyyy-mm-ddThh:mm:ss.sss±hhmm * - yyyy-mm-ddThh:mm:ss.sss±hh * * Hint: To support timestamps with lower or higher accuracy, the millisecond * specification can be removed or contain up to 9 digits. * * Hint: The regex used cannot validate the maximum number of days based on * year and month. For example, "2023-06-31T00:00:00.000Z" is valid although * June has only 30 days. * * Hint: The regex also allows a space as a separator between the date and time * parts instead of the "T" character. * * Hint: The regex also allows a space before the UTC offset (e.g., " +00:00") * to support PostgreSQL's `timestamptz` output format. * * @param message The error message. * * @returns An ISO timestamp action. */ export function isoTimestamp< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): IsoTimestampAction; // @__NO_SIDE_EFFECTS__ export function isoTimestamp( message?: ErrorMessage> ): IsoTimestampAction< string, ErrorMessage> | undefined > { return { kind: 'validation', type: 'iso_timestamp', reference: isoTimestamp, async: false, expects: null, requirement: ISO_TIMESTAMP_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'timestamp', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/isoWeek/index.ts ================================================ export * from './isoWeek.ts'; ================================================ FILE: library/src/actions/isoWeek/isoWeek.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { isoWeek, type IsoWeekAction, type IsoWeekIssue } from './isoWeek.ts'; describe('isoWeek', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = IsoWeekAction; expectTypeOf(isoWeek()).toEqualTypeOf(); expectTypeOf( isoWeek(undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(isoWeek('message')).toEqualTypeOf< IsoWeekAction >(); }); test('with function message', () => { expectTypeOf( isoWeek string>(() => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = IsoWeekAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/isoWeek/isoWeek.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { ISO_WEEK_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue } from '../../vitest/expectActionIssue.ts'; import { expectNoActionIssue } from '../../vitest/expectNoActionIssue.ts'; import { isoWeek, type IsoWeekIssue as IsoWeek, type IsoWeekAction, } from './isoWeek.ts'; describe('isoWeek', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'iso_week', reference: isoWeek, expects: null, requirement: ISO_WEEK_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: IsoWeekAction = { ...baseAction, message: undefined, }; expect(isoWeek()).toStrictEqual(action); expect(isoWeek(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(isoWeek('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies IsoWeekAction); }); test('with function message', () => { const message = () => 'message'; expect(isoWeek(message)).toStrictEqual({ ...baseAction, message, } satisfies IsoWeekAction); }); }); describe('should return dataset without issues', () => { const action = isoWeek(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid ISO date times', () => { expectNoActionIssue(action, ['0000-W01', '2023-W29', '9999-W53']); }); }); describe('should return dataset with issues', () => { const action = isoWeek('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'iso_week', expected: null, message: 'message', requirement: ISO_WEEK_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for blank spaces', () => { expectActionIssue(action, baseIssue, [ ' 0000-W01', '0000-W01 ', ' 0000-W01 ', ]); }); test('for missing separators', () => { expectActionIssue(action, baseIssue, ['0000-01', '0000W01', '000001']); }); test('for wrong separators', () => { expectActionIssue(action, baseIssue, [ '0000- 01', '0000-A01', '0000-Z01', '0000-w01', '0000.W01', '0000–W01', '0000 W01', '0000/W01', '0000_W01', ]); }); test('for invalid year', () => { expectActionIssue(action, baseIssue, [ '-W01', // missing digits '0-W01', // 1 digit '00-W01', // 2 digit '000-W01', // 3 digits '00000-W01', // 5 digits ]); }); test('for invalid weeks', () => { expectActionIssue(action, baseIssue, [ '0000-W', // missing digits '0000-W0', // 1 digit '0000-W000', // 3 digits '0000-W00', // 00 '0000-W54', // 54 '0000-W99', // 99 ]); }); }); }); ================================================ FILE: library/src/actions/isoWeek/isoWeek.ts ================================================ import { ISO_WEEK_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * ISO week issue interface. */ export interface IsoWeekIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'iso_week'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The ISO week regex. */ readonly requirement: RegExp; } /** * ISO week action interface. */ export interface IsoWeekAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'iso_week'; /** * The action reference. */ readonly reference: typeof isoWeek; /** * The expected property. */ readonly expects: null; /** * The ISO week regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates an [ISO week](https://en.wikipedia.org/wiki/ISO_8601) validation action. * * Format: yyyy-Www * * Hint: The regex used cannot validate the maximum number of weeks based on * the year. For example, "2021W53" is valid although 2021 has only 52 weeks. * * @returns An ISO week action. */ export function isoWeek(): IsoWeekAction< TInput, undefined >; /** * Creates an [ISO week](https://en.wikipedia.org/wiki/ISO_8601) validation action. * * Format: yyyy-Www * * Hint: The regex used cannot validate the maximum number of weeks based on * the year. For example, "2021W53" is valid although 2021 has only 52 weeks. * * @param message The error message. * * @returns An ISO week action. */ export function isoWeek< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): IsoWeekAction; // @__NO_SIDE_EFFECTS__ export function isoWeek( message?: ErrorMessage> ): IsoWeekAction> | undefined> { return { kind: 'validation', type: 'iso_week', reference: isoWeek, async: false, expects: null, requirement: ISO_WEEK_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'week', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/isrc/index.ts ================================================ export * from './isrc.ts'; ================================================ FILE: library/src/actions/isrc/isrc.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { isrc, type IsrcAction, type IsrcIssue } from './isrc.ts'; describe('isrc', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = IsrcAction; expectTypeOf(isrc()).toEqualTypeOf(); expectTypeOf(isrc(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(isrc('message')).toEqualTypeOf< IsrcAction >(); }); test('with function message', () => { expectTypeOf(isrc string>(() => 'message')).toEqualTypeOf< IsrcAction string> >(); }); }); describe('should infer correct types', () => { type Action = IsrcAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/isrc/isrc.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { ISRC_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { isrc, type IsrcAction, type IsrcIssue } from './isrc.ts'; describe('isrc', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'isrc', reference: isrc, expects: null, requirement: ISRC_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: IsrcAction = { ...baseAction, message: undefined, }; expect(isrc()).toStrictEqual(action); expect(isrc(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(isrc('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies IsrcAction); }); test('with function message', () => { const message = () => 'message'; expect(isrc(message)).toStrictEqual({ ...baseAction, message, } satisfies IsrcAction); }); }); describe('should return dataset without issues', () => { const action = isrc(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid ISRC without separators', () => { expectNoActionIssue(action, [ 'DEU671703268', 'FRIDO2512641', 'GBBPW0700093', 'US2S70465020', ]); }); test('for valid ISRC with separators', () => { expectNoActionIssue(action, [ 'DE-U67-17-03268', 'FR-IDO-25-12641', 'GB-BPW-07-00093', 'US-2S7-04-65020', ]); }); }); describe('should return dataset with issues', () => { const action = isrc('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'isrc', expected: null, message: 'message', requirement: ISRC_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for blank spaces', () => { expectActionIssue(action, baseIssue, [ ' DE-U67-17-03268', 'DE-U67-17-03268 ', ' DE-U67-17-03268 ', ]); }); test('for missing separators', () => { expectActionIssue(action, baseIssue, [ 'DEU67-17-03268', 'DE-U6717-03268', 'DE-U67-1703268', ]); }); test('for double separators', () => { expectActionIssue(action, baseIssue, [ 'DE--U67-17-03268', 'DE-U67--17-03268', 'DE-U67-17--03268', 'DE--U67--17--03268', ]); }); test('for invalid separators', () => { expectActionIssue(action, baseIssue, [ 'DE U67 17 03268', 'DE/U67/17/03268', 'DE_U67_17_03268', 'DE–U67–17–03268', ]); }); test('for invalid fragment length', () => { expectActionIssue(action, baseIssue, [ 'D-U67-17-03268', // missing country code character 'DEU-U67-17-03268', // extra country code character 'DE-U6-17-03268', // missing registrant code character 'DE-U67x-17-03268', // extra registrant code character 'DE-U67-1-03268', // missing year digit 'DE-U67-170-03268', // extra year digit 'DE-U67-17-0326', // missing designation digit 'DE-U67-17-032680', // extra designation digit ]); }); test('for invalid fragments', () => { expectActionIssue(action, baseIssue, [ '0EU671703268', // Country Code-fragment '0E-U67-17-03268', // Country Code-fragment 'DEa671703268', // Registrant Code-fragment 'DE-a67-17-03268', // Registrant Code-fragment 'DEU67A703268', // Year of Reference-fragment 'DE-U67-A7-03268', // Year of Reference-fragment 'DEU6717A3268', // Designation Code-fragment 'DE-U67-17-A3268', // Designation Code-fragment ]); }); }); }); ================================================ FILE: library/src/actions/isrc/isrc.ts ================================================ import { ISRC_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * ISRC issue interface. */ export interface IsrcIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'isrc'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The ISRC regex. */ readonly requirement: RegExp; } /** * ISRC action interface. */ export interface IsrcAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'isrc'; /** * The action reference. */ readonly reference: typeof isrc; /** * The expected property. */ readonly expects: null; /** * The ISRC regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates an [ISRC](https://en.wikipedia.org/wiki/International_Standard_Recording_Code) validation action. * * Formats: * - CCXXXYYNNNNN * - CC-XXX-YY-NNNNN * * @returns An ISRC action. * * @beta */ export function isrc(): IsrcAction; /** * Creates an [ISRC](https://en.wikipedia.org/wiki/International_Standard_Recording_Code) validation action. * * @param message The error message. * * @returns An ISRC action. * * @beta */ export function isrc< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): IsrcAction; // @__NO_SIDE_EFFECTS__ export function isrc( message?: ErrorMessage> ): IsrcAction> | undefined> { return { kind: 'validation', type: 'isrc', reference: isrc, async: false, expects: null, requirement: ISRC_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'ISRC', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/jwsCompact/index.ts ================================================ export * from './jwsCompact.ts'; ================================================ FILE: library/src/actions/jwsCompact/jwsCompact.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { jwsCompact, type JwsCompactAction, type JwsCompactIssue, } from './jwsCompact.ts'; describe('jwsCompact', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = JwsCompactAction; expectTypeOf(jwsCompact()).toEqualTypeOf(); expectTypeOf( jwsCompact(undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(jwsCompact('message')).toEqualTypeOf< JwsCompactAction >(); }); test('with function message', () => { expectTypeOf( jwsCompact string>(() => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = JwsCompactAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< JwsCompactIssue >(); }); }); }); ================================================ FILE: library/src/actions/jwsCompact/jwsCompact.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { JWS_COMPACT_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { jwsCompact, type JwsCompactAction, type JwsCompactIssue, } from './jwsCompact.ts'; describe('jwsCompact', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'jws_compact', reference: jwsCompact, expects: null, requirement: JWS_COMPACT_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: JwsCompactAction = { ...baseAction, message: undefined, }; expect(jwsCompact()).toStrictEqual(action); expect(jwsCompact(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(jwsCompact('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies JwsCompactAction); }); test('with function message', () => { const message = () => 'message'; expect(jwsCompact(message)).toStrictEqual({ ...baseAction, message, } satisfies JwsCompactAction); }); }); describe('should return dataset without issues', () => { const action = jwsCompact(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid JWS compact strings', () => { expectNoActionIssue(action, [ 'ab.cd.ef', 'abc.def.ghi', 'abcd.efgh.ijkl', 'abcdef.ghijkl.mnopqr', 'ab_cd-.ef-gh_.ij_kl-', 'abcdefgh.ijklmnop.qrstuvwx', 'abcd.efgh.', ]); }); test('for empty payload segments', () => { expectNoActionIssue(action, ['abcd..ijkl', 'abcdef..']); }); }); describe('should return dataset with issues', () => { const action = jwsCompact('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'jws_compact', expected: null, message: 'message', requirement: JWS_COMPACT_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for missing segments', () => { expectActionIssue(action, baseIssue, ['abcd.efgh', 'segment.twopart']); }); test('for additional segments', () => { expectActionIssue(action, baseIssue, [ 'header.payload.signature.extra', 'a.b.c.d', ]); }); test('for invalid base64url segments', () => { expectActionIssue(action, baseIssue, [ 'a.a.a', 'ab=.cd.ef', 'abc==.def.ghi', 'abcd.efgh.ijkl==', ]); }); test('for blank spaces', () => { expectActionIssue(action, baseIssue, [ ' abcd.efgh.ijkl', 'abcd.efgh.ijkl ', 'abcd .efgh.ijkl', ]); }); test('for invalid characters', () => { expectActionIssue(action, baseIssue, [ 'abcd.efgh.ij@l', 'segment.twopart.si gnature', 'segment.twopart.si\\u00a9gnature', 'segment.twopart.si©gnature', ]); }); }); }); ================================================ FILE: library/src/actions/jwsCompact/jwsCompact.ts ================================================ import { JWS_COMPACT_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * JWS compact issue interface. * * @beta */ export interface JwsCompactIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'jws_compact'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The JWS compact regex. */ readonly requirement: RegExp; } /** * JWS compact action interface. * * @beta */ export interface JwsCompactAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'jws_compact'; /** * The action reference. */ readonly reference: typeof jwsCompact; /** * The expected property. */ readonly expects: null; /** * The JWS compact regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates a [JWS compact serialization](https://datatracker.ietf.org/doc/html/rfc7515#section-3.1) * validation action. * * Hint: This validation action only checks the three-part compact string shape * with unpadded Base64URL-like segments. It does not decode the segments, * verify the signature, or validate claims. * * @returns A JWS compact action. * * @beta */ export function jwsCompact(): JwsCompactAction< TInput, undefined >; /** * Creates a [JWS compact serialization](https://datatracker.ietf.org/doc/html/rfc7515#section-3.1) * validation action. * * Hint: This validation action only checks the three-part compact string shape * with unpadded Base64URL-like segments. It does not decode the segments, * verify the signature, or validate claims. * * @param message The error message. * * @returns A JWS compact action. * * @beta */ export function jwsCompact< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): JwsCompactAction; // @__NO_SIDE_EFFECTS__ export function jwsCompact( message?: ErrorMessage> ): JwsCompactAction> | undefined> { return { kind: 'validation', type: 'jws_compact', reference: jwsCompact, async: false, expects: null, requirement: JWS_COMPACT_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'JWS compact', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/length/index.ts ================================================ export * from './length.ts'; ================================================ FILE: library/src/actions/length/length.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { length, type LengthAction, type LengthIssue } from './length.ts'; describe('length', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = LengthAction; expectTypeOf(length(10)).toEqualTypeOf(); expectTypeOf( length(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(length(10, 'message')).toEqualTypeOf< LengthAction >(); }); test('with function message', () => { expectTypeOf( length string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Input = [1, 'two', { value: 'three' }]; type Action = LengthAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/length/length.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { length, type LengthAction, type LengthIssue } from './length.ts'; describe('length', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'length', reference: length, expects: '5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: LengthAction = { ...baseAction, message: undefined, }; expect(length(5)).toStrictEqual(action); expect(length(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(length(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies LengthAction); }); test('with function message', () => { const message = () => 'message'; expect(length(5, message)).toStrictEqual({ ...baseAction, message, } satisfies LengthAction); }); }); describe('should return dataset without issues', () => { const action = length(3); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid strings', () => { expectNoActionIssue(action, [ ' ', ' \n\n', '\n\n\t', 'abc', 'ABC', '123', 'あああ', // 'あ' is 3 bytes but the total length of the string is 3 '@#$', ]); }); test('for valid arrays', () => { expectNoActionIssue(action, [ [1, 2, 3], ['foo', 'bar', 'baz'], [1, null, undefined], [[1, 2, 3, 4], [5], [6, 7]], [{ value: 1 }, { value: 2 }, { value: 3 }], ['1', 2, { value: 3 }], ]); }); }); describe('should return dataset with issues', () => { const action = length(3, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'length', expected: '3', message: 'message', requirement: 3, }; test('for invalid strings', () => { expectActionIssue( action, baseIssue, [ '', ' ', ' ', '\n', '\n\t', 'あ', // 'あ' is 3 bytes 'ab', 'abcd', '1', '12', '1234', '@', '@#', '@#$%', ], (value) => `${value.length}` ); }); test('for invalid arrays', () => { expectActionIssue( action, baseIssue, [ [], [1], ['1', '2'], [1, '2', 3, '4'], [[1, 2, 3]], [[1, 2], ['3']], [{ 1: 'one', 2: 'two', 3: 'three' }], [[1], [2], null, [{ value: 3 }]], ], (value) => `${value.length}` ); }); }); }); ================================================ FILE: library/src/actions/length/length.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { LengthInput } from '../types.ts'; /** * Length issue interface. */ export interface LengthIssue< TInput extends LengthInput, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'length'; /** * The expected property. */ readonly expected: `${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The required length. */ readonly requirement: TRequirement; } /** * Length action interface. */ export interface LengthAction< TInput extends LengthInput, TRequirement extends number, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'length'; /** * The action reference. */ readonly reference: typeof length; /** * The expected property. */ readonly expects: `${TRequirement}`; /** * The required length. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a length validation action. * * @param requirement The required length. * * @returns A length action. */ export function length< TInput extends LengthInput, const TRequirement extends number, >(requirement: TRequirement): LengthAction; /** * Creates a length validation action. * * @param requirement The required length. * @param message The error message. * * @returns A length action. */ export function length< TInput extends LengthInput, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): LengthAction; // @__NO_SIDE_EFFECTS__ export function length( requirement: number, message?: ErrorMessage> ): LengthAction< LengthInput, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'length', reference: length, async: false, expects: `${requirement}`, requirement, message, '~run'(dataset, config) { if (dataset.typed && dataset.value.length !== this.requirement) { _addIssue(this, 'length', dataset, config, { received: `${dataset.value.length}`, }); } return dataset; }, }; } ================================================ FILE: library/src/actions/ltValue/index.ts ================================================ export * from './ltValue.ts'; ================================================ FILE: library/src/actions/ltValue/ltValue.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { ltValue, type LtValueAction, type LtValueIssue } from './ltValue.ts'; describe('ltValue', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = LtValueAction; expectTypeOf(ltValue(10)).toEqualTypeOf(); expectTypeOf( ltValue(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(ltValue(10, 'message')).toEqualTypeOf< LtValueAction >(); }); test('with function message', () => { expectTypeOf( ltValue string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = LtValueAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< LtValueIssue >(); }); }); }); ================================================ FILE: library/src/actions/ltValue/ltValue.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { NumberIssue } from '../../schemas/index.ts'; import { _stringify } from '../../utils/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { ltValue, type LtValueAction } from './ltValue.ts'; describe('ltValue', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'lt_value', reference: ltValue, expects: '<5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: LtValueAction = { ...baseAction, message: undefined, }; expect(ltValue(5)).toStrictEqual(action); expect(ltValue(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(ltValue(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies LtValueAction); }); test('with function message', () => { const message = () => 'message'; expect(ltValue(5, message)).toStrictEqual({ ...baseAction, message, } satisfies LtValueAction); }); }); describe('should return dataset without issues', () => { test('for untyped inputs', () => { const issues: [NumberIssue] = [ { kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', message: 'message', }, ]; expect( ltValue(1)['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues }); }); test('for valid bigints', () => { expectNoActionIssue(ltValue(10n), [-9999n, 0n, 9n]); }); test('for valid non-bigints', () => { expectNoActionIssue(ltValue(10n), [ '-10', '', ' ', '0', '9', ' 9 ', -10, 0, 9, -Infinity, -10.0, 0.0, 9.0, 9.5, false, true, new Date(-10), new Date(0), new Date(9), ]); expectNoActionIssue(ltValue(1n), [ '-1', '', ' ', ' 0 ', '0', -1, 0.0, 0, 0.5, -Infinity, false, new Date(-1), new Date(0), ]); expectNoActionIssue(ltValue(0n), [ '-1', ' -1 ', -0.5, -1, -1.0, -Infinity, new Date(-1), ]); }); test('for valid booleans', () => { expectNoActionIssue(ltValue(true), [false]); }); test('for valid non-booleans', () => { expectNoActionIssue(ltValue(true), [ '-1', ' 0 ', '0', '0.5', -1, 0.0, 0, 0.5, -Infinity, new Date(-1), new Date(0), -1n, 0n, ]); expectNoActionIssue(ltValue(false), [ '-1', ' -1 ', '-0.5', -0.5, -1, -1.0, -Infinity, new Date(-1), -1n, ]); }); test('for valid dates', () => { const date = new Date(); expectNoActionIssue(ltValue(date), [ new Date(0), new Date(+date - 999999), new Date(+date - 1), ]); }); test('for valid non-dates', () => { const date1 = new Date(10); expectNoActionIssue(ltValue(date1), [ '-10', ' 9 ', '9', '9.5', 9.5, 9, 9.0, -Infinity, false, true, -10n, 0n, 9n, ]); const date2 = new Date(1); expectNoActionIssue(ltValue(date2), [ '-1', '', ' ', ' 0 ', '0', '0.5', -1, 0.0, 0, 0.5, -Infinity, false, -1n, 0n, ]); const date3 = new Date(0); expectNoActionIssue(ltValue(date3), [ '-1', ' -1 ', '-0.5', -0.5, -1, -1.0, -Infinity, -1n, ]); }); test('for valid numbers', () => { expectNoActionIssue(ltValue(10), [Number.MIN_VALUE, 0, 9, 9.5]); }); test('for valid non-numbers', () => { expectNoActionIssue(ltValue(10), [ '-10', ' 9 ', '9', '9.5', '', ' ', false, true, new Date(-10), new Date(0), new Date(9), -10n, 0n, 9n, ]); expectNoActionIssue(ltValue(1), [ '-1', ' 0 ', '0', '0.5', '', ' ', false, new Date(-1), new Date(0), -1n, 0n, ]); expectNoActionIssue(ltValue(0), [ '-1', ' -1 ', '-0.5', new Date(-1), -1n, ]); }); test('for valid strings', () => { expectNoActionIssue(ltValue('2024'), ['', '1234', '2023']); }); test('for valid non-strings', () => { expectNoActionIssue(ltValue('10'), [ -10, 0, 9.5, 9, 9.0, -Infinity, false, true, new Date(-10), new Date(0), new Date(9), -10n, 0n, 9n, ]); expectNoActionIssue(ltValue('1'), [ -1, 0, 0.5, -Infinity, false, new Date(-1), new Date(0), -1n, 0n, ]); expectNoActionIssue(ltValue('0'), [ -0.5, -1, -1.0, -Infinity, new Date(-1), -1n, ]); }); }); describe('should return dataset with issues', () => { const baseInfo = { kind: 'validation', type: 'lt_value', message: 'message', } as const; const getReceived = (value: unknown): string => value instanceof Date ? value.toJSON() : _stringify(value); test('for invalid bigints', () => { expectActionIssue( ltValue(10n, 'message'), { ...baseInfo, expected: '<10', requirement: 10n }, [10n, 11n, 9999n] ); }); test('for invalid non-bigints', () => { expectActionIssue( ltValue(123n, 'message'), { ...baseInfo, expected: '<123', requirement: 123n }, [ 'nan', '122px', '+ 122', '122.0', '123', '124', 123, 124, 124.0, Infinity, NaN, new Date(123), new Date(124), ], getReceived ); expectActionIssue( ltValue(1n, 'message'), { ...baseInfo, expected: '<1', requirement: 1n }, [ 'nan', '0px', '+ 0', '0.0', '1', 1, 1.0, 2, Infinity, NaN, true, new Date(1), new Date(2), ], getReceived ); expectActionIssue( ltValue(0n, 'message'), { ...baseInfo, expected: '<0', requirement: 0n }, [ 'nan', '-1px', '- 1', '-1.0', '0', 0, 0.0, 1, 1.0, Infinity, NaN, false, true, new Date(0), new Date(1), ], getReceived ); }); test('for invalid booleans', () => { expectActionIssue( ltValue(false, 'message'), { ...baseInfo, expected: ' { expectActionIssue( ltValue(false, 'message'), { ...baseInfo, expected: ' { const date = new Date(); expectActionIssue( ltValue(date, 'message'), { ...baseInfo, expected: `<${date.toJSON()}`, requirement: date }, [date, new Date(+date + 1), new Date(+date + 999999)], (value) => value.toJSON() ); }); test('for invalid non-dates', () => { const date1 = new Date(123); expectActionIssue( ltValue(date1, 'message'), { ...baseInfo, expected: `<${date1.toJSON()}`, requirement: date1 }, [ 'nan', '122px', '+ 122', '123', '124.0', 123, 124, 124.0, Infinity, NaN, 123n, 124n, ], getReceived ); const date2 = new Date(1); expectActionIssue( ltValue(date2, 'message'), { ...baseInfo, expected: `<${date2.toJSON()}`, requirement: date2 }, [ 'nan', '0px', '+ 0', '1', '1.0', 1, 1.0, 2, Infinity, NaN, true, 1n, 2n, ], getReceived ); const date3 = new Date(0); expectActionIssue( ltValue(date3, 'message'), { ...baseInfo, expected: `<${date3.toJSON()}`, requirement: date3 }, [ 'nan', '-1px', '- 1', '0', '0.0', 0, 0.0, 1, 1.0, Infinity, NaN, false, true, 0n, 1n, ], getReceived ); }); test('for invalid numbers', () => { expectActionIssue( ltValue(10, 'message'), { ...baseInfo, expected: '<10', requirement: 10 }, [10, 11, 9999, Number.MAX_VALUE, NaN] ); }); test('for invalid non-numbers', () => { expectActionIssue( ltValue(123, 'message'), { ...baseInfo, expected: '<123', requirement: 123 }, [ 'nan', '122px', '+ 122', '123', '124', '124.0', new Date(123), new Date(124), 123n, 124n, ], getReceived ); expectActionIssue( ltValue(1, 'message'), { ...baseInfo, expected: '<1', requirement: 1 }, [ 'nan', '0px', '+ 0', '1', '1.0', true, new Date(1), new Date(2), 1n, 2n, ], getReceived ); expectActionIssue( ltValue(0, 'message'), { ...baseInfo, expected: '<0', requirement: 0 }, [ 'nan', '-1px', '- 1', '0', '0.0', false, true, new Date(0), new Date(1), 0n, 1n, ], getReceived ); }); test('for invalid strings', () => { expectActionIssue( ltValue('2024', 'message'), { ...baseInfo, expected: '<"2024"', requirement: '2024' }, ['2024', '2025', '9999', 'XYZ'] ); }); test('for invalid non-strings', () => { expectActionIssue( ltValue('123', 'message'), { ...baseInfo, expected: '<"123"', requirement: '123' }, [ 123, 124, 124.0, Infinity, NaN, new Date(123), new Date(124), 123n, 124n, ], getReceived ); expectActionIssue( ltValue('1', 'message'), { ...baseInfo, expected: '<"1"', requirement: '1' }, [1, 1.0, 2, Infinity, NaN, true, new Date(1), new Date(2), 1n, 2n], getReceived ); expectActionIssue( ltValue('0', 'message'), { ...baseInfo, expected: '<"0"', requirement: '0' }, [ 0, 0.0, 1, 1.0, Infinity, NaN, false, true, new Date(0), new Date(1), 0n, 1n, ], getReceived ); }); }); }); ================================================ FILE: library/src/actions/ltValue/ltValue.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _stringify } from '../../utils/index.ts'; import type { ValueInput } from '../types.ts'; /** * Less than value issue type. */ export interface LtValueIssue< TInput extends ValueInput, TRequirement extends TInput, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'lt_value'; /** * The expected property. */ readonly expected: `<${string}`; /** * The less than value. */ readonly requirement: TRequirement; } /** * Less than value action type. */ export interface LtValueAction< TInput extends ValueInput, TRequirement extends TInput, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'lt_value'; /** * The action reference. */ readonly reference: typeof ltValue; /** * The expected property. */ readonly expects: `<${string}`; /** * The less than value. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a less than value validation action. * * @param requirement The less than value. * * @returns A less than value action. */ export function ltValue< TInput extends ValueInput, const TRequirement extends TInput, >(requirement: TRequirement): LtValueAction; /** * Creates a less than value validation action. * * @param requirement The less than value. * @param message The error message. * * @returns A less than value action. */ export function ltValue< TInput extends ValueInput, const TRequirement extends TInput, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): LtValueAction; // @__NO_SIDE_EFFECTS__ export function ltValue( requirement: ValueInput, message?: ErrorMessage> ): LtValueAction< ValueInput, ValueInput, ErrorMessage> | undefined > { return { kind: 'validation', type: 'lt_value', reference: ltValue, async: false, expects: `<${ requirement instanceof Date ? requirement.toJSON() : _stringify(requirement) }`, requirement, message, '~run'(dataset, config) { if (dataset.typed && !(dataset.value < this.requirement)) { _addIssue(this, 'value', dataset, config, { received: dataset.value instanceof Date ? dataset.value.toJSON() : _stringify(dataset.value), }); } return dataset; }, }; } ================================================ FILE: library/src/actions/mac/index.ts ================================================ export * from './mac.ts'; ================================================ FILE: library/src/actions/mac/mac.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { mac, type MacAction, type MacIssue } from './mac.ts'; describe('mac', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = MacAction; expectTypeOf(mac()).toEqualTypeOf(); expectTypeOf(mac(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(mac('message')).toEqualTypeOf< MacAction >(); }); test('with function message', () => { expectTypeOf(mac string>(() => 'message')).toEqualTypeOf< MacAction string> >(); }); }); describe('should infer correct types', () => { type Action = MacAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/mac/mac.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { MAC_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { mac, type MacAction, type MacIssue } from './mac.ts'; describe('mac', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'mac', reference: mac, expects: null, requirement: MAC_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: MacAction = { ...baseAction, message: undefined, }; expect(mac()).toStrictEqual(action); expect(mac(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(mac('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies MacAction); }); test('with function message', () => { const message = () => 'message'; expect(mac(message)).toStrictEqual({ ...baseAction, message, } satisfies MacAction); }); }); describe('should return dataset without issues', () => { const action = mac(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for 48-bit MAC address', () => { expectNoActionIssue(action, [ 'b6:05:20:67:f9:58', 'B6:05:20:67:F9:58', 'b6-05-20-67-f9-58', 'B6-05-20-67-F9-58', 'b605.2067.f958', 'B605.2067.F958', '00:00:00:00:00:00', '99:99:99:99:99:99', 'aa:aa:aa:aa:aa:aa', 'AA:AA:AA:AA:AA:AA', 'ff:ff:ff:ff:ff:ff', 'FF:FF:FF:FF:FF:FF', '00-00-00-00-00-00', '99-99-99-99-99-99', 'aa-aa-aa-aa-aa-aa', 'AA-AA-AA-AA-AA-AA', 'ff-ff-ff-ff-ff-ff', 'FF-FF-FF-FF-FF-FF', '0000.0000.0000', '9999.9999.9999', 'aaaa.aaaa.aaaa', 'AAAA.AAAA.AAAA', 'ffff.ffff.ffff', 'FFFF.FFFF.FFFF', ]); }); test('for 64-bit MAC address', () => { expectNoActionIssue(action, [ '00:25:96:FF:FE:12:34:56', '00-1A-2B-3C-4D-5E-6F-70', '0025.96FF.FE12.3456', '0025:96FF:FE12:3456', '00:00:00:00:00:00:00:00', '99:99:99:99:99:99:99:99', 'aa:aa:aa:aa:aa:aa:aa:aa', 'AA:AA:AA:AA:AA:AA:AA:AA', 'ff:ff:ff:ff:ff:ff:ff:ff', 'FF:FF:FF:FF:FF:FF:FF:FF', '00-00-00-00-00-00-00-00', '99-99-99-99-99-99-99-99', 'aa-aa-aa-aa-aa-aa-aa-aa', 'AA-AA-AA-AA-AA-AA-AA-AA', 'ff-ff-ff-ff-ff-ff-ff-ff', 'FF-FF-FF-FF-FF-FF-FF-FF', '0000.0000.0000.0000', '9999.9999.9999.9999', 'aaaa.aaaa.aaaa.aaaa', 'AAAA.AAAA.AAAA.AAAA', 'ffff.ffff.ffff.ffff', 'FFFF.FFFF.FFFF.FFFF', '0000:0000:0000:0000', '9999:9999:9999:9999', 'aaaa:aaaa:aaaa:aaaa', 'AAAA:AAAA:AAAA:AAAA', 'ffff:ffff:ffff:ffff', 'FFFF:FFFF:FFFF:FFFF', ]); }); }); describe('should return dataset with issues', () => { const action = mac('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'mac', expected: null, message: 'message', requirement: MAC_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for invalid MAC address', () => { expectActionIssue(action, baseIssue, [ // intended to test both - mac48 and mac64 parts of the regular expression '00:1G:2B:3C:4D:5E', '00:1A:2B:3C:4D', '00:1A:2B:3C:4D:5E:6F', '00:1A:2B:3C:4D:5E:6F:70:80', '00-1G-2B-3C-4D-5E', '00-1A-2B-3C-4D', '00-1A-2B-3C-4D-5E-6F', '00-1A-2B-3C-4D-5E-6F-70-80', 'b605-2067-f958', '00_1A_2B_3C_4D_5E', '001A2B3C4D5E6F', 'ZZ:ZZ:ZZ:ZZ:ZZ:ZZ', '00:1A:2B:3C:4D:5E:6F:70:80:90:AB', '001122334455', '00:1A:2B:3C:4D:5E:6F:70:ZZ', 'GHIJ:KLNM:OPQR', '00:00:00:00:00:00:00', '00-00-00-00-00-00-00', // intended to test mac48 part of the regular expression '0:0:0:0:0:0', '000:000:000:000:000:000', '00:00:00:00:00', '0-0-0-0-0-0', '000-000-000-000-000-000', '00-00-00-00-00', '000.000.000', '00000.00000.00000', '-10:-10:-10:-10:-10:-10', '100:100:100:100:100:100', 'gg:gg:gg:gg:gg:gg', 'GG:GG:GG:GG:GG:GG', 'zz:zz:zz:zz:zz:zz', '-10--10--10--10--10--10', '100-100-100-100-100-100', 'gg-gg-gg-gg-gg-gg', 'GG-GG-GG-GG-GG-GG', 'zz-zz-zz-zz-zz-zz', 'ZZ-ZZ-ZZ-ZZ-ZZ-ZZ', '-1000.-1000.-1000', '10000.10000.10000', 'gggg.gggg.gggg', 'GGGG.GGGG.GGGG', 'zzzz.zzzz.zzzz', 'ZZZZ.ZZZZ.ZZZZ', // intended to test mac64 part of the regular expression '0:0:0:0:0:0:0:0', '000:000:000:000:000:000:000:000', '00:00:00:00:00:00:00:00:00', '0-0-0-0-0-0-0-0', '000-000-000-000-000-000-000-000', '00-00-00-00-00-00-00-00-00', '000.000.000.000', '00000.00000.00000.00000', '0000.0000.0000.0000.0000', '000:000:000:000', '00000:00000:00000:00000', '0000:0000:0000', '0000:0000:0000:0000:0000', '-10:-10:-10:-10:-10:-10:-10:-10', '10000:10000:10000:10000:10000:10000:10000:10000', 'zzzz:zzzz:zzzz:zzzz:zzzz:zzzz:zzzz:zzzz', 'ZZZZ:ZZZZ:ZZZZ:ZZZZ:ZZZZ:ZZZZ:ZZZZ:ZZZZ', 'gggg:gggg:gggg:gggg:gggg:gggg:gggg:gggg', 'GGGG:GGGG:GGGG:GGGG:GGGG:GGGG:GGGG:GGGG', '-10--10--10--10--10--10--10--10', '10000-10000-10000-10000-10000-10000-10000-10000', 'zzzz-zzzz-zzzz-zzzz-zzzz-zzzz-zzzz-zzzz', 'ZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZ', 'gggg-gggg-gggg-gggg-gggg-gggg-gggg-gggg', 'GGGG-GGGG-GGGG-GGGG-GGGG-GGGG-GGGG-GGGG', '-1000.-1000.-1000.-1000', '10000.10000.10000.10000', 'zzzz.zzzz.zzzz.zzzz', 'ZZZZ.ZZZZ.ZZZZ.ZZZZ', 'gggg.gggg.gggg.gggg', 'GGGG.GGGG.GGGG.GGGG', '-1000:-1000:-1000:-1000', '10000:10000:10000:10000', 'zzzz:zzzz:zzzz:zzzz', 'ZZZZ:ZZZZ:ZZZZ:ZZZZ', 'gggg:gggg:gggg:gggg', 'GGGG:GGGG:GGGG:GGGG', ]); }); }); }); ================================================ FILE: library/src/actions/mac/mac.ts ================================================ import { MAC_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * MAC issue interface. */ export interface MacIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'mac'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The MAC regex. */ readonly requirement: RegExp; } /** * MAC action interface. */ export interface MacAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'mac'; /** * The action reference. */ readonly reference: typeof mac; /** * The expected property. */ readonly expects: null; /** * The MAC regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates a [MAC address](https://en.wikipedia.org/wiki/MAC_address) validation action. * * @returns A MAC action. */ export function mac(): MacAction; /** * Creates a [MAC address](https://en.wikipedia.org/wiki/MAC_address) validation action. * * @param message The error message. * * @returns A MAC action. */ export function mac< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): MacAction; // @__NO_SIDE_EFFECTS__ export function mac( message?: ErrorMessage> ): MacAction> | undefined> { return { kind: 'validation', type: 'mac', reference: mac, async: false, expects: null, requirement: MAC_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'MAC', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/mac48/index.ts ================================================ export * from './mac48.ts'; ================================================ FILE: library/src/actions/mac48/mac48.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { mac48, type Mac48Action, type Mac48Issue } from './mac48.ts'; describe('mac48', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = Mac48Action; expectTypeOf(mac48()).toEqualTypeOf(); expectTypeOf(mac48(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(mac48('message')).toEqualTypeOf< Mac48Action >(); }); test('with function message', () => { expectTypeOf(mac48 string>(() => 'message')).toEqualTypeOf< Mac48Action string> >(); }); }); describe('should infer correct types', () => { type Action = Mac48Action; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/mac48/mac48.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { MAC48_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { mac48, type Mac48Action, type Mac48Issue } from './mac48.ts'; describe('mac48', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'mac48', reference: mac48, expects: null, requirement: MAC48_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: Mac48Action = { ...baseAction, message: undefined, }; expect(mac48()).toStrictEqual(action); expect(mac48(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(mac48('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies Mac48Action); }); test('with function message', () => { const message = () => 'message'; expect(mac48(message)).toStrictEqual({ ...baseAction, message, } satisfies Mac48Action); }); }); describe('should return dataset without issues', () => { const action = mac48(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for 48-bit MAC address', () => { expectNoActionIssue(action, [ 'b6:05:20:67:f9:58', 'B6:05:20:67:F9:58', 'b6-05-20-67-f9-58', 'B6-05-20-67-F9-58', 'b605.2067.f958', 'B605.2067.F958', '00:00:00:00:00:00', '99:99:99:99:99:99', 'aa:aa:aa:aa:aa:aa', 'AA:AA:AA:AA:AA:AA', 'ff:ff:ff:ff:ff:ff', 'FF:FF:FF:FF:FF:FF', '00-00-00-00-00-00', '99-99-99-99-99-99', 'aa-aa-aa-aa-aa-aa', 'AA-AA-AA-AA-AA-AA', 'ff-ff-ff-ff-ff-ff', 'FF-FF-FF-FF-FF-FF', '0000.0000.0000', '9999.9999.9999', 'aaaa.aaaa.aaaa', 'AAAA.AAAA.AAAA', 'ffff.ffff.ffff', 'FFFF.FFFF.FFFF', ]); }); }); describe('should return dataset with issues', () => { const action = mac48('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'mac48', expected: null, message: 'message', requirement: MAC48_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for 64-bit MAC address', () => { expectActionIssue(action, baseIssue, [ '00:25:96:FF:FE:12:34:56', '00-1A-2B-3C-4D-5E-6F-70', '0025.96FF.FE12.3456', '0025:96FF:FE12:3456', ]); }); test('for invalid 48-bit MAC address', () => { expectActionIssue(action, baseIssue, [ '00:1G:2B:3C:4D:5E', '00:1A:2B:3C:4D', '00:1A:2B:3C:4D:5E:6F', '00:1A:2B:3C:4D:5E:6F:70:80', '00-1G-2B-3C-4D-5E', '00-1A-2B-3C-4D', '00-1A-2B-3C-4D-5E-6F', '00-1A-2B-3C-4D-5E-6F-70-80', 'b605-2067-f958', '00_1A_2B_3C_4D_5E', '001A2B3C4D5E6F', '00:1A:2B:3C:4D:5E:6F:70:80:90:AB', '001122334455', '00:1A:2B:3C:4D:5E:6F:70:ZZ', 'GHIJ:KLNM:OPQR', '00:00:00:00:00:00:00', '00-00-00-00-00-00-00', '0:0:0:0:0:0', '000:000:000:000:000:000', '00:00:00:00:00', '0-0-0-0-0-0', '000-000-000-000-000-000', '00-00-00-00-00', '000.000.000', '00000.00000.00000', '0000.0000', '0000.0000.0000.0000', '-10:-10:-10:-10:-10:-10', '100:100:100:100:100:100', 'gg:gg:gg:gg:gg:gg', 'GG:GG:GG:GG:GG:GG', 'zz:zz:zz:zz:zz:zz', 'ZZ:ZZ:ZZ:ZZ:ZZ:ZZ', '-10--10--10--10--10--10', '100-100-100-100-100-100', 'gg-gg-gg-gg-gg-gg', 'GG-GG-GG-GG-GG-GG', 'zz-zz-zz-zz-zz-zz', 'ZZ-ZZ-ZZ-ZZ-ZZ-ZZ', '-1000.-1000.-1000', '10000.10000.10000', 'gggg.gggg.gggg', 'GGGG.GGGG.GGGG', 'zzzz.zzzz.zzzz', 'ZZZZ.ZZZZ.ZZZZ', ]); }); }); }); ================================================ FILE: library/src/actions/mac48/mac48.ts ================================================ import { MAC48_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * 48-bit MAC issue interface. */ export interface Mac48Issue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'mac48'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The 48-bit MAC regex. */ readonly requirement: RegExp; } /** * 48-bit MAC action interface. */ export interface Mac48Action< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'mac48'; /** * The action reference. */ readonly reference: typeof mac48; /** * The expected property. */ readonly expects: null; /** * The 48-bit MAC regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates a 48-bit [MAC address](https://en.wikipedia.org/wiki/MAC_address) validation action. * * @returns A 48-bit MAC action. */ export function mac48(): Mac48Action; /** * Creates a 48-bit [MAC address](https://en.wikipedia.org/wiki/MAC_address) validation action. * * @param message The error message. * * @returns A 48-bit MAC action. */ export function mac48< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): Mac48Action; // @__NO_SIDE_EFFECTS__ export function mac48( message?: ErrorMessage> ): Mac48Action> | undefined> { return { kind: 'validation', type: 'mac48', reference: mac48, async: false, expects: null, requirement: MAC48_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, '48-bit MAC', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/mac64/index.ts ================================================ export * from './mac64.ts'; ================================================ FILE: library/src/actions/mac64/mac64.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { mac64, type Mac64Action, type Mac64Issue } from './mac64.ts'; describe('mac64', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = Mac64Action; expectTypeOf(mac64()).toEqualTypeOf(); expectTypeOf(mac64(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(mac64('message')).toEqualTypeOf< Mac64Action >(); }); test('with function message', () => { expectTypeOf(mac64 string>(() => 'message')).toEqualTypeOf< Mac64Action string> >(); }); }); describe('should infer correct types', () => { type Action = Mac64Action; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/mac64/mac64.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { MAC64_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { mac64, type Mac64Action, type Mac64Issue } from './mac64.ts'; describe('mac64', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'mac64', reference: mac64, expects: null, requirement: MAC64_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: Mac64Action = { ...baseAction, message: undefined, }; expect(mac64()).toStrictEqual(action); expect(mac64(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(mac64('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies Mac64Action); }); test('with function message', () => { const message = () => 'message'; expect(mac64(message)).toStrictEqual({ ...baseAction, message, } satisfies Mac64Action); }); }); describe('should return dataset without issues', () => { const action = mac64(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for 64-bit MAC address', () => { expectNoActionIssue(action, [ '00:25:96:FF:FE:12:34:56', '00-1A-2B-3C-4D-5E-6F-70', '0025.96FF.FE12.3456', '0025:96FF:FE12:3456', '00:00:00:00:00:00:00:00', '99:99:99:99:99:99:99:99', 'aa:aa:aa:aa:aa:aa:aa:aa', 'AA:AA:AA:AA:AA:AA:AA:AA', 'ff:ff:ff:ff:ff:ff:ff:ff', 'FF:FF:FF:FF:FF:FF:FF:FF', '00-00-00-00-00-00-00-00', '99-99-99-99-99-99-99-99', 'aa-aa-aa-aa-aa-aa-aa-aa', 'AA-AA-AA-AA-AA-AA-AA-AA', 'ff-ff-ff-ff-ff-ff-ff-ff', 'FF-FF-FF-FF-FF-FF-FF-FF', '0000.0000.0000.0000', '9999.9999.9999.9999', 'aaaa.aaaa.aaaa.aaaa', 'AAAA.AAAA.AAAA.AAAA', 'ffff.ffff.ffff.ffff', 'FFFF.FFFF.FFFF.FFFF', '0000:0000:0000:0000', '9999:9999:9999:9999', 'aaaa:aaaa:aaaa:aaaa', 'AAAA:AAAA:AAAA:AAAA', 'ffff:ffff:ffff:ffff', 'FFFF:FFFF:FFFF:FFFF', ]); }); }); describe('should return dataset with issues', () => { const action = mac64('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'mac64', expected: null, message: 'message', requirement: MAC64_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for 48-bit MAC address', () => { expectActionIssue(action, baseIssue, [ 'b6:05:20:67:f9:58', 'b6-05-20-67-f9-58', 'b605.2067.f958', '0000.0000.0000', ]); }); test('for invalid 64-bit MAC address', () => { expectActionIssue(action, baseIssue, [ '00:1G:2B:3C:4D:5E', '00:1A:2B:3C:4D', '00:1A:2B:3C:4D:5E:6F', '00:1A:2B:3C:4D:5E:6F:70:80', '00-1G-2B-3C-4D-5E', '00-1A-2B-3C-4D', '00-1A-2B-3C-4D-5E-6F', '00-1A-2B-3C-4D-5E-6F-70-80', 'b605-2067-f958', '00_1A_2B_3C_4D_5E', '001A2B3C4D5E6F', 'ZZ:ZZ:ZZ:ZZ:ZZ:ZZ', '00:1A:2B:3C:4D:5E:6F:70:80:90:AB', '001122334455', '00:1A:2B:3C:4D:5E:6F:70:ZZ', 'GHIJ:KLNM:OPQR', '0:0:0:0:0:0:0:0', '000:000:000:000:000:000:000:000', '00:00:00:00:00:00:00', '00:00:00:00:00:00:00:00:00', '0-0-0-0-0-0-0-0', '000-000-000-000-000-000-000-000', '00-00-00-00-00-00-00', '00-00-00-00-00-00-00-00-00', '000.000.000.000', '00000.00000.00000.00000', '0000.0000.0000.0000.0000', '000:000:000:000', '00000:00000:00000:00000', '0000:0000:0000', '0000:0000:0000:0000:0000', '-10:-10:-10:-10:-10:-10:-10:-10', '10000:10000:10000:10000:10000:10000:10000:10000', 'zzzz:zzzz:zzzz:zzzz:zzzz:zzzz:zzzz:zzzz', 'ZZZZ:ZZZZ:ZZZZ:ZZZZ:ZZZZ:ZZZZ:ZZZZ:ZZZZ', 'gggg:gggg:gggg:gggg:gggg:gggg:gggg:gggg', 'GGGG:GGGG:GGGG:GGGG:GGGG:GGGG:GGGG:GGGG', '-10--10--10--10--10--10--10--10', '10000-10000-10000-10000-10000-10000-10000-10000', 'zzzz-zzzz-zzzz-zzzz-zzzz-zzzz-zzzz-zzzz', 'ZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZ-ZZZZ', 'gggg-gggg-gggg-gggg-gggg-gggg-gggg-gggg', 'GGGG-GGGG-GGGG-GGGG-GGGG-GGGG-GGGG-GGGG', '-1000.-1000.-1000.-1000', '10000.10000.10000.10000', 'zzzz.zzzz.zzzz.zzzz', 'ZZZZ.ZZZZ.ZZZZ.ZZZZ', 'gggg.gggg.gggg.gggg', 'GGGG.GGGG.GGGG.GGGG', '-1000:-1000:-1000:-1000', '10000:10000:10000:10000', 'zzzz:zzzz:zzzz:zzzz', 'ZZZZ:ZZZZ:ZZZZ:ZZZZ', 'gggg:gggg:gggg:gggg', 'GGGG:GGGG:GGGG:GGGG', ]); }); }); }); ================================================ FILE: library/src/actions/mac64/mac64.ts ================================================ import { MAC64_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * 64-bit MAC issue interface. */ export interface Mac64Issue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'mac64'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The 64-bit MAC regex. */ readonly requirement: RegExp; } /** * 64-bit MAC action interface. */ export interface Mac64Action< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'mac64'; /** * The action reference. */ readonly reference: typeof mac64; /** * The expected property. */ readonly expects: null; /** * The 64-bit MAC regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates a 64-bit [MAC address](https://en.wikipedia.org/wiki/MAC_address) validation action. * * @returns A 64-bit MAC action. */ export function mac64(): Mac64Action; /** * Creates a 64-bit [MAC address](https://en.wikipedia.org/wiki/MAC_address) validation action. * * @param message The error message. * * @returns A 64-bit MAC action. */ export function mac64< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): Mac64Action; // @__NO_SIDE_EFFECTS__ export function mac64( message?: ErrorMessage> ): Mac64Action> | undefined> { return { kind: 'validation', type: 'mac64', reference: mac64, async: false, expects: null, requirement: MAC64_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, '64-bit MAC', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/mapItems/index.ts ================================================ export * from './mapItems.ts'; ================================================ FILE: library/src/actions/mapItems/mapItems.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { mapItems, type MapItemsAction } from './mapItems.ts'; describe('mapItems', () => { test('should return action object', () => { expectTypeOf( mapItems((item) => ({ item })) ).toEqualTypeOf>(); }); describe('should infer correct types', () => { type Action = MapItemsAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf<{ item: number }[]>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/mapItems/mapItems.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { mapItems, type MapItemsAction } from './mapItems.ts'; describe('mapItems', () => { const operation = (item: number) => ({ item }); const action = mapItems(operation); test('should return action object', () => { expect(action).toStrictEqual({ kind: 'transformation', type: 'map_items', reference: mapItems, async: false, operation, '~run': expect.any(Function), } satisfies MapItemsAction); }); test('should transform input', () => { expect( action['~run']({ typed: true, value: [-12, 345, 0] }, {}) ).toStrictEqual({ typed: true, value: [{ item: -12 }, { item: 345 }, { item: 0 }], }); }); }); ================================================ FILE: library/src/actions/mapItems/mapItems.ts ================================================ import type { BaseTransformation } from '../../types/index.ts'; import type { ArrayInput } from '../types.ts'; /** * Array action type. */ type ArrayAction = ( item: TInput[number], index: number, array: TInput ) => TOutput; /** * Map items action interface. */ export interface MapItemsAction extends BaseTransformation { /** * The action type. */ readonly type: 'map_items'; /** * The action reference. */ readonly reference: typeof mapItems; /** * The map items operation. */ readonly operation: ArrayAction; } /** * Creates a map items transformation action. * * @param operation The map items operation. * * @returns A map items action. */ export function mapItems( operation: ArrayAction ): MapItemsAction; // @__NO_SIDE_EFFECTS__ export function mapItems( operation: ArrayAction ): MapItemsAction { return { kind: 'transformation', type: 'map_items', reference: mapItems, async: false, operation, '~run'(dataset) { dataset.value = dataset.value.map(this.operation); return dataset; }, }; } ================================================ FILE: library/src/actions/maxBytes/index.ts ================================================ export * from './maxBytes.ts'; ================================================ FILE: library/src/actions/maxBytes/maxBytes.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { maxBytes, type MaxBytesAction, type MaxBytesIssue, } from './maxBytes.ts'; describe('maxBytes', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = MaxBytesAction; expectTypeOf(maxBytes(10)).toEqualTypeOf(); expectTypeOf( maxBytes(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( maxBytes(10, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( maxBytes string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = MaxBytesAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< MaxBytesIssue >(); }); }); }); ================================================ FILE: library/src/actions/maxBytes/maxBytes.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { maxBytes, type MaxBytesAction, type MaxBytesIssue, } from './maxBytes.ts'; describe('maxBytes', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'max_bytes', reference: maxBytes, expects: '<=5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: MaxBytesAction = { ...baseAction, message: undefined, }; expect(maxBytes(5)).toStrictEqual(action); expect(maxBytes(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(maxBytes(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies MaxBytesAction); }); test('with function message', () => { const message = () => 'message'; expect(maxBytes(5, message)).toStrictEqual({ ...baseAction, message, } satisfies MaxBytesAction); }); }); describe('should return dataset without issues', () => { const action = maxBytes(5); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid strings', () => { expectNoActionIssue(action, ['', '1', '1234', '12345']); }); test('for valid chars', () => { expectNoActionIssue(action, [ 'あ', // 'あ' is 3 bytes '🤖!', // '🤖' is 4 bytes ]); }); }); describe('should return dataset with issues', () => { const action = maxBytes(5, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'max_bytes', expected: '<=5', message: 'message', requirement: 5, }; const getReceived = (value: string) => `${new TextEncoder().encode(value).length}`; test('for invalid strings', () => { expectActionIssue( action, baseIssue, ['123456', 'foobarbaz123'], getReceived ); }); test('for invalid chars', () => { expectActionIssue( action, baseIssue, [ 'あい', // 'あい' is 6 bytes ], getReceived ); }); }); }); ================================================ FILE: library/src/actions/maxBytes/maxBytes.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _getByteCount } from '../../utils/index.ts'; /** * Max bytes issue interface. */ export interface MaxBytesIssue< TInput extends string, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'max_bytes'; /** * The expected property. */ readonly expected: `<=${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The maximum bytes. */ readonly requirement: TRequirement; } /** * Max bytes action interface. */ export interface MaxBytesAction< TInput extends string, TRequirement extends number, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'max_bytes'; /** * The action reference. */ readonly reference: typeof maxBytes; /** * The expected property. */ readonly expects: `<=${TRequirement}`; /** * The maximum bytes. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a max [bytes](https://en.wikipedia.org/wiki/Byte) validation action. * * @param requirement The maximum bytes. * * @returns A max bytes action. */ export function maxBytes< TInput extends string, const TRequirement extends number, >(requirement: TRequirement): MaxBytesAction; /** * Creates a max [bytes](https://en.wikipedia.org/wiki/Byte) validation action. * * @param requirement The maximum bytes. * @param message The error message. * * @returns A max bytes action. */ export function maxBytes< TInput extends string, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): MaxBytesAction; // @__NO_SIDE_EFFECTS__ export function maxBytes( requirement: number, message?: ErrorMessage> ): MaxBytesAction< string, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'max_bytes', reference: maxBytes, async: false, expects: `<=${requirement}`, requirement, message, '~run'(dataset, config) { if (dataset.typed) { const length = _getByteCount(dataset.value); if (length > this.requirement) { _addIssue(this, 'bytes', dataset, config, { received: `${length}`, }); } } return dataset; }, }; } ================================================ FILE: library/src/actions/maxEntries/index.ts ================================================ export * from './maxEntries.ts'; ================================================ FILE: library/src/actions/maxEntries/maxEntries.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { maxEntries, type MaxEntriesAction, type MaxEntriesIssue, } from './maxEntries.ts'; describe('maxEntries', () => { type Input = Record; describe('should return action object', () => { test('with undefined message', () => { type Action = MaxEntriesAction; expectTypeOf(maxEntries(10)).toEqualTypeOf(); expectTypeOf( maxEntries(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( maxEntries(10, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( maxEntries string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = MaxEntriesAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< MaxEntriesIssue >(); }); }); }); ================================================ FILE: library/src/actions/maxEntries/maxEntries.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { RecordIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { maxEntries, type MaxEntriesAction, type MaxEntriesIssue, } from './maxEntries.ts'; describe('maxEntries', () => { type Input = Record; describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'max_entries', reference: maxEntries, expects: '<=3', requirement: 3, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: MaxEntriesAction = { ...baseAction, message: undefined, }; expect(maxEntries(3)).toStrictEqual(action); expect(maxEntries(3, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(maxEntries(3, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies MaxEntriesAction); }); test('with function message', () => { const message = () => 'message'; expect(maxEntries(3, message)).toStrictEqual({ ...baseAction, message, } satisfies MaxEntriesAction); }); }); describe('should return dataset without issues', () => { const action = maxEntries(3); test('for untyped inputs', () => { const issues: [RecordIssue] = [ { kind: 'schema', type: 'record', input: null, expected: 'Object', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid objects', () => { expectNoActionIssue(action, [ {}, { foo: 1 }, { foo: 1, bar: 2 }, { foo: 1, bar: 2, baz: 3 }, ]); }); }); describe('should return dataset with issues', () => { const action = maxEntries(3, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'max_entries', expected: '<=3', message: 'message', requirement: 3, }; test('for invalid objects', () => { expectActionIssue( action, baseIssue, [ { foo: 1, bar: 2, baz: 3, qux: 4 }, { foo: 1, bar: 2, baz: 3, qux: 4, quux: 5 }, ], (value) => `${Object.keys(value).length}` ); }); }); }); ================================================ FILE: library/src/actions/maxEntries/maxEntries.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { EntriesInput } from '../types.ts'; /** * Max entries issue interface. * * @beta */ export interface MaxEntriesIssue< TInput extends EntriesInput, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'max_entries'; /** * The expected property. */ readonly expected: `<=${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The maximum entries. */ readonly requirement: TRequirement; } /** * Max entries action interface. * * @beta */ export interface MaxEntriesAction< TInput extends EntriesInput, TRequirement extends number, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation< TInput, TInput, MaxEntriesIssue > { /** * The action type. */ readonly type: 'max_entries'; /** * The action reference. */ readonly reference: typeof maxEntries; /** * The expected property. */ readonly expects: `<=${TRequirement}`; /** * The maximum entries. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a max entries validation action. * * @param requirement The maximum entries. * * @returns A max entries action. * * @beta */ export function maxEntries< TInput extends EntriesInput, const TRequirement extends number, >(requirement: TRequirement): MaxEntriesAction; /** * Creates a max entries validation action. * * @param requirement The maximum entries. * @param message The error message. * * @returns A max entries action. * * @beta */ export function maxEntries< TInput extends EntriesInput, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): MaxEntriesAction; // @__NO_SIDE_EFFECTS__ export function maxEntries( requirement: number, message?: ErrorMessage> ): MaxEntriesAction< EntriesInput, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'max_entries', reference: maxEntries, async: false, expects: `<=${requirement}`, requirement, message, '~run'(dataset, config) { if (!dataset.typed) return dataset; const count = Object.keys(dataset.value).length; if (dataset.typed && count > this.requirement) { _addIssue(this, 'entries', dataset, config, { received: `${count}`, }); } return dataset; }, }; } ================================================ FILE: library/src/actions/maxGraphemes/index.ts ================================================ export * from './maxGraphemes.ts'; ================================================ FILE: library/src/actions/maxGraphemes/maxGraphemes.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { maxGraphemes, type MaxGraphemesAction, type MaxGraphemesIssue, } from './maxGraphemes.ts'; describe('maxGraphemes', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = MaxGraphemesAction; expectTypeOf(maxGraphemes(10)).toEqualTypeOf(); expectTypeOf( maxGraphemes(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( maxGraphemes(10, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( maxGraphemes string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Input = 'example string'; type Action = MaxGraphemesAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< MaxGraphemesIssue >(); }); }); }); ================================================ FILE: library/src/actions/maxGraphemes/maxGraphemes.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { _getGraphemeCount } from '../../utils/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { maxGraphemes, type MaxGraphemesAction, type MaxGraphemesIssue, } from './maxGraphemes.ts'; describe('maxGraphemes', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'max_graphemes', reference: maxGraphemes, expects: '<=5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: MaxGraphemesAction = { ...baseAction, message: undefined, }; expect(maxGraphemes(5)).toStrictEqual(action); expect(maxGraphemes(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(maxGraphemes(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies MaxGraphemesAction); }); test('with function message', () => { const message = () => 'message'; expect(maxGraphemes(5, message)).toStrictEqual({ ...baseAction, message, } satisfies MaxGraphemesAction); }); }); describe('should return dataset without issues', () => { const action = maxGraphemes(5); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid strings', () => { expectNoActionIssue(action, ['', ' ', '1', 'foo', '12345', '12 45']); }); test('for valid emoji', () => { expectNoActionIssue(action, ['😀', '😀👋🏼', '😀👋🏼🧩👩🏻‍🏫', '😀👋🏼🧩👩🏻‍🏫🫥']); }); }); describe('should return dataset with issues', () => { const action = maxGraphemes(5, 'message'); const baseIssue: Omit< MaxGraphemesIssue, 'input' | 'received' > = { kind: 'validation', type: 'max_graphemes', expected: '<=5', message: 'message', requirement: 5, }; test('for invalid strings', () => { expectActionIssue( action, baseIssue, ['123456', '12345 ', '123456789', 'foo bar baz'], (value) => `${_getGraphemeCount(value)}` ); }); test('for invalid emoji', () => { expectActionIssue( action, baseIssue, ['😀👋🏼🧩👩🏻‍🏫🫥🫠', '😀👋🏼🧩👩🏻‍🏫🫥🫠🧑‍💻👻🥎'], (value) => `${_getGraphemeCount(value)}` ); }); }); }); ================================================ FILE: library/src/actions/maxGraphemes/maxGraphemes.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _getGraphemeCount } from '../../utils/index.ts'; /** * Max graphemes issue interface. */ export interface MaxGraphemesIssue< TInput extends string, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'max_graphemes'; /** * The expected property. */ readonly expected: `<=${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The maximum graphemes. */ readonly requirement: TRequirement; } /** * Max graphemes action interface. */ export interface MaxGraphemesAction< TInput extends string, TRequirement extends number, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation< TInput, TInput, MaxGraphemesIssue > { /** * The action type. */ readonly type: 'max_graphemes'; /** * The action reference. */ readonly reference: typeof maxGraphemes; /** * The expected property. */ readonly expects: `<=${TRequirement}`; /** * The maximum graphemes. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a max graphemes validation action. * * @param requirement The maximum graphemes. * * @returns A max graphemes action. */ export function maxGraphemes< TInput extends string, const TRequirement extends number, >( requirement: TRequirement ): MaxGraphemesAction; /** * Creates a max graphemes validation action. * * @param requirement The maximum graphemes. * @param message The error message. * * @returns A max graphemes action. */ export function maxGraphemes< TInput extends string, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): MaxGraphemesAction; // @__NO_SIDE_EFFECTS__ export function maxGraphemes( requirement: number, message?: ErrorMessage> ): MaxGraphemesAction< string, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'max_graphemes', reference: maxGraphemes, async: false, expects: `<=${requirement}`, requirement, message, '~run'(dataset, config) { if (dataset.typed) { const count = _getGraphemeCount(dataset.value); if (count > this.requirement) { _addIssue(this, 'graphemes', dataset, config, { received: `${count}`, }); } } return dataset; }, }; } ================================================ FILE: library/src/actions/maxLength/index.ts ================================================ export * from './maxLength.ts'; ================================================ FILE: library/src/actions/maxLength/maxLength.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { maxLength, type MaxLengthAction, type MaxLengthIssue, } from './maxLength.ts'; describe('maxLength', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = MaxLengthAction; expectTypeOf(maxLength(10)).toEqualTypeOf(); expectTypeOf( maxLength(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( maxLength(10, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( maxLength string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = MaxLengthAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< MaxLengthIssue >(); }); }); }); ================================================ FILE: library/src/actions/maxLength/maxLength.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { maxLength, type MaxLengthAction, type MaxLengthIssue, } from './maxLength.ts'; describe('maxLength', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'max_length', reference: maxLength, expects: '<=5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: MaxLengthAction = { ...baseAction, message: undefined, }; expect(maxLength(5)).toStrictEqual(action); expect(maxLength(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(maxLength(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies MaxLengthAction); }); test('with function message', () => { const message = () => 'message'; expect(maxLength(5, message)).toStrictEqual({ ...baseAction, message, } satisfies MaxLengthAction); }); }); describe('should return dataset without issues', () => { const action = maxLength(5); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid strings', () => { expectNoActionIssue(action, ['', 'foo', '12345']); }); test('for valid arrays', () => { expectNoActionIssue(action, [[], ['foo', 'bar'], [1, 2, 3, 4, 5]]); }); }); describe('should return dataset with issues', () => { const action = maxLength(5, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'max_length', expected: '<=5', message: 'message', requirement: 5, }; test('for invalid strings', () => { expectActionIssue( action, baseIssue, ['123456', 'foobarbaz123'], (value) => `${value.length}` ); }); test('for invalid arrays', () => { expectActionIssue( action, baseIssue, [[1, 2, 3, 4, 5, 6], Array(999)], (value) => `${value.length}` ); }); }); }); ================================================ FILE: library/src/actions/maxLength/maxLength.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { LengthInput } from '../types.ts'; /** * Max length issue interface. */ export interface MaxLengthIssue< TInput extends LengthInput, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'max_length'; /** * The expected property. */ readonly expected: `<=${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The maximum length. */ readonly requirement: TRequirement; } /** * Max length action interface. */ export interface MaxLengthAction< TInput extends LengthInput, TRequirement extends number, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'max_length'; /** * The action reference. */ readonly reference: typeof maxLength; /** * The expected property. */ readonly expects: `<=${TRequirement}`; /** * The maximum length. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a max length validation action. * * @param requirement The maximum length. * * @returns A max length action. */ export function maxLength< TInput extends LengthInput, const TRequirement extends number, >(requirement: TRequirement): MaxLengthAction; /** * Creates a max length validation action. * * @param requirement The maximum length. * @param message The error message. * * @returns A max length action. */ export function maxLength< TInput extends LengthInput, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): MaxLengthAction; // @__NO_SIDE_EFFECTS__ export function maxLength( requirement: number, message?: ErrorMessage> ): MaxLengthAction< LengthInput, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'max_length', reference: maxLength, async: false, expects: `<=${requirement}`, requirement, message, '~run'(dataset, config) { if (dataset.typed && dataset.value.length > this.requirement) { _addIssue(this, 'length', dataset, config, { received: `${dataset.value.length}`, }); } return dataset; }, }; } ================================================ FILE: library/src/actions/maxSize/index.ts ================================================ export * from './maxSize.ts'; ================================================ FILE: library/src/actions/maxSize/maxSize.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { maxSize, type MaxSizeAction, type MaxSizeIssue } from './maxSize.ts'; describe('maxSize', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = MaxSizeAction; expectTypeOf(maxSize(10)).toEqualTypeOf(); expectTypeOf( maxSize(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(maxSize(10, 'message')).toEqualTypeOf< MaxSizeAction >(); }); test('with function message', () => { expectTypeOf( maxSize string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = MaxSizeAction, 10, undefined>; test('of input', () => { expectTypeOf>().toEqualTypeOf>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< MaxSizeIssue, 10> >(); }); }); }); ================================================ FILE: library/src/actions/maxSize/maxSize.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { MapIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { maxSize, type MaxSizeAction, type MaxSizeIssue } from './maxSize.ts'; describe('maxSize', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'max_size', reference: maxSize, expects: '<=5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: MaxSizeAction = { ...baseAction, message: undefined, }; expect(maxSize(5)).toStrictEqual(action); expect(maxSize(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(maxSize(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies MaxSizeAction); }); test('with function message', () => { const message = () => 'message'; expect(maxSize(5, message)).toStrictEqual({ ...baseAction, message, } satisfies MaxSizeAction); }); }); describe('should return dataset without issues', () => { const action = maxSize(3); test('for untyped inputs', () => { const issues: [MapIssue] = [ { kind: 'schema', type: 'map', input: null, expected: 'Map', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid maps', () => { expectNoActionIssue(action, [ new Map(), new Map([[1, null]]), new Map([ [1, 'one'], ['2', 'two'], ]), new Map([ ['1', 'one'], [2, null], [true, null], ]), ]); }); test('for valid sets', () => { expectNoActionIssue(action, [ new Set(), new Set([1]), new Set([1, '2']), new Set(['1', 2, { value: 3 }]), ]); }); test('for valid blobs', () => { expectNoActionIssue(action, [ new Blob([]), new Blob(['1']), new Blob(['hi'], { type: 'text/plain' }), new Blob([new Uint8Array([72, 101, 121])]), // 'Hey' ]); }); }); describe('should return dataset with issues', () => { const action = maxSize(3, 'message'); const baseIssue: Omit< MaxSizeIssue, 3>, 'input' | 'received' > = { kind: 'validation', type: 'max_size', expected: '<=3', message: 'message', requirement: 3, }; test('for invalid maps', () => { expectActionIssue( action, baseIssue, [ new Map([ [1, 'one'], [2, 'two'], [3, 'three'], [4, 'four'], ]), new Map([ ['one', 'foo'], ['two', 123], ['three', true], ['four', null], ['five', undefined], ['six', {}], ['seven', []], ]), ], (value) => `${value.size}` ); }); test('for invalid sets', () => { expectActionIssue( action, baseIssue, [ new Set([1, 2, 3, 4]), new Set([1, null, '3', true, undefined, [], {}]), ], (value) => `${value.size}` ); }); test('for invalid blobs', () => { expectActionIssue( action, baseIssue, [ new Blob(['Hey!'], { type: 'text/plain' }), new Blob( [new Uint8Array([72, 101, 108, 108, 111])], // 'Hello' { type: 'text/plain' } ), new Blob(['foobarbaz123']), ], (value) => `${value.size}` ); }); }); }); ================================================ FILE: library/src/actions/maxSize/maxSize.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { SizeInput } from '../types.ts'; /** * Max size issue interface. */ export interface MaxSizeIssue< TInput extends SizeInput, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'max_size'; /** * The expected property. */ readonly expected: `<=${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The maximum size. */ readonly requirement: TRequirement; } /** * Max size action interface. */ export interface MaxSizeAction< TInput extends SizeInput, TRequirement extends number, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'max_size'; /** * The action reference. */ readonly reference: typeof maxSize; /** * The expected property. */ readonly expects: `<=${TRequirement}`; /** * The maximum size. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a max size validation action. * * @param requirement The maximum size. * * @returns A max size action. */ export function maxSize< TInput extends SizeInput, const TRequirement extends number, >(requirement: TRequirement): MaxSizeAction; /** * Creates a max size validation action. * * @param requirement The maximum size. * @param message The error message. * * @returns A max size action. */ export function maxSize< TInput extends SizeInput, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): MaxSizeAction; // @__NO_SIDE_EFFECTS__ export function maxSize( requirement: number, message?: ErrorMessage> ): MaxSizeAction< SizeInput, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'max_size', reference: maxSize, async: false, expects: `<=${requirement}`, requirement, message, '~run'(dataset, config) { if (dataset.typed && dataset.value.size > this.requirement) { _addIssue(this, 'size', dataset, config, { received: `${dataset.value.size}`, }); } return dataset; }, }; } ================================================ FILE: library/src/actions/maxValue/index.ts ================================================ export * from './maxValue.ts'; ================================================ FILE: library/src/actions/maxValue/maxValue.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { maxValue, type MaxValueAction, type MaxValueIssue, } from './maxValue.ts'; describe('maxValue', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = MaxValueAction; expectTypeOf(maxValue(10)).toEqualTypeOf(); expectTypeOf( maxValue(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( maxValue(10, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( maxValue string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = MaxValueAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< MaxValueIssue >(); }); }); }); ================================================ FILE: library/src/actions/maxValue/maxValue.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { NumberIssue } from '../../schemas/index.ts'; import { _stringify } from '../../utils/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { maxValue, type MaxValueAction } from './maxValue.ts'; describe('maxValue', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'max_value', reference: maxValue, expects: '<=5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: MaxValueAction = { ...baseAction, message: undefined, }; expect(maxValue(5)).toStrictEqual(action); expect(maxValue(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(maxValue(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies MaxValueAction); }); test('with function message', () => { const message = () => 'message'; expect(maxValue(5, message)).toStrictEqual({ ...baseAction, message, } satisfies MaxValueAction); }); }); describe('should return dataset without issues', () => { test('for untyped inputs', () => { const issues: [NumberIssue] = [ { kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', message: 'message', }, ]; expect( maxValue(1)['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues }); }); test('for valid bigints', () => { expectNoActionIssue(maxValue(10n), [-9999n, 0n, 10n]); }); test('for valid non-bigints', () => { expectNoActionIssue(maxValue(10n), [ '-10', '', ' ', '0', '10', ' 10 ', -10, 0, 10, -Infinity, -10.0, 0.0, 10.0, false, true, new Date(-10), new Date(0), new Date(10), ]); expectNoActionIssue(maxValue(1n), [ '-1', '', ' ', '0', ' 0 ', '1', -Infinity, -1, 0, 1, -1.0, 0.0, 1.0, false, true, new Date(-1), new Date(0), new Date(1), ]); expectNoActionIssue(maxValue(0n), [ '-1', ' -1 ', ' ', '0', -Infinity, -1, -0, -1.0, -0.0, false, new Date(-1), new Date(0), ]); }); test('for valid booleans', () => { expectNoActionIssue(maxValue(true), [true, false]); expectNoActionIssue(maxValue(false), [false]); }); test('for valid non-booleans', () => { expectNoActionIssue(maxValue(true), [ '-1', '-1.0', '', ' ', '0', '0.0', ' 0 ', '1', '1.0', -Infinity, -1, 0, 0.0, 1, new Date(-1), new Date(0), new Date(1), -1n, 0n, 1n, ]); expectNoActionIssue(maxValue(false), [ '-1', '-1.0', ' -1 ', ' ', '0', '0.0', -Infinity, -1, -1.0, -0.5, -0, new Date(-1), new Date(0), -1n, 0n, ]); }); test('for valid dates', () => { const date = new Date(); expectNoActionIssue(maxValue(date), [ new Date(0), new Date(+date - 999999), date, ]); }); test('for valid non-dates', () => { const date1 = new Date(10); expectNoActionIssue(maxValue(date1), [ '-10', '-10.0', '', ' ', '0', '0.0', '10', '10.0', ' 10 ', -10, 0, 10, -Infinity, -10.0, 0.0, 10.0, false, true, -10n, 0n, 10n, ]); const date2 = new Date(1); expectNoActionIssue(maxValue(date2), [ '-1', '-1.0', '', ' ', '0', '0.0', ' 0 ', '1', '1.0', -Infinity, -1, 0, 0.0, 1, false, true, -1n, 0n, 1n, ]); const date3 = new Date(0); expectNoActionIssue(maxValue(date3), [ '-1', '-1.0', ' -1 ', ' ', '0', '0.0', -Infinity, -1, -1.0, -0.5, -0, false, -1n, 0n, ]); }); test('for valid numbers', () => { expectNoActionIssue(maxValue(10), [Number.MIN_VALUE, 0, 10]); }); test('for valid non-numbers', () => { expectNoActionIssue(maxValue(10), [ '-10', '-10.0', '', ' ', '0', '0.0', '10', '10.0', ' 10 ', false, true, new Date(-10), new Date(0), new Date(10), -10n, 0n, 10n, ]); expectNoActionIssue(maxValue(1), [ '-1', '-1.0', '', ' ', '0', '0.0', ' 0 ', '1', '1.0', false, true, new Date(-1), new Date(0), new Date(1), -1n, 0n, 1n, ]); expectNoActionIssue(maxValue(0), [ '-1', '-1.0', ' -1 ', ' ', '0', '0.0', false, new Date(-1), new Date(0), -1n, 0n, ]); }); test('for valid strings', () => { expectNoActionIssue(maxValue('2024'), ['', '1234', '2024']); }); test('for valid non-strings', () => { expectNoActionIssue(maxValue('10'), [ -10, 0, 10, -Infinity, -10.0, 0.0, 10.0, false, true, new Date(-10), new Date(0), new Date(10), -10n, 0n, 10n, ]); expectNoActionIssue(maxValue('1'), [ -Infinity, -1, 0, 0.0, 1, false, true, new Date(-1), new Date(0), new Date(1), -1n, 0n, 1n, ]); expectNoActionIssue(maxValue('0'), [ -Infinity, -1, -1.0, -0.5, -0, false, new Date(-1), new Date(0), -1n, 0n, ]); }); }); describe('should return dataset with issues', () => { const baseInfo = { kind: 'validation', type: 'max_value', message: 'message', } as const; const getReceived = (value: unknown): string => value instanceof Date ? value.toJSON() : _stringify(value); test('for invalid bigints', () => { expectActionIssue( maxValue(10n, 'message'), { ...baseInfo, expected: '<=10', requirement: 10n }, [11n, 9999n] ); }); test('for invalid non-bigints', () => { expectActionIssue( maxValue(123n, 'message'), { ...baseInfo, expected: '<=123', requirement: 123n }, [ 'nan', '123px', '+ 123', '123.0', '126', 124, 124.0, Infinity, NaN, new Date(124), ], getReceived ); expectActionIssue( maxValue(1n, 'message'), { ...baseInfo, expected: '<=1', requirement: 1n }, ['nan', '1px', '+ 1', '1.0', '2', 2, 2.0, Infinity, NaN, new Date(2)], getReceived ); expectActionIssue( maxValue(0n, 'message'), { ...baseInfo, expected: '<=0', requirement: 0n }, [ 'nan', '0px', '+ 0', '0.0', '1', 0.5, 1, 1.0, Infinity, NaN, true, new Date(1), ], getReceived ); }); test('for invalid booleans', () => { expectActionIssue( maxValue(false, 'message'), { ...baseInfo, expected: '<=false', requirement: false }, [true] ); }); test('for invalid non-booleans', () => { expectActionIssue( maxValue(false, 'message'), { ...baseInfo, expected: '<=false', requirement: false }, ['nan', '0px', '+ 0', '1', 0.5, 1, 1.0, Infinity, NaN, new Date(1), 1n], getReceived ); expectActionIssue( maxValue(true, 'message'), { ...baseInfo, expected: '<=true', requirement: true }, ['nan', '1px', '+ 1', '2', 2, 2.0, Infinity, NaN, new Date(2), 2n], getReceived ); }); test('for invalid dates', () => { const date = new Date(); expectActionIssue( maxValue(date, 'message'), { ...baseInfo, expected: `<=${date.toJSON()}`, requirement: date }, [new Date(+date + 1), new Date(+date + 999999)], (value) => value.toJSON() ); }); test('for invalid non-dates', () => { const date1 = new Date(123); expectActionIssue( maxValue(date1, 'message'), { ...baseInfo, expected: `<=${date1.toJSON()}`, requirement: date1 }, [ 'nan', '123px', '+ 123', '123.5', '126', 124, 124.0, Infinity, NaN, 124n, ], getReceived ); const date2 = new Date(1); expectActionIssue( maxValue(date2, 'message'), { ...baseInfo, expected: `<=${date2.toJSON()}`, requirement: date2 }, ['nan', '1px', '+ 1', '2', 2, 2.0, Infinity, NaN, 2n], getReceived ); const date3 = new Date(0); expectActionIssue( maxValue(date3, 'message'), { ...baseInfo, expected: `<=${date3.toJSON()}`, requirement: date3 }, ['nan', '0px', '+ 0', '1', 0.5, 1, 1.0, Infinity, NaN, true, 1n], getReceived ); }); test('for invalid numbers', () => { expectActionIssue( maxValue(10, 'message'), { ...baseInfo, expected: '<=10', requirement: 10 }, [11, 9999, Number.MAX_VALUE, NaN] ); }); test('for invalid non-numbers', () => { expectActionIssue( maxValue(123, 'message'), { ...baseInfo, expected: '<=123', requirement: 123 }, ['nan', '123px', '+ 123', '126', new Date(124), 124n], getReceived ); expectActionIssue( maxValue(1, 'message'), { ...baseInfo, expected: '<=1', requirement: 1 }, ['nan', '1px', '+ 1', '2', new Date(2), 2n], getReceived ); expectActionIssue( maxValue(0, 'message'), { ...baseInfo, expected: '<=0', requirement: 0 }, ['nan', '0px', '+ 0', '0.5', '1', true, new Date(1), 1n], getReceived ); }); test('for invalid strings', () => { expectActionIssue( maxValue('2024', 'message'), { ...baseInfo, expected: '<="2024"', requirement: '2024' }, ['2025', '9999', 'XYZ'] ); }); test('for invalid non-strings', () => { expectActionIssue( maxValue('123', 'message'), { ...baseInfo, expected: '<="123"', requirement: '123' }, [123.5, 124, 124.0, Infinity, NaN, new Date(124), 124n], getReceived ); expectActionIssue( maxValue('1', 'message'), { ...baseInfo, expected: '<="1"', requirement: '1' }, [2, 2.0, Infinity, NaN, new Date(2), 2n], getReceived ); expectActionIssue( maxValue('0', 'message'), { ...baseInfo, expected: '<="0"', requirement: '0' }, [0.5, 1, 1.0, Infinity, NaN, true, new Date(1), 1n], getReceived ); }); }); }); ================================================ FILE: library/src/actions/maxValue/maxValue.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _stringify } from '../../utils/index.ts'; import type { ValueInput } from '../types.ts'; /** * Max value issue interface. */ export interface MaxValueIssue< TInput extends ValueInput, TRequirement extends ValueInput, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'max_value'; /** * The expected property. */ readonly expected: `<=${string}`; /** * The maximum value. */ readonly requirement: TRequirement; } /** * Max value action interface. */ export interface MaxValueAction< TInput extends ValueInput, TRequirement extends TInput, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'max_value'; /** * The action reference. */ readonly reference: typeof maxValue; /** * The expected property. */ readonly expects: `<=${string}`; /** * The maximum value. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a max value validation action. * * @param requirement The maximum value. * * @returns A max value action. */ export function maxValue< TInput extends ValueInput, const TRequirement extends TInput, >(requirement: TRequirement): MaxValueAction; /** * Creates a max value validation action. * * @param requirement The maximum value. * @param message The error message. * * @returns A max value action. */ export function maxValue< TInput extends ValueInput, const TRequirement extends TInput, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): MaxValueAction; // @__NO_SIDE_EFFECTS__ export function maxValue( requirement: ValueInput, message?: ErrorMessage> ): MaxValueAction< ValueInput, ValueInput, ErrorMessage> | undefined > { return { kind: 'validation', type: 'max_value', reference: maxValue, async: false, expects: `<=${ requirement instanceof Date ? requirement.toJSON() : _stringify(requirement) }`, requirement, message, '~run'(dataset, config) { if (dataset.typed && !(dataset.value <= this.requirement)) { _addIssue(this, 'value', dataset, config, { received: dataset.value instanceof Date ? dataset.value.toJSON() : _stringify(dataset.value), }); } return dataset; }, }; } ================================================ FILE: library/src/actions/maxWords/index.ts ================================================ export * from './maxWords.ts'; ================================================ FILE: library/src/actions/maxWords/maxWords.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { maxWords, type MaxWordsAction, type MaxWordsIssue, } from './maxWords.ts'; describe('maxWords', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = MaxWordsAction; expectTypeOf(maxWords('en', 3)).toEqualTypeOf(); expectTypeOf( maxWords('en', 3, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( maxWords('en', 3, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( maxWords string>('en', 3, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Input = 'foo bar baz'; type Action = MaxWordsAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< MaxWordsIssue >(); }); }); }); ================================================ FILE: library/src/actions/maxWords/maxWords.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { _getWordCount } from '../../utils/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { maxWords, type MaxWordsAction, type MaxWordsIssue, } from './maxWords.ts'; describe('maxWords', () => { describe('should return action object', () => { const baseAction: Omit< MaxWordsAction, 'message' > = { kind: 'validation', type: 'max_words', reference: maxWords, expects: '<=3', locales: 'en', requirement: 3, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: MaxWordsAction = { ...baseAction, message: undefined, }; expect(maxWords('en', 3)).toStrictEqual(action); expect(maxWords('en', 3, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(maxWords('en', 3, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies MaxWordsAction); }); test('with function message', () => { const message = () => 'message'; expect(maxWords('en', 3, message)).toStrictEqual({ ...baseAction, message, } satisfies MaxWordsAction); }); }); describe('should return dataset without issues', () => { const action = maxWords('en', 3); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid strings', () => { expectNoActionIssue(action, [ '', ' ', 'foo', 'foo bar', 'for bar baz', 'Lorem ipsum?', 'Lorem ipsum dolor?', 'Hi, welcome!', 'Hi, welcome home!', ]); }); }); describe('should return dataset with issues', () => { const action = maxWords('en', 3, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'max_words', expected: '<=3', message: 'message', requirement: 3, }; test('for invalid strings', () => { expectActionIssue( action, baseIssue, [ 'for bar baz qux', 'Lorem ipsum dolor sit?', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit?', 'Hi, welcome home! How are you?', ], (value) => `${_getWordCount('en', value)}` ); }); }); }); ================================================ FILE: library/src/actions/maxWords/maxWords.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _getWordCount } from '../../utils/index.ts'; /** * Max words issue interface. */ export interface MaxWordsIssue< TInput extends string, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'max_words'; /** * The expected property. */ readonly expected: `<=${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The maximum words. */ readonly requirement: TRequirement; } /** * Max words action interface. */ export interface MaxWordsAction< TInput extends string, TLocales extends Intl.LocalesArgument, TRequirement extends number, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'max_words'; /** * The action reference. */ readonly reference: typeof maxWords; /** * The expected property. */ readonly expects: `<=${TRequirement}`; /** * The locales to be used. */ readonly locales: TLocales; /** * The maximum words. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a max words validation action. * * @param locales The locales to be used. * @param requirement The maximum words. * * @returns A max words action. */ export function maxWords< TInput extends string, TLocales extends Intl.LocalesArgument, const TRequirement extends number, >( locales: TLocales, requirement: TRequirement ): MaxWordsAction; /** * Creates a max words validation action. * * @param locales The locales to be used. * @param requirement The maximum words. * @param message The error message. * * @returns A max words action. */ export function maxWords< TInput extends string, TLocales extends Intl.LocalesArgument, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( locales: TLocales, requirement: TRequirement, message: TMessage ): MaxWordsAction; // @__NO_SIDE_EFFECTS__ export function maxWords( locales: Intl.LocalesArgument, requirement: number, message?: ErrorMessage> ): MaxWordsAction< string, Intl.LocalesArgument, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'max_words', reference: maxWords, async: false, expects: `<=${requirement}`, locales, requirement, message, '~run'(dataset, config) { if (dataset.typed) { const count = _getWordCount(this.locales, dataset.value); if (count > this.requirement) { _addIssue(this, 'words', dataset, config, { received: `${count}`, }); } } return dataset; }, }; } ================================================ FILE: library/src/actions/metadata/index.ts ================================================ export * from './metadata.ts'; ================================================ FILE: library/src/actions/metadata/metadata.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { metadata, type MetadataAction } from './metadata.ts'; describe('metadata', () => { type Action = MetadataAction; test('should return action object', () => { expectTypeOf( metadata({ key: 'foo' }) ).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/metadata/metadata.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { metadata, type MetadataAction } from './metadata.ts'; describe('metadata', () => { test('should return action object', () => { expect(metadata({ key: 'foo' })).toStrictEqual({ kind: 'metadata', type: 'metadata', reference: metadata, metadata: { key: 'foo' }, } satisfies MetadataAction); }); }); ================================================ FILE: library/src/actions/metadata/metadata.ts ================================================ import type { BaseMetadata } from '../../types/index.ts'; /** * Metadata action interface. */ export interface MetadataAction< TInput, TMetadata extends Record, > extends BaseMetadata { /** * The action type. */ readonly type: 'metadata'; /** * The action reference. */ readonly reference: typeof metadata; /** * The metadata object. */ readonly metadata: TMetadata; } /** * Creates a custom metadata action. * * @param metadata_ The metadata object. * * @returns A metadata action. */ // @__NO_SIDE_EFFECTS__ export function metadata< TInput, const TMetadata extends Record, >(metadata_: TMetadata): MetadataAction { return { kind: 'metadata', type: 'metadata', reference: metadata, metadata: metadata_, }; } ================================================ FILE: library/src/actions/mimeType/index.ts ================================================ export * from './mimeType.ts'; ================================================ FILE: library/src/actions/mimeType/mimeType.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { mimeType, type MimeTypeAction, type MimeTypeIssue, } from './mimeType.ts'; describe('mimeType', () => { const requirement = ['text/html', 'image/png'] as const; type Requirement = typeof requirement; describe('should return action object', () => { test('with undefined message', () => { type Action = MimeTypeAction; expectTypeOf(mimeType(requirement)).toEqualTypeOf(); expectTypeOf(mimeType(requirement, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(mimeType(requirement, 'message')).toEqualTypeOf< MimeTypeAction >(); }); test('with function message', () => { expectTypeOf(mimeType(requirement, () => 'message')).toEqualTypeOf< MimeTypeAction string> >(); }); }); describe('should infer correct types', () => { type Action = MimeTypeAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< MimeTypeIssue >(); }); }); }); ================================================ FILE: library/src/actions/mimeType/mimeType.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { FileIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { mimeType, type MimeTypeAction, type MimeTypeIssue, } from './mimeType.ts'; describe('mimeType', () => { const requirement = ['text/html', 'image/png'] as const; type Requirement = typeof requirement; describe('should return action object', () => { const baseAction: Omit< MimeTypeAction, 'message' > = { kind: 'validation', type: 'mime_type', reference: mimeType, expects: '("text/html" | "image/png")', requirement, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: MimeTypeAction = { ...baseAction, message: undefined, }; expect(mimeType(requirement)).toStrictEqual(action); expect(mimeType(requirement, undefined)).toStrictEqual(action); }); test('with string message', () => { const message = 'message'; expect(mimeType(requirement, message)).toStrictEqual({ ...baseAction, message, } satisfies MimeTypeAction); }); test('with function message', () => { const message = () => 'message'; expect(mimeType(requirement, message)).toStrictEqual({ ...baseAction, message, } satisfies MimeTypeAction); }); }); describe('should return dataset without issues', () => { const action = mimeType(requirement); test('for untyped inputs', () => { const issues: [FileIssue] = [ { kind: 'schema', type: 'file', input: null, expected: 'File', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid MIME types', () => { expectNoActionIssue(action, [ new Blob(['foo'], { type: 'text/html' }), new Blob(['foo'], { type: 'image/png' }), ]); }); }); describe('should return dataset with issues', () => { const action = mimeType(requirement, 'message'); const baseIssue: Omit< MimeTypeIssue, 'input' | 'received' | 'expected' | 'requirement' > = { kind: 'validation', type: 'mime_type', message: 'message', }; test('for valid MIME types', () => { expectActionIssue( action, { ...baseIssue, expected: '("text/html" | "image/png")', requirement }, [ new Blob(['foo'], { type: 'text/plain' }), new Blob(['foo'], { type: 'image/jpeg' }), ], (input) => `"${input.type}"` ); }); test('for empty requirement', () => { expectActionIssue( mimeType([], 'message'), { ...baseIssue, expected: 'never', requirement: [] }, [ new Blob(['foo'], { type: 'text/plain' }), new Blob(['foo'], { type: 'image/jpeg' }), ], (input) => `"${input.type}"` ); }); }); }); ================================================ FILE: library/src/actions/mimeType/mimeType.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _joinExpects } from '../../utils/index.ts'; /** * Requirement type. */ type Requirement = readonly `${string}/${string}`[]; /** * MIME type issue interface. */ export interface MimeTypeIssue< TInput extends Blob, TRequirement extends Requirement, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'mime_type'; /** * The expected input. */ readonly expected: string; /** * The received input. */ readonly received: `"${string}"`; /** * The MIME types. */ readonly requirement: TRequirement; } /** * MIME type action interface. */ export interface MimeTypeAction< TInput extends Blob, TRequirement extends Requirement, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'mime_type'; /** * The action reference. */ readonly reference: typeof mimeType; /** * The expected property. */ readonly expects: string; /** * The MIME types. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a [MIME type](https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/MIME_types) validation action. * * @param requirement The MIME types. * * @returns A MIME type action. */ export function mimeType< TInput extends Blob, const TRequirement extends Requirement, >(requirement: TRequirement): MimeTypeAction; /** * Creates a [MIME type](https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/MIME_types) validation action. * * @param requirement The MIME types. * @param message The error message. * * @returns A MIME type action. */ export function mimeType< TInput extends Blob, const TRequirement extends Requirement, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): MimeTypeAction; // @__NO_SIDE_EFFECTS__ export function mimeType( requirement: Requirement, message?: ErrorMessage> ): MimeTypeAction< Blob, Requirement, ErrorMessage> | undefined > { return { kind: 'validation', type: 'mime_type', reference: mimeType, async: false, expects: _joinExpects( requirement.map((option) => `"${option}"`), '|' ), requirement, message, '~run'(dataset, config) { if ( dataset.typed && !this.requirement.includes(dataset.value.type as `${string}/${string}`) ) { _addIssue(this, 'MIME type', dataset, config, { received: `"${dataset.value.type}"`, }); } return dataset; }, }; } ================================================ FILE: library/src/actions/minBytes/index.ts ================================================ export * from './minBytes.ts'; ================================================ FILE: library/src/actions/minBytes/minBytes.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { minBytes, type MinBytesAction, type MinBytesIssue, } from './minBytes.ts'; describe('minBytes', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = MinBytesAction; expectTypeOf(minBytes(10)).toEqualTypeOf(); expectTypeOf( minBytes(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( minBytes(10, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( minBytes string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = MinBytesAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< MinBytesIssue >(); }); }); }); ================================================ FILE: library/src/actions/minBytes/minBytes.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { minBytes, type MinBytesAction, type MinBytesIssue, } from './minBytes.ts'; describe('minBytes', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'min_bytes', reference: minBytes, expects: '>=5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: MinBytesAction = { ...baseAction, message: undefined, }; expect(minBytes(5)).toStrictEqual(action); expect(minBytes(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(minBytes(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies MinBytesAction); }); test('with function message', () => { const message = () => 'message'; expect(minBytes(5, message)).toStrictEqual({ ...baseAction, message, } satisfies MinBytesAction); }); }); describe('should return dataset without issues', () => { const action = minBytes(5); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid strings', () => { expectNoActionIssue(action, ['12345', '123456', 'foobarbaz123']); }); test('for valid chars', () => { expectNoActionIssue(action, [ '🤖!', // '🤖' is 4 bytes 'あい', // 'あい' is 6 bytes ]); }); }); describe('should return dataset with issues', () => { const action = minBytes(5, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'min_bytes', expected: '>=5', message: 'message', requirement: 5, }; const getReceived = (value: string) => `${new TextEncoder().encode(value).length}`; test('for invalid strings', () => { expectActionIssue(action, baseIssue, ['', '1', '1234'], getReceived); }); test('for invalid chars', () => { expectActionIssue( action, baseIssue, [ 'あ', // 'あ' is 3 bytes '🤖', // '🤖' is 4 bytes ], getReceived ); }); }); }); ================================================ FILE: library/src/actions/minBytes/minBytes.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _getByteCount } from '../../utils/index.ts'; /** * Min bytes issue interface. */ export interface MinBytesIssue< TInput extends string, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'min_bytes'; /** * The expected property. */ readonly expected: `>=${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The minimum bytes. */ readonly requirement: TRequirement; } /** * Min bytes action interface. */ export interface MinBytesAction< TInput extends string, TRequirement extends number, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'min_bytes'; /** * The action reference. */ readonly reference: typeof minBytes; /** * The expected property. */ readonly expects: `>=${TRequirement}`; /** * The minimum bytes. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a min [bytes](https://en.wikipedia.org/wiki/Byte) validation action. * * @param requirement The minimum bytes. * * @returns A min bytes action. */ export function minBytes< TInput extends string, const TRequirement extends number, >(requirement: TRequirement): MinBytesAction; /** * Creates a min [bytes](https://en.wikipedia.org/wiki/Byte) validation action. * * @param requirement The minimum bytes. * @param message The error message. * * @returns A min bytes action. */ export function minBytes< TInput extends string, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): MinBytesAction; // @__NO_SIDE_EFFECTS__ export function minBytes( requirement: number, message?: ErrorMessage> ): MinBytesAction< string, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'min_bytes', reference: minBytes, async: false, expects: `>=${requirement}`, requirement, message, '~run'(dataset, config) { if (dataset.typed) { const length = _getByteCount(dataset.value); if (length < this.requirement) { _addIssue(this, 'bytes', dataset, config, { received: `${length}`, }); } } return dataset; }, }; } ================================================ FILE: library/src/actions/minEntries/index.ts ================================================ export * from './minEntries.ts'; ================================================ FILE: library/src/actions/minEntries/minEntries.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { minEntries, type MinEntriesAction, type MinEntriesIssue, } from './minEntries.ts'; describe('minEntries', () => { type Input = Record; describe('should return action object', () => { test('with undefined message', () => { type Action = MinEntriesAction; expectTypeOf(minEntries(10)).toEqualTypeOf(); expectTypeOf( minEntries(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( minEntries(10, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( minEntries string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = MinEntriesAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< MinEntriesIssue >(); }); }); }); ================================================ FILE: library/src/actions/minEntries/minEntries.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { RecordIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { minEntries, type MinEntriesAction, type MinEntriesIssue, } from './minEntries.ts'; describe('minEntries', () => { type Input = Record; describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'min_entries', reference: minEntries, expects: '>=2', requirement: 2, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: MinEntriesAction = { ...baseAction, message: undefined, }; expect(minEntries(2)).toStrictEqual(action); expect(minEntries(2, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(minEntries(2, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies MinEntriesAction); }); test('with function message', () => { const message = () => 'message'; expect(minEntries(2, message)).toStrictEqual({ ...baseAction, message, } satisfies MinEntriesAction); }); }); describe('should return dataset without issues', () => { const action = minEntries(3); test('for untyped inputs', () => { const issues: [RecordIssue] = [ { kind: 'schema', type: 'record', input: null, expected: 'Object', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid objects', () => { expectNoActionIssue(action, [ { foo: 1, bar: 2, baz: 3 }, { foo: 1, bar: 2, baz: 3, qux: 4 }, { foo: 1, bar: 2, baz: 3, qux: 4, quux: 5 }, ]); }); }); describe('should return dataset with issues', () => { const action = minEntries(3, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'min_entries', expected: '>=3', message: 'message', requirement: 3, }; test('for invalid objects', () => { expectActionIssue( action, baseIssue, [{}, { foo: 1 }, { foo: 1, bar: 2 }], (value) => `${Object.keys(value).length}` ); }); }); }); ================================================ FILE: library/src/actions/minEntries/minEntries.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { EntriesInput } from '../types.ts'; /** * Min entries issue interface. * * @beta */ export interface MinEntriesIssue< TInput extends EntriesInput, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'min_entries'; /** * The expected property. */ readonly expected: `>=${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The minimum entries. */ readonly requirement: TRequirement; } /** * Min entries action interface. * * @beta */ export interface MinEntriesAction< TInput extends EntriesInput, TRequirement extends number, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation< TInput, TInput, MinEntriesIssue > { /** * The action type. */ readonly type: 'min_entries'; /** * The action reference. */ readonly reference: typeof minEntries; /** * The expected property. */ readonly expects: `>=${TRequirement}`; /** * The minimum entries. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a min entries validation action. * * @param requirement The minimum entries. * * @returns A min entries action. * * @beta */ export function minEntries< TInput extends EntriesInput, const TRequirement extends number, >(requirement: TRequirement): MinEntriesAction; /** * Creates a min entries validation action. * * @param requirement The minimum entries. * @param message The error message. * * @returns A min entries action. * * @beta */ export function minEntries< TInput extends EntriesInput, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): MinEntriesAction; // @__NO_SIDE_EFFECTS__ export function minEntries( requirement: number, message?: ErrorMessage> ): MinEntriesAction< EntriesInput, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'min_entries', reference: minEntries, async: false, expects: `>=${requirement}`, requirement, message, '~run'(dataset, config) { if (!dataset.typed) return dataset; const count = Object.keys(dataset.value).length; if (dataset.typed && count < this.requirement) { _addIssue(this, 'entries', dataset, config, { received: `${count}`, }); } return dataset; }, }; } ================================================ FILE: library/src/actions/minGraphemes/index.ts ================================================ export * from './minGraphemes.ts'; ================================================ FILE: library/src/actions/minGraphemes/minGraphemes.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { minGraphemes, type MinGraphemesAction, type MinGraphemesIssue, } from './minGraphemes.ts'; describe('minGraphemes', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = MinGraphemesAction; expectTypeOf(minGraphemes(10)).toEqualTypeOf(); expectTypeOf( minGraphemes(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( minGraphemes(10, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( minGraphemes string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Input = 'example string'; type Action = MinGraphemesAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< MinGraphemesIssue >(); }); }); }); ================================================ FILE: library/src/actions/minGraphemes/minGraphemes.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { _getGraphemeCount } from '../../utils/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { minGraphemes, type MinGraphemesAction, type MinGraphemesIssue, } from './minGraphemes.ts'; describe('minGraphemes', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'min_graphemes', reference: minGraphemes, expects: '>=5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: MinGraphemesAction = { ...baseAction, message: undefined, }; expect(minGraphemes(5)).toStrictEqual(action); expect(minGraphemes(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(minGraphemes(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies MinGraphemesAction); }); test('with function message', () => { const message = () => 'message'; expect(minGraphemes(5, message)).toStrictEqual({ ...baseAction, message, } satisfies MinGraphemesAction); }); }); describe('should return dataset without issues', () => { const action = minGraphemes(5); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid strings', () => { expectNoActionIssue(action, [ '12345', '1234 ', '123456', '123456789', 'foo bar baz', ]); }); test('for valid emoji', () => { expectNoActionIssue(action, [ '😀👋🏼🧩👩🏻‍🏫🫥', '😀👋🏼🧩👩🏻‍🏫🫥🫠', '😀👋🏼🧩👩🏻‍🏫🫥🫠🧑‍💻👻🥎', ]); }); }); describe('should return dataset with issues', () => { const action = minGraphemes(5, 'message'); const baseIssue: Omit< MinGraphemesIssue, 'input' | 'received' > = { kind: 'validation', type: 'min_graphemes', expected: '>=5', message: 'message', requirement: 5, }; test('for invalid strings', () => { expectActionIssue( action, baseIssue, ['', ' ', '1', 'foo', '1234', '12 4'], (value) => `${_getGraphemeCount(value)}` ); }); test('for invalid emoji', () => { expectActionIssue( action, baseIssue, ['😀', '😀👋🏼', '😀👋🏼🧩👩🏻‍🏫'], (value) => `${_getGraphemeCount(value)}` ); }); }); }); ================================================ FILE: library/src/actions/minGraphemes/minGraphemes.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _getGraphemeCount } from '../../utils/index.ts'; /** * Min graphemes issue interface. */ export interface MinGraphemesIssue< TInput extends string, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'min_graphemes'; /** * The expected property. */ readonly expected: `>=${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The minimum graphemes. */ readonly requirement: TRequirement; } /** * Min graphemes action interface. */ export interface MinGraphemesAction< TInput extends string, TRequirement extends number, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation< TInput, TInput, MinGraphemesIssue > { /** * The action type. */ readonly type: 'min_graphemes'; /** * The action reference. */ readonly reference: typeof minGraphemes; /** * The expected property. */ readonly expects: `>=${TRequirement}`; /** * The minimum graphemes. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a min graphemes validation action. * * @param requirement The minimum graphemes. * * @returns A min graphemes action. */ export function minGraphemes< TInput extends string, const TRequirement extends number, >( requirement: TRequirement ): MinGraphemesAction; /** * Creates a min graphemes validation action. * * @param requirement The minimum graphemes. * @param message The error message. * * @returns A min graphemes action. */ export function minGraphemes< TInput extends string, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): MinGraphemesAction; // @__NO_SIDE_EFFECTS__ export function minGraphemes( requirement: number, message?: ErrorMessage> ): MinGraphemesAction< string, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'min_graphemes', reference: minGraphemes, async: false, expects: `>=${requirement}`, requirement, message, '~run'(dataset, config) { if (dataset.typed) { const count = _getGraphemeCount(dataset.value); if (count < this.requirement) { _addIssue(this, 'graphemes', dataset, config, { received: `${count}`, }); } } return dataset; }, }; } ================================================ FILE: library/src/actions/minLength/index.ts ================================================ export * from './minLength.ts'; ================================================ FILE: library/src/actions/minLength/minLength.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { minLength, type MinLengthAction, type MinLengthIssue, } from './minLength.ts'; describe('minLength', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = MinLengthAction; expectTypeOf(minLength(10)).toEqualTypeOf(); expectTypeOf( minLength(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( minLength(10, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( minLength string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = MinLengthAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< MinLengthIssue >(); }); }); }); ================================================ FILE: library/src/actions/minLength/minLength.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { minLength, type MinLengthAction, type MinLengthIssue, } from './minLength.ts'; describe('minLength', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'min_length', reference: minLength, expects: '>=5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: MinLengthAction = { ...baseAction, message: undefined, }; expect(minLength(5)).toStrictEqual(action); expect(minLength(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(minLength(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies MinLengthAction); }); test('with function message', () => { const message = () => 'message'; expect(minLength(5, message)).toStrictEqual({ ...baseAction, message, } satisfies MinLengthAction); }); }); describe('should return dataset without issues', () => { const action = minLength(5); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid strings', () => { expectNoActionIssue(action, ['12345', '123456', 'foobarbaz123']); }); test('for valid arrays', () => { expectNoActionIssue(action, [[1, 2, 3, 4, 5], Array(6), Array(999)]); }); }); describe('should return dataset with issues', () => { const action = minLength(5, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'min_length', expected: '>=5', message: 'message', requirement: 5, }; test('for invalid strings', () => { expectActionIssue( action, baseIssue, ['', 'foo', '1234'], (value) => `${value.length}` ); }); test('for invalid arrays', () => { expectActionIssue( action, baseIssue, [[], ['foo', 'bar'], [1, 2, 3, 4]], (value) => `${value.length}` ); }); }); }); ================================================ FILE: library/src/actions/minLength/minLength.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { LengthInput } from '../types.ts'; /** * Min length issue interface. */ export interface MinLengthIssue< TInput extends LengthInput, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'min_length'; /** * The expected property. */ readonly expected: `>=${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The minimum length. */ readonly requirement: TRequirement; } /** * Min length action interface. */ export interface MinLengthAction< TInput extends LengthInput, TRequirement extends number, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'min_length'; /** * The action reference. */ readonly reference: typeof minLength; /** * The expected property. */ readonly expects: `>=${TRequirement}`; /** * The minimum length. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a min length validation action. * * @param requirement The minimum length. * * @returns A min length action. */ export function minLength< TInput extends LengthInput, const TRequirement extends number, >(requirement: TRequirement): MinLengthAction; /** * Creates a min length validation action. * * @param requirement The minimum length. * @param message The error message. * * @returns A min length action. */ export function minLength< TInput extends LengthInput, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): MinLengthAction; // @__NO_SIDE_EFFECTS__ export function minLength( requirement: number, message?: ErrorMessage> ): MinLengthAction< LengthInput, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'min_length', reference: minLength, async: false, expects: `>=${requirement}`, requirement, message, '~run'(dataset, config) { if (dataset.typed && dataset.value.length < this.requirement) { _addIssue(this, 'length', dataset, config, { received: `${dataset.value.length}`, }); } return dataset; }, }; } ================================================ FILE: library/src/actions/minSize/index.ts ================================================ export * from './minSize.ts'; ================================================ FILE: library/src/actions/minSize/minSize.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { minSize, type MinSizeAction, type MinSizeIssue } from './minSize.ts'; describe('minSize', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = MinSizeAction; expectTypeOf(minSize(10)).toEqualTypeOf(); expectTypeOf( minSize(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(minSize(10, 'message')).toEqualTypeOf< MinSizeAction >(); }); test('with function message', () => { expectTypeOf( minSize string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = MinSizeAction, 10, undefined>; test('of input', () => { expectTypeOf>().toEqualTypeOf>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< MinSizeIssue, 10> >(); }); }); }); ================================================ FILE: library/src/actions/minSize/minSize.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { MapIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { minSize, type MinSizeAction, type MinSizeIssue } from './minSize.ts'; describe('minSize', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'min_size', reference: minSize, expects: '>=5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: MinSizeAction = { ...baseAction, message: undefined, }; expect(minSize(5)).toStrictEqual(action); expect(minSize(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(minSize(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies MinSizeAction); }); test('with function message', () => { const message = () => 'message'; expect(minSize(5, message)).toStrictEqual({ ...baseAction, message, } satisfies MinSizeAction); }); }); describe('should return dataset without issues', () => { const action = minSize(3); test('for untyped inputs', () => { const issues: [MapIssue] = [ { kind: 'schema', type: 'map', input: null, expected: 'Map', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid maps', () => { expectNoActionIssue(action, [ new Map([ [1, 'one'], [2, 'two'], [3, 'three'], ]), new Map([ [1, 'one'], ['2', 'two'], [3, 'three'], [4, 'four'], ]), new Map([ ['1', 'one'], [2, null], [true, null], [4, 'four'], [5, 'five'], ]), ]); }); test('for valid sets', () => { expectNoActionIssue(action, [ new Set([1, 2, 3]), new Set([1, 'two', null, '4']), new Set(['1', 2, 'three', null, { value: '5' }]), ]); }); test('for valid blobs', () => { expectNoActionIssue(action, [ new Blob(['123']), new Blob(['1', '2', '3'], { type: 'text/plain' }), new Blob( [ new Uint8Array([72, 101, 108, 108, 111]), // 'Hello' new Blob(['!'], { type: 'text/plain' }), ], { type: 'text/plain' } ), new Blob(['foobarbaz123']), ]); }); }); describe('should return dataset with issues', () => { const action = minSize(3, 'message'); const baseIssue: Omit< MinSizeIssue, 3>, 'input' | 'received' > = { kind: 'validation', type: 'min_size', expected: '>=3', message: 'message', requirement: 3, }; test('for invalid maps', () => { expectActionIssue( action, baseIssue, [ new Map(), new Map([[1, 'one']]), new Map([ ['one', 1], ['two', 2], ]), ], (value) => `${value.size}` ); }); test('for invalid sets', () => { expectActionIssue( action, baseIssue, [new Set(), new Set([1]), new Set(['one', null])], (value) => `${value.size}` ); }); test('for invalid blobs', () => { expectActionIssue( action, baseIssue, [ new Blob([]), new Blob(['1']), new Blob(['hi'], { type: 'text/plain' }), new Blob([new Uint8Array([72, 105])]), // 'Hi' ], (value) => `${value.size}` ); }); }); }); ================================================ FILE: library/src/actions/minSize/minSize.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { SizeInput } from '../types.ts'; /** * Min size issue interface. */ export interface MinSizeIssue< TInput extends SizeInput, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'min_size'; /** * The expected property. */ readonly expected: `>=${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The minimum size. */ readonly requirement: TRequirement; } /** * Min size action interface. */ export interface MinSizeAction< TInput extends SizeInput, TRequirement extends number, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'min_size'; /** * The action reference. */ readonly reference: typeof minSize; /** * The expected property. */ readonly expects: `>=${TRequirement}`; /** * The minimum size. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a min size validation action. * * @param requirement The minimum size. * * @returns A min size action. */ export function minSize< TInput extends SizeInput, const TRequirement extends number, >(requirement: TRequirement): MinSizeAction; /** * Creates a min size validation action. * * @param requirement The minimum size. * @param message The error message. * * @returns A min size action. */ export function minSize< TInput extends SizeInput, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): MinSizeAction; // @__NO_SIDE_EFFECTS__ export function minSize( requirement: number, message?: ErrorMessage> ): MinSizeAction< SizeInput, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'min_size', reference: minSize, async: false, expects: `>=${requirement}`, requirement, message, '~run'(dataset, config) { if (dataset.typed && dataset.value.size < this.requirement) { _addIssue(this, 'size', dataset, config, { received: `${dataset.value.size}`, }); } return dataset; }, }; } ================================================ FILE: library/src/actions/minValue/index.ts ================================================ export * from './minValue.ts'; ================================================ FILE: library/src/actions/minValue/minValue.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { minValue, type MinValueAction, type MinValueIssue, } from './minValue.ts'; describe('minValue', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = MinValueAction; expectTypeOf(minValue(10)).toEqualTypeOf(); expectTypeOf( minValue(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( minValue(10, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( minValue string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = MinValueAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< MinValueIssue >(); }); }); }); ================================================ FILE: library/src/actions/minValue/minValue.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { NumberIssue } from '../../schemas/index.ts'; import { _stringify } from '../../utils/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { minValue, type MinValueAction } from './minValue.ts'; describe('minValue', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'min_value', reference: minValue, expects: '>=5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: MinValueAction = { ...baseAction, message: undefined, }; expect(minValue(5)).toStrictEqual(action); expect(minValue(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(minValue(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies MinValueAction); }); test('with function message', () => { const message = () => 'message'; expect(minValue(5, message)).toStrictEqual({ ...baseAction, message, } satisfies MinValueAction); }); }); describe('should return dataset without issues', () => { test('for untyped inputs', () => { const issues: [NumberIssue] = [ { kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', message: 'message', }, ]; expect( minValue(1)['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues }); }); test('for valid bigints', () => { expectNoActionIssue(minValue(10n), [10n, 11n, 9999n]); }); test('for valid non-bigints', () => { expectNoActionIssue(minValue(10n), [ '10', '+10', ' 10 ', '15', 10, 10.0, 15, 15.0, Infinity, new Date(10), new Date(20), ]); expectNoActionIssue(minValue(1n), [ '1', '+1', 1, Infinity, true, new Date(1), ]); expectNoActionIssue(minValue(0n), [ '', ' ', '0', '1', 0, 1, 0.0, 1.0, Infinity, false, true, new Date(0), new Date(1), ]); }); test('for valid booleans', () => { expectNoActionIssue(minValue(false), [false, true]); expectNoActionIssue(minValue(true), [true]); }); test('for valid non-booleans', () => { expectNoActionIssue(minValue(true), [ '1', '99', '+1', '+99', '1.0', '99.9', ' 1 ', ' 99 ', 1, 99, 1.0, 99.9, Infinity, new Date(1), new Date(99), 1n, 99n, ]); expectNoActionIssue(minValue(false), [ '', ' ', '-0', '0', '1', '99', '0.0', '1.0', '99.9', ' 0 ', ' 1 ', ' 99 ', -0, 0, 1, 99, -0.0, 0.0, 1.0, 99.9, Infinity, new Date(0), new Date(1), new Date(99), 0n, 1n, 99n, ]); }); test('for valid dates', () => { const date = new Date(); expectNoActionIssue(minValue(date), [ date, new Date(+date + 1), new Date(+date + 999999), ]); }); test('for valid non-dates', () => { expectNoActionIssue(minValue(new Date(10)), [ '+10', '10.0', ' 10 ', '99', '99.99', 10, 99, 10.0, 99.99, Infinity, 10n, 99n, ]); expectNoActionIssue(minValue(new Date(1)), [ '1', '+1', '1.0', ' 1 ', 1, 1.0, Infinity, true, 1n, ]); expectNoActionIssue(minValue(new Date(0)), [ '', ' ', '0', '1', '0.0', '1.0', ' 0 ', ' 1 ', 0, -0, 1, 0.0, 1.0, Infinity, false, true, 0n, 1n, ]); }); test('for valid numbers', () => { expectNoActionIssue(minValue(10), [10, 11, 9999, Number.MAX_VALUE]); }); test('for valid non-numbers', () => { expectNoActionIssue(minValue(10), [ '+10', '10.0', ' 10 ', '99', '99.99', ' 99 ', new Date(10), new Date(99), 10n, 99n, ]); expectNoActionIssue(minValue(1), [ '1', '+1', '1.0', ' 1 ', true, new Date(1), 1n, ]); expectNoActionIssue(minValue(0), [ '', ' ', '-0', '0', '1', '+1', '0.0', '1.0', ' 0 ', ' 1 ', false, true, new Date(0), new Date(1), 0n, 1n, ]); }); test('for valid strings', () => { expectNoActionIssue(minValue('2024'), ['2024', '2025', '9999', 'XYZ']); }); test('for valid non-strings', () => { expectNoActionIssue(minValue('10'), [ 10, 10.0, 99, 99.99, Infinity, new Date(10), new Date(99), 10n, 99n, ]); expectNoActionIssue(minValue('1'), [ 1, 1.0, Infinity, true, new Date(1), 1n, ]); expectNoActionIssue(minValue('0'), [ 0, -0, 1, 0.0, 1.0, Infinity, false, true, new Date(0), new Date(1), 0n, 1n, ]); }); }); describe('should return dataset with issues', () => { const baseInfo = { kind: 'validation', type: 'min_value', message: 'message', } as const; const getReceived = (value: unknown): string => value instanceof Date ? value.toJSON() : _stringify(value); test('for invalid bigints', () => { expectActionIssue( minValue(10n, 'message'), { ...baseInfo, expected: '>=10', requirement: 10n }, [-9999n, 0n, 9n] ); }); test('for invalid non-bigints', () => { expectActionIssue( minValue(123n, 'message'), { ...baseInfo, expected: '>=123', requirement: 123n }, [ 'nan', '123px', '+ 123', '-124', '-123', '', ' ', '0.0', '122', ' 122 ', '123.0', -124, -123, 0, 122, 122.5, NaN, false, true, new Date(-124), new Date(-123), new Date(0), new Date(122), ], getReceived ); expectActionIssue( minValue(1n, 'message'), { ...baseInfo, expected: '>=1', requirement: 1n }, [ 'nan', '1px', '+ 1', '-1', '', ' ', '0', ' 0.5 ', '1.0', -1, 0, 0.5, NaN, false, new Date(-1), new Date(0), ], getReceived ); expectActionIssue( minValue(0n, 'message'), { ...baseInfo, expected: '>=0', requirement: 0n }, [ 'nan', '0px', '+ 0', '-0.5', '-1', ' -1 ', '0.0', -1, -0.5, NaN, new Date(-1), ], getReceived ); }); test('for invalid booleans', () => { expectActionIssue( minValue(true, 'message'), { ...baseInfo, expected: '>=true', requirement: true }, [false] ); }); test('for invalid non-booleans', () => { expectActionIssue( minValue(false, 'message'), { ...baseInfo, expected: '>=false', requirement: false }, [ 'nan', '0px', '+ 0', '-0.5', '-1', ' -1 ', -1, -0.5, NaN, new Date(-1), -1n, ], getReceived ); expectActionIssue( minValue(true, 'message'), { ...baseInfo, expected: '>=true', requirement: true }, [ 'nan', '1px', '+ 1', '-2', '-1', '', ' ', '0', ' 0.5 ', -2, -1, 0, 0.5, NaN, new Date(-2), new Date(-1), new Date(0), -2n, -1n, 0n, ], getReceived ); }); test('for invalid dates', () => { const date = new Date(); expectActionIssue( minValue(date, 'message'), { ...baseInfo, expected: `>=${date.toJSON()}`, requirement: date }, [new Date(0), new Date(+date - 999999), new Date(+date - 1)], (value) => value.toJSON() ); }); test('for invalid non-dates', () => { const date1 = new Date(123); expectActionIssue( minValue(date1, 'message'), { ...baseInfo, expected: `>=${date1.toJSON()}`, requirement: date1 }, [ 'nan', '123px', '+ 123', '-124', '-123', '', ' ', '0.0', '122', ' 122 ', -124, -123, 0, 122, 122.5, NaN, false, true, -124n, -123n, 0n, 122n, ], getReceived ); const date2 = new Date(1); expectActionIssue( minValue(date2, 'message'), { ...baseInfo, expected: `>=${date2.toJSON()}`, requirement: date2 }, [ 'nan', '1px', '+ 1', '-1', '', ' ', '0', ' 0.5 ', -1, 0, 0.5, NaN, false, -1n, 0n, ], getReceived ); const date3 = new Date(0); expectActionIssue( minValue(date3, 'message'), { ...baseInfo, expected: `>=${date3.toJSON()}`, requirement: date3 }, ['nan', '0px', '+ 0', '-0.5', '-1', ' -1 ', -1, -0.5, NaN, -1n], getReceived ); }); test('for invalid numbers', () => { expectActionIssue( minValue(10, 'message'), { ...baseInfo, expected: '>=10', requirement: 10 }, [Number.MIN_VALUE, 0, 9, NaN] ); }); test('for invalid non-numbers', () => { expectActionIssue( minValue(123, 'message'), { ...baseInfo, expected: '>=123', requirement: 123 }, [ 'nan', '123px', '+ 123', '-124', '-123', '', ' ', '0.0', '122', ' 122 ', false, true, new Date(-124), new Date(-123), new Date(0), new Date(122), -124n, -123n, 0n, 122n, ], getReceived ); expectActionIssue( minValue(1, 'message'), { ...baseInfo, expected: '>=1', requirement: 1 }, [ 'nan', '1px', '+ 1', '-1', '', ' ', '0', ' 0.5 ', false, new Date(-1), new Date(0), -1n, 0n, ], getReceived ); expectActionIssue( minValue(0, 'message'), { ...baseInfo, expected: '>=0', requirement: 0 }, ['nan', '0px', '+ 0', '-0.5', '-1', ' -1 ', new Date(-1), -1n], getReceived ); }); test('for invalid strings', () => { expectActionIssue( minValue('2024', 'message'), { ...baseInfo, expected: '>="2024"', requirement: '2024' }, ['', '1234', '2023'] ); }); test('for invalid non-strings', () => { expectActionIssue( minValue('123', 'message'), { ...baseInfo, expected: '>="123"', requirement: '123' }, [ -124, -123, 0, 122, 122.5, NaN, false, true, new Date(-124), new Date(-123), new Date(0), new Date(122), -124n, -123n, 0n, 122n, ], getReceived ); expectActionIssue( minValue('1', 'message'), { ...baseInfo, expected: '>="1"', requirement: '1' }, [-1, 0, 0.5, NaN, false, new Date(-1), new Date(0), -1n, 0n], getReceived ); expectActionIssue( minValue('0', 'message'), { ...baseInfo, expected: '>="0"', requirement: '0' }, [-1, -0.5, NaN, new Date(-1), -1n], getReceived ); }); }); }); ================================================ FILE: library/src/actions/minValue/minValue.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _stringify } from '../../utils/index.ts'; import type { ValueInput } from '../types.ts'; /** * Min value issue interface. */ export interface MinValueIssue< TInput extends ValueInput, TRequirement extends ValueInput, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'min_value'; /** * The expected property. */ readonly expected: `>=${string}`; /** * The minimum value. */ readonly requirement: TRequirement; } /** * Min value action interface. */ export interface MinValueAction< TInput extends ValueInput, TRequirement extends TInput, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'min_value'; /** * The action reference. */ readonly reference: typeof minValue; /** * The expected property. */ readonly expects: `>=${string}`; /** * The minimum value. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a min value validation action. * * @param requirement The minimum value. * * @returns A min value action. */ export function minValue< TInput extends ValueInput, const TRequirement extends TInput, >(requirement: TRequirement): MinValueAction; /** * Creates a min value validation action. * * @param requirement The minimum value. * @param message The error message. * * @returns A min value action. */ export function minValue< TInput extends ValueInput, const TRequirement extends TInput, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): MinValueAction; // @__NO_SIDE_EFFECTS__ export function minValue( requirement: ValueInput, message?: ErrorMessage> ): MinValueAction< ValueInput, ValueInput, ErrorMessage> | undefined > { return { kind: 'validation', type: 'min_value', reference: minValue, async: false, expects: `>=${ requirement instanceof Date ? requirement.toJSON() : _stringify(requirement) }`, requirement, message, '~run'(dataset, config) { if (dataset.typed && !(dataset.value >= this.requirement)) { _addIssue(this, 'value', dataset, config, { received: dataset.value instanceof Date ? dataset.value.toJSON() : _stringify(dataset.value), }); } return dataset; }, }; } ================================================ FILE: library/src/actions/minWords/index.ts ================================================ export * from './minWords.ts'; ================================================ FILE: library/src/actions/minWords/minWords.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { minWords, type MinWordsAction, type MinWordsIssue, } from './minWords.ts'; describe('minWords', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = MinWordsAction; expectTypeOf(minWords('en', 3)).toEqualTypeOf(); expectTypeOf( minWords('en', 3, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( minWords('en', 3, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( minWords string>('en', 3, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Input = 'foo bar baz'; type Action = MinWordsAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< MinWordsIssue >(); }); }); }); ================================================ FILE: library/src/actions/minWords/minWords.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { _getWordCount } from '../../utils/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { minWords, type MinWordsAction, type MinWordsIssue, } from './minWords.ts'; describe('minWords', () => { describe('should return action object', () => { const baseAction: Omit< MinWordsAction, 'message' > = { kind: 'validation', type: 'min_words', reference: minWords, expects: '>=3', locales: 'en', requirement: 3, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: MinWordsAction = { ...baseAction, message: undefined, }; expect(minWords('en', 3)).toStrictEqual(action); expect(minWords('en', 3, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(minWords('en', 3, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies MinWordsAction); }); test('with function message', () => { const message = () => 'message'; expect(minWords('en', 3, message)).toStrictEqual({ ...baseAction, message, } satisfies MinWordsAction); }); }); describe('should return dataset without issues', () => { const action = minWords('en', 3); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid strings', () => { expectNoActionIssue(action, [ 'for bar baz', 'for bar baz qux', 'Lorem ipsum dolor?', 'Lorem ipsum dolor sit?', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit?', 'Hi, welcome home!', 'Hi, welcome home! How are you?', ]); }); }); describe('should return dataset with issues', () => { const action = minWords('en', 3, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'min_words', expected: '>=3', message: 'message', requirement: 3, }; test('for invalid strings', () => { expectActionIssue( action, baseIssue, [ '', ' ', 'foo', 'foo bar', 'Lorem?', 'Lorem ipsum?', 'Hi, ...', 'Hi, welcome!', ], (value) => `${_getWordCount('en', value)}` ); }); }); }); ================================================ FILE: library/src/actions/minWords/minWords.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _getWordCount } from '../../utils/index.ts'; /** * Min words issue interface. */ export interface MinWordsIssue< TInput extends string, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'min_words'; /** * The expected property. */ readonly expected: `>=${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The minimum words. */ readonly requirement: TRequirement; } /** * Min words action interface. */ export interface MinWordsAction< TInput extends string, TLocales extends Intl.LocalesArgument, TRequirement extends number, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'min_words'; /** * The action reference. */ readonly reference: typeof minWords; /** * The expected property. */ readonly expects: `>=${TRequirement}`; /** * The locales to be used. */ readonly locales: TLocales; /** * The minimum words. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a min words validation action. * * @param locales The locales to be used. * @param requirement The minimum words. * * @returns A min words action. */ export function minWords< TInput extends string, TLocales extends Intl.LocalesArgument, const TRequirement extends number, >( locales: TLocales, requirement: TRequirement ): MinWordsAction; /** * Creates a min words validation action. * * @param locales The locales to be used. * @param requirement The minimum words. * @param message The error message. * * @returns A min words action. */ export function minWords< TInput extends string, TLocales extends Intl.LocalesArgument, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( locales: TLocales, requirement: TRequirement, message: TMessage ): MinWordsAction; // @__NO_SIDE_EFFECTS__ export function minWords( locales: Intl.LocalesArgument, requirement: number, message?: ErrorMessage> ): MinWordsAction< string, Intl.LocalesArgument, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'min_words', reference: minWords, async: false, expects: `>=${requirement}`, locales, requirement, message, '~run'(dataset, config) { if (dataset.typed) { const count = _getWordCount(this.locales, dataset.value); if (count < this.requirement) { _addIssue(this, 'words', dataset, config, { received: `${count}`, }); } } return dataset; }, }; } ================================================ FILE: library/src/actions/multipleOf/index.ts ================================================ export * from './multipleOf.ts'; ================================================ FILE: library/src/actions/multipleOf/multipleOf.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { multipleOf, type MultipleOfAction, type MultipleOfIssue, } from './multipleOf.ts'; describe('multipleOf', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = MultipleOfAction; expectTypeOf(multipleOf(10)).toEqualTypeOf(); expectTypeOf( multipleOf(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( multipleOf(10, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( multipleOf string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action1 = MultipleOfAction; type Action2 = MultipleOfAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< MultipleOfIssue >(); expectTypeOf>().toEqualTypeOf< MultipleOfIssue >(); }); }); }); ================================================ FILE: library/src/actions/multipleOf/multipleOf.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { NumberIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { multipleOf, type MultipleOfAction } from './multipleOf.ts'; describe('multipleOf', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'multiple_of', reference: multipleOf, expects: '%5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: MultipleOfAction = { ...baseAction, message: undefined, }; expect(multipleOf(5)).toStrictEqual(action); expect(multipleOf(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(multipleOf(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies MultipleOfAction); }); test('with function message', () => { const message = () => 'message'; expect(multipleOf(5, message)).toStrictEqual({ ...baseAction, message, } satisfies MultipleOfAction); }); }); describe('should return dataset without issues', () => { test('for untyped inputs', () => { const issues: [NumberIssue] = [ { kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', message: 'message', }, ]; expect( multipleOf(5)['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid numbers', () => { expectNoActionIssue(multipleOf(5), [-15, -10, -5, 0, 5, 10, 15]); }); test('for valid bigints', () => { expectNoActionIssue(multipleOf(5n), [-15n, -10n, -5n, 0n, 5n, 10n, 15n]); }); }); describe('should return dataset with issues', () => { const baseIssue = { kind: 'validation', type: 'multiple_of', expected: '%5', message: 'message', } as const; test('for invalid numbers', () => { expectActionIssue( multipleOf(5, 'message'), { ...baseIssue, requirement: 5 }, [-14, -9, -4, 1, 3, 6, 11] ); }); test('for infinity', () => { expectActionIssue( multipleOf(5, 'message'), { ...baseIssue, requirement: 5 }, [-Infinity, Infinity] ); }); test('for NaN', () => { expectActionIssue( multipleOf(5, 'message'), { ...baseIssue, requirement: 5 }, [NaN] ); }); test('for invalid bigints', () => { expectActionIssue( multipleOf(5n, 'message'), { ...baseIssue, requirement: 5n }, [-14n, -9n, -4n, 1n, 3n, 6n, 11n] ); }); }); }); ================================================ FILE: library/src/actions/multipleOf/multipleOf.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Input type */ type Input = number | bigint; /** * Multiple of issue interface. */ export interface MultipleOfIssue< TInput extends Input, TRequirement extends Input, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'multiple_of'; /** * The expected property. */ readonly expected: `%${TRequirement}`; /** * The received property. */ readonly received: `${TInput}`; /** * The divisor. */ readonly requirement: TRequirement; } /** * Multiple of action interface. */ export interface MultipleOfAction< TInput extends Input, TRequirement extends Input, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation< TInput, TInput, MultipleOfIssue > { /** * The action type. */ readonly type: 'multiple_of'; /** * The action reference. */ readonly reference: typeof multipleOf; /** * The expected property. */ readonly expects: `%${TRequirement}`; /** * The divisor. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a [multiple](https://en.wikipedia.org/wiki/Multiple_(mathematics)) of validation action. * * @param requirement The divisor. * * @returns A multiple of action. */ export function multipleOf< TInput extends number, const TRequirement extends number, >(requirement: TRequirement): MultipleOfAction; /** * Creates a [multiple](https://en.wikipedia.org/wiki/Multiple_(mathematics)) of validation action. * * @param requirement The divisor. * * @returns A multiple of action. */ export function multipleOf< TInput extends bigint, const TRequirement extends bigint, >(requirement: TRequirement): MultipleOfAction; /** * Creates a [multiple](https://en.wikipedia.org/wiki/Multiple_(mathematics)) of validation action. * * @param requirement The divisor. * @param message The error message. * * @returns A multiple of action. */ export function multipleOf< TInput extends number, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): MultipleOfAction; /** * Creates a [multiple](https://en.wikipedia.org/wiki/Multiple_(mathematics)) of validation action. * * @param requirement The divisor. * @param message The error message. * * @returns A multiple of action. */ export function multipleOf< TInput extends bigint, const TRequirement extends bigint, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): MultipleOfAction; // @__NO_SIDE_EFFECTS__ export function multipleOf( requirement: Input, message?: ErrorMessage> ): MultipleOfAction< Input, Input, ErrorMessage> | undefined > { return { kind: 'validation', type: 'multiple_of', reference: multipleOf, async: false, expects: `%${requirement}`, requirement, message, '~run'(dataset, config) { // @ts-expect-error if (dataset.typed && dataset.value % this.requirement != 0) { _addIssue(this, 'multiple', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/nanoid/index.ts ================================================ export * from './nanoid.ts'; ================================================ FILE: library/src/actions/nanoid/nanoid.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { nanoid, type NanoIdAction, type NanoIdIssue } from './nanoid.ts'; describe('nanoid', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = NanoIdAction; expectTypeOf(nanoid()).toEqualTypeOf(); expectTypeOf( nanoid(undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(nanoid('message')).toEqualTypeOf< NanoIdAction >(); }); test('with function message', () => { expectTypeOf(nanoid string>(() => 'message')).toEqualTypeOf< NanoIdAction string> >(); }); }); describe('should infer correct types', () => { type Action = NanoIdAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/nanoid/nanoid.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { NANO_ID_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { nanoid, type NanoIdAction, type NanoIdIssue } from './nanoid.ts'; describe('nanoid', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'nanoid', reference: nanoid, expects: null, requirement: NANO_ID_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: NanoIdAction = { ...baseAction, message: undefined, }; expect(nanoid()).toStrictEqual(action); expect(nanoid(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(nanoid('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies NanoIdAction); }); test('with function message', () => { const message = () => 'message'; expect(nanoid(message)).toStrictEqual({ ...baseAction, message, } satisfies NanoIdAction); }); }); describe('should return dataset without issues', () => { const action = nanoid(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for normal Nano IDs', () => { expectNoActionIssue(action, [ 'NOi6NWfhDRpgzBYFRR-uE', 'D7j9AWMA6anLPDE2_2uHz', 'g_Se_MXrTmRJpmcp8cN5m', 'Oc0XNYtCgyrX-x2T33z3E', 'gGCr-6yBmZkOTJQ1oLAFr', ]); }); test('for single char', () => { expectNoActionIssue(action, ['a', 'z', 'A', 'Z', '0', '9', '_', '-']); }); test('for two chars', () => { expectNoActionIssue(action, ['aa', 'zz', 'AZ', '09', '_-', '9A']); }); test('for long IDs', () => { expectNoActionIssue(action, [ '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-', ]); }); }); describe('should return dataset with issues', () => { const action = nanoid('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'nanoid', expected: null, message: 'message', requirement: NANO_ID_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for blank spaces', () => { expectActionIssue(action, baseIssue, [ ' vM7SGqVFmPS5tw7fII-G', 'BImGM 7USGakXaVhydHgO', 'LBjowKnkbk95kK3IoUV7 ', ]); }); test('for special chars', () => { expectActionIssue(action, baseIssue, [ '@1o5BK76uGc-mbqeprAvX', '#Lcb2qbTsjS98y9Vf-G15', '$3WZ4tXxsuiDBezXIJKlP', '%gSjBHLFDO67bE-nbgBRi', '&2zYmqr0APdImhdxC69t4', '–gGCr6yBmZkOTJQ1oLAFr', ]); }); }); }); ================================================ FILE: library/src/actions/nanoid/nanoid.ts ================================================ import { NANO_ID_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Nano ID issue interface. */ export interface NanoIdIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'nanoid'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: string; /** * The Nano ID regex. */ readonly requirement: RegExp; } /** * Nano ID issue type. * * @deprecated Use `NanoIdIssue` instead. */ export type NanoIDIssue = NanoIdIssue; /** * Nano ID action interface. */ export interface NanoIdAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'nanoid'; /** * The action reference. */ readonly reference: typeof nanoid; /** * The expected property. */ readonly expects: null; /** * The Nano ID regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Nano ID action type. * * @deprecated Use `NanoIdAction` instead. */ export type NanoIDAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > = NanoIdAction; /** * Creates a [Nano ID](https://github.com/ai/nanoid) validation action. * * @returns A Nano ID action. */ export function nanoid(): NanoIdAction< TInput, undefined >; /** * Creates a [Nano ID](https://github.com/ai/nanoid) validation action. * * @param message The error message. * * @returns A Nano ID action. */ export function nanoid< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): NanoIdAction; // @__NO_SIDE_EFFECTS__ export function nanoid( message?: ErrorMessage> ): NanoIdAction> | undefined> { return { kind: 'validation', type: 'nanoid', reference: nanoid, async: false, expects: null, requirement: NANO_ID_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'Nano ID', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/nonEmpty/index.ts ================================================ export * from './nonEmpty.ts'; ================================================ FILE: library/src/actions/nonEmpty/nonEmpty.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { nonEmpty, type NonEmptyAction, type NonEmptyIssue, } from './nonEmpty.ts'; describe('nonEmpty', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = NonEmptyAction; expectTypeOf(nonEmpty()).toEqualTypeOf(); expectTypeOf( nonEmpty(undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(nonEmpty('message')).toEqualTypeOf< NonEmptyAction >(); }); test('with function message', () => { expectTypeOf( nonEmpty string>(() => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = NonEmptyAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/nonEmpty/nonEmpty.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { nonEmpty, type NonEmptyAction, type NonEmptyIssue, } from './nonEmpty.ts'; describe('nonEmpty', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'non_empty', reference: nonEmpty, expects: '!0', async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: NonEmptyAction = { ...baseAction, message: undefined, }; expect(nonEmpty()).toStrictEqual(action); expect(nonEmpty(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(nonEmpty('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies NonEmptyAction); }); test('with function message', () => { const message = () => 'message'; expect(nonEmpty(message)).toStrictEqual({ ...baseAction, message, } satisfies NonEmptyAction); }); }); describe('should return dataset without issues', () => { const action = nonEmpty(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid strings', () => { expectNoActionIssue(action, [' ', '\n', 'foo', 'foobarbaz123']); }); test('for valid arrays', () => { expectNoActionIssue(action, [[null], [1, 2, 3, 4, 6], Array(999)]); }); }); describe('should return dataset with issues', () => { const action = nonEmpty('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'non_empty', expected: '!0', message: 'message', }; test('for invalid strings', () => { expectActionIssue(action, baseIssue, [''], () => '0'); }); test('for invalid arrays', () => { expectActionIssue(action, baseIssue, [[]], () => '0'); }); }); }); ================================================ FILE: library/src/actions/nonEmpty/nonEmpty.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { LengthInput } from '../types.ts'; /** * Non empty issue interface. */ export interface NonEmptyIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'non_empty'; /** * The expected input. */ readonly expected: '!0'; /** * The received input. */ readonly received: '0'; } /** * Non empty action interface. */ export interface NonEmptyAction< TInput extends LengthInput, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'non_empty'; /** * The action reference. */ readonly reference: typeof nonEmpty; /** * The expected property. */ readonly expects: '!0'; /** * The error message. */ readonly message: TMessage; } /** * Creates a non-empty validation action. * * @returns A non-empty action. */ export function nonEmpty(): NonEmptyAction< TInput, undefined >; /** * Creates a non-empty validation action. * * @param message The error message. * * @returns A non-empty action. */ export function nonEmpty< TInput extends LengthInput, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): NonEmptyAction; // @__NO_SIDE_EFFECTS__ export function nonEmpty( message?: ErrorMessage> ): NonEmptyAction< LengthInput, ErrorMessage> | undefined > { return { kind: 'validation', type: 'non_empty', reference: nonEmpty, async: false, expects: '!0', message, '~run'(dataset, config) { if (dataset.typed && dataset.value.length === 0) { _addIssue(this, 'length', dataset, config, { received: '0', }); } return dataset; }, }; } ================================================ FILE: library/src/actions/normalize/index.ts ================================================ export * from './normalize.ts'; ================================================ FILE: library/src/actions/normalize/normalize.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { normalize, type NormalizeAction } from './normalize.ts'; describe('normalize', () => { describe('should return action object', () => { test('with undefined form', () => { expectTypeOf(normalize()).toEqualTypeOf>(); }); test('with defined form', () => { expectTypeOf(normalize('NFKC')).toEqualTypeOf>(); }); }); describe('should infer correct types', () => { type Action = NormalizeAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/normalize/normalize.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { normalize, type NormalizeAction } from './normalize.ts'; describe('normalize', () => { describe('should return action object', () => { const baseAction: Omit, 'form'> = { kind: 'transformation', type: 'normalize', reference: normalize, async: false, '~run': expect.any(Function), }; test('with undefined form', () => { expect(normalize()).toStrictEqual({ ...baseAction, form: undefined, } satisfies NormalizeAction); }); test('with defined form', () => { expect(normalize('NFKD')).toStrictEqual({ ...baseAction, form: 'NFKD', } satisfies NormalizeAction<'NFKD'>); }); }); describe('should normalize string', () => { test('with undefined form', () => { expect( normalize()['~run']({ typed: true, value: '\u00F1' }, {}) ).toStrictEqual({ typed: true, value: 'ñ', }); expect( normalize()['~run']({ typed: true, value: '\u006E\u0303' }, {}) ).toStrictEqual({ typed: true, value: 'ñ', }); }); test('with defined form', () => { expect( normalize('NFKD')['~run']({ typed: true, value: '\uFB00' }, {}) ).toStrictEqual({ typed: true, value: 'ff', }); expect( normalize('NFKD')['~run']({ typed: true, value: '\u0066\u0066' }, {}) ).toStrictEqual({ typed: true, value: 'ff', }); }); }); }); ================================================ FILE: library/src/actions/normalize/normalize.ts ================================================ import type { BaseTransformation } from '../../types/index.ts'; /** * Normalize form type. */ export type NormalizeForm = 'NFC' | 'NFD' | 'NFKC' | 'NFKD'; /** * Normalize action interface. */ export interface NormalizeAction extends BaseTransformation { /** * The action type. */ readonly type: 'normalize'; /** * The action reference. */ readonly reference: typeof normalize; /** * The normalization form. */ readonly form: TForm; } /** * Creates a normalize transformation action. * * @returns A normalize action. */ export function normalize(): NormalizeAction; /** * Creates a normalize transformation action. * * @param form The normalization form. * * @returns A normalize action. */ export function normalize( form: TForm ): NormalizeAction; // @__NO_SIDE_EFFECTS__ export function normalize( form?: NormalizeForm ): NormalizeAction { return { kind: 'transformation', type: 'normalize', reference: normalize, async: false, form, '~run'(dataset) { dataset.value = dataset.value.normalize(this.form); return dataset; }, }; } ================================================ FILE: library/src/actions/notBytes/index.ts ================================================ export * from './notBytes.ts'; ================================================ FILE: library/src/actions/notBytes/notBytes.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { notBytes, type NotBytesAction, type NotBytesIssue, } from './notBytes.ts'; describe('notBytes', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = NotBytesAction; expectTypeOf(notBytes(10)).toEqualTypeOf(); expectTypeOf( notBytes(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( notBytes(10, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( notBytes string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = NotBytesAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< NotBytesIssue >(); }); }); }); ================================================ FILE: library/src/actions/notBytes/notBytes.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { notBytes, type NotBytesAction, type NotBytesIssue, } from './notBytes.ts'; describe('notBytes', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'not_bytes', reference: notBytes, expects: '!5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: NotBytesAction = { ...baseAction, message: undefined, }; expect(notBytes(5)).toStrictEqual(action); expect(notBytes(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(notBytes(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies NotBytesAction); }); test('with function message', () => { const message = () => 'message'; expect(notBytes(5, message)).toStrictEqual({ ...baseAction, message, } satisfies NotBytesAction); }); }); describe('should return dataset without issues', () => { const action = notBytes(5); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid strings', () => { expectNoActionIssue(action, ['', '1234', '123456', '123456789']); }); test('for valid chars', () => { expectNoActionIssue(action, [ 'あ', // 'あ' is 3 bytes '🤖', // '🤖' is 4 bytes 'あい', // 'あい' is 6 bytes ]); }); }); describe('should return dataset with issues', () => { const action = notBytes(5, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'not_bytes', expected: '!5', message: 'message', requirement: 5, }; const getReceived = (value: string) => `${new TextEncoder().encode(value).length}`; test('for invalid strings', () => { expectActionIssue(action, baseIssue, ['12345', 'abcde'], getReceived); }); test('for invalid chars', () => { expectActionIssue( action, baseIssue, [ '12あ', // 'あ' is 3 bytes '🤖!', // '🤖' is 4 bytes ], getReceived ); }); }); }); ================================================ FILE: library/src/actions/notBytes/notBytes.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _getByteCount } from '../../utils/index.ts'; /** * Not bytes issue interface. */ export interface NotBytesIssue< TInput extends string, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'not_bytes'; /** * The expected property. */ readonly expected: `!${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The not required bytes. */ readonly requirement: TRequirement; } /** * Not bytes action interface. */ export interface NotBytesAction< TInput extends string, TRequirement extends number, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'not_bytes'; /** * The action reference. */ readonly reference: typeof notBytes; /** * The expected property. */ readonly expects: `!${TRequirement}`; /** * The not required bytes. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a not [bytes](https://en.wikipedia.org/wiki/Byte) validation action. * * @param requirement The not required bytes. * * @returns A not bytes action. */ export function notBytes< TInput extends string, const TRequirement extends number, >(requirement: TRequirement): NotBytesAction; /** * Creates a not [bytes](https://en.wikipedia.org/wiki/Byte) validation action. * * @param requirement The not required bytes. * @param message The error message. * * @returns A not bytes action. */ export function notBytes< TInput extends string, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): NotBytesAction; // @__NO_SIDE_EFFECTS__ export function notBytes( requirement: number, message?: ErrorMessage> ): NotBytesAction< string, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'not_bytes', reference: notBytes, async: false, expects: `!${requirement}`, requirement, message, '~run'(dataset, config) { if (dataset.typed) { const length = _getByteCount(dataset.value); if (length === this.requirement) { _addIssue(this, 'bytes', dataset, config, { received: `${length}`, }); } } return dataset; }, }; } ================================================ FILE: library/src/actions/notEntries/index.ts ================================================ export * from './notEntries.ts'; ================================================ FILE: library/src/actions/notEntries/notEntries.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { notEntries, type NotEntriesAction, type NotEntriesIssue, } from './notEntries.ts'; describe('notEntries', () => { type Input = Record; describe('should return action object', () => { test('with undefined message', () => { type Action = NotEntriesAction; expectTypeOf(notEntries(10)).toEqualTypeOf(); expectTypeOf( notEntries(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( notEntries(10, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( notEntries string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = NotEntriesAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< NotEntriesIssue >(); }); }); }); ================================================ FILE: library/src/actions/notEntries/notEntries.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { RecordIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { notEntries, type NotEntriesAction, type NotEntriesIssue, } from './notEntries.ts'; describe('notEntries', () => { type Input = Record; describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'not_entries', reference: notEntries, expects: '!3', requirement: 3, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: NotEntriesAction = { ...baseAction, message: undefined, }; expect(notEntries(3)).toStrictEqual(action); expect(notEntries(3, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(notEntries(3, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies NotEntriesAction); }); test('with function message', () => { const message = () => 'message'; expect(notEntries(3, message)).toStrictEqual({ ...baseAction, message, } satisfies NotEntriesAction); }); }); describe('should return dataset without issues', () => { const action = notEntries(3); test('for untyped inputs', () => { const issues: [RecordIssue] = [ { kind: 'schema', type: 'record', input: null, expected: 'Object', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid objects', () => { expectNoActionIssue(action, [ {}, { foo: 1 }, { foo: 1, bar: 2 }, { foo: 1, bar: 2, baz: 3, qux: 4 }, { foo: 1, bar: 2, baz: 3, qux: 4, quux: 5 }, ]); }); }); describe('should return dataset with issues', () => { const action = notEntries(3, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'not_entries', expected: '!3', message: 'message', requirement: 3, }; test('for invalid objects', () => { expectActionIssue( action, baseIssue, [{ foo: 1, bar: 2, baz: 3 }], (value) => `${Object.keys(value).length}` ); }); }); }); ================================================ FILE: library/src/actions/notEntries/notEntries.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { EntriesInput } from '../types.ts'; /** * Not entries issue interface. * * @beta */ export interface NotEntriesIssue< TInput extends EntriesInput, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'not_entries'; /** * The expected property. */ readonly expected: `!${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The not required entries. */ readonly requirement: TRequirement; } /** * Not entries action interface. * * @beta */ export interface NotEntriesAction< TInput extends EntriesInput, TRequirement extends number, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation< TInput, TInput, NotEntriesIssue > { /** * The action type. */ readonly type: 'not_entries'; /** * The action reference. */ readonly reference: typeof notEntries; /** * The expected property. */ readonly expects: `!${TRequirement}`; /** * The not required entries. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a not entries validation action. * * @param requirement The not required entries. * * @returns A not entries action. * * @beta */ export function notEntries< TInput extends EntriesInput, const TRequirement extends number, >(requirement: TRequirement): NotEntriesAction; /** * Creates a not entries validation action. * * @param requirement The not required entries. * @param message The error message. * * @returns A not entries action. * * @beta */ export function notEntries< TInput extends EntriesInput, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): NotEntriesAction; // @__NO_SIDE_EFFECTS__ export function notEntries( requirement: number, message?: ErrorMessage> ): NotEntriesAction< EntriesInput, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'not_entries', reference: notEntries, async: false, expects: `!${requirement}`, requirement, message, '~run'(dataset, config) { if (!dataset.typed) return dataset; const count = Object.keys(dataset.value).length; if (dataset.typed && count === this.requirement) { _addIssue(this, 'entries', dataset, config, { received: `${count}`, }); } return dataset; }, }; } ================================================ FILE: library/src/actions/notGraphemes/index.ts ================================================ export * from './notGraphemes.ts'; ================================================ FILE: library/src/actions/notGraphemes/notGraphemes.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { notGraphemes, type NotGraphemesAction, type NotGraphemesIssue, } from './notGraphemes.ts'; describe('notGraphemes', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = NotGraphemesAction; expectTypeOf(notGraphemes(10)).toEqualTypeOf(); expectTypeOf( notGraphemes(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( notGraphemes(10, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( notGraphemes string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Input = 'example string'; type Action = NotGraphemesAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< NotGraphemesIssue >(); }); }); }); ================================================ FILE: library/src/actions/notGraphemes/notGraphemes.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { _getGraphemeCount } from '../../utils/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { notGraphemes, type NotGraphemesAction, type NotGraphemesIssue, } from './notGraphemes.ts'; describe('notGraphemes', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'not_graphemes', reference: notGraphemes, expects: '!5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: NotGraphemesAction = { ...baseAction, message: undefined, }; expect(notGraphemes(5)).toStrictEqual(action); expect(notGraphemes(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(notGraphemes(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies NotGraphemesAction); }); test('with function message', () => { const message = () => 'message'; expect(notGraphemes(5, message)).toStrictEqual({ ...baseAction, message, } satisfies NotGraphemesAction); }); }); describe('should return dataset without issues', () => { const action = notGraphemes(5); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid strings', () => { expectNoActionIssue(action, [ '', ' ', '1', '1234', '123 ', '123456', '12 456', '123456789', ]); }); test('for valid emoji', () => { expectNoActionIssue(action, [ '😀', '😀👋🏼🧩👩🏻‍🏫', '😀👋🏼🧩👩🏻‍🏫🫥🫠', '😀👋🏼🧩👩🏻‍🏫🫥🫠🧑‍💻👻🥎', ]); }); }); describe('should return dataset with issues', () => { const action = notGraphemes(5, 'message'); const baseIssue: Omit< NotGraphemesIssue, 'input' | 'received' > = { kind: 'validation', type: 'not_graphemes', expected: '!5', message: 'message', requirement: 5, }; test('for invalid strings', () => { expectActionIssue( action, baseIssue, ['12345', '12 45', '1234 ', 'hello'], (value) => `${_getGraphemeCount(value)}` ); }); test('for invalid emoji', () => { expectActionIssue( action, baseIssue, ['😀👋🏼🧩👩🏻‍🏫🫥'], (value) => `${_getGraphemeCount(value)}` ); }); }); }); ================================================ FILE: library/src/actions/notGraphemes/notGraphemes.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _getGraphemeCount } from '../../utils/index.ts'; /** * Not graphemes issue interface. */ export interface NotGraphemesIssue< TInput extends string, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'not_graphemes'; /** * The expected property. */ readonly expected: `!${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The not required graphemes. */ readonly requirement: TRequirement; } /** * Not graphemes action interface. */ export interface NotGraphemesAction< TInput extends string, TRequirement extends number, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation< TInput, TInput, NotGraphemesIssue > { /** * The action type. */ readonly type: 'not_graphemes'; /** * The action reference. */ readonly reference: typeof notGraphemes; /** * The expected property. */ readonly expects: `!${TRequirement}`; /** * The not required graphemes. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a not graphemes validation action. * * @param requirement The not required graphemes. * * @returns A not graphemes action. */ export function notGraphemes< TInput extends string, const TRequirement extends number, >( requirement: TRequirement ): NotGraphemesAction; /** * Creates a not graphemes validation action. * * @param requirement The not required graphemes. * @param message The error message. * * @returns A not graphemes action. */ export function notGraphemes< TInput extends string, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): NotGraphemesAction; // @__NO_SIDE_EFFECTS__ export function notGraphemes( requirement: number, message?: ErrorMessage> ): NotGraphemesAction< string, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'not_graphemes', reference: notGraphemes, async: false, expects: `!${requirement}`, requirement, message, '~run'(dataset, config) { if (dataset.typed) { const count = _getGraphemeCount(dataset.value); if (count === this.requirement) { _addIssue(this, 'graphemes', dataset, config, { received: `${count}`, }); } } return dataset; }, }; } ================================================ FILE: library/src/actions/notLength/index.ts ================================================ export * from './notLength.ts'; ================================================ FILE: library/src/actions/notLength/notLength.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { notLength, type NotLengthAction, type NotLengthIssue, } from './notLength.ts'; describe('notLength', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = NotLengthAction; expectTypeOf(notLength(10)).toEqualTypeOf(); expectTypeOf( notLength(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( notLength(10, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( notLength string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Input = [1, 'two', { value: 'three' }]; type Action = NotLengthAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< NotLengthIssue >(); }); }); }); ================================================ FILE: library/src/actions/notLength/notLength.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { notLength, type NotLengthAction, type NotLengthIssue, } from './notLength.ts'; describe('notLength', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'not_length', reference: notLength, expects: '!5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: NotLengthAction = { ...baseAction, message: undefined, }; expect(notLength(5)).toStrictEqual(action); expect(notLength(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(notLength(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies NotLengthAction); }); test('with function message', () => { const message = () => 'message'; expect(notLength(5, message)).toStrictEqual({ ...baseAction, message, } satisfies NotLengthAction); }); }); describe('should return dataset without issues', () => { const action = notLength(3); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid strings', () => { expectNoActionIssue(action, [ '', ' ', ' ', '\n', '\n\t', 'あ', // 'あ' is 3 bytes 'ab', 'abcd', '1', '12', '1234', '@', '@#', '@#$%', ]); }); test('for valid arrays', () => { expectNoActionIssue(action, [ [], [1], ['1', '2'], [1, '2', 3, '4'], [[1, 2, 3]], [[1, 2], ['3']], [{ 1: 'one', 2: 'two', 3: 'three' }], [[1], [2], null, [{ value: 3 }]], ]); }); }); describe('should return dataset with issues', () => { const action = notLength(3, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'not_length', expected: '!3', message: 'message', requirement: 3, }; test('for invalid strings', () => { expectActionIssue( action, baseIssue, [ ' ', ' \n\n', '\n\n\t', 'abc', 'ABC', '123', 'あああ', // 'あ' is 3 bytes but the total length of the string is 3 '@#$', ], (value) => `${value.length}` ); }); test('for invalid arrays', () => { expectActionIssue( action, baseIssue, [ [1, 2, 3], ['foo', 'bar', 'baz'], [1, null, undefined], [[1, 2, 3, 4], [5], [6, 7]], [{ value: 1 }, { value: 2 }, { value: 3 }], ['1', 2, { value: 3 }], ], (value) => `${value.length}` ); }); }); }); ================================================ FILE: library/src/actions/notLength/notLength.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { LengthInput } from '../types.ts'; /** * Not length issue interface. */ export interface NotLengthIssue< TInput extends LengthInput, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'not_length'; /** * The expected property. */ readonly expected: `!${TRequirement}`; /** * The received property. */ readonly received: `${TRequirement}`; /** * The not required length. */ readonly requirement: TRequirement; } /** * Not length action interface. */ export interface NotLengthAction< TInput extends LengthInput, TRequirement extends number, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'not_length'; /** * The action reference. */ readonly reference: typeof notLength; /** * The expected property. */ readonly expects: `!${TRequirement}`; /** * The not required length. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a not length validation action. * * @param requirement The not required length. * * @returns A not length action. */ export function notLength< TInput extends LengthInput, const TRequirement extends number, >(requirement: TRequirement): NotLengthAction; /** * Creates a not length validation action. * * @param requirement The not required length. * @param message The error message. * * @returns A not length action. */ export function notLength< TInput extends LengthInput, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): NotLengthAction; // @__NO_SIDE_EFFECTS__ export function notLength( requirement: number, message?: ErrorMessage> ): NotLengthAction< LengthInput, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'not_length', reference: notLength, async: false, expects: `!${requirement}`, requirement, message, '~run'(dataset, config) { if (dataset.typed && dataset.value.length === this.requirement) { _addIssue(this, 'length', dataset, config, { received: `${dataset.value.length}`, }); } return dataset; }, }; } ================================================ FILE: library/src/actions/notSize/index.ts ================================================ export * from './notSize.ts'; ================================================ FILE: library/src/actions/notSize/notSize.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { notSize, type NotSizeAction, type NotSizeIssue } from './notSize.ts'; describe('notSize', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = NotSizeAction; expectTypeOf(notSize(10)).toEqualTypeOf(); expectTypeOf( notSize(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(notSize(10, 'message')).toEqualTypeOf< NotSizeAction >(); }); test('with function message', () => { expectTypeOf( notSize string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = NotSizeAction, 10, undefined>; test('of input', () => { expectTypeOf>().toEqualTypeOf>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< NotSizeIssue, 10> >(); }); }); }); ================================================ FILE: library/src/actions/notSize/notSize.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { MapIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { notSize, type NotSizeAction, type NotSizeIssue } from './notSize.ts'; describe('notSize', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'not_size', reference: notSize, expects: '!5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: NotSizeAction = { ...baseAction, message: undefined, }; expect(notSize(5)).toStrictEqual(action); expect(notSize(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(notSize(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies NotSizeAction); }); test('with function message', () => { const message = () => 'message'; expect(notSize(5, message)).toStrictEqual({ ...baseAction, message, } satisfies NotSizeAction); }); }); describe('should return dataset without issues', () => { const action = notSize(3); test('for untyped inputs', () => { const issues: [MapIssue] = [ { kind: 'schema', type: 'map', input: null, expected: 'Map', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid maps', () => { expectNoActionIssue(action, [ new Map(), new Map([[1, 'one']]), new Map([ ['one', 1], ['two', null], ]), new Map([ [1, 'one'], [2, 'two'], ['3', 'three'], [4, null], ]), ]); }); test('for valid sets', () => { expectNoActionIssue(action, [ new Set(), new Set([1]), new Set(['one', null]), new Set('1234'), new Set([[1, 2, 3, 4], [5, 6], [7], [8, 9]]), ]); }); test('for valid blobs', () => { expectNoActionIssue(action, [ new Blob([]), new Blob(['']), new Blob([' ']), new Blob(['1']), new Blob(['hi'], { type: 'text/plain' }), new Blob([new Uint8Array([72, 105])]), // 'Hi' new Blob([' \t\n']), new Blob([new Uint8Array([104, 105, 33, 33])]), // 'hi!!' new Blob(['🤖']), new Blob(['🤖😍']), ]); }); }); describe('should return dataset with issues', () => { const action = notSize(3, 'message'); const baseIssue: Omit< NotSizeIssue, 3>, 'input' | 'received' > = { kind: 'validation', type: 'not_size', expected: '!3', message: 'message', requirement: 3, }; test('for invalid maps', () => { expectActionIssue( action, baseIssue, [ new Map([ [1, 'one'], [2, 'two'], [3, 'three'], ]), new Map([ [' ', 'space'], ['\n', 'new-line'], ['\t', 'tab'], ]), new Map([ ['one', 1], ['two', '2'], ['three', 3], ]), new Map([ ['1', 'one'], [2, null], [true, null], ]), ], (value) => `${value.size}` ); }); test('for invalid sets', () => { expectActionIssue( action, baseIssue, [ new Set([1, 2, 3]), new Set('123'), new Set([' ', '\n', '\t']), new Set([[1, 2, 3, 4], [5, 6], [7]]), new Set([1, 'two', null]), new Set(['1', { value: '5' }, null]), ], (value) => `${value.size}` ); }); test('for invalid blobs', () => { expectActionIssue( action, baseIssue, [ new Blob(['bot']), new Blob(['✨']), new Blob([' \t\n']), new Blob(['1', '2', '3'], { type: 'text/plain' }), new Blob( [ new Uint8Array([104, 105]), // 'hi' new Blob(['!'], { type: 'text/plain' }), ], { type: 'text/plain' } ), ], (value) => `${value.size}` ); }); }); }); ================================================ FILE: library/src/actions/notSize/notSize.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { SizeInput } from '../types.ts'; /** * Not size issue interface. */ export interface NotSizeIssue< TInput extends SizeInput, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'not_size'; /** * The expected property. */ readonly expected: `!${TRequirement}`; /** * The received property. */ readonly received: `${TRequirement}`; /** * The not required size. */ readonly requirement: TRequirement; } /** * Not size action interface. */ export interface NotSizeAction< TInput extends SizeInput, TRequirement extends number, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'not_size'; /** * The action reference. */ readonly reference: typeof notSize; /** * The expected property. */ readonly expects: `!${TRequirement}`; /** * The not required size. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a not size validation action. * * @param requirement The not required size. * * @returns A not size action. */ export function notSize< TInput extends SizeInput, const TRequirement extends number, >(requirement: TRequirement): NotSizeAction; /** * Creates a not size validation action. * * @param requirement The not required size. * @param message The error message. * * @returns A not size action. */ export function notSize< TInput extends SizeInput, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): NotSizeAction; // @__NO_SIDE_EFFECTS__ export function notSize( requirement: number, message?: ErrorMessage> ): NotSizeAction< SizeInput, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'not_size', reference: notSize, async: false, expects: `!${requirement}`, requirement, message, '~run'(dataset, config) { if (dataset.typed && dataset.value.size === this.requirement) { _addIssue(this, 'size', dataset, config, { received: `${dataset.value.size}`, }); } return dataset; }, }; } ================================================ FILE: library/src/actions/notValue/index.ts ================================================ export * from './notValue.ts'; ================================================ FILE: library/src/actions/notValue/notValue.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { notValue, type NotValueAction, type NotValueIssue, } from './notValue.ts'; describe('notValue', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = NotValueAction; expectTypeOf(notValue(10)).toEqualTypeOf(); expectTypeOf( notValue(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( notValue(10, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( notValue string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = NotValueAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< NotValueIssue >(); }); }); }); ================================================ FILE: library/src/actions/notValue/notValue.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { NumberIssue } from '../../schemas/index.ts'; import { _stringify } from '../../utils/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { notValue, type NotValueAction } from './notValue.ts'; describe('notValue', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'not_value', reference: notValue, expects: '!5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: NotValueAction = { ...baseAction, message: undefined, }; expect(notValue(5)).toStrictEqual(action); expect(notValue(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(notValue(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies NotValueAction); }); test('with function message', () => { const message = () => 'message'; expect(notValue(5, message)).toStrictEqual({ ...baseAction, message, } satisfies NotValueAction); }); }); describe('should return dataset with issues', () => { test('for untyped inputs', () => { const issues: [NumberIssue] = [ { kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', message: 'message', }, ]; expect( notValue(1)['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid bigints', () => { expectNoActionIssue(notValue(10n), [-123n, 0n, 9n, 11n, 123n]); }); test('for valid non-bigints', () => { expectNoActionIssue(notValue(10n), [ 9, 11, 9.0, 11.0, '9', '11', '9.0', '11.0', '', ' ', new Date(9), new Date(11), true, false, ]); expectNoActionIssue(notValue(1n), [ 0, 0.0, '0', ' 0 ', '', ' ', false, new Date(0), ]); expectNoActionIssue(notValue(0n), [ 1, 1.0, '1', ' 1 ', true, new Date(1), ]); }); test('for valid booleans', () => { expectNoActionIssue(notValue(true), [false]); expectNoActionIssue(notValue(false), [true]); }); test('for valid non-booleans', () => { expectNoActionIssue(notValue(true), [ 0n, 0, 0.0, '0', '0.0', ' 0 ', '', ' ', new Date(0), ]); expectNoActionIssue(notValue(true), [ 123n, 123, 123.0, '123', '123.0', 'foo', 'true', new Date(123), ]); expectNoActionIssue(notValue(false), [ 1n, 1, 1.0, '1', '1.0', ' 1 ', new Date(1), ]); expectNoActionIssue(notValue(false), [ 123n, 123, 123.0, '123', '123.0', 'foo', 'false', new Date(123), ]); }); test('for valid dates', () => { const date = new Date(); const nextDate = new Date(+date + 1); expectNoActionIssue(notValue(date), [ new Date(+date - 1), nextDate, new Date(+date + 999999), new Date(nextDate.getTime()), new Date(nextDate.toISOString()), new Date( nextDate.getFullYear(), nextDate.getMonth(), nextDate.getDate(), nextDate.getHours(), nextDate.getMinutes(), nextDate.getSeconds(), nextDate.getMilliseconds() ), ]); }); test('for valid non-dates', () => { expectNoActionIssue(notValue(new Date(10)), [ 9n, 11n, 9, 11, 9.0, 11.0, '9', '11', '9.0', '11.0', '', ' ', true, false, ]); expectNoActionIssue(notValue(new Date(1)), [ 0, 0.0, 0n, '0', '0.0', ' 0 ', '', ' ', false, ]); expectNoActionIssue(notValue(new Date(0)), [ 1, 1.0, 1n, '1', '1.0', ' 1 ', true, ]); }); test('for valid numbers', () => { expectNoActionIssue(notValue(10), [ -Infinity, Number.MIN_VALUE, -10, -9, 9, 11, 9999, Number.MAX_VALUE, Infinity, NaN, ]); }); test('for valid non-numbers', () => { expectNoActionIssue(notValue(10), [ 9n, 11n, '9', '11', '9.0', '11.0', '', ' ', new Date(9), true, false, ]); expectNoActionIssue(notValue(1), [ 0n, '0', '0.0', ' 0 ', '', ' ', false, new Date(0), ]); expectNoActionIssue(notValue(0), [ 1n, '1', '1.0', ' 1 ', true, new Date(1), ]); }); test('for valid strings', () => { expectNoActionIssue(notValue('2024'), [ '202', '024', ' 2024', '2024 ', '02024', '20240', '020240', '2025', '9999', 'XYZ', ]); }); test('for valid non-strings', () => { expectNoActionIssue(notValue('10'), [ 9n, 11n, 9, 11, 9.0, 11.0, new Date(9), new Date(11), true, false, ]); expectNoActionIssue(notValue('1'), [0n, 0, 0.0, false, new Date(0)]); expectNoActionIssue(notValue('0'), [1n, 1, 1.0, true, new Date(1)]); }); }); describe('should return dataset with issues', () => { const baseInfo = { kind: 'validation', type: 'not_value', message: 'message', } as const; const getReceived = (value: unknown): string => value instanceof Date ? value.toJSON() : _stringify(value); test('for invalid bigints', () => { expectActionIssue( notValue(123n, 'message'), { ...baseInfo, expected: '!123', requirement: 123n }, [123n, BigInt(123), BigInt('123')] ); }); test('for invalid non-bigints', () => { expectActionIssue( notValue(123n, 'message'), { ...baseInfo, expected: '!123', requirement: 123n }, [123, 123.0, '123', ' 123 ', new Date(123)], getReceived ); expectActionIssue( notValue(1n, 'message'), { ...baseInfo, expected: '!1', requirement: 1n }, [1, 1.0, '1', ' 1 ', true, new Date(1)], getReceived ); expectActionIssue( notValue(0n, 'message'), { ...baseInfo, expected: '!0', requirement: 0n }, [0, 0.0, '0', ' 0 ', '', ' ', false, new Date(0)], getReceived ); }); test('for invalid booleans', () => { expectActionIssue( notValue(true, 'message'), { ...baseInfo, expected: '!true', requirement: true }, [true] ); expectActionIssue( notValue(false, 'message'), { ...baseInfo, expected: '!false', requirement: false }, [false] ); }); test('for invalid non-booleans', () => { expectActionIssue( notValue(true, 'message'), { ...baseInfo, expected: '!true', requirement: true }, [1, 1.0, 1n, '1', '1.0', ' 1 ', new Date(1)], getReceived ); expectActionIssue( notValue(false, 'message'), { ...baseInfo, expected: '!false', requirement: false }, [0, 0.0, 0n, '0', '0.0', ' 0 ', '', ' ', new Date(0)], getReceived ); }); test('for invalid dates', () => { const date = new Date(); expectActionIssue( notValue(date, 'message'), { ...baseInfo, expected: `!${date.toJSON()}`, requirement: date }, [ date, new Date(date.getTime()), new Date(date.toISOString()), new Date( date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds() ), ], getReceived ); }); test('for invalid non-dates', () => { const date1 = new Date(123); expectActionIssue( notValue(date1, 'message'), { ...baseInfo, expected: `!${date1.toJSON()}`, requirement: date1 }, [123, 123.0, 123n, '123', '123.0', ' 123 '], getReceived ); const date2 = new Date(1); expectActionIssue( notValue(date2, 'message'), { ...baseInfo, expected: `!${date2.toJSON()}`, requirement: date2 }, [1, 1.0, 1n, '1', '1.0', ' 1 ', true], getReceived ); const date3 = new Date(0); expectActionIssue( notValue(date3, 'message'), { ...baseInfo, expected: `!${date3.toJSON()}`, requirement: date3 }, [0, 0.0, 0n, '0', '0.0', ' 0 ', '', ' ', false], getReceived ); }); test('for invalid numbers', () => { expectActionIssue( notValue(123, 'message'), { ...baseInfo, expected: '!123', requirement: 123 }, [123, 123.0, Number(123)] ); }); test('for invalid non-numbers', () => { expectActionIssue( notValue(123, 'message'), { ...baseInfo, expected: '!123', requirement: 123 }, [123n, '123', '123.0', ' 123 ', new Date(123)], getReceived ); expectActionIssue( notValue(1, 'message'), { ...baseInfo, expected: '!1', requirement: 1 }, [1n, '1', '1.0', ' 1 ', true, new Date(1)], getReceived ); expectActionIssue( notValue(0, 'message'), { ...baseInfo, expected: '!0', requirement: 0 }, [0n, '0', '0.0', ' 0 ', '', ' ', false, new Date(0)], getReceived ); }); test('for invalid strings', () => { expectActionIssue( notValue('2024', 'message'), { ...baseInfo, expected: '!"2024"', requirement: '2024' }, ['2024'] ); }); test('for invalid non-strings', () => { expectActionIssue( notValue('123', 'message'), { ...baseInfo, expected: '!"123"', requirement: '123' }, [123, 123.0, 123n, new Date(123)], getReceived ); expectActionIssue( notValue('1', 'message'), { ...baseInfo, expected: '!"1"', requirement: '1' }, [1n, 1, 1.0, true, new Date(1)], getReceived ); expectActionIssue( notValue('0', 'message'), { ...baseInfo, expected: '!"0"', requirement: '0' }, [0n, 0, 0.0, false, new Date(0)], getReceived ); }); }); }); ================================================ FILE: library/src/actions/notValue/notValue.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _stringify } from '../../utils/index.ts'; import type { ValueInput } from '../types.ts'; /** * Not value issue interface. */ export interface NotValueIssue< TInput extends ValueInput, TRequirement extends TInput, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'not_value'; /** * The expected property. */ readonly expected: `!${string}`; /** * The not required value. */ readonly requirement: TRequirement; } /** * Not value action interface. */ export interface NotValueAction< TInput extends ValueInput, TRequirement extends TInput, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'not_value'; /** * The action reference. */ readonly reference: typeof notValue; /** * The expected property. */ readonly expects: `!${string}`; /** * The not required value. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a not value validation action. * * @param requirement The not required value. * * @returns A not value action. */ export function notValue< TInput extends ValueInput, const TRequirement extends TInput, >(requirement: TRequirement): NotValueAction; /** * Creates a not value validation action. * * @param requirement The not required value. * @param message The error message. * * @returns A not value action. */ export function notValue< TInput extends ValueInput, const TRequirement extends TInput, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): NotValueAction; // @__NO_SIDE_EFFECTS__ export function notValue( requirement: ValueInput, message?: ErrorMessage> ): NotValueAction< ValueInput, ValueInput, ErrorMessage> | undefined > { return { kind: 'validation', type: 'not_value', reference: notValue, async: false, expects: requirement instanceof Date ? `!${requirement.toJSON()}` : `!${_stringify(requirement)}`, requirement, message, '~run'(dataset, config) { if ( dataset.typed && this.requirement <= dataset.value && this.requirement >= dataset.value ) { _addIssue(this, 'value', dataset, config, { received: dataset.value instanceof Date ? dataset.value.toJSON() : _stringify(dataset.value), }); } return dataset; }, }; } ================================================ FILE: library/src/actions/notValues/index.ts ================================================ export * from './notValues.ts'; ================================================ FILE: library/src/actions/notValues/notValues.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { notValues, type NotValuesAction, type NotValuesIssue, } from './notValues.ts'; describe('notValues', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = NotValuesAction; expectTypeOf(notValues([7, 12])).toEqualTypeOf(); expectTypeOf( notValues([7, 12], undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( notValues([7, 12], 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( notValues string>([7, 12], () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = NotValuesAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< NotValuesIssue >(); }); }); }); ================================================ FILE: library/src/actions/notValues/notValues.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { NumberIssue } from '../../schemas/index.ts'; import { _stringify } from '../../utils/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { notValues, type NotValuesAction } from './notValues.ts'; describe('notValues', () => { describe('should return action object', () => { const baseAction: Omit< NotValuesAction, 'message' > = { kind: 'validation', type: 'not_values', reference: notValues, expects: '!(1 | 3 | 5)', requirement: [1, 3, 5], async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: NotValuesAction = { ...baseAction, message: undefined, }; expect(notValues([1, 3, 5])).toStrictEqual(action); expect(notValues([1, 3, 5], undefined)).toStrictEqual(action); }); test('with string message', () => { expect(notValues([1, 3, 5], 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies NotValuesAction); }); test('with function message', () => { const message = () => 'message'; expect(notValues([1, 3, 5], message)).toStrictEqual({ ...baseAction, message, } satisfies NotValuesAction); }); }); describe('should return dataset without issues', () => { test('for untyped inputs', () => { const issues: [NumberIssue] = [ { kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', message: 'message', }, ]; expect( notValues([1, 3, 5])['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid bigints', () => { expectNoActionIssue(notValues([10n, 11n, 12n]), [ -123n, 0n, 9n, 13n, 123n, ]); }); test('for valid non-bigints', () => { expectNoActionIssue(notValues([10n, 11n, 12n]), [ 9, 13, 9.0, 13.0, '9', '13', '9.0', '13.0', '', ' ', new Date(9), new Date(13), true, false, ]); expectNoActionIssue(notValues([1n]), [ 0, 0.0, '0', ' 0 ', '', ' ', false, new Date(0), ]); expectNoActionIssue(notValues([0n]), [ 1, 1.0, '1', ' 1 ', true, new Date(1), ]); }); test('for valid booleans', () => { expectNoActionIssue(notValues([true]), [false]); expectNoActionIssue(notValues([false]), [true]); }); test('for valid non-booleans', () => { expectNoActionIssue(notValues([true]), [ 0n, 0, 0.0, '0', '0.0', ' 0 ', '', ' ', new Date(0), ]); expectNoActionIssue(notValues([true]), [ 123n, 123, 123.0, '123', '123.0', 'foo', 'true', new Date(123), ]); expectNoActionIssue(notValues([false]), [ 1n, 1, 1.0, '1', '1.0', ' 1 ', new Date(1), ]); expectNoActionIssue(notValues([false]), [ 123n, 123, 123.0, '123', '123.0', 'foo', 'false', new Date(123), ]); }); test('for valid dates', () => { const negDate = new Date(-10); const posDate = new Date(12); const nextPosDate = new Date(+posDate + 1); expectNoActionIssue(notValues([negDate, posDate]), [ new Date(0), new Date(+negDate - 1), new Date(+negDate + 1), new Date(+posDate - 1), nextPosDate, new Date(nextPosDate.getTime()), new Date(nextPosDate.toISOString()), new Date( nextPosDate.getFullYear(), nextPosDate.getMonth(), nextPosDate.getDate(), nextPosDate.getHours(), nextPosDate.getMinutes(), nextPosDate.getSeconds(), nextPosDate.getMilliseconds() ), ]); expectNoActionIssue(notValues([new Date(0)]), [ new Date(-1), new Date(1), ]); }); test('for valid non-dates', () => { expectNoActionIssue( notValues([new Date(10), new Date(11), new Date(12)]), [ 9n, 13n, 9, 13, 9.0, 13.0, '9', '13', '9.0', '13.0', '', ' ', true, false, ] ); expectNoActionIssue(notValues([new Date(1)]), [ 0, 0.0, 0n, '0', '0.0', ' 0 ', '', ' ', false, ]); expectNoActionIssue(notValues([new Date(0)]), [ 1, 1.0, 1n, '1', '1.0', ' 1 ', true, ]); }); test('for valid numbers', () => { expectNoActionIssue(notValues([10, 11, 12]), [ -Infinity, Number.MIN_VALUE, -10, -9, 9, 13, 9999, Number.MAX_VALUE, Infinity, NaN, ]); expectNoActionIssue(notValues([0]), [ -1, 1, -1.0, 1.0, -Infinity, Infinity, NaN, ]); }); test('for valid non-numbers', () => { expectNoActionIssue(notValues([10, 11, 12]), [ 9n, 13n, '9', '13', '9.0', '13.0', '', ' ', new Date(9), new Date(13), true, false, ]); expectNoActionIssue(notValues([1]), [ 0n, '0', '0.0', ' 0 ', '', ' ', false, new Date(0), ]); expectNoActionIssue(notValues([0]), [ 1n, '1', '1.0', ' 1 ', true, new Date(1), ]); }); test('for valid strings', () => { expectNoActionIssue(notValues(['-100', '10']), [ ' -100 ', ' 10 ', '-100.0', '10.0', '-1000', '100', '-0100', '010', '-99', '-101', '9', '11', '', ' ', 'abc', ]); expectNoActionIssue(notValues(['0']), [ '', ' ', ' 0 ', '0.0', '-0', 'abc', ]); }); test('for valid non-strings', () => { expectNoActionIssue(notValues(['10', '11', '12']), [ 9n, 13n, 9, 13, 9.0, 13.0, new Date(9), new Date(13), true, false, ]); expectNoActionIssue(notValues(['1']), [0n, 0, 0.0, false, new Date(0)]); expectNoActionIssue(notValues(['0']), [1n, 1, 1.0, true, new Date(1)]); }); }); describe('should return dataset with issues', () => { const baseInfo = { kind: 'validation', type: 'not_values', message: 'message', } as const; const getReceived = (value: unknown): string => value instanceof Date ? value.toJSON() : _stringify(value); test('for invalid bigints', () => { expectActionIssue( notValues([-2n, 0n, 3n], 'message'), { ...baseInfo, expected: '!(-2 | 0 | 3)', requirement: [-2n, 0n, 3n], }, [-2n, 0n, 3n, BigInt(3), BigInt('3')] ); }); test('for invalid non-bigints', () => { expectActionIssue( notValues([10n, 11n, 12n], 'message'), { ...baseInfo, expected: '!(10 | 11 | 12)', requirement: [10n, 11n, 12n], }, [ 10, 11, 12, 10.0, 11.0, 12.0, '10', '11', '12', ' 10 ', ' 11 ', ' 12 ', new Date(10), new Date(11), new Date(12), ], getReceived ); expectActionIssue( notValues([1n], 'message'), { ...baseInfo, expected: '!1', requirement: [1n] }, [1, 1.0, '1', ' 1 ', true, new Date(1)], getReceived ); expectActionIssue( notValues([0n], 'message'), { ...baseInfo, expected: '!0', requirement: [0n] }, [0, 0.0, '0', ' 0 ', '', ' ', false, new Date(0)], getReceived ); }); test('for invalid booleans', () => { expectActionIssue( notValues([true], 'message'), { ...baseInfo, expected: '!true', requirement: [true] }, [true] ); expectActionIssue( notValues([false], 'message'), { ...baseInfo, expected: '!false', requirement: [false] }, [false] ); }); test('for invalid non-booleans', () => { expectActionIssue( notValues([true], 'message'), { ...baseInfo, expected: '!true', requirement: [true] }, [1, 1.0, 1n, '1', '1.0', new Date(1)], getReceived ); expectActionIssue( notValues([false], 'message'), { ...baseInfo, expected: '!false', requirement: [false] }, [0, 0.0, 0n, '0', '0.0', '', ' ', new Date(0)], getReceived ); expectActionIssue( notValues([false, true], 'message'), { ...baseInfo, expected: '!(false | true)', requirement: [false, true], }, [ 0, 1, 0.0, 1.0, 0n, 1n, '0', '1', '0.0', '1.0', '', ' ', new Date(0), new Date(1), ], getReceived ); }); test('for invalid dates', () => { const negDate = new Date(-2); const posDate = new Date(3); expectActionIssue( notValues([negDate, posDate], 'message'), { ...baseInfo, expected: `!(${negDate.toJSON()} | ${posDate.toJSON()})`, requirement: [negDate, posDate], }, [ negDate, posDate, new Date(posDate.getTime()), new Date(posDate.toISOString()), new Date( posDate.getFullYear(), posDate.getMonth(), posDate.getDate(), posDate.getHours(), posDate.getMinutes(), posDate.getSeconds(), posDate.getMilliseconds() ), ], getReceived ); const zeroDate = new Date(0); expectActionIssue( notValues([zeroDate], 'message'), { ...baseInfo, expected: `!${zeroDate.toJSON()}`, requirement: [zeroDate], }, [zeroDate, new Date(0)], getReceived ); }); test('for invalid non-dates', () => { const date1 = new Date(10); const date2 = new Date(11); const date3 = new Date(12); expectActionIssue( notValues([date1, date2, date3], 'message'), { ...baseInfo, expected: `!(${date1.toJSON()} | ${date2.toJSON()} | ${date3.toJSON()})`, requirement: [date1, date2, date3], }, [ 10, 11, 12, 10.0, 11.0, 12.0, 10n, 11n, 12n, '10', '11', '12', '10.0', '11.0', '12.0', ' 10 ', ' 11 ', ' 12 ', ], getReceived ); const date4 = new Date(1); expectActionIssue( notValues([date4], 'message'), { ...baseInfo, expected: `!${date4.toJSON()}`, requirement: [date4] }, [1, 1.0, 1n, '1', '1.0', ' 1 ', true], getReceived ); const date5 = new Date(0); expectActionIssue( notValues([date5], 'message'), { ...baseInfo, expected: `!${date5.toJSON()}`, requirement: [date5] }, [0, 0.0, 0n, '0', '0.0', ' 0 ', '', ' ', false], getReceived ); }); test('for invalid numbers', () => { expectActionIssue( notValues([-2, 3], 'message'), { ...baseInfo, expected: '!(-2 | 3)', requirement: [-2, 3] }, [-2, 3, -2.0, 3.0] ); expectActionIssue( notValues([0], 'message'), { ...baseInfo, expected: '!0', requirement: [0] }, [-0, 0.0, 0] ); }); test('for invalid non-numbers', () => { expectActionIssue( notValues([10, 11, 12], 'message'), { ...baseInfo, expected: '!(10 | 11 | 12)', requirement: [10, 11, 12] }, [ 10n, 11n, 12n, '10', '11', '12', '10.0', '11.0', '12.0', ' 10 ', ' 11 ', ' 12 ', new Date(10), new Date(11), new Date(12), ], getReceived ); expectActionIssue( notValues([1], 'message'), { ...baseInfo, expected: '!1', requirement: [1] }, [1n, '1', '1.0', ' 1 ', true, new Date(1)], getReceived ); expectActionIssue( notValues([0], 'message'), { ...baseInfo, expected: '!0', requirement: [0] }, [0n, '0', '0.0', ' 0 ', '', ' ', false, new Date(0)], getReceived ); }); test('for invalid strings', () => { expectActionIssue( notValues(['2024', '2025'], 'message'), { ...baseInfo, expected: '!("2024" | "2025")', requirement: ['2024', '2025'], }, ['2024', '2025'] ); expectActionIssue( notValues(['0'], 'message'), { ...baseInfo, expected: '!"0"', requirement: ['0'], }, ['0'] ); }); test('for invalid non-strings', () => { expectActionIssue( notValues(['10', '11', '12'], 'message'), { ...baseInfo, expected: '!("10" | "11" | "12")', requirement: ['10', '11', '12'], }, [ 10n, 11n, 12n, 10, 11, 12, 10.0, 11.0, 12.0, new Date(10), new Date(11), new Date(12), ], getReceived ); expectActionIssue( notValues(['1'], 'message'), { ...baseInfo, expected: '!"1"', requirement: ['1'] }, [1n, 1, 1.0, true, new Date(1)], getReceived ); expectActionIssue( notValues(['0'], 'message'), { ...baseInfo, expected: '!"0"', requirement: ['0'] }, [0n, 0, 0.0, false, new Date(0)], getReceived ); }); }); }); ================================================ FILE: library/src/actions/notValues/notValues.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _joinExpects, _stringify } from '../../utils/index.ts'; import type { ValueInput } from '../types.ts'; /** * Not values issue type. */ export interface NotValuesIssue< TInput extends ValueInput, TRequirement extends readonly TInput[], > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'not_values'; /** * The expected property. */ readonly expected: `!${string}`; /** * The not required values. */ readonly requirement: TRequirement; } /** * Not values action type. */ export interface NotValuesAction< TInput extends ValueInput, TRequirement extends readonly TInput[], TMessage extends | ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'not_values'; /** * The action reference. */ readonly reference: typeof notValues; /** * The expected property. */ readonly expects: `!${string}`; /** * The not required values. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a not values validation action. * * @param requirement The not required values. * * @returns A not values action. */ export function notValues< TInput extends ValueInput, const TRequirement extends readonly TInput[], >(requirement: TRequirement): NotValuesAction; /** * Creates a not values validation action. * * @param requirement The not required values. * @param message The error message. * * @returns A not values action. */ export function notValues< TInput extends ValueInput, const TRequirement extends readonly TInput[], const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): NotValuesAction; // @__NO_SIDE_EFFECTS__ export function notValues( requirement: readonly ValueInput[], message?: ErrorMessage> ): NotValuesAction< ValueInput, readonly ValueInput[], ErrorMessage> | undefined > { return { kind: 'validation', type: 'not_values', reference: notValues, async: false, expects: `!${_joinExpects( requirement.map((value) => value instanceof Date ? value.toJSON() : _stringify(value) ), '|' )}`, requirement, message, '~run'(dataset, config) { if ( dataset.typed && this.requirement.some( (value) => value <= dataset.value && value >= dataset.value ) ) { _addIssue(this, 'value', dataset, config, { received: dataset.value instanceof Date ? dataset.value.toJSON() : _stringify(dataset.value), }); } return dataset; }, }; } ================================================ FILE: library/src/actions/notWords/index.ts ================================================ export * from './notWords.ts'; ================================================ FILE: library/src/actions/notWords/notWords.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { notWords, type NotWordsAction, type NotWordsIssue, } from './notWords.ts'; describe('notWords', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = NotWordsAction; expectTypeOf(notWords('en', 3)).toEqualTypeOf(); expectTypeOf( notWords('en', 3, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( notWords('en', 3, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( notWords string>('en', 3, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Input = 'foo bar baz'; type Action = NotWordsAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< NotWordsIssue >(); }); }); }); ================================================ FILE: library/src/actions/notWords/notWords.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { _getWordCount } from '../../utils/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { notWords, type NotWordsAction, type NotWordsIssue, } from './notWords.ts'; describe('notWords', () => { describe('should return action object', () => { const baseAction: Omit< NotWordsAction, 'message' > = { kind: 'validation', type: 'not_words', reference: notWords, expects: '!3', locales: 'en', requirement: 3, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: NotWordsAction = { ...baseAction, message: undefined, }; expect(notWords('en', 3)).toStrictEqual(action); expect(notWords('en', 3, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(notWords('en', 3, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies NotWordsAction); }); test('with function message', () => { const message = () => 'message'; expect(notWords('en', 3, message)).toStrictEqual({ ...baseAction, message, } satisfies NotWordsAction); }); }); describe('should return dataset without issues', () => { const action = notWords('en', 3); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid strings', () => { expectNoActionIssue(action, [ '', ' ', 'foo', 'foo bar', 'for bar baz qux', 'Lorem ipsum?', 'Lorem ipsum dolor sit?', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit?', 'Hi, welcome!', 'Hi, welcome home! How are you?', ]); }); }); describe('should return dataset with issues', () => { const action = notWords('en', 3, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'not_words', expected: '!3', message: 'message', requirement: 3, }; test('for invalid strings', () => { expectActionIssue( action, baseIssue, ['foo bar baz', 'Lorem ipsum dolor?', 'Hi, welcome home!'], (value) => `${_getWordCount('en', value)}` ); }); }); }); ================================================ FILE: library/src/actions/notWords/notWords.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _getWordCount } from '../../utils/index.ts'; /** * Not words issue interface. */ export interface NotWordsIssue< TInput extends string, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'not_words'; /** * The expected property. */ readonly expected: `!${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The not required words. */ readonly requirement: TRequirement; } /** * Not words action interface. */ export interface NotWordsAction< TInput extends string, TLocales extends Intl.LocalesArgument, TRequirement extends number, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'not_words'; /** * The action reference. */ readonly reference: typeof notWords; /** * The expected property. */ readonly expects: `!${TRequirement}`; /** * The locales to be used. */ readonly locales: TLocales; /** * The not required words. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a not words validation action. * * @param locales The locales to be used. * @param requirement The not required words. * * @returns A not words action. */ export function notWords< TInput extends string, TLocales extends Intl.LocalesArgument, const TRequirement extends number, >( locales: TLocales, requirement: TRequirement ): NotWordsAction; /** * Creates a not words validation action. * * @param locales The locales to be used. * @param requirement The not required words. * @param message The error message. * * @returns A not words action. */ export function notWords< TInput extends string, TLocales extends Intl.LocalesArgument, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( locales: TLocales, requirement: TRequirement, message: TMessage ): NotWordsAction; // @__NO_SIDE_EFFECTS__ export function notWords( locales: Intl.LocalesArgument, requirement: number, message?: ErrorMessage> ): NotWordsAction< string, Intl.LocalesArgument, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'not_words', reference: notWords, async: false, expects: `!${requirement}`, locales, requirement, message, '~run'(dataset, config) { if (dataset.typed) { const count = _getWordCount(this.locales, dataset.value); if (count === this.requirement) { _addIssue(this, 'words', dataset, config, { received: `${count}`, }); } } return dataset; }, }; } ================================================ FILE: library/src/actions/octal/index.ts ================================================ export * from './octal.ts'; ================================================ FILE: library/src/actions/octal/octal.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { octal, type OctalAction, type OctalIssue } from './octal.ts'; describe('octal', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = OctalAction; expectTypeOf(octal()).toEqualTypeOf(); expectTypeOf(octal(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(octal('message')).toEqualTypeOf< OctalAction >(); }); test('with function message', () => { expectTypeOf(octal string>(() => 'message')).toEqualTypeOf< OctalAction string> >(); }); }); describe('should infer correct types', () => { type Action = OctalAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/octal/octal.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { OCTAL_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { octal, type OctalAction, type OctalIssue } from './octal.ts'; describe('octal', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'octal', reference: octal, expects: null, requirement: OCTAL_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: OctalAction = { ...baseAction, message: undefined, }; expect(octal()).toStrictEqual(action); expect(octal(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(octal('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies OctalAction); }); test('with function message', () => { const message = () => 'message'; expect(octal(message)).toStrictEqual({ ...baseAction, message, } satisfies OctalAction); }); }); describe('should return dataset without issues', () => { const action = octal(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for octal chars', () => { expectNoActionIssue(action, ['0', '1', '2', '3', '4', '5', '6', '7']); }); test('for two chars', () => { expectNoActionIssue(action, ['00', '12', '77']); }); test('for multiple chars', () => { expectNoActionIssue(action, [ '000000000000000', '777777777777', '01234567', '1234567', ]); }); test('for 0o prefix', () => { expectNoActionIssue(action, [ '0o000000000000000', '0o777777777777', '0o01234567', '0o1234567', ]); }); }); describe('should return dataset with issues', () => { const action = octal('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'octal', expected: null, message: 'message', requirement: OCTAL_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for blank spaces', () => { expectActionIssue(action, baseIssue, [' 1', '1 ', ' 1 ', '1 2']); }); test('for number signs', () => { expectActionIssue(action, baseIssue, ['+1', '-1', '+123', '-123']); }); test('for float numbers', () => { expectActionIssue(action, baseIssue, ['0.1', '123.456']); }); test('for exponential numbers', () => { expectActionIssue(action, baseIssue, ['1e-3', '1e+3']); }); test('for invalid digits', () => { expectActionIssue(action, baseIssue, [ '8', '9', '012345678', '012384567', '901234567', ]); }); test('for invalid letters', () => { expectActionIssue(action, baseIssue, [ 'a', 'A', 'b', 'B', 'y', 'Y', 'z', 'Z', '012345abc67', '012345ABC68789', '01234568789abc', '012345abc68789ABC', 'xyz01234568789abc', 'XYZ012345abc68789', '123456789abcdefghijklmnopqrstuvwxyz', '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', ]); }); test('for only prefix', () => { expectActionIssue(action, baseIssue, ['0o', '0O']); }); test('for invalid prefix', () => { expectActionIssue(action, baseIssue, [ '0h01234567', '0H01234567', '0x01234567', '0X01234567', ]); }); test('for special chars', () => { expectActionIssue(action, baseIssue, [ '-', '-1', '+', '+1', '#', '#1', '$', '$1', '%', '1%', ]); }); }); }); ================================================ FILE: library/src/actions/octal/octal.ts ================================================ import { OCTAL_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Octal issue interface. */ export interface OctalIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'octal'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The octal regex. */ readonly requirement: RegExp; } /** * Octal action interface. */ export interface OctalAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'octal'; /** * The action reference. */ readonly reference: typeof octal; /** * The expected property. */ readonly expects: null; /** * The octal regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates an [octal](https://en.wikipedia.org/wiki/Octal) validation action. * * @returns An octal action. */ export function octal(): OctalAction; /** * Creates an [octal](https://en.wikipedia.org/wiki/Octal) validation action. * * @param message The error message. * * @returns An octal action. */ export function octal< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): OctalAction; // @__NO_SIDE_EFFECTS__ export function octal( message?: ErrorMessage> ): OctalAction> | undefined> { return { kind: 'validation', type: 'octal', reference: octal, async: false, expects: null, requirement: OCTAL_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'octal', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/parseBoolean/index.ts ================================================ export * from './parseBoolean.ts'; ================================================ FILE: library/src/actions/parseBoolean/parseBoolean.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { parseBoolean, type ParseBooleanAction, type ParseBooleanConfig, type ParseBooleanIssue, } from './parseBoolean.ts'; describe('parseBoolean', () => { describe('should return action object', () => { const config: ParseBooleanConfig = { truthy: ['yep'], falsy: ['nope'], }; test('with undefined config and undefined message', () => { type Action = ParseBooleanAction; expectTypeOf(parseBoolean()).toEqualTypeOf(); expectTypeOf(parseBoolean(undefined)).toEqualTypeOf(); expectTypeOf(parseBoolean(undefined, undefined)).toEqualTypeOf(); }); test('with undefined config and string message', () => { expectTypeOf(parseBoolean(undefined, 'message')).toEqualTypeOf< ParseBooleanAction >(); }); test('with undefined config and function message', () => { expectTypeOf(parseBoolean(undefined, () => 'message')).toEqualTypeOf< ParseBooleanAction string> >(); }); test('with config and undefined message', () => { type Action = ParseBooleanAction; expectTypeOf(parseBoolean(config)).toEqualTypeOf(); expectTypeOf(parseBoolean(config, undefined)).toEqualTypeOf(); }); test('with config and string message', () => { expectTypeOf(parseBoolean(config, 'message')).toEqualTypeOf< ParseBooleanAction >(); }); test('with config and function message', () => { expectTypeOf(parseBoolean(config, () => 'message')).toEqualTypeOf< ParseBooleanAction string> >(); }); test('with mixed-type config', () => { const mixedConfig: ParseBooleanConfig = { truthy: [1, true, 'yes'], falsy: [0, false, null], }; type Action = ParseBooleanAction; expectTypeOf(parseBoolean(mixedConfig)).toEqualTypeOf(); }); }); describe('should infer correct types', () => { type Input = 'foo'; type Action = ParseBooleanAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< ParseBooleanIssue >(); }); }); }); ================================================ FILE: library/src/actions/parseBoolean/parseBoolean.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { parseBoolean, type ParseBooleanAction, type ParseBooleanConfig, type ParseBooleanIssue, } from './parseBoolean.ts'; describe('parseBoolean', () => { const defaultExpected = '(true | 1 | "true" | "1" | "yes" | "y" | "on" | "enabled" | false | 0 | "false" | "0" | "no" | "n" | "off" | "disabled")'; describe('should return action object', () => { const config: ParseBooleanConfig = { truthy: ['yep'], falsy: ['nope'], }; const baseAction: Omit< ParseBooleanAction, 'message' | 'config' | 'expects' > = { kind: 'transformation', type: 'parse_boolean', reference: parseBoolean, async: false, '~run': expect.any(Function), }; test('with undefined config and undefined message', () => { const action: ParseBooleanAction = { ...baseAction, expects: defaultExpected, config: undefined, message: undefined, }; expect(parseBoolean()).toStrictEqual(action); expect(parseBoolean(undefined)).toStrictEqual(action); expect(parseBoolean(undefined, undefined)).toStrictEqual(action); }); test('with undefined config and string message', () => { expect(parseBoolean(undefined, 'message')).toStrictEqual({ ...baseAction, expects: defaultExpected, config: undefined, message: 'message', } satisfies ParseBooleanAction); }); test('with undefined config and function message', () => { const message = () => 'message'; expect(parseBoolean(undefined, message)).toStrictEqual({ ...baseAction, expects: defaultExpected, config: undefined, message, } satisfies ParseBooleanAction string>); }); test('with config and undefined message', () => { const action: ParseBooleanAction = { ...baseAction, expects: '("yep" | "nope")', config, message: undefined, }; expect(parseBoolean(config)).toStrictEqual(action); expect(parseBoolean(config, undefined)).toStrictEqual(action); }); test('with config and string message', () => { expect(parseBoolean(config, 'message')).toStrictEqual({ ...baseAction, expects: '("yep" | "nope")', config, message: 'message', } satisfies ParseBooleanAction); }); test('with config and function message', () => { const message = () => 'message'; expect(parseBoolean(config, message)).toStrictEqual({ ...baseAction, expects: '("yep" | "nope")', config, message, } satisfies ParseBooleanAction string>); }); }); describe('should handle default config', () => { const action = parseBoolean(); 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, }); }); test('for boolean true', () => { expect(action['~run']({ typed: true, value: true }, {})).toStrictEqual({ typed: true, value: true, }); }); test('for number 1', () => { expect(action['~run']({ typed: true, value: 1 }, {})).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, }); }); test('for boolean false', () => { expect(action['~run']({ typed: true, value: false }, {})).toStrictEqual( { typed: true, value: false, } ); }); test('for number 0', () => { expect(action['~run']({ typed: true, value: 0 }, {})).toStrictEqual({ typed: true, value: false, }); }); }); }); describe('should handle custom config with `truthy` only', () => { describe('for lowercase `truthy` values', () => { const action = parseBoolean({ 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 = parseBoolean({ 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 config with `falsy` only', () => { describe('for lowercase `falsy` values', () => { const action = parseBoolean({ 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 = parseBoolean({ 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 config all together', () => { const action = parseBoolean({ truthy: ['YEP'], falsy: ['NOPE'], }); 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 handle custom non-string config', () => { const action = parseBoolean({ truthy: [1, true], falsy: [0, false, null], }); test('for number 1', () => { expect(action['~run']({ typed: true, value: 1 }, {})).toStrictEqual({ typed: true, value: true, }); }); test('for boolean true', () => { expect(action['~run']({ typed: true, value: true }, {})).toStrictEqual({ typed: true, value: true, }); }); test('for number 0', () => { expect(action['~run']({ typed: true, value: 0 }, {})).toStrictEqual({ typed: true, value: false, }); }); test('for boolean false', () => { expect(action['~run']({ typed: true, value: false }, {})).toStrictEqual({ typed: true, value: false, }); }); test('for null', () => { expect(action['~run']({ typed: true, value: null }, {})).toStrictEqual({ typed: true, value: false, }); }); }); describe('should return dataset with issues', () => { describe('for default config', () => { const action = parseBoolean(); const baseIssue: Omit< ParseBooleanIssue, 'input' | 'received' | 'message' > = { kind: 'transformation', type: 'parse_boolean', 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 boolean: 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 boolean: 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 boolean: Expected ${defaultExpected} but received 123`, }, ], }); }); }); describe('for custom config truthy only', () => { const action = parseBoolean({ truthy: ['yep'], }); const baseIssue: Omit< ParseBooleanIssue, 'input' | 'received' | 'message' > = { kind: 'transformation', type: 'parse_boolean', expected: '("yep" | false | 0 | "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 boolean: Expected ${baseIssue.expected} but received "enabled"`, }, ], }); }); }); describe('for custom config falsy only', () => { const action = parseBoolean({ falsy: ['nope'], }); const baseIssue: Omit< ParseBooleanIssue, 'input' | 'received' | 'message' > = { kind: 'transformation', type: 'parse_boolean', expected: '(true | 1 | "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 boolean: Expected ${baseIssue.expected} but received "disabled"`, }, ], }); }); }); describe('for custom config all together', () => { const action = parseBoolean({ truthy: ['YEP'], falsy: ['NOPE'], }); const baseIssue: Omit< ParseBooleanIssue, 'input' | 'received' | 'message' > = { kind: 'transformation', type: 'parse_boolean', expected: '("YEP" | "NOPE")', requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for invalid input as string "something"', () => { const value = 'something'; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value, issues: [ { ...baseIssue, input: value, received: '"something"', message: `Invalid boolean: Expected ${baseIssue.expected} but received "something"`, }, ], }); }); }); describe('with custom message', () => { test('with string message', () => { const action = parseBoolean(undefined, 'custom message'); const value = 'something'; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value, issues: [ { kind: 'transformation', type: 'parse_boolean', expected: defaultExpected, input: value, received: '"something"', message: 'custom message', requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }, ], }); }); test('with function message', () => { const message = () => 'custom message'; const action = parseBoolean(undefined, message); const value = 'something'; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value, issues: [ { kind: 'transformation', type: 'parse_boolean', expected: defaultExpected, input: value, received: '"something"', message: 'custom message', requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }, ], }); }); }); }); }); ================================================ FILE: library/src/actions/parseBoolean/parseBoolean.ts ================================================ import type { BaseIssue, BaseTransformation, ErrorMessage, MaybeReadonly, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _joinExpects, _stringify } from '../../utils/index.ts'; const TRUTHY = [true, 1, 'true', '1', 'yes', 'y', 'on', 'enabled']; const FALSY = [false, 0, 'false', '0', 'no', 'n', 'off', 'disabled']; /** * Parse boolean config interface. * * @beta */ export interface ParseBooleanConfig { /** * The truthy values. */ truthy?: MaybeReadonly | undefined; /** * The falsy values. */ falsy?: MaybeReadonly | undefined; } /** * Parse boolean issue interface. * * @beta */ export interface ParseBooleanIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'transformation'; /** * The issue type. */ readonly type: 'parse_boolean'; /** * The expected property. */ readonly expected: string; } /** * Parse boolean action interface. * * @beta */ export interface ParseBooleanAction< TInput, TConfig extends ParseBooleanConfig | undefined, TMessage extends | ErrorMessage> | undefined = undefined, > extends BaseTransformation> { /** * The action type. */ readonly type: 'parse_boolean'; /** * The action reference. */ readonly reference: typeof parseBoolean; /** * The expected property. */ readonly expects: string; /** * The parse boolean config. */ readonly config: TConfig; /** * The error message. */ readonly message: TMessage; } /** * Creates a parse boolean transformation action. * * @returns A parse boolean action. * * @beta */ export function parseBoolean(): ParseBooleanAction< TInput, undefined, undefined >; /** * Creates a parse boolean transformation action. * * @param config The parse boolean config. * * @returns A parse boolean action. * * @beta */ export function parseBoolean< TInput, const TConfig extends ParseBooleanConfig | undefined, >(config: TConfig): ParseBooleanAction; /** * Creates a parse boolean transformation action. * * @param config The parse boolean config. * @param message The error message. * * @returns A parse boolean action. * * @beta */ export function parseBoolean< TInput, const TConfig extends ParseBooleanConfig | undefined, const TMessage extends ErrorMessage> | undefined, >( config: TConfig, message: TMessage ): ParseBooleanAction; // @__NO_SIDE_EFFECTS__ export function parseBoolean( config?: ParseBooleanConfig, message?: ErrorMessage> ): ParseBooleanAction< unknown, ParseBooleanConfig | undefined, ErrorMessage> | undefined > { const normalize = (v: unknown) => typeof v === 'string' ? v.toLowerCase() : v; const truthyRaw = config?.truthy ?? TRUTHY; const falsyRaw = config?.falsy ?? FALSY; const truthy = config?.truthy ? config.truthy.map(normalize) : TRUTHY; const falsy = config?.falsy ? config.falsy.map(normalize) : FALSY; return { kind: 'transformation', type: 'parse_boolean', reference: parseBoolean, expects: _joinExpects([...truthyRaw, ...falsyRaw].map(_stringify), '|'), config, message, async: false, '~run'(dataset, config) { const input = normalize(dataset.value); if (truthy.includes(input)) { dataset.value = true; } else if (falsy.includes(input)) { dataset.value = false; } else { _addIssue(this, 'boolean', dataset, config); // @ts-expect-error dataset.typed = false; } return dataset as OutputDataset>; }, }; } ================================================ FILE: library/src/actions/parseJson/index.ts ================================================ export * from './parseJson.ts'; ================================================ FILE: library/src/actions/parseJson/parseJson.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { parseJson, type ParseJsonAction, type ParseJsonConfig, type ParseJsonIssue, } from './parseJson.ts'; describe('parseJson', () => { describe('should return action object', () => { const config: ParseJsonConfig = { reviver: (key, value) => value, }; test('with undefined config and undefined message', () => { type Action = ParseJsonAction; expectTypeOf(parseJson()).toEqualTypeOf(); expectTypeOf(parseJson(undefined)).toEqualTypeOf(); expectTypeOf(parseJson(undefined, undefined)).toEqualTypeOf(); }); test('with undefined config and string message', () => { expectTypeOf(parseJson(undefined, 'message')).toEqualTypeOf< ParseJsonAction >(); }); test('with undefined config and function message', () => { expectTypeOf(parseJson(undefined, () => 'message')).toEqualTypeOf< ParseJsonAction string> >(); }); test('with config and undefined message', () => { type Action = ParseJsonAction; expectTypeOf(parseJson(config)).toEqualTypeOf(); expectTypeOf(parseJson(config, undefined)).toEqualTypeOf(); }); test('with config and string message', () => { expectTypeOf(parseJson(config, 'message')).toEqualTypeOf< ParseJsonAction >(); }); test('with config and function message', () => { expectTypeOf(parseJson(config, () => 'message')).toEqualTypeOf< ParseJsonAction string> >(); }); }); describe('should infer correct types', () => { type Input = 'foo'; type Action = ParseJsonAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toBeUnknown(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/parseJson/parseJson.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { parseJson, type ParseJsonAction, type ParseJsonConfig, type ParseJsonIssue, } from './parseJson.ts'; describe('parseJson', () => { describe('should return action object', () => { const config: ParseJsonConfig = { reviver: (key, value) => value, }; const baseAction: Omit< ParseJsonAction, 'message' | 'config' > = { kind: 'transformation', type: 'parse_json', reference: parseJson, async: false, '~run': expect.any(Function), }; test('with undefined config and undefined message', () => { const action: ParseJsonAction = { ...baseAction, config: undefined, message: undefined, }; expect(parseJson()).toStrictEqual(action); expect(parseJson(undefined)).toStrictEqual(action); expect(parseJson(undefined, undefined)).toStrictEqual(action); }); test('with undefined config and string message', () => { expect(parseJson(undefined, 'message')).toStrictEqual({ ...baseAction, config: undefined, message: 'message', } satisfies ParseJsonAction); }); test('with undefined config and function message', () => { const message = () => 'message'; expect(parseJson(undefined, message)).toStrictEqual({ ...baseAction, config: undefined, message, } satisfies ParseJsonAction string>); }); test('with config and undefined message', () => { const action: ParseJsonAction = { ...baseAction, config, message: undefined, }; expect(parseJson(config)).toStrictEqual(action); expect(parseJson(config, undefined)).toStrictEqual(action); }); test('with config and string message', () => { expect(parseJson(config, 'message')).toStrictEqual({ ...baseAction, config, message: 'message', } satisfies ParseJsonAction); }); test('with config and function message', () => { const message = () => 'message'; expect(parseJson(config, message)).toStrictEqual({ ...baseAction, config, message, } satisfies ParseJsonAction string>); }); }); describe('should convert JSON string into JSON data', () => { const input = '{"foo":"bar"}'; test('without config', () => { expect( parseJson()['~run']({ typed: true, value: input }, {}) ).toStrictEqual({ typed: true, value: { foo: 'bar' }, }); }); test('with reviver', () => { expect( parseJson({ reviver: (key, value) => typeof value === 'string' ? value.toUpperCase() : value, })['~run']({ typed: true, value: input }, {}) ).toStrictEqual({ typed: true, value: { foo: 'BAR' }, }); }); }); describe('should return dataset with issues', () => { const action = parseJson(undefined, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'transformation', type: 'parse_json', expected: null, message: 'message', requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for normal text', () => { const input = 'foo'; expect(action['~run']({ typed: true, value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseIssue, input, received: `"Unexpected token 'o', "foo" is not valid JSON"`, } satisfies ParseJsonIssue, ], }); }); test('for invalid JSON string', () => { const input = '{"foo":20n}'; expect(action['~run']({ typed: true, value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseIssue, input, received: expect.toBeOneOf([ `"Expected ',' or '}' after property value in JSON at position 9"`, `"Expected ',' or '}' after property value in JSON at position 9 (line 1 column 10)"`, ]), } satisfies ParseJsonIssue, ], }); }); }); describe('should throw non-Error exceptions', () => { test('for non-Error thrown by reviver', () => { const action = parseJson({ reviver: () => { throw 'custom string error'; }, }); expect(() => action['~run']({ typed: true, value: '{}' }, {})).toThrow( 'custom string error' ); }); }); }); ================================================ FILE: library/src/actions/parseJson/parseJson.ts ================================================ import type { BaseIssue, BaseTransformation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Parse JSON config interface. * * @beta */ export interface ParseJsonConfig { /** * The JSON reviver function. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any reviver?: (this: any, key: string, value: any) => any; } /** * Parse JSON issue interface. * * @beta */ export interface ParseJsonIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'transformation'; /** * The issue type. */ readonly type: 'parse_json'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; } /** * Parse JSON action interface. * * @beta */ export interface ParseJsonAction< TInput extends string, TConfig extends ParseJsonConfig | undefined, TMessage extends ErrorMessage> | undefined, > extends BaseTransformation> { /** * The action type. */ readonly type: 'parse_json'; /** * The action reference. */ readonly reference: typeof parseJson; /** * The action config. */ readonly config: TConfig; /** * The error message. */ readonly message: TMessage; } /** * Creates a parse JSON transformation action. * * @returns A parse JSON action. * * @beta */ export function parseJson(): ParseJsonAction< TInput, undefined, undefined >; /** * Creates a parse JSON transformation action. * * @param config The action config. * * @returns A parse JSON action. * * @beta */ export function parseJson< TInput extends string, const TConfig extends ParseJsonConfig | undefined, >(config: TConfig): ParseJsonAction; /** * Creates a parse JSON transformation action. * * @param config The action config. * @param message The error message. * * @returns A parse JSON action. * * @beta */ export function parseJson< TInput extends string, const TConfig extends ParseJsonConfig | undefined, const TMessage extends ErrorMessage> | undefined, >( config: TConfig, message: TMessage ): ParseJsonAction; // @__NO_SIDE_EFFECTS__ export function parseJson( config?: ParseJsonConfig, message?: ErrorMessage> ): ParseJsonAction< string, ParseJsonConfig | undefined, ErrorMessage> | undefined > { return { kind: 'transformation', type: 'parse_json', reference: parseJson, config, message, async: false, '~run'(dataset, config) { try { dataset.value = JSON.parse(dataset.value, this.config?.reviver); } catch (error) { if (error instanceof Error) { _addIssue(this, 'JSON', dataset, config, { received: `"${error.message}"`, }); // @ts-expect-error dataset.typed = false; } else { throw error; } } return dataset; }, }; } ================================================ FILE: library/src/actions/partialCheck/index.ts ================================================ export * from './partialCheck.ts'; export * from './partialCheckAsync.ts'; export type { PartialCheckIssue } from './types.ts'; ================================================ FILE: library/src/actions/partialCheck/partialCheck.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { partialCheck, type PartialCheckAction } from './partialCheck.ts'; import type { DeepPickN, PartialCheckIssue } from './types.ts'; describe('partialCheck', () => { // eslint-disable-next-line @typescript-eslint/consistent-type-definitions type Input = { nested: { key1: number; key2: string; key3: boolean } }; const paths = [['nested', 'key2']] as const; type PathList = typeof paths; type Selection = DeepPickN; const requirement = (input: Selection) => input.nested.key2.includes('foo'); describe('should return action object', () => { test('with undefined message', () => { type Action = PartialCheckAction; expectTypeOf( partialCheck(paths, requirement) ).toEqualTypeOf(); expectTypeOf( partialCheck( paths, requirement, undefined ) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( partialCheck( paths, requirement, 'message' ) ).toEqualTypeOf< PartialCheckAction >(); }); test('with function message', () => { expectTypeOf( partialCheck string>( paths, requirement, () => 'message' ) ).toEqualTypeOf< PartialCheckAction string> >(); }); }); describe('should infer correct types', () => { type Action = PartialCheckAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< PartialCheckIssue >(); }); }); }); ================================================ FILE: library/src/actions/partialCheck/partialCheck.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { NumberIssue, ObjectIssue, StringIssue, } from '../../schemas/index.ts'; import type { FailureDataset, PartialDataset, SuccessDataset, } from '../../types/index.ts'; import type { MinLengthIssue } from '../minLength/index.ts'; import { partialCheck, type PartialCheckAction } from './partialCheck.ts'; import type { DeepPickN, PartialCheckIssue } from './types.ts'; describe('partialCheck', () => { describe('should return action object', () => { // eslint-disable-next-line @typescript-eslint/consistent-type-definitions type Input = { nested: { key1: number; key2: string; key3: boolean } }; const paths = [['nested', 'key2']] as const; type PathList = typeof paths; type Selection = DeepPickN; const requirement = (input: Selection) => input.nested.key2.includes('foo'); const baseAction: Omit< PartialCheckAction, 'message' > = { kind: 'validation', type: 'partial_check', reference: partialCheck, expects: null, paths, requirement, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: PartialCheckAction = { ...baseAction, message: undefined, }; expect( partialCheck(paths, requirement) ).toStrictEqual(action); expect( partialCheck( paths, requirement, undefined ) ).toStrictEqual(action); }); test('with string message', () => { const message = 'message'; expect( partialCheck( paths, requirement, message ) ).toStrictEqual({ ...baseAction, message, } satisfies PartialCheckAction); }); test('with function message', () => { const message = () => 'message'; expect( partialCheck( paths, requirement, message ) ).toStrictEqual({ ...baseAction, message, } satisfies PartialCheckAction< Input, PathList, Selection, typeof message >); }); }); // eslint-disable-next-line @typescript-eslint/consistent-type-definitions type Input = { nested: { key: string }; tuple: [number, { key: string }, number]; other: string; }; type PathList = [['nested', 'key'], ['tuple', 1, 'key']]; type Selection = DeepPickN; const requirement = (input: Selection) => input.nested.key === input.tuple[1].key; const action = partialCheck( [ ['nested', 'key'], ['tuple', 1, 'key'], ], requirement, 'message' ); const baseInfo = { message: 'message', requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; describe('should return same dataset', () => { test('if root is untyped', () => { const dataset: FailureDataset = { typed: false, value: null, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: null, expected: 'Object', received: 'null', path: undefined, }, ], }; expect(action['~run'](dataset, {})).toStrictEqual(dataset); }); test('if part of path is untyped', () => { const input = { nested: null, tuple: [123, { key: 'foo' }, 456], other: 'bar', }; const dataset: FailureDataset = { typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: null, expected: 'Object', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, ], }, ], }; expect(action['~run'](dataset, {})).toStrictEqual(dataset); }); test('if entire path is untyped', () => { const input = { nested: { key: null }, tuple: [123, { key: 'foo' }, 456], other: 'bar', }; const dataset: FailureDataset = { typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'value', input: input.nested, key: 'key', value: input.nested.key, }, ], }, ], }; expect(action['~run'](dataset, {})).toStrictEqual(dataset); }); test('if validation returns true', () => { const dataset: SuccessDataset = { typed: true, value: { nested: { key: 'foo' }, tuple: [123, { key: 'foo' }, 456], other: 'bar', }, }; expect(action['~run'](dataset, {})).toStrictEqual(dataset); }); }); describe('should add issue to dataset', () => { test('if there are no previous issues', () => { const input: Input = { nested: { key: 'foo' }, tuple: [123, { key: 'baz' }, 456], other: 'bar', }; const dataset: SuccessDataset = { typed: true, value: input, }; expect(action['~run'](dataset, {})).toStrictEqual({ ...dataset, issues: [ { ...baseInfo, kind: 'validation', type: 'partial_check', input, expected: null, received: 'Object', requirement, }, ], } satisfies PartialDataset>); }); test('if there are previous issues but the dataset is typed', () => { const input: Input = { nested: { key: 'foo' }, tuple: [123, { key: 'baz' }, 456], other: 'bar', }; const firstIssue: MinLengthIssue = { ...baseInfo, kind: 'validation', type: 'min_length', input: 'foo', expected: '>=5', received: '3', requirement: 5, path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'value', input: input.nested, key: 'key', value: input.nested.key, }, ], }; const dataset: PartialDataset> = { typed: true, value: input, issues: [firstIssue], }; expect(action['~run'](dataset, {})).toStrictEqual({ ...dataset, issues: [ firstIssue, { ...baseInfo, kind: 'validation', type: 'partial_check', input: input, expected: null, received: 'Object', requirement, }, ], } satisfies PartialDataset< Input, MinLengthIssue | PartialCheckIssue >); }); test('if there are previous issues but only with unrelated paths', () => { const input: { nested: { key: string }; tuple: [number, { key: string }, null]; other: null; } = { nested: { key: 'foo' }, tuple: [123, { key: 'baz' }, null], other: null, }; const firstIssue: NumberIssue = { ...baseInfo, kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'tuple', value: input.tuple, }, { type: 'array', origin: 'value', input: input.tuple, key: 2, value: input.tuple[2], }, ], }; const secondIssue: StringIssue = { ...baseInfo, kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'other', value: input.other, }, ], }; const dataset: FailureDataset = { typed: false, value: input, issues: [firstIssue, secondIssue], }; expect(action['~run'](dataset, {})).toStrictEqual({ ...dataset, issues: [ firstIssue, secondIssue, { ...baseInfo, kind: 'validation', type: 'partial_check', input: input, expected: null, received: 'Object', requirement, }, ], } satisfies FailureDataset< NumberIssue | StringIssue | PartialCheckIssue >); }); }); }); ================================================ FILE: library/src/actions/partialCheck/partialCheck.ts ================================================ import type { BaseValidation, ErrorMessage } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { DeepPickN, PartialCheckIssue, PartialInput, Paths, RequiredPaths, ValidPaths, } from './types.ts'; import { _isPartiallyTyped } from './utils/index.ts'; /** * Partial check action interface. */ export interface PartialCheckAction< TInput extends PartialInput, TPaths extends Paths, TSelection extends DeepPickN, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'partial_check'; /** * The action reference. */ readonly reference: typeof partialCheck; /** * The expected property. */ readonly expects: null; /** * The selected paths. */ readonly paths: TPaths; /** * The validation function. */ readonly requirement: (input: TSelection) => boolean; /** * The error message. */ readonly message: TMessage; } /** * Creates a partial check validation action. * * @param paths The selected paths. * @param requirement The validation function. * * @returns A partial check action. */ export function partialCheck< TInput extends PartialInput, const TPaths extends RequiredPaths, const TSelection extends DeepPickN, >( paths: ValidPaths, requirement: (input: TSelection) => boolean ): PartialCheckAction; /** * Creates a partial check validation action. * * @param paths The selected paths. * @param requirement The validation function. * @param message The error message. * * @returns A partial check action. */ export function partialCheck< TInput extends PartialInput, const TPaths extends RequiredPaths, const TSelection extends DeepPickN, const TMessage extends | ErrorMessage> | undefined, >( paths: ValidPaths, requirement: (input: TSelection) => boolean, message: TMessage ): PartialCheckAction; // @__NO_SIDE_EFFECTS__ export function partialCheck( paths: Paths, requirement: (input: PartialInput) => boolean, message?: ErrorMessage> ): PartialCheckAction< PartialInput, Paths, PartialInput, ErrorMessage> | undefined > { return { kind: 'validation', type: 'partial_check', reference: partialCheck, async: false, expects: null, paths, requirement, message, '~run'(dataset, config) { if ( (dataset.typed || _isPartiallyTyped(dataset, paths)) && // @ts-expect-error !this.requirement(dataset.value) ) { _addIssue(this, 'input', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/partialCheck/partialCheckAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { type PartialCheckActionAsync, partialCheckAsync, } from './partialCheckAsync.ts'; import type { DeepPickN, PartialCheckIssue } from './types.ts'; describe('partialCheckAsync', () => { // eslint-disable-next-line @typescript-eslint/consistent-type-definitions type Input = { nested: { key1: number; key2: string; key3: boolean } }; const paths = [['nested', 'key2']] as const; type PathList = typeof paths; type Selection = DeepPickN; const requirement = async (input: Selection) => input.nested.key2.includes('foo'); describe('should return action object', () => { test('with undefined message', () => { type Action = PartialCheckActionAsync< Input, PathList, Selection, undefined >; expectTypeOf( partialCheckAsync(paths, requirement) ).toEqualTypeOf(); expectTypeOf( partialCheckAsync( paths, requirement, undefined ) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( partialCheckAsync( paths, requirement, 'message' ) ).toEqualTypeOf< PartialCheckActionAsync >(); }); test('with function message', () => { expectTypeOf( partialCheckAsync string>( paths, requirement, () => 'message' ) ).toEqualTypeOf< PartialCheckActionAsync string> >(); }); }); describe('should infer correct types', () => { type Action = PartialCheckActionAsync< Input, PathList, Selection, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< PartialCheckIssue >(); }); }); }); ================================================ FILE: library/src/actions/partialCheck/partialCheckAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { NumberIssue, ObjectIssue, StringIssue, } from '../../schemas/index.ts'; import type { FailureDataset, PartialDataset, SuccessDataset, } from '../../types/index.ts'; import type { MinLengthIssue } from '../minLength/index.ts'; import { type PartialCheckActionAsync, partialCheckAsync, } from './partialCheckAsync.ts'; import type { DeepPickN, PartialCheckIssue } from './types.ts'; describe('partialCheckAsync', () => { describe('should return action object', () => { // eslint-disable-next-line @typescript-eslint/consistent-type-definitions type Input = { nested: { key1: number; key2: string; key3: boolean } }; const paths = [['nested', 'key2']] as const; type PathList = typeof paths; type Selection = DeepPickN; const requirement = async (input: Selection) => input.nested.key2.includes('foo'); const baseAction: Omit< PartialCheckActionAsync, 'message' > = { kind: 'validation', type: 'partial_check', reference: partialCheckAsync, expects: null, paths, requirement, async: true, '~run': expect.any(Function), }; test('with undefined message', () => { const action: PartialCheckActionAsync< Input, PathList, Selection, undefined > = { ...baseAction, message: undefined, }; expect( partialCheckAsync(paths, requirement) ).toStrictEqual(action); expect( partialCheckAsync( paths, requirement, undefined ) ).toStrictEqual(action); }); test('with string message', () => { const message = 'message'; expect( partialCheckAsync( paths, requirement, message ) ).toStrictEqual({ ...baseAction, message, } satisfies PartialCheckActionAsync< Input, PathList, Selection, 'message' >); }); test('with function message', () => { const message = () => 'message'; expect( partialCheckAsync( paths, requirement, message ) ).toStrictEqual({ ...baseAction, message, } satisfies PartialCheckActionAsync< Input, PathList, Selection, typeof message >); }); }); // eslint-disable-next-line @typescript-eslint/consistent-type-definitions type Input = { nested: { key: string }; tuple: [number, { key: string }, number]; other: string; }; type PathList = [['nested', 'key'], ['tuple', 1, 'key']]; type Selection = DeepPickN; const requirement = async (input: Selection) => input.nested.key === input.tuple[1].key; const action = partialCheckAsync( [ ['nested', 'key'], ['tuple', 1, 'key'], ], requirement, 'message' ); const baseInfo = { message: 'message', requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; describe('should return same dataset', () => { test('if root is untyped', async () => { const dataset: FailureDataset = { typed: false, value: null, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: null, expected: 'Object', received: 'null', path: undefined, }, ], }; expect(await action['~run'](dataset, {})).toStrictEqual(dataset); }); test('if part of path is untyped', async () => { const input = { nested: null, tuple: [123, { key: 'foo' }, 456], other: 'bar', }; const dataset: FailureDataset = { typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: null, expected: 'Object', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, ], }, ], }; expect(await action['~run'](dataset, {})).toStrictEqual(dataset); }); test('if entire path is untyped', async () => { const input = { nested: { key: null }, tuple: [123, { key: 'foo' }, 456], other: 'bar', }; const dataset: FailureDataset = { typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'value', input: input.nested, key: 'key', value: input.nested.key, }, ], }, ], }; expect(await action['~run'](dataset, {})).toStrictEqual(dataset); }); test('if validation returns true', async () => { const dataset: SuccessDataset = { typed: true, value: { nested: { key: 'foo' }, tuple: [123, { key: 'foo' }, 456], other: 'bar', }, }; expect(await action['~run'](dataset, {})).toStrictEqual(dataset); }); }); describe('should add issue to dataset', () => { test('if there are no previous issues', async () => { const input: Input = { nested: { key: 'foo' }, tuple: [123, { key: 'baz' }, 456], other: 'bar', }; const dataset: SuccessDataset = { typed: true, value: input, }; expect(await action['~run'](dataset, {})).toStrictEqual({ ...dataset, issues: [ { ...baseInfo, kind: 'validation', type: 'partial_check', input, expected: null, received: 'Object', requirement, }, ], } satisfies PartialDataset>); }); test('if there are previous issues but the dataset is typed', async () => { const input: Input = { nested: { key: 'foo' }, tuple: [123, { key: 'baz' }, 456], other: 'bar', }; const firstIssue: MinLengthIssue = { ...baseInfo, kind: 'validation', type: 'min_length', input: 'foo', expected: '>=5', received: '3', requirement: 5, path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'value', input: input.nested, key: 'key', value: input.nested.key, }, ], }; const dataset: PartialDataset> = { typed: true, value: input, issues: [firstIssue], }; expect(await action['~run'](dataset, {})).toStrictEqual({ ...dataset, issues: [ firstIssue, { ...baseInfo, kind: 'validation', type: 'partial_check', input: input, expected: null, received: 'Object', requirement, }, ], } satisfies PartialDataset< Input, MinLengthIssue | PartialCheckIssue >); }); test('if there are previous issues but only with unrelated paths', async () => { const input: { nested: { key: string }; tuple: [number, { key: string }, null]; other: null; } = { nested: { key: 'foo' }, tuple: [123, { key: 'baz' }, null], other: null, }; const firstIssue: NumberIssue = { ...baseInfo, kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'tuple', value: input.tuple, }, { type: 'array', origin: 'value', input: input.tuple, key: 2, value: input.tuple[2], }, ], }; const secondIssue: StringIssue = { ...baseInfo, kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'other', value: input.other, }, ], }; const dataset: FailureDataset = { typed: false, value: input, issues: [firstIssue, secondIssue], }; expect(await action['~run'](dataset, {})).toStrictEqual({ ...dataset, issues: [ firstIssue, secondIssue, { ...baseInfo, kind: 'validation', type: 'partial_check', input: input, expected: null, received: 'Object', requirement, }, ], } satisfies FailureDataset< NumberIssue | StringIssue | PartialCheckIssue >); }); }); }); ================================================ FILE: library/src/actions/partialCheck/partialCheckAsync.ts ================================================ import type { BaseValidationAsync, ErrorMessage, MaybePromise, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { DeepPickN, PartialCheckIssue, PartialInput, Paths, RequiredPaths, ValidPaths, } from './types.ts'; import { _isPartiallyTyped } from './utils/index.ts'; /** * Partial check action async interface. */ export interface PartialCheckActionAsync< TInput extends PartialInput, TPaths extends Paths, TSelection extends DeepPickN, TMessage extends ErrorMessage> | undefined, > extends BaseValidationAsync> { /** * The action type. */ readonly type: 'partial_check'; /** * The action reference. */ readonly reference: typeof partialCheckAsync; /** * The expected property. */ readonly expects: null; /** * The selected paths. */ readonly paths: TPaths; /** * The validation function. */ readonly requirement: (input: TSelection) => MaybePromise; /** * The error message. */ readonly message: TMessage; } /** * Creates a partial check validation action. * * @param paths The selected paths. * @param requirement The validation function. * * @returns A partial check action. */ export function partialCheckAsync< TInput extends PartialInput, const TPaths extends RequiredPaths, const TSelection extends DeepPickN, >( paths: ValidPaths, requirement: (input: TSelection) => MaybePromise ): PartialCheckActionAsync; /** * Creates a partial check validation action. * * @param paths The selected paths. * @param requirement The validation function. * @param message The error message. * * @returns A partial check action. */ export function partialCheckAsync< TInput extends PartialInput, const TPaths extends RequiredPaths, const TSelection extends DeepPickN, const TMessage extends | ErrorMessage> | undefined, >( paths: ValidPaths, requirement: (input: TSelection) => MaybePromise, message: TMessage ): PartialCheckActionAsync; // @__NO_SIDE_EFFECTS__ export function partialCheckAsync( paths: Paths, requirement: (input: PartialInput) => MaybePromise, message?: ErrorMessage> ): PartialCheckActionAsync< PartialInput, Paths, PartialInput, ErrorMessage> | undefined > { return { kind: 'validation', type: 'partial_check', reference: partialCheckAsync, async: true, expects: null, paths, requirement, message, async '~run'(dataset, config) { if ( (dataset.typed || _isPartiallyTyped(dataset, paths)) && // @ts-expect-error !(await this.requirement(dataset.value)) ) { _addIssue(this, 'input', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/partialCheck/types.ts ================================================ import type { BaseIssue, IsAny, IsNever, MaybePromise, } from '../../types/index.ts'; /** * Partial input type. */ export type PartialInput = Record | ArrayLike; /** * Partial check issue interface. */ export interface PartialCheckIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'partial_check'; /** * The expected input. */ readonly expected: null; /** * The validation function. */ readonly requirement: (input: TInput) => MaybePromise; } /** * Extracts the exact keys of a tuple, array or object. */ type KeyOf = IsAny extends true ? never : TValue extends readonly unknown[] ? number extends TValue['length'] ? '$' // For arrays we use '$' as a wildcard : { [TKey in keyof TValue]: TKey extends `${infer TIndex extends number}` ? TIndex : never; }[number] : TValue extends Record ? keyof TValue & (string | number) : never; /** * Path type. */ type Path = readonly (string | number)[]; /** * Required path type. */ type RequiredPath = readonly [string | number, ...Path]; /** * Paths type. */ export type Paths = readonly RequiredPath[]; /** * Required paths type. */ export type RequiredPaths = readonly [RequiredPath, ...RequiredPath[]]; /** * Lazily evaluate only the first valid path segment based on the given value. */ type LazyPath< TValue, TPathToCheck extends Path, TValidPath extends Path = readonly [], > = // If path to check is empty, return last valid path TPathToCheck extends readonly [] ? TValidPath : // If first key of path to check is valid, continue with next key TPathToCheck extends readonly [ infer TFirstKey extends KeyOf, ...infer TPathRest extends Path, ] ? LazyPath< TFirstKey extends keyof TValue ? TValue[TFirstKey] : TFirstKey extends '$' ? TValue extends readonly unknown[] ? TValue[number] : never : never, TPathRest, readonly [...TValidPath, TFirstKey] > : // If current value has valid keys, return them IsNever> extends false ? readonly [...TValidPath, KeyOf] : // Otherwise, return only last valid path TValidPath; /** * Returns the path if valid, otherwise the first possible valid path based on * the given value. */ type ValidPath = TPath extends LazyPath ? TPath : LazyPath; /** * Returns a valid path for any given path based on the given value. */ export type ValidPaths = { [TKey in keyof TPaths]: ValidPath; }; /** * Deeply picks specific keys. * * Hint: If this type is ever exported and accessible from the outside, it must * be wrapped in `UnionToIntersect` to avoid invalid results. */ type DeepPick = TPath extends readonly [ infer TFirstKey extends string | number, ...infer TPathRest extends Path, ] ? TValue extends readonly unknown[] ? number extends TValue['length'] ? TPathRest extends readonly [] ? TValue : DeepPick[] : { [TKey in keyof TValue]: TKey extends `${TFirstKey}` ? TPathRest extends readonly [] ? TValue[TKey] : DeepPick : unknown; } : { [TKey in keyof TValue as TKey extends TFirstKey ? TKey : never]: TPathRest extends readonly [] ? TValue[TKey] : DeepPick; } : never; /** * Deeply merges two types. */ type DeepMerge = TValue1 extends readonly unknown[] ? TValue2 extends readonly unknown[] ? number extends TValue1['length'] | TValue2['length'] ? DeepMerge[] : { [TKey in keyof TValue1]: TKey extends keyof TValue2 ? unknown extends TValue1[TKey] ? TValue2[TKey] : TValue1[TKey] : never; } : never : TValue1 extends Record ? TValue2 extends Record ? { [TKey in keyof (TValue1 & TValue2)]: TKey extends keyof TValue1 ? TKey extends keyof TValue2 ? DeepMerge : TValue1[TKey] : TKey extends keyof TValue2 ? TValue2[TKey] : never; } : never : TValue1 & TValue2; /** * Deeply picks N specific keys. */ export type DeepPickN = TPaths extends readonly [ infer TFirstPath extends Path, ...infer TRestPaths extends Paths, ] ? TRestPaths extends readonly [] ? DeepPick : DeepMerge, DeepPickN> : TInput; ================================================ FILE: library/src/actions/partialCheck/utils/_isPartiallyTyped/_isPartiallyTyped.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { NumberIssue, ObjectIssue, StringIssue, } from '../../../../schemas/index.ts'; import type { FailureDataset, SuccessDataset, } from '../../../../types/index.ts'; import { _isPartiallyTyped } from './_isPartiallyTyped.ts'; describe('_isPartiallyTyped', () => { // eslint-disable-next-line @typescript-eslint/consistent-type-definitions type Input = { nested: { key1: string; key2: string }; tuple: [number, { key1: string; key2: string }, number]; array: { key1: string; key2: string }[]; other: string; }; const paths = [ ['nested', 'key2'], ['tuple', 1, 'key2'], ['array', '$', 'key2'], ] as const; const baseInfo = { message: 'message', requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; describe('should return false', () => { test('if issue has no path', () => { const dataset: FailureDataset = { typed: false, value: null, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: null, expected: 'Object', received: 'null', path: undefined, }, ], }; expect(_isPartiallyTyped(dataset, paths)).toBe(false); }); test('if part of path matches path of issue', () => { const input = { nested: null, tuple: [123, { key1: 'foo', key2: 'bar' }, 456], array: [{ key1: 'foo', key2: 'bar' }], other: 'foo', }; const dataset: FailureDataset = { typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: null, expected: 'Object', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, ], }, ], }; expect(_isPartiallyTyped(dataset, paths)).toBe(false); }); test('if entire path matches path of issue', () => { const input = { nested: { key1: 'foo', key2: null }, tuple: [123, { key1: 'foo', key2: 'bar' }, 456], array: [{ key1: 'foo', key2: 'bar' }], other: 'foo', }; const dataset: FailureDataset = { typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'value', input: input.nested, key: 'key2', value: input.nested.key2, }, ], }, ], }; expect(_isPartiallyTyped(dataset, paths)).toBe(false); }); test('if array wildcard of path matches path of issue', () => { const input = { nested: { key1: 'foo', key2: 'bar' }, tuple: [123, { key1: 'foo', key2: 'bar' }, 456], array: [{ key1: 'foo', key2: 'bar' }, null], other: 'foo', }; const dataset: FailureDataset = { typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: null, expected: 'Object', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'array', value: input.array, }, { type: 'array', origin: 'value', input: input.array, key: 1, value: input.array[1], }, ], }, ], }; expect(_isPartiallyTyped(dataset, paths)).toBe(false); }); }); describe('should return true', () => { test('if there are no issues', () => { const input: Input = { nested: { key1: 'foo', key2: 'bar' }, tuple: [123, { key1: 'foo', key2: 'bar' }, 456], array: [{ key1: 'foo', key2: 'bar' }], other: 'foo', }; const dataset: SuccessDataset = { typed: true, value: input, }; expect(_isPartiallyTyped(dataset, paths)).toBe(true); }); test('if only unselected paths are untyped', () => { const input = { nested: { key: 'foo' }, tuple: [123, { key: 'baz' }, null], array: [{ key: 'foo' }, { key: 'bar' }], other: null, }; const dataset: FailureDataset = { typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'tuple', value: input.tuple, }, { type: 'array', origin: 'value', input: input.tuple, key: 2, value: input.tuple[2], }, ], }, { ...baseInfo, kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'other', value: input.other, }, ], }, ], }; expect(_isPartiallyTyped(dataset, paths)).toBe(true); }); }); }); ================================================ FILE: library/src/actions/partialCheck/utils/_isPartiallyTyped/_isPartiallyTyped.ts ================================================ import type { BaseIssue, OutputDataset } from '../../../../types/index.ts'; import type { Paths } from '../../types.ts'; /** * Checks if a dataset is partially typed. * * @param dataset The dataset to check. * @param paths The paths to check. * * @returns Whether it is partially typed. * * @internal */ // @__NO_SIDE_EFFECTS__ export function _isPartiallyTyped( dataset: OutputDataset>, paths: Paths ): boolean { // If issues exist, check if a specified path matches path of a schema issue if (dataset.issues) { for (const path of paths) { for (const issue of dataset.issues) { // Hint: We also mark the data as untyped if there are validation // issues, since the data could potentially be untyped if a pipeline // contains a transformation action. // Create typed variable let typed = false; // Calculate bound of match check const bound = Math.min(path.length, issue.path?.length ?? 0); // Mark data as typed if any path items of same index do not match for (let index = 0; index < bound; index++) { if ( // @ts-expect-error path[index] !== issue.path[index].key && // @ts-expect-error (path[index] !== '$' || issue.path[index].type !== 'array') ) { typed = true; break; } } // Return false if untyped if (!typed) { return false; } } } } // Return true if typed return true; } ================================================ FILE: library/src/actions/partialCheck/utils/_isPartiallyTyped/index.ts ================================================ export * from './_isPartiallyTyped.ts'; ================================================ FILE: library/src/actions/partialCheck/utils/index.ts ================================================ export * from './_isPartiallyTyped/index.ts'; ================================================ FILE: library/src/actions/rawCheck/index.ts ================================================ export * from './rawCheck.ts'; export * from './rawCheckAsync.ts'; export * from './types.ts'; ================================================ FILE: library/src/actions/rawCheck/rawCheck.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { rawCheck, type RawCheckAction } from './rawCheck.ts'; import type { RawCheckIssue } from './types.ts'; describe('rawCheck', () => { test('should return action object', () => { expectTypeOf( rawCheck( // eslint-disable-next-line @typescript-eslint/no-empty-function () => {} ) ).toEqualTypeOf>(); }); describe('should infer correct types', () => { type Input = ['foo', 123, true]; type Action = RawCheckAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/rawCheck/rawCheck.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { rawCheck, type RawCheckAction } from './rawCheck.ts'; import type { RawCheckIssue } from './types.ts'; describe('rawCheck', () => { const action = rawCheck(({ dataset, addIssue }) => { if (dataset.typed && dataset.value <= 0) { addIssue({ message: 'message' }); } }); test('should return action object', () => { expect(action).toStrictEqual({ kind: 'validation', type: 'raw_check', reference: rawCheck, expects: null, async: false, '~run': expect.any(Function), } satisfies RawCheckAction); }); describe('should return dataset without issues', () => { test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid inputs', () => { expectNoActionIssue(action, [1, 12345, Infinity]); }); }); describe('should return dataset with issues', () => { const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'raw_check', expected: null, message: 'message', }; test('for invalid inputs', () => { expectActionIssue(action, baseIssue, [0, -1, -12345, -Infinity]); }); }); }); ================================================ FILE: library/src/actions/rawCheck/rawCheck.ts ================================================ import type { BaseValidation } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { RawCheckContext, RawCheckIssue } from './types.ts'; /** * Raw check action interface. */ export interface RawCheckAction extends BaseValidation> { /** * The action type. */ readonly type: 'raw_check'; /** * The action reference. */ readonly reference: typeof rawCheck; /** * The expected property. */ readonly expects: null; } /** * Creates a raw check validation action. * * @param action The validation action. * * @returns A raw check action. */ // @__NO_SIDE_EFFECTS__ export function rawCheck( action: (context: RawCheckContext) => void ): RawCheckAction { return { kind: 'validation', type: 'raw_check', reference: rawCheck, async: false, expects: null, '~run'(dataset, config) { action({ dataset, config, addIssue: (info) => _addIssue(this, info?.label ?? 'input', dataset, config, info), }); return dataset; }, }; } ================================================ FILE: library/src/actions/rawCheck/rawCheckAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { type RawCheckActionAsync, rawCheckAsync } from './rawCheckAsync.ts'; import type { RawCheckIssue } from './types.ts'; describe('rawCheckAsync', () => { test('should return action object', () => { expectTypeOf( rawCheckAsync( // eslint-disable-next-line @typescript-eslint/no-empty-function async () => {} ) ).toEqualTypeOf>(); }); describe('should infer correct types', () => { type Input = ['foo', 123, true]; type Action = RawCheckActionAsync; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/rawCheck/rawCheckAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssueAsync, expectNoActionIssueAsync, } from '../../vitest/index.ts'; import { type RawCheckActionAsync, rawCheckAsync } from './rawCheckAsync.ts'; import type { RawCheckIssue } from './types.ts'; describe('rawCheckAsync', () => { const action = rawCheckAsync(async ({ dataset, addIssue }) => { if (dataset.typed && dataset.value <= 0) { addIssue({ message: 'message' }); } }); test('should return action object', () => { expect(action).toStrictEqual({ kind: 'validation', type: 'raw_check', reference: rawCheckAsync, expects: null, async: true, '~run': expect.any(Function), } satisfies RawCheckActionAsync); }); describe('should return dataset without issues', () => { test('for untyped inputs', async () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( await action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid inputs', async () => { await expectNoActionIssueAsync(action, [1, 12345, Infinity]); }); }); describe('should return dataset with issues', () => { const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'raw_check', expected: null, message: 'message', }; test('for invalid inputs', async () => { await expectActionIssueAsync(action, baseIssue, [ 0, -1, -12345, -Infinity, ]); }); }); }); ================================================ FILE: library/src/actions/rawCheck/rawCheckAsync.ts ================================================ import type { BaseValidationAsync, MaybePromise } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { RawCheckContext, RawCheckIssue } from './types.ts'; /** * Raw check action async interface. */ export interface RawCheckActionAsync extends BaseValidationAsync> { /** * The action type. */ readonly type: 'raw_check'; /** * The action reference. */ readonly reference: typeof rawCheckAsync; /** * The expected property. */ readonly expects: null; } /** * Creates a raw check validation action. * * @param action The validation action. * * @returns A raw check action. */ // @__NO_SIDE_EFFECTS__ export function rawCheckAsync( action: (context: RawCheckContext) => MaybePromise ): RawCheckActionAsync { return { kind: 'validation', type: 'raw_check', reference: rawCheckAsync, async: true, expects: null, async '~run'(dataset, config) { await action({ dataset, config, addIssue: (info) => _addIssue(this, info?.label ?? 'input', dataset, config, info), }); return dataset; }, }; } ================================================ FILE: library/src/actions/rawCheck/types.ts ================================================ import type { BaseIssue, Config, ErrorMessage, IssuePathItem, OutputDataset, } from '../../types/index.ts'; /** * Raw check issue interface. */ export interface RawCheckIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'raw_check'; } /** * Raw check issue info interface. */ export interface RawCheckIssueInfo { label?: string | undefined; input?: unknown | undefined; expected?: string | undefined; received?: string | undefined; message?: ErrorMessage> | undefined; path?: [IssuePathItem, ...IssuePathItem[]] | undefined; } /** * Raw check add issue type. */ export type RawCheckAddIssue = ( info?: RawCheckIssueInfo ) => void; /** * Raw check context interface. */ export interface RawCheckContext { readonly dataset: OutputDataset>; readonly config: Config>; readonly addIssue: RawCheckAddIssue; } ================================================ FILE: library/src/actions/rawTransform/index.ts ================================================ export * from './rawTransform.ts'; export * from './rawTransformAsync.ts'; export * from './types.ts'; ================================================ FILE: library/src/actions/rawTransform/rawTransform.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { rawTransform, type RawTransformAction } from './rawTransform.ts'; import type { RawTransformIssue } from './types.ts'; describe('rawTransform', () => { test('should return action object', () => { expectTypeOf( rawTransform(({ dataset }) => dataset.value.length) ).toEqualTypeOf>(); }); describe('should infer correct types', () => { type Action = RawTransformAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< RawTransformIssue >(); }); }); }); ================================================ FILE: library/src/actions/rawTransform/rawTransform.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { rawTransform, type RawTransformAction } from './rawTransform.ts'; describe('rawTransform', () => { const action = rawTransform( ({ dataset, addIssue, NEVER }) => { const length = dataset.value.length; if (length < 3) { addIssue({ message: 'message' }); return NEVER; } return length; } ); test('should return action object', () => { expect(action).toStrictEqual({ kind: 'transformation', type: 'raw_transform', reference: rawTransform, async: false, '~run': expect.any(Function), } satisfies RawTransformAction); }); describe('should return dataset without issues', () => { test('for valid inputs', () => { expect(action['~run']({ typed: true, value: 'foo' }, {})).toStrictEqual({ typed: true, value: 3, }); expect( action['~run']({ typed: true, value: '123456789' }, {}) ).toStrictEqual({ typed: true, value: 9, }); }); }); describe('should return dataset with issues', () => { test('for invalid inputs', () => { expect(action['~run']({ typed: true, value: 'fo' }, {})).toStrictEqual({ typed: false, value: 'fo', issues: [ { kind: 'transformation', type: 'raw_transform', expected: null, message: 'message', input: 'fo', received: '"fo"', requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }, ], }); }); }); }); ================================================ FILE: library/src/actions/rawTransform/rawTransform.ts ================================================ import type { BaseIssue, BaseTransformation, OutputDataset, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { RawTransformContext, RawTransformIssue } from './types.ts'; /** * Raw transform action interface. */ export interface RawTransformAction extends BaseTransformation> { /** * The action type. */ readonly type: 'raw_transform'; /** * The action reference. */ readonly reference: typeof rawTransform; } /** * Creates a raw transformation action. * * @param action The transformation action. * * @returns A raw transform action. */ // @__NO_SIDE_EFFECTS__ export function rawTransform( action: (context: RawTransformContext) => TOutput ): RawTransformAction { return { kind: 'transformation', type: 'raw_transform', reference: rawTransform, async: false, '~run'(dataset, config) { // Execute action and get its output const output = action({ dataset, config, addIssue: (info) => _addIssue(this, info?.label ?? 'input', dataset, config, info), NEVER: null as never, }); // Update dataset depending on issues if (dataset.issues) { // @ts-expect-error dataset.typed = false; } else { // @ts-expect-error dataset.value = output; } // Return output dataset // @ts-expect-error return dataset as OutputDataset< TOutput, BaseIssue | RawTransformIssue >; }, }; } ================================================ FILE: library/src/actions/rawTransform/rawTransformAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { type RawTransformActionAsync, rawTransformAsync, } from './rawTransformAsync.ts'; import type { RawTransformIssue } from './types.ts'; describe('rawTransformAsync', () => { test('should return action object', () => { expectTypeOf( rawTransformAsync( async ({ dataset }) => dataset.value.length ) ).toEqualTypeOf>(); }); describe('should infer correct types', () => { type Action = RawTransformActionAsync; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< RawTransformIssue >(); }); }); }); ================================================ FILE: library/src/actions/rawTransform/rawTransformAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { type RawTransformActionAsync, rawTransformAsync, } from './rawTransformAsync.ts'; describe('rawTransformAsync', () => { const action = rawTransformAsync( async ({ dataset, addIssue, NEVER }) => { const length = dataset.value.length; if (length < 3) { addIssue({ message: 'message' }); return NEVER; } return length; } ); test('should return action object', () => { expect(action).toStrictEqual({ kind: 'transformation', type: 'raw_transform', reference: rawTransformAsync, async: true, '~run': expect.any(Function), } satisfies RawTransformActionAsync); }); describe('should return dataset without issues', () => { test('for valid inputs', async () => { expect( await action['~run']({ typed: true, value: 'foo' }, {}) ).toStrictEqual({ typed: true, value: 3, }); expect( await action['~run']({ typed: true, value: '123456789' }, {}) ).toStrictEqual({ typed: true, value: 9, }); }); }); describe('should return dataset with issues', () => { test('for invalid inputs', async () => { expect( await action['~run']({ typed: true, value: 'fo' }, {}) ).toStrictEqual({ typed: false, value: 'fo', issues: [ { kind: 'transformation', type: 'raw_transform', expected: null, message: 'message', input: 'fo', received: '"fo"', requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }, ], }); }); }); }); ================================================ FILE: library/src/actions/rawTransform/rawTransformAsync.ts ================================================ import type { BaseIssue, BaseTransformationAsync, MaybePromise, OutputDataset, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { RawTransformContext, RawTransformIssue } from './types.ts'; /** * Raw transform action async interface. */ export interface RawTransformActionAsync extends BaseTransformationAsync> { /** * The action type. */ readonly type: 'raw_transform'; /** * The action reference. */ readonly reference: typeof rawTransformAsync; } /** * Creates a raw transformation action. * * @param action The transformation action. * * @returns A raw transform action. */ // @__NO_SIDE_EFFECTS__ export function rawTransformAsync( action: (context: RawTransformContext) => MaybePromise ): RawTransformActionAsync { return { kind: 'transformation', type: 'raw_transform', reference: rawTransformAsync, async: true, async '~run'(dataset, config) { // Execute action and get its output const output = await action({ dataset, config, addIssue: (info) => _addIssue(this, info?.label ?? 'input', dataset, config, info), NEVER: null as never, }); // Update dataset depending on issues if (dataset.issues) { // @ts-expect-error dataset.typed = false; } else { // @ts-expect-error dataset.value = output; } // Return output dataset // @ts-expect-error return dataset as OutputDataset< TOutput, BaseIssue | RawTransformIssue >; }, }; } ================================================ FILE: library/src/actions/rawTransform/types.ts ================================================ import type { BaseIssue, Config, ErrorMessage, IssuePathItem, SuccessDataset, } from '../../types/index.ts'; /** * Raw transform issue interface. */ export interface RawTransformIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'transformation'; /** * The issue type. */ readonly type: 'raw_transform'; } /** * Raw transform issue info interface. */ export interface RawTransformIssueInfo { label?: string | undefined; input?: unknown | undefined; expected?: string | undefined; received?: string | undefined; message?: ErrorMessage> | undefined; path?: [IssuePathItem, ...IssuePathItem[]] | undefined; } /** * Raw transform add issue type. */ export type RawTransformAddIssue = ( info?: RawTransformIssueInfo ) => void; /** * Raw transform context interface. */ export interface RawTransformContext { readonly dataset: SuccessDataset; readonly config: Config>; readonly addIssue: RawTransformAddIssue; readonly NEVER: never; } ================================================ FILE: library/src/actions/readonly/index.ts ================================================ export * from './readonly.ts'; ================================================ FILE: library/src/actions/readonly/readonly.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { readonly, type ReadonlyAction } from './readonly.ts'; describe('readonly', () => { test('should return action object', () => { // eslint-disable-next-line @typescript-eslint/consistent-type-definitions type Input = { key: string }; type Action = ReadonlyAction; expectTypeOf(readonly()).toEqualTypeOf(); }); describe('should infer correct types', () => { // eslint-disable-next-line @typescript-eslint/consistent-type-definitions type Input1 = { for: string; bar: number }; type Action1 = ReadonlyAction; type Input2 = [string, number]; type Action2 = ReadonlyAction; type Input3 = Map; type Action3 = ReadonlyAction; type Input4 = Set; type Action4 = ReadonlyAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf<{ readonly for: string; readonly bar: number; }>(); expectTypeOf>().toEqualTypeOf< readonly [string, number] >(); expectTypeOf>().toEqualTypeOf< ReadonlyMap >(); expectTypeOf>().toEqualTypeOf>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/readonly/readonly.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { readonly, type ReadonlyAction } from './readonly.ts'; describe('readonly', () => { test('should return action object', () => { expect(readonly()).toStrictEqual({ kind: 'transformation', type: 'readonly', reference: readonly, async: false, '~run': expect.any(Function), } satisfies ReadonlyAction<{ key: string }>); }); test('should return same dataset', () => { const dataset = { typed: true, value: { key: 'foo' } } as const; expect(readonly()['~run'](dataset, {})).toStrictEqual(dataset); }); }); ================================================ FILE: library/src/actions/readonly/readonly.ts ================================================ import type { BaseTransformation, SuccessDataset } from '../../types/index.ts'; /** * Readonly output type. */ type ReadonlyOutput = TInput extends Map ? ReadonlyMap : TInput extends Set ? ReadonlySet : Readonly; /** * Readonly action interface. */ export interface ReadonlyAction extends BaseTransformation, never> { /** * The action type. */ readonly type: 'readonly'; /** * The action reference. */ readonly reference: typeof readonly; } /** * Creates a readonly transformation action. * * @returns A readonly action. */ export function readonly(): ReadonlyAction; // @__NO_SIDE_EFFECTS__ export function readonly(): ReadonlyAction { return { kind: 'transformation', type: 'readonly', reference: readonly, async: false, '~run'(dataset) { return dataset as SuccessDataset>; }, }; } ================================================ FILE: library/src/actions/reduceItems/index.ts ================================================ export * from './reduceItems.ts'; ================================================ FILE: library/src/actions/reduceItems/reduceItems.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { reduceItems, type ReduceItemsAction } from './reduceItems.ts'; describe('reduceItems', () => { test('should return action object', () => { expectTypeOf( reduceItems((output, item) => output + item, 0) ).toEqualTypeOf>(); }); describe('should infer correct types', () => { type Action = ReduceItemsAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/reduceItems/reduceItems.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { reduceItems, type ReduceItemsAction } from './reduceItems.ts'; describe('reduceItems', () => { const operation = (output: number, item: number) => output + item; const initial = 0; const action = reduceItems(operation, initial); test('should return action object', () => { expect(action).toStrictEqual({ kind: 'transformation', type: 'reduce_items', reference: reduceItems, async: false, operation, initial, '~run': expect.any(Function), } satisfies ReduceItemsAction); }); test('should transform input', () => { expect( action['~run']({ typed: true, value: [9, -12, 345, 0, 999] }, {}) ).toStrictEqual({ typed: true, value: 1341, }); }); }); ================================================ FILE: library/src/actions/reduceItems/reduceItems.ts ================================================ import type { BaseTransformation, SuccessDataset } from '../../types/index.ts'; import type { ArrayInput } from '../types.ts'; /** * Array action type. */ type ArrayAction = ( output: TOutput, item: TInput[number], index: number, array: TInput ) => TOutput; /** * Reduce items action interface. */ export interface ReduceItemsAction extends BaseTransformation { /** * The action type. */ readonly type: 'reduce_items'; /** * The action reference. */ readonly reference: typeof reduceItems; /** * The reduce items operation. */ readonly operation: ArrayAction; /** * The initial value. */ readonly initial: TOutput; } /** * Creates a reduce items transformation action. * * @param operation The reduce items operation. * @param initial The initial value. * * @returns A reduce items action. */ export function reduceItems( operation: ArrayAction, initial: TOutput ): ReduceItemsAction; // @__NO_SIDE_EFFECTS__ export function reduceItems( operation: ArrayAction, initial: unknown ): ReduceItemsAction { return { kind: 'transformation', type: 'reduce_items', reference: reduceItems, async: false, operation, initial, '~run'(dataset) { // @ts-expect-error dataset.value = dataset.value.reduce(this.operation, this.initial); return dataset as SuccessDataset; }, }; } ================================================ FILE: library/src/actions/regex/index.ts ================================================ export * from './regex.ts'; ================================================ FILE: library/src/actions/regex/regex.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { regex, type RegexAction, type RegexIssue } from './regex.ts'; describe('regex', () => { describe('should return action object', () => { const requirement = /^ID-\d{3}$/u; test('with undefined message', () => { type Action = RegexAction; expectTypeOf(regex(requirement)).toEqualTypeOf(); expectTypeOf(regex(requirement, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(regex(requirement, 'message')).toEqualTypeOf< RegexAction >(); }); test('with function message', () => { expectTypeOf(regex(requirement, () => 'message')).toEqualTypeOf< RegexAction string> >(); }); }); describe('should infer correct types', () => { type Action = RegexAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/regex/regex.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { regex, type RegexAction, type RegexIssue } from './regex.ts'; describe('regex', () => { const requirement = /^ID-\d{3}$/u; describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'regex', reference: regex, expects: `${requirement}`, requirement, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: RegexAction = { ...baseAction, message: undefined, }; expect(regex(requirement)).toStrictEqual(action); expect(regex(requirement, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(regex(requirement, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies RegexAction); }); test('with function message', () => { const message = () => 'message'; expect(regex(requirement, message)).toStrictEqual({ ...baseAction, message, } satisfies RegexAction); }); }); describe('should return dataset without issues', () => { const action = regex(requirement); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for matching strings', () => { expectNoActionIssue(action, ['ID-000', 'ID-123', 'ID-999']); }); }); describe('should return dataset with issues', () => { const action = regex(requirement, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'regex', expected: `${requirement}`, requirement, message: 'message', }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for blank spaces', () => { expectActionIssue(action, baseIssue, [' ID-000', 'ID-000 ', ' ID-000 ']); }); test('for missing separator', () => { expectActionIssue(action, baseIssue, ['ID000']); }); test('for invalid separators', () => { expectActionIssue(action, baseIssue, [ 'ID 000', 'ID:000', 'ID–000', 'ID_000', 'ID/000', 'ID.000', ]); }); test('for invalid prefix', () => { expectActionIssue(action, baseIssue, [ 'id-000', 'D-000', 'I-000', 'AD-000', 'IA-000', ]); }); test('for invalid number', () => { expectActionIssue(action, baseIssue, [ 'ID-0', // 1 digit 'ID-00', // 2 digits 'ID-0000', // 4 digits 'ID-00000', // 5 digits 'ID-A00', // letter 'ID-0A0', // letter 'ID-00A', // letter 'ID-a00', // letter 'ID-0a0', // letter 'ID-00a', // letter ]); }); }); }); ================================================ FILE: library/src/actions/regex/regex.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Regex issue interface. */ export interface RegexIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'regex'; /** * The expected input. */ readonly expected: string; /** * The received input. */ readonly received: `"${string}"`; /** * The regex pattern. */ readonly requirement: RegExp; } /** * Regex action interface. */ export interface RegexAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'regex'; /** * The action reference. */ readonly reference: typeof regex; /** * The expected property. */ readonly expects: string; /** * The regex pattern. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates a [regex](https://en.wikipedia.org/wiki/Regular_expression) validation action. * * Hint: Be careful with the global flag `g` in your regex pattern, as it can lead to unexpected results. See [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test#using_test_on_a_regex_with_the_global_flag) for more information. * * @param requirement The regex pattern. * * @returns A regex action. */ export function regex( requirement: RegExp ): RegexAction; /** * Creates a [regex](https://en.wikipedia.org/wiki/Regular_expression) validation action. * * Hint: Be careful with the global flag `g` in your regex pattern, as it can lead to unexpected results. See [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test#using_test_on_a_regex_with_the_global_flag) for more information. * * @param requirement The regex pattern. * @param message The error message. * * @returns A regex action. */ export function regex< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(requirement: RegExp, message: TMessage): RegexAction; // @__NO_SIDE_EFFECTS__ export function regex( requirement: RegExp, message?: ErrorMessage> ): RegexAction> | undefined> { return { kind: 'validation', type: 'regex', reference: regex, async: false, expects: `${requirement}`, requirement, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'format', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/returns/index.ts ================================================ export * from './returns.ts'; export * from './returnsAsync.ts'; ================================================ FILE: library/src/actions/returns/returns.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { number } from '../../schemas/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { returns, type ReturnsAction } from './returns.ts'; describe('returns', () => { type Input = (arg1: string, arg2: number, ...rest: boolean[]) => unknown; const schema = number(); type Schema = typeof schema; type Action = ReturnsAction; test('should return action object', () => { expectTypeOf(returns(schema)).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< (arg1: string, arg2: number, ...rest: boolean[]) => number >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/returns/returns.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { number } from '../../schemas/index.ts'; import { returns, type ReturnsAction } from './returns.ts'; describe('returns', () => { type Input = (arg1: unknown) => unknown; const schema = number(); type Schema = typeof schema; const action = returns(schema); test('should return action object', () => { expect(action).toStrictEqual({ kind: 'transformation', type: 'returns', reference: returns, async: false, schema, '~run': expect.any(Function), } satisfies ReturnsAction); }); const func = (arg1: unknown) => arg1; const dataset = action['~run']({ typed: true, value: func }, {}); test('should return new function', () => { expect(dataset).toStrictEqual({ typed: true, value: expect.any(Function), }); expect(dataset.value).not.toBe(func); }); test('should not throw error for valid returns', () => { if (dataset.typed) { expect(() => dataset.value(123)).not.toThrowError(); expect(dataset.value(123)).toBe(123); } }); test('should throw error for invalid returns', () => { if (dataset.typed) { expect(() => dataset.value('123')).toThrowError(); expect(() => dataset.value(123n)).toThrowError(); expect(() => dataset.value(null)).toThrowError(); } }); }); ================================================ FILE: library/src/actions/returns/returns.ts ================================================ import type { BaseIssue, BaseSchema, BaseTransformation, InferOutput, } from '../../types/index.ts'; import { ValiError } from '../../utils/index.ts'; /** * Returns action type. */ export interface ReturnsAction< // eslint-disable-next-line @typescript-eslint/no-explicit-any TInput extends (...args: any[]) => unknown, TSchema extends BaseSchema>, > extends BaseTransformation< TInput, (...args: Parameters) => InferOutput, never > { /** * The action type. */ readonly type: 'returns'; /** * The action reference. */ readonly reference: typeof returns; /** * The arguments schema. */ readonly schema: TSchema; } /** * Creates a function return transformation action. * * @param schema The arguments schema. * * @returns An returns action. */ export function returns< // eslint-disable-next-line @typescript-eslint/no-explicit-any TInput extends (...args: any[]) => unknown, TSchema extends BaseSchema>, >(schema: TSchema): ReturnsAction; // @__NO_SIDE_EFFECTS__ export function returns( schema: BaseSchema> ): ReturnsAction< (...args: unknown[]) => unknown, BaseSchema> > { return { kind: 'transformation', type: 'returns', reference: returns, async: false, schema, '~run'(dataset, config) { const func = dataset.value; dataset.value = (...args_) => { const returnsDataset = this.schema['~run']( { value: func(...args_) }, config ); if (returnsDataset.issues) { throw new ValiError(returnsDataset.issues); } return returnsDataset.value; }; return dataset; }, }; } ================================================ FILE: library/src/actions/returns/returnsAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { pipeAsync } from '../../methods/index.ts'; import { number } from '../../schemas/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { minValue } from '../minValue/index.ts'; import { type ReturnsActionAsync, returnsAsync } from './returnsAsync.ts'; describe('returnsAsync', () => { type Input = ( arg1: string, arg2: number, ...rest: boolean[] ) => Promise; const schema = pipeAsync(number(), minValue(0)); type Schema = typeof schema; type Action = ReturnsActionAsync; test('should return action object', () => { expectTypeOf(returnsAsync(schema)).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< (arg1: string, arg2: number, ...rest: boolean[]) => Promise >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/returns/returnsAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { pipeAsync } from '../../methods/index.ts'; import { number } from '../../schemas/index.ts'; import { minValue } from '../minValue/index.ts'; import { type ReturnsActionAsync, returnsAsync } from './returnsAsync.ts'; describe('returnsAsync', () => { type Input = (arg1: unknown) => Promise; const schema = pipeAsync(number(), minValue(0)); type Schema = typeof schema; const action = returnsAsync(schema); test('should return action object', () => { expect(action).toStrictEqual({ kind: 'transformation', type: 'returns', reference: returnsAsync, async: false, schema, '~run': expect.any(Function), } satisfies ReturnsActionAsync); }); const func = async (arg1: unknown) => arg1; const dataset = action['~run']({ typed: true, value: func }, {}); test('should return new function', () => { expect(dataset).toStrictEqual({ typed: true, value: expect.any(Function), }); expect(dataset.value).not.toBe(func); }); test('should not throw error for valid returnsAsync', async () => { if (dataset.typed) { await expect(dataset.value(123)).resolves.not.toThrowError(); expect(await dataset.value(123)).toBe(123); } }); test('should throw error for invalid returnsAsync', async () => { if (dataset.typed) { await expect(dataset.value(-123)).rejects.toThrowError(); await expect(dataset.value('123')).rejects.toThrowError(); await expect(dataset.value(123n)).rejects.toThrowError(); await expect(dataset.value(null)).rejects.toThrowError(); } }); }); ================================================ FILE: library/src/actions/returns/returnsAsync.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, BaseTransformation, InferOutput, SuccessDataset, } from '../../types/index.ts'; import { ValiError } from '../../utils/index.ts'; /** * Returns action async type. */ export interface ReturnsActionAsync< // eslint-disable-next-line @typescript-eslint/no-explicit-any TInput extends (...args: any[]) => unknown, TSchema extends | BaseSchema> | BaseSchemaAsync>, > extends BaseTransformation< TInput, (...args: Parameters) => Promise>>, never > { /** * The action type. */ readonly type: 'returns'; /** * The action reference. */ readonly reference: typeof returnsAsync; /** * The arguments schema. */ readonly schema: TSchema; } /** * Creates a function arguments transformation action. * * @param schema The arguments schema. * * @returns An returns action. */ export function returnsAsync< // eslint-disable-next-line @typescript-eslint/no-explicit-any TInput extends (...args: any[]) => unknown, TSchema extends | BaseSchema> | BaseSchemaAsync>, >(schema: TSchema): ReturnsActionAsync; // @__NO_SIDE_EFFECTS__ export function returnsAsync( schema: | BaseSchema> | BaseSchemaAsync> ): ReturnsActionAsync< (...args: unknown[]) => unknown, | BaseSchema> | BaseSchemaAsync> > { return { kind: 'transformation', type: 'returns', reference: returnsAsync, async: false, schema, '~run'(dataset, config) { const func = dataset.value; dataset.value = async (...args_) => { const returnsDataset = await this.schema['~run']( { value: await func(...args_) }, config ); if (returnsDataset.issues) { throw new ValiError(returnsDataset.issues); } return returnsDataset.value; }; return dataset as SuccessDataset< (...args: unknown[]) => Promise >; }, }; } ================================================ FILE: library/src/actions/rfcEmail/index.ts ================================================ export * from './rfcEmail.ts'; ================================================ FILE: library/src/actions/rfcEmail/rfcEmail.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type {} from '../email/email.ts'; import { rfcEmail, type RfcEmailAction, type RfcEmailIssue, } from './rfcEmail.ts'; describe('rfcEmail', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = RfcEmailAction; expectTypeOf(rfcEmail()).toEqualTypeOf(); expectTypeOf(rfcEmail(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(rfcEmail('message')).toEqualTypeOf< RfcEmailAction >(); }); test('with function message', () => { expectTypeOf(rfcEmail(() => 'message')).toEqualTypeOf< RfcEmailAction string> >(); }); }); describe('should infer correct types', () => { type Action = RfcEmailAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/rfcEmail/rfcEmail.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { RFC_EMAIL_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { rfcEmail, type RfcEmailAction, type RfcEmailIssue, } from './rfcEmail.ts'; describe('rfcEmail', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'rfc_email', reference: rfcEmail, expects: null, requirement: RFC_EMAIL_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: RfcEmailAction = { ...baseAction, message: undefined, }; expect(rfcEmail()).toStrictEqual(action); expect(rfcEmail(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(rfcEmail('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies RfcEmailAction); }); test('with function message', () => { const message = () => 'message'; expect(rfcEmail(message)).toStrictEqual({ ...baseAction, message, } satisfies RfcEmailAction); }); }); describe('should return dataset without issues', () => { const action = rfcEmail(); // General tests test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for simple email', () => { expectNoActionIssue(action, ['email@example.com']); }); test('for very short email', () => { expectNoActionIssue(action, ['a@b.cd']); }); // Start of local part test('for underscore in beginning of local part', () => { expectNoActionIssue(action, ['_email@example.com']); }); test('for hyphen in beginning of local part', () => { expectNoActionIssue(action, ['-email@example.com']); }); test('for plus in beginning of local part', () => { expectNoActionIssue(action, ['+email@example.com']); }); test('for dot in beginning of local part', () => { expectNoActionIssue(action, ['.email@example.com']); }); // End of local part test('for underscore in end of local part', () => { expectNoActionIssue(action, ['email_@example.com']); }); test('for hyphen in end of local part', () => { expectNoActionIssue(action, ['email-@example.com']); }); test('for plus in end of local part', () => { expectNoActionIssue(action, ['email+@example.com']); }); test('for dot in end of local part', () => { expectNoActionIssue(action, ['email.@example.com']); }); // Middle of local part test('for dot in local part', () => { expectNoActionIssue(action, ['firstname.lastname@example.com']); }); test('for two following dots in local part', () => { expectNoActionIssue(action, ['email..email@example.com']); }); test('for underscore in local part', () => { expectNoActionIssue(action, ['firstname_lastname@example.com']); }); test('for hyphen in local part', () => { expectNoActionIssue(action, ['firstname-lastname@example.com']); }); test('for plus in local part', () => { expectNoActionIssue(action, ['firstname+lastname@example.com']); }); // Special local parts test('for numerical local part', () => { expectNoActionIssue(action, ['1234567890@example.com']); }); test('for underscore local part', () => { expectNoActionIssue(action, ['_______@example.com']); }); test('for special chars in local part', () => { expectNoActionIssue(action, ['#$&%@example.com']); }); // Domain part variations test('for hyphen in domain part', () => { expectNoActionIssue(action, ['email@example-domain.com']); }); test('for domain with subdomain', () => { expectNoActionIssue(action, ['email@subdomain.example.com']); }); test('for subdomain and hyphen in domain', () => { expectNoActionIssue(action, ['email@subdomain.example-domain.com']); }); test('for long top level domain', () => { expectNoActionIssue(action, ['email@example.technology']); }); test('for country code TLD', () => { expectNoActionIssue(action, ['email@example.co.uk']); }); test('for subdomain and country code TLD', () => { expectNoActionIssue(action, ['email@subdomain.example.co.uk']); }); test('for numerical domain', () => { expectNoActionIssue(action, ['email@123.com']); }); test('for punycode domain', () => { expectNoActionIssue(action, ['email@xn--exmple-cua.com']); }); test('for punycode TLD', () => { expectNoActionIssue(action, ['email@example.xn--6frz82g']); }); test('for numerical TLD', () => { expectNoActionIssue(action, ['email@example.123']); }); test('for single char TLD', () => { expectNoActionIssue(action, ['email@example.a']); }); test('for missing TLD', () => { expectNoActionIssue(action, ['email@example']); }); }); describe('should return dataset with issues', () => { const action = rfcEmail('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'rfc_email', expected: null, message: 'message', requirement: RFC_EMAIL_REGEX, }; // General tests test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for simple strings', () => { expectActionIssue(action, baseIssue, ['email', 'emailexamplecom']); }); test('for email with spaces', () => { expectActionIssue(action, baseIssue, [ ' email@example.com', 'e mail@example.com', 'email @example.com', 'email@ example.com', 'email@exa mple.com', 'email@example. com', 'email@example.com ', ]); }); // Missing parts test('for missing local part', () => { expectActionIssue(action, baseIssue, ['@example.com']); }); test('for missing @ symbol', () => { expectActionIssue(action, baseIssue, [ 'example.com', 'email.example.com', ]); }); test('for missing domain part', () => { expectActionIssue(action, baseIssue, ['email@']); }); test('for missing domain name', () => { expectActionIssue(action, baseIssue, ['email@.com']); }); // Invalid repeated chars test('for two following @ symbols', () => { expectActionIssue(action, baseIssue, ['email@@example.com']); }); test('for dot in end of domain name', () => { expectActionIssue(action, baseIssue, ['email@example..com']); }); // Beginning and end of domain part test('for underscore in beginning of domain part', () => { expectActionIssue(action, baseIssue, ['email@_example.com']); }); test('for hypen in beginning of domain part', () => { expectActionIssue(action, baseIssue, ['email@-example.com']); }); test('for plus in beginning of domain part', () => { expectActionIssue(action, baseIssue, ['email@+example.com']); }); test('for dot in beginning of domain part', () => { expectActionIssue(action, baseIssue, ['email@.example.com']); }); test('for underscore in end of domain name', () => { expectActionIssue(action, baseIssue, ['email@example_.com']); }); test('for hypen in end of domain name', () => { expectActionIssue(action, baseIssue, ['email@example-.com']); }); test('for plus in end of domain name', () => { expectActionIssue(action, baseIssue, ['email@example+.com']); }); // Other special cases test('for repeated domain part', () => { expectActionIssue(action, baseIssue, ['email@example@example.com']); }); test('for special chars in domain part', () => { expectActionIssue(action, baseIssue, [ 'email@#$&%.com', 'email@example.#$&%', ]); }); test('for non ASCII chars', () => { expectActionIssue(action, baseIssue, [ 'あいうえお@example.com', 'email@あいうえお.com', 'email@example.あいう', ]); }); test('for email username', () => { expectActionIssue(action, baseIssue, [ 'Joe Smith ', 'email@example.com (Joe Smith)', ]); }); }); }); ================================================ FILE: library/src/actions/rfcEmail/rfcEmail.ts ================================================ import { RFC_EMAIL_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * RFC email issue interface. */ export interface RfcEmailIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'rfc_email'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The RFC email regex. */ readonly requirement: RegExp; } /** * RFC email action interface. */ export interface RfcEmailAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'rfc_email'; /** * The action reference. */ readonly reference: typeof rfcEmail; /** * The expected property. */ readonly expects: null; /** * The RFC email regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates a [RFC email](https://datatracker.ietf.org/doc/html/rfc5322#section-3.4.1) * validation action. * * Hint: This validation action intentionally validates the entire RFC 5322 * specification. If you are interested in an action that only covers common * email addresses, please use the `email` action instead. * * @returns A RFC email action. */ export function rfcEmail(): RfcEmailAction< TInput, undefined >; /** * Creates a [RFC email](https://datatracker.ietf.org/doc/html/rfc5322#section-3.4.1) * validation action. * * Hint: This validation action intentionally validates the entire RFC 5322 * specification. If you are interested in an action that only covers common * email addresses, please use the `email` action instead. * * @param message The error message. * * @returns A RFC email action. */ export function rfcEmail< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): RfcEmailAction; // @__NO_SIDE_EFFECTS__ export function rfcEmail( message?: ErrorMessage> ): RfcEmailAction> | undefined> { return { kind: 'validation', type: 'rfc_email', reference: rfcEmail, expects: null, async: false, requirement: RFC_EMAIL_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'email', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/safeInteger/index.ts ================================================ export * from './safeInteger.ts'; ================================================ FILE: library/src/actions/safeInteger/safeInteger.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { safeInteger, type SafeIntegerAction, type SafeIntegerIssue, } from './safeInteger.ts'; describe('safeInteger', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = SafeIntegerAction; expectTypeOf(safeInteger()).toEqualTypeOf(); expectTypeOf(safeInteger(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(safeInteger('message')).toEqualTypeOf< SafeIntegerAction >(); }); test('with function message', () => { expectTypeOf(safeInteger(() => 'message')).toEqualTypeOf< SafeIntegerAction string> >(); }); }); describe('should infer correct types', () => { type Action = SafeIntegerAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< SafeIntegerIssue >(); }); }); }); ================================================ FILE: library/src/actions/safeInteger/safeInteger.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { NumberIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { safeInteger, type SafeIntegerAction, type SafeIntegerIssue, } from './safeInteger.ts'; describe('safeInteger', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'safe_integer', reference: safeInteger, expects: null, requirement: expect.any(Function), async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: SafeIntegerAction = { ...baseAction, message: undefined, }; expect(safeInteger()).toStrictEqual(action); expect(safeInteger(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(safeInteger('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies SafeIntegerAction); }); test('with function message', () => { const message = () => 'message'; expect(safeInteger(message)).toStrictEqual({ ...baseAction, message, } satisfies SafeIntegerAction); }); }); describe('should return dataset without issues', () => { const action = safeInteger(); test('for untyped inputs', () => { const issues: [NumberIssue] = [ { kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for safe integer numbers', () => { expectNoActionIssue(action, [ 0, 123456789, -123456789, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER, ]); }); }); describe('should return dataset with issues', () => { const action = safeInteger('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'safe_integer', expected: null, message: 'message', requirement: expect.any(Function), }; test('for unsafe integer numbers', () => { expectActionIssue(action, baseIssue, [ Number.MAX_VALUE, Number.MIN_VALUE, Number.MAX_SAFE_INTEGER + 1, Number.MIN_SAFE_INTEGER - 1, ]); }); test('for floating point numbers', () => { expectActionIssue(action, baseIssue, [0.1, 12.34, -1 / 3, Math.PI]); }); test('for infinite numbers', () => { expectActionIssue(action, baseIssue, [Infinity, -Infinity]); }); test('for not a number', () => { expectActionIssue(action, baseIssue, [NaN]); }); }); }); ================================================ FILE: library/src/actions/safeInteger/safeInteger.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Safe integer issue interface. */ export interface SafeIntegerIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'safe_integer'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `${number}`; /** * The validation function. */ readonly requirement: (input: number) => boolean; } /** * Safe integer action interface. */ export interface SafeIntegerAction< TInput extends number, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'safe_integer'; /** * The action reference. */ readonly reference: typeof safeInteger; /** * The expected property. */ readonly expects: null; /** * The validation function. */ readonly requirement: (input: number) => boolean; /** * The error message. */ readonly message: TMessage; } /** * Creates a safe integer validation action. * * @returns A safe integer action. */ export function safeInteger(): SafeIntegerAction< TInput, undefined >; /** * Creates a safe integer validation action. * * @param message The error message. * * @returns A safe integer action. */ export function safeInteger< TInput extends number, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): SafeIntegerAction; // @__NO_SIDE_EFFECTS__ export function safeInteger( message?: ErrorMessage> ): SafeIntegerAction< number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'safe_integer', reference: safeInteger, async: false, expects: null, requirement: Number.isSafeInteger, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement(dataset.value)) { _addIssue(this, 'safe integer', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/size/index.ts ================================================ export * from './size.ts'; ================================================ FILE: library/src/actions/size/size.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { size, type SizeAction, type SizeIssue } from './size.ts'; describe('size', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = SizeAction; expectTypeOf(size(10)).toEqualTypeOf(); expectTypeOf( size(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(size(10, 'message')).toEqualTypeOf< SizeAction >(); }); test('with function message', () => { expectTypeOf( size string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = SizeAction, 10, undefined>; test('of input', () => { expectTypeOf>().toEqualTypeOf>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< SizeIssue, 10> >(); }); }); }); ================================================ FILE: library/src/actions/size/size.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { MapIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { size, type SizeAction, type SizeIssue } from './size.ts'; describe('size', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'size', reference: size, expects: '5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: SizeAction = { ...baseAction, message: undefined, }; expect(size(5)).toStrictEqual(action); expect(size(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(size(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies SizeAction); }); test('with function message', () => { const message = () => 'message'; expect(size(5, message)).toStrictEqual({ ...baseAction, message, } satisfies SizeAction); }); }); describe('should return dataset without issues', () => { const action = size(3); test('for untyped inputs', () => { const issues: [MapIssue] = [ { kind: 'schema', type: 'map', input: null, expected: 'Map', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid maps', () => { expectNoActionIssue(action, [ new Map([ [1, 'one'], [2, 'two'], [3, 'three'], ]), new Map([ [' ', 'space'], ['\n', 'new-line'], ['\t', 'tab'], ]), new Map([ ['one', 1], ['two', '2'], ['three', 3], ]), new Map([ ['1', 'one'], [2, null], [true, null], ]), ]); }); test('for valid sets', () => { expectNoActionIssue(action, [ new Set([1, 2, 3]), new Set('123'), new Set([' ', '\n', '\t']), new Set([[1, 2, 3, 4], [5, 6], [7]]), new Set([1, 'two', null]), new Set(['1', { value: '5' }, null]), ]); }); test('for valid blobs', () => { expectNoActionIssue(action, [ new Blob(['bot']), new Blob(['✨']), new Blob([' \t\n']), new Blob(['1', '2', '3'], { type: 'text/plain' }), new Blob( [ new Uint8Array([104, 105]), // 'hi' new Blob(['!'], { type: 'text/plain' }), ], { type: 'text/plain' } ), ]); }); }); describe('should return dataset with issues', () => { const action = size(3, 'message'); const baseIssue: Omit< SizeIssue, 3>, 'input' | 'received' > = { kind: 'validation', type: 'size', expected: '3', message: 'message', requirement: 3, }; test('for invalid maps', () => { expectActionIssue( action, baseIssue, [ new Map(), new Map([[1, 'one']]), new Map([ ['one', 1], ['two', null], ]), new Map([ [1, 'one'], [2, 'two'], ['3', 'three'], [4, null], ]), ], (value) => `${value.size}` ); }); test('for invalid sets', () => { expectActionIssue( action, baseIssue, [ new Set(), new Set([1]), new Set(['one', null]), new Set('1234'), new Set([[1, 2, 3, 4], [5, 6], [7], [8, 9]]), ], (value) => `${value.size}` ); }); test('for invalid blobs', () => { expectActionIssue( action, baseIssue, [ new Blob([]), new Blob(['']), new Blob([' ']), new Blob(['1']), new Blob(['hi'], { type: 'text/plain' }), new Blob([new Uint8Array([72, 105])]), // 'Hi' new Blob([' \t\n']), new Blob([new Uint8Array([104, 105, 33, 33])]), // 'hi!!' new Blob(['🤖']), new Blob(['🤖😍']), ], (value) => `${value.size}` ); }); }); }); ================================================ FILE: library/src/actions/size/size.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { SizeInput } from '../types.ts'; /** * Size issue interface. */ export interface SizeIssue< TInput extends SizeInput, TRequirement extends number, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'size'; /** * The expected property. */ readonly expected: `${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The required size. */ readonly requirement: TRequirement; } /** * Size action interface. */ export interface SizeAction< TInput extends SizeInput, TRequirement extends number, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'size'; /** * The action reference. */ readonly reference: typeof size; /** * The expected property. */ readonly expects: `${TRequirement}`; /** * The required size. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a size validation action. * * @param requirement The required size. * * @returns A size action. */ export function size< TInput extends SizeInput, const TRequirement extends number, >(requirement: TRequirement): SizeAction; /** * Creates a size validation action. * * @param requirement The required size. * @param message The error message. * * @returns A size action. */ export function size< TInput extends SizeInput, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): SizeAction; // @__NO_SIDE_EFFECTS__ export function size( requirement: number, message?: ErrorMessage> ): SizeAction< SizeInput, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'size', reference: size, async: false, expects: `${requirement}`, requirement, message, '~run'(dataset, config) { if (dataset.typed && dataset.value.size !== this.requirement) { _addIssue(this, 'size', dataset, config, { received: `${dataset.value.size}`, }); } return dataset; }, }; } ================================================ FILE: library/src/actions/slug/index.ts ================================================ export * from './slug.ts'; ================================================ FILE: library/src/actions/slug/slug.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { slug, type SlugAction, type SlugIssue } from './slug.ts'; describe('slug', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = SlugAction; expectTypeOf(slug()).toEqualTypeOf(); expectTypeOf(slug(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(slug('message')).toEqualTypeOf< SlugAction >(); }); test('with function message', () => { expectTypeOf(slug(() => 'message')).toEqualTypeOf< SlugAction string> >(); }); }); describe('should infer correct types', () => { type Action = SlugAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/slug/slug.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { SLUG_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { slug, type SlugAction, type SlugIssue } from './slug.ts'; describe('slug', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'slug', reference: slug, expects: null, requirement: SLUG_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: SlugAction = { ...baseAction, message: undefined, }; expect(slug()).toStrictEqual(action); expect(slug(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(slug('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies SlugAction); }); test('with function message', () => { const message = () => 'message'; expect(slug(message)).toStrictEqual({ ...baseAction, message, } satisfies SlugAction); }); }); describe('should return dataset without issues', () => { const action = slug(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid single word', () => { expectNoActionIssue(action, [ 'a', 'z', '0', '9', 'az', '09', '120', 'abc129', '968foo', 'foo135bar', '357ace642', 'collection', ]); }); test('for valid separated words', () => { expectNoActionIssue(action, [ 'a-a', 'a_a', 'z-z', 'z_z', '0-0', '0_0', '9-9', '9_9', 'az-az', 'az_az', '09-09', '09_09', '120-120', '120_120', 'abc129-abc129', 'abc129_abc129', '968foo-968foo', '968foo_968foo', 'foo135bar-foo135bar', 'foo135bar_foo135bar', '357ace642-357ace642', '357ace642_357ace642', 'this-that-other-outre-collection', ]); }); }); describe('should return dataset with issues', () => { const action = slug('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'slug', expected: null, message: 'message', requirement: SLUG_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for strings with invalid chars', () => { expectActionIssue(action, baseIssue, [ // rfc3986 valid characters 'A', 'Z', '.', '~', // rfc3986 reserved characters ':', '/', '?', '#', '[', ']', '@', '!', '$', '&', "'", '(', ')', '*', '+', ',', ';', '=', // characters that occupy more than one byte 'é', '❤️', // URL-encoded '%40', // '@' '%20', // ' ' '%2F%C3%A9', // 'é' // strings containing at least one invalid character 'helloWorld', 'café', // regex specific tests 'a-A', 'a-Z', 'a-.', 'a-~', 'a-:', 'a-/', 'a-?', 'a-#', 'a-[', 'a-]', 'a-@', 'a-!', 'a-$', 'a-&', "a-'", 'a-(', 'a-)', 'a-*', 'a-+', 'a-,', 'a-;', 'a-=', 'a-é', 'a-❤️', 'a-%40', 'a-%20', 'a-%2F%C3%A9', ]); }); test('for invalid separators', () => { expectActionIssue(action, baseIssue, [ 'hello world', 'hello+world', 'hello%20world', // consecutive valid separator characters 'hello--world', 'hello__world', 'hello-_world', 'hello_-world', ]); }); test('for separators at start or end', () => { expectActionIssue(action, baseIssue, [ '-hello', '_hello', '-123', '_123', 'hello-', 'hello_', '123-', '123_', '-hello-', '_hello_', ]); }); }); }); ================================================ FILE: library/src/actions/slug/slug.ts ================================================ import { SLUG_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Slug issue type. */ export interface SlugIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'slug'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The slug regex. */ readonly requirement: RegExp; } /** * Slug action type. */ export interface SlugAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'slug'; /** * The action reference. */ readonly reference: typeof slug; /** * The expected property. */ readonly expects: null; /** * The slug regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates a [slug](https://en.wikipedia.org/wiki/Clean_URL#Slug) validation action. * * @returns A slug action. */ export function slug(): SlugAction; /** * Creates a [slug](https://en.wikipedia.org/wiki/Clean_URL#Slug) validation action. * * @param message The error message. * * @returns A slug action. */ export function slug< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): SlugAction; // @__NO_SIDE_EFFECTS__ export function slug( message?: ErrorMessage> ): SlugAction> | undefined> { return { kind: 'validation', type: 'slug', reference: slug, async: false, expects: null, requirement: SLUG_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'slug', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/someItem/index.ts ================================================ export * from './someItem.ts'; ================================================ FILE: library/src/actions/someItem/someItem.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { someItem, type SomeItemAction, type SomeItemIssue, } from './someItem.ts'; describe('someItem', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = SomeItemAction; expectTypeOf( someItem((item: string) => Boolean(item)) ).toEqualTypeOf(); expectTypeOf( someItem( (item: string) => Boolean(item), undefined ) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( someItem( (item: string) => Boolean(item), 'message' ) ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( someItem string>( (item: string) => Boolean(item), () => 'message' ) ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Input = ['foo', 123, true]; type Action = SomeItemAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/someItem/someItem.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { ArrayIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { someItem, type SomeItemAction, type SomeItemIssue, } from './someItem.ts'; describe('someItem', () => { describe('should return action object', () => { const requirement = (item: string) => item.startsWith('DE'); const baseAction: Omit, 'message'> = { kind: 'validation', type: 'some_item', reference: someItem, expects: null, requirement, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: SomeItemAction = { ...baseAction, message: undefined, }; expect(someItem(requirement)).toStrictEqual(action); expect( someItem(requirement, undefined) ).toStrictEqual(action); }); test('with string message', () => { const message = 'message'; expect(someItem(requirement, message)).toStrictEqual( { ...baseAction, message, } satisfies SomeItemAction ); }); test('with function message', () => { const message = () => 'message'; expect( someItem(requirement, message) ).toStrictEqual({ ...baseAction, message, } satisfies SomeItemAction); }); }); describe('should return dataset without issues', () => { const action = someItem((item: number) => item > 9); test('for untyped inputs', () => { const issues: [ArrayIssue] = [ { kind: 'schema', type: 'array', input: null, expected: 'Array', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid typed inputs', () => { expectNoActionIssue(action, [ [10], [-1, 10], [10, 11, 12], [1, 2, 3, 4, 99, 6], ]); }); }); describe('should return dataset with issues', () => { const requirement = (item: number) => item > 9; const action = someItem(requirement, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'some_item', expected: null, message: 'message', requirement, }; test('for empty array', () => { expectActionIssue(action, baseIssue, [[]]); }); test('for invalid typed inputs', () => { expectActionIssue(action, baseIssue, [ [9], [7, 8, 9], [-1, 0, 1, 2, 3, 4], ]); }); }); }); ================================================ FILE: library/src/actions/someItem/someItem.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; import type { ArrayInput, ArrayRequirement } from '../types.ts'; /** * Some item issue interface. */ export interface SomeItemIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'some_item'; /** * The expected property. */ readonly expected: null; /** * The validation function. */ readonly requirement: ArrayRequirement; } /** * Some item action interface. */ export interface SomeItemAction< TInput extends ArrayInput, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'some_item'; /** * The action reference. */ readonly reference: typeof someItem; /** * The expected property. */ readonly expects: null; /** * The validation function. */ readonly requirement: ArrayRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a some item validation action. * * @param requirement The validation function. * * @returns A some item action. */ export function someItem( requirement: ArrayRequirement ): SomeItemAction; /** * Creates a some item validation action. * * @param requirement The validation function. * @param message The error message. * * @returns A some item action. */ export function someItem< TInput extends ArrayInput, const TMessage extends ErrorMessage> | undefined, >( requirement: ArrayRequirement, message: TMessage ): SomeItemAction; // @__NO_SIDE_EFFECTS__ export function someItem( requirement: ArrayRequirement, message?: ErrorMessage> ): SomeItemAction< unknown[], ErrorMessage> | undefined > { return { kind: 'validation', type: 'some_item', reference: someItem, async: false, expects: null, requirement, message, '~run'(dataset, config) { if (dataset.typed && !dataset.value.some(this.requirement)) { _addIssue(this, 'item', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/sortItems/index.ts ================================================ export * from './sortItems.ts'; ================================================ FILE: library/src/actions/sortItems/sortItems.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { sortItems, type SortItemsAction } from './sortItems.ts'; describe('sortItems', () => { test('should return action object', () => { expectTypeOf( sortItems((itemA, itemB) => itemA > itemB ? 1 : itemA < itemB ? -1 : 0 ) ).toEqualTypeOf>(); }); describe('should infer correct types', () => { type Input = (string | number)[]; type Action = SortItemsAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/sortItems/sortItems.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { sortItems, type SortItemsAction } from './sortItems.ts'; describe('sortItems', () => { const operation = (itemA: number, itemB: number) => itemA > itemB ? 1 : itemA < itemB ? -1 : 0; const action = sortItems(operation); test('should return action object', () => { expect(action).toStrictEqual({ kind: 'transformation', type: 'sort_items', reference: sortItems, async: false, operation, '~run': expect.any(Function), } satisfies SortItemsAction); }); test('should transform input', () => { expect( action['~run']({ typed: true, value: [9, -12, 345, 0, 999] }, {}) ).toStrictEqual({ typed: true, value: [-12, 0, 9, 345, 999], }); }); }); ================================================ FILE: library/src/actions/sortItems/sortItems.ts ================================================ import type { BaseTransformation } from '../../types/index.ts'; import type { ArrayInput } from '../types.ts'; /** * Array action type. */ type ArrayAction = ( itemA: TInput[number], itemB: TInput[number] ) => number; /** * Sort items action interface. */ export interface SortItemsAction extends BaseTransformation { /** * The action type. */ readonly type: 'sort_items'; /** * The action reference. */ readonly reference: typeof sortItems; /** * The sort items operation. */ readonly operation: ArrayAction | undefined; } /** * Creates a sort items transformation action. * * @param operation The sort items operation. * * @returns A sort items action. */ export function sortItems( operation?: ArrayAction ): SortItemsAction; // @__NO_SIDE_EFFECTS__ export function sortItems( operation?: ArrayAction ): SortItemsAction { return { kind: 'transformation', type: 'sort_items', reference: sortItems, async: false, operation, '~run'(dataset) { dataset.value = dataset.value.sort(this.operation); return dataset; }, }; } ================================================ FILE: library/src/actions/startsWith/index.ts ================================================ export * from './startsWith.ts'; ================================================ FILE: library/src/actions/startsWith/startsWith.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { startsWith, type StartsWithAction, type StartsWithIssue, } from './startsWith.ts'; describe('startsWith', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = StartsWithAction; expectTypeOf(startsWith('foo')).toEqualTypeOf(); expectTypeOf( startsWith('foo', undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( startsWith('foo', 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( startsWith string>('foo', () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = StartsWithAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< StartsWithIssue >(); }); }); }); ================================================ FILE: library/src/actions/startsWith/startsWith.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { startsWith, type StartsWithAction, type StartsWithIssue, } from './startsWith.ts'; describe('startsWith', () => { describe('should return action object', () => { const baseAction: Omit< StartsWithAction, 'message' > = { kind: 'validation', type: 'starts_with', reference: startsWith, expects: '"abc"', requirement: 'abc', async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: StartsWithAction = { ...baseAction, message: undefined, }; expect(startsWith('abc')).toStrictEqual(action); expect(startsWith('abc', undefined)).toStrictEqual(action); }); test('with string message', () => { expect(startsWith('abc', 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies StartsWithAction); }); test('with function message', () => { const message = () => 'message'; expect(startsWith('abc', message)).toStrictEqual({ ...baseAction, message, } satisfies StartsWithAction); }); }); describe('should return dataset without issues', () => { const action = startsWith('abc'); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid inputs', () => { expectNoActionIssue(action, ['abc', 'abcdef', 'abc123', 'abc123def']); }); }); describe('should return dataset with issues', () => { const action = startsWith('abc', 'message'); const baseIssue: Omit< StartsWithIssue, 'input' | 'received' > = { kind: 'validation', type: 'starts_with', expected: '"abc"', message: 'message', requirement: 'abc', }; test('for invalid inputs', () => { expectActionIssue( action, baseIssue, [ '', 'a', 'ab', ' abc', 'Abc', 'a123', 'ab123', 'abdef', 'aabc', 'zabc', 'zabcdef', ], (value) => `"${value.slice(0, 'abc'.length)}"` ); }); }); }); ================================================ FILE: library/src/actions/startsWith/startsWith.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Starts with issue interface. */ export interface StartsWithIssue< TInput extends string, TRequirement extends string, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'starts_with'; /** * The expected property. */ readonly expected: `"${TRequirement}"`; /** * The received property. */ readonly received: `"${string}"`; /** * The start string. */ readonly requirement: TRequirement; } /** * Starts with action interface. */ export interface StartsWithAction< TInput extends string, TRequirement extends string, TMessage extends | ErrorMessage> | undefined, > extends BaseValidation< TInput, TInput, StartsWithIssue > { /** * The action type. */ readonly type: 'starts_with'; /** * The action reference. */ readonly reference: typeof startsWith; /** * The expected property. */ readonly expects: `"${TRequirement}"`; /** * The start string. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a starts with validation action. * * @param requirement The start string. * * @returns A starts with action. */ export function startsWith< TInput extends string, const TRequirement extends string, >(requirement: TRequirement): StartsWithAction; /** * Creates a starts with validation action. * * @param requirement The start string. * @param message The error message. * * @returns A starts with action. */ export function startsWith< TInput extends string, const TRequirement extends string, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): StartsWithAction; // @__NO_SIDE_EFFECTS__ export function startsWith( requirement: string, message?: ErrorMessage> ): StartsWithAction< string, string, ErrorMessage> | undefined > { return { kind: 'validation', type: 'starts_with', reference: startsWith, async: false, expects: `"${requirement}"`, requirement, message, '~run'(dataset, config) { if (dataset.typed && !dataset.value.startsWith(this.requirement)) { _addIssue(this, 'start', dataset, config, { received: `"${dataset.value.slice(0, this.requirement.length)}"`, }); } return dataset; }, }; } ================================================ FILE: library/src/actions/stringifyJson/index.ts ================================================ export * from './stringifyJson.ts'; ================================================ FILE: library/src/actions/stringifyJson/stringifyJson.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { stringifyJson, type StringifyJsonAction, type StringifyJsonConfig, type StringifyJsonIssue, } from './stringifyJson.ts'; describe('stringifyJson', () => { describe('should return action object', () => { const config: StringifyJsonConfig = { replacer: (key, value) => value, }; test('with undefined config and undefined message', () => { type Action = StringifyJsonAction; expectTypeOf(stringifyJson()).toEqualTypeOf(); expectTypeOf(stringifyJson(undefined)).toEqualTypeOf(); expectTypeOf(stringifyJson(undefined, undefined)).toEqualTypeOf(); }); test('with undefined config and string message', () => { expectTypeOf(stringifyJson(undefined, 'message')).toEqualTypeOf< StringifyJsonAction >(); }); test('with undefined config and function message', () => { expectTypeOf(stringifyJson(undefined, () => 'message')).toEqualTypeOf< StringifyJsonAction string> >(); }); test('with config and undefined message', () => { type Action = StringifyJsonAction< unknown, StringifyJsonConfig, undefined >; expectTypeOf(stringifyJson(config)).toEqualTypeOf(); expectTypeOf(stringifyJson(config, undefined)).toEqualTypeOf(); }); test('with config and string message', () => { expectTypeOf(stringifyJson(config, 'message')).toEqualTypeOf< StringifyJsonAction >(); }); test('with config and function message', () => { expectTypeOf(stringifyJson(config, () => 'message')).toEqualTypeOf< StringifyJsonAction string> >(); }); }); describe('should infer correct types', () => { // eslint-disable-next-line @typescript-eslint/consistent-type-definitions type Input = { foo: string }; type Action = StringifyJsonAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< StringifyJsonIssue >(); }); }); }); ================================================ FILE: library/src/actions/stringifyJson/stringifyJson.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { stringifyJson, type StringifyJsonAction, type StringifyJsonConfig, type StringifyJsonIssue, } from './stringifyJson.ts'; describe('stringifyJson', () => { describe('should return action object', () => { const config: StringifyJsonConfig = { replacer: (key, value) => value, }; const baseAction: Omit< StringifyJsonAction, 'message' | 'config' > = { kind: 'transformation', type: 'stringify_json', reference: stringifyJson, async: false, '~run': expect.any(Function), }; test('with undefined config and undefined message', () => { const action: StringifyJsonAction = { ...baseAction, config: undefined, message: undefined, }; expect(stringifyJson()).toStrictEqual(action); expect(stringifyJson(undefined)).toStrictEqual(action); expect(stringifyJson(undefined, undefined)).toStrictEqual(action); }); test('with undefined config and string message', () => { expect(stringifyJson(undefined, 'message')).toStrictEqual({ ...baseAction, config: undefined, message: 'message', } satisfies StringifyJsonAction); }); test('with undefined config and function message', () => { const message = () => 'message'; expect(stringifyJson(undefined, message)).toStrictEqual({ ...baseAction, config: undefined, message, } satisfies StringifyJsonAction string>); }); test('with config and undefined message', () => { const action: StringifyJsonAction< unknown, StringifyJsonConfig, undefined > = { ...baseAction, config, message: undefined, }; expect(stringifyJson(config)).toStrictEqual(action); expect(stringifyJson(config, undefined)).toStrictEqual(action); }); test('with config and string message', () => { expect(stringifyJson(config, 'message')).toStrictEqual({ ...baseAction, config, message: 'message', } satisfies StringifyJsonAction); }); test('with config and function message', () => { const message = () => 'message'; expect(stringifyJson(config, message)).toStrictEqual({ ...baseAction, config, message, } satisfies StringifyJsonAction< unknown, StringifyJsonConfig, () => string >); }); }); describe('should convert JSON date into JSON string', () => { test('without config', () => { expect( stringifyJson()['~run']({ typed: true, value: { foo: 'bar' } }, {}) ).toStrictEqual({ typed: true, value: '{"foo":"bar"}', }); }); test('with replacer', () => { expect( stringifyJson({ replacer: (key, value) => typeof value === 'string' ? value.toUpperCase() : value, })['~run']({ typed: true, value: { foo: 'bar' } }, {}) ).toStrictEqual({ typed: true, value: '{"foo":"BAR"}', }); }); test('with space', () => { expect( stringifyJson({ space: 2 })['~run']( { typed: true, value: { foo: 'bar' } }, {} ) ).toStrictEqual({ typed: true, value: '{\n "foo": "bar"\n}', }); }); test('for nested undefined', () => { expect( stringifyJson()['~run']({ typed: true, value: { foo: undefined } }, {}) ).toStrictEqual({ typed: true, value: '{}', }); }); test('for nested function', () => { expect( stringifyJson()['~run']({ typed: true, value: { foo: () => null } }, {}) ).toStrictEqual({ typed: true, value: '{}', }); }); }); describe('should return dataset with issues', () => { const action = stringifyJson(undefined, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'transformation', type: 'stringify_json', expected: null, message: 'message', requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for undefined input', () => { const input = undefined; expect(action['~run']({ typed: true, value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseIssue, input, received: 'undefined', }, ], }); }); test('for bigint input', () => { const input = 123n; expect(action['~run']({ typed: true, value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseIssue, input, received: '"Do not know how to serialize a BigInt"', }, ], }); }); test('for nested bigint', () => { const input = { foo: 123n }; expect(action['~run']({ typed: true, value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseIssue, input, received: '"Do not know how to serialize a BigInt"', }, ], }); }); test('for function input', () => { const input = () => null; expect(action['~run']({ typed: true, value: input }, {})).toStrictEqual({ typed: false, value: undefined, issues: [ { ...baseIssue, input, received: 'Function', }, ], }); }); test('for circular dependency', () => { const input = { foo: null as unknown }; input.foo = input; expect(action['~run']({ typed: true, value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseIssue, input, received: `"Converting circular structure to JSON\n --> starting at object with constructor 'Object'\n --- property 'foo' closes the circle"`, }, ], }); }); }); describe('should throw non-Error exceptions', () => { test('for non-Error thrown by replacer', () => { const action = stringifyJson({ replacer: () => { throw 'custom string error'; }, }); expect(() => action['~run']({ typed: true, value: { foo: 'bar' } }, {}) ).toThrow('custom string error'); }); }); }); ================================================ FILE: library/src/actions/stringifyJson/stringifyJson.ts ================================================ import type { BaseIssue, BaseTransformation, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * Stringify JSON config interface. * * @beta */ export interface StringifyJsonConfig { /** * The JSON replacer function or array. */ replacer?: // eslint-disable-next-line @typescript-eslint/no-explicit-any ((this: any, key: string, value: any) => any) | (number | string)[]; /** * The JSON space option. */ space?: string | number; } /** * Stringify JSON issue interface. * * @beta */ export interface StringifyJsonIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'transformation'; /** * The issue type. */ readonly type: 'stringify_json'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; } /** * Stringify JSON action interface. * * @beta */ export interface StringifyJsonAction< TInput, TConfig extends StringifyJsonConfig | undefined, TMessage extends ErrorMessage> | undefined, > extends BaseTransformation> { /** * The action type. */ readonly type: 'stringify_json'; /** * The action reference. */ readonly reference: typeof stringifyJson; /** * The action config. */ readonly config: TConfig; /** * The error message. */ readonly message: TMessage; } /** * Creates a stringify JSON transformation action. * * @returns A stringify JSON action. * * @beta */ export function stringifyJson(): StringifyJsonAction< TInput, undefined, undefined >; /** * Creates a stringify JSON transformation action. * * @param config The action config. * * @returns A stringify JSON action. * * @beta */ export function stringifyJson< TInput, const TConfig extends StringifyJsonConfig | undefined, >(config: TConfig): StringifyJsonAction; /** * Creates a stringify JSON transformation action. * * @param config The action config. * @param message The error message. * * @returns A stringify JSON action. * * @beta */ export function stringifyJson< TInput, const TConfig extends StringifyJsonConfig | undefined, const TMessage extends ErrorMessage> | undefined, >( config: TConfig, message: TMessage ): StringifyJsonAction; // @__NO_SIDE_EFFECTS__ export function stringifyJson( config?: StringifyJsonConfig, message?: ErrorMessage> ): StringifyJsonAction< unknown, StringifyJsonConfig | undefined, ErrorMessage> | undefined > { return { kind: 'transformation', type: 'stringify_json', reference: stringifyJson, message, config, async: false, '~run'(dataset, config) { try { const output = JSON.stringify( dataset.value, // @ts-expect-error this.config?.replacer, this.config?.space ); if (output === undefined) { _addIssue(this, 'JSON', dataset, config); // @ts-expect-error dataset.typed = false; } dataset.value = output; } catch (error) { if (error instanceof Error) { _addIssue(this, 'JSON', dataset, config, { received: `"${error.message}"`, }); // @ts-expect-error dataset.typed = false; } else { throw error; } } return dataset as OutputDataset>; }, }; } ================================================ FILE: library/src/actions/title/index.ts ================================================ export * from './title.ts'; ================================================ FILE: library/src/actions/title/title.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { title, type TitleAction } from './title.ts'; describe('title', () => { type Action = TitleAction; test('should return action object', () => { expectTypeOf(title('text')).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/title/title.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { title, type TitleAction } from './title.ts'; describe('title', () => { test('should return action object', () => { expect(title('text')).toStrictEqual({ kind: 'metadata', type: 'title', reference: title, title: 'text', } satisfies TitleAction); }); }); ================================================ FILE: library/src/actions/title/title.ts ================================================ import type { BaseMetadata } from '../../types/index.ts'; /** * Title action interface. */ export interface TitleAction extends BaseMetadata { /** * The action type. */ readonly type: 'title'; /** * The action reference. */ readonly reference: typeof title; /** * The title text. */ readonly title: TTitle; } /** * Creates a title metadata action. * * @param title_ The title text. * * @returns A title action. */ // @__NO_SIDE_EFFECTS__ export function title( title_: TTitle ): TitleAction { return { kind: 'metadata', type: 'title', reference: title, title: title_, }; } ================================================ FILE: library/src/actions/toBigint/index.ts ================================================ export * from './toBigint.ts'; ================================================ FILE: library/src/actions/toBigint/toBigint.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { toBigint, type ToBigintAction, type ToBigintIssue, } from './toBigint.ts'; describe('toBigint', () => { describe('should return action object', () => { test('without message', () => { expectTypeOf(toBigint()).toEqualTypeOf< ToBigintAction >(); }); test('with message', () => { expectTypeOf(toBigint('message')).toEqualTypeOf< ToBigintAction >(); }); }); describe('should infer correct types', () => { type Action = ToBigintAction<'123', undefined>; test('of input', () => { expectTypeOf>().toEqualTypeOf<'123'>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/toBigint/toBigint.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { toBigint, type ToBigintAction, type ToBigintIssue, } from './toBigint.ts'; describe('toBigint', () => { describe('should return action object', () => { test('without message', () => { expect(toBigint()).toStrictEqual({ kind: 'transformation', type: 'to_bigint', reference: toBigint, async: false, message: undefined, '~run': expect.any(Function), } satisfies ToBigintAction); }); test('with message', () => { expect(toBigint('message')).toStrictEqual({ kind: 'transformation', type: 'to_bigint', reference: toBigint, async: false, message: 'message', '~run': expect.any(Function), } satisfies ToBigintAction); }); }); describe('should transform to bigint', () => { const action = toBigint(); test('for string', () => { expect(action['~run']({ typed: true, value: '123' }, {})).toStrictEqual({ typed: true, value: 123n, }); }); test('for number', () => { expect(action['~run']({ typed: true, value: 123 }, {})).toStrictEqual({ typed: true, value: 123n, }); }); test('for bigint', () => { expect(action['~run']({ typed: true, value: 123n }, {})).toStrictEqual({ typed: true, value: 123n, }); }); test('for boolean', () => { expect(action['~run']({ typed: true, value: true }, {})).toStrictEqual({ typed: true, value: 1n, }); }); }); describe('should return dataset with issues', () => { const action = toBigint(); const baseIssue: Omit< ToBigintIssue, 'input' | 'received' | 'message' > = { kind: 'transformation', type: 'to_bigint', expected: null, requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; // Primitive types test('for null', () => { const value = null; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value, issues: [ { ...baseIssue, input: value, received: 'null', message: 'Invalid bigint: Received null', }, ], }); }); test('for numbers', () => { const value = 123.45; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value, issues: [ { ...baseIssue, input: value, received: '123.45', message: 'Invalid bigint: Received 123.45', }, ], }); }); test('for NaN', () => { const value = NaN; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value, issues: [ { ...baseIssue, input: value, received: 'NaN', message: 'Invalid bigint: Received NaN', }, ], }); }); test('for Infinity', () => { const value = Infinity; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value, issues: [ { ...baseIssue, input: value, received: 'Infinity', message: 'Invalid bigint: Received Infinity', }, ], }); }); test('for undefined', () => { const value = undefined; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value, issues: [ { ...baseIssue, input: value, received: 'undefined', message: 'Invalid bigint: Received undefined', }, ], }); }); test('for symbols', () => { const value = Symbol(); expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value, issues: [ { ...baseIssue, input: value, received: 'symbol', message: 'Invalid bigint: Received symbol', }, ], }); }); // Invalid strings test('for decimal strings', () => { const value = '123.45'; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value, issues: [ { ...baseIssue, input: value, received: '"123.45"', message: 'Invalid bigint: Received "123.45"', }, ], }); }); test('for invalid strings', () => { const value = 'abc'; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value, issues: [ { ...baseIssue, input: value, received: '"abc"', message: 'Invalid bigint: Received "abc"', }, ], }); }); // Complex types test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function const value = () => {}; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value, issues: [ { ...baseIssue, input: value, received: 'Function', message: 'Invalid bigint: Received Function', }, ], }); }); test('for objects', () => { const value = {}; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value, issues: [ { ...baseIssue, input: value, received: 'Object', message: 'Invalid bigint: Received Object', }, ], }); }); }); }); ================================================ FILE: library/src/actions/toBigint/toBigint.ts ================================================ import type { BaseIssue, BaseTransformation, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * To bigint issue interface. */ export interface ToBigintIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'transformation'; /** * The issue type. */ readonly type: 'to_bigint'; /** * The expected property. */ readonly expected: null; } /** * To bigint action interface. */ export interface ToBigintAction< TInput, TMessage extends ErrorMessage> | undefined, > extends BaseTransformation> { /** * The action type. */ readonly type: 'to_bigint'; /** * The action reference. */ readonly reference: typeof toBigint; /** * The error message. */ readonly message: TMessage; } /** * Creates a to bigint transformation action. * * @returns A to bigint action. * * @beta */ export function toBigint(): ToBigintAction; /** * Creates a to bigint transformation action. * * @param message The error message. * * @returns A to bigint action. * * @beta */ export function toBigint< TInput, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): ToBigintAction; // @__NO_SIDE_EFFECTS__ export function toBigint( message?: ErrorMessage> ): ToBigintAction> | undefined> { return { kind: 'transformation', type: 'to_bigint', reference: toBigint, async: false, message, '~run'(dataset, config) { try { // @ts-expect-error dataset.value = BigInt(dataset.value); } catch { _addIssue(this, 'bigint', dataset, config); // @ts-expect-error dataset.typed = false; } return dataset as OutputDataset>; }, }; } ================================================ FILE: library/src/actions/toBoolean/index.ts ================================================ export * from './toBoolean.ts'; ================================================ FILE: library/src/actions/toBoolean/toBoolean.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { toBoolean, type ToBooleanAction } from './toBoolean.ts'; describe('toBoolean', () => { test('should return action object', () => { expectTypeOf(toBoolean<'foo'>()).toEqualTypeOf>(); }); describe('should infer correct types', () => { type Action = ToBooleanAction<'foo'>; test('of input', () => { expectTypeOf>().toEqualTypeOf<'foo'>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/toBoolean/toBoolean.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { toBoolean, type ToBooleanAction } from './toBoolean.ts'; describe('toBoolean', () => { test('should return action object', () => { expect(toBoolean()).toStrictEqual({ kind: 'transformation', type: 'to_boolean', reference: toBoolean, async: false, '~run': expect.any(Function), } satisfies ToBooleanAction); }); describe('should transform to boolean', () => { const action = toBoolean(); // Falsy values test('for empty strings', () => { expect(action['~run']({ typed: true, value: '' }, {})).toStrictEqual({ typed: true, value: false, }); }); test('for zeros', () => { expect(action['~run']({ typed: true, value: 0 }, {})).toStrictEqual({ typed: true, value: false, }); expect(action['~run']({ typed: true, value: -0 }, {})).toStrictEqual({ typed: true, value: false, }); expect(action['~run']({ typed: true, value: 0n }, {})).toStrictEqual({ typed: true, value: false, }); }); test('for NaN numbers', () => { expect(action['~run']({ typed: true, value: NaN }, {})).toStrictEqual({ typed: true, value: false, }); }); test('for false booleans', () => { expect(action['~run']({ typed: true, value: false }, {})).toStrictEqual({ typed: true, value: false, }); }); test('for null', () => { expect(action['~run']({ typed: true, value: null }, {})).toStrictEqual({ typed: true, value: false, }); }); test('for undefined', () => { expect( action['~run']({ typed: true, value: undefined }, {}) ).toStrictEqual({ typed: true, value: false, }); }); // Truthy values test('for non-empty strings', () => { expect(action['~run']({ typed: true, value: 'foo' }, {})).toStrictEqual({ typed: true, value: true, }); expect(action['~run']({ typed: true, value: '0' }, {})).toStrictEqual({ typed: true, value: true, }); expect(action['~run']({ typed: true, value: 'false' }, {})).toStrictEqual( { typed: true, value: true, } ); }); test('for non-zero numbers', () => { expect(action['~run']({ typed: true, value: 1 }, {})).toStrictEqual({ typed: true, value: true, }); expect(action['~run']({ typed: true, value: -1 }, {})).toStrictEqual({ typed: true, value: true, }); expect( action['~run']({ typed: true, value: Infinity }, {}) ).toStrictEqual({ typed: true, value: true, }); expect( action['~run']({ typed: true, value: -Infinity }, {}) ).toStrictEqual({ typed: true, value: true, }); }); test('for non-zero bigints', () => { expect(action['~run']({ typed: true, value: 1n }, {})).toStrictEqual({ typed: true, value: true, }); expect(action['~run']({ typed: true, value: -1n }, {})).toStrictEqual({ typed: true, value: true, }); }); test('for true booleans', () => { expect(action['~run']({ typed: true, value: true }, {})).toStrictEqual({ typed: true, value: true, }); }); test('for symbols', () => { expect( action['~run']({ typed: true, value: Symbol() }, {}) ).toStrictEqual({ typed: true, value: true, }); expect( action['~run']({ typed: true, value: Symbol('foo') }, {}) ).toStrictEqual({ typed: true, value: true, }); }); test('for arrays', () => { expect(action['~run']({ typed: true, value: [] }, {})).toStrictEqual({ typed: true, value: true, }); expect(action['~run']({ typed: true, value: [0] }, {})).toStrictEqual({ typed: true, value: true, }); expect(action['~run']({ typed: true, value: ['foo'] }, {})).toStrictEqual( { typed: true, value: true, } ); }); test('for functions', () => { expect( action['~run']( { typed: true, // eslint-disable-next-line @typescript-eslint/no-empty-function value: () => {}, }, {} ) ).toStrictEqual({ typed: true, value: true, }); expect( action['~run']( { typed: true, value: // eslint-disable-next-line @typescript-eslint/no-empty-function function () {}, }, {} ) ).toStrictEqual({ typed: true, value: true, }); }); test('for objects', () => { expect(action['~run']({ typed: true, value: {} }, {})).toStrictEqual({ typed: true, value: true, }); expect( action['~run']({ typed: true, value: { key: 'value' } }, {}) ).toStrictEqual({ typed: true, value: true, }); }); }); }); ================================================ FILE: library/src/actions/toBoolean/toBoolean.ts ================================================ import type { BaseTransformation, SuccessDataset } from '../../types/index.ts'; /** * To boolean action interface. */ export interface ToBooleanAction extends BaseTransformation { /** * The action type. */ readonly type: 'to_boolean'; /** * The action reference. */ readonly reference: typeof toBoolean; } /** * Creates a to boolean transformation action. * * @returns A to boolean action. * * @beta */ // @__NO_SIDE_EFFECTS__ export function toBoolean(): ToBooleanAction { return { kind: 'transformation', type: 'to_boolean', reference: toBoolean, async: false, '~run'(dataset) { // @ts-expect-error dataset.value = Boolean(dataset.value); return dataset as SuccessDataset; }, }; } ================================================ FILE: library/src/actions/toDate/index.ts ================================================ export * from './toDate.ts'; ================================================ FILE: library/src/actions/toDate/toDate.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { toDate, type ToDateAction, type ToDateIssue } from './toDate.ts'; describe('toDate', () => { test('should return action object', () => { expectTypeOf(toDate<'123'>()).toEqualTypeOf< ToDateAction<'123', undefined> >(); }); describe('should infer correct types', () => { type Action = ToDateAction<'123', undefined>; test('of input', () => { expectTypeOf>().toEqualTypeOf<'123'>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/toDate/toDate.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { toDate, type ToDateAction, type ToDateIssue } from './toDate.ts'; describe('toDate', () => { describe('should return action object', () => { test('without message', () => { expect(toDate()).toStrictEqual({ kind: 'transformation', type: 'to_date', reference: toDate, async: false, message: undefined, '~run': expect.any(Function), } satisfies ToDateAction); }); test('with message', () => { expect(toDate('message')).toStrictEqual({ kind: 'transformation', type: 'to_date', reference: toDate, async: false, message: 'message', '~run': expect.any(Function), } satisfies ToDateAction); }); }); describe('should transform to date', () => { const action = toDate(); test('for string', () => { expect( action['~run']({ typed: true, value: '2024-05-06' }, {}) ).toStrictEqual({ typed: true, value: expect.any(Date), }); }); test('for number', () => { expect( action['~run']({ typed: true, value: 1714924800000 }, {}) ).toStrictEqual({ typed: true, value: expect.any(Date), }); }); test('for date', () => { const date = new Date(); expect(action['~run']({ typed: true, value: date }, {})).toStrictEqual({ typed: true, value: date, }); }); }); describe('should return dataset with issues', () => { const action = toDate(); const invalidDate = new Date('invalid'); const baseIssue: Omit< ToDateIssue, 'input' | 'received' | 'message' > = { kind: 'transformation', type: 'to_date', expected: null, requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; // Primitive types test('for bigints', () => { const value = 123n; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value, issues: [ { ...baseIssue, input: value, received: '123', message: 'Invalid date: Received 123', }, ], }); }); test('for symbols', () => { const value = Symbol(); expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value, issues: [ { ...baseIssue, input: value, received: 'symbol', message: 'Invalid date: Received symbol', }, ], }); }); // Invalid strings test('for invalid date strings', () => { const value = 'invalid'; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value: invalidDate, issues: [ { ...baseIssue, input: invalidDate, received: '"Invalid Date"', message: 'Invalid date: Received "Invalid Date"', }, ], }); }); // Complex types test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function const value = () => {}; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value: invalidDate, issues: [ { ...baseIssue, input: invalidDate, received: '"Invalid Date"', message: 'Invalid date: Received "Invalid Date"', }, ], }); }); test('for objects', () => { const value = {}; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value: invalidDate, issues: [ { ...baseIssue, input: invalidDate, received: '"Invalid Date"', message: 'Invalid date: Received "Invalid Date"', }, ], }); }); }); }); ================================================ FILE: library/src/actions/toDate/toDate.ts ================================================ import type { BaseIssue, BaseTransformation, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * To date issue interface. */ export interface ToDateIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'transformation'; /** * The issue type. */ readonly type: 'to_date'; /** * The expected property. */ readonly expected: null; } /** * To date action interface. */ export interface ToDateAction< TInput, TMessage extends ErrorMessage> | undefined, > extends BaseTransformation> { /** * The action type. */ readonly type: 'to_date'; /** * The action reference. */ readonly reference: typeof toDate; /** * The error message. */ readonly message: TMessage; } /** * Creates a to date transformation action. * * @returns A to date action. * * @beta */ export function toDate(): ToDateAction; /** * Creates a to date transformation action. * * @param message The error message. * * @returns A to date action. * * @beta */ export function toDate< TInput, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): ToDateAction; // @__NO_SIDE_EFFECTS__ export function toDate( message?: ErrorMessage> ): ToDateAction> | undefined> { return { kind: 'transformation', type: 'to_date', reference: toDate, async: false, message, '~run'(dataset, config) { try { // @ts-expect-error dataset.value = new Date(dataset.value); // @ts-expect-error if (isNaN(dataset.value)) { _addIssue(this, 'date', dataset, config, { received: '"Invalid Date"', }); // @ts-expect-error dataset.typed = false; } } catch { _addIssue(this, 'date', dataset, config); // @ts-expect-error dataset.typed = false; } return dataset as OutputDataset>; }, }; } ================================================ FILE: library/src/actions/toLowerCase/index.ts ================================================ export * from './toLowerCase.ts'; ================================================ FILE: library/src/actions/toLowerCase/toLowerCase.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { toLowerCase, type ToLowerCaseAction } from './toLowerCase.ts'; describe('toLowerCase', () => { test('should return action object', () => { expectTypeOf(toLowerCase()).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/toLowerCase/toLowerCase.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { toLowerCase, type ToLowerCaseAction } from './toLowerCase.ts'; describe('toLowerCase', () => { test('should return action object', () => { expect(toLowerCase()).toStrictEqual({ kind: 'transformation', type: 'to_lower_case', reference: toLowerCase, async: false, '~run': expect.any(Function), } satisfies ToLowerCaseAction); }); describe('should lower case string', () => { const action = toLowerCase(); test('for string', () => { expect( action['~run']({ typed: true, value: ' TeSt123 ' }, {}) ).toStrictEqual({ typed: true, value: ' test123 ', }); }); }); }); ================================================ FILE: library/src/actions/toLowerCase/toLowerCase.ts ================================================ import type { BaseTransformation } from '../../types/index.ts'; /** * To lower case action interface. */ export interface ToLowerCaseAction extends BaseTransformation { /** * The action type. */ readonly type: 'to_lower_case'; /** * The action reference. */ readonly reference: typeof toLowerCase; } /** * Creates a to lower case transformation action. * * @returns A to lower case action. */ // @__NO_SIDE_EFFECTS__ export function toLowerCase(): ToLowerCaseAction { return { kind: 'transformation', type: 'to_lower_case', reference: toLowerCase, async: false, '~run'(dataset) { dataset.value = dataset.value.toLowerCase(); return dataset; }, }; } ================================================ FILE: library/src/actions/toMaxValue/index.ts ================================================ export * from './toMaxValue.ts'; ================================================ FILE: library/src/actions/toMaxValue/toMaxValue.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/infer.ts'; import { toMaxValue, type ToMaxValueAction } from './toMaxValue.ts'; describe('toMaxValue', () => { test('should return action object', () => { expectTypeOf(toMaxValue(10)).toEqualTypeOf< ToMaxValueAction >(); }); describe('should infer correct types', () => { type Action = ToMaxValueAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/toMaxValue/toMaxValue.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { toMaxValue, type ToMaxValueAction } from './toMaxValue.ts'; describe('toMaxValue', () => { const action = toMaxValue(10); test('should return action object', () => { expect(action).toStrictEqual({ kind: 'transformation', type: 'to_max_value', reference: toMaxValue, requirement: 10, async: false, '~run': expect.any(Function), } satisfies ToMaxValueAction); }); test('should transform to max value', () => { const outputDataset = { typed: true, value: 10 }; expect(action['~run']({ typed: true, value: 10 }, {})).toStrictEqual( outputDataset ); expect(action['~run']({ typed: true, value: 11 }, {})).toStrictEqual( outputDataset ); expect( action['~run']({ typed: true, value: Number.MAX_VALUE }, {}) ).toStrictEqual(outputDataset); }); test('should not transform value', () => { expect( action['~run']({ typed: true, value: Number.MIN_VALUE }, {}) ).toStrictEqual({ typed: true, value: Number.MIN_VALUE, }); expect(action['~run']({ typed: true, value: 0 }, {})).toStrictEqual({ typed: true, value: 0, }); expect(action['~run']({ typed: true, value: 9 }, {})).toStrictEqual({ typed: true, value: 9, }); }); }); ================================================ FILE: library/src/actions/toMaxValue/toMaxValue.ts ================================================ import type { BaseTransformation } from '../../types/index.ts'; import type { ValueInput } from '../types.ts'; /** * To max value action interface. */ export interface ToMaxValueAction< TInput extends ValueInput, TRequirement extends TInput, > extends BaseTransformation { /** * The action type. */ readonly type: 'to_max_value'; /** * The action reference. */ readonly reference: typeof toMaxValue; /** * The maximum value. */ readonly requirement: TRequirement; } /** * Creates a to max value transformation action. * * @param requirement The maximum value. * * @returns A to max value action. */ // @__NO_SIDE_EFFECTS__ export function toMaxValue< TInput extends ValueInput, const TRequirement extends TInput, >(requirement: TRequirement): ToMaxValueAction { return { kind: 'transformation', type: 'to_max_value', reference: toMaxValue, async: false, requirement, '~run'(dataset) { dataset.value = dataset.value > this.requirement ? this.requirement : dataset.value; return dataset; }, }; } ================================================ FILE: library/src/actions/toMinValue/index.ts ================================================ export * from './toMinValue.ts'; ================================================ FILE: library/src/actions/toMinValue/toMinValue.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/infer.ts'; import { toMinValue, type ToMinValueAction } from './toMinValue.ts'; describe('toMinValue', () => { test('should return action object', () => { expectTypeOf(toMinValue(10)).toEqualTypeOf< ToMinValueAction >(); }); describe('should infer correct types', () => { type Action = ToMinValueAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/toMinValue/toMinValue.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { toMinValue, type ToMinValueAction } from './toMinValue.ts'; describe('toMinValue', () => { const action = toMinValue(10); test('should return action object', () => { expect(action).toStrictEqual({ kind: 'transformation', type: 'to_min_value', reference: toMinValue, requirement: 10, async: false, '~run': expect.any(Function), } satisfies ToMinValueAction); }); test('should transform to min value', () => { const outputDataset = { typed: true, value: 10 }; expect(action['~run']({ typed: true, value: 9 }, {})).toStrictEqual( outputDataset ); expect(action['~run']({ typed: true, value: 0 }, {})).toStrictEqual( outputDataset ); expect( action['~run']({ typed: true, value: Number.MIN_VALUE }, {}) ).toStrictEqual(outputDataset); }); test('should not transform value', () => { expect(action['~run']({ typed: true, value: 10 }, {})).toStrictEqual({ typed: true, value: 10, }); expect(action['~run']({ typed: true, value: 11 }, {})).toStrictEqual({ typed: true, value: 11, }); expect( action['~run']({ typed: true, value: Number.MAX_VALUE }, {}) ).toStrictEqual({ typed: true, value: Number.MAX_VALUE, }); }); }); ================================================ FILE: library/src/actions/toMinValue/toMinValue.ts ================================================ import type { BaseTransformation } from '../../types/index.ts'; import type { ValueInput } from '../types.ts'; /** * To min value action interface. */ export interface ToMinValueAction< TInput extends ValueInput, TRequirement extends TInput, > extends BaseTransformation { /** * The action type. */ readonly type: 'to_min_value'; /** * The action reference. */ readonly reference: typeof toMinValue; /** * The minimum value. */ readonly requirement: TRequirement; } /** * Creates a to min value transformation action. * * @param requirement The minimum value. * * @returns A to min value action. */ // @__NO_SIDE_EFFECTS__ export function toMinValue< TInput extends ValueInput, const TRequirement extends TInput, >(requirement: TRequirement): ToMinValueAction { return { kind: 'transformation', type: 'to_min_value', reference: toMinValue, async: false, requirement, '~run'(dataset) { dataset.value = dataset.value < this.requirement ? this.requirement : dataset.value; return dataset; }, }; } ================================================ FILE: library/src/actions/toNumber/index.ts ================================================ export * from './toNumber.ts'; ================================================ FILE: library/src/actions/toNumber/toNumber.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { toNumber, type ToNumberAction, type ToNumberIssue, } from './toNumber.ts'; describe('toNumber', () => { test('should return action object', () => { expectTypeOf(toNumber<'123'>()).toEqualTypeOf< ToNumberAction<'123', undefined> >(); }); describe('should infer correct types', () => { type Action = ToNumberAction<'123', undefined>; test('of input', () => { expectTypeOf>().toEqualTypeOf<'123'>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/toNumber/toNumber.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { toNumber, type ToNumberAction, type ToNumberIssue, } from './toNumber.ts'; describe('toNumber', () => { describe('should return action object', () => { test('without message', () => { expect(toNumber()).toStrictEqual({ kind: 'transformation', type: 'to_number', reference: toNumber, async: false, message: undefined, '~run': expect.any(Function), } satisfies ToNumberAction); }); test('with message', () => { expect(toNumber('message')).toStrictEqual({ kind: 'transformation', type: 'to_number', reference: toNumber, async: false, message: 'message', '~run': expect.any(Function), } satisfies ToNumberAction); }); }); describe('should transform to number', () => { const action = toNumber(); test('for string', () => { expect(action['~run']({ typed: true, value: '123' }, {})).toStrictEqual({ typed: true, value: 123, }); }); test('for number', () => { expect(action['~run']({ typed: true, value: 123 }, {})).toStrictEqual({ typed: true, value: 123, }); }); test('for bigint', () => { expect(action['~run']({ typed: true, value: 123n }, {})).toStrictEqual({ typed: true, value: 123, }); }); test('for boolean', () => { expect(action['~run']({ typed: true, value: true }, {})).toStrictEqual({ typed: true, value: 1, }); }); test('for null', () => { expect(action['~run']({ typed: true, value: null }, {})).toStrictEqual({ typed: true, value: 0, }); }); }); describe('should return dataset with issues', () => { const action = toNumber(); const baseIssue: Omit< ToNumberIssue, 'input' | 'received' | 'message' > = { kind: 'transformation', type: 'to_number', expected: null, requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; // Primitive types test('for undefined', () => { const value = undefined; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value: NaN, issues: [ { ...baseIssue, input: NaN, received: 'NaN', message: 'Invalid number: Received NaN', }, ], }); }); test('for symbols', () => { const value = Symbol(); expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value, issues: [ { ...baseIssue, input: value, received: 'symbol', message: 'Invalid number: Received symbol', }, ], }); }); // Invalid strings test('for invalid strings', () => { const value = 'abc'; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value: NaN, issues: [ { ...baseIssue, input: NaN, received: 'NaN', message: 'Invalid number: Received NaN', }, ], }); }); test('for partially numeric strings', () => { const value = '123abc'; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value: NaN, issues: [ { ...baseIssue, input: NaN, received: 'NaN', message: 'Invalid number: Received NaN', }, ], }); }); // Complex types test('for arrays with multiple elements', () => { const value = [1, 2]; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value: NaN, issues: [ { ...baseIssue, input: NaN, received: 'NaN', message: 'Invalid number: Received NaN', }, ], }); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function const value = () => {}; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value: NaN, issues: [ { ...baseIssue, input: NaN, received: 'NaN', message: 'Invalid number: Received NaN', }, ], }); }); test('for objects', () => { const value = {}; expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value: NaN, issues: [ { ...baseIssue, input: NaN, received: 'NaN', message: 'Invalid number: Received NaN', }, ], }); }); test('for invalid dates', () => { const value = new Date('invalid'); expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: false, value: NaN, issues: [ { ...baseIssue, input: NaN, received: 'NaN', message: 'Invalid number: Received NaN', }, ], }); }); }); }); ================================================ FILE: library/src/actions/toNumber/toNumber.ts ================================================ import type { BaseIssue, BaseTransformation, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * To number issue interface. */ export interface ToNumberIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'transformation'; /** * The issue type. */ readonly type: 'to_number'; /** * The expected property. */ readonly expected: null; } /** * To number action interface. */ export interface ToNumberAction< TInput, TMessage extends ErrorMessage> | undefined, > extends BaseTransformation> { /** * The action type. */ readonly type: 'to_number'; /** * The action reference. */ readonly reference: typeof toNumber; /** * The error message. */ readonly message: TMessage; } /** * Creates a to number transformation action. * * @returns A to number action. * * @beta */ export function toNumber(): ToNumberAction; /** * Creates a to number transformation action. * * @param message The error message. * * @returns A to number action. * * @beta */ export function toNumber< TInput, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): ToNumberAction; // @__NO_SIDE_EFFECTS__ export function toNumber( message?: ErrorMessage> ): ToNumberAction> | undefined> { return { kind: 'transformation', type: 'to_number', reference: toNumber, async: false, message, '~run'(dataset, config) { try { dataset.value = Number(dataset.value); // @ts-expect-error if (isNaN(dataset.value)) { _addIssue(this, 'number', dataset, config); // @ts-expect-error dataset.typed = false; } } catch { _addIssue(this, 'number', dataset, config); // @ts-expect-error dataset.typed = false; } return dataset as OutputDataset>; }, }; } ================================================ FILE: library/src/actions/toString/index.ts ================================================ export * from './toString.ts'; ================================================ FILE: library/src/actions/toString/toString.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { toString, type ToStringAction, type ToStringIssue, } from './toString.ts'; describe('toString', () => { test('should return action object', () => { expectTypeOf(toString<'foo'>()).toEqualTypeOf< ToStringAction<'foo', undefined> >(); }); describe('should infer correct types', () => { type Action = ToStringAction<'foo', undefined>; test('of input', () => { expectTypeOf>().toEqualTypeOf<'foo'>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/toString/toString.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { toString, type ToStringAction, type ToStringIssue, } from './toString.ts'; describe('toString', () => { describe('should return action object', () => { test('without message', () => { expect(toString()).toStrictEqual({ kind: 'transformation', type: 'to_string', reference: toString, async: false, message: undefined, '~run': expect.any(Function), } satisfies ToStringAction); }); test('with message', () => { expect(toString('message')).toStrictEqual({ kind: 'transformation', type: 'to_string', reference: toString, async: false, message: 'message', '~run': expect.any(Function), } satisfies ToStringAction); }); }); describe('should transform to string', () => { const action = toString(); test('for string', () => { expect(action['~run']({ typed: true, value: 'foo' }, {})).toStrictEqual({ typed: true, value: 'foo', }); }); test('for number', () => { expect(action['~run']({ typed: true, value: 123 }, {})).toStrictEqual({ typed: true, value: '123', }); }); test('for bigint', () => { expect(action['~run']({ typed: true, value: 123n }, {})).toStrictEqual({ typed: true, value: '123', }); }); test('for boolean', () => { expect(action['~run']({ typed: true, value: true }, {})).toStrictEqual({ typed: true, value: 'true', }); }); test('for null', () => { expect(action['~run']({ typed: true, value: null }, {})).toStrictEqual({ typed: true, value: 'null', }); }); test('for undefined', () => { expect( action['~run']({ typed: true, value: undefined }, {}) ).toStrictEqual({ typed: true, value: 'undefined', }); }); test('for symbol', () => { expect( action['~run']({ typed: true, value: Symbol('foo') }, {}) ).toStrictEqual({ typed: true, value: 'Symbol(foo)', }); }); }); describe('should return dataset with issues', () => { const action = toString(); const baseIssue: Omit< ToStringIssue, 'input' | 'received' | 'message' > = { kind: 'transformation', type: 'to_string', expected: null, requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for objects with faulty toString', () => { const faultyToString = { toString() { throw new Error('oops'); }, }; expect( action['~run']({ typed: true, value: faultyToString }, {}) ).toStrictEqual({ typed: false, value: faultyToString, issues: [ { ...baseIssue, input: faultyToString, received: 'Object', message: 'Invalid string: Received Object', }, ], }); }); }); }); ================================================ FILE: library/src/actions/toString/toString.ts ================================================ import type { BaseIssue, BaseTransformation, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * To string issue interface. */ export interface ToStringIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'transformation'; /** * The issue type. */ readonly type: 'to_string'; /** * The expected property. */ readonly expected: null; } /** * To string action interface. */ export interface ToStringAction< TInput, TMessage extends ErrorMessage> | undefined, > extends BaseTransformation> { /** * The action type. */ readonly type: 'to_string'; /** * The action reference. */ readonly reference: typeof toString; /** * The error message. */ readonly message: TMessage; } /** * Creates a to string transformation action. * * @returns A to string action. * * @beta */ export function toString(): ToStringAction; /** * Creates a to string transformation action. * * @param message The error message. * * @returns A to string action. * * @beta */ export function toString< TInput, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): ToStringAction; // @__NO_SIDE_EFFECTS__ export function toString( message?: ErrorMessage> ): ToStringAction> | undefined> { return { kind: 'transformation', type: 'to_string', reference: toString, async: false, message, '~run'(dataset, config) { try { dataset.value = String(dataset.value); } catch { _addIssue(this, 'string', dataset, config); // @ts-expect-error dataset.typed = false; } return dataset as OutputDataset>; }, }; } ================================================ FILE: library/src/actions/toUpperCase/index.ts ================================================ export * from './toUpperCase.ts'; ================================================ FILE: library/src/actions/toUpperCase/toUpperCase.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { toUpperCase, type ToUpperCaseAction } from './toUpperCase.ts'; describe('toUpperCase', () => { test('should return action object', () => { expectTypeOf(toUpperCase()).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/toUpperCase/toUpperCase.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { toUpperCase, type ToUpperCaseAction } from './toUpperCase.ts'; describe('toUpperCase', () => { test('should return action object', () => { expect(toUpperCase()).toStrictEqual({ kind: 'transformation', type: 'to_upper_case', reference: toUpperCase, async: false, '~run': expect.any(Function), } satisfies ToUpperCaseAction); }); describe('should upper case string', () => { const action = toUpperCase(); test('for string', () => { expect( action['~run']({ typed: true, value: ' TeSt123 ' }, {}) ).toStrictEqual({ typed: true, value: ' TEST123 ', }); }); }); }); ================================================ FILE: library/src/actions/toUpperCase/toUpperCase.ts ================================================ import type { BaseTransformation } from '../../types/index.ts'; /** * To upper case action interface. */ export interface ToUpperCaseAction extends BaseTransformation { /** * The action type. */ readonly type: 'to_upper_case'; /** * The action reference. */ readonly reference: typeof toUpperCase; } /** * Creates a to upper case transformation action. * * @returns A to upper case action. */ // @__NO_SIDE_EFFECTS__ export function toUpperCase(): ToUpperCaseAction { return { kind: 'transformation', type: 'to_upper_case', reference: toUpperCase, async: false, '~run'(dataset) { dataset.value = dataset.value.toUpperCase(); return dataset; }, }; } ================================================ FILE: library/src/actions/transform/index.ts ================================================ export * from './transform.ts'; export * from './transformAsync.ts'; ================================================ FILE: library/src/actions/transform/transform.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { transform, type TransformAction } from './transform.ts'; describe('transform', () => { type Action = TransformAction; test('should return action object', () => { expectTypeOf( transform((value: string) => value.length) ).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/transform/transform.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { transform, type TransformAction } from './transform.ts'; describe('transform', () => { test('should return action object', () => { const operation = (input: string) => input.length; const action = transform(operation); expect(action).toStrictEqual({ kind: 'transformation', type: 'transform', reference: transform, async: false, operation, '~run': expect.any(Function), } satisfies TransformAction); }); describe('should transform input', () => { test('to length of string', () => { const action = transform((input: string) => input.length); expect( action['~run']({ typed: true, value: '123456' }, {}) ).toStrictEqual({ typed: true, value: 6, }); }); test('to object with new key', () => { const action = transform((input: { key1: string }) => ({ ...input, key2: 123, })); expect( action['~run']({ typed: true, value: { key1: 'foo' } }, {}) ).toStrictEqual({ typed: true, value: { key1: 'foo', key2: 123 }, }); }); }); }); ================================================ FILE: library/src/actions/transform/transform.ts ================================================ import type { BaseTransformation, SuccessDataset } from '../../types/index.ts'; /** * Transform action interface. */ export interface TransformAction extends BaseTransformation { /** * The action type. */ readonly type: 'transform'; /** * The action reference. */ readonly reference: typeof transform; /** * The transformation operation. */ readonly operation: (input: TInput) => TOutput; } /** * Creates a custom transformation action. * * @param operation The transformation operation. * * @returns A transform action. */ // @__NO_SIDE_EFFECTS__ export function transform( operation: (input: TInput) => TOutput ): TransformAction { return { kind: 'transformation', type: 'transform', reference: transform, async: false, operation, '~run'(dataset) { // @ts-expect-error dataset.value = this.operation(dataset.value); // @ts-expect-error return dataset as SuccessDataset; }, }; } ================================================ FILE: library/src/actions/transform/transformAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { type TransformActionAsync, transformAsync } from './transformAsync.ts'; describe('transformAsync', () => { type Action = TransformActionAsync; test('should return action object', () => { expectTypeOf( transformAsync(async (value: string) => value.length) ).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/transform/transformAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { type TransformActionAsync, transformAsync } from './transformAsync.ts'; describe('transformAsync', () => { test('should return action object', () => { const operation = async (input: string) => input.length; const action = transformAsync(operation); expect(action).toStrictEqual({ kind: 'transformation', type: 'transform', reference: transformAsync, async: true, operation, '~run': expect.any(Function), } satisfies TransformActionAsync); }); describe('should transform input', () => { test('to length of string', async () => { const action = transformAsync(async (input: string) => input.length); expect( await action['~run']({ typed: true, value: '123456' }, {}) ).toStrictEqual({ typed: true, value: 6, }); }); test('to object with new key', async () => { const action = transformAsync(async (input: { key1: string }) => ({ ...input, key2: 123, })); expect( await action['~run']({ typed: true, value: { key1: 'foo' } }, {}) ).toStrictEqual({ typed: true, value: { key1: 'foo', key2: 123 }, }); }); }); }); ================================================ FILE: library/src/actions/transform/transformAsync.ts ================================================ import type { BaseTransformationAsync, SuccessDataset, } from '../../types/index.ts'; /** * Transform action async interface. */ export interface TransformActionAsync extends BaseTransformationAsync { /** * The action type. */ readonly type: 'transform'; /** * The action reference. */ readonly reference: typeof transformAsync; /** * The transformation operation. */ readonly operation: (input: TInput) => Promise; } /** * Creates a custom transformation action. * * @param operation The transformation operation. * * @returns A transform action. */ // @__NO_SIDE_EFFECTS__ export function transformAsync( operation: (input: TInput) => Promise ): TransformActionAsync { return { kind: 'transformation', type: 'transform', reference: transformAsync, async: true, operation, async '~run'(dataset) { // @ts-expect-error dataset.value = await this.operation(dataset.value); // @ts-expect-error return dataset as SuccessDataset; }, }; } ================================================ FILE: library/src/actions/trim/index.ts ================================================ export * from './trim.ts'; ================================================ FILE: library/src/actions/trim/trim.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { trim, type TrimAction } from './trim.ts'; describe('trim', () => { test('should return action object', () => { expectTypeOf(trim()).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/trim/trim.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { trim, type TrimAction } from './trim.ts'; describe('trim', () => { test('should return action object', () => { expect(trim()).toStrictEqual({ kind: 'transformation', type: 'trim', reference: trim, async: false, '~run': expect.any(Function), } satisfies TrimAction); }); describe('should trim string', () => { const action = trim(); test('for empty string', () => { expect(action['~run']({ typed: true, value: '' }, {})).toStrictEqual({ typed: true, value: '', }); expect(action['~run']({ typed: true, value: ' ' }, {})).toStrictEqual({ typed: true, value: '', }); }); test('with blanks at start', () => { expect(action['~run']({ typed: true, value: ' foo' }, {})).toStrictEqual( { typed: true, value: 'foo', } ); }); test('with blanks at end', () => { expect(action['~run']({ typed: true, value: 'foo ' }, {})).toStrictEqual( { typed: true, value: 'foo', } ); }); test('with blanks at start and end', () => { expect( action['~run']({ typed: true, value: ' foo ' }, {}) ).toStrictEqual({ typed: true, value: 'foo', }); }); }); }); ================================================ FILE: library/src/actions/trim/trim.ts ================================================ import type { BaseTransformation } from '../../types/index.ts'; /** * Trim action interface. */ export interface TrimAction extends BaseTransformation { /** * The action type. */ readonly type: 'trim'; /** * The action reference. */ readonly reference: typeof trim; } /** * Creates a trim transformation action. * * @returns A trim action. */ // @__NO_SIDE_EFFECTS__ export function trim(): TrimAction { return { kind: 'transformation', type: 'trim', reference: trim, async: false, '~run'(dataset) { dataset.value = dataset.value.trim(); return dataset; }, }; } ================================================ FILE: library/src/actions/trimEnd/index.ts ================================================ export * from './trimEnd.ts'; ================================================ FILE: library/src/actions/trimEnd/trimEnd.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { trimEnd, type TrimEndAction } from './trimEnd.ts'; describe('trim', () => { test('should return action object', () => { expectTypeOf(trimEnd()).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/trimEnd/trimEnd.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { trimEnd, type TrimEndAction } from './trimEnd.ts'; describe('trimEnd', () => { test('should return action object', () => { expect(trimEnd()).toStrictEqual({ kind: 'transformation', type: 'trim_end', reference: trimEnd, async: false, '~run': expect.any(Function), } satisfies TrimEndAction); }); describe('should trim end of string', () => { const action = trimEnd(); test('for empty string', () => { expect(action['~run']({ typed: true, value: '' }, {})).toStrictEqual({ typed: true, value: '', }); expect(action['~run']({ typed: true, value: ' ' }, {})).toStrictEqual({ typed: true, value: '', }); }); test('with blanks at end', () => { expect(action['~run']({ typed: true, value: 'foo ' }, {})).toStrictEqual( { typed: true, value: 'foo', } ); }); }); test('should not trim start of string', () => { expect( trimEnd()['~run']({ typed: true, value: ' foo' }, {}) ).toStrictEqual({ typed: true, value: ' foo', }); }); }); ================================================ FILE: library/src/actions/trimEnd/trimEnd.ts ================================================ import type { BaseTransformation } from '../../types/index.ts'; /** * Trim end action interface. */ export interface TrimEndAction extends BaseTransformation { /** * The action type. */ readonly type: 'trim_end'; /** * The action reference. */ readonly reference: typeof trimEnd; } /** * Creates a trim end transformation action. * * @returns A trim end action. */ // @__NO_SIDE_EFFECTS__ export function trimEnd(): TrimEndAction { return { kind: 'transformation', type: 'trim_end', reference: trimEnd, async: false, '~run'(dataset) { dataset.value = dataset.value.trimEnd(); return dataset; }, }; } ================================================ FILE: library/src/actions/trimStart/index.ts ================================================ export * from './trimStart.ts'; ================================================ FILE: library/src/actions/trimStart/trimStart.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { trimStart, type TrimStartAction } from './trimStart.ts'; describe('trim', () => { test('should return action object', () => { expectTypeOf(trimStart()).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/actions/trimStart/trimStart.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { trimStart, type TrimStartAction } from './trimStart.ts'; describe('trimStart', () => { test('should return action object', () => { expect(trimStart()).toStrictEqual({ kind: 'transformation', type: 'trim_start', reference: trimStart, async: false, '~run': expect.any(Function), } satisfies TrimStartAction); }); describe('should trim start of string', () => { const action = trimStart(); test('for empty string', () => { expect(action['~run']({ typed: true, value: '' }, {})).toStrictEqual({ typed: true, value: '', }); expect(action['~run']({ typed: true, value: ' ' }, {})).toStrictEqual({ typed: true, value: '', }); }); test('with blanks at start', () => { expect(action['~run']({ typed: true, value: ' foo' }, {})).toStrictEqual( { typed: true, value: 'foo', } ); }); }); test('should not trim end of string', () => { expect( trimStart()['~run']({ typed: true, value: 'foo ' }, {}) ).toStrictEqual({ typed: true, value: 'foo ' }); }); }); ================================================ FILE: library/src/actions/trimStart/trimStart.ts ================================================ import type { BaseTransformation } from '../../types/index.ts'; /** * Trim start action interface. */ export interface TrimStartAction extends BaseTransformation { /** * The action type. */ readonly type: 'trim_start'; /** * The action reference. */ readonly reference: typeof trimStart; } /** * Creates a trim start transformation action. * * @returns A trim start action. */ // @__NO_SIDE_EFFECTS__ export function trimStart(): TrimStartAction { return { kind: 'transformation', type: 'trim_start', reference: trimStart, async: false, '~run'(dataset) { dataset.value = dataset.value.trimStart(); return dataset; }, }; } ================================================ FILE: library/src/actions/types.ts ================================================ import type { MaybePromise, MaybeReadonly } from '../types/index.ts'; /** * Array input type. */ export type ArrayInput = MaybeReadonly; /** * Array requirement type. */ export type ArrayRequirement = ( item: TInput[number], index: number, array: TInput ) => boolean; /** * Array requirement async type. */ export type ArrayRequirementAsync = ( item: TInput[number], index: number, array: TInput ) => MaybePromise; /** * Content input type. */ export type ContentInput = string | MaybeReadonly; /** * Content requirement type. */ export type ContentRequirement = TInput extends readonly unknown[] ? TInput[number] : TInput; /** * Entries input type. */ export type EntriesInput = Record; /** * Length input type. */ export type LengthInput = string | ArrayLike; /** * Size input type. */ export type SizeInput = Blob | Map | Set; /** * Value input type. */ export type ValueInput = string | number | bigint | boolean | Date; ================================================ FILE: library/src/actions/ulid/index.ts ================================================ export * from './ulid.ts'; ================================================ FILE: library/src/actions/ulid/ulid.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { ulid, type UlidAction, type UlidIssue } from './ulid.ts'; describe('ulid', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = UlidAction; expectTypeOf(ulid()).toEqualTypeOf(); expectTypeOf(ulid(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(ulid('message')).toEqualTypeOf< UlidAction >(); }); test('with function message', () => { expectTypeOf(ulid string>(() => 'message')).toEqualTypeOf< UlidAction string> >(); }); }); describe('should infer correct types', () => { type Action = UlidAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/ulid/ulid.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { ULID_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { ulid, type UlidAction, type UlidIssue } from './ulid.ts'; describe('ulid', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'ulid', reference: ulid, expects: null, requirement: ULID_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: UlidAction = { ...baseAction, message: undefined, }; expect(ulid()).toStrictEqual(action); expect(ulid(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(ulid('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies UlidAction); }); test('with function message', () => { const message = () => 'message'; expect(ulid(message)).toStrictEqual({ ...baseAction, message, } satisfies UlidAction); }); }); describe('should return dataset without issues', () => { const action = ulid(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid ULIDs', () => { expectNoActionIssue(action, [ '01ARZ3NDEKTSV4RRFFQ69G5FAV', '01bx5zzkbkactav9wevgemmvry', '0123456789abcdefghjkmnpqrs', 'ABCDEFGHJKMNPQRSTVWXYZ0123', ]); }); }); describe('should return dataset with issues', () => { const action = ulid('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'ulid', expected: null, message: 'message', requirement: ULID_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for blank spaces', () => { expectActionIssue(action, baseIssue, [ ' 01ARZ3NDEKTSV4RRFFQ69G5FAV', '01ARZ3NDEKTSV4RRFFQ69G5FAV ', ' 01ARZ3NDEKTSV4RRFFQ69G5FAV ', ]); }); test('for too short ULIDs', () => { expectActionIssue(action, baseIssue, [ '01ARZ3NDEKTSV4RRFFQ69G5FA', '01bx5zzkbkactav9', ]); }); test('for too long ULIDs', () => { expectActionIssue(action, baseIssue, [ '01ARZ3NDEKTSV4RRFFQ69G5FAV1', '01bx5zzkbkactav9wevgemmvry123456789', ]); }); test('for invalid letters', () => { expectActionIssue(action, baseIssue, [ '01ARZ3NDIKTSV4RRFFQ69G5FAV', '01bx5zikbkactav9wevgemmvry', 'L1ARZ3NDEKTSV4RRFFQ69G5FAV', 'l1bx5zzkbkactav9wevgemmvry', '01ARZ3NDEKTSV4RRFFQ69G5OAV', '01bx5zzkbkactav9wevgemmory', '01ARZ3NDEKTSV4RRFFQ69G5FAU', '01bx5zzkbkactav9wevgemmvru', ]); }); }); }); ================================================ FILE: library/src/actions/ulid/ulid.ts ================================================ import { ULID_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * ULID issue interface. */ export interface UlidIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'ulid'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The ULID regex. */ readonly requirement: RegExp; } /** * ULID action interface. */ export interface UlidAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'ulid'; /** * The action reference. */ readonly reference: typeof ulid; /** * The expected property. */ readonly expects: null; /** * The ULID regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates an [ULID](https://github.com/ulid/spec) validation action. * * @returns An ULID action. */ export function ulid(): UlidAction; /** * Creates an [ULID](https://github.com/ulid/spec) validation action. * * @param message The error message. * * @returns An ULID action. */ export function ulid< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): UlidAction; // @__NO_SIDE_EFFECTS__ export function ulid( message?: ErrorMessage> ): UlidAction> | undefined> { return { kind: 'validation', type: 'ulid', reference: ulid, async: false, expects: null, requirement: ULID_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'ULID', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/url/index.ts ================================================ export * from './url.ts'; ================================================ FILE: library/src/actions/url/url.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { url, type UrlAction, type UrlIssue } from './url.ts'; describe('url', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = UrlAction; expectTypeOf(url()).toEqualTypeOf(); expectTypeOf(url(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(url('message')).toEqualTypeOf< UrlAction >(); }); test('with function message', () => { expectTypeOf(url(() => 'message')).toEqualTypeOf< UrlAction string> >(); }); }); describe('should infer correct types', () => { type Action = UrlAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/url/url.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { url, type UrlAction, type UrlIssue } from './url.ts'; describe('url', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'url', reference: url, expects: null, requirement: expect.any(Function), async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: UrlAction = { ...baseAction, message: undefined, }; expect(url()).toStrictEqual(action); expect(url(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(url('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies UrlAction); }); test('with function message', () => { const message = () => 'message'; expect(url(message)).toStrictEqual({ ...baseAction, message, } satisfies UrlAction); }); }); describe('should return dataset without issues', () => { const action = url(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for a HTTP URL', () => { expectNoActionIssue(action, [ 'http://example.com', 'http://www.example.com/path', 'http://subdomain1.subdomain2.example.com/path1/path2?param1=value1¶m2=value2', ]); }); test('for a HTTPS URL', () => { expectNoActionIssue(action, [ 'https://example.com', 'https://www.example.com/path', 'https://subdomain1.subdomain2.example.com/path1/path2?param1=value1¶m2=value2', ]); }); test('for a FTP URL', () => { expectNoActionIssue(action, [ 'ftp://example.com', 'ftp://www.example.com/path', 'ftp://subdomain1.subdomain2.example.com/path1/path2?param1=value1¶m2=value2', ]); }); }); describe('should return dataset with issues', () => { const action = url('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'url', expected: null, message: 'message', requirement: expect.any(Function), }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for URL without schema', () => { expectActionIssue(action, baseIssue, [ 'example.com', 'www.example.com/path', 'subdomain1.subdomain2.example.com/path1/path2?param1=value1¶m2=value2', ]); }); }); }); ================================================ FILE: library/src/actions/url/url.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * URL issue interface. */ export interface UrlIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'url'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The validation function. */ readonly requirement: (input: string) => boolean; } /** * URL action interface. */ export interface UrlAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'url'; /** * The action reference. */ readonly reference: typeof url; /** * The expected property. */ readonly expects: null; /** * The validation function. */ readonly requirement: (input: string) => boolean; /** * The error message. */ readonly message: TMessage; } /** * Creates an [URL](https://en.wikipedia.org/wiki/URL) validation action. * * Hint: The value is passed to the URL constructor to check if it is valid. * This check is not perfect. For example, values like "abc:1234" are accepted. * * @returns An URL action. */ export function url(): UrlAction; /** * Creates an [URL](https://en.wikipedia.org/wiki/URL) validation action. * * Hint: The value is passed to the URL constructor to check if it is valid. * This check is not perfect. For example, values like "abc:1234" are accepted. * * @param message The error message. * * @returns An URL action. */ export function url< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): UrlAction; // @__NO_SIDE_EFFECTS__ export function url( message?: ErrorMessage> | undefined ): UrlAction> | undefined> { return { kind: 'validation', type: 'url', reference: url, async: false, expects: null, requirement(input) { try { new URL(input); return true; } catch { return false; } }, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement(dataset.value)) { _addIssue(this, 'URL', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/uuid/index.ts ================================================ export * from './uuid.ts'; ================================================ FILE: library/src/actions/uuid/uuid.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { uuid, type UuidAction, type UuidIssue } from './uuid.ts'; describe('uuid', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = UuidAction; expectTypeOf(uuid()).toEqualTypeOf(); expectTypeOf(uuid(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(uuid('message')).toEqualTypeOf< UuidAction >(); }); test('with function message', () => { expectTypeOf(uuid string>(() => 'message')).toEqualTypeOf< UuidAction string> >(); }); }); describe('should infer correct types', () => { type Action = UuidAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/uuid/uuid.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { UUID_REGEX } from '../../regex.ts'; import type { StringIssue } from '../../schemas/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { uuid, type UuidAction, type UuidIssue } from './uuid.ts'; describe('uuid', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'uuid', reference: uuid, expects: null, requirement: UUID_REGEX, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: UuidAction = { ...baseAction, message: undefined, }; expect(uuid()).toStrictEqual(action); expect(uuid(undefined)).toStrictEqual(action); }); test('with string message', () => { expect(uuid('message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies UuidAction); }); test('with function message', () => { const message = () => 'message'; expect(uuid(message)).toStrictEqual({ ...baseAction, message, } satisfies UuidAction); }); }); describe('should return dataset without issues', () => { const action = uuid(); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid UUID v1', () => { expectNoActionIssue(action, [ 'a6021db4-0b07-11ef-9262-0242ac120002', 'bf576dbe-0b07-11ef-9262-0242ac120002', 'bf576fda-0b07-11ef-9262-0242ac120002', 'bf577106-0b07-11ef-9262-0242ac120002', 'bf57721e-0b07-11ef-9262-0242ac120002', ]); }); test('for valid UUID v4', () => { expectNoActionIssue(action, [ 'c1e12793-2e77-4611-874d-a4f9cc727e1e', '95d9d16b-feba-495d-ab7b-07e4212ff3d0', 'c4322ec9-5c1f-4865-b0b1-52298acc5a8e', '6f66b7d5-8400-4e48-99f9-ae94ba418069', '779c2294-cb0a-4347-9587-61d4509d32db', ]); }); test('for valid UUID v7', () => { expectNoActionIssue(action, [ '018f4f48-1658-7538-8aa9-e3b64526bb43', '018f4f48-9a53-72b6-8ee6-91c47cd95f6f', '018f4f48-b0a1-75bc-ab3f-11081dfb40b8', '018f4f48-cecc-7bfc-b0bc-a77fe4d77d66', '018f4f48-e99c-7008-adbe-e3b7e7497ed8', ]); }); test('for special nil UUID', () => { expectNoActionIssue(action, ['00000000-0000-0000-0000-000000000000']); }); }); describe('should return dataset with issues', () => { const action = uuid('message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'uuid', expected: null, message: 'message', requirement: UUID_REGEX, }; test('for empty strings', () => { expectActionIssue(action, baseIssue, ['', ' ', '\n']); }); test('for blank spaces', () => { expectActionIssue(action, baseIssue, [ ' c1e12793-2e77-4611-874d-a4f9cc727e1e', 'c1e12793-2e77-4611-874d-a4f9cc727e1e ', ' c1e12793-2e77-4611-874d-a4f9cc727e1e ', ]); }); test('for too short UUIDs', () => { expectActionIssue(action, baseIssue, [ 'e05717b-1020-4f83-8dce-f33dcac6c101', 'e057f17b-100-4f83-8dce-f33dcac6c101', 'e057f17b-1020-f83-8dce-f33dcac6c101', 'e057f17b-1020-4f83-8de-f33dcac6c101', 'e057f17b-1020-4f83-8dce-f3dcac6c101', ]); }); test('for too long UUIDs', () => { expectActionIssue(action, baseIssue, [ 'e057f147b-1020-4f83-8dce-f33dcac6c101', 'e057f17b-10220-4f83-8dce-f33dcac6c101', 'e057f17b-1020-4f873-8dce-f33dcac6c101', 'e057f17b-1020-4f83-8dc2e-f33dcac6c101', 'e057f17b-1020-4f83-8dce-f33d3cac6c101', ]); }); test('for invalid hyphenated UUIDs', () => { expectActionIssue(action, baseIssue, [ 'a6021db4-0b07-11ef-9262-0242ac120002-', '95d9d16b-feba-495d-ab7b--07e4212ff3d0', '95d9d16b--feba-495d-ab7b-07e4212ff3d0', '95d9d16b--feba--495d--ab7b--07e4212ff3d0', ]); }); test('for invalid placed hyphens', () => { expectActionIssue(action, baseIssue, [ 'a6021db4-0b07-11ef-9262-0242ac120002-0', '95d9d16b-feba-495d-ab7b-07e4212ff3d-0', 'c1e1279-32e77-4611-874d-a4f9cc727e1e', ]); }); test('for invalid letters', () => { expectActionIssue(action, baseIssue, [ 'd8600862-9dea-4g51-b261-ff899d608069', 'd8600862-9dea-4d51-b261-hf899d608069', 'd8600862-9dea-4d51-k261-ff899d608069', 'd8600862-9dea-4d51-b261-zf899d608069', 'd8600862-9dta-4d51-b261-ff899d608069', 'd8600862-9dex-4d51-b261-ff899d608069', ]); }); }); }); ================================================ FILE: library/src/actions/uuid/uuid.ts ================================================ import { UUID_REGEX } from '../../regex.ts'; import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue } from '../../utils/index.ts'; /** * UUID issue interface. */ export interface UuidIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'uuid'; /** * The expected property. */ readonly expected: null; /** * The received property. */ readonly received: `"${string}"`; /** * The UUID regex. */ readonly requirement: RegExp; } /** * UUID action interface. */ export interface UuidAction< TInput extends string, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'uuid'; /** * The action reference. */ readonly reference: typeof uuid; /** * The expected property. */ readonly expects: null; /** * The UUID regex. */ readonly requirement: RegExp; /** * The error message. */ readonly message: TMessage; } /** * Creates an [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) validation action. * * @returns An UUID action. */ export function uuid(): UuidAction; /** * Creates an [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) validation action. * * @param message The error message. * * @returns An UUID action. */ export function uuid< TInput extends string, const TMessage extends ErrorMessage> | undefined, >(message: TMessage): UuidAction; // @__NO_SIDE_EFFECTS__ export function uuid( message?: ErrorMessage> ): UuidAction> | undefined> { return { kind: 'validation', type: 'uuid', reference: uuid, async: false, expects: null, requirement: UUID_REGEX, message, '~run'(dataset, config) { if (dataset.typed && !this.requirement.test(dataset.value)) { _addIssue(this, 'UUID', dataset, config); } return dataset; }, }; } ================================================ FILE: library/src/actions/value/index.ts ================================================ export * from './value.ts'; ================================================ FILE: library/src/actions/value/value.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { value, type ValueAction, type ValueIssue } from './value.ts'; describe('value', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = ValueAction; expectTypeOf(value(10)).toEqualTypeOf(); expectTypeOf( value(10, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(value(10, 'message')).toEqualTypeOf< ValueAction >(); }); test('with function message', () => { expectTypeOf( value string>(10, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = ValueAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< ValueIssue >(); }); }); }); ================================================ FILE: library/src/actions/value/value.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { NumberIssue } from '../../schemas/index.ts'; import { _stringify } from '../../utils/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { value, type ValueAction } from './value.ts'; describe('value', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'value', reference: value, expects: '5', requirement: 5, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: ValueAction = { ...baseAction, message: undefined, }; expect(value(5)).toStrictEqual(action); expect(value(5, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(value(5, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies ValueAction); }); test('with function message', () => { const message = () => 'message'; expect(value(5, message)).toStrictEqual({ ...baseAction, message, } satisfies ValueAction); }); }); describe('should return dataset without issues', () => { test('for untyped inputs', () => { const issues: [NumberIssue] = [ { kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', message: 'message', }, ]; expect( value(1)['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid bigints', () => { expectNoActionIssue(value(123n), [123n, BigInt(123), BigInt('123')]); }); test('for valid non-bigints', () => { expectNoActionIssue(value(123n), [ 123, 123.0, '123', ' 123 ', new Date(123), ]); expectNoActionIssue(value(1n), [1, 1.0, '1', ' 1 ', true, new Date(1)]); expectNoActionIssue(value(0n), [ 0, 0.0, '0', ' 0 ', '', ' ', false, new Date(0), ]); }); test('for valid booleans', () => { expectNoActionIssue(value(true), [true]); expectNoActionIssue(value(false), [false]); }); test('for valid non-booleans', () => { expectNoActionIssue(value(true), [ 1, 1.0, 1n, '1', '1.0', ' 1 ', new Date(1), ]); expectNoActionIssue(value(false), [ 0, 0.0, 0n, '0', '0.0', ' 0 ', '', ' ', new Date(0), ]); }); test('for valid dates', () => { const date = new Date(); expectNoActionIssue(value(date), [ date, new Date(date.getTime()), new Date(date.toISOString()), new Date( date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds() ), ]); }); test('for valid non-dates', () => { expectNoActionIssue(value(new Date(123)), [ 123, 123.0, 123n, '123', '123.0', ' 123 ', ]); expectNoActionIssue(value(new Date(1)), [ 1, 1.0, 1n, '1', '1.0', ' 1 ', true, ]); expectNoActionIssue(value(new Date(0)), [ 0, 0.0, 0n, '0', '0.0', ' 0 ', '', ' ', false, ]); }); test('for valid numbers', () => { expectNoActionIssue(value(123), [123, 123.0, Number('123')]); }); test('for valid non-numbers', () => { expectNoActionIssue(value(123), [ 123n, '123', '123.0', ' 123 ', new Date(123), ]); expectNoActionIssue(value(1), [1n, '1', '1.0', ' 1 ', true, new Date(1)]); expectNoActionIssue(value(0), [ 0n, '0', '0.0', ' 0 ', '', ' ', false, new Date(0), ]); }); test('for valid strings', () => { expectNoActionIssue(value('2024'), ['2024']); }); test('for valid non-strings', () => { expectNoActionIssue(value('1'), [1n, 1, 1.0, true, new Date(1)]); expectNoActionIssue(value('0'), [0n, 0, 0.0, false, new Date(0)]); }); }); describe('should return dataset with issues', () => { const baseInfo = { kind: 'validation', type: 'value', message: 'message', } as const; const getReceived = (value: unknown): string => value instanceof Date ? value.toJSON() : _stringify(value); test('for invalid bigints', () => { expectActionIssue( value(10n, 'message'), { ...baseInfo, expected: '10', requirement: 10n }, [-123n, 0n, 9n, 11n, 123n] ); }); test('for invalid non-bigints', () => { expectActionIssue( value(10n, 'message'), { ...baseInfo, expected: '10', requirement: 10n }, [ 9, 11, 9.0, 11.0, '9', '11', '9.0', '11.0', '', ' ', new Date(9), new Date(11), true, false, ], getReceived ); expectActionIssue( value(1n, 'message'), { ...baseInfo, expected: '1', requirement: 1n }, [0, 0.0, '0', ' 0 ', '', ' ', false, new Date(0)], getReceived ); expectActionIssue( value(0n, 'message'), { ...baseInfo, expected: '0', requirement: 0n }, [1, 1.0, '1', ' 1 ', true, new Date(1)], getReceived ); }); test('for invalid booleans', () => { expectActionIssue( value(true, 'message'), { ...baseInfo, expected: 'true', requirement: true }, [false] ); expectActionIssue( value(false, 'message'), { ...baseInfo, expected: 'false', requirement: false }, [true] ); }); test('for invalid non-booleans', () => { expectActionIssue( value(true, 'message'), { ...baseInfo, expected: 'true', requirement: true }, [0n, 0, 0.0, '0', '0.0', ' 0 ', '', ' ', new Date(0)], getReceived ); expectActionIssue( value(true, 'message'), { ...baseInfo, expected: 'true', requirement: true }, [123n, 123, 123.0, '123', '123.0', 'foo', 'true', new Date(123)], getReceived ); expectActionIssue( value(false, 'message'), { ...baseInfo, expected: 'false', requirement: false }, [1n, 1, 1.0, '1', '1.0', ' 1 ', new Date(1)], getReceived ); expectActionIssue( value(false, 'message'), { ...baseInfo, expected: 'false', requirement: false }, [123n, 123, 123.0, '123', '123.0', 'foo', 'false', new Date(123)], getReceived ); }); test('for invalid dates', () => { const date = new Date(); expectActionIssue( value(date, 'message'), { ...baseInfo, expected: `${date.toJSON()}`, requirement: date }, [new Date(+date - 1), new Date(+date + 1), new Date(+date + 999999)], (value) => value.toJSON() ); }); test('for invalid non-dates', () => { const date1 = new Date(10); expectActionIssue( value(date1, 'message'), { ...baseInfo, expected: date1.toJSON(), requirement: date1 }, [ 9n, 11n, 9, 11, 9.0, 11.0, '9', '11', '9.0', '11.0', '', ' ', true, false, ], getReceived ); const date2 = new Date(1); expectActionIssue( value(date2, 'message'), { ...baseInfo, expected: date2.toJSON(), requirement: date2 }, [0, 0.0, 0n, '0', '0.0', ' 0 ', '', ' ', false], getReceived ); const date3 = new Date(0); expectActionIssue( value(date3, 'message'), { ...baseInfo, expected: date3.toJSON(), requirement: date3 }, [1, 1.0, 1n, '1', '1.0', ' 1 ', true], getReceived ); }); test('for invalid numbers', () => { expectActionIssue( value(10, 'message'), { ...baseInfo, expected: '10', requirement: 10 }, [ -Infinity, Number.MIN_VALUE, -10, -9, 9, 11, 9999, Number.MAX_VALUE, Infinity, NaN, ] ); }); test('for invalid non-numbers', () => { expectActionIssue( value(10, 'message'), { ...baseInfo, expected: '10', requirement: 10 }, [9n, 11n, '9', '11', '9.0', '11.0', '', ' ', new Date(9), true, false], getReceived ); expectActionIssue( value(1, 'message'), { ...baseInfo, expected: '1', requirement: 1 }, [0n, '0', '0.0', ' 0 ', '', ' ', false, new Date(0)], getReceived ); expectActionIssue( value(0, 'message'), { ...baseInfo, expected: '0', requirement: 0 }, [1n, '1', '1.0', ' 1 ', true, new Date(1)], getReceived ); }); test('for invalid strings', () => { expectActionIssue( value('2024', 'message'), { ...baseInfo, expected: '"2024"', requirement: '2024' }, [ '202', '024', ' 2024', '2024 ', '02024', '20240', '020240', '2025', '9999', 'XYZ', ] ); }); test('for invalid non-strings', () => { expectActionIssue( value('10', 'message'), { ...baseInfo, expected: '"10"', requirement: '10' }, [9n, 11n, 9, 11, 9.0, 11.0, new Date(9), new Date(11), true, false], getReceived ); expectActionIssue( value('1', 'message'), { ...baseInfo, expected: '"1"', requirement: '1' }, [0n, 0, 0.0, false, new Date(0)], getReceived ); expectActionIssue( value('0', 'message'), { ...baseInfo, expected: '"0"', requirement: '0' }, [1n, 1, 1.0, true, new Date(1)], getReceived ); }); }); }); ================================================ FILE: library/src/actions/value/value.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _stringify } from '../../utils/index.ts'; import type { ValueInput } from '../types.ts'; /** * Value issue interface. */ export interface ValueIssue< TInput extends ValueInput, TRequirement extends TInput, > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'value'; /** * The expected property. */ readonly expected: string; /** * The required value. */ readonly requirement: TRequirement; } /** * Value action interface. */ export interface ValueAction< TInput extends ValueInput, TRequirement extends TInput, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'value'; /** * The action reference. */ readonly reference: typeof value; /** * The expected property. */ readonly expects: string; /** * The required value. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a value validation action. * * @param requirement The required value. * * @returns A value action. */ export function value< TInput extends ValueInput, const TRequirement extends TInput, >(requirement: TRequirement): ValueAction; /** * Creates a value validation action. * * @param requirement The required value. * @param message The error message. * * @returns A value action. */ export function value< TInput extends ValueInput, const TRequirement extends TInput, const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): ValueAction; // @__NO_SIDE_EFFECTS__ export function value( requirement: ValueInput, message?: ErrorMessage> ): ValueAction< ValueInput, ValueInput, ErrorMessage> | undefined > { return { kind: 'validation', type: 'value', reference: value, async: false, expects: requirement instanceof Date ? requirement.toJSON() : _stringify(requirement), requirement, message, '~run'(dataset, config) { if ( dataset.typed && !( this.requirement <= dataset.value && this.requirement >= dataset.value ) ) { _addIssue(this, 'value', dataset, config, { received: dataset.value instanceof Date ? dataset.value.toJSON() : _stringify(dataset.value), }); } return dataset; }, }; } ================================================ FILE: library/src/actions/values/index.ts ================================================ export * from './values.ts'; ================================================ FILE: library/src/actions/values/values.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { values, type ValuesAction, type ValuesIssue } from './values.ts'; describe('values', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = ValuesAction; expectTypeOf( values([2, 4, 6]) ).toEqualTypeOf(); expectTypeOf( values([2, 4, 6], undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( values([2, 4, 6], 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( values string>([2, 4, 6], () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Action = ValuesAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< ValuesIssue >(); }); }); }); ================================================ FILE: library/src/actions/values/values.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { NumberIssue } from '../../schemas/index.ts'; import { _stringify } from '../../utils/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { values, type ValuesAction } from './values.ts'; describe('values', () => { describe('should return action object', () => { const baseAction: Omit< ValuesAction, 'message' > = { kind: 'validation', type: 'values', reference: values, expects: '(2 | 4 | 6)', requirement: [2, 4, 6], async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: ValuesAction = { ...baseAction, message: undefined, }; expect(values([2, 4, 6])).toStrictEqual(action); expect(values([2, 4, 6], undefined)).toStrictEqual(action); }); test('with string message', () => { expect(values([2, 4, 6], 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies ValuesAction); }); test('with function message', () => { const message = () => 'message'; expect(values([2, 4, 6], message)).toStrictEqual({ ...baseAction, message, } satisfies ValuesAction); }); }); describe('should return dataset without issues', () => { test('for untyped inputs', () => { const issues: [NumberIssue] = [ { kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', message: 'message', }, ]; expect( values([1])['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid bigints', () => { expectNoActionIssue(values([-2n, 3n]), [-2n, 3n, BigInt(3), BigInt('3')]); expectNoActionIssue(values([0n]), [0n]); }); test('for valid non-bigints', () => { expectNoActionIssue(values([-123n, 456n]), [ -123, 456, -123.0, 456.0, '-123', '456', ' -123 ', ' 456 ', new Date(-123), new Date(456), ]); expectNoActionIssue(values([1n]), [ 1, 1.0, '1', ' 1 ', true, new Date(1), ]); expectNoActionIssue(values([0n]), [ 0, 0.0, '0', ' 0 ', '', ' ', false, new Date(0), ]); }); test('for valid booleans', () => { expectNoActionIssue(values([true]), [true]); expectNoActionIssue(values([false]), [false]); expectNoActionIssue(values([true, false]), [false, true]); }); test('for valid non-booleans', () => { expectNoActionIssue(values([true]), [ 1, 1.0, 1n, '1', '1.0', ' 1 ', new Date(1), ]); expectNoActionIssue(values([false]), [ 0, 0.0, 0n, '0', '0.0', ' 0 ', '', ' ', new Date(0), ]); expectNoActionIssue(values([false, true]), [ 1, 0, 1.0, 0.0, 1n, 0n, '1', '0', '1.0', '0.0', ' 1 ', ' 0 ', '', ' ', new Date(1), new Date(0), ]); }); test('for valid dates', () => { const date = new Date(); const nextDate = new Date(+date + 1); expectNoActionIssue(values([date, nextDate]), [ nextDate, date, new Date(+nextDate), new Date(date.getTime()), new Date(date.toISOString()), new Date( date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds() ), ]); }); test('for valid non-dates', () => { expectNoActionIssue(values([new Date(-123), new Date(456)]), [ -123, 456, -123.0, 456.0, -123n, 456n, '-123', '456', '-123.0', '456.0', ' -123 ', ' 456 ', ]); expectNoActionIssue(values([new Date(1)]), [ 1, 1.0, 1n, '1', '1.0', ' 1 ', true, ]); expectNoActionIssue(values([new Date(0)]), [ 0, 0.0, 0n, '0', '0.0', ' 0 ', '', ' ', false, ]); }); test('for valid numbers', () => { expectNoActionIssue(values([-2, 3]), [-2, 3, 3.0, Number('3')]); expectNoActionIssue(values([0]), [0]); }); test('for valid non-numbers', () => { expectNoActionIssue(values([-123, 456]), [ -123n, 456n, '-123', '456', '-123.0', '456.0', ' -123 ', ' 456 ', new Date(-123), new Date(456), ]); expectNoActionIssue(values([1]), [ 1n, '1', '1.0', ' 1 ', true, new Date(1), ]); expectNoActionIssue(values([0]), [ 0n, '0', '0.0', ' 0 ', '', ' ', false, new Date(0), ]); }); test('for valid strings', () => { expectNoActionIssue(values(['2024', '2025']), ['2024', '2025']); expectNoActionIssue(values(['0']), ['0']); }); test('for valid non-strings', () => { expectNoActionIssue(values(['-123', '456']), [ -123n, 456n, -123, 456, -123.0, 456.0, new Date(-123), new Date(456), ]); expectNoActionIssue(values(['1']), [1n, 1, 1.0, true, new Date(1)]); expectNoActionIssue(values(['0']), [0n, 0, 0.0, false, new Date(0)]); }); }); describe('should return dataset with issues', () => { const baseInfo = { kind: 'validation', type: 'values', message: 'message', } as const; const getReceived = (value: unknown): string => value instanceof Date ? value.toJSON() : _stringify(value); test('for invalid bigints', () => { expectActionIssue( values([-2n, 0n, 1n], 'message'), { ...baseInfo, expected: '(-2 | 0 | 1)', requirement: [-2n, 0n, 1n] }, [-1n, 2n, 100n] ); }); test('for invalid non-bigints', () => { expectActionIssue( values([10n, 11n, 12n], 'message'), { ...baseInfo, expected: '(10 | 11 | 12)', requirement: [10n, 11n, 12n], }, [ 9, 13, 9.0, 13.0, '9', '13', '9.0', '13.0', '', ' ', new Date(9), new Date(13), true, false, ], getReceived ); expectActionIssue( values([1n], 'message'), { ...baseInfo, expected: '1', requirement: [1n] }, [0, 0.0, '0', ' 0 ', '', ' ', false, new Date(0)], getReceived ); expectActionIssue( values([0n], 'message'), { ...baseInfo, expected: '0', requirement: [0n] }, [1, 1.0, '1', ' 1 ', true, new Date(1)], getReceived ); }); test('for invalid booleans', () => { expectActionIssue( values([true], 'message'), { ...baseInfo, expected: 'true', requirement: [true] }, [false] ); expectActionIssue( values([false], 'message'), { ...baseInfo, expected: 'false', requirement: [false] }, [true] ); }); test('for invalid non-booleans', () => { expectActionIssue( values([true], 'message'), { ...baseInfo, expected: 'true', requirement: [true] }, [0n, 0, 0.0, '0', '0.0', ' 0 ', '', ' ', new Date(0)], getReceived ); expectActionIssue( values([true], 'message'), { ...baseInfo, expected: 'true', requirement: [true] }, [123n, 123, 123.0, '123', '123.0', 'foo', 'true', new Date(123)], getReceived ); expectActionIssue( values([false], 'message'), { ...baseInfo, expected: 'false', requirement: [false] }, [1n, 1, 1.0, '1', '1.0', ' 1 ', new Date(1)], getReceived ); expectActionIssue( values([false], 'message'), { ...baseInfo, expected: 'false', requirement: [false] }, [123n, 123, 123.0, '123', '123.0', 'foo', 'false', new Date(123)], getReceived ); }); test('for invalid dates', () => { const date = new Date(); const datePlusTwo = new Date(+date + 2); expectActionIssue( values([date, datePlusTwo], 'message'), { ...baseInfo, expected: `(${date.toJSON()} | ${datePlusTwo.toJSON()})`, requirement: [date, datePlusTwo], }, [new Date(+date - 1), new Date(+date + 1), new Date(+date + 999999)], (value) => value.toJSON() ); }); test('for invalid non-dates', () => { const date1 = new Date(10); expectActionIssue( values([date1], 'message'), { ...baseInfo, expected: date1.toJSON(), requirement: [date1] }, [ 9n, 11n, 9, 11, 9.0, 11.0, '9', '11', '9.0', '11.0', '', ' ', true, false, ], getReceived ); const date2 = new Date(1); expectActionIssue( values([date2], 'message'), { ...baseInfo, expected: date2.toJSON(), requirement: [date2] }, [0, 0.0, 0n, '0', '0.0', ' 0 ', '', ' ', false], getReceived ); const date3 = new Date(0); expectActionIssue( values([date3], 'message'), { ...baseInfo, expected: date3.toJSON(), requirement: [date3] }, [1, 1.0, 1n, '1', '1.0', ' 1 ', true], getReceived ); }); test('for invalid numbers', () => { expectActionIssue( values([-123, 456], 'message'), { ...baseInfo, expected: '(-123 | 456)', requirement: [-123, 456] }, [ -Infinity, Number.MIN_VALUE, -124, -122, 0, 455, 457, 9999, Number.MAX_VALUE, Infinity, NaN, ] ); }); test('for invalid non-numbers', () => { expectActionIssue( values([10, 11, 12], 'message'), { ...baseInfo, expected: '(10 | 11 | 12)', requirement: [10, 11, 12] }, [ 9n, 13n, '9', '13', '9.0', '13.0', '', ' ', new Date(9), new Date(13), true, false, ], getReceived ); expectActionIssue( values([1], 'message'), { ...baseInfo, expected: '1', requirement: [1] }, [0n, '0', '0.0', ' 0 ', '', ' ', false, new Date(0)], getReceived ); expectActionIssue( values([0], 'message'), { ...baseInfo, expected: '0', requirement: [0] }, [1n, '1', '1.0', ' 1 ', true, new Date(1)], getReceived ); }); test('for invalid strings', () => { expectActionIssue( values(['2024', '2025'], 'message'), { ...baseInfo, expected: '("2024" | "2025")', requirement: ['2024', '2025'], }, [ '202', '024', ' 2024', '2024 ', '02024', '20240', '020240', '2026', '9999', 'XYZ', ] ); }); test('for invalid non-strings', () => { expectActionIssue( values(['10', '11', '12'], 'message'), { ...baseInfo, expected: '("10" | "11" | "12")', requirement: ['10', '11', '12'], }, [9n, 13n, 9, 13, 9.0, 13.0, new Date(9), new Date(13), true, false], getReceived ); expectActionIssue( values(['1'], 'message'), { ...baseInfo, expected: '"1"', requirement: ['1'] }, [0n, 0, 0.0, false, new Date(0)], getReceived ); expectActionIssue( values(['0'], 'message'), { ...baseInfo, expected: '"0"', requirement: ['0'] }, [1n, 1, 1.0, true, new Date(1)], getReceived ); }); }); }); ================================================ FILE: library/src/actions/values/values.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _joinExpects, _stringify } from '../../utils/index.ts'; import type { ValueInput } from '../types.ts'; /** * Values issue type. */ export interface ValuesIssue< TInput extends ValueInput, TRequirement extends readonly TInput[], > extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'values'; /** * The expected property. */ readonly expected: string; /** * The required values. */ readonly requirement: TRequirement; } /** * Values action type. */ export interface ValuesAction< TInput extends ValueInput, TRequirement extends readonly TInput[], TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'values'; /** * The action reference. */ readonly reference: typeof values; /** * The expected property. */ readonly expects: string; /** * The required values. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a values validation action. * * @param requirement The required values. * * @returns A values action. */ export function values< TInput extends ValueInput, const TRequirement extends readonly TInput[], >(requirement: TRequirement): ValuesAction; /** * Creates a values validation action. * * @param requirement The required values. * @param message The error message. * * @returns A values action. */ export function values< TInput extends ValueInput, const TRequirement extends readonly TInput[], const TMessage extends | ErrorMessage> | undefined, >( requirement: TRequirement, message: TMessage ): ValuesAction; // @__NO_SIDE_EFFECTS__ export function values( requirement: readonly ValueInput[], message?: ErrorMessage> ): ValuesAction< ValueInput, readonly ValueInput[], ErrorMessage> | undefined > { return { kind: 'validation', type: 'values', reference: values, async: false, expects: `${_joinExpects( requirement.map((value) => value instanceof Date ? value.toJSON() : _stringify(value) ), '|' )}`, requirement, message, '~run'(dataset, config) { if ( dataset.typed && !this.requirement.some( (value) => value <= dataset.value && value >= dataset.value ) ) { _addIssue(this, 'value', dataset, config, { received: dataset.value instanceof Date ? dataset.value.toJSON() : _stringify(dataset.value), }); } return dataset; }, }; } ================================================ FILE: library/src/actions/words/index.ts ================================================ export * from './words.ts'; ================================================ FILE: library/src/actions/words/words.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { words, type WordsAction, type WordsIssue } from './words.ts'; describe('words', () => { describe('should return action object', () => { test('with undefined message', () => { type Action = WordsAction; expectTypeOf(words('en', 3)).toEqualTypeOf(); expectTypeOf( words('en', 3, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( words('en', 3, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( words string>('en', 3, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Input = 'foo bar baz'; type Action = WordsAction; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/actions/words/words.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { _getWordCount } from '../../utils/index.ts'; import { expectActionIssue, expectNoActionIssue } from '../../vitest/index.ts'; import { words, type WordsAction, type WordsIssue } from './words.ts'; describe('words', () => { describe('should return action object', () => { const baseAction: Omit, 'message'> = { kind: 'validation', type: 'words', reference: words, expects: '3', locales: 'en', requirement: 3, async: false, '~run': expect.any(Function), }; test('with undefined message', () => { const action: WordsAction = { ...baseAction, message: undefined, }; expect(words('en', 3)).toStrictEqual(action); expect(words('en', 3, undefined)).toStrictEqual(action); }); test('with string message', () => { expect(words('en', 3, 'message')).toStrictEqual({ ...baseAction, message: 'message', } satisfies WordsAction); }); test('with function message', () => { const message = () => 'message'; expect(words('en', 3, message)).toStrictEqual({ ...baseAction, message, } satisfies WordsAction); }); }); describe('should return dataset without issues', () => { const action = words('en', 3); test('for untyped inputs', () => { const issues: [StringIssue] = [ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'message', }, ]; expect( action['~run']({ typed: false, value: null, issues }, {}) ).toStrictEqual({ typed: false, value: null, issues, }); }); test('for valid strings', () => { expectNoActionIssue(action, [ 'foo bar baz', 'Lorem ipsum dolor?', 'Hi, welcome home!', ]); }); }); describe('should return dataset with issues', () => { const action = words('en', 3, 'message'); const baseIssue: Omit, 'input' | 'received'> = { kind: 'validation', type: 'words', expected: '3', message: 'message', requirement: 3, }; test('for invalid strings', () => { expectActionIssue( action, baseIssue, [ '', ' ', 'foo', 'foo bar', 'for bar baz qux', 'Lorem ipsum?', 'Lorem ipsum dolor sit?', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit?', 'Hi, welcome!', 'Hi, welcome home! How are you?', ], (value) => `${_getWordCount('en', value)}` ); }); }); }); ================================================ FILE: library/src/actions/words/words.ts ================================================ import type { BaseIssue, BaseValidation, ErrorMessage, } from '../../types/index.ts'; import { _addIssue, _getWordCount } from '../../utils/index.ts'; /** * Words issue interface. */ export interface WordsIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'validation'; /** * The issue type. */ readonly type: 'words'; /** * The expected property. */ readonly expected: `${TRequirement}`; /** * The received property. */ readonly received: `${number}`; /** * The required words. */ readonly requirement: TRequirement; } /** * Words action interface. */ export interface WordsAction< TInput extends string, TLocales extends Intl.LocalesArgument, TRequirement extends number, TMessage extends ErrorMessage> | undefined, > extends BaseValidation> { /** * The action type. */ readonly type: 'words'; /** * The action reference. */ readonly reference: typeof words; /** * The expected property. */ readonly expects: `${TRequirement}`; /** * The locales to be used. */ readonly locales: TLocales; /** * The required words. */ readonly requirement: TRequirement; /** * The error message. */ readonly message: TMessage; } /** * Creates a words validation action. * * @param locales The locales to be used. * @param requirement The required words. * * @returns A words action. */ export function words< TInput extends string, const TLocales extends Intl.LocalesArgument, const TRequirement extends number, >( locales: TLocales, requirement: TRequirement ): WordsAction; /** * Creates a words validation action. * * @param locales The locales to be used. * @param requirement The required words. * @param message The error message. * * @returns A words action. */ export function words< TInput extends string, const TLocales extends Intl.LocalesArgument, const TRequirement extends number, const TMessage extends | ErrorMessage> | undefined, >( locales: TLocales, requirement: TRequirement, message: TMessage ): WordsAction; // @__NO_SIDE_EFFECTS__ export function words( locales: Intl.LocalesArgument, requirement: number, message?: ErrorMessage> ): WordsAction< string, Intl.LocalesArgument, number, ErrorMessage> | undefined > { return { kind: 'validation', type: 'words', reference: words, async: false, expects: `${requirement}`, locales, requirement, message, '~run'(dataset, config) { if (dataset.typed) { const count = _getWordCount(this.locales, dataset.value); if (count !== this.requirement) { _addIssue(this, 'words', dataset, config, { received: `${count}`, }); } } return dataset; }, }; } ================================================ FILE: library/src/index.ts ================================================ export * from './actions/index.ts'; export * from './methods/index.ts'; export * from './regex.ts'; export * from './schemas/index.ts'; export * from './storages/index.ts'; export type { ArrayPathItem, BaseIssue, BaseMetadata, BaseSchema, BaseSchemaAsync, BaseTransformation, BaseTransformationAsync, BaseValidation, BaseValidationAsync, Config, Default, DefaultAsync, DefaultValue, ErrorMessage, FailureDataset, GenericIssue, GenericMetadata, GenericSchema, GenericSchemaAsync, GenericTransformation, GenericTransformationAsync, GenericValidation, GenericValidationAsync, GenericPipeAction, GenericPipeActionAsync, GenericPipeItem, GenericPipeItemAsync, InferInput, InferOutput, InferIssue, IssueDotPath, IssuePathItem, MapPathItem, ObjectPathItem, ObjectEntries, ObjectKeys, ObjectEntriesAsync, OutputDataset, PartialDataset, PipeAction, PipeActionAsync, PipeItem, PipeItemAsync, SchemaWithoutPipe, SetPathItem, SuccessDataset, StandardProps, TupleItems, TupleItemsAsync, UnknownDataset, UnknownPathItem, } from './types/index.ts'; export * from './utils/index.ts'; ================================================ FILE: library/src/methods/assert/assert.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { object, string } from '../../schemas/index.ts'; import { pipe } from '../pipe/pipe.ts'; import { assert } from './assert.ts'; describe('assert', () => { test('should assert input type of schema', () => { const input: unknown = { key: 'foo' }; assert( object({ key: pipe( string(), transform((input) => input.length) ), }), input ); expectTypeOf(input).toEqualTypeOf<{ key: string }>(); }); }); ================================================ FILE: library/src/methods/assert/assert.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { number, object, string } from '../../schemas/index.ts'; import { pipe } from '../pipe/index.ts'; import { assert } from './assert.ts'; describe('assert', () => { const entries = { key: pipe( string(), transform((input) => input.length) ), }; test('should not throw for valid input', () => { expect(() => assert(string(), 'foo')).not.toThrowError(); expect(() => assert(number(), 123)).not.toThrowError(); expect(() => assert(object(entries), { key: 'foo' })).not.toThrowError(); }); test('should throw for invalid input', () => { expect(() => assert(string(), 123)).toThrowError(); expect(() => assert(number(), 'foo')).toThrowError(); expect(() => assert(object(entries), null)).toThrowError(); }); }); ================================================ FILE: library/src/methods/assert/assert.ts ================================================ import type { BaseIssue, BaseSchema, InferInput } from '../../types/index.ts'; import { ValiError } from '../../utils/index.ts'; /** * Checks if the input matches the schema. As this is an assertion function, it * can be used as a type guard. * * @param schema The schema to be used. * @param input The input to be tested. */ export function assert< const TSchema extends BaseSchema>, >(schema: TSchema, input: unknown): asserts input is InferInput { const issues = schema['~run']({ value: input }, { abortEarly: true }).issues; if (issues) { throw new ValiError(issues); } } ================================================ FILE: library/src/methods/assert/index.ts ================================================ export * from './assert.ts'; ================================================ FILE: library/src/methods/cache/_LruCache.test.ts ================================================ import { afterAll, beforeEach, describe, expect, test, vi } from 'vitest'; import { _LruCache } from './_LruCache.ts'; describe('_LruCache', () => { test('should create stable keys for the same input and config', () => { const cache = new _LruCache(); const input = { key: 'foo' }; const config = { lang: 'de', abortEarly: true }; expect(cache.key(input, config)).toBe(cache.key(input, config)); }); test('should create different keys for different configs', () => { const cache = new _LruCache(); expect(cache.key('foo', { lang: 'de' })).not.toBe( cache.key('foo', { lang: 'en' }) ); }); test('should create different keys for different abort configs', () => { const cache = new _LruCache(); expect(cache.key('foo', {})).not.toBe( cache.key('foo', { abortEarly: true }) ); }); test('should distinguish numbers and bigints', () => { const cache = new _LruCache(); expect(cache.key(1, {})).not.toBe(cache.key(1n, {})); }); test('should handle null input', () => { const cache = new _LruCache(); expect(cache.key(null, {})).toContain('null'); }); test('should include symbol type for symbol input', () => { const cache = new _LruCache(); expect(cache.key(Symbol('foo'), {})).toBe( 'symbol|undefined|undefined|undefined|undefined' ); }); test('should create different keys for different object references', () => { const cache = new _LruCache(); expect(cache.key({}, {})).not.toBe(cache.key({}, {})); }); test('should return undefined on cache miss', () => { const cache = new _LruCache(); expect(cache.get('foo')).toBeUndefined(); }); test('should get stored values by key', () => { const cache = new _LruCache(); cache.set('foo', 'bar'); expect(cache.get('foo')).toBe('bar'); }); test('should clear stored values', () => { const cache = new _LruCache(); cache.set('foo', 'bar'); cache.clear(); expect(cache.get('foo')).toBeUndefined(); }); describe('should allow custom max age', () => { beforeEach(() => { vi.useFakeTimers(); }); afterAll(() => { vi.useRealTimers(); }); test('and clear expired values', () => { const cache = new _LruCache({ maxAge: 1000 }); cache.set('foo', 'bar'); expect(cache.get('foo')).toBe('bar'); vi.advanceTimersByTime(1001); expect(cache.get('foo')).toBeUndefined(); }); test('and not reset expiry on get', () => { const cache = new _LruCache({ maxAge: 1000 }); cache.set('foo', 'bar'); expect(cache.get('foo')).toBe('bar'); vi.advanceTimersByTime(500); expect(cache.get('foo')).toBe('bar'); vi.advanceTimersByTime(501); expect(cache.get('foo')).toBeUndefined(); }); }); test('should evict oldest key when max size is exceeded', () => { const cache = new _LruCache({ maxSize: 2 }); cache.set('foo', 'foo'); cache.set('bar', 'bar'); cache.set('baz', 'baz'); expect(cache.get('foo')).toBeUndefined(); expect(cache.get('bar')).toBe('bar'); expect(cache.get('baz')).toBe('baz'); }); }); ================================================ FILE: library/src/methods/cache/_LruCache.ts ================================================ import type { BaseIssue, Config } from '../../types/index.ts'; import type { Cache, CacheConfig } from './types.ts'; /** * Efficient LRU cache using Map iteration order. */ class _LruCache implements Cache { // Stores [value, timestamp] tuples to avoid object allocation overhead private store: Map | undefined; // Assign stable IDs to references private refIds: WeakMap | undefined; // Counter for tracking references private refCount = 0; // Cache configuration private readonly maxSize: number; private readonly maxAge: number; private readonly hasMaxAge: boolean; constructor(config?: CacheConfig) { this.maxSize = config?.maxSize ?? 1000; this.maxAge = config?.maxAge ?? Infinity; this.hasMaxAge = isFinite(this.maxAge); } /** * Stringifies an unknown input to a cache key component. * * @param input The unknown input. * * @returns A cache key component. */ #stringify(input: unknown): string { const type = typeof input; if (type === 'string') { return `"${input}"`; } if (type === 'number' || type === 'boolean') { return `${input}`; } if (type === 'bigint') { return `${input}n`; } if (type === 'object' || type === 'function') { if (input) { this.refIds ??= new WeakMap(); let id = this.refIds.get(input as WeakKey); if (!id) { id = ++this.refCount; this.refIds.set(input as WeakKey, id); } return `#${id}`; } return 'null'; } return type; } /** * Creates a cache key from input and config. * * @param input The input value. * @param config The parse configuration. * * @returns The cache key. */ key(input: unknown, config: Config> = {}): string { return `${this.#stringify(input)}|${this.#stringify(config.lang)}|${this.#stringify( config.message )}|${this.#stringify(config.abortEarly)}|${this.#stringify( config.abortPipeEarly )}`; } /** * Gets a value from the cache by key. * * @param key The cache key. * * @returns The cached value. */ get(key: string): TValue | undefined { if (!this.store) return undefined; // Get entry tuple [value, timestamp] const entry = this.store.get(key); // Return undefined if not found if (!entry) return undefined; // Delete stale entry if maxAge is exceeded if (this.hasMaxAge && Date.now() - entry[1] > this.maxAge) { this.store.delete(key); return undefined; } // Reorder by deleting and re-inserting at end (most recently used) this.store.delete(key); this.store.set(key, entry); // Return cached value return entry[0]; } /** * Sets a value in the cache by key. * * @param key The cache key. * @param value The cached value. */ set(key: string, value: TValue): void { this.store ??= new Map(); // Delete first to ensure insertion at end for correct ordering this.store.delete(key); // Set value with current timestamp if maxAge is used const timestamp = this.hasMaxAge ? Date.now() : 0; this.store.set(key, [value, timestamp]); // Evict oldest entry (first key) if over maxSize if (this.store.size > this.maxSize) { this.store.delete(this.store.keys().next().value!); } } /** * Clears all entries from the cache. */ clear(): void { this.store?.clear(); } } export { _LruCache }; ================================================ FILE: library/src/methods/cache/cache.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { StringIssue, StringSchema } from '../../schemas/index.ts'; import { string } from '../../schemas/index.ts'; import type { InferInput, InferIssue, InferOutput, OutputDataset, } from '../../types/index.ts'; import type { SchemaWithCache } from './cache.ts'; import { cache } from './cache.ts'; import type { Cache } from './types.ts'; describe('cache', () => { describe('should return schema object', () => { test('without config', () => { const schema = string(); expectTypeOf(cache(schema)).toEqualTypeOf< SchemaWithCache >(); expectTypeOf(cache(schema, undefined)).toEqualTypeOf< SchemaWithCache >(); }); test('with config', () => { const schema = string(); expectTypeOf(cache(schema, { maxSize: 10 })).toMatchTypeOf< SchemaWithCache >(); expectTypeOf< SchemaWithCache >().toMatchTypeOf(cache(schema, { maxSize: 10 })); }); }); describe('should infer correct types', () => { type Schema = SchemaWithCache, undefined>; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); test('of cache', () => { expectTypeOf().toEqualTypeOf< Cache> >(); }); }); }); ================================================ FILE: library/src/methods/cache/cache.test.ts ================================================ import { describe, expect, test, vi } from 'vitest'; import { minLength, transform } from '../../actions/index.ts'; import { string } from '../../schemas/index.ts'; import { pipe } from '../index.ts'; import { cache, type SchemaWithCache } from './cache.ts'; describe('cache', () => { describe('should return schema object', () => { const schema = string(); type Schema = typeof schema; const baseSchema: Omit, 'cacheConfig'> = { ...schema, cache: expect.any(Object), '~run': expect.any(Function), }; test('without cache config', () => { expect(cache(schema)).toStrictEqual({ ...baseSchema, cacheConfig: undefined, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, } satisfies SchemaWithCache); }); test('with cache config', () => { expect(cache(schema, { maxSize: 123 })).toStrictEqual({ ...baseSchema, cacheConfig: { maxSize: 123 }, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, } satisfies SchemaWithCache); }); }); describe('should cache output', () => { test('for same input and config', () => { const baseSchema = string(); const runSpy = vi.spyOn(baseSchema, '~run'); const schema = cache(baseSchema); const dataset1 = schema['~run']({ value: 'foo' }, {}); const dataset2 = schema['~run']({ value: 'foo' }, {}); expect(dataset1).toStrictEqual({ typed: true, value: 'foo', issues: undefined, }); expect(dataset2).toStrictEqual({ typed: true, value: 'foo', issues: undefined, }); expect(dataset1).not.toBe(dataset2); expect(runSpy).toHaveBeenCalledTimes(1); }); test('without reusing mutated pipe datasets', () => { const baseSchema = string(); const runSpy = vi.spyOn(baseSchema, '~run'); const schema = pipe( cache(baseSchema), transform((input) => `${input}!`) ); expect(schema['~run']({ value: 'foo' }, {})).toStrictEqual({ typed: true, value: 'foo!', issues: undefined, }); expect(schema['~run']({ value: 'foo' }, {})).toStrictEqual({ typed: true, value: 'foo!', issues: undefined, }); expect(runSpy).toHaveBeenCalledTimes(1); }); }); describe('should respect config changes', () => { test('for lang config', () => { const baseSchema = string(); const runSpy = vi.spyOn(baseSchema, '~run'); const schema = cache(baseSchema); const defaultDataset = schema['~run']({ value: 'foo' }, {}); const langDataset = schema['~run']({ value: 'foo' }, { lang: 'de' }); const defaultDataset2 = schema['~run']({ value: 'foo' }, {}); const langDataset2 = schema['~run']({ value: 'foo' }, { lang: 'de' }); expect(defaultDataset).not.toBe(langDataset); expect(defaultDataset).toStrictEqual({ typed: true, value: 'foo', issues: undefined, }); expect(defaultDataset2).toStrictEqual({ typed: true, value: 'foo', issues: undefined, }); expect(defaultDataset2).not.toBe(defaultDataset); expect(langDataset).toStrictEqual({ typed: true, value: 'foo', issues: undefined, }); expect(langDataset2).toStrictEqual({ typed: true, value: 'foo', issues: undefined, }); expect(langDataset2).not.toBe(langDataset); expect(runSpy).toHaveBeenCalledTimes(2); }); test('for abort config', () => { const schema = cache(pipe(string(), minLength(4), minLength(6))); const defaultDataset = schema['~run']({ value: 'foo' }, {}); const abortDataset = schema['~run']( { value: 'foo' }, { abortEarly: true } ); expect(defaultDataset).not.toBe(abortDataset); expect(defaultDataset.issues).toHaveLength(2); expect(abortDataset.issues).toHaveLength(1); }); }); describe('should expose cache for manual clearing', () => { test('to invalidate cached output', () => { const baseSchema = string(); const runSpy = vi.spyOn(baseSchema, '~run'); const schema = cache(baseSchema); expect(schema['~run']({ value: 'foo' }, {})).toStrictEqual({ typed: true, value: 'foo', issues: undefined, }); expect(schema['~run']({ value: 'foo' }, {})).toStrictEqual({ typed: true, value: 'foo', issues: undefined, }); expect(runSpy).toHaveBeenCalledTimes(1); schema.cache.clear(); expect(schema['~run']({ value: 'foo' }, {})).toStrictEqual({ typed: true, value: 'foo', issues: undefined, }); expect(runSpy).toHaveBeenCalledTimes(2); }); }); }); ================================================ FILE: library/src/methods/cache/cache.ts ================================================ import type { OutputDataset } from '../../types/index.ts'; import type { BaseIssue, BaseSchema, InferIssue, InferOutput, } from '../../types/index.ts'; import { _cloneDataset, _getStandardProps } from '../../utils/index.ts'; import { _LruCache } from './_LruCache.ts'; import type { Cache, CacheConfig } from './types.ts'; /** * Schema with cache type. * * @beta */ export type SchemaWithCache< TSchema extends BaseSchema>, TCacheConfig extends CacheConfig | undefined, > = TSchema & { /** * The cache config. */ readonly cacheConfig: TCacheConfig; /** * The cache instance. */ readonly cache: Cache< OutputDataset, InferIssue> >; }; /** * Caches the output of a schema. * * Hint: Primitive inputs are cached by value. Object and function inputs are * cached by reference identity, so mutating input objects and reusing the same * reference can return a stale cached dataset. Returned objects are also * reused by reference, so mutating cached output can affect later cache hits. * * @param schema The schema to cache. * * @returns The cached schema. * * @beta */ export function cache< const TSchema extends BaseSchema>, >(schema: TSchema): SchemaWithCache; /** * Caches the output of a schema. * * Hint: Primitive inputs are cached by value. Object and function inputs are * cached by reference identity, so mutating input objects and reusing the same * reference can return a stale cached dataset. Returned objects are also * reused by reference, so mutating cached output can affect later cache hits. * * @param schema The schema to cache. * @param config The cache config. * * @returns The cached schema. * * @beta */ export function cache< const TSchema extends BaseSchema>, const TCacheConfig extends CacheConfig | undefined, >( schema: TSchema, config: TCacheConfig ): SchemaWithCache; // @__NO_SIDE_EFFECTS__ export function cache( schema: BaseSchema>, config?: CacheConfig ): SchemaWithCache< BaseSchema>, CacheConfig | undefined > { return { ...schema, cacheConfig: config, cache: new _LruCache(config), get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, runConfig) { const key = this.cache.key(dataset.value, runConfig); let outputDataset = this.cache.get(key); if (!outputDataset) { this.cache.set( key, (outputDataset = schema['~run'](dataset, runConfig)) ); } // Hint: We clone the dataset before returning it so downstream pipe items // do not mutate the cached dataset wrapper or issues array. return _cloneDataset(outputDataset); }, }; } ================================================ FILE: library/src/methods/cache/cacheAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { StringIssue, StringSchema } from '../../schemas/index.ts'; import { string } from '../../schemas/index.ts'; import type { InferInput, InferIssue, InferOutput, OutputDataset, } from '../../types/index.ts'; import type { SchemaWithCacheAsync } from './cacheAsync.ts'; import { cacheAsync } from './cacheAsync.ts'; import type { Cache } from './types.ts'; describe('cacheAsync', () => { describe('should return schema object', () => { test('without config', () => { const schema = string(); expectTypeOf(cacheAsync(schema)).toEqualTypeOf< SchemaWithCacheAsync >(); expectTypeOf(cacheAsync(schema, undefined)).toEqualTypeOf< SchemaWithCacheAsync >(); }); test('with config', () => { const schema = string(); expectTypeOf(cacheAsync(schema, { maxSize: 10 })).toMatchTypeOf< SchemaWithCacheAsync >(); expectTypeOf< SchemaWithCacheAsync >().toMatchTypeOf(cacheAsync(schema, { maxSize: 10 })); }); }); describe('should infer correct types', () => { type Schema = SchemaWithCacheAsync, undefined>; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); test('of cache', () => { expectTypeOf().toEqualTypeOf< Cache> >(); }); }); }); ================================================ FILE: library/src/methods/cache/cacheAsync.test.ts ================================================ import { describe, expect, test, vi } from 'vitest'; import { minLength, transformAsync } from '../../actions/index.ts'; import { string } from '../../schemas/index.ts'; import { pipe, pipeAsync } from '../index.ts'; import { cacheAsync, type SchemaWithCacheAsync } from './cacheAsync.ts'; describe('cacheAsync', () => { describe('should return schema object', () => { const schema = string(); type Schema = typeof schema; const baseSchema: Omit< SchemaWithCacheAsync, 'cacheConfig' > = { ...schema, async: true, cache: expect.any(Object), '~run': expect.any(Function), }; test('without cache config', () => { expect(cacheAsync(schema)).toStrictEqual({ ...baseSchema, cacheConfig: undefined, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, } satisfies SchemaWithCacheAsync); }); test('with cache config', () => { expect(cacheAsync(schema, { maxSize: 123 })).toStrictEqual({ ...baseSchema, cacheConfig: { maxSize: 123 }, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, } satisfies SchemaWithCacheAsync); }); }); describe('should cache output', () => { test('for same input and config', async () => { const baseSchema = string(); const runSpy = vi.spyOn(baseSchema, '~run'); const schema = cacheAsync(baseSchema); const dataset1 = await schema['~run']({ value: 'foo' }, {}); const dataset2 = await schema['~run']({ value: 'foo' }, {}); expect(dataset1).toStrictEqual({ typed: true, value: 'foo', issues: undefined, }); expect(dataset2).toStrictEqual({ typed: true, value: 'foo', issues: undefined, }); expect(dataset1).not.toBe(dataset2); expect(runSpy).toHaveBeenCalledTimes(1); }); test('without reusing mutated pipe datasets', async () => { const baseSchema = string(); const runSpy = vi.spyOn(baseSchema, '~run'); const schema = pipeAsync( cacheAsync(baseSchema), transformAsync(async (input) => `${input}!`) ); await expect(schema['~run']({ value: 'foo' }, {})).resolves.toStrictEqual( { typed: true, value: 'foo!', issues: undefined, } ); await expect(schema['~run']({ value: 'foo' }, {})).resolves.toStrictEqual( { typed: true, value: 'foo!', issues: undefined, } ); expect(runSpy).toHaveBeenCalledTimes(1); }); }); describe('should respect config changes', () => { test('for lang config', async () => { const baseSchema = string(); const runSpy = vi.spyOn(baseSchema, '~run'); const schema = cacheAsync(baseSchema); const defaultDataset = await schema['~run']({ value: 'foo' }, {}); const langDataset = await schema['~run']( { value: 'foo' }, { lang: 'de' } ); const defaultDataset2 = await schema['~run']({ value: 'foo' }, {}); const langDataset2 = await schema['~run']( { value: 'foo' }, { lang: 'de' } ); expect(defaultDataset).not.toBe(langDataset); expect(defaultDataset).toStrictEqual({ typed: true, value: 'foo', issues: undefined, }); expect(defaultDataset2).toStrictEqual({ typed: true, value: 'foo', issues: undefined, }); expect(defaultDataset2).not.toBe(defaultDataset); expect(langDataset).toStrictEqual({ typed: true, value: 'foo', issues: undefined, }); expect(langDataset2).toStrictEqual({ typed: true, value: 'foo', issues: undefined, }); expect(langDataset2).not.toBe(langDataset); expect(runSpy).toHaveBeenCalledTimes(2); }); test('for abort config', async () => { const schema = cacheAsync(pipe(string(), minLength(4), minLength(6))); const defaultDataset = await schema['~run']({ value: 'foo' }, {}); const abortDataset = await schema['~run']( { value: 'foo' }, { abortEarly: true } ); expect(defaultDataset).not.toBe(abortDataset); expect(defaultDataset.issues).toHaveLength(2); expect(abortDataset.issues).toHaveLength(1); }); }); describe('should expose cache for manual clearing', () => { test('to invalidate cached output', async () => { const baseSchema = string(); const runSpy = vi.spyOn(baseSchema, '~run'); const schema = cacheAsync(baseSchema); await expect(schema['~run']({ value: 'foo' }, {})).resolves.toStrictEqual( { typed: true, value: 'foo', issues: undefined, } ); await expect(schema['~run']({ value: 'foo' }, {})).resolves.toStrictEqual( { typed: true, value: 'foo', issues: undefined, } ); expect(runSpy).toHaveBeenCalledTimes(1); schema.cache.clear(); await expect(schema['~run']({ value: 'foo' }, {})).resolves.toStrictEqual( { typed: true, value: 'foo', issues: undefined, } ); expect(runSpy).toHaveBeenCalledTimes(2); }); }); describe('should deduplicate concurrent calls', () => { test('for matching input and config', async () => { const baseSchema = string(); const runSpy = vi.spyOn(baseSchema, '~run'); const schema = cacheAsync(baseSchema); const promise1 = schema['~run']({ value: 'foo' }, {}); const promise2 = schema['~run']({ value: 'foo' }, {}); const [dataset1, dataset2] = await Promise.all([promise1, promise2]); expect(dataset1).toStrictEqual(dataset2); expect(dataset1).not.toBe(dataset2); expect(runSpy).toHaveBeenCalledTimes(1); }); }); describe('should retry after rejection', () => { test('for later calls', async () => { const baseSchema = string(); vi.spyOn(baseSchema, '~run').mockReturnValueOnce( Promise.reject(new Error('test error')) as never ); const schema = cacheAsync(baseSchema); await expect(schema['~run']({ value: 'foo' }, {})).rejects.toThrow( 'test error' ); await expect(schema['~run']({ value: 'foo' }, {})).resolves.toStrictEqual( { typed: true, value: 'foo', issues: undefined, } ); }); }); describe('should propagate errors', () => { test('to concurrent callers', async () => { const baseSchema = string(); const runSpy = vi .spyOn(baseSchema, '~run') .mockReturnValue(Promise.reject(new Error('test error')) as never); const schema = cacheAsync(baseSchema); const promise1 = schema['~run']({ value: 'foo' }, {}); const promise2 = schema['~run']({ value: 'foo' }, {}); await expect(promise1).rejects.toThrow('test error'); await expect(promise2).rejects.toThrow('test error'); expect(runSpy).toHaveBeenCalledTimes(1); }); }); }); ================================================ FILE: library/src/methods/cache/cacheAsync.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, Config, InferInput, InferIssue, InferOutput, OutputDataset, StandardProps, UnknownDataset, } from '../../types/index.ts'; import { _cloneDataset, _getStandardProps } from '../../utils/index.ts'; import { _LruCache } from './_LruCache.ts'; import type { Cache, CacheConfig } from './types.ts'; /** * Schema with cache async type. * * @beta */ export type SchemaWithCacheAsync< TSchema extends | BaseSchema> | BaseSchemaAsync>, TCacheConfig extends CacheConfig | undefined, > = Omit & { /** * Whether it's async. */ readonly async: true; /** * The cache config. */ readonly cacheConfig: TCacheConfig; /** * The cache instance. */ readonly cache: Cache< OutputDataset, InferIssue> >; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferInput, InferOutput >; /** * Parses unknown input values. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => Promise, InferIssue>>; }; /** * Caches the output of a schema. * * Hint: Primitive inputs are cached by value. Object and function inputs are * cached by reference identity, so mutating input objects and reusing the same * reference can return a stale cached dataset. Returned objects are also * reused by reference, so mutating cached output can affect later cache hits. * * @param schema The schema to cache. * * @returns The cached schema. * * @beta */ // @ts-expect-error export function cacheAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, >(schema: TSchema): SchemaWithCacheAsync; /** * Caches the output of a schema. * * Hint: Primitive inputs are cached by value. Object and function inputs are * cached by reference identity, so mutating input objects and reusing the same * reference can return a stale cached dataset. Returned objects are also * reused by reference, so mutating cached output can affect later cache hits. * * @param schema The schema to cache. * @param config The cache config. * * @returns The cached schema. * * @beta */ export function cacheAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TCacheConfig extends CacheConfig | undefined, >( schema: TSchema, config: TCacheConfig ): SchemaWithCacheAsync; // @__NO_SIDE_EFFECTS__ export function cacheAsync( schema: | BaseSchema> | BaseSchemaAsync>, config?: CacheConfig ): SchemaWithCacheAsync< | BaseSchema> | BaseSchemaAsync>, CacheConfig | undefined > { let activeRuns: | Map>>> | undefined; return { ...schema, async: true, cacheConfig: config, cache: new _LruCache(config), get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, runConfig) { // Create cache key based on input and config const key = this.cache.key(dataset.value, runConfig); // Check and return cached output if exists const cached = this.cache.get(key); if (cached) { // Hint: We clone the dataset before returning it so downstream pipe // items do not mutate the cached dataset wrapper or issues array. return _cloneDataset(cached); } // If not cached, check if a matching run is already in progress let promise = activeRuns?.get(key); if (!promise) { activeRuns ??= new Map(); promise = Promise.resolve(schema['~run'](dataset, runConfig)); activeRuns.set(key, promise); } // Await pending promise, cache output and return try { const outputDataset = await promise; this.cache.set(key, outputDataset); // Hint: We clone the dataset before returning it so downstream pipe // items do not mutate the cached dataset wrapper or issues array. return _cloneDataset(outputDataset); // Cleanup active runs map } finally { activeRuns?.delete(key); } }, }; } ================================================ FILE: library/src/methods/cache/index.ts ================================================ export * from './cache.ts'; export * from './cacheAsync.ts'; export * from './types.ts'; ================================================ FILE: library/src/methods/cache/types.ts ================================================ import type { BaseIssue, Config } from '../../types/index.ts'; /** * Cache interface type. * * @beta */ export interface Cache { /** * Creates a cache key from input and config. * * Hint: Primitive inputs are keyed by value. Object and function inputs are * keyed by reference identity. */ key(input: unknown, config?: Config>): string; /** * Gets a value from the cache by key. */ get(key: string): TValue | undefined; /** * Sets a value in the cache by key. */ set(key: string, value: TValue): void; /** * Clears all entries from the cache. */ clear(): void; } /** * Cache config type. * * @beta */ export interface CacheConfig { /** * The maximum number of items to cache. * * @default 1000 */ maxSize?: number; /** * The maximum age of a cache entry in milliseconds. * * @default Infinity */ maxAge?: number; } ================================================ FILE: library/src/methods/config/config.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { objectAsync, string } from '../../schemas/index.ts'; import { config } from './config.ts'; describe('config', () => { test('should return schema object', () => { const schema = string(); expectTypeOf(config(schema, { abortEarly: true })).toEqualTypeOf< typeof schema >(); }); test('should return async schema object', () => { const schema = objectAsync({ key: string() }); expectTypeOf(config(schema, { abortEarly: true })).toEqualTypeOf< typeof schema >(); }); }); ================================================ FILE: library/src/methods/config/config.test.ts ================================================ import { describe, expect, test, vi } from 'vitest'; import { objectAsync, string } from '../../schemas/index.ts'; import type { BaseIssue, Config } from '../../types/index.ts'; import { config } from './config.ts'; describe('config', () => { test('should return copy of passed schema', () => { expect(config(string(), {})).toStrictEqual({ kind: 'schema', type: 'string', reference: string, expects: 'string', async: false, message: undefined, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }); }); test('should override config of schema', () => { const schema = string(); // @ts-expect-error schema['~run'] = vi.fn(schema['~run']); const dataset = { value: 'foo' }; const globalConfig: Config> = { lang: 'de', }; const localConfig: Config> = { abortPipeEarly: true, }; config(schema, localConfig)['~run'](dataset, globalConfig); expect(schema['~run']).toHaveBeenCalledWith(dataset, { ...globalConfig, ...localConfig, }); }); test('should override config of async schema', () => { const schema = objectAsync({ key: string() }); // @ts-expect-error schema['~run'] = vi.fn(schema['~run']); const dataset = { value: { key: 'foo' } }; const globalConfig: Config> = { lang: 'de', }; const localConfig: Config> = { abortEarly: true, lang: 'en', }; config(schema, localConfig)['~run'](dataset, globalConfig); expect(schema['~run']).toHaveBeenCalledWith(dataset, { ...globalConfig, ...localConfig, }); }); }); ================================================ FILE: library/src/methods/config/config.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, Config, InferIssue, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; /** * Changes the local configuration of a schema. * * @param schema The schema to configure. * @param config The parse configuration. * * @returns The configured schema. */ // @__NO_SIDE_EFFECTS__ export function config< const TSchema extends | BaseSchema> | BaseSchemaAsync>, >(schema: TSchema, config: Config>): TSchema { return { ...schema, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config_) { return schema['~run'](dataset, { ...config_, ...config }); }, }; } ================================================ FILE: library/src/methods/config/index.ts ================================================ export * from './config.ts'; ================================================ FILE: library/src/methods/fallback/fallback.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { transform, type TransformAction } from '../../actions/index.ts'; import type { ArrayIssue, ArraySchema } from '../../schemas/array/index.ts'; import { number, type NumberIssue, type NumberSchema, } from '../../schemas/index.ts'; import type { ObjectIssue, ObjectSchema } from '../../schemas/object/index.ts'; import type { StringIssue, StringSchema } from '../../schemas/string/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { InferFallback } from '../getFallback/index.ts'; import { pipe, type SchemaWithPipe } from '../pipe/index.ts'; import { fallback, type SchemaWithFallback } from './fallback.ts'; describe('fallback', () => { describe('should return schema object', () => { const schema = pipe(number(), transform(String)); type Schema = typeof schema; test('with value fallback', () => { expectTypeOf(fallback(schema, '123' as const)).toEqualTypeOf< SchemaWithFallback >(); }); test('with function fallback', () => { expectTypeOf(fallback(schema, () => '123' as const)).toEqualTypeOf< SchemaWithFallback '123'> >(); }); }); describe('should infer correct types', () => { type Schema1 = SchemaWithFallback< SchemaWithPipe< [NumberSchema, TransformAction] >, () => '123' >; type Schema2 = SchemaWithFallback< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, { readonly foo: readonly string[] } >; type Schema3 = SchemaWithFallback< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, () => { readonly foo: readonly string[] } >; test('of input', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); }); test('of fallback', () => { expectTypeOf>().toEqualTypeOf<'123'>(); expectTypeOf>().toEqualTypeOf<{ readonly foo: readonly string[]; }>(); expectTypeOf>().toEqualTypeOf<{ readonly foo: readonly string[]; }>(); }); }); }); ================================================ FILE: library/src/methods/fallback/fallback.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { boolean, number, union } from '../../schemas/index.ts'; import { pipe } from '../pipe/index.ts'; import { fallback, type SchemaWithFallback } from './fallback.ts'; describe('fallback', () => { describe('should return schema object', () => { const schema = pipe(number(), transform(String)); type Schema = typeof schema; const baseSchema: Omit, 'fallback'> = { ...schema, '~run': expect.any(Function), }; test('with value fallback', () => { expect(fallback(schema, '123')).toStrictEqual({ ...baseSchema, fallback: '123', '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, } satisfies SchemaWithFallback); }); test('with function fallback', () => { const fallbackArg = () => '123'; expect(fallback(schema, fallbackArg)).toStrictEqual({ ...baseSchema, fallback: fallbackArg, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, } satisfies SchemaWithFallback); }); }); const schema = fallback( pipe(union([number(), boolean()]), transform(String)), '123' ); describe('should return default dataset', () => { test('for valid input', () => { expect(schema['~run']({ value: 789 }, {})).toStrictEqual({ typed: true, value: '789', }); }); }); describe('should return dataset with fallback', () => { test('for invalid input', () => { expect(schema['~run']({ value: 'foo' }, {})).toStrictEqual({ typed: true, value: '123', }); }); }); }); ================================================ FILE: library/src/methods/fallback/fallback.ts ================================================ import type { BaseIssue, BaseSchema, Config, InferIssue, InferOutput, MaybeDeepReadonly, OutputDataset, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; import { getFallback } from '../getFallback/index.ts'; /** * Fallback type. */ export type Fallback< TSchema extends BaseSchema>, > = | MaybeDeepReadonly> | (( dataset?: OutputDataset, InferIssue>, config?: Config> ) => MaybeDeepReadonly>); /** * Schema with fallback type. */ export type SchemaWithFallback< TSchema extends BaseSchema>, TFallback extends Fallback, > = TSchema & { /** * The fallback value. */ readonly fallback: TFallback; }; /** * Returns a fallback value as output if the input does not match the schema. * * @param schema The schema to catch. * @param fallback The fallback value. * * @returns The passed schema. */ // @__NO_SIDE_EFFECTS__ export function fallback< const TSchema extends BaseSchema>, const TFallback extends Fallback, >( schema: TSchema, fallback: TFallback ): SchemaWithFallback { return { ...schema, fallback, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { const outputDataset = schema['~run'](dataset, config); return outputDataset.issues ? { typed: true, value: getFallback(this, outputDataset, config) } : outputDataset; }, }; } ================================================ FILE: library/src/methods/fallback/fallbackAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { transform, type TransformAction } from '../../actions/index.ts'; import type { ArrayIssue, ArraySchema } from '../../schemas/array/index.ts'; import { number, type NumberIssue, type NumberSchema, } from '../../schemas/index.ts'; import type { ObjectIssue, ObjectSchema } from '../../schemas/object/index.ts'; import type { StringIssue, StringSchema } from '../../schemas/string/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { InferFallback } from '../getFallback/index.ts'; import { pipe, type SchemaWithPipe } from '../pipe/index.ts'; import { fallbackAsync, type SchemaWithFallbackAsync, } from './fallbackAsync.ts'; describe('fallbackAsync', () => { describe('should return schema object', () => { const schema = pipe(number(), transform(String)); type Schema = typeof schema; test('with value fallback', () => { expectTypeOf(fallbackAsync(schema, '123' as const)).toEqualTypeOf< SchemaWithFallbackAsync >(); }); test('with function fallback', () => { expectTypeOf(fallbackAsync(schema, () => '123' as const)).toEqualTypeOf< SchemaWithFallbackAsync '123'> >(); }); test('with async function fallback', () => { expectTypeOf( fallbackAsync(schema, async () => '123' as const) ).toEqualTypeOf Promise<'123'>>>(); }); }); describe('should infer correct types', () => { type Schema1 = SchemaWithFallbackAsync< SchemaWithPipe< [NumberSchema, TransformAction] >, () => Promise<'123'> >; type Schema2 = SchemaWithFallbackAsync< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, { readonly foo: readonly string[] } >; type Schema3 = SchemaWithFallbackAsync< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, () => { readonly foo: readonly string[] } >; type Schema4 = SchemaWithFallbackAsync< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, () => Promise<{ readonly foo: readonly string[] }> >; test('of input', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); }); test('of fallback', () => { expectTypeOf>().toEqualTypeOf>(); expectTypeOf>().toEqualTypeOf<{ readonly foo: readonly string[]; }>(); expectTypeOf>().toEqualTypeOf<{ readonly foo: readonly string[]; }>(); expectTypeOf>().toEqualTypeOf< Promise<{ readonly foo: readonly string[] }> >(); }); }); }); ================================================ FILE: library/src/methods/fallback/fallbackAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { transformAsync } from '../../actions/index.ts'; import { boolean, number, union } from '../../schemas/index.ts'; import { pipeAsync } from '../pipe/index.ts'; import { fallbackAsync, type SchemaWithFallbackAsync, } from './fallbackAsync.ts'; describe('fallbackAsync', () => { describe('should return schema object', () => { const schema = pipeAsync( number(), transformAsync(async (input) => String(input)) ); type Schema = typeof schema; const baseSchema: Omit< SchemaWithFallbackAsync, 'fallback' > = { ...schema, async: true, '~run': expect.any(Function), }; test('with value fallback', () => { expect(fallbackAsync(schema, '123')).toStrictEqual({ ...baseSchema, fallback: '123', '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, } satisfies SchemaWithFallbackAsync); }); test('with function fallback', () => { const fallbackArg = () => '123'; expect(fallbackAsync(schema, fallbackArg)).toStrictEqual({ ...baseSchema, fallback: fallbackArg, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, } satisfies SchemaWithFallbackAsync); }); test('with async function fallback', () => { const fallbackArg = async () => '123'; expect(fallbackAsync(schema, fallbackArg)).toStrictEqual({ ...baseSchema, fallback: fallbackArg, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, } satisfies SchemaWithFallbackAsync); }); }); const schema = fallbackAsync( pipeAsync( union([number(), boolean()]), transformAsync(async (input) => String(input)) ), async () => '123' ); describe('should return default dataset', () => { test('for valid input', async () => { expect(await schema['~run']({ value: 789 }, {})).toStrictEqual({ typed: true, value: '789', }); }); }); describe('should return dataset with fallback', () => { test('for invalid input', async () => { expect(await schema['~run']({ value: 'foo' }, {})).toStrictEqual({ typed: true, value: '123', }); }); }); }); ================================================ FILE: library/src/methods/fallback/fallbackAsync.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, Config, InferInput, InferIssue, InferOutput, MaybeDeepReadonly, MaybePromise, OutputDataset, StandardProps, UnknownDataset, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; import { getFallback } from '../getFallback/index.ts'; /** * Fallback async type. */ export type FallbackAsync< TSchema extends | BaseSchema> | BaseSchemaAsync>, > = | MaybeDeepReadonly> | (( dataset?: OutputDataset, InferIssue>, config?: Config> ) => MaybePromise>>); /** * Schema with fallback async type. */ export type SchemaWithFallbackAsync< TSchema extends | BaseSchema> | BaseSchemaAsync>, TFallback extends FallbackAsync, > = Omit & { /** * The fallback value. */ readonly fallback: TFallback; /** * Whether it's async. */ readonly async: true; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferInput, InferOutput >; /** * Parses unknown input values. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => Promise, InferIssue>>; }; /** * Returns a fallback value as output if the input does not match the schema. * * @param schema The schema to catch. * @param fallback The fallback value. * * @returns The passed schema. */ // @__NO_SIDE_EFFECTS__ export function fallbackAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TFallback extends FallbackAsync, >( schema: TSchema, fallback: TFallback ): SchemaWithFallbackAsync { return { ...schema, fallback, async: true, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { const outputDataset = await schema['~run'](dataset, config); return outputDataset.issues ? { typed: true, value: await getFallback(this, outputDataset, config), } : outputDataset; }, }; } ================================================ FILE: library/src/methods/fallback/index.ts ================================================ export * from './fallback.ts'; export * from './fallbackAsync.ts'; ================================================ FILE: library/src/methods/flatten/flatten.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { ArraySchema, NumberIssue, NumberSchema, ObjectSchema, } from '../../schemas/index.ts'; import type { ArrayPathItem, ObjectPathItem } from '../../types/index.ts'; import { flatten } from './flatten.ts'; describe('flatten', () => { const issues: [NumberIssue] = [ { kind: 'schema', type: 'number', input: 'foo', expected: 'number', received: '"foo"', message: 'Invalid type: Expected number but received "foo"', path: [ { type: 'object', origin: 'value', input: { dot: [{ path: 'foo' }] }, key: 'dot', value: [{ path: 'foo' }], } satisfies ObjectPathItem, { type: 'array', origin: 'value', input: [{ path: 'foo' }], key: 0, value: { path: 'foo' }, } satisfies ArrayPathItem, { type: 'object', origin: 'value', input: { path: 'foo' }, key: 'path', value: 'foo', } satisfies ObjectPathItem, ], abortEarly: undefined, abortPipeEarly: undefined, issues: undefined, lang: undefined, }, ]; test('should return generic flat errors', () => { expectTypeOf(flatten(issues)).toEqualTypeOf<{ readonly root?: [string, ...string[]]; readonly nested?: Readonly< Partial> >; readonly other?: [string, ...string[]]; }>(); }); test('should return specific flat errors', () => { type Schema = ObjectSchema< { dot: ArraySchema< ObjectSchema<{ path: NumberSchema }, undefined>, undefined >; }, undefined >; expectTypeOf(flatten(issues)).toEqualTypeOf<{ readonly root?: [string, ...string[]]; readonly nested?: Readonly< Partial< Record< 'dot' | `dot.${number}` | `dot.${number}.path`, [string, ...string[]] > > >; readonly other?: [string, ...string[]]; }>(); }); }); ================================================ FILE: library/src/methods/flatten/flatten.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { CheckIssue, IncludesIssue, MinLengthIssue, MinValueIssue, } from '../../actions'; import type { NumberIssue, StringIssue } from '../../schemas'; import type { ArrayPathItem, ObjectPathItem, SetPathItem } from '../../types'; import { flatten } from './flatten.ts'; describe('flatten', () => { const commonIssueInfo = { abortEarly: undefined, abortPipeEarly: undefined, issues: undefined, lang: undefined, }; test('should return empty object', () => { // @ts-expect-error expect(flatten([])).toStrictEqual({}); }); test('should return single root error', () => { const rootIssues1: [StringIssue] = [ { ...commonIssueInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', message: 'Invalid type: Expected string but received 123', path: undefined, }, ]; expect(flatten(rootIssues1)).toStrictEqual({ root: ['Invalid type: Expected string but received 123'], }); }); test('should return multiple root errors', () => { const rootIssues2: [ IncludesIssue, MinLengthIssue, ] = [ { ...commonIssueInfo, kind: 'validation', type: 'includes', input: '123', expected: '"foo"', received: '!"foo"', message: 'Invalid content: Expected "foo" but received !"foo"', requirement: 'foo', path: undefined, }, { ...commonIssueInfo, kind: 'validation', type: 'min_length', input: '123', expected: '>=5', received: '3', message: 'Invalid length: Expected >=5 but received 3', requirement: 5, path: undefined, }, ]; expect(flatten(rootIssues2)).toStrictEqual({ root: [ 'Invalid content: Expected "foo" but received !"foo"', 'Invalid length: Expected >=5 but received 3', ], }); }); test('should return single nested error', () => { const nestedIssue: NumberIssue = { ...commonIssueInfo, kind: 'schema', type: 'number', input: '1', expected: 'number', received: '"1"', message: 'Invalid type: Expected number but received "1"', path: [ { type: 'array', origin: 'value', input: ['1'], key: 0, value: '1', } satisfies ArrayPathItem, ], }; expect(flatten([nestedIssue])).toStrictEqual({ nested: { 0: ['Invalid type: Expected number but received "1"'], }, }); }); test('should return multiple nested errors', () => { const input = { key1: 'bar', key2: '21', }; const nestedIssues: [ IncludesIssue, MinLengthIssue, NumberIssue, ] = [ { ...commonIssueInfo, kind: 'validation', type: 'includes', input: '123', expected: '"foo"', received: '!"foo"', message: 'Invalid content: Expected "foo" but received !"foo"', requirement: 'foo', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: input.key1, } satisfies ObjectPathItem, ], }, { ...commonIssueInfo, kind: 'validation', type: 'min_length', input: '123', expected: '>=5', received: '3', message: 'Invalid length: Expected >=5 but received 3', requirement: 5, path: [ { type: 'object', origin: 'value', input, key: 'key1', value: input.key1, } satisfies ObjectPathItem, ], }, { expected: 'number', input: '21', kind: 'schema', message: 'Invalid type: Expected number but received "21"', path: [ { type: 'object', origin: 'value', input, key: 'key2', value: input.key2, } satisfies ObjectPathItem, ], received: '"21"', type: 'number', }, ]; expect(flatten(nestedIssues)).toStrictEqual({ nested: { key1: [ 'Invalid content: Expected "foo" but received !"foo"', 'Invalid length: Expected >=5 but received 3', ], key2: ['Invalid type: Expected number but received "21"'], }, }); }); test('should return nested error with dot path', () => { const nestedIssue: NumberIssue = { ...commonIssueInfo, kind: 'schema', type: 'number', input: 'foo', expected: 'number', received: '"foo"', message: 'Invalid type: Expected number but received "foo"', path: [ { type: 'object', origin: 'value', input: { dot: [{ path: 'foo' }] }, key: 'dot', value: [{ path: 'foo' }], } satisfies ObjectPathItem, { type: 'array', origin: 'value', input: [{ path: 'foo' }], key: 0, value: { path: 'foo' }, } satisfies ArrayPathItem, { type: 'object', origin: 'value', input: { path: 'foo' }, key: 'path', value: 'foo', } satisfies ObjectPathItem, ], }; expect(flatten([nestedIssue])).toStrictEqual({ nested: { 'dot.0.path': ['Invalid type: Expected number but received "foo"'], }, }); }); test('should return single other error', () => { const otherIssue: NumberIssue = { ...commonIssueInfo, kind: 'schema', type: 'number', input: 'abc', expected: 'number', received: '"abc"', message: 'Invalid type: Expected number but received "abc"', path: [ { type: 'set', origin: 'value', input: new Set(['abc']), key: null, value: 'abc', } satisfies SetPathItem, ], }; expect(flatten([otherIssue])).toStrictEqual({ other: ['Invalid type: Expected number but received "abc"'], }); }); test('should return multiple other errors', () => { const input = new Set(['abc']); const otherIssues: [ IncludesIssue, MinLengthIssue, ] = [ { ...commonIssueInfo, kind: 'validation', type: 'includes', input: 'abc', received: '!"bar"', expected: '"bar"', message: 'Invalid content: Expected "bar" but received !"bar"', requirement: 'bar', path: [ { type: 'set', origin: 'value', input, key: null, value: 'abc', } satisfies SetPathItem, ], }, { ...commonIssueInfo, kind: 'validation', type: 'min_length', input: 'abc', expected: '>=4', received: '3', message: 'Invalid length: Expected >=4 but received 3', requirement: 4, path: [ { type: 'set', origin: 'value', input, key: null, value: 'abc', } satisfies SetPathItem, ], }, ]; expect(flatten(otherIssues)).toStrictEqual({ other: [ 'Invalid content: Expected "bar" but received !"bar"', 'Invalid length: Expected >=4 but received 3', ], }); }); test('should return different kind of errors', () => { const input = { positiveValue: -1, positiveNums: new Set([-1]) }; const issues: [ MinValueIssue, MinValueIssue, CheckIssue, ] = [ { ...commonIssueInfo, kind: 'validation', type: 'min_value', input: -1, received: '-1', expected: '>=0', message: 'Invalid value: Expected >=0 but received -1', requirement: 0, path: [ { type: 'object', origin: 'value', input, key: 'positiveValue', value: -1, } satisfies ObjectPathItem, ], }, { ...commonIssueInfo, kind: 'validation', type: 'min_value', input: -1, expected: '>=0', received: '-1', message: 'Invalid value: Expected >=0 but received -1', requirement: 0, path: [ { type: 'object', origin: 'value', input, key: 'positiveNums', value: input['positiveNums'], }, { type: 'set', origin: 'value', input: input['positiveNums'], key: null, value: -1, }, ] satisfies [ObjectPathItem, SetPathItem], }, { ...commonIssueInfo, kind: 'validation', type: 'check', input, expected: null, received: 'Object', requirement: () => false, message: 'Invalid input: Received Object', }, ]; expect(flatten(issues)).toStrictEqual({ root: ['Invalid input: Received Object'], nested: { positiveValue: ['Invalid value: Expected >=0 but received -1'], }, other: ['Invalid value: Expected >=0 but received -1'], }); }); }); ================================================ FILE: library/src/methods/flatten/flatten.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, InferIssue, IssueDotPath, Prettify, } from '../../types/index.ts'; import { getDotPath } from '../../utils/index.ts'; /** * Flat errors type. */ export type FlatErrors< TSchema extends | BaseSchema> | BaseSchemaAsync> | undefined, > = Prettify<{ /** * The root errors. * * Hint: The error messages of issues without a path that belong to the root * of the schema are added to this key. */ readonly root?: [string, ...string[]]; /** * The nested errors. * * Hint: The error messages of issues with a path that belong to the nested * parts of the schema and can be converted to a dot path are added to this * key. */ readonly nested?: Prettify< Readonly< Partial< Record< TSchema extends | BaseSchema> | BaseSchemaAsync> ? IssueDotPath : string, [string, ...string[]] > > > >; /** * The other errors. * * Hint: Some issue paths, for example for complex data types like `Set` and * `Map`, have no key or a key that cannot be converted to a dot path. These * error messages are added to this key. */ readonly other?: [string, ...string[]]; }>; /** * Flatten the error messages of issues. * * @param issues The list of issues. * * @returns A flat error object. */ export function flatten( issues: [BaseIssue, ...BaseIssue[]] ): FlatErrors; /** * Flatten the error messages of issues. * * @param issues The list of issues. * * @returns A flat error object. */ export function flatten< TSchema extends | BaseSchema> | BaseSchemaAsync>, >(issues: [InferIssue, ...InferIssue[]]): FlatErrors; // @__NO_SIDE_EFFECTS__ export function flatten( issues: [BaseIssue, ...BaseIssue[]] ): FlatErrors { // Create flat errors object const flatErrors: FlatErrors = {}; // Add message of each issue to flat errors object for (const issue of issues) { // If issue has path, add message to nested or other errors if (issue.path) { // Get dot path from issue const dotPath = getDotPath(issue); // If path has valid keys, add message to nested errors if (dotPath) { if (!flatErrors.nested) { // @ts-expect-error flatErrors.nested = {}; } if (flatErrors.nested![dotPath]) { flatErrors.nested![dotPath]!.push(issue.message); } else { // @ts-expect-error flatErrors.nested![dotPath] = [issue.message]; } // Otherwise, add message to other errors } else { if (flatErrors.other) { flatErrors.other.push(issue.message); } else { // @ts-expect-error flatErrors.other = [issue.message]; } } // Otherwise, add message to root errors } else { if (flatErrors.root) { flatErrors.root.push(issue.message); } else { // @ts-expect-error flatErrors.root = [issue.message]; } } } // Return flat errors object return flatErrors; } ================================================ FILE: library/src/methods/flatten/index.ts ================================================ export * from './flatten.ts'; ================================================ FILE: library/src/methods/forward/forward.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { check, type CheckIssue } from '../../actions/index.ts'; import type { BaseValidation, InferInput, InferIssue, InferOutput, } from '../../types/index.ts'; import { forward } from './forward.ts'; describe('forward', () => { // eslint-disable-next-line @typescript-eslint/consistent-type-definitions type Input = { nested: { key: string }[] }; type Path = ['nested', 1, 'key']; const action = forward, Path>( check((input) => Boolean(input), 'message'), ['nested', 1, 'key'] ); test('should return action object', () => { expectTypeOf(action).toEqualTypeOf< BaseValidation> >(); }); describe('should infer correct types', () => { type Action = typeof action; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/methods/forward/forward.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { check, type CheckIssue, type MinLengthIssue, } from '../../actions/index.ts'; import type { PartialDataset, SuccessDataset } from '../../types/index.ts'; import { forward } from './forward.ts'; describe('forward', () => { test('should forward issues to end of path list', () => { const input = { nested: [{ key: 'value_1' }, { key: 'value_2' }] }; type Input = typeof input; type Path = ['nested', 1, 'key']; const requirement = () => false; expect( forward, Path>(check(requirement, 'message'), [ 'nested', 1, 'key', ])['~run']({ typed: true, value: input }, {}) ).toStrictEqual({ typed: true, value: input, issues: [ { kind: 'validation', type: 'check', input, expected: null, received: 'Object', message: 'message', path: [ { type: 'unknown', origin: 'value', input: input, key: 'nested', value: input.nested, }, { type: 'unknown', origin: 'value', input: input.nested, key: 1, value: input.nested[1], }, { type: 'unknown', origin: 'value', input: input.nested[1], key: 'key', value: input.nested[1].key, }, ], requirement, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }, ], } satisfies PartialDataset>); }); test('should stop forwarding if path input is undefined', () => { const input = { nested: [{ key: 'value_1' }, { key: 'value_2' }] }; type Input = typeof input; type Path = ['nested', 6, 'key']; const requirement = () => false; expect( forward, Path>(check(requirement, 'message'), [ 'nested', 6, 'key', ])['~run']({ typed: true, value: input }, {}) ).toStrictEqual({ typed: true, value: input, issues: [ { kind: 'validation', type: 'check', input, expected: null, received: 'Object', message: 'message', path: [ { type: 'unknown', origin: 'value', input: input, key: 'nested', value: input.nested, }, { type: 'unknown', origin: 'value', input: input.nested, key: 6, value: input.nested[6], }, ], requirement, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }, ], } satisfies PartialDataset>); }); test('should only forward issues of wrapped action', () => { const input = { nested: [{ key: 'value_1' }, { key: 'value_2' }] }; type Input = typeof input; type Path = ['nested', 1, 'key']; const requirement = () => false; const prevIssue: MinLengthIssue = { kind: 'validation', type: 'min_length', input: input.nested, expected: '>=3', received: '2', message: 'message', path: [ { type: 'object', origin: 'value', input: input, key: 'nested', value: input.nested, }, ], requirement: 3, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; expect( forward, Path>(check(requirement, 'message'), [ 'nested', 1, 'key', ])['~run']( { typed: true, value: input, // Hint: We pass a copy of the previous issue to avoid accidentally // modifying our test data. issues: [{ ...prevIssue, path: [...prevIssue.path!] }], }, {} ) ).toStrictEqual({ typed: true, value: input, issues: [ prevIssue, { kind: 'validation', type: 'check', input, expected: null, received: 'Object', message: 'message', path: [ { type: 'unknown', origin: 'value', input: input, key: 'nested', value: input.nested, }, { type: 'unknown', origin: 'value', input: input.nested, key: 1, value: input.nested[1], }, { type: 'unknown', origin: 'value', input: input.nested[1], key: 'key', value: input.nested[1].key, }, ], requirement, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }, ], } satisfies PartialDataset< Input, MinLengthIssue | CheckIssue >); }); test('should do nothing if there are no issues', () => { const input = { nested: [{ key: 'value_1' }, { key: 'value_2' }] }; type Input = typeof input; type Path = ['nested', 6, 'key']; const requirement = () => true; expect( forward, Path>(check(requirement, 'message'), [ 'nested', 6, 'key', ])['~run']({ typed: true, value: input }, {}) ).toStrictEqual({ typed: true, value: input, } satisfies SuccessDataset); }); }); ================================================ FILE: library/src/methods/forward/forward.ts ================================================ import type { BaseIssue, BaseValidation, IssuePathItem, } from '../../types/index.ts'; import type { RequiredPath, ValidPath } from './types.ts'; // TODO: We should try to find a better way to type this function without // breaking the type inference, as the current implementation loses some type // information by returning a `BaseValidation` instead of the original type. // In the process, we should also figure out how to add a `.forward' property // to the returnd object in a type-safe way, similar to how the `fallback` // method works. /** * Forwards the issues of the passed validation action. * * @param action The validation action. * @param path The path to forward the issues to. * * @returns The modified action. */ // @__NO_SIDE_EFFECTS__ export function forward< TInput extends Record | ArrayLike, TIssue extends BaseIssue, const TPath extends RequiredPath, >( action: BaseValidation, path: ValidPath ): BaseValidation { return { ...action, '~run'(dataset, config) { // Create copy of previous issues const prevIssues = dataset.issues && [...dataset.issues]; // Run validation action dataset = action['~run'](dataset, config); // If dataset contains issues, forward newly added issues if (dataset.issues) { for (const issue of dataset.issues) { if (!prevIssues?.includes(issue)) { // Create path input variable let pathInput: unknown = dataset.value; // Try to forward issue to end of path list for (const key of path) { // Create path value variable // @ts-expect-error const pathValue: unknown = pathInput[key]; // Create path item for current key const pathItem: IssuePathItem = { type: 'unknown', origin: 'value', input: pathInput, key, value: pathValue, }; // Forward issue by adding path item if (issue.path) { issue.path.push(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // If path value is undefined, stop forwarding if (!pathValue) { break; } // Set next path input to current path value pathInput = pathValue; } } } } // Return output dataset return dataset; }, }; } ================================================ FILE: library/src/methods/forward/forwardAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { check, type CheckIssue } from '../../actions/index.ts'; import type { BaseValidationAsync, InferInput, InferIssue, InferOutput, } from '../../types/index.ts'; import { forwardAsync } from './forwardAsync.ts'; describe('forwardAsync', () => { // eslint-disable-next-line @typescript-eslint/consistent-type-definitions type Input = { nested: { key: string }[] }; type Path = ['nested', 1, 'key']; const action = forwardAsync, Path>( check((input) => Boolean(input), 'message'), ['nested', 1, 'key'] ); test('should return action object', () => { expectTypeOf(action).toEqualTypeOf< BaseValidationAsync> >(); }); describe('should infer correct types', () => { type Action = typeof action; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/methods/forward/forwardAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { check, type CheckIssue, type MinLengthIssue, } from '../../actions/index.ts'; import type { PartialDataset, SuccessDataset } from '../../types/index.ts'; import { forwardAsync } from './forwardAsync.ts'; describe('forwardAsync', () => { test('should forward issues to end of path list', async () => { const input = { nested: [{ key: 'value_1' }, { key: 'value_2' }] }; type Input = typeof input; type Path = ['nested', 1, 'key']; const requirement = () => false; expect( await forwardAsync, Path>( check(requirement, 'message'), ['nested', 1, 'key'] )['~run']({ typed: true, value: input }, {}) ).toStrictEqual({ typed: true, value: input, issues: [ { kind: 'validation', type: 'check', input, expected: null, received: 'Object', message: 'message', path: [ { type: 'unknown', origin: 'value', input: input, key: 'nested', value: input.nested, }, { type: 'unknown', origin: 'value', input: input.nested, key: 1, value: input.nested[1], }, { type: 'unknown', origin: 'value', input: input.nested[1], key: 'key', value: input.nested[1].key, }, ], requirement, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }, ], } satisfies PartialDataset>); }); test('should stop forwarding if path input is undefined', async () => { const input = { nested: [{ key: 'value_1' }, { key: 'value_2' }] }; type Input = typeof input; type Path = ['nested', 6, 'key']; const requirement = () => false; expect( await forwardAsync, Path>( check(requirement, 'message'), ['nested', 6, 'key'] )['~run']({ typed: true, value: input }, {}) ).toStrictEqual({ typed: true, value: input, issues: [ { kind: 'validation', type: 'check', input, expected: null, received: 'Object', message: 'message', path: [ { type: 'unknown', origin: 'value', input: input, key: 'nested', value: input.nested, }, { type: 'unknown', origin: 'value', input: input.nested, key: 6, value: input.nested[6], }, ], requirement, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }, ], } satisfies PartialDataset>); }); test('should only forward issues of wrapped action', async () => { const input = { nested: [{ key: 'value_1' }, { key: 'value_2' }] }; type Input = typeof input; type Path = ['nested', 1, 'key']; const requirement = () => false; const prevIssue: MinLengthIssue = { kind: 'validation', type: 'min_length', input: input.nested, expected: '>=3', received: '2', message: 'message', path: [ { type: 'object', origin: 'value', input: input, key: 'nested', value: input.nested, }, ], requirement: 3, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; expect( await forwardAsync, Path>( check(requirement, 'message'), ['nested', 1, 'key'] )['~run']( { typed: true, value: input, // Hint: We pass a copy of the previous issue to avoid accidentally // modifying our test data. issues: [{ ...prevIssue, path: [...prevIssue.path!] }], }, {} ) ).toStrictEqual({ typed: true, value: input, issues: [ prevIssue, { kind: 'validation', type: 'check', input, expected: null, received: 'Object', message: 'message', path: [ { type: 'unknown', origin: 'value', input: input, key: 'nested', value: input.nested, }, { type: 'unknown', origin: 'value', input: input.nested, key: 1, value: input.nested[1], }, { type: 'unknown', origin: 'value', input: input.nested[1], key: 'key', value: input.nested[1].key, }, ], requirement, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }, ], } satisfies PartialDataset< Input, MinLengthIssue | CheckIssue >); }); test('should do nothing if there are no issues', async () => { const input = { nested: [{ key: 'value_1' }, { key: 'value_2' }] }; type Input = typeof input; type Path = ['nested', 6, 'key']; const requirement = () => true; expect( await forwardAsync, Path>( check(requirement, 'message'), ['nested', 6, 'key'] )['~run']({ typed: true, value: input }, {}) ).toStrictEqual({ typed: true, value: input, } satisfies SuccessDataset); }); }); ================================================ FILE: library/src/methods/forward/forwardAsync.ts ================================================ import type { BaseIssue, BaseValidation, BaseValidationAsync, IssuePathItem, } from '../../types/index.ts'; import type { RequiredPath, ValidPath } from './types.ts'; // TODO: We should try to find a better way to type this function without // breaking the type inference, as the current implementation loses some type // information by returning a `BaseValidation` instead of the original type. // In the process, we should also figure out how to add a `.forward' property // to the returnd object in a type-safe way, similar to how the `fallback` // method works. /** * Forwards the issues of the passed validation action. * * @param action The validation action. * @param path The path to forward the issues to. * * @returns The modified action. */ // @__NO_SIDE_EFFECTS__ export function forwardAsync< TInput extends Record | ArrayLike, TIssue extends BaseIssue, const TPath extends RequiredPath, >( action: | BaseValidation | BaseValidationAsync, path: ValidPath ): BaseValidationAsync { return { ...action, async: true, async '~run'(dataset, config) { // Create copy of previous issues const prevIssues = dataset.issues && [...dataset.issues]; // Run validation action dataset = await action['~run'](dataset, config); // If dataset contains issues, forward newly added issues if (dataset.issues) { for (const issue of dataset.issues) { if (!prevIssues?.includes(issue)) { // Create path input variable let pathInput: unknown = dataset.value; // Try to forward issue to end of path list for (const key of path) { // Create path value variable // @ts-expect-error const pathValue: unknown = pathInput[key]; // Create path item for current key const pathItem: IssuePathItem = { type: 'unknown', origin: 'value', input: pathInput, key, value: pathValue, }; // Forward issue by adding path item if (issue.path) { issue.path.push(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // If path value is undefined, stop forwarding if (!pathValue) { break; } // Set next path input to current path value pathInput = pathValue; } } } } // Return output dataset return dataset; }, }; } ================================================ FILE: library/src/methods/forward/index.ts ================================================ export * from './forward.ts'; export * from './forwardAsync.ts'; ================================================ FILE: library/src/methods/forward/types.ts ================================================ import type { IsAny, IsNever } from '../../types/index.ts'; /** * Extracts the exact keys of a tuple, array or object. */ type KeyOf = IsAny extends true ? never : TValue extends readonly unknown[] ? number extends TValue['length'] ? number : { [TKey in keyof TValue]: TKey extends `${infer TIndex extends number}` ? TIndex : never; }[number] : TValue extends Record ? keyof TValue & (string | number) : never; /** * Path type. */ type Path = readonly (string | number)[]; /** * Required path type. */ export type RequiredPath = readonly [string | number, ...Path]; /** * Lazily evaluate only the first valid path segment based on the given value. */ type LazyPath< TValue, TPathToCheck extends Path, TValidPath extends Path = readonly [], > = // If path to check is empty, return last valid path TPathToCheck extends readonly [] ? TValidPath : // If first key of path to check is valid, continue with next key TPathToCheck extends readonly [ infer TFirstKey extends KeyOf & keyof TValue, ...infer TPathRest extends Path, ] ? LazyPath< TValue[TFirstKey], TPathRest, readonly [...TValidPath, TFirstKey] > : // If current value has valid keys, return them IsNever> extends false ? readonly [...TValidPath, KeyOf] : // Otherwise, return only last valid path TValidPath; /** * Returns the path if valid, otherwise the first possible valid path based on * the given value. */ export type ValidPath< TValue extends Record | ArrayLike, TPath extends RequiredPath, > = TPath extends LazyPath ? TPath : LazyPath; ================================================ FILE: library/src/methods/getDefault/getDefault.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { exactOptional, exactOptionalAsync, nullable, nullableAsync, nullish, nullishAsync, number, object, optional, optionalAsync, string, undefinedable, undefinedableAsync, } from '../../schemas/index.ts'; import { pipe, pipeAsync } from '../pipe/index.ts'; import { getDefault } from './getDefault.ts'; describe('getDefault', () => { test('should return undefined', () => { expectTypeOf(getDefault(string())).toEqualTypeOf(); expectTypeOf(getDefault(number())).toEqualTypeOf(); expectTypeOf(getDefault(object({}))).toEqualTypeOf(); }); describe('should return exact optional default', () => { test('for undefined value', () => { expectTypeOf( getDefault(exactOptional(string())) ).toEqualTypeOf(); expectTypeOf( getDefault(exactOptional(string(), undefined)) ).toEqualTypeOf(); }); test('for direct value', () => { expectTypeOf( getDefault(exactOptional(string(), 'foo')) ).toEqualTypeOf<'foo'>(); }); test('for value getter', () => { expectTypeOf( getDefault(exactOptional(string(), () => 'foo' as const)) ).toEqualTypeOf<'foo'>(); }); test('for async value getter', () => { expectTypeOf( getDefault(exactOptionalAsync(string(), async () => 'foo' as const)) ).toEqualTypeOf>(); }); test('for schema with pipe', () => { expectTypeOf( getDefault(pipe(exactOptional(string(), 'foo'))) ).toEqualTypeOf<'foo'>(); expectTypeOf( getDefault(pipeAsync(exactOptional(string(), 'foo'))) ).toEqualTypeOf<'foo'>(); expectTypeOf( getDefault(pipeAsync(exactOptionalAsync(string(), 'foo'))) ).toEqualTypeOf<'foo'>(); }); }); describe('should return optional default', () => { test('for undefined value', () => { expectTypeOf(getDefault(optional(string()))).toEqualTypeOf(); expectTypeOf( getDefault(optional(string(), undefined)) ).toEqualTypeOf(); expectTypeOf( getDefault(optional(string(), () => undefined)) ).toEqualTypeOf(); expectTypeOf( getDefault(optionalAsync(string(), async () => undefined)) ).toEqualTypeOf>(); }); test('for direct value', () => { expectTypeOf( getDefault(optional(string(), 'foo')) ).toEqualTypeOf<'foo'>(); }); test('for value getter', () => { expectTypeOf( getDefault(optional(string(), () => 'foo' as const)) ).toEqualTypeOf<'foo'>(); }); test('for async value getter', () => { expectTypeOf( getDefault(optionalAsync(string(), async () => 'foo' as const)) ).toEqualTypeOf>(); }); test('for schema with pipe', () => { expectTypeOf( getDefault(pipe(optional(string(), 'foo'))) ).toEqualTypeOf<'foo'>(); expectTypeOf( getDefault(pipeAsync(optional(string(), 'foo'))) ).toEqualTypeOf<'foo'>(); expectTypeOf( getDefault(pipeAsync(optionalAsync(string(), 'foo'))) ).toEqualTypeOf<'foo'>(); }); }); describe('should return nullable default', () => { test('for undefined value', () => { expectTypeOf(getDefault(nullable(string()))).toEqualTypeOf(); }); test('for null value', () => { expectTypeOf(getDefault(nullable(string(), null))).toEqualTypeOf(); expectTypeOf( getDefault(nullable(string(), () => null)) ).toEqualTypeOf(); expectTypeOf( getDefault(nullableAsync(string(), async () => null)) ).toEqualTypeOf>(); }); test('for direct value', () => { expectTypeOf( getDefault(nullable(string(), 'foo')) ).toEqualTypeOf<'foo'>(); }); test('for value getter', () => { expectTypeOf( getDefault(nullable(string(), () => 'foo' as const)) ).toEqualTypeOf<'foo'>(); }); test('for async value getter', () => { expectTypeOf( getDefault(nullableAsync(string(), async () => 'foo' as const)) ).toEqualTypeOf>(); }); test('for schema with pipe', () => { expectTypeOf( getDefault(pipe(nullable(string(), 'foo'))) ).toEqualTypeOf<'foo'>(); expectTypeOf( getDefault(pipeAsync(nullable(string(), 'foo'))) ).toEqualTypeOf<'foo'>(); expectTypeOf( getDefault(pipeAsync(nullableAsync(string(), 'foo'))) ).toEqualTypeOf<'foo'>(); }); }); describe('should return nullish default', () => { test('for undefined value', () => { expectTypeOf(getDefault(nullish(string()))).toEqualTypeOf(); expectTypeOf( getDefault(nullish(string(), undefined)) ).toEqualTypeOf(); expectTypeOf( getDefault(nullish(string(), () => undefined)) ).toEqualTypeOf(); expectTypeOf( getDefault(nullishAsync(string(), async () => undefined)) ).toEqualTypeOf>(); }); test('for null value', () => { expectTypeOf(getDefault(nullish(string(), null))).toEqualTypeOf(); expectTypeOf( getDefault(nullish(string(), () => null)) ).toEqualTypeOf(); expectTypeOf( getDefault(nullishAsync(string(), async () => null)) ).toEqualTypeOf>(); }); test('for direct value', () => { expectTypeOf(getDefault(nullish(string(), 'foo'))).toEqualTypeOf<'foo'>(); }); test('for value getter', () => { expectTypeOf( getDefault(nullish(string(), () => 'foo' as const)) ).toEqualTypeOf<'foo'>(); }); test('for async value getter', () => { expectTypeOf( getDefault(nullishAsync(string(), async () => 'foo' as const)) ).toEqualTypeOf>(); }); test('for schema with pipe', () => { expectTypeOf( getDefault(pipe(nullish(string(), 'foo'))) ).toEqualTypeOf<'foo'>(); expectTypeOf( getDefault(pipeAsync(nullish(string(), 'foo'))) ).toEqualTypeOf<'foo'>(); expectTypeOf( getDefault(pipeAsync(nullishAsync(string(), 'foo'))) ).toEqualTypeOf<'foo'>(); }); }); describe('should return undefinedable default', () => { test('for undefined value', () => { expectTypeOf( getDefault(undefinedable(string())) ).toEqualTypeOf(); expectTypeOf( getDefault(undefinedable(string(), undefined)) ).toEqualTypeOf(); expectTypeOf( getDefault(undefinedable(string(), () => undefined)) ).toEqualTypeOf(); expectTypeOf( getDefault(undefinedableAsync(string(), async () => undefined)) ).toEqualTypeOf>(); }); test('for direct value', () => { expectTypeOf( getDefault(undefinedable(string(), 'foo')) ).toEqualTypeOf<'foo'>(); }); test('for value getter', () => { expectTypeOf( getDefault(undefinedable(string(), () => 'foo' as const)) ).toEqualTypeOf<'foo'>(); }); test('for async value getter', () => { expectTypeOf( getDefault(undefinedableAsync(string(), async () => 'foo' as const)) ).toEqualTypeOf>(); }); test('for schema with pipe', () => { expectTypeOf( getDefault(pipe(undefinedable(string(), 'foo'))) ).toEqualTypeOf<'foo'>(); expectTypeOf( getDefault(pipeAsync(undefinedable(string(), 'foo'))) ).toEqualTypeOf<'foo'>(); expectTypeOf( getDefault(pipeAsync(undefinedableAsync(string(), 'foo'))) ).toEqualTypeOf<'foo'>(); }); }); }); ================================================ FILE: library/src/methods/getDefault/getDefault.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { exactOptional, exactOptionalAsync, nullable, nullableAsync, nullish, nullishAsync, number, object, optional, optionalAsync, string, undefinedable, undefinedableAsync, } from '../../schemas/index.ts'; import { pipe, pipeAsync } from '../pipe/index.ts'; import { getDefault } from './getDefault.ts'; describe('getDefault', () => { test('should return undefined', () => { expect(getDefault(string())).toBeUndefined(); expect(getDefault(number())).toBeUndefined(); expect(getDefault(object({}))).toBeUndefined(); }); describe('should return exact optional default', () => { test('for undefined value', async () => { expect(getDefault(exactOptional(string()))).toBeUndefined(); expect(getDefault(exactOptional(string(), undefined))).toBeUndefined(); }); test('for direct value', () => { expect(getDefault(exactOptional(string(), 'foo'))).toBe('foo'); expect(getDefault(exactOptionalAsync(string(), 'foo'))).toBe('foo'); }); test('for value getter', () => { expect(getDefault(exactOptional(string(), () => 'foo'))).toBe('foo'); expect(getDefault(exactOptionalAsync(string(), () => 'foo'))).toBe('foo'); }); test('for asycn value getter', async () => { expect( await getDefault(exactOptionalAsync(string(), async () => 'foo')) ).toBe('foo'); }); test('for schema with pipe', () => { expect(getDefault(pipe(exactOptional(string(), 'foo')))).toBe('foo'); expect(getDefault(pipeAsync(exactOptional(string(), 'foo')))).toBe('foo'); expect(getDefault(pipeAsync(exactOptionalAsync(string(), 'foo')))).toBe( 'foo' ); }); }); describe('should return optional default', () => { test('for undefined value', async () => { expect(getDefault(optional(string()))).toBeUndefined(); expect(getDefault(optional(string(), undefined))).toBeUndefined(); expect(getDefault(optional(string(), () => undefined))).toBeUndefined(); expect( await getDefault(optionalAsync(string(), async () => undefined)) ).toBeUndefined(); }); test('for direct value', () => { expect(getDefault(optional(string(), 'foo'))).toBe('foo'); expect(getDefault(optionalAsync(string(), 'foo'))).toBe('foo'); }); test('for value getter', () => { expect(getDefault(optional(string(), () => 'foo'))).toBe('foo'); expect(getDefault(optionalAsync(string(), () => 'foo'))).toBe('foo'); }); test('for asycn value getter', async () => { expect(await getDefault(optionalAsync(string(), async () => 'foo'))).toBe( 'foo' ); }); test('for schema with pipe', () => { expect(getDefault(pipe(optional(string(), 'foo')))).toBe('foo'); expect(getDefault(pipeAsync(optional(string(), 'foo')))).toBe('foo'); expect(getDefault(pipeAsync(optionalAsync(string(), 'foo')))).toBe('foo'); }); }); describe('should return nullable default', () => { test('for undefined value', async () => { expect(getDefault(nullable(string()))).toBeUndefined(); }); test('for null value', async () => { expect(getDefault(nullable(string(), null))).toBeNull(); expect(getDefault(nullable(string(), () => null))).toBeNull(); expect( await getDefault(nullableAsync(string(), async () => null)) ).toBeNull(); }); test('for direct value', () => { expect(getDefault(nullable(string(), 'foo'))).toBe('foo'); expect(getDefault(nullableAsync(string(), 'foo'))).toBe('foo'); }); test('for value getter', () => { expect(getDefault(nullable(string(), () => 'foo'))).toBe('foo'); expect(getDefault(nullableAsync(string(), () => 'foo'))).toBe('foo'); }); test('for value getter', async () => { expect(await getDefault(nullableAsync(string(), async () => 'foo'))).toBe( 'foo' ); }); test('for schema with pipe', () => { expect(getDefault(pipe(nullable(string(), 'foo')))).toBe('foo'); expect(getDefault(pipeAsync(nullable(string(), 'foo')))).toBe('foo'); expect(getDefault(pipeAsync(nullableAsync(string(), 'foo')))).toBe('foo'); }); }); describe('should return nullish default', () => { test('for undefined value', async () => { expect(getDefault(nullish(string()))).toBeUndefined(); expect(getDefault(nullish(string(), undefined))).toBeUndefined(); expect(getDefault(nullish(string(), () => undefined))).toBeUndefined(); expect( await getDefault(nullishAsync(string(), async () => undefined)) ).toBeUndefined(); }); test('for null value', async () => { expect(getDefault(nullish(string(), null))).toBeNull(); expect(getDefault(nullish(string(), () => null))).toBeNull(); expect( await getDefault(nullishAsync(string(), async () => null)) ).toBeNull(); }); test('for direct value', () => { expect(getDefault(nullish(string(), 'foo'))).toBe('foo'); expect(getDefault(nullishAsync(string(), 'foo'))).toBe('foo'); }); test('for value getter', () => { expect(getDefault(nullish(string(), () => 'foo'))).toBe('foo'); expect(getDefault(nullishAsync(string(), () => 'foo'))).toBe('foo'); }); test('for value getter', async () => { expect(await getDefault(nullishAsync(string(), async () => 'foo'))).toBe( 'foo' ); }); test('for schema with pipe', () => { expect(getDefault(pipe(nullish(string(), 'foo')))).toBe('foo'); expect(getDefault(pipeAsync(nullish(string(), 'foo')))).toBe('foo'); expect(getDefault(pipeAsync(nullishAsync(string(), 'foo')))).toBe('foo'); }); }); describe('should return undefinedable default', () => { test('for undefined value', async () => { expect(getDefault(undefinedable(string()))).toBeUndefined(); expect(getDefault(undefinedable(string(), undefined))).toBeUndefined(); expect( getDefault(undefinedable(string(), () => undefined)) ).toBeUndefined(); expect( await getDefault(undefinedableAsync(string(), async () => undefined)) ).toBeUndefined(); }); test('for direct value', () => { expect(getDefault(undefinedable(string(), 'foo'))).toBe('foo'); expect(getDefault(undefinedableAsync(string(), 'foo'))).toBe('foo'); }); test('for value getter', () => { expect(getDefault(undefinedable(string(), () => 'foo'))).toBe('foo'); expect(getDefault(undefinedableAsync(string(), () => 'foo'))).toBe('foo'); }); test('for asycn value getter', async () => { expect( await getDefault(undefinedableAsync(string(), async () => 'foo')) ).toBe('foo'); }); test('for schema with pipe', () => { expect(getDefault(pipe(undefinedable(string(), 'foo')))).toBe('foo'); expect(getDefault(pipeAsync(undefinedable(string(), 'foo')))).toBe('foo'); expect(getDefault(pipeAsync(undefinedableAsync(string(), 'foo')))).toBe( 'foo' ); }); }); }); ================================================ FILE: library/src/methods/getDefault/getDefault.ts ================================================ import type { ExactOptionalSchema, ExactOptionalSchemaAsync, NullableSchema, NullableSchemaAsync, NullishSchema, NullishSchemaAsync, OptionalSchema, OptionalSchemaAsync, UndefinedableSchema, UndefinedableSchemaAsync, } from '../../schemas/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, Config, InferIssue, UnknownDataset, } from '../../types/index.ts'; /** * Schema with default type. */ type SchemaWithDefault = | ExactOptionalSchema< BaseSchema>, unknown > | NullableSchema>, unknown> | NullishSchema>, unknown> | OptionalSchema>, unknown> | UndefinedableSchema< BaseSchema>, unknown >; /** * Schema with default async type. */ type SchemaWithDefaultAsync = | ExactOptionalSchemaAsync< | BaseSchema> | BaseSchemaAsync>, unknown > | NullableSchemaAsync< | BaseSchema> | BaseSchemaAsync>, unknown > | NullishSchemaAsync< | BaseSchema> | BaseSchemaAsync>, unknown > | OptionalSchemaAsync< | BaseSchema> | BaseSchemaAsync>, unknown > | UndefinedableSchemaAsync< | BaseSchema> | BaseSchemaAsync>, unknown >; /** * Infer default type. */ export type InferDefault< TSchema extends | BaseSchema> | BaseSchemaAsync> | SchemaWithDefault | SchemaWithDefaultAsync, > = TSchema extends SchemaWithDefault | SchemaWithDefaultAsync ? // eslint-disable-next-line @typescript-eslint/no-explicit-any TSchema['default'] extends (...args: any) => any ? ReturnType : TSchema['default'] : undefined; /** * Returns the default value of the schema. * * @param schema The schema to get it from. * @param dataset The input dataset if available. * @param config The config if available. * * @returns The default value. */ // @__NO_SIDE_EFFECTS__ export function getDefault< const TSchema extends | BaseSchema> | BaseSchemaAsync>, >( schema: TSchema, dataset?: UnknownDataset, config?: Config> ): InferDefault { // @ts-expect-error return typeof schema.default === 'function' ? // @ts-expect-error schema.default(dataset, config) : // @ts-expect-error schema.default; } ================================================ FILE: library/src/methods/getDefault/index.ts ================================================ export * from './getDefault.ts'; ================================================ FILE: library/src/methods/getDefaults/getDefaults.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { boolean, nullable, nullish, number, object, optional, strictObject, strictTuple, string, tuple, } from '../../schemas/index.ts'; import { getDefaults } from './getDefaults.ts'; describe('getDefaults', () => { test('should return undefined', () => { expectTypeOf(getDefaults(string())).toEqualTypeOf(); expectTypeOf(getDefaults(number())).toEqualTypeOf(); expectTypeOf(getDefaults(boolean())).toEqualTypeOf(); }); test('should return default', () => { expectTypeOf(getDefaults(optional(string(), 'foo'))).toEqualTypeOf<'foo'>(); expectTypeOf( getDefaults(nullish(number(), () => 123 as const)) ).toEqualTypeOf<123>(); expectTypeOf( getDefaults(nullable(boolean(), false)) ).toEqualTypeOf(); }); describe('should return object defaults', () => { test('for empty object', () => { // eslint-disable-next-line @typescript-eslint/no-empty-object-type expectTypeOf(getDefaults(object({}))).toEqualTypeOf<{}>(); }); test('for simple object', () => { expectTypeOf( getDefaults( object({ key1: optional(string(), 'foo'), key2: nullish(number(), () => 123 as const), key3: nullable(boolean(), false), key4: string(), }) ) ).toEqualTypeOf<{ key1: 'foo'; key2: 123; key3: false; key4: undefined; }>(); }); test('for nested object', () => { expectTypeOf( getDefaults( object({ nested: strictObject({ key1: optional(string(), 'foo'), key2: nullish(number(), () => 123 as const), key3: nullable(boolean(), false), }), other: string(), }) ) ).toEqualTypeOf<{ nested: { key1: 'foo'; key2: 123; key3: false; }; other: undefined; }>(); }); }); describe('should return tuple defaults', () => { test('for empty tuple', () => { expectTypeOf(getDefaults(tuple([]))).toEqualTypeOf<[]>(); }); test('for simple tuple', () => { expectTypeOf( getDefaults( tuple([ optional(string(), 'foo'), nullish(number(), () => 123 as const), nullable(boolean(), false), string(), ]) ) ).toEqualTypeOf<['foo', 123, false, undefined]>(); }); test('for nested tuple', () => { expectTypeOf( getDefaults( tuple([ strictTuple([ optional(string(), 'foo'), nullish(number(), () => 123 as const), nullable(boolean(), false), ]), string(), ]) ) ).toEqualTypeOf<[['foo', 123, false], undefined]>(); }); }); }); ================================================ FILE: library/src/methods/getDefaults/getDefaults.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { boolean, nullable, nullish, number, object, optional, strictObject, strictTuple, string, tuple, } from '../../schemas/index.ts'; import { getDefaults } from './getDefaults.ts'; describe('getDefaults', () => { test('should return undefined', () => { expect(getDefaults(string())).toBeUndefined(); expect(getDefaults(number())).toBeUndefined(); expect(getDefaults(boolean())).toBeUndefined(); }); test('should return default', () => { expect(getDefaults(optional(string(), 'foo'))).toBe('foo'); expect(getDefaults(nullish(number(), () => 123 as const))).toBe(123); expect(getDefaults(nullable(boolean(), false))).toBe(false); }); describe('should return object defaults', () => { test('for empty object', () => { expect(getDefaults(object({}))).toStrictEqual({}); }); test('for simple object', () => { expect( getDefaults( object({ key1: optional(string(), 'foo'), key2: nullish(number(), () => 123 as const), key3: nullable(boolean(), false), key4: string(), }) ) ).toStrictEqual({ key1: 'foo', key2: 123, key3: false, key4: undefined, }); }); test('for nested object', () => { expect( getDefaults( object({ nested: strictObject({ key1: optional(string(), 'foo'), key2: nullish(number(), () => 123 as const), key3: nullable(boolean(), false), }), other: string(), }) ) ).toStrictEqual({ nested: { key1: 'foo', key2: 123, key3: false, }, other: undefined, }); }); }); describe('should return tuple defaults', () => { test('for empty tuple', () => { expect(getDefaults(tuple([]))).toStrictEqual([]); }); test('for simple tuple', () => { expect( getDefaults( tuple([ optional(string(), 'foo'), nullish(number(), () => 123 as const), nullable(boolean(), false), string(), ]) ) ).toStrictEqual(['foo', 123, false, undefined]); }); test('for nested tuple', () => { expect( getDefaults( tuple([ strictTuple([ optional(string(), 'foo'), nullish(number(), () => 123 as const), nullable(boolean(), false), ]), string(), ]) ) ).toStrictEqual([['foo', 123, false], undefined]); }); }); }); ================================================ FILE: library/src/methods/getDefaults/getDefaults.ts ================================================ import type { LooseObjectIssue, LooseObjectSchema, LooseTupleIssue, LooseTupleSchema, ObjectIssue, ObjectSchema, ObjectWithRestIssue, ObjectWithRestSchema, StrictObjectIssue, StrictObjectSchema, StrictTupleIssue, StrictTupleSchema, TupleIssue, TupleSchema, TupleWithRestIssue, TupleWithRestSchema, } from '../../schemas/index.ts'; import type { BaseIssue, BaseSchema, ErrorMessage, ObjectEntries, TupleItems, } from '../../types/index.ts'; import { getDefault } from '../getDefault/index.ts'; import type { InferDefaults } from './types.ts'; /** * Returns the default values of the schema. * * Hint: The difference to `getDefault` is that for object and tuple schemas * this function recursively returns the default values of the subschemas * instead of `undefined`. * * @param schema The schema to get them from. * * @returns The default values. */ // @__NO_SIDE_EFFECTS__ export function getDefaults< const TSchema extends | BaseSchema> | LooseObjectSchema< ObjectEntries, ErrorMessage | undefined > | LooseTupleSchema | undefined> | ObjectSchema | undefined> | ObjectWithRestSchema< ObjectEntries, BaseSchema>, ErrorMessage | undefined > | StrictObjectSchema< ObjectEntries, ErrorMessage | undefined > | StrictTupleSchema | undefined> | TupleSchema | undefined> | TupleWithRestSchema< TupleItems, BaseSchema>, ErrorMessage | undefined >, >(schema: TSchema): InferDefaults { // If it is an object schema, return defaults of entries if ('entries' in schema) { const object: Record = {}; for (const key in schema.entries) { object[key] = getDefaults(schema.entries[key]); } return object as InferDefaults; } // If it is a tuple schema, return defaults of items if ('items' in schema) { return schema.items.map(getDefaults) as InferDefaults; } // Otherwise, return default or `undefined` // @ts-expect-error return getDefault(schema); } ================================================ FILE: library/src/methods/getDefaults/getDefaultsAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { boolean, nullableAsync, nullish, number, object, objectAsync, optional, strictObjectAsync, strictTupleAsync, string, tuple, tupleAsync, } from '../../schemas/index.ts'; import { getDefaultsAsync } from './getDefaultsAsync.ts'; describe('getDefaultsAsync', () => { test('should return undefined', () => { expectTypeOf(getDefaultsAsync(string())).toEqualTypeOf< Promise >(); expectTypeOf(getDefaultsAsync(number())).toEqualTypeOf< Promise >(); expectTypeOf(getDefaultsAsync(boolean())).toEqualTypeOf< Promise >(); }); test('should return default', () => { expectTypeOf(getDefaultsAsync(optional(string(), 'foo'))).toEqualTypeOf< Promise<'foo'> >(); expectTypeOf( getDefaultsAsync(nullish(number(), () => 123 as const)) ).toEqualTypeOf>(); expectTypeOf( getDefaultsAsync(nullableAsync(boolean(), async () => false as const)) ).toEqualTypeOf>(); }); describe('should return object defaults', () => { test('for empty object', () => { // eslint-disable-next-line @typescript-eslint/no-empty-object-type expectTypeOf(getDefaultsAsync(object({}))).toEqualTypeOf>(); }); test('for simple object', () => { expectTypeOf( getDefaultsAsync( objectAsync({ key1: optional(string(), 'foo'), key2: nullish(number(), () => 123 as const), key3: nullableAsync(boolean(), false), key4: string(), }) ) ).toEqualTypeOf< Promise<{ key1: 'foo'; key2: 123; key3: false; key4: undefined; }> >(); }); test('for nested object', () => { expectTypeOf( getDefaultsAsync( objectAsync({ nested: strictObjectAsync({ key1: optional(string(), 'foo'), key2: nullish(number(), () => 123 as const), key3: nullableAsync(boolean(), false), }), other: string(), }) ) ).toEqualTypeOf< Promise<{ nested: { key1: 'foo'; key2: 123; key3: false; }; other: undefined; }> >(); }); }); describe('should return tuple defaults', () => { test('for empty tuple', () => { expectTypeOf(getDefaultsAsync(tuple([]))).toEqualTypeOf>(); }); test('for simple tuple', () => { expectTypeOf( getDefaultsAsync( tupleAsync([ optional(string(), 'foo'), nullish(number(), () => 123 as const), nullableAsync(boolean(), false), string(), ]) ) ).toEqualTypeOf>(); }); test('for nested tuple', () => { expectTypeOf( getDefaultsAsync( tupleAsync([ strictTupleAsync([ optional(string(), 'foo'), nullish(number(), () => 123 as const), nullableAsync(boolean(), false), ]), string(), ]) ) ).toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/methods/getDefaults/getDefaultsAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { boolean, nullableAsync, nullish, number, object, objectAsync, optional, strictObjectAsync, strictTupleAsync, string, tuple, tupleAsync, } from '../../schemas/index.ts'; import { getDefaultsAsync } from './getDefaultsAsync.ts'; describe('getDefaultsAsync', () => { test('should return undefined', async () => { expect(await getDefaultsAsync(string())).toBeUndefined(); expect(await getDefaultsAsync(number())).toBeUndefined(); expect(await getDefaultsAsync(boolean())).toBeUndefined(); }); test('should return default', async () => { expect(await getDefaultsAsync(optional(string(), 'foo'))).toBe('foo'); expect(await getDefaultsAsync(nullish(number(), () => 123 as const))).toBe( 123 ); expect( await getDefaultsAsync( nullableAsync(boolean(), async () => false as const) ) ).toBe(false); }); describe('should return object defaults', () => { test('for empty object', async () => { expect(await getDefaultsAsync(object({}))).toStrictEqual({}); }); test('for simple object', async () => { expect( await getDefaultsAsync( objectAsync({ key1: optional(string(), 'foo'), key2: nullish(number(), () => 123 as const), key3: nullableAsync(boolean(), false), key4: string(), }) ) ).toStrictEqual({ key1: 'foo', key2: 123, key3: false, key4: undefined, }); }); test('for nested object', async () => { expect( await getDefaultsAsync( objectAsync({ nested: strictObjectAsync({ key1: optional(string(), 'foo'), key2: nullish(number(), () => 123 as const), key3: nullableAsync(boolean(), false), }), other: string(), }) ) ).toStrictEqual({ nested: { key1: 'foo', key2: 123, key3: false, }, other: undefined, }); }); }); describe('should return tuple defaults', () => { test('for empty tuple', async () => { expect(await getDefaultsAsync(tuple([]))).toStrictEqual([]); }); test('for simple tuple', async () => { expect( await getDefaultsAsync( tupleAsync([ optional(string(), 'foo'), nullish(number(), () => 123 as const), nullableAsync(boolean(), false), string(), ]) ) ).toStrictEqual(['foo', 123, false, undefined]); }); test('for nested tuple', async () => { expect( await getDefaultsAsync( tupleAsync([ strictTupleAsync([ optional(string(), 'foo'), nullish(number(), () => 123 as const), nullableAsync(boolean(), false), ]), string(), ]) ) ).toStrictEqual([['foo', 123, false], undefined]); }); }); }); ================================================ FILE: library/src/methods/getDefaults/getDefaultsAsync.ts ================================================ import type { LooseObjectIssue, LooseObjectSchema, LooseObjectSchemaAsync, LooseTupleIssue, LooseTupleSchema, LooseTupleSchemaAsync, ObjectIssue, ObjectSchema, ObjectSchemaAsync, ObjectWithRestIssue, ObjectWithRestSchema, ObjectWithRestSchemaAsync, StrictObjectIssue, StrictObjectSchema, StrictObjectSchemaAsync, StrictTupleIssue, StrictTupleSchema, StrictTupleSchemaAsync, TupleIssue, TupleSchema, TupleSchemaAsync, TupleWithRestIssue, TupleWithRestSchema, TupleWithRestSchemaAsync, } from '../../schemas/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, ErrorMessage, ObjectEntries, ObjectEntriesAsync, TupleItems, TupleItemsAsync, } from '../../types/index.ts'; import { getDefault } from '../getDefault/index.ts'; import type { InferDefaults } from './types.ts'; /** * Returns the default values of the schema. * * Hint: The difference to `getDefault` is that for object and tuple schemas * this function recursively returns the default values of the subschemas * instead of `undefined`. * * @param schema The schema to get them from. * * @returns The default values. */ // @__NO_SIDE_EFFECTS__ export async function getDefaultsAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync> | LooseObjectSchema< ObjectEntries, ErrorMessage | undefined > | LooseObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined > | LooseTupleSchema | undefined> | LooseTupleSchemaAsync< TupleItemsAsync, ErrorMessage | undefined > | ObjectSchema | undefined> | ObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined > | ObjectWithRestSchema< ObjectEntries, BaseSchema>, ErrorMessage | undefined > | ObjectWithRestSchemaAsync< ObjectEntriesAsync, | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined > | StrictObjectSchema< ObjectEntries, ErrorMessage | undefined > | StrictObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined > | StrictTupleSchema | undefined> | StrictTupleSchemaAsync< TupleItemsAsync, ErrorMessage | undefined > | TupleSchema | undefined> | TupleSchemaAsync | undefined> | TupleWithRestSchema< TupleItems, BaseSchema>, ErrorMessage | undefined > | TupleWithRestSchemaAsync< TupleItemsAsync, | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined >, >(schema: TSchema): Promise> { // If it is an object schema, return defaults of entries if ('entries' in schema) { return Object.fromEntries( await Promise.all( Object.entries(schema.entries).map(async ([key, value]) => [ key, await getDefaultsAsync(value), ]) ) ) as InferDefaults; } // If it is a tuple schema, return defaults of items if ('items' in schema) { return Promise.all(schema.items.map(getDefaultsAsync)) as Promise< InferDefaults >; } // Otherwise, return default or `undefined` // @ts-expect-error return getDefault(schema); } ================================================ FILE: library/src/methods/getDefaults/index.ts ================================================ export * from './getDefaults.ts'; export * from './getDefaultsAsync.ts'; export * from './types.ts'; ================================================ FILE: library/src/methods/getDefaults/types.ts ================================================ import type { LooseObjectIssue, LooseObjectSchema, LooseObjectSchemaAsync, LooseTupleIssue, LooseTupleSchema, LooseTupleSchemaAsync, ObjectIssue, ObjectSchema, ObjectSchemaAsync, ObjectWithRestIssue, ObjectWithRestSchema, ObjectWithRestSchemaAsync, StrictObjectIssue, StrictObjectSchema, StrictObjectSchemaAsync, StrictTupleIssue, StrictTupleSchema, StrictTupleSchemaAsync, TupleIssue, TupleSchema, TupleSchemaAsync, TupleWithRestIssue, TupleWithRestSchema, TupleWithRestSchemaAsync, } from '../../schemas/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, ErrorMessage, } from '../../types/index.ts'; import type { InferDefault } from '../getDefault/index.ts'; /** * Infer defaults type. */ export type InferDefaults< TSchema extends | BaseSchema> | BaseSchemaAsync>, > = TSchema extends | LooseObjectSchema< infer TEntries, ErrorMessage | undefined > | ObjectSchema | undefined> | ObjectWithRestSchema< infer TEntries, BaseSchema>, ErrorMessage | undefined > | StrictObjectSchema< infer TEntries, ErrorMessage | undefined > ? { -readonly [TKey in keyof TEntries]: InferDefaults } : TSchema extends | LooseObjectSchemaAsync< infer TEntries, ErrorMessage | undefined > | ObjectSchemaAsync< infer TEntries, ErrorMessage | undefined > | ObjectWithRestSchemaAsync< infer TEntries, BaseSchema>, ErrorMessage | undefined > | StrictObjectSchemaAsync< infer TEntries, ErrorMessage | undefined > ? { -readonly [TKey in keyof TEntries]: InferDefaults } : TSchema extends | LooseTupleSchema< infer TItems, ErrorMessage | undefined > | StrictTupleSchema< infer TItems, ErrorMessage | undefined > | TupleSchema | undefined> | TupleWithRestSchema< infer TItems, BaseSchema>, ErrorMessage | undefined > ? { -readonly [TKey in keyof TItems]: InferDefaults } : TSchema extends | LooseTupleSchemaAsync< infer TItems, ErrorMessage | undefined > | StrictTupleSchemaAsync< infer TItems, ErrorMessage | undefined > | TupleSchemaAsync< infer TItems, ErrorMessage | undefined > | TupleWithRestSchemaAsync< infer TItems, BaseSchema>, ErrorMessage | undefined > ? { -readonly [TKey in keyof TItems]: InferDefaults } : Awaited>; ================================================ FILE: library/src/methods/getDescription/getDescription.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { description, title } from '../../actions/index.ts'; import { string } from '../../schemas/index.ts'; import { pipe } from '../pipe/index.ts'; import { getDescription } from './getDescription.ts'; describe('getDescription', () => { test('should return undefined', () => { expect(getDescription(string())).toBeUndefined(); expect(getDescription(pipe(string()))).toBeUndefined(); expect(getDescription(pipe(string(), title('foo')))).toBeUndefined(); }); test('should return description', () => { expect(getDescription(pipe(string(), description('foo')))).toBe('foo'); expect( getDescription(pipe(string(), description('foo'), description('bar'))) ).toBe('bar'); expect( getDescription( pipe(pipe(string(), description('foo')), description('bar')) ) ).toBe('bar'); expect( getDescription( pipe(string(), description('foo'), pipe(string(), description('bar'))) ) ).toBe('foo'); }); }); ================================================ FILE: library/src/methods/getDescription/getDescription.ts ================================================ import type { DescriptionAction } from '../../actions/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, PipeItem, PipeItemAsync, } from '../../types/index.ts'; import { _getLastMetadata } from '../../utils/index.ts'; import type { SchemaWithPipe, SchemaWithPipeAsync } from '../index.ts'; /** * Schema type. */ type Schema = | BaseSchema> | BaseSchemaAsync> | SchemaWithPipe< readonly [ BaseSchema>, ...( | PipeItem> // eslint-disable-line @typescript-eslint/no-explicit-any | DescriptionAction )[], ] > | SchemaWithPipeAsync< readonly [ ( | BaseSchema> | BaseSchemaAsync> ), ...( | PipeItem> // eslint-disable-line @typescript-eslint/no-explicit-any | PipeItemAsync> // eslint-disable-line @typescript-eslint/no-explicit-any | DescriptionAction )[], ] >; /** * Returns the description of the schema. * * If multiple descriptions are defined, the last one of the highest level is * returned. If no description is defined, `undefined` is returned. * * @param schema The schema to get the description from. * * @returns The description, if any. * * @beta */ // TODO: Investigate if return type can be strongly typed // @__NO_SIDE_EFFECTS__ export function getDescription(schema: Schema): string | undefined { return _getLastMetadata(schema, 'description'); } ================================================ FILE: library/src/methods/getDescription/index.ts ================================================ export * from './getDescription.ts'; ================================================ FILE: library/src/methods/getExamples/getExamples.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { email, examples, startsWith } from '../../actions/index.ts'; import { string } from '../../schemas/index.ts'; import type { GenericSchema } from '../../types/index.ts'; import { pipe, pipeAsync } from '../pipe/index.ts'; import { getExamples } from './getExamples.ts'; describe('getExamples', () => { test('should return generic examples', () => { const genericSchema = string() as GenericSchema; expectTypeOf(getExamples(genericSchema)).toEqualTypeOf<[]>(); }); describe('should return empty array', () => { test('for schema without pipe', () => { expectTypeOf(getExamples(string())).toEqualTypeOf<[]>(); }); test('for schema with empty pipe', () => { expectTypeOf(getExamples(pipe(string()))).toEqualTypeOf(); }); test('for schema with no examples in pipe', () => { expectTypeOf(getExamples(pipe(string(), email()))).toEqualTypeOf< readonly [] >(); }); }); describe('should return single examples', () => { test('for simple schema with examples', () => { expectTypeOf( getExamples(pipe(string(), examples(['foo', 'bar']))) ).toEqualTypeOf(); }); test('for schema with examples in nested pipe', () => { expectTypeOf( getExamples(pipe(pipe(string(), examples(['foo', 'bar'])), email())) ).toEqualTypeOf(); }); test('for schema with examples in deeply nested pipe', () => { expectTypeOf( getExamples( pipe( string(), pipe(pipe(string(), examples(['foo', 'bar'])), email()), startsWith('foo') ) ) ).toEqualTypeOf(); }); test('for schema with examples in async pipe', () => { expectTypeOf( getExamples(pipeAsync(string(), examples(['foo', 'bar']))) ).toEqualTypeOf(); }); }); describe('should return merged examples', () => { test('for simple schema with multiple examples', () => { expectTypeOf( getExamples( pipe(string(), examples(['foo', 'bar']), examples(['baz', 'qux'])) ) ).toEqualTypeOf(); }); test('for schema with multiple examples in nested pipe', () => { expectTypeOf( getExamples( pipe( pipe(string(), examples(['foo', 'bar'])), examples(['baz', 'qux']) ) ) ).toEqualTypeOf(); }); test('for schema with multiple examples in deeply nested pipe', () => { expectTypeOf( getExamples( pipe( string(), pipe(pipe(string(), examples(['foo', 'bar'])), email()), examples(['baz', 'qux']) ) ) ).toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/methods/getExamples/getExamples.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { email, examples, startsWith } from '../../actions/index.ts'; import { string } from '../../schemas/index.ts'; import { pipe, pipeAsync } from '../pipe/index.ts'; import { getExamples } from './getExamples.ts'; describe('getExamples', () => { describe('should return empty array', () => { test('for schema without pipe', () => { expect(getExamples(string())).toStrictEqual([]); }); test('for schema with empty pipe', () => { expect(getExamples(pipe(string()))).toStrictEqual([]); }); test('for schema with no examples in pipe', () => { expect(getExamples(pipe(string(), email()))).toStrictEqual([]); }); }); describe('should return single examples', () => { test('for simple schema with examples', () => { expect( getExamples(pipe(string(), examples(['foo', 'bar']))) ).toStrictEqual(['foo', 'bar']); }); test('for schema with examples in nested pipe', () => { expect( getExamples(pipe(pipe(string(), examples(['foo', 'bar'])), email())) ).toStrictEqual(['foo', 'bar']); }); test('for schema with examples in deeply nested pipe', () => { expect( getExamples( pipe( string(), pipe(pipe(string(), examples(['foo', 'bar'])), email()), startsWith('foo') ) ) ).toStrictEqual(['foo', 'bar']); }); test('for schema with examples in async pipe', () => { expect( getExamples(pipeAsync(string(), examples(['foo', 'bar']))) ).toStrictEqual(['foo', 'bar']); }); }); describe('should return merged examples', () => { test('for simple schema with multiple examples', () => { expect( getExamples( pipe(string(), examples(['foo', 'bar']), examples(['baz', 'qux'])) ) ).toStrictEqual(['foo', 'bar', 'baz', 'qux']); }); test('for schema with multiple examples in nested pipe', () => { expect( getExamples( pipe( pipe(string(), examples(['foo', 'bar'])), examples(['baz', 'qux']) ) ) ).toStrictEqual(['foo', 'bar', 'baz', 'qux']); }); test('for schema with multiple examples in deeply nested pipe', () => { expect( getExamples( pipe( string(), pipe(pipe(string(), examples(['foo', 'bar'])), email()), examples(['baz', 'qux']) ) ) ).toStrictEqual(['foo', 'bar', 'baz', 'qux']); }); }); }); ================================================ FILE: library/src/methods/getExamples/getExamples.ts ================================================ import type { ExamplesAction } from '../../actions/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, PipeItem, PipeItemAsync, } from '../../types/index.ts'; import type { SchemaWithPipe, SchemaWithPipeAsync } from '../index.ts'; /** * Schema type. */ type Schema = | BaseSchema> | BaseSchemaAsync> | SchemaWithPipe< readonly [ BaseSchema>, ...( | PipeItem> // eslint-disable-line @typescript-eslint/no-explicit-any | ExamplesAction )[], ] > | SchemaWithPipeAsync< readonly [ ( | BaseSchema> | BaseSchemaAsync> ), ...( | PipeItem> // eslint-disable-line @typescript-eslint/no-explicit-any | PipeItemAsync> // eslint-disable-line @typescript-eslint/no-explicit-any | ExamplesAction )[], ] >; /** * Recursively concat type. */ type RecursiveConcat< TRootPipe extends readonly // prettier-ignore // eslint-disable-next-line @typescript-eslint/no-explicit-any (| PipeItem> // eslint-disable-next-line @typescript-eslint/no-explicit-any | PipeItemAsync> )[], TCollectedExamples extends unknown[] = [], > = TRootPipe extends readonly [ infer TFirstItem, ...infer TPipeRest extends readonly // prettier-ignore // eslint-disable-next-line @typescript-eslint/no-explicit-any (| PipeItem> // eslint-disable-next-line @typescript-eslint/no-explicit-any | PipeItemAsync> )[], ] ? TFirstItem extends | SchemaWithPipe | SchemaWithPipeAsync ? RecursiveConcat< TPipeRest, RecursiveConcat > : TFirstItem extends ExamplesAction ? RecursiveConcat : RecursiveConcat : TCollectedExamples; /** * Infer examples type. */ export type InferExamples = TSchema extends | SchemaWithPipe | SchemaWithPipeAsync ? Readonly> : []; /** * Returns the examples of a schema. * * If multiple examples are defined, it concatenates them using depth-first * search. If no examples are defined, an empty array is returned. * * @param schema The schema to get the examples from. * * @returns The examples, if any. * * @beta */ // @__NO_SIDE_EFFECTS__ export function getExamples( schema: TSchema ): InferExamples { const examples: unknown[] = []; function depthFirstCollect(schema: Schema): void { if ('pipe' in schema) { for (const item of schema.pipe) { if (item.kind === 'schema' && 'pipe' in item) { depthFirstCollect(item); } else if (item.kind === 'metadata' && item.type === 'examples') { // @ts-expect-error examples.push(...item.examples); } } } } depthFirstCollect(schema); // @ts-expect-error return examples; } ================================================ FILE: library/src/methods/getExamples/index.ts ================================================ export * from './getExamples.ts'; ================================================ FILE: library/src/methods/getFallback/getFallback.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { array, number, object, string } from '../../schemas/index.ts'; import { fallback, fallbackAsync } from '../fallback/index.ts'; import { pipe } from '../pipe/index.ts'; import { getFallback } from './getFallback.ts'; describe('getFallback', () => { test('should return undefined', () => { expectTypeOf(getFallback(string())).toEqualTypeOf(); expectTypeOf(getFallback(number())).toEqualTypeOf(); expectTypeOf(getFallback(object({}))).toEqualTypeOf(); }); describe('should return fallback for simple values', () => { const schema = pipe(string(), transform(parseInt)); test('for direct value', () => { expectTypeOf( getFallback(fallback(schema, 123 as const)) ).toEqualTypeOf<123>(); }); test('for value getter', () => { expectTypeOf( getFallback(fallback(schema, () => 123 as const)) ).toEqualTypeOf<123>(); }); test('for async value getter', () => { expectTypeOf( getFallback(fallbackAsync(schema, async () => 123 as const)) ).toEqualTypeOf>(); }); }); describe('should return fallback for object with array', () => { const schema = object({ foo: array(string()) }); test('for direct value', () => { const value: { readonly foo: readonly string[] } = { foo: [] }; expectTypeOf(getFallback(fallback(schema, value))).toEqualTypeOf<{ readonly foo: readonly string[]; }>(); }); test('for value getter', () => { const getter: () => { readonly foo: readonly string[] } = () => ({ foo: [], }); expectTypeOf(getFallback(fallback(schema, getter))).toEqualTypeOf<{ readonly foo: readonly string[]; }>(); }); test('for async value getter', () => { const getter: () => Promise<{ readonly foo: readonly string[]; }> = async () => ({ foo: [] }); expectTypeOf(getFallback(fallbackAsync(schema, getter))).toEqualTypeOf< Promise<{ readonly foo: readonly string[] }> >(); }); }); }); ================================================ FILE: library/src/methods/getFallback/getFallback.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { number, object, string } from '../../schemas/index.ts'; import { fallback, fallbackAsync } from '../fallback/index.ts'; import { pipe } from '../pipe/index.ts'; import { getFallback } from './getFallback.ts'; describe('getFallback', () => { test('should return undefined', () => { expect(getFallback(string())).toBeUndefined(); expect(getFallback(number())).toBeUndefined(); expect(getFallback(object({}))).toBeUndefined(); }); describe('should return fallback fallback', () => { const schema = pipe(string(), transform(parseInt)); test('for direct value', () => { expect(getFallback(fallback(schema, 123))).toBe(123); expect(getFallback(fallbackAsync(schema, 123))).toBe(123); }); test('for value getter', () => { expect(getFallback(fallback(schema, () => 123))).toBe(123); expect(getFallback(fallbackAsync(schema, () => 123))).toBe(123); }); test('for asycn value getter', async () => { expect(await getFallback(fallbackAsync(schema, async () => 123))).toBe( 123 ); }); }); }); ================================================ FILE: library/src/methods/getFallback/getFallback.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, Config, InferIssue, InferOutput, MaybeDeepReadonly, MaybePromise, OutputDataset, } from '../../types/index.ts'; import type { SchemaWithFallback, SchemaWithFallbackAsync, } from '../fallback/index.ts'; /** * Infer fallback type. */ export type InferFallback< TSchema extends | BaseSchema> | BaseSchemaAsync>, > = TSchema extends | SchemaWithFallback< BaseSchema>, infer TFallback > | SchemaWithFallbackAsync< | BaseSchema> | BaseSchemaAsync>, infer TFallback > ? TFallback extends MaybeDeepReadonly> ? TFallback : TFallback extends () => MaybePromise< MaybeDeepReadonly> > ? ReturnType : never : undefined; /** * Returns the fallback value of the schema. * * @param schema The schema to get it from. * @param dataset The output dataset if available. * @param config The config if available. * * @returns The fallback value. */ // @__NO_SIDE_EFFECTS__ export function getFallback< const TSchema extends | BaseSchema> | BaseSchemaAsync>, >( schema: TSchema, dataset?: OutputDataset, InferIssue>, config?: Config> ): InferFallback { // @ts-expect-error return typeof schema.fallback === 'function' ? // @ts-expect-error schema.fallback(dataset, config) : // @ts-expect-error schema.fallback; } ================================================ FILE: library/src/methods/getFallback/index.ts ================================================ export * from './getFallback.ts'; ================================================ FILE: library/src/methods/getFallbacks/getFallbacks.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { boolean, number, object, strictObject, strictTuple, string, tuple, } from '../../schemas/index.ts'; import { fallback } from '../fallback/index.ts'; import { getFallbacks } from './getFallbacks.ts'; describe('getFallbacks', () => { test('should return undefined', () => { expectTypeOf(getFallbacks(string())).toEqualTypeOf(); expectTypeOf(getFallbacks(number())).toEqualTypeOf(); expectTypeOf(getFallbacks(boolean())).toEqualTypeOf(); }); test('should return default', () => { expectTypeOf( getFallbacks(fallback(string(), 'foo' as const)) ).toEqualTypeOf<'foo'>(); expectTypeOf( getFallbacks(fallback(number(), () => 123 as const)) ).toEqualTypeOf<123>(); expectTypeOf( getFallbacks(fallback(boolean(), false as const)) ).toEqualTypeOf(); }); describe('should return object defaults', () => { test('for empty object', () => { // eslint-disable-next-line @typescript-eslint/no-empty-object-type expectTypeOf(getFallbacks(object({}))).toEqualTypeOf<{}>(); }); test('for simple object', () => { expectTypeOf( getFallbacks( object({ key1: fallback(string(), 'foo' as const), key2: fallback(number(), () => 123 as const), key3: fallback(boolean(), false as const), key4: string(), }) ) ).toEqualTypeOf<{ key1: 'foo'; key2: 123; key3: false; key4: undefined; }>(); }); test('for nested object', () => { expectTypeOf( getFallbacks( object({ nested: strictObject({ key1: fallback(string(), 'foo' as const), key2: fallback(number(), () => 123 as const), key3: fallback(boolean(), false as const), }), other: string(), }) ) ).toEqualTypeOf<{ nested: { key1: 'foo'; key2: 123; key3: false; }; other: undefined; }>(); }); }); describe('should return tuple defaults', () => { test('for empty tuple', () => { expectTypeOf(getFallbacks(tuple([]))).toEqualTypeOf<[]>(); }); test('for simple tuple', () => { expectTypeOf( getFallbacks( tuple([ fallback(string(), 'foo' as const), fallback(number(), () => 123 as const), fallback(boolean(), false as const), string(), ]) ) ).toEqualTypeOf<['foo', 123, false, undefined]>(); }); test('for nested tuple', () => { expectTypeOf( getFallbacks( tuple([ strictTuple([ fallback(string(), 'foo' as const), fallback(number(), () => 123 as const), fallback(boolean(), false as const), ]), string(), ]) ) ).toEqualTypeOf<[['foo', 123, false], undefined]>(); }); }); }); ================================================ FILE: library/src/methods/getFallbacks/getFallbacks.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { boolean, number, object, strictObject, strictTuple, string, tuple, } from '../../schemas/index.ts'; import { fallback } from '../fallback/index.ts'; import { getFallbacks } from './getFallbacks.ts'; describe('getFallbacks', () => { test('should return undefined', () => { expect(getFallbacks(string())).toBeUndefined(); expect(getFallbacks(number())).toBeUndefined(); expect(getFallbacks(boolean())).toBeUndefined(); }); test('should return default', () => { expect(getFallbacks(fallback(string(), 'foo' as const))).toBe('foo'); expect(getFallbacks(fallback(number(), () => 123 as const))).toBe(123); expect(getFallbacks(fallback(boolean(), false as const))).toBe(false); }); describe('should return object defaults', () => { test('for empty object', () => { expect(getFallbacks(object({}))).toStrictEqual({}); }); test('for simple object', () => { expect( getFallbacks( object({ key1: fallback(string(), 'foo' as const), key2: fallback(number(), () => 123 as const), key3: fallback(boolean(), false as const), key4: string(), }) ) ).toStrictEqual({ key1: 'foo', key2: 123, key3: false, key4: undefined, }); }); test('for nested object', () => { expect( getFallbacks( object({ nested: strictObject({ key1: fallback(string(), 'foo' as const), key2: fallback(number(), () => 123 as const), key3: fallback(boolean(), false as const), }), other: string(), }) ) ).toStrictEqual({ nested: { key1: 'foo', key2: 123, key3: false, }, other: undefined, }); }); }); describe('should return tuple defaults', () => { test('for empty tuple', () => { expect(getFallbacks(tuple([]))).toStrictEqual([]); }); test('for simple tuple', () => { expect( getFallbacks( tuple([ fallback(string(), 'foo' as const), fallback(number(), () => 123 as const), fallback(boolean(), false as const), string(), ]) ) ).toStrictEqual(['foo', 123, false, undefined]); }); test('for nested tuple', () => { expect( getFallbacks( tuple([ strictTuple([ fallback(string(), 'foo' as const), fallback(number(), () => 123 as const), fallback(boolean(), false as const), ]), string(), ]) ) ).toStrictEqual([['foo', 123, false], undefined]); }); }); }); ================================================ FILE: library/src/methods/getFallbacks/getFallbacks.ts ================================================ import type { LooseObjectIssue, LooseObjectSchema, LooseTupleIssue, LooseTupleSchema, ObjectIssue, ObjectSchema, ObjectWithRestIssue, ObjectWithRestSchema, StrictObjectIssue, StrictObjectSchema, StrictTupleIssue, StrictTupleSchema, TupleIssue, TupleSchema, TupleWithRestIssue, TupleWithRestSchema, } from '../../schemas/index.ts'; import type { BaseIssue, BaseSchema, ErrorMessage, ObjectEntries, TupleItems, } from '../../types/index.ts'; import { getFallback } from '../getFallback/index.ts'; import type { InferFallbacks } from './types.ts'; /** * Returns the fallback values of the schema. * * Hint: The difference to `getFallback` is that for object and tuple schemas * this function recursively returns the fallback values of the subschemas * instead of `undefined`. * * @param schema The schema to get them from. * * @returns The fallback values. */ // @__NO_SIDE_EFFECTS__ export function getFallbacks< const TSchema extends | BaseSchema> | LooseObjectSchema< ObjectEntries, ErrorMessage | undefined > | LooseTupleSchema | undefined> | ObjectSchema | undefined> | ObjectWithRestSchema< ObjectEntries, BaseSchema>, ErrorMessage | undefined > | StrictObjectSchema< ObjectEntries, ErrorMessage | undefined > | StrictTupleSchema | undefined> | TupleSchema | undefined> | TupleWithRestSchema< TupleItems, BaseSchema>, ErrorMessage | undefined >, >(schema: TSchema): InferFallbacks { // If it is an object schema, return fallbacks of entries if ('entries' in schema) { const object: Record = {}; for (const key in schema.entries) { object[key] = getFallbacks(schema.entries[key]); } return object as InferFallbacks; } // If it is a tuple schema, return fallbacks of items if ('items' in schema) { return schema.items.map(getFallbacks) as InferFallbacks; } // Otherwise, return fallback or `undefined` // @ts-expect-error return getFallback(schema); } ================================================ FILE: library/src/methods/getFallbacks/getFallbacksAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { boolean, number, object, objectAsync, strictObjectAsync, strictTupleAsync, string, tuple, tupleAsync, } from '../../schemas/index.ts'; import { fallback, fallbackAsync } from '../fallback/index.ts'; import { getFallbacksAsync } from './getFallbacksAsync.ts'; describe('getFallbacksAsync', () => { test('should return undefined', () => { expectTypeOf(getFallbacksAsync(string())).toEqualTypeOf< Promise >(); expectTypeOf(getFallbacksAsync(number())).toEqualTypeOf< Promise >(); expectTypeOf(getFallbacksAsync(boolean())).toEqualTypeOf< Promise >(); }); test('should return default', () => { expectTypeOf( getFallbacksAsync(fallback(string(), 'foo' as const)) ).toEqualTypeOf>(); expectTypeOf( getFallbacksAsync(fallback(number(), () => 123 as const)) ).toEqualTypeOf>(); expectTypeOf( getFallbacksAsync(fallbackAsync(boolean(), async () => false as const)) ).toEqualTypeOf>(); }); describe('should return object defaults', () => { test('for empty object', () => { // eslint-disable-next-line @typescript-eslint/no-empty-object-type expectTypeOf(getFallbacksAsync(object({}))).toEqualTypeOf>(); }); test('for simple object', () => { expectTypeOf( getFallbacksAsync( objectAsync({ key1: fallback(string(), 'foo' as const), key2: fallback(number(), () => 123 as const), key3: fallbackAsync(boolean(), false as const), key4: string(), }) ) ).toEqualTypeOf< Promise<{ key1: 'foo'; key2: 123; key3: false; key4: undefined; }> >(); }); test('for nested object', () => { expectTypeOf( getFallbacksAsync( objectAsync({ nested: strictObjectAsync({ key1: fallback(string(), 'foo' as const), key2: fallback(number(), () => 123 as const), key3: fallbackAsync(boolean(), false as const), }), other: string(), }) ) ).toEqualTypeOf< Promise<{ nested: { key1: 'foo'; key2: 123; key3: false; }; other: undefined; }> >(); }); }); describe('should return tuple defaults', () => { test('for empty tuple', () => { expectTypeOf(getFallbacksAsync(tuple([]))).toEqualTypeOf>(); }); test('for simple tuple', () => { expectTypeOf( getFallbacksAsync( tupleAsync([ fallback(string(), 'foo' as const), fallback(number(), () => 123 as const), fallbackAsync(boolean(), false as const), string(), ]) ) ).toEqualTypeOf>(); }); test('for nested tuple', () => { expectTypeOf( getFallbacksAsync( tupleAsync([ strictTupleAsync([ fallback(string(), 'foo' as const), fallback(number(), () => 123 as const), fallbackAsync(boolean(), false as const), ]), string(), ]) ) ).toEqualTypeOf>(); }); }); }); ================================================ FILE: library/src/methods/getFallbacks/getFallbacksAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { boolean, number, object, objectAsync, strictObjectAsync, strictTupleAsync, string, tuple, tupleAsync, } from '../../schemas/index.ts'; import { fallback, fallbackAsync } from '../fallback/index.ts'; import { getFallbacksAsync } from './getFallbacksAsync.ts'; describe('await getFallbacksAsync', () => { test('should return undefined', async () => { expect(await getFallbacksAsync(string())).toBeUndefined(); expect(await getFallbacksAsync(number())).toBeUndefined(); expect(await getFallbacksAsync(boolean())).toBeUndefined(); }); test('should return default', async () => { expect(await getFallbacksAsync(fallback(string(), 'foo' as const))).toBe( 'foo' ); expect( await getFallbacksAsync(fallback(number(), () => 123 as const)) ).toBe(123); expect( await getFallbacksAsync( fallbackAsync(boolean(), async () => false as const) ) ).toBe(false); }); describe('should return object defaults', () => { test('for empty object', async () => { expect(await getFallbacksAsync(object({}))).toStrictEqual({}); }); test('for simple object', async () => { expect( await getFallbacksAsync( objectAsync({ key1: fallback(string(), 'foo' as const), key2: fallback(number(), () => 123 as const), key3: fallbackAsync(boolean(), false as const), key4: string(), }) ) ).toStrictEqual({ key1: 'foo', key2: 123, key3: false, key4: undefined, }); }); test('for nested object', async () => { expect( await getFallbacksAsync( objectAsync({ nested: strictObjectAsync({ key1: fallback(string(), 'foo' as const), key2: fallback(number(), () => 123 as const), key3: fallbackAsync(boolean(), false as const), }), other: string(), }) ) ).toStrictEqual({ nested: { key1: 'foo', key2: 123, key3: false, }, other: undefined, }); }); }); describe('should return tuple defaults', () => { test('for empty tuple', async () => { expect(await getFallbacksAsync(tuple([]))).toStrictEqual([]); }); test('for simple tuple', async () => { expect( await getFallbacksAsync( tupleAsync([ fallback(string(), 'foo' as const), fallback(number(), () => 123 as const), fallbackAsync(boolean(), false as const), string(), ]) ) ).toStrictEqual(['foo', 123, false, undefined]); }); test('for nested tuple', async () => { expect( await getFallbacksAsync( tupleAsync([ strictTupleAsync([ fallback(string(), 'foo' as const), fallback(number(), () => 123 as const), fallbackAsync(boolean(), false as const), ]), string(), ]) ) ).toStrictEqual([['foo', 123, false], undefined]); }); }); }); ================================================ FILE: library/src/methods/getFallbacks/getFallbacksAsync.ts ================================================ import type { LooseObjectIssue, LooseObjectSchema, LooseObjectSchemaAsync, LooseTupleIssue, LooseTupleSchema, LooseTupleSchemaAsync, ObjectIssue, ObjectSchema, ObjectSchemaAsync, ObjectWithRestIssue, ObjectWithRestSchema, ObjectWithRestSchemaAsync, StrictObjectIssue, StrictObjectSchema, StrictObjectSchemaAsync, StrictTupleIssue, StrictTupleSchema, StrictTupleSchemaAsync, TupleIssue, TupleSchema, TupleSchemaAsync, TupleWithRestIssue, TupleWithRestSchema, TupleWithRestSchemaAsync, } from '../../schemas/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, ErrorMessage, ObjectEntries, ObjectEntriesAsync, TupleItems, TupleItemsAsync, } from '../../types/index.ts'; import { getFallback } from '../getFallback/index.ts'; import type { InferFallbacks } from './types.ts'; /** * Returns the fallback values of the schema. * * Hint: The difference to `getFallback` is that for object and tuple schemas * this function recursively returns the fallback values of the subschemas * instead of `undefined`. * * @param schema The schema to get them from. * * @returns The fallback values. */ // @__NO_SIDE_EFFECTS__ export async function getFallbacksAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync> | LooseObjectSchema< ObjectEntries, ErrorMessage | undefined > | LooseObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined > | LooseTupleSchema | undefined> | LooseTupleSchemaAsync< TupleItemsAsync, ErrorMessage | undefined > | ObjectSchema | undefined> | ObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined > | ObjectWithRestSchema< ObjectEntries, BaseSchema>, ErrorMessage | undefined > | ObjectWithRestSchemaAsync< ObjectEntriesAsync, | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined > | StrictObjectSchema< ObjectEntries, ErrorMessage | undefined > | StrictObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined > | StrictTupleSchema | undefined> | StrictTupleSchemaAsync< TupleItemsAsync, ErrorMessage | undefined > | TupleSchema | undefined> | TupleSchemaAsync | undefined> | TupleWithRestSchema< TupleItems, BaseSchema>, ErrorMessage | undefined > | TupleWithRestSchemaAsync< TupleItemsAsync, | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined >, >(schema: TSchema): Promise> { // If it is an object schema, return fallbacks of entries if ('entries' in schema) { return Object.fromEntries( await Promise.all( Object.entries(schema.entries).map(async ([key, value]) => [ key, await getFallbacksAsync(value), ]) ) ) as InferFallbacks; } // If it is a tuple schema, return fallbacks of items if ('items' in schema) { return Promise.all(schema.items.map(getFallbacksAsync)) as Promise< InferFallbacks >; } // Otherwise, return fallback or `undefined` // @ts-expect-error return getFallback(schema); } ================================================ FILE: library/src/methods/getFallbacks/index.ts ================================================ export * from './getFallbacks.ts'; export * from './getFallbacksAsync.ts'; export * from './types.ts'; ================================================ FILE: library/src/methods/getFallbacks/types.ts ================================================ import type { LooseObjectIssue, LooseObjectSchema, LooseObjectSchemaAsync, LooseTupleIssue, LooseTupleSchema, LooseTupleSchemaAsync, ObjectIssue, ObjectSchema, ObjectSchemaAsync, ObjectWithRestIssue, ObjectWithRestSchema, ObjectWithRestSchemaAsync, StrictObjectIssue, StrictObjectSchema, StrictObjectSchemaAsync, StrictTupleIssue, StrictTupleSchema, StrictTupleSchemaAsync, TupleIssue, TupleSchema, TupleSchemaAsync, TupleWithRestIssue, TupleWithRestSchema, TupleWithRestSchemaAsync, } from '../../schemas/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, ErrorMessage, } from '../../types/index.ts'; import type { InferFallback } from '../getFallback/index.ts'; /** * Infer fallbacks type. */ export type InferFallbacks< TSchema extends | BaseSchema> | BaseSchemaAsync>, > = TSchema extends | LooseObjectSchema< infer TEntries, ErrorMessage | undefined > | ObjectSchema | undefined> | ObjectWithRestSchema< infer TEntries, BaseSchema>, ErrorMessage | undefined > | StrictObjectSchema< infer TEntries, ErrorMessage | undefined > ? { -readonly [TKey in keyof TEntries]: InferFallbacks } : TSchema extends | LooseObjectSchemaAsync< infer TEntries, ErrorMessage | undefined > | ObjectSchemaAsync< infer TEntries, ErrorMessage | undefined > | ObjectWithRestSchemaAsync< infer TEntries, BaseSchema>, ErrorMessage | undefined > | StrictObjectSchemaAsync< infer TEntries, ErrorMessage | undefined > ? { -readonly [TKey in keyof TEntries]: InferFallbacks } : TSchema extends | LooseTupleSchema< infer TItems, ErrorMessage | undefined > | StrictTupleSchema< infer TItems, ErrorMessage | undefined > | TupleSchema | undefined> | TupleWithRestSchema< infer TItems, BaseSchema>, ErrorMessage | undefined > ? { -readonly [TKey in keyof TItems]: InferFallbacks } : TSchema extends | LooseTupleSchemaAsync< infer TItems, ErrorMessage | undefined > | StrictTupleSchemaAsync< infer TItems, ErrorMessage | undefined > | TupleSchemaAsync< infer TItems, ErrorMessage | undefined > | TupleWithRestSchemaAsync< infer TItems, BaseSchema>, ErrorMessage | undefined > ? { -readonly [TKey in keyof TItems]: InferFallbacks } : Awaited>; ================================================ FILE: library/src/methods/getMetadata/getMetadata.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { email, metadata, startsWith } from '../../actions/index.ts'; import { string } from '../../schemas/index.ts'; import type { GenericSchema } from '../../types/schema.ts'; import { pipe } from '../pipe/index.ts'; import { getMetadata } from './getMetadata.ts'; describe('getMetadata', () => { test('should return generic metadata', () => { const genericSchema = string() as GenericSchema; expectTypeOf(getMetadata(genericSchema)).toEqualTypeOf< Record >(); }); describe('should return empty object', () => { test('for schema without pipe', () => { // eslint-disable-next-line @typescript-eslint/no-empty-object-type expectTypeOf(getMetadata(string())).toEqualTypeOf<{}>(); }); test('for schema with empty pipe', () => { // eslint-disable-next-line @typescript-eslint/no-empty-object-type expectTypeOf(getMetadata(pipe(string()))).toEqualTypeOf<{}>(); }); test('for schema with no metadata in pipe', () => { // eslint-disable-next-line @typescript-eslint/no-empty-object-type expectTypeOf(getMetadata(pipe(string(), email()))).toEqualTypeOf<{}>(); }); }); describe('should return single metadata', () => { test('for simple schema with metadata', () => { expectTypeOf( getMetadata(pipe(string(), metadata({ key: 'foo' }))) ).toEqualTypeOf<{ readonly key: 'foo' }>(); }); test('for schema with metadata in nested pipe', () => { expectTypeOf( getMetadata(pipe(pipe(string(), metadata({ key: 'foo' })), email())) ).toEqualTypeOf<{ readonly key: 'foo' }>(); }); test('for schema with metadata in deeply nested pipe', () => { expectTypeOf( getMetadata( pipe( string(), pipe(pipe(string(), metadata({ key: 'foo' })), email()), startsWith('foo') ) ) ).toEqualTypeOf<{ readonly key: 'foo' }>(); }); }); describe('should return merged metadata', () => { test('for simple schema with multiple metadata', () => { expectTypeOf( getMetadata( pipe( string(), metadata({ key1: 'foo', key2: 'bar' }), metadata({ key2: 'baz', key3: 'qux' }) ) ) ).toEqualTypeOf<{ readonly key1: 'foo'; readonly key2: 'baz'; readonly key3: 'qux'; }>(); }); test('for schema with multiple metadata in nested pipe', () => { expectTypeOf( getMetadata( pipe( pipe(string(), metadata({ key1: 'foo', key2: 'bar' })), metadata({ key2: 'baz', key3: 'qux' }), email() ) ) ).toEqualTypeOf<{ readonly key1: 'foo'; readonly key2: 'baz'; readonly key3: 'qux'; }>(); }); test('for schema with multiple metadata in deeply nested pipe', () => { expectTypeOf( getMetadata( pipe( string(), pipe( pipe(string(), metadata({ key1: 'foo', key2: 'bar' })), metadata({ key2: 'baz' }), email() ), metadata({ key3: 'qux' }), startsWith('foo') ) ) ).toEqualTypeOf<{ readonly key1: 'foo'; readonly key2: 'baz'; readonly key3: 'qux'; }>(); }); }); }); ================================================ FILE: library/src/methods/getMetadata/getMetadata.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { email, metadata, startsWith } from '../../actions/index.ts'; import { string } from '../../schemas/index.ts'; import { pipe } from '../pipe/index.ts'; import { getMetadata } from './getMetadata.ts'; describe('getMetadata', () => { describe('should return empty object', () => { test('for schema without pipe', () => { expect(getMetadata(string())).toStrictEqual({}); }); test('for schema with empty pipe', () => { expect(getMetadata(pipe(string()))).toStrictEqual({}); }); test('for schema with no metadata in pipe', () => { expect(getMetadata(pipe(string(), email()))).toStrictEqual({}); }); }); describe('should return single metadata', () => { test('for simple schema with metadata', () => { expect( getMetadata(pipe(string(), metadata({ key: 'foo' }))) ).toStrictEqual({ key: 'foo' }); }); test('for schema with metadata in nested pipe', () => { expect( getMetadata(pipe(pipe(string(), metadata({ key: 'foo' })), email())) ).toStrictEqual({ key: 'foo' }); }); test('for schema with metadata in deeply nested pipe', () => { expect( getMetadata( pipe( string(), pipe(pipe(string(), metadata({ key: 'foo' })), email()), startsWith('foo') ) ) ).toStrictEqual({ key: 'foo' }); }); }); describe('should return merged metadata', () => { test('for simple schema with multiple metadata', () => { expect( getMetadata( pipe( string(), metadata({ key1: 'foo', key2: 'bar' }), metadata({ key2: 'baz', key3: 'qux' }) ) ) ).toStrictEqual({ key1: 'foo', key2: 'baz', key3: 'qux', }); }); test('for schema with multiple metadata in nested pipe', () => { expect( getMetadata( pipe( pipe(string(), metadata({ key1: 'foo', key2: 'bar' })), metadata({ key2: 'baz', key3: 'qux' }), email() ) ) ).toStrictEqual({ key1: 'foo', key2: 'baz', key3: 'qux', }); }); test('for schema with multiple metadata in deeply nested pipe', () => { expect( getMetadata( pipe( string(), pipe( pipe(string(), metadata({ key1: 'foo', key2: 'bar' })), metadata({ key2: 'baz' }), email() ), metadata({ key3: 'qux' }), startsWith('foo') ) ) ).toStrictEqual({ key1: 'foo', key2: 'baz', key3: 'qux', }); }); }); }); ================================================ FILE: library/src/methods/getMetadata/getMetadata.ts ================================================ import type { MetadataAction } from '../../actions/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, Merge, PipeItem, PipeItemAsync, Prettify, } from '../../types/index.ts'; import type { SchemaWithPipe, SchemaWithPipeAsync } from '../pipe/index.ts'; /** * Schema type. */ type Schema = | BaseSchema> | BaseSchemaAsync> | SchemaWithPipe< readonly [ BaseSchema>, ...( | PipeItem> // eslint-disable-line @typescript-eslint/no-explicit-any | MetadataAction> )[], ] > | SchemaWithPipeAsync< readonly [ ( | BaseSchema> | BaseSchemaAsync> ), ...( | PipeItem> // eslint-disable-line @typescript-eslint/no-explicit-any | PipeItemAsync> // eslint-disable-line @typescript-eslint/no-explicit-any | MetadataAction> )[], ] >; /** * Basic pipe item type. */ type BasicPipeItem = // eslint-disable-next-line @typescript-eslint/no-explicit-any | PipeItem> // eslint-disable-next-line @typescript-eslint/no-explicit-any | PipeItemAsync> | MetadataAction>; /** * Recursive merge type. */ type RecursiveMerge< TRootPipe extends readonly BasicPipeItem[], // eslint-disable-next-line @typescript-eslint/no-empty-object-type TCollectedMetadata extends Record = {}, > = TRootPipe extends readonly [ infer TFirstItem, ...infer TPipeRest extends readonly BasicPipeItem[], ] ? TFirstItem extends | SchemaWithPipe | SchemaWithPipeAsync ? RecursiveMerge> : TFirstItem extends MetadataAction ? RecursiveMerge> : RecursiveMerge : TCollectedMetadata; /** * Infer metadata type. * * @beta */ export type InferMetadata = // eslint-disable-next-line @typescript-eslint/no-explicit-any BaseSchema extends TSchema ? Record : // eslint-disable-next-line @typescript-eslint/no-explicit-any BaseSchemaAsync extends TSchema ? Record : TSchema extends | SchemaWithPipe | SchemaWithPipeAsync ? Prettify> : // eslint-disable-next-line @typescript-eslint/no-empty-object-type {}; /** * Returns the metadata of a schema. * * If multiple metadata are defined, it shallowly merges them using depth-first * search. If no metadata is defined, an empty object is returned. * * @param schema Schema to get the metadata from. * * @returns The metadata, if any. * * @beta */ // @__NO_SIDE_EFFECTS__ export function getMetadata( schema: TSchema ): InferMetadata { const result = {}; function depthFirstMerge(schema: Schema): void { if ('pipe' in schema) { for (const item of schema.pipe) { if (item.kind === 'schema' && 'pipe' in item) { depthFirstMerge(item); } else if (item.kind === 'metadata' && item.type === 'metadata') { // @ts-expect-error Object.assign(result, item.metadata); } } } } depthFirstMerge(schema); // @ts-expect-error return result; } ================================================ FILE: library/src/methods/getMetadata/index.ts ================================================ export * from './getMetadata.ts'; ================================================ FILE: library/src/methods/getTitle/getTitle.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { description, title } from '../../actions/index.ts'; import { string } from '../../schemas/index.ts'; import { pipe } from '../pipe/index.ts'; import { getTitle } from './getTitle.ts'; describe('getTitle', () => { test('should return undefined', () => { expect(getTitle(string())).toBeUndefined(); expect(getTitle(pipe(string()))).toBeUndefined(); expect(getTitle(pipe(string(), description('foo')))).toBeUndefined(); }); test('should return title', () => { expect(getTitle(pipe(string(), title('foo')))).toBe('foo'); expect(getTitle(pipe(string(), title('foo'), title('bar')))).toBe('bar'); expect(getTitle(pipe(pipe(string(), title('foo')), title('bar')))).toBe( 'bar' ); expect( getTitle(pipe(string(), title('foo'), pipe(string(), title('bar')))) ).toBe('foo'); }); }); ================================================ FILE: library/src/methods/getTitle/getTitle.ts ================================================ import type { TitleAction } from '../../actions/title/title.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, PipeItem, PipeItemAsync, } from '../../types/index.ts'; import { _getLastMetadata } from '../../utils/index.ts'; import type { SchemaWithPipe, SchemaWithPipeAsync } from '../index.ts'; /** * Schema type. */ type Schema = | BaseSchema> | BaseSchemaAsync> | SchemaWithPipe< readonly [ BaseSchema>, ...( | PipeItem> // eslint-disable-line @typescript-eslint/no-explicit-any | TitleAction )[], ] > | SchemaWithPipeAsync< readonly [ ( | BaseSchema> | BaseSchemaAsync> ), ...( | PipeItem> // eslint-disable-line @typescript-eslint/no-explicit-any | PipeItemAsync> // eslint-disable-line @typescript-eslint/no-explicit-any | TitleAction )[], ] >; /** * Returns the title of the schema. * * If multiple titles are defined, the last one of the highest level is * returned. If no title is defined, `undefined` is returned. * * @param schema The schema to get the title from. * * @returns The title, if any. * * @beta */ // TODO: Investigate if return type can be strongly typed // @__NO_SIDE_EFFECTS__ export function getTitle(schema: Schema): string | undefined { return _getLastMetadata(schema, 'title'); } ================================================ FILE: library/src/methods/getTitle/index.ts ================================================ export * from './getTitle.ts'; ================================================ FILE: library/src/methods/index.ts ================================================ export * from './assert/index.ts'; export * from './cache/index.ts'; export * from './config/index.ts'; export * from './fallback/index.ts'; export * from './flatten/index.ts'; export * from './forward/index.ts'; export * from './getDefault/index.ts'; export * from './getDefaults/index.ts'; export * from './getDescription/index.ts'; export * from './getExamples/index.ts'; export * from './getFallback/index.ts'; export * from './getFallbacks/index.ts'; export * from './getMetadata/index.ts'; export * from './getTitle/index.ts'; export * from './is/index.ts'; export * from './keyof/index.ts'; export * from './message/index.ts'; export * from './omit/index.ts'; export * from './parse/index.ts'; export * from './parser/index.ts'; export * from './partial/index.ts'; export * from './pick/index.ts'; export * from './pipe/index.ts'; export * from './required/index.ts'; export * from './safeParse/index.ts'; export * from './safeParser/index.ts'; export * from './summarize/index.ts'; export * from './unwrap/index.ts'; ================================================ FILE: library/src/methods/is/index.ts ================================================ export * from './is.ts'; ================================================ FILE: library/src/methods/is/is.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { object, string } from '../../schemas/index.ts'; import { pipe } from '../pipe/pipe.ts'; import { is } from './is.ts'; describe('is', () => { const input: unknown = { key: 'foo' }; const isValid = is( object({ key: pipe( string(), transform((input) => input.length) ), }), input ); test('should infer input type for valid input', () => { if (isValid) { expectTypeOf(input).toEqualTypeOf<{ key: string }>(); } }); test('should not infer input type for invalid input', () => { if (!isValid) { expectTypeOf(input).toEqualTypeOf(); } }); }); ================================================ FILE: library/src/methods/is/is.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { number, object, string } from '../../schemas/index.ts'; import { pipe } from '../pipe/index.ts'; import { is } from './is.ts'; describe('is', () => { const entries = { key: pipe( string(), transform((input) => input.length) ), }; test('should return true for valid input', () => { expect(is(string(), 'foo')).toBe(true); expect(is(number(), 123)).toBe(true); expect(is(object(entries), { key: 'foo' })).toBe(true); }); test('should return false for invalid input', () => { expect(is(string(), 123)).toBe(false); expect(is(number(), 'foo')).toBe(false); expect(is(object(entries), null)).toBe(false); }); }); ================================================ FILE: library/src/methods/is/is.ts ================================================ import type { BaseIssue, BaseSchema, InferInput } from '../../types/index.ts'; /** * Checks if the input matches the schema. By using a type predicate, this * function can be used as a type guard. * * @param schema The schema to be used. * @param input The input to be tested. * * @returns Whether the input matches the schema. */ // @__NO_SIDE_EFFECTS__ export function is< const TSchema extends BaseSchema>, >(schema: TSchema, input: unknown): input is InferInput { return !schema['~run']({ value: input }, { abortEarly: true }).issues; } ================================================ FILE: library/src/methods/keyof/index.ts ================================================ export * from './keyof.ts'; ================================================ FILE: library/src/methods/keyof/keyof.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { null_, number, object, type PicklistIssue, type PicklistSchema, string, unknown, } from '../../schemas/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { keyof } from './keyof.ts'; describe('keyof', () => { const objectSchema = object({ foo: string(), bar: number(), baz: null_() }); type Options = ['foo', 'bar', 'baz']; describe('should return schema object', () => { test('with undefined message', () => { type Schema = PicklistSchema; expectTypeOf(keyof(objectSchema)).toEqualTypeOf(); expectTypeOf(keyof(objectSchema, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(keyof(objectSchema, 'message')).toEqualTypeOf< PicklistSchema >(); }); test('with function message', () => { expectTypeOf(keyof(objectSchema, () => 'message')).toEqualTypeOf< PicklistSchema string> >(); }); }); describe('should infer correct types', () => { type Schema = PicklistSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf<'foo' | 'bar' | 'baz'>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< 'foo' | 'bar' | 'baz' >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); test('should not trigger TS error for many keys', () => { expectTypeOf( keyof( object({ k00: unknown(), k01: unknown(), k02: unknown(), k03: unknown(), k04: unknown(), k05: unknown(), k06: unknown(), k07: unknown(), k08: unknown(), k09: unknown(), k10: unknown(), k11: unknown(), k12: unknown(), k13: unknown(), k14: unknown(), k15: unknown(), k16: unknown(), k17: unknown(), k18: unknown(), k19: unknown(), k20: unknown(), k21: unknown(), k22: unknown(), k23: unknown(), k24: unknown(), k25: unknown(), k26: unknown(), k27: unknown(), k28: unknown(), k29: unknown(), k30: unknown(), k31: unknown(), k32: unknown(), k33: unknown(), k34: unknown(), k35: unknown(), k36: unknown(), k37: unknown(), k38: unknown(), k39: unknown(), k40: unknown(), k41: unknown(), k42: unknown(), k43: unknown(), k44: unknown(), k45: unknown(), k46: unknown(), k47: unknown(), k48: unknown(), k49: unknown(), k50: unknown(), k51: unknown(), k52: unknown(), k53: unknown(), k54: unknown(), k55: unknown(), k56: unknown(), k57: unknown(), k58: unknown(), k59: unknown(), k60: unknown(), }) ) ).toEqualTypeOf< PicklistSchema< [ 'k00', 'k01', 'k02', 'k03', 'k04', 'k05', 'k06', 'k07', 'k08', 'k09', 'k10', 'k11', 'k12', 'k13', 'k14', 'k15', 'k16', 'k17', 'k18', 'k19', 'k20', 'k21', 'k22', 'k23', 'k24', 'k25', 'k26', 'k27', 'k28', 'k29', 'k30', 'k31', 'k32', 'k33', 'k34', 'k35', 'k36', 'k37', 'k38', 'k39', 'k40', 'k41', 'k42', 'k43', 'k44', 'k45', 'k46', 'k47', 'k48', 'k49', 'k50', 'k51', 'k52', 'k53', 'k54', 'k55', 'k56', 'k57', 'k58', 'k59', 'k60', ], undefined > >(); }); }); ================================================ FILE: library/src/methods/keyof/keyof.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { null_, number, object, picklist, type PicklistSchema, string, } from '../../schemas/index.ts'; import { keyof } from './keyof.ts'; describe('keyof', () => { const objectSchema = object({ foo: string(), bar: number(), baz: null_() }); const options = ['foo', 'bar', 'baz'] as const; type Options = typeof options; describe('should return objectSchema object', () => { const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'picklist', reference: picklist, expects: '("foo" | "bar" | "baz")', options, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const picklistSchema: PicklistSchema = { ...baseSchema, message: undefined, }; expect(keyof(objectSchema)).toStrictEqual(picklistSchema); expect(keyof(objectSchema, undefined)).toStrictEqual(picklistSchema); }); test('with string message', () => { expect(keyof(objectSchema, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies PicklistSchema); }); test('with function message', () => { const message = () => 'message'; expect(keyof(objectSchema, message)).toStrictEqual({ ...baseSchema, message, } satisfies PicklistSchema); }); }); }); ================================================ FILE: library/src/methods/keyof/keyof.ts ================================================ import { type LooseObjectIssue, type LooseObjectSchema, type LooseObjectSchemaAsync, type ObjectIssue, type ObjectSchema, type ObjectSchemaAsync, type ObjectWithRestIssue, type ObjectWithRestSchema, type ObjectWithRestSchemaAsync, picklist, type PicklistIssue, type PicklistSchema, type StrictObjectIssue, type StrictObjectSchema, type StrictObjectSchemaAsync, } from '../../schemas/index.ts'; import type { BaseIssue, BaseSchema, ErrorMessage, ObjectEntries, ObjectEntriesAsync, UnionToTuple, } from '../../types/index.ts'; /** * Schema type. */ type Schema = | LooseObjectSchema | undefined> | LooseObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined > | ObjectSchema | undefined> | ObjectSchemaAsync | undefined> | ObjectWithRestSchema< ObjectEntries, BaseSchema>, ErrorMessage | undefined > | ObjectWithRestSchemaAsync< ObjectEntriesAsync, BaseSchema>, ErrorMessage | undefined > | StrictObjectSchema< ObjectEntries, ErrorMessage | undefined > | StrictObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined >; /** * Force tuple type. */ type ForceTuple = T extends [string, ...string[]] ? T : []; /** * Object keys type. */ type ObjectKeys = ForceTuple< UnionToTuple >; /** * Creates a picklist schema of object keys. * * @param schema The object schema. * * @returns A picklist schema. */ export function keyof( schema: TSchema ): PicklistSchema, undefined>; /** * Creates a picklist schema of object keys. * * @param schema The object schema. * @param message The error message. * * @returns A picklist schema. */ export function keyof< const TSchema extends Schema, const TMessage extends ErrorMessage | undefined, >( schema: TSchema, message: TMessage ): PicklistSchema, TMessage>; // @__NO_SIDE_EFFECTS__ export function keyof( schema: Schema, message?: ErrorMessage ): PicklistSchema, ErrorMessage | undefined> { return picklist(Object.keys(schema.entries) as ObjectKeys, message); } ================================================ FILE: library/src/methods/message/index.ts ================================================ export * from './message.ts'; ================================================ FILE: library/src/methods/message/message.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { objectAsync, string } from '../../schemas/index.ts'; import { message } from './message.ts'; describe('message', () => { test('should return schema object', () => { const schema = string(); expectTypeOf(message(schema, 'message')).toEqualTypeOf(); }); test('should return async schema object', () => { const schema = objectAsync({ key: string() }); expectTypeOf(message(schema, 'message')).toEqualTypeOf(); }); }); ================================================ FILE: library/src/methods/message/message.test.ts ================================================ import { describe, expect, test, vi } from 'vitest'; import { objectAsync, string } from '../../schemas/index.ts'; import type { BaseIssue, Config } from '../../types/index.ts'; import { message } from './message.ts'; describe('message', () => { test('should return copy of passed schema', () => { expect(message(string(), 'message')).toStrictEqual({ kind: 'schema', type: 'string', reference: string, expects: 'string', async: false, message: undefined, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }); }); test('should override config of schema', () => { const schema = string(); // @ts-expect-error schema['~run'] = vi.fn(schema['~run']); const dataset = { value: 'foo' }; const globalConfig: Config> = { abortPipeEarly: true, message: 'global config error', }; const errorMessage = 'local config error'; message(schema, errorMessage)['~run'](dataset, globalConfig); expect(schema['~run']).toHaveBeenCalledWith(dataset, { ...globalConfig, message: errorMessage, }); }); test('should override config of async schema', () => { const schema = objectAsync({ key: string() }); // @ts-expect-error schema['~run'] = vi.fn(schema['~run']); const dataset = { value: { key: 'foo' } }; const globalConfig: Config> = { abortPipeEarly: true, message: 'global config error', }; const errorMessage = 'local config error'; message(schema, errorMessage)['~run'](dataset, globalConfig); expect(schema['~run']).toHaveBeenCalledWith(dataset, { ...globalConfig, message: errorMessage, }); }); }); ================================================ FILE: library/src/methods/message/message.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, ErrorMessage, InferIssue, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; /** * Changes the local message configuration of a schema. * * @param schema The schema to configure. * @param message_ The error message. * * @returns The configured schema. */ // @__NO_SIDE_EFFECTS__ export function message< const TSchema extends | BaseSchema> | BaseSchemaAsync>, >(schema: TSchema, message_: ErrorMessage>): TSchema { return { ...schema, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { return schema['~run'](dataset, { ...config, message: message_ }); }, }; } ================================================ FILE: library/src/methods/omit/index.ts ================================================ export * from './omit.ts'; ================================================ FILE: library/src/methods/omit/omit.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { boolean, type BooleanIssue, type BooleanSchema, number, type NumberIssue, type NumberSchema, object, type ObjectIssue, type ObjectSchema, objectWithRest, type ObjectWithRestIssue, type ObjectWithRestSchema, string, type StringIssue, type StringSchema, } from '../../schemas/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { omit, type SchemaWithOmit } from './omit.ts'; describe('omit', () => { describe('object', () => { type Schema = SchemaWithOmit< ObjectSchema< { readonly key1: StringSchema; readonly key2: NumberSchema; readonly key3: StringSchema; readonly key4: NumberSchema; }, undefined >, ['key1', 'key3'] >; test('should return schema object', () => { expectTypeOf( omit( object({ key1: string(), key2: number(), key3: string(), key4: number(), }), ['key1', 'key3'] ) ).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf<{ key2: number; key4: number; }>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf<{ key2: number; key4: number; }>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< ObjectIssue | NumberIssue >(); }); }); }); describe('objectWithRest', () => { type Schema = SchemaWithOmit< ObjectWithRestSchema< { readonly key1: StringSchema; readonly key2: NumberSchema; readonly key3: StringSchema; readonly key4: NumberSchema; }, BooleanSchema, undefined >, ['key2', 'key3'] >; test('should return schema object', () => { expectTypeOf( omit( objectWithRest( { key1: string(), key2: number(), key3: string(), key4: number() }, boolean() ), ['key2', 'key3'] ) ).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf< { key1: string; key4: number } & { [key: string]: boolean } >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< { key1: string; key4: number } & { [key: string]: boolean } >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< ObjectWithRestIssue | NumberIssue | StringIssue | BooleanIssue >(); }); }); }); }); ================================================ FILE: library/src/methods/omit/omit.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { boolean, type BooleanIssue, number, object, objectWithRest, string, } from '../../schemas/index.ts'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssue } from '../../vitest/index.ts'; import { omit } from './omit.ts'; describe('omit', () => { const entries = { key1: string(), key2: number(), key3: string(), key4: number(), }; const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, } as const; describe('object', () => { const schema = omit(object(entries), ['key1', 'key3']); test('should return schema object', () => { expect(schema).toStrictEqual({ kind: 'schema', type: 'object', reference: object, expects: 'Object', entries: { key2: { ...number(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: { ...number(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, }, message: undefined, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } satisfies typeof schema); }); describe('should return dataset without nested issues', () => { test('if not omitted keys are specified', () => { expectNoSchemaIssue(schema, [{ key2: 123, key4: 456 }]); }); test('for unknown entries', () => { expect( schema['~run']( { value: { key1: 'foo', key2: 123, key4: 456, other: null } }, {} ) ).toStrictEqual({ typed: true, value: { key2: 123, key4: 456 }, }); }); }); describe('should return dataset with nested issues', () => { test('if a not omitted key is missing', () => { expect(schema['~run']({ value: { key2: 123 } }, {})).toStrictEqual({ typed: false, value: { key2: 123 }, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key4"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: { key2: 123 }, key: 'key4', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); }); }); describe('objectWithRest', () => { const schema = omit(objectWithRest(entries, boolean()), ['key2', 'key3']); test('should return schema object', () => { expect(schema).toStrictEqual({ kind: 'schema', type: 'object_with_rest', reference: objectWithRest, expects: 'Object', entries: { key1: { ...string(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: { ...number(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, }, rest: { ...boolean(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, message: undefined, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } satisfies typeof schema); }); describe('should return dataset without nested issues', () => { test('if not omitted keys are specified', () => { // @ts-expect-error expectNoSchemaIssue(schema, [{ key1: 'foo', key4: 456 }]); }); test('if omitted key matches rest', () => { // @ts-expect-error expectNoSchemaIssue(schema, [{ key1: 'foo', key2: true, key4: 456 }]); }); }); describe('should return dataset with nested issues', () => { test('if a not omitted key is missing', () => { expect(schema['~run']({ value: { key1: 'foo' } }, {})).toStrictEqual({ typed: false, value: { key1: 'foo' }, issues: [ { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key4"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: { key1: 'foo' }, key: 'key4', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('if an omitted key does not match rest', () => { expect( schema['~run']({ value: { key1: 'foo', key2: null, key4: 456 } }, {}) ).toStrictEqual({ typed: false, value: { key1: 'foo', key2: null, key4: 456 }, issues: [ { ...baseInfo, kind: 'schema', type: 'boolean', input: null, expected: 'boolean', received: 'null', path: [ { type: 'object', origin: 'value', input: { key1: 'foo', key2: null, key4: 456 }, key: 'key2', value: null, }, ], } satisfies BooleanIssue, ], } satisfies FailureDataset>); }); }); }); }); ================================================ FILE: library/src/methods/omit/omit.ts ================================================ import type { LooseObjectIssue, LooseObjectSchema, LooseObjectSchemaAsync, ObjectIssue, ObjectSchema, ObjectSchemaAsync, ObjectWithRestIssue, ObjectWithRestSchema, ObjectWithRestSchemaAsync, StrictObjectIssue, StrictObjectSchema, StrictObjectSchemaAsync, } from '../../schemas/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, Config, ErrorMessage, InferInput, InferIssue, InferObjectInput, InferObjectIssue, InferObjectOutput, InferOutput, ObjectEntries, ObjectEntriesAsync, ObjectKeys, OutputDataset, SchemaWithoutPipe, StandardProps, UnknownDataset, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; /** * Schema type. */ type Schema = SchemaWithoutPipe< | LooseObjectSchema | undefined> | LooseObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined > | ObjectSchema | undefined> | ObjectSchemaAsync | undefined> | ObjectWithRestSchema< ObjectEntries, BaseSchema>, ErrorMessage | undefined > | ObjectWithRestSchemaAsync< ObjectEntriesAsync, | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined > | StrictObjectSchema< ObjectEntries, ErrorMessage | undefined > | StrictObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined > >; /** * Schema with omit type. */ export type SchemaWithOmit< TSchema extends Schema, TKeys extends ObjectKeys, > = TSchema extends | ObjectSchema | undefined> | StrictObjectSchema< infer TEntries, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: Omit; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput>, InferObjectOutput> >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => OutputDataset< InferObjectOutput>, | Extract, { type: TSchema['type'] }> | InferObjectIssue> >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput>; readonly output: InferObjectOutput>; readonly issue: | Extract, { type: TSchema['type'] }> | InferObjectIssue>; } | undefined; } : TSchema extends | ObjectSchemaAsync< infer TEntries, ErrorMessage | undefined > | StrictObjectSchemaAsync< infer TEntries, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: Omit; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput>, InferObjectOutput> >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => Promise< OutputDataset< InferObjectOutput>, | Extract, { type: TSchema['type'] }> | InferObjectIssue> > >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput>; readonly output: InferObjectOutput>; readonly issue: | Extract, { type: TSchema['type'] }> | InferObjectIssue>; } | undefined; } : TSchema extends LooseObjectSchema< infer TEntries, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: Omit; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput> & { [key: string]: unknown; }, InferObjectInput> & { [key: string]: unknown; } >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => OutputDataset< InferObjectOutput> & { [key: string]: unknown; }, | Extract, { type: TSchema['type'] }> | InferObjectIssue> >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput< Omit > & { [key: string]: unknown; }; readonly output: InferObjectOutput< Omit > & { [key: string]: unknown; }; readonly issue: | Extract, { type: TSchema['type'] }> | InferObjectIssue>; } | undefined; } : TSchema extends LooseObjectSchemaAsync< infer TEntries, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: Omit; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput> & { [key: string]: unknown; }, InferObjectInput> & { [key: string]: unknown; } >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => Promise< OutputDataset< InferObjectOutput> & { [key: string]: unknown; }, | Extract, { type: TSchema['type'] }> | InferObjectIssue> > >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput< Omit > & { [key: string]: unknown; }; readonly output: InferObjectOutput< Omit > & { [key: string]: unknown; }; readonly issue: | Extract, { type: TSchema['type'] }> | InferObjectIssue>; } | undefined; } : TSchema extends ObjectWithRestSchema< infer TEntries, BaseSchema>, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: Omit; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput> & { [key: string]: InferInput; }, InferObjectOutput> & { [key: string]: InferOutput; } >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => OutputDataset< InferObjectOutput> & { [key: string]: InferOutput; }, | Extract, { type: TSchema['type'] }> | InferObjectIssue> | InferIssue >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput< Omit > & { [key: string]: InferInput; }; readonly output: InferObjectOutput< Omit > & { [key: string]: InferOutput }; readonly issue: | Extract, { type: TSchema['type'] }> | InferObjectIssue> | InferIssue; } | undefined; } : TSchema extends ObjectWithRestSchemaAsync< infer TEntries, BaseSchema>, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: Omit; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput> & { [key: string]: InferInput; }, InferObjectOutput> & { [key: string]: InferOutput; } >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => Promise< OutputDataset< InferObjectOutput> & { [key: string]: InferOutput; }, | Extract, { type: TSchema['type'] }> | InferObjectIssue> | InferIssue > >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput< Omit > & { [key: string]: InferInput; }; readonly output: InferObjectOutput< Omit > & { [key: string]: InferOutput }; readonly issue: | Extract< InferIssue, { type: TSchema['type'] } > | InferObjectIssue> | InferIssue; } | undefined; } : never; /** * Creates a modified copy of an object schema that does not contain the * selected entries. * * @param schema The schema to omit from. * @param keys The selected entries. * * @returns An object schema. */ // @__NO_SIDE_EFFECTS__ export function omit< const TSchema extends Schema, const TKeys extends ObjectKeys, >(schema: TSchema, keys: TKeys): SchemaWithOmit { // Create modified object entries // @ts-expect-error const entries: Omit = { ...schema.entries, }; for (const key of keys) { // @ts-expect-error // eslint-disable-next-line @typescript-eslint/no-dynamic-delete delete entries[key]; } // Rerturn modified copy of schema // @ts-expect-error return { ...schema, entries, get '~standard'() { return _getStandardProps(this); }, }; } ================================================ FILE: library/src/methods/parse/index.ts ================================================ export * from './parse.ts'; export * from './parseAsync.ts'; ================================================ FILE: library/src/methods/parse/parse.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { object, string } from '../../schemas/index.ts'; import { pipe } from '../pipe/pipe.ts'; import { parse } from './parse.ts'; describe('parse', () => { test('should return output type of schema', () => { expectTypeOf( parse( object({ key: pipe( string(), transform((input) => input.length) ), }), { key: 'foo' } ) ).toEqualTypeOf<{ key: number }>(); }); }); ================================================ FILE: library/src/methods/parse/parse.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { number, object, string } from '../../schemas/index.ts'; import { pipe } from '../pipe/index.ts'; import { parse } from './parse.ts'; describe('parse', () => { const entries = { key: pipe( string(), transform((input) => input.length) ), }; test('should return output for valid input', () => { expect(parse(string(), 'hello')).toBe('hello'); expect(parse(number(), 123)).toBe(123); expect(parse(object(entries), { key: 'foo' })).toStrictEqual({ key: 3, }); }); test('should throw error for invalid input', () => { expect(() => parse(string(), 123)).toThrowError(); expect(() => parse(number(), 'foo')).toThrowError(); expect(() => parse(object(entries), null)).toThrowError(); }); }); ================================================ FILE: library/src/methods/parse/parse.ts ================================================ import { getGlobalConfig } from '../../storages/index.ts'; import type { BaseIssue, BaseSchema, Config, InferIssue, InferOutput, } from '../../types/index.ts'; import { ValiError } from '../../utils/index.ts'; /** * Parses an unknown input based on a schema. * * @param schema The schema to be used. * @param input The input to be parsed. * @param config The parse configuration. * * @returns The parsed input. */ export function parse< const TSchema extends BaseSchema>, >( schema: TSchema, input: unknown, config?: Config> ): InferOutput { const dataset = schema['~run']({ value: input }, getGlobalConfig(config)); if (dataset.issues) { throw new ValiError(dataset.issues); } return dataset.value; } ================================================ FILE: library/src/methods/parse/parseAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { object, string } from '../../schemas/index.ts'; import { pipe } from '../pipe/pipe.ts'; import { parseAsync } from './parseAsync.ts'; describe('parseAsync', () => { test('should return output type of schema', () => { expectTypeOf( parseAsync( object({ key: pipe( string(), transform((input) => input.length) ), }), { key: 'foo' } ) ).toEqualTypeOf>(); }); }); ================================================ FILE: library/src/methods/parse/parseAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { number, objectAsync, string } from '../../schemas/index.ts'; import { pipe } from '../pipe/index.ts'; import { parseAsync } from './parseAsync.ts'; describe('parseAsync', () => { const entries = { key: pipe( string(), transform((input) => input.length) ), }; test('should return output for valid input', async () => { expect(await parseAsync(string(), 'hello')).toBe('hello'); expect(await parseAsync(number(), 123)).toBe(123); expect( await parseAsync(objectAsync(entries), { key: 'foo' }) ).toStrictEqual({ key: 3, }); }); test('should throw error for invalid input', async () => { await expect(() => parseAsync(string(), 123)).rejects.toThrowError(); await expect(() => parseAsync(number(), 'foo')).rejects.toThrowError(); await expect(() => parseAsync(objectAsync(entries), null) ).rejects.toThrowError(); }); }); ================================================ FILE: library/src/methods/parse/parseAsync.ts ================================================ import { getGlobalConfig } from '../../storages/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, Config, InferIssue, InferOutput, } from '../../types/index.ts'; import { ValiError } from '../../utils/index.ts'; /** * Parses an unknown input based on a schema. * * @param schema The schema to be used. * @param input The input to be parsed. * @param config The parse configuration. * * @returns The parsed input. */ export async function parseAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, >( schema: TSchema, input: unknown, config?: Config> ): Promise> { const dataset = await schema['~run']( { value: input }, getGlobalConfig(config) ); if (dataset.issues) { throw new ValiError(dataset.issues); } return dataset.value; } ================================================ FILE: library/src/methods/parser/index.ts ================================================ export * from './parser.ts'; export * from './parserAsync.ts'; ================================================ FILE: library/src/methods/parser/parser.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { object, string } from '../../schemas/index.ts'; import type { Config, InferIssue } from '../../types/index.ts'; import { pipe } from '../pipe/pipe.ts'; import { type Parser, parser } from './parser.ts'; describe('parser', () => { describe('should return function object', () => { const schema = object({ key: pipe( string(), transform((input) => input.length) ), }); type Schema = typeof schema; test('without config', () => { expectTypeOf(parser(schema)).toEqualTypeOf>(); expectTypeOf(parser(schema, undefined)).toEqualTypeOf< Parser >(); }); test('with config', () => { const config: Config> = { abortEarly: true, }; expectTypeOf(parser(schema, config)).toEqualTypeOf< Parser >(); }); }); test('should return output type of schema', () => { expectTypeOf( parser( object({ key: pipe( string(), transform((input) => input.length) ), }) )({ key: 'foo' }) ).toEqualTypeOf<{ key: number }>(); }); }); ================================================ FILE: library/src/methods/parser/parser.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { number, object, string } from '../../schemas/index.ts'; import type { Config, InferIssue } from '../../types/index.ts'; import { pipe } from '../pipe/index.ts'; import { parser } from './parser.ts'; describe('parser', () => { const entries = { key: pipe( string(), transform((input) => input.length) ), }; describe('should return function object', () => { const schema = object(entries); test('without config', () => { const func1 = parser(schema); expect(func1).toBeInstanceOf(Function); expect(func1.schema).toBe(schema); expect(func1.config).toBeUndefined(); const func2 = parser(schema, undefined); expect(func2).toBeInstanceOf(Function); expect(func2.schema).toBe(schema); expect(func2.config).toBeUndefined(); }); test('with config', () => { const config: Config> = { abortEarly: true, }; const func = parser(schema, config); expect(func).toBeInstanceOf(Function); expect(func.schema).toBe(schema); expect(func.config).toBe(config); }); }); test('should return output for valid input', () => { expect(parser(string())('hello')).toBe('hello'); expect(parser(number())(123)).toBe(123); expect(parser(object(entries))({ key: 'foo' })).toStrictEqual({ key: 3, }); }); test('should throw error for invalid input', () => { expect(() => parser(string())(123)).toThrowError(); expect(() => parser(number())('foo')).toThrowError(); expect(() => parser(object(entries))(null)).toThrowError(); }); }); ================================================ FILE: library/src/methods/parser/parser.ts ================================================ import type { BaseIssue, BaseSchema, Config, InferIssue, InferOutput, } from '../../types/index.ts'; import { parse } from '../parse/index.ts'; /** * The parser interface. */ export interface Parser< TSchema extends BaseSchema>, TConfig extends Config> | undefined, > { /** * Parses an unknown input based on the schema. */ (input: unknown): InferOutput; /** * The schema to be used. */ readonly schema: TSchema; /** * The parser configuration. */ readonly config: TConfig; } /** * Returns a function that parses an unknown input based on a schema. * * @param schema The schema to be used. * * @returns The parser function. */ export function parser< const TSchema extends BaseSchema>, >(schema: TSchema): Parser; /** * Returns a function that parses an unknown input based on a schema. * * @param schema The schema to be used. * @param config The parser configuration. * * @returns The parser function. */ export function parser< const TSchema extends BaseSchema>, const TConfig extends Config> | undefined, >(schema: TSchema, config: TConfig): Parser; // @__NO_SIDE_EFFECTS__ export function parser( schema: BaseSchema>, config?: Config>>> ): Parser< BaseSchema>, Config> | undefined > { const func: Parser< BaseSchema>, Config> | undefined > = (input: unknown) => parse(schema, input, config); // @ts-expect-error func.schema = schema; // @ts-expect-error func.config = config; return func; } ================================================ FILE: library/src/methods/parser/parserAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { object, string } from '../../schemas/index.ts'; import type { Config, InferIssue } from '../../types/index.ts'; import { pipe } from '../pipe/pipe.ts'; import { type ParserAsync, parserAsync } from './parserAsync.ts'; describe('parserAsync', () => { describe('should return function object', () => { const schema = object({ key: pipe( string(), transform((input) => input.length) ), }); type Schema = typeof schema; test('without config', () => { expectTypeOf(parserAsync(schema)).toEqualTypeOf< ParserAsync >(); expectTypeOf(parserAsync(schema, undefined)).toEqualTypeOf< ParserAsync >(); }); test('with config', () => { const config: Config> = { abortEarly: true, }; expectTypeOf(parserAsync(schema, config)).toEqualTypeOf< ParserAsync >(); }); }); test('should return output type of schema', () => { expectTypeOf( parserAsync( object({ key: pipe( string(), transform((input) => input.length) ), }) )({ key: 'foo' }) ).toEqualTypeOf>(); }); }); ================================================ FILE: library/src/methods/parser/parserAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { number, objectAsync, string } from '../../schemas/index.ts'; import type { Config, InferIssue } from '../../types/index.ts'; import { pipe } from '../pipe/index.ts'; import { parserAsync } from './parserAsync.ts'; describe('parserAsync', () => { const entries = { key: pipe( string(), transform((input) => input.length) ), }; describe('should return function object', () => { const schema = objectAsync(entries); test('without config', () => { const func1 = parserAsync(schema); expect(func1).toBeInstanceOf(Function); expect(func1.schema).toBe(schema); expect(func1.config).toBeUndefined(); const func2 = parserAsync(schema, undefined); expect(func2).toBeInstanceOf(Function); expect(func2.schema).toBe(schema); expect(func2.config).toBeUndefined(); }); test('with config', () => { const config: Config> = { abortEarly: true, }; const func = parserAsync(schema, config); expect(func).toBeInstanceOf(Function); expect(func.schema).toBe(schema); expect(func.config).toBe(config); }); }); test('should return output for valid input', async () => { expect(await parserAsync(string())('hello')).toBe('hello'); expect(await parserAsync(number())(123)).toBe(123); expect( await parserAsync(objectAsync(entries))({ key: 'foo' }) ).toStrictEqual({ key: 3, }); }); test('should throw error for invalid input', async () => { await expect(() => parserAsync(string())(123)).rejects.toThrowError(); await expect(() => parserAsync(number())('foo')).rejects.toThrowError(); await expect(() => parserAsync(objectAsync(entries))(null) ).rejects.toThrowError(); }); }); ================================================ FILE: library/src/methods/parser/parserAsync.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, Config, InferIssue, InferOutput, } from '../../types/index.ts'; import { parseAsync } from '../parse/index.ts'; /** * The parser async interface. */ export interface ParserAsync< TSchema extends | BaseSchema> | BaseSchemaAsync>, TConfig extends Config> | undefined, > { /** * Parses an unknown input based on the schema. */ (input: unknown): Promise>; /** * The schema to be used. */ readonly schema: TSchema; /** * The parser configuration. */ readonly config: TConfig; } /** * Returns a function that parses an unknown input based on a schema. * * @param schema The schema to be used. * * @returns The parser function. */ export function parserAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, >(schema: TSchema): ParserAsync; /** * Returns a function that parses an unknown input based on a schema. * * @param schema The schema to be used. * @param config The parser configuration. * * @returns The parser function. */ export function parserAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TConfig extends Config> | undefined, >(schema: TSchema, config: TConfig): ParserAsync; // @__NO_SIDE_EFFECTS__ export function parserAsync( schema: | BaseSchema> | BaseSchemaAsync>, config?: Config< InferIssue< | BaseSchema> | BaseSchemaAsync> > > ): ParserAsync< | BaseSchema> | BaseSchemaAsync>, Config> | undefined > { const func: ParserAsync< | BaseSchema> | BaseSchemaAsync>, Config> | undefined > = (input: unknown) => parseAsync(schema, input, config); // @ts-expect-error func.schema = schema; // @ts-expect-error func.config = config; return func; } ================================================ FILE: library/src/methods/partial/index.ts ================================================ export * from './partial.ts'; export * from './partialAsync.ts'; ================================================ FILE: library/src/methods/partial/partial.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { boolean, type BooleanIssue, nullish, number, type NumberIssue, object, type ObjectIssue, objectWithRest, type ObjectWithRestIssue, string, type StringIssue, } from '../../schemas/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { partial, type SchemaWithPartial } from './partial.ts'; describe('partial', () => { const entries = { key1: string(), key2: number(), key3: string(), key4: nullish(number(), () => 123), }; describe('object', () => { const wrapped = object(entries); type Wrapped = typeof wrapped; type Schema1 = SchemaWithPartial; type Schema2 = SchemaWithPartial; describe('should return schema object', () => { test('with undefined keys', () => { expectTypeOf(partial(wrapped)).toEqualTypeOf(); }); test('with specific keys', () => { expectTypeOf( partial(wrapped, ['key1', 'key3']) ).toEqualTypeOf(); }); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf<{ key1?: string; key2?: number; key3?: string; key4?: number | null; }>(); expectTypeOf>().toEqualTypeOf<{ key1?: string; key2: number; key3?: string; key4?: number | null; }>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf<{ key1?: string; key2?: number; key3?: string; key4?: number; }>(); expectTypeOf>().toEqualTypeOf<{ key1?: string; key2: number; key3?: string; key4: number; }>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< ObjectIssue | StringIssue | NumberIssue >(); expectTypeOf>().toEqualTypeOf< ObjectIssue | StringIssue | NumberIssue >(); }); }); }); describe('objectWithRest', () => { const wrapped = objectWithRest(entries, boolean()); type Wrapped = typeof wrapped; type Schema1 = SchemaWithPartial; type Schema2 = SchemaWithPartial; describe('should return schema object', () => { test('with undefined keys', () => { expectTypeOf(partial(wrapped)).toEqualTypeOf(); }); test('with specific keys', () => { expectTypeOf( partial(wrapped, ['key2', 'key3']) ).toEqualTypeOf(); }); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf< { key1?: string; key2?: number; key3?: string; key4?: number | null; } & { [key: string]: boolean } >(); expectTypeOf>().toEqualTypeOf< { key1: string; key2?: number; key3?: string; key4?: number | null; } & { [key: string]: boolean } >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< { key1?: string; key2?: number; key3?: string; key4?: number; } & { [key: string]: boolean } >(); expectTypeOf>().toEqualTypeOf< { key1: string; key2?: number; key3?: string; key4: number; } & { [key: string]: boolean } >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< ObjectWithRestIssue | NumberIssue | StringIssue | BooleanIssue >(); expectTypeOf>().toEqualTypeOf< ObjectWithRestIssue | NumberIssue | StringIssue | BooleanIssue >(); }); }); }); }); ================================================ FILE: library/src/methods/partial/partial.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { boolean, nullish, number, object, objectWithRest, optional, string, } from '../../schemas/index.ts'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssue } from '../../vitest/index.ts'; import { partial } from './partial.ts'; describe('partial', () => { const entries = { key1: string(), key2: number(), key3: string(), key4: nullish(number(), 123), }; const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, } as const; describe('object', () => { const wrapped = object(entries); const schema1 = partial(wrapped); const schema2 = partial(wrapped, ['key1', 'key3']); describe('should return schema object', () => { test('with undefined keys', () => { expect(schema1).toStrictEqual({ kind: 'schema', type: 'object', reference: object, expects: 'Object', entries: { key1: { ...optional(entries.key1), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: { ...optional(entries.key2), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...optional(entries.key3), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: { ...optional(entries.key4), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, }, message: undefined, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } satisfies typeof schema1); }); test('with specific keys', () => { expect(schema2).toStrictEqual({ kind: 'schema', type: 'object', reference: object, expects: 'Object', entries: { key1: { ...optional(entries.key1), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: entries.key2, key3: { ...optional(entries.key3), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: entries.key4, }, message: undefined, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } satisfies typeof schema2); }); }); describe('should return dataset without nested issues', () => { test('if partial keys are present', () => { const input = { key1: 'foo', key2: 123, key3: 'bar', key4: 123 }; expectNoSchemaIssue(schema1, [input]); expectNoSchemaIssue(schema2, [input]); }); test('if partial keys are missing', () => { expectNoSchemaIssue(schema1, [{}]); expectNoSchemaIssue(schema2, [{ key2: 123, key4: 123 }]); }); }); describe('should return dataset with nested issues', () => { test('if non-partialed keys are missing', () => { for (const input of [{}, { key1: 'foo', key3: 'bar' }]) { expect(schema2['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: { ...input, key4: 123 }, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: input, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); } }); }); }); describe('objectWithRest', () => { const rest = boolean(); const wrapped = objectWithRest(entries, rest); const schema1 = partial(wrapped); const schema2 = partial(wrapped, ['key2', 'key3']); describe('should return schema object', () => { test('with undefined keys', () => { expect(schema1).toStrictEqual({ kind: 'schema', type: 'object_with_rest', reference: objectWithRest, expects: 'Object', entries: { key1: { ...optional(entries.key1), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: { ...optional(entries.key2), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...optional(entries.key3), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: { ...optional(entries.key4), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, }, rest, message: undefined, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } satisfies typeof schema1); }); test('with specific keys', () => { expect(schema2).toStrictEqual({ kind: 'schema', type: 'object_with_rest', reference: objectWithRest, expects: 'Object', entries: { key1: entries.key1, key2: { ...optional(entries.key2), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...optional(entries.key3), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: entries.key4, }, rest, message: undefined, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } satisfies typeof schema2); }); }); describe('should return dataset without nested issues', () => { test('if partial keys are present', () => { const input = { key1: 'foo', key2: 123, key3: 'bar', key4: 123, other: true, }; // @ts-expect-error expectNoSchemaIssue(schema1, [input]); // @ts-expect-error expectNoSchemaIssue(schema2, [input]); }); test('if partial keys are missing', () => { expectNoSchemaIssue(schema1, [{}]); // @ts-expect-error expectNoSchemaIssue(schema2, [{ key1: 'foo', key4: 123, other: true }]); }); }); describe('should return dataset with nested issues', () => { test('if non-partialed keys are missing', () => { for (const input of [{}, { key2: 123, key3: 'bar', other: true }]) { expect(schema2['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: { ...input, key4: 123 }, issues: [ { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: input, key: 'key1', value: undefined, }, ], }, ], } satisfies FailureDataset>); } }); }); }); }); ================================================ FILE: library/src/methods/partial/partial.ts ================================================ import { type LooseObjectIssue, type LooseObjectSchema, type ObjectIssue, type ObjectSchema, type ObjectWithRestIssue, type ObjectWithRestSchema, optional, type OptionalSchema, type StrictObjectIssue, type StrictObjectSchema, } from '../../schemas/index.ts'; import type { BaseIssue, BaseSchema, Config, ErrorMessage, InferInput, InferIssue, InferObjectInput, InferObjectOutput, InferOutput, ObjectEntries, ObjectKeys, OutputDataset, SchemaWithoutPipe, StandardProps, UnknownDataset, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; /** * Schema type. */ type Schema = SchemaWithoutPipe< | LooseObjectSchema | undefined> | ObjectSchema | undefined> | ObjectWithRestSchema< ObjectEntries, BaseSchema>, ErrorMessage | undefined > | StrictObjectSchema< ObjectEntries, ErrorMessage | undefined > >; /** * Partial entries type. */ type PartialEntries< TEntries extends ObjectEntries, TKeys extends readonly (keyof TEntries)[] | undefined, > = { [TKey in keyof TEntries]: TKeys extends readonly (keyof TEntries)[] ? TKey extends TKeys[number] ? OptionalSchema : TEntries[TKey] : OptionalSchema; }; /** * Schema with partial type. */ export type SchemaWithPartial< TSchema extends Schema, TKeys extends ObjectKeys | undefined, > = TSchema extends | ObjectSchema | undefined> | StrictObjectSchema< infer TEntries, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: PartialEntries; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput>, InferObjectOutput> >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => OutputDataset< InferObjectOutput>, InferIssue >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput>; readonly output: InferObjectOutput>; readonly issue: InferIssue; } | undefined; } : TSchema extends LooseObjectSchema< infer TEntries, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: PartialEntries; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput> & { [key: string]: unknown; }, InferObjectOutput> & { [key: string]: unknown; } >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => OutputDataset< InferObjectOutput> & { [key: string]: unknown; }, InferIssue >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput< PartialEntries > & { [key: string]: unknown; }; readonly output: InferObjectOutput< PartialEntries > & { [key: string]: unknown; }; readonly issue: InferIssue; } | undefined; } : TSchema extends ObjectWithRestSchema< infer TEntries, infer TRest, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: PartialEntries; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput> & { [key: string]: InferInput; }, InferObjectOutput> & { [key: string]: InferOutput; } >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => OutputDataset< InferObjectOutput> & { [key: string]: InferOutput; }, InferIssue >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput< PartialEntries > & { [key: string]: InferInput; }; readonly output: InferObjectOutput< PartialEntries > & { [key: string]: InferOutput }; readonly issue: InferIssue; } | undefined; } : never; /** * Creates a modified copy of an object schema that marks all entries as optional. * * @param schema The schema to modify. * * @returns An object schema. */ export function partial( schema: TSchema ): SchemaWithPartial; /** * Creates a modified copy of an object schema that marks the selected entries * as optional. * * @param schema The schema to modify. * @param keys The selected entries. * * @returns An object schema. */ export function partial< const TSchema extends Schema, const TKeys extends ObjectKeys, >(schema: TSchema, keys: TKeys): SchemaWithPartial; // @__NO_SIDE_EFFECTS__ export function partial( schema: Schema, keys?: ObjectKeys ): SchemaWithPartial | undefined> { // Create modified object entries const entries: PartialEntries> = {}; for (const key in schema.entries) { // @ts-expect-error entries[key] = !keys || keys.includes(key) ? optional(schema.entries[key]) : schema.entries[key]; } // Return modified copy of schema return { ...schema, entries, get '~standard'() { return _getStandardProps(this); }, }; } ================================================ FILE: library/src/methods/partial/partialAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { boolean, type BooleanIssue, nullishAsync, number, type NumberIssue, objectAsync, type ObjectIssue, objectWithRestAsync, type ObjectWithRestIssue, string, type StringIssue, } from '../../schemas/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { partialAsync, type SchemaWithPartialAsync } from './partialAsync.ts'; describe('partialAsync', () => { const entries = { key1: string(), key2: number(), key3: string(), key4: nullishAsync(number(), async () => 123), }; describe('objectAsync', () => { const wrapped = objectAsync(entries); type Wrapped = typeof wrapped; type Schema1 = SchemaWithPartialAsync; type Schema2 = SchemaWithPartialAsync; describe('should return schema objectAsync', () => { test('with undefined keys', () => { expectTypeOf(partialAsync(wrapped)).toEqualTypeOf(); }); test('with specific keys', () => { expectTypeOf( partialAsync(wrapped, ['key1', 'key3']) ).toEqualTypeOf(); }); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf<{ key1?: string; key2?: number; key3?: string; key4?: number | null; }>(); expectTypeOf>().toEqualTypeOf<{ key1?: string; key2: number; key3?: string; key4?: number | null; }>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf<{ key1?: string; key2?: number; key3?: string; key4?: number; }>(); expectTypeOf>().toEqualTypeOf<{ key1?: string; key2: number; key3?: string; key4: number; }>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< ObjectIssue | StringIssue | NumberIssue >(); expectTypeOf>().toEqualTypeOf< ObjectIssue | StringIssue | NumberIssue >(); }); }); }); describe('objectWithRestAsync', () => { const wrapped = objectWithRestAsync(entries, boolean()); type Wrapped = typeof wrapped; type Schema1 = SchemaWithPartialAsync; type Schema2 = SchemaWithPartialAsync; describe('should return schema objectAsync', () => { test('with undefined keys', () => { expectTypeOf(partialAsync(wrapped)).toEqualTypeOf(); }); test('with specific keys', () => { expectTypeOf( partialAsync(wrapped, ['key2', 'key3']) ).toEqualTypeOf(); }); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf< { key1?: string; key2?: number; key3?: string; key4?: number | null; } & { [key: string]: boolean } >(); expectTypeOf>().toEqualTypeOf< { key1: string; key2?: number; key3?: string; key4?: number | null; } & { [key: string]: boolean } >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< { key1?: string; key2?: number; key3?: string; key4?: number; } & { [key: string]: boolean } >(); expectTypeOf>().toEqualTypeOf< { key1: string; key2?: number; key3?: string; key4: number; } & { [key: string]: boolean } >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< ObjectWithRestIssue | NumberIssue | StringIssue | BooleanIssue >(); expectTypeOf>().toEqualTypeOf< ObjectWithRestIssue | NumberIssue | StringIssue | BooleanIssue >(); }); }); }); }); ================================================ FILE: library/src/methods/partial/partialAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { boolean, nullishAsync, number, objectAsync, objectWithRestAsync, optionalAsync, string, } from '../../schemas/index.ts'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssueAsync } from '../../vitest/index.ts'; import { partialAsync } from './partialAsync.ts'; describe('partialAsync', () => { const entries = { key1: string(), key2: number(), key3: string(), key4: nullishAsync(number(), async () => 123), }; const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, } as const; describe('objectAsync', () => { const wrapped = objectAsync(entries); const schema1 = partialAsync(wrapped); const schema2 = partialAsync(wrapped, ['key1', 'key3']); describe('should return schema objectAsync', () => { test('with undefined keys', () => { expect(schema1).toStrictEqual({ kind: 'schema', type: 'object', reference: objectAsync, expects: 'Object', entries: { key1: { ...optionalAsync(entries.key1), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: { ...optionalAsync(entries.key2), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...optionalAsync(entries.key3), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: { ...optionalAsync(entries.key4), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, }, message: undefined, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } satisfies typeof schema1); }); test('with specific keys', () => { expect(schema2).toStrictEqual({ kind: 'schema', type: 'object', reference: objectAsync, expects: 'Object', entries: { key1: { ...optionalAsync(entries.key1), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: entries.key2, key3: { ...optionalAsync(entries.key3), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: entries.key4, }, message: undefined, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } satisfies typeof schema2); }); }); describe('should return dataset without nested issues', () => { test('if partialAsync keys are present', async () => { const input = { key1: 'foo', key2: 123, key3: 'bar', key4: 123 }; await expectNoSchemaIssueAsync(schema1, [input]); await expectNoSchemaIssueAsync(schema2, [input]); }); test('if partialAsync keys are missing', async () => { await expectNoSchemaIssueAsync(schema1, [{}]); await expectNoSchemaIssueAsync(schema2, [{ key2: 123, key4: 123 }]); }); }); describe('should return dataset with nested issues', () => { test('if non-partialed keys are missing', async () => { for (const input of [{}, { key1: 'foo', key3: 'bar' }]) { expect(await schema2['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: { ...input, key4: 123 }, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: input, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); } }); }); }); describe('objectWithRestAsync', () => { const rest = boolean(); const wrapped = objectWithRestAsync(entries, rest); const schema1 = partialAsync(wrapped); const schema2 = partialAsync(wrapped, ['key2', 'key3']); describe('should return schema objectAsync', () => { test('with undefined keys', () => { expect(schema1).toStrictEqual({ kind: 'schema', type: 'object_with_rest', reference: objectWithRestAsync, expects: 'Object', entries: { key1: { ...optionalAsync(entries.key1), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: { ...optionalAsync(entries.key2), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...optionalAsync(entries.key3), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: { ...optionalAsync(entries.key4), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, }, rest, message: undefined, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } satisfies typeof schema1); }); test('with specific keys', () => { expect(schema2).toStrictEqual({ kind: 'schema', type: 'object_with_rest', reference: objectWithRestAsync, expects: 'Object', entries: { key1: entries.key1, key2: { ...optionalAsync(entries.key2), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...optionalAsync(entries.key3), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: entries.key4, }, rest, message: undefined, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } satisfies typeof schema2); }); }); describe('should return dataset without nested issues', () => { test('if partialAsync keys are present', async () => { const input = { key1: 'foo', key2: 123, key3: 'bar', key4: 123, other: true, }; // @ts-expect-error await expectNoSchemaIssueAsync(schema1, [input]); // @ts-expect-error await expectNoSchemaIssueAsync(schema2, [input]); }); test('if partialAsync keys are missing', async () => { await expectNoSchemaIssueAsync(schema1, [{}]); await expectNoSchemaIssueAsync(schema2, [ // @ts-expect-error { key1: 'foo', key4: 123, other: true }, ]); }); }); describe('should return dataset with nested issues', () => { test('if non-partialed keys are missing', async () => { for (const input of [{}, { key2: 123, key3: 'bar', other: true }]) { expect(await schema2['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: { ...input, key4: 123 }, issues: [ { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: input, key: 'key1', value: undefined, }, ], }, ], } satisfies FailureDataset>); } }); }); }); }); ================================================ FILE: library/src/methods/partial/partialAsync.ts ================================================ import { type LooseObjectIssue, type LooseObjectSchemaAsync, type ObjectIssue, type ObjectSchemaAsync, type ObjectWithRestIssue, type ObjectWithRestSchemaAsync, optionalAsync, type OptionalSchemaAsync, type StrictObjectIssue, type StrictObjectSchemaAsync, } from '../../schemas/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, Config, ErrorMessage, InferInput, InferIssue, InferObjectInput, InferObjectOutput, InferOutput, ObjectEntriesAsync, ObjectKeys, OutputDataset, SchemaWithoutPipe, StandardProps, UnknownDataset, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; /** * Schema type. */ type Schema = SchemaWithoutPipe< | LooseObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined > | ObjectSchemaAsync | undefined> | ObjectWithRestSchemaAsync< ObjectEntriesAsync, | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined > | StrictObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined > >; /** * Partial entries type. */ type PartialEntries< TEntries extends ObjectEntriesAsync, TKeys extends readonly (keyof TEntries)[] | undefined, > = { [TKey in keyof TEntries]: TKeys extends readonly (keyof TEntries)[] ? TKey extends TKeys[number] ? OptionalSchemaAsync : TEntries[TKey] : OptionalSchemaAsync; }; /** * Schema with partial type. */ export type SchemaWithPartialAsync< TSchema extends Schema, TKeys extends ObjectKeys | undefined, > = TSchema extends | ObjectSchemaAsync | undefined> | StrictObjectSchemaAsync< infer TEntries, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: PartialEntries; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput>, InferObjectOutput> >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => Promise< OutputDataset< InferObjectOutput>, InferIssue > >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput>; readonly output: InferObjectOutput>; readonly issue: InferIssue; } | undefined; } : TSchema extends LooseObjectSchemaAsync< infer TEntries, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: PartialEntries; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput> & { [key: string]: unknown; }, InferObjectOutput> & { [key: string]: unknown; } >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => Promise< OutputDataset< InferObjectOutput> & { [key: string]: unknown; }, InferIssue > >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput< PartialEntries > & { [key: string]: unknown; }; readonly output: InferObjectOutput< PartialEntries > & { [key: string]: unknown; }; readonly issue: InferIssue; } | undefined; } : TSchema extends ObjectWithRestSchemaAsync< infer TEntries, infer TRest, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: PartialEntries; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput> & { [key: string]: InferInput; }, InferObjectOutput> & { [key: string]: InferOutput; } >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => Promise< OutputDataset< InferObjectOutput> & { [key: string]: InferOutput; }, InferIssue > >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput< PartialEntries > & { [key: string]: InferInput; }; readonly output: InferObjectOutput< PartialEntries > & { [key: string]: InferOutput }; readonly issue: InferIssue; } | undefined; } : never; /** * Creates a modified copy of an object schema that marks all entries as optional. * * @param schema The schema to modify. * * @returns An object schema. */ export function partialAsync( schema: TSchema ): SchemaWithPartialAsync; /** * Creates a modified copy of an object schema that marks the selected entries * as optional. * * @param schema The schema to modify. * @param keys The selected entries. * * @returns An object schema. */ export function partialAsync< const TSchema extends Schema, const TKeys extends ObjectKeys, >(schema: TSchema, keys: TKeys): SchemaWithPartialAsync; // @__NO_SIDE_EFFECTS__ export function partialAsync( schema: Schema, keys?: ObjectKeys ): SchemaWithPartialAsync | undefined> { // Create modified object entries const entries: PartialEntries> = {}; for (const key in schema.entries) { // @ts-expect-error entries[key] = !keys || keys.includes(key) ? optionalAsync(schema.entries[key]) : schema.entries[key]; } // Return modified copy of schema return { ...schema, entries, get '~standard'() { return _getStandardProps(this); }, }; } ================================================ FILE: library/src/methods/pick/index.ts ================================================ export * from './pick.ts'; ================================================ FILE: library/src/methods/pick/pick.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { boolean, type BooleanIssue, type BooleanSchema, number, type NumberIssue, type NumberSchema, object, type ObjectIssue, type ObjectSchema, objectWithRest, type ObjectWithRestIssue, type ObjectWithRestSchema, string, type StringIssue, type StringSchema, } from '../../schemas/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { pick, type SchemaWithPick } from './pick.ts'; describe('pick', () => { describe('object', () => { type Schema = SchemaWithPick< ObjectSchema< { readonly key1: StringSchema; readonly key2: NumberSchema; readonly key3: StringSchema; readonly key4: NumberSchema; }, undefined >, ['key1', 'key3'] >; test('should return schema object', () => { expectTypeOf( pick( object({ key1: string(), key2: number(), key3: string(), key4: number(), }), ['key1', 'key3'] ) ).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf<{ key1: string; key3: string; }>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf<{ key1: string; key3: string; }>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< ObjectIssue | StringIssue >(); }); }); }); describe('objectWithRest', () => { type Schema = SchemaWithPick< ObjectWithRestSchema< { readonly key1: StringSchema; readonly key2: NumberSchema; readonly key3: StringSchema; readonly key4: NumberSchema; }, BooleanSchema, undefined >, ['key2', 'key3'] >; test('should return schema object', () => { expectTypeOf( pick( objectWithRest( { key1: string(), key2: number(), key3: string(), key4: number() }, boolean() ), ['key2', 'key3'] ) ).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf< { key2: number; key3: string } & { [key: string]: boolean } >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< { key2: number; key3: string } & { [key: string]: boolean } >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< ObjectWithRestIssue | NumberIssue | StringIssue | BooleanIssue >(); }); }); }); }); ================================================ FILE: library/src/methods/pick/pick.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { boolean, type BooleanIssue, number, object, objectWithRest, string, } from '../../schemas/index.ts'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssue } from '../../vitest/index.ts'; import { pick } from './pick.ts'; describe('pick', () => { const entries = { key1: string(), key2: number(), key3: string(), key4: number(), }; const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, } as const; describe('object', () => { const schema = pick(object(entries), ['key1', 'key3']); test('should return schema object', () => { expect(schema).toStrictEqual({ kind: 'schema', type: 'object', reference: object, expects: 'Object', entries: { key1: { ...string(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...string(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, }, message: undefined, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } satisfies typeof schema); }); describe('should return dataset without nested issues', () => { test('if picked keys are specified', () => { expectNoSchemaIssue(schema, [{ key1: 'foo', key3: 'bar' }]); }); test('for unknown entries', () => { expect( schema['~run']( { value: { key1: 'foo', key2: 123, key3: 'bar', other: null } }, {} ) ).toStrictEqual({ typed: true, value: { key1: 'foo', key3: 'bar' }, }); }); }); describe('should return dataset with nested issues', () => { test('if a picked key is missing', () => { expect(schema['~run']({ value: { key3: 'bar' } }, {})).toStrictEqual({ typed: false, value: { key3: 'bar' }, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: { key3: 'bar' }, key: 'key1', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); }); }); describe('objectWithRest', () => { const schema = pick(objectWithRest(entries, boolean()), ['key2', 'key3']); test('should return schema object', () => { expect(schema).toStrictEqual({ kind: 'schema', type: 'object_with_rest', reference: objectWithRest, expects: 'Object', entries: { key2: { ...number(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...string(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, }, rest: { ...boolean(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, message: undefined, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } satisfies typeof schema); }); describe('should return dataset without nested issues', () => { test('if picked keys are specified', () => { // @ts-expect-error expectNoSchemaIssue(schema, [{ key2: 123, key3: 'bar' }]); }); test('if not picked key matches rest', () => { // @ts-expect-error expectNoSchemaIssue(schema, [{ key1: false, key2: 123, key3: 'bar' }]); }); }); describe('should return dataset with nested issues', () => { test('if a picked key is missing', () => { expect(schema['~run']({ value: { key3: 'foo' } }, {})).toStrictEqual({ typed: false, value: { key3: 'foo' }, issues: [ { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: { key3: 'foo' }, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('if a not picked key does not match rest', () => { expect( schema['~run']({ value: { key1: 'foo', key2: 123, key3: 'foo' } }, {}) ).toStrictEqual({ typed: false, value: { key1: 'foo', key2: 123, key3: 'foo' }, issues: [ { ...baseInfo, kind: 'schema', type: 'boolean', input: 'foo', expected: 'boolean', received: '"foo"', path: [ { type: 'object', origin: 'value', input: { key1: 'foo', key2: 123, key3: 'foo' }, key: 'key1', value: 'foo', }, ], } satisfies BooleanIssue, ], } satisfies FailureDataset>); }); }); }); }); ================================================ FILE: library/src/methods/pick/pick.ts ================================================ import type { LooseObjectIssue, LooseObjectSchema, LooseObjectSchemaAsync, ObjectIssue, ObjectSchema, ObjectSchemaAsync, ObjectWithRestIssue, ObjectWithRestSchema, ObjectWithRestSchemaAsync, StrictObjectIssue, StrictObjectSchema, StrictObjectSchemaAsync, } from '../../schemas/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, Config, ErrorMessage, InferInput, InferIssue, InferObjectInput, InferObjectIssue, InferObjectOutput, InferOutput, ObjectEntries, ObjectEntriesAsync, ObjectKeys, OutputDataset, SchemaWithoutPipe, StandardProps, UnknownDataset, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; /** * The schema type. */ type Schema = SchemaWithoutPipe< | LooseObjectSchema | undefined> | LooseObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined > | ObjectSchema | undefined> | ObjectSchemaAsync | undefined> | ObjectWithRestSchema< ObjectEntries, BaseSchema>, ErrorMessage | undefined > | ObjectWithRestSchemaAsync< ObjectEntriesAsync, | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined > | StrictObjectSchema< ObjectEntries, ErrorMessage | undefined > | StrictObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined > >; /** * Schema with pick type. */ export type SchemaWithPick< TSchema extends Schema, TKeys extends ObjectKeys, > = TSchema extends | ObjectSchema | undefined> | StrictObjectSchema< infer TEntries, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: Pick; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput>, InferObjectOutput> >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => OutputDataset< InferObjectOutput>, | Extract, { type: TSchema['type'] }> | InferObjectIssue> >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput>; readonly output: InferObjectOutput>; readonly issue: | Extract, { type: TSchema['type'] }> | InferObjectIssue>; } | undefined; } : TSchema extends | ObjectSchemaAsync< infer TEntries, ErrorMessage | undefined > | StrictObjectSchemaAsync< infer TEntries, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: Pick; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput>, InferObjectOutput> >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => Promise< OutputDataset< InferObjectOutput>, | Extract, { type: TSchema['type'] }> | InferObjectIssue> > >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput>; readonly output: InferObjectOutput>; readonly issue: | Extract, { type: TSchema['type'] }> | InferObjectIssue>; } | undefined; } : TSchema extends LooseObjectSchema< infer TEntries, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: Pick; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput> & { [key: string]: unknown; }, InferObjectOutput> & { [key: string]: unknown; } >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => OutputDataset< InferObjectOutput> & { [key: string]: unknown; }, | Extract, { type: TSchema['type'] }> | InferObjectIssue> >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput< Pick > & { [key: string]: unknown; }; readonly output: InferObjectOutput< Pick > & { [key: string]: unknown; }; readonly issue: | Extract, { type: TSchema['type'] }> | InferObjectIssue>; } | undefined; } : TSchema extends LooseObjectSchemaAsync< infer TEntries, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: Pick; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput> & { [key: string]: unknown; }, InferObjectOutput> & { [key: string]: unknown; } >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => Promise< OutputDataset< InferObjectOutput> & { [key: string]: unknown; }, | Extract, { type: TSchema['type'] }> | InferObjectIssue> > >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput< Pick > & { [key: string]: unknown; }; readonly output: InferObjectOutput< Pick > & { [key: string]: unknown; }; readonly issue: | Extract, { type: TSchema['type'] }> | InferObjectIssue>; } | undefined; } : TSchema extends ObjectWithRestSchema< infer TEntries, BaseSchema>, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: Pick; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput> & { [key: string]: InferInput; }, InferObjectOutput> & { [key: string]: InferOutput; } >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => OutputDataset< InferObjectOutput> & { [key: string]: InferOutput; }, | Extract, { type: TSchema['type'] }> | InferObjectIssue> | InferIssue >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput< Pick > & { [key: string]: InferInput; }; readonly output: InferObjectOutput< Pick > & { [key: string]: InferOutput }; readonly issue: | Extract, { type: TSchema['type'] }> | InferObjectIssue> | InferIssue; } | undefined; } : TSchema extends ObjectWithRestSchemaAsync< infer TEntries, BaseSchema>, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: Pick; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput> & { [key: string]: InferInput; }, InferObjectOutput> & { [key: string]: InferOutput; } >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => Promise< OutputDataset< InferObjectOutput> & { [key: string]: InferOutput; }, | Extract, { type: TSchema['type'] }> | InferObjectIssue> | InferIssue > >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput< Pick > & { [key: string]: InferInput; }; readonly output: InferObjectOutput< Pick > & { [key: string]: InferOutput }; readonly issue: | Extract< InferIssue, { type: TSchema['type'] } > | InferObjectIssue> | InferIssue; } | undefined; } : never; /** * Creates a modified copy of an object schema that contains only the selected * entries. * * @param schema The schema to pick from. * @param keys The selected entries. * * @returns An object schema. */ // @__NO_SIDE_EFFECTS__ export function pick< const TSchema extends Schema, const TKeys extends ObjectKeys, >(schema: TSchema, keys: TKeys): SchemaWithPick { // Create modified object entries // @ts-expect-error const entries: Pick = {}; for (const key of keys) { // @ts-expect-error entries[key] = schema.entries[key]; } // Return modified copy of schema // @ts-expect-error return { ...schema, entries, get '~standard'() { return _getStandardProps(this); }, }; } ================================================ FILE: library/src/methods/pipe/index.ts ================================================ export * from './pipe.ts'; export * from './pipeAsync.ts'; ================================================ FILE: library/src/methods/pipe/pipe.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { decimal, type DecimalAction, type DecimalIssue, description, type DescriptionAction, minLength, type MinLengthAction, type MinLengthIssue, minValue, type MinValueAction, type MinValueIssue, transform, type TransformAction, trim, type TrimAction, } from '../../actions/index.ts'; import { number, type NumberIssue, type NumberSchema, string, type StringIssue, type StringSchema, } from '../../schemas/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { pipe, type SchemaWithPipe } from './pipe.ts'; describe('pipe', () => { const schema = pipe( string(), description('text'), trim(), minLength(1), decimal(), transform(parseInt), number(), minValue(100) ); test('should return schema object', () => { expectTypeOf(schema).toEqualTypeOf< SchemaWithPipe< readonly [ StringSchema, DescriptionAction, TrimAction, MinLengthAction, DecimalAction, TransformAction, NumberSchema, MinValueAction, ] > >(); }); describe('should infer correct types', () => { type Schema = typeof schema; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< | StringIssue | MinLengthIssue | DecimalIssue | NumberIssue | MinValueIssue >(); }); }); }); ================================================ FILE: library/src/methods/pipe/pipe.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { decimal, type DecimalIssue, description, minLength, type MinLengthIssue, minValue, transform, trim, } from '../../actions/index.ts'; import { DECIMAL_REGEX } from '../../regex.ts'; import { string } from '../../schemas/index.ts'; import { pipe } from './pipe.ts'; describe('pipe', () => { const schema = pipe( string(), description('text'), trim(), minLength(1), decimal() ); test('should return schema object', () => { expect(schema).toStrictEqual({ kind: 'schema', type: 'string', reference: string, expects: 'string', message: undefined, pipe: [ { ...string(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, description('text'), { ...trim(), '~run': expect.any(Function), }, { ...minLength(1), '~run': expect.any(Function), }, { ...decimal(), '~run': expect.any(Function), }, ], async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } satisfies typeof schema); }); test('should return dataset without issues', () => { expect(schema['~run']({ value: ' 123 ' }, {})).toStrictEqual({ typed: true, value: '123', }); }); const baseInfo = { message: expect.any(String), path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const minLengthIssue: MinLengthIssue = { ...baseInfo, kind: 'validation', type: 'min_length', input: '', expected: '>=1', received: '0', requirement: 1, }; const decimalIssue: DecimalIssue = { ...baseInfo, kind: 'validation', type: 'decimal', input: '', expected: null, received: '""', requirement: DECIMAL_REGEX, }; test('should return dataset with issues', () => { expect(schema['~run']({ value: ' ' }, {})).toStrictEqual({ typed: true, value: '', issues: [minLengthIssue, decimalIssue], }); }); describe('should break pipe if necessary', () => { test('for abort early config', () => { expect( schema['~run']({ value: ' ' }, { abortEarly: true }) ).toStrictEqual({ typed: true, value: '', issues: [{ ...minLengthIssue, abortEarly: true }], }); }); test('for abort pipe early config', () => { expect( schema['~run']({ value: ' ' }, { abortPipeEarly: true }) ).toStrictEqual({ typed: true, value: '', issues: [{ ...minLengthIssue, abortPipeEarly: true }], }); }); test('if next action is schema', () => { expect( pipe(schema, string(), minLength(10))['~run']({ value: ' ' }, {}) ).toStrictEqual({ typed: false, value: '', issues: [minLengthIssue, decimalIssue], }); }); test('if next action is transformation', () => { expect( pipe(schema, transform(parseInt), minValue(999))['~run']( { value: ' ' }, {} ) ).toStrictEqual({ typed: false, value: '', issues: [minLengthIssue, decimalIssue], }); }); }); }); ================================================ FILE: library/src/methods/pipe/pipe.ts ================================================ import type { BaseIssue, BaseSchema, Config, FirstTupleItem, InferInput, InferIssue, InferOutput, LastTupleItem, OutputDataset, PipeAction, PipeItem, StandardProps, UnknownDataset, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; /** * Schema with pipe type. */ export type SchemaWithPipe< TPipe extends readonly [ BaseSchema>, // eslint-disable-next-line @typescript-eslint/no-explicit-any ...PipeItem>[], ], > = Omit, 'pipe' | '~standard' | '~run' | '~types'> & { /** * The pipe items. */ readonly pipe: TPipe; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferInput>, InferOutput> >; /** * Parses unknown input values. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => OutputDataset< InferOutput>, InferIssue >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferInput>; readonly output: InferOutput>; readonly issue: InferIssue; } | undefined; }; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * * @returns A schema with a pipeline. */ export function pipe< const TSchema extends BaseSchema>, const TItem1 extends PipeItem< InferOutput, unknown, BaseIssue >, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue> ): SchemaWithPipe; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * * @returns A schema with a pipeline. */ export function pipe< const TSchema extends BaseSchema>, const TItem1 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem2 extends PipeItem< InferOutput, unknown, BaseIssue >, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue>, item2: | TItem2 | PipeAction, InferOutput, InferIssue> ): SchemaWithPipe; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * * @returns A schema with a pipeline. */ export function pipe< const TSchema extends BaseSchema>, const TItem1 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem2 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem3 extends PipeItem< InferOutput, unknown, BaseIssue >, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue>, item2: | TItem2 | PipeAction, InferOutput, InferIssue>, item3: | TItem3 | PipeAction, InferOutput, InferIssue> ): SchemaWithPipe; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * * @returns A schema with a pipeline. */ export function pipe< const TSchema extends BaseSchema>, const TItem1 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem2 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem3 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem4 extends PipeItem< InferOutput, unknown, BaseIssue >, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue>, item2: | TItem2 | PipeAction, InferOutput, InferIssue>, item3: | TItem3 | PipeAction, InferOutput, InferIssue>, item4: | TItem4 | PipeAction, InferOutput, InferIssue> ): SchemaWithPipe; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * * @returns A schema with a pipeline. */ export function pipe< const TSchema extends BaseSchema>, const TItem1 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem2 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem3 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem4 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem5 extends PipeItem< InferOutput, unknown, BaseIssue >, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue>, item2: | TItem2 | PipeAction, InferOutput, InferIssue>, item3: | TItem3 | PipeAction, InferOutput, InferIssue>, item4: | TItem4 | PipeAction, InferOutput, InferIssue>, item5: | TItem5 | PipeAction, InferOutput, InferIssue> ): SchemaWithPipe; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * * @returns A schema with a pipeline. */ export function pipe< const TSchema extends BaseSchema>, const TItem1 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem2 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem3 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem4 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem5 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem6 extends PipeItem< InferOutput, unknown, BaseIssue >, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue>, item2: | TItem2 | PipeAction, InferOutput, InferIssue>, item3: | TItem3 | PipeAction, InferOutput, InferIssue>, item4: | TItem4 | PipeAction, InferOutput, InferIssue>, item5: | TItem5 | PipeAction, InferOutput, InferIssue>, item6: | TItem6 | PipeAction, InferOutput, InferIssue> ): SchemaWithPipe< readonly [TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * * @returns A schema with a pipeline. */ export function pipe< const TSchema extends BaseSchema>, const TItem1 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem2 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem3 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem4 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem5 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem6 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem7 extends PipeItem< InferOutput, unknown, BaseIssue >, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue>, item2: | TItem2 | PipeAction, InferOutput, InferIssue>, item3: | TItem3 | PipeAction, InferOutput, InferIssue>, item4: | TItem4 | PipeAction, InferOutput, InferIssue>, item5: | TItem5 | PipeAction, InferOutput, InferIssue>, item6: | TItem6 | PipeAction, InferOutput, InferIssue>, item7: | TItem7 | PipeAction, InferOutput, InferIssue> ): SchemaWithPipe< readonly [TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * * @returns A schema with a pipeline. */ export function pipe< const TSchema extends BaseSchema>, const TItem1 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem2 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem3 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem4 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem5 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem6 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem7 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem8 extends PipeItem< InferOutput, unknown, BaseIssue >, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue>, item2: | TItem2 | PipeAction, InferOutput, InferIssue>, item3: | TItem3 | PipeAction, InferOutput, InferIssue>, item4: | TItem4 | PipeAction, InferOutput, InferIssue>, item5: | TItem5 | PipeAction, InferOutput, InferIssue>, item6: | TItem6 | PipeAction, InferOutput, InferIssue>, item7: | TItem7 | PipeAction, InferOutput, InferIssue>, item8: | TItem8 | PipeAction, InferOutput, InferIssue> ): SchemaWithPipe< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * * @returns A schema with a pipeline. */ export function pipe< const TSchema extends BaseSchema>, const TItem1 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem2 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem3 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem4 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem5 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem6 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem7 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem8 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem9 extends PipeItem< InferOutput, unknown, BaseIssue >, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue>, item2: | TItem2 | PipeAction, InferOutput, InferIssue>, item3: | TItem3 | PipeAction, InferOutput, InferIssue>, item4: | TItem4 | PipeAction, InferOutput, InferIssue>, item5: | TItem5 | PipeAction, InferOutput, InferIssue>, item6: | TItem6 | PipeAction, InferOutput, InferIssue>, item7: | TItem7 | PipeAction, InferOutput, InferIssue>, item8: | TItem8 | PipeAction, InferOutput, InferIssue>, item9: | TItem9 | PipeAction, InferOutput, InferIssue> ): SchemaWithPipe< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * @param item10 The tenth pipe item. * * @returns A schema with a pipeline. */ export function pipe< const TSchema extends BaseSchema>, const TItem1 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem2 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem3 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem4 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem5 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem6 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem7 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem8 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem9 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem10 extends PipeItem< InferOutput, unknown, BaseIssue >, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue>, item2: | TItem2 | PipeAction, InferOutput, InferIssue>, item3: | TItem3 | PipeAction, InferOutput, InferIssue>, item4: | TItem4 | PipeAction, InferOutput, InferIssue>, item5: | TItem5 | PipeAction, InferOutput, InferIssue>, item6: | TItem6 | PipeAction, InferOutput, InferIssue>, item7: | TItem7 | PipeAction, InferOutput, InferIssue>, item8: | TItem8 | PipeAction, InferOutput, InferIssue>, item9: | TItem9 | PipeAction, InferOutput, InferIssue>, item10: | TItem10 | PipeAction, InferOutput, InferIssue> ): SchemaWithPipe< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * @param item10 The tenth pipe item. * @param item11 The eleventh pipe item. * * @returns A schema with a pipeline. */ export function pipe< const TSchema extends BaseSchema>, const TItem1 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem2 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem3 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem4 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem5 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem6 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem7 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem8 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem9 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem10 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem11 extends PipeItem< InferOutput, unknown, BaseIssue >, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue>, item2: | TItem2 | PipeAction, InferOutput, InferIssue>, item3: | TItem3 | PipeAction, InferOutput, InferIssue>, item4: | TItem4 | PipeAction, InferOutput, InferIssue>, item5: | TItem5 | PipeAction, InferOutput, InferIssue>, item6: | TItem6 | PipeAction, InferOutput, InferIssue>, item7: | TItem7 | PipeAction, InferOutput, InferIssue>, item8: | TItem8 | PipeAction, InferOutput, InferIssue>, item9: | TItem9 | PipeAction, InferOutput, InferIssue>, item10: | TItem10 | PipeAction< InferOutput, InferOutput, InferIssue >, item11: | TItem11 | PipeAction< InferOutput, InferOutput, InferIssue > ): SchemaWithPipe< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, TItem11, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * @param item10 The tenth pipe item. * @param item11 The eleventh pipe item. * @param item12 The twelfth pipe item. * * @returns A schema with a pipeline. */ export function pipe< const TSchema extends BaseSchema>, const TItem1 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem2 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem3 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem4 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem5 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem6 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem7 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem8 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem9 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem10 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem11 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem12 extends PipeItem< InferOutput, unknown, BaseIssue >, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue>, item2: | TItem2 | PipeAction, InferOutput, InferIssue>, item3: | TItem3 | PipeAction, InferOutput, InferIssue>, item4: | TItem4 | PipeAction, InferOutput, InferIssue>, item5: | TItem5 | PipeAction, InferOutput, InferIssue>, item6: | TItem6 | PipeAction, InferOutput, InferIssue>, item7: | TItem7 | PipeAction, InferOutput, InferIssue>, item8: | TItem8 | PipeAction, InferOutput, InferIssue>, item9: | TItem9 | PipeAction, InferOutput, InferIssue>, item10: | TItem10 | PipeAction< InferOutput, InferOutput, InferIssue >, item11: | TItem11 | PipeAction< InferOutput, InferOutput, InferIssue >, item12: | TItem12 | PipeAction< InferOutput, InferOutput, InferIssue > ): SchemaWithPipe< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, TItem11, TItem12, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * @param item10 The tenth pipe item. * @param item11 The eleventh pipe item. * @param item12 The twelfth pipe item. * @param item13 The thirteenth pipe item. * * @returns A schema with a pipeline. */ export function pipe< const TSchema extends BaseSchema>, const TItem1 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem2 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem3 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem4 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem5 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem6 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem7 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem8 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem9 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem10 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem11 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem12 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem13 extends PipeItem< InferOutput, unknown, BaseIssue >, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue>, item2: | TItem2 | PipeAction, InferOutput, InferIssue>, item3: | TItem3 | PipeAction, InferOutput, InferIssue>, item4: | TItem4 | PipeAction, InferOutput, InferIssue>, item5: | TItem5 | PipeAction, InferOutput, InferIssue>, item6: | TItem6 | PipeAction, InferOutput, InferIssue>, item7: | TItem7 | PipeAction, InferOutput, InferIssue>, item8: | TItem8 | PipeAction, InferOutput, InferIssue>, item9: | TItem9 | PipeAction, InferOutput, InferIssue>, item10: | TItem10 | PipeAction< InferOutput, InferOutput, InferIssue >, item11: | TItem11 | PipeAction< InferOutput, InferOutput, InferIssue >, item12: | TItem12 | PipeAction< InferOutput, InferOutput, InferIssue >, item13: | TItem13 | PipeAction< InferOutput, InferOutput, InferIssue > ): SchemaWithPipe< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, TItem11, TItem12, TItem13, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * @param item10 The tenth pipe item. * @param item11 The eleventh pipe item. * @param item12 The twelfth pipe item. * @param item13 The thirteenth pipe item. * @param item14 The fourteenth pipe item. * * @returns A schema with a pipeline. */ export function pipe< const TSchema extends BaseSchema>, const TItem1 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem2 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem3 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem4 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem5 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem6 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem7 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem8 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem9 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem10 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem11 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem12 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem13 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem14 extends PipeItem< InferOutput, unknown, BaseIssue >, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue>, item2: | TItem2 | PipeAction, InferOutput, InferIssue>, item3: | TItem3 | PipeAction, InferOutput, InferIssue>, item4: | TItem4 | PipeAction, InferOutput, InferIssue>, item5: | TItem5 | PipeAction, InferOutput, InferIssue>, item6: | TItem6 | PipeAction, InferOutput, InferIssue>, item7: | TItem7 | PipeAction, InferOutput, InferIssue>, item8: | TItem8 | PipeAction, InferOutput, InferIssue>, item9: | TItem9 | PipeAction, InferOutput, InferIssue>, item10: | TItem10 | PipeAction< InferOutput, InferOutput, InferIssue >, item11: | TItem11 | PipeAction< InferOutput, InferOutput, InferIssue >, item12: | TItem12 | PipeAction< InferOutput, InferOutput, InferIssue >, item13: | TItem13 | PipeAction< InferOutput, InferOutput, InferIssue >, item14: | TItem14 | PipeAction< InferOutput, InferOutput, InferIssue > ): SchemaWithPipe< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, TItem11, TItem12, TItem13, TItem14, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * @param item10 The tenth pipe item. * @param item11 The eleventh pipe item. * @param item12 The twelfth pipe item. * @param item13 The thirteenth pipe item. * @param item14 The fourteenth pipe item. * @param item15 The fifteenth pipe item. * * @returns A schema with a pipeline. */ export function pipe< const TSchema extends BaseSchema>, const TItem1 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem2 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem3 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem4 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem5 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem6 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem7 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem8 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem9 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem10 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem11 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem12 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem13 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem14 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem15 extends PipeItem< InferOutput, unknown, BaseIssue >, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue>, item2: | TItem2 | PipeAction, InferOutput, InferIssue>, item3: | TItem3 | PipeAction, InferOutput, InferIssue>, item4: | TItem4 | PipeAction, InferOutput, InferIssue>, item5: | TItem5 | PipeAction, InferOutput, InferIssue>, item6: | TItem6 | PipeAction, InferOutput, InferIssue>, item7: | TItem7 | PipeAction, InferOutput, InferIssue>, item8: | TItem8 | PipeAction, InferOutput, InferIssue>, item9: | TItem9 | PipeAction, InferOutput, InferIssue>, item10: | TItem10 | PipeAction< InferOutput, InferOutput, InferIssue >, item11: | TItem11 | PipeAction< InferOutput, InferOutput, InferIssue >, item12: | TItem12 | PipeAction< InferOutput, InferOutput, InferIssue >, item13: | TItem13 | PipeAction< InferOutput, InferOutput, InferIssue >, item14: | TItem14 | PipeAction< InferOutput, InferOutput, InferIssue >, item15: | TItem15 | PipeAction< InferOutput, InferOutput, InferIssue > ): SchemaWithPipe< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, TItem11, TItem12, TItem13, TItem14, TItem15, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * @param item10 The tenth pipe item. * @param item11 The eleventh pipe item. * @param item12 The twelfth pipe item. * @param item13 The thirteenth pipe item. * @param item14 The fourteenth pipe item. * @param item15 The fifteenth pipe item. * @param item16 The sixteenth pipe item. * * @returns A schema with a pipeline. */ export function pipe< const TSchema extends BaseSchema>, const TItem1 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem2 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem3 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem4 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem5 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem6 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem7 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem8 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem9 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem10 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem11 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem12 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem13 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem14 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem15 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem16 extends PipeItem< InferOutput, unknown, BaseIssue >, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue>, item2: | TItem2 | PipeAction, InferOutput, InferIssue>, item3: | TItem3 | PipeAction, InferOutput, InferIssue>, item4: | TItem4 | PipeAction, InferOutput, InferIssue>, item5: | TItem5 | PipeAction, InferOutput, InferIssue>, item6: | TItem6 | PipeAction, InferOutput, InferIssue>, item7: | TItem7 | PipeAction, InferOutput, InferIssue>, item8: | TItem8 | PipeAction, InferOutput, InferIssue>, item9: | TItem9 | PipeAction, InferOutput, InferIssue>, item10: | TItem10 | PipeAction< InferOutput, InferOutput, InferIssue >, item11: | TItem11 | PipeAction< InferOutput, InferOutput, InferIssue >, item12: | TItem12 | PipeAction< InferOutput, InferOutput, InferIssue >, item13: | TItem13 | PipeAction< InferOutput, InferOutput, InferIssue >, item14: | TItem14 | PipeAction< InferOutput, InferOutput, InferIssue >, item15: | TItem15 | PipeAction< InferOutput, InferOutput, InferIssue >, item16: | TItem16 | PipeAction< InferOutput, InferOutput, InferIssue > ): SchemaWithPipe< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, TItem11, TItem12, TItem13, TItem14, TItem15, TItem16, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * @param item10 The tenth pipe item. * @param item11 The eleventh pipe item. * @param item12 The twelfth pipe item. * @param item13 The thirteenth pipe item. * @param item14 The fourteenth pipe item. * @param item15 The fifteenth pipe item. * @param item16 The sixteenth pipe item. * * @returns A schema with a pipeline. */ export function pipe< const TSchema extends BaseSchema>, const TItem1 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem2 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem3 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem4 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem5 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem6 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem7 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem8 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem9 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem10 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem11 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem12 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem13 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem14 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem15 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem16 extends PipeItem< InferOutput, unknown, BaseIssue >, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue>, item2: | TItem2 | PipeAction, InferOutput, InferIssue>, item3: | TItem3 | PipeAction, InferOutput, InferIssue>, item4: | TItem4 | PipeAction, InferOutput, InferIssue>, item5: | TItem5 | PipeAction, InferOutput, InferIssue>, item6: | TItem6 | PipeAction, InferOutput, InferIssue>, item7: | TItem7 | PipeAction, InferOutput, InferIssue>, item8: | TItem8 | PipeAction, InferOutput, InferIssue>, item9: | TItem9 | PipeAction, InferOutput, InferIssue>, item10: | TItem10 | PipeAction< InferOutput, InferOutput, InferIssue >, item11: | TItem11 | PipeAction< InferOutput, InferOutput, InferIssue >, item12: | TItem12 | PipeAction< InferOutput, InferOutput, InferIssue >, item13: | TItem13 | PipeAction< InferOutput, InferOutput, InferIssue >, item14: | TItem14 | PipeAction< InferOutput, InferOutput, InferIssue >, item15: | TItem15 | PipeAction< InferOutput, InferOutput, InferIssue >, item16: | TItem16 | PipeAction< InferOutput, InferOutput, InferIssue > ): SchemaWithPipe< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, TItem11, TItem12, TItem13, TItem14, TItem15, TItem16, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * @param item10 The tenth pipe item. * @param item11 The eleventh pipe item. * @param item12 The twelfth pipe item. * @param item13 The thirteenth pipe item. * @param item14 The fourteenth pipe item. * @param item15 The fifteenth pipe item. * @param item16 The sixteenth pipe item. * @param item17 The seventeenth pipe item. * * @returns A schema with a pipeline. */ export function pipe< const TSchema extends BaseSchema>, const TItem1 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem2 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem3 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem4 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem5 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem6 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem7 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem8 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem9 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem10 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem11 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem12 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem13 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem14 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem15 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem16 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem17 extends PipeItem< InferOutput, unknown, BaseIssue >, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue>, item2: | TItem2 | PipeAction, InferOutput, InferIssue>, item3: | TItem3 | PipeAction, InferOutput, InferIssue>, item4: | TItem4 | PipeAction, InferOutput, InferIssue>, item5: | TItem5 | PipeAction, InferOutput, InferIssue>, item6: | TItem6 | PipeAction, InferOutput, InferIssue>, item7: | TItem7 | PipeAction, InferOutput, InferIssue>, item8: | TItem8 | PipeAction, InferOutput, InferIssue>, item9: | TItem9 | PipeAction, InferOutput, InferIssue>, item10: | TItem10 | PipeAction< InferOutput, InferOutput, InferIssue >, item11: | TItem11 | PipeAction< InferOutput, InferOutput, InferIssue >, item12: | TItem12 | PipeAction< InferOutput, InferOutput, InferIssue >, item13: | TItem13 | PipeAction< InferOutput, InferOutput, InferIssue >, item14: | TItem14 | PipeAction< InferOutput, InferOutput, InferIssue >, item15: | TItem15 | PipeAction< InferOutput, InferOutput, InferIssue >, item16: | TItem16 | PipeAction< InferOutput, InferOutput, InferIssue >, item17: | TItem17 | PipeAction< InferOutput, InferOutput, InferIssue > ): SchemaWithPipe< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, TItem11, TItem12, TItem13, TItem14, TItem15, TItem16, TItem17, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * @param item10 The tenth pipe item. * @param item11 The eleventh pipe item. * @param item12 The twelfth pipe item. * @param item13 The thirteenth pipe item. * @param item14 The fourteenth pipe item. * @param item15 The fifteenth pipe item. * @param item16 The sixteenth pipe item. * @param item17 The seventeenth pipe item. * @param item18 The eighteenth pipe item. * * @returns A schema with a pipeline. */ export function pipe< const TSchema extends BaseSchema>, const TItem1 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem2 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem3 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem4 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem5 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem6 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem7 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem8 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem9 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem10 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem11 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem12 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem13 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem14 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem15 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem16 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem17 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem18 extends PipeItem< InferOutput, unknown, BaseIssue >, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue>, item2: | TItem2 | PipeAction, InferOutput, InferIssue>, item3: | TItem3 | PipeAction, InferOutput, InferIssue>, item4: | TItem4 | PipeAction, InferOutput, InferIssue>, item5: | TItem5 | PipeAction, InferOutput, InferIssue>, item6: | TItem6 | PipeAction, InferOutput, InferIssue>, item7: | TItem7 | PipeAction, InferOutput, InferIssue>, item8: | TItem8 | PipeAction, InferOutput, InferIssue>, item9: | TItem9 | PipeAction, InferOutput, InferIssue>, item10: | TItem10 | PipeAction< InferOutput, InferOutput, InferIssue >, item11: | TItem11 | PipeAction< InferOutput, InferOutput, InferIssue >, item12: | TItem12 | PipeAction< InferOutput, InferOutput, InferIssue >, item13: | TItem13 | PipeAction< InferOutput, InferOutput, InferIssue >, item14: | TItem14 | PipeAction< InferOutput, InferOutput, InferIssue >, item15: | TItem15 | PipeAction< InferOutput, InferOutput, InferIssue >, item16: | TItem16 | PipeAction< InferOutput, InferOutput, InferIssue >, item17: | TItem17 | PipeAction< InferOutput, InferOutput, InferIssue >, item18: | TItem18 | PipeAction< InferOutput, InferOutput, InferIssue > ): SchemaWithPipe< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, TItem11, TItem12, TItem13, TItem14, TItem15, TItem16, TItem17, TItem18, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * @param item10 The tenth pipe item. * @param item11 The eleventh pipe item. * @param item12 The twelfth pipe item. * @param item13 The thirteenth pipe item. * @param item14 The fourteenth pipe item. * @param item15 The fifteenth pipe item. * @param item16 The sixteenth pipe item. * @param item17 The seventeenth pipe item. * @param item18 The eighteenth pipe item. * @param item19 The nineteenth pipe item. * * @returns A schema with a pipeline. */ export function pipe< const TSchema extends BaseSchema>, const TItem1 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem2 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem3 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem4 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem5 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem6 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem7 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem8 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem9 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem10 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem11 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem12 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem13 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem14 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem15 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem16 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem17 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem18 extends PipeItem< InferOutput, unknown, BaseIssue >, const TItem19 extends PipeItem< InferOutput, unknown, BaseIssue >, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue>, item2: | TItem2 | PipeAction, InferOutput, InferIssue>, item3: | TItem3 | PipeAction, InferOutput, InferIssue>, item4: | TItem4 | PipeAction, InferOutput, InferIssue>, item5: | TItem5 | PipeAction, InferOutput, InferIssue>, item6: | TItem6 | PipeAction, InferOutput, InferIssue>, item7: | TItem7 | PipeAction, InferOutput, InferIssue>, item8: | TItem8 | PipeAction, InferOutput, InferIssue>, item9: | TItem9 | PipeAction, InferOutput, InferIssue>, item10: | TItem10 | PipeAction< InferOutput, InferOutput, InferIssue >, item11: | TItem11 | PipeAction< InferOutput, InferOutput, InferIssue >, item12: | TItem12 | PipeAction< InferOutput, InferOutput, InferIssue >, item13: | TItem13 | PipeAction< InferOutput, InferOutput, InferIssue >, item14: | TItem14 | PipeAction< InferOutput, InferOutput, InferIssue >, item15: | TItem15 | PipeAction< InferOutput, InferOutput, InferIssue >, item16: | TItem16 | PipeAction< InferOutput, InferOutput, InferIssue >, item17: | TItem17 | PipeAction< InferOutput, InferOutput, InferIssue >, item18: | TItem18 | PipeAction< InferOutput, InferOutput, InferIssue >, item19: | TItem19 | PipeAction< InferOutput, InferOutput, InferIssue > ): SchemaWithPipe< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, TItem11, TItem12, TItem13, TItem14, TItem15, TItem16, TItem17, TItem18, TItem19, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param items The pipe items. * * @returns A schema with a pipeline. */ export function pipe< const TSchema extends BaseSchema>, const TItems extends readonly PipeItem< InferOutput, InferOutput, BaseIssue >[], >( schema: TSchema, ...items: TItems ): SchemaWithPipe; // @__NO_SIDE_EFFECTS__ export function pipe< const TSchema extends BaseSchema>, const TItems extends readonly PipeItem< unknown, unknown, BaseIssue >[], >( ...pipe: [TSchema, ...TItems] ): SchemaWithPipe { return { ...pipe[0], pipe, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // Execute pipeline items in sequence for (const item of pipe) { // Exclude metadata items from execution if (item.kind !== 'metadata') { // Mark dataset as untyped and break pipe if there are issues and pipe // item is schema or transformation if ( dataset.issues && (item.kind === 'schema' || item.kind === 'transformation') ) { dataset.typed = false; break; } // Continue pipe execution if there is no reason to abort early if ( !dataset.issues || (!config.abortEarly && !config.abortPipeEarly) ) { // @ts-expect-error dataset = item['~run'](dataset, config); } } } // Return output dataset // @ts-expect-error return dataset as OutputDataset>; }, }; } ================================================ FILE: library/src/methods/pipe/pipeAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { decimal, type DecimalAction, type DecimalIssue, description, type DescriptionAction, minLength, type MinLengthAction, type MinLengthIssue, minValue, type MinValueAction, type MinValueIssue, type TransformActionAsync, transformAsync, trim, type TrimAction, } from '../../actions/index.ts'; import { number, type NumberIssue, type NumberSchema, string, type StringIssue, type StringSchema, } from '../../schemas/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { pipeAsync, type SchemaWithPipeAsync } from './pipeAsync.ts'; describe('pipeAsync', () => { const schema = pipeAsync( string(), description('text'), trim(), minLength(1), decimal(), transformAsync(async (input) => parseInt(input)), number(), minValue(100) ); test('should return schema object', () => { expectTypeOf(schema).toEqualTypeOf< SchemaWithPipeAsync< readonly [ StringSchema, DescriptionAction, TrimAction, MinLengthAction, DecimalAction, TransformActionAsync, NumberSchema, MinValueAction, ] > >(); }); describe('should infer correct types', () => { type Schema = typeof schema; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< | StringIssue | MinLengthIssue | DecimalIssue | NumberIssue | MinValueIssue >(); }); }); }); ================================================ FILE: library/src/methods/pipe/pipeAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { decimal, type DecimalIssue, description, minLength, type MinLengthIssue, minValue, transform, trim, } from '../../actions/index.ts'; import { DECIMAL_REGEX } from '../../regex.ts'; import { string } from '../../schemas/index.ts'; import { pipeAsync } from './pipeAsync.ts'; describe('pipeAsync', () => { const schema = pipeAsync( string(), description('text'), trim(), minLength(1), decimal() ); test('should return schema object', () => { expect(schema).toStrictEqual({ kind: 'schema', type: 'string', reference: string, expects: 'string', message: undefined, pipe: [ { ...string(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, description('text'), { ...trim(), '~run': expect.any(Function), }, { ...minLength(1), '~run': expect.any(Function), }, { ...decimal(), '~run': expect.any(Function), }, ], async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } satisfies typeof schema); }); test('should return dataset without issues', async () => { expect(await schema['~run']({ value: ' 123 ' }, {})).toStrictEqual({ typed: true, value: '123', }); }); const baseInfo = { message: expect.any(String), path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const minLengthIssue: MinLengthIssue = { ...baseInfo, kind: 'validation', type: 'min_length', input: '', expected: '>=1', received: '0', requirement: 1, }; const decimalIssue: DecimalIssue = { ...baseInfo, kind: 'validation', type: 'decimal', input: '', expected: null, received: '""', requirement: DECIMAL_REGEX, }; test('should return dataset with issues', async () => { expect(await schema['~run']({ value: ' ' }, {})).toStrictEqual({ typed: true, value: '', issues: [minLengthIssue, decimalIssue], }); }); describe('should break pipe if necessary', () => { test('for abort early config', async () => { expect( await schema['~run']({ value: ' ' }, { abortEarly: true }) ).toStrictEqual({ typed: true, value: '', issues: [{ ...minLengthIssue, abortEarly: true }], }); }); test('for abort pipe early config', async () => { expect( await schema['~run']({ value: ' ' }, { abortPipeEarly: true }) ).toStrictEqual({ typed: true, value: '', issues: [{ ...minLengthIssue, abortPipeEarly: true }], }); }); test('if next action is schema', async () => { expect( await pipeAsync(schema, string(), minLength(10))['~run']( { value: ' ' }, {} ) ).toStrictEqual({ typed: false, value: '', issues: [minLengthIssue, decimalIssue], }); }); test('if next action is transformation', async () => { expect( await pipeAsync(schema, transform(parseInt), minValue(999))['~run']( { value: ' ' }, {} ) ).toStrictEqual({ typed: false, value: '', issues: [minLengthIssue, decimalIssue], }); }); }); }); ================================================ FILE: library/src/methods/pipe/pipeAsync.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, Config, FirstTupleItem, InferInput, InferIssue, InferOutput, LastTupleItem, OutputDataset, PipeAction, PipeActionAsync, PipeItem, PipeItemAsync, StandardProps, UnknownDataset, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; /** * Schema with pipe async type. */ export type SchemaWithPipeAsync< TPipe extends readonly [ ( | BaseSchema> | BaseSchemaAsync> ), ...( | PipeItem> // eslint-disable-line @typescript-eslint/no-explicit-any | PipeItemAsync> // eslint-disable-line @typescript-eslint/no-explicit-any )[], ], > = Omit< FirstTupleItem, 'async' | 'pipe' | '~standard' | '~run' | '~types' > & { /** * The pipe items. */ readonly pipe: TPipe; /** * Whether it's async. */ readonly async: true; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferInput>, InferOutput> >; /** * Parses unknown input values. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => Promise< OutputDataset>, InferIssue> >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferInput>; readonly output: InferOutput>; readonly issue: InferIssue; } | undefined; }; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * * @returns A schema with a pipeline. */ export function pipeAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TItem1 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue > ): SchemaWithPipeAsync; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * * @returns A schema with a pipeline. */ export function pipeAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TItem1 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem2 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item2: | TItem2 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue > ): SchemaWithPipeAsync; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * * @returns A schema with a pipeline. */ export function pipeAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TItem1 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem2 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem3 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item2: | TItem2 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item3: | TItem3 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue > ): SchemaWithPipeAsync; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * * @returns A schema with a pipeline. */ export function pipeAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TItem1 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem2 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem3 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem4 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item2: | TItem2 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item3: | TItem3 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item4: | TItem4 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue > ): SchemaWithPipeAsync; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * * @returns A schema with a pipeline. */ export function pipeAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TItem1 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem2 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem3 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem4 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem5 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item2: | TItem2 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item3: | TItem3 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item4: | TItem4 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item5: | TItem5 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue > ): SchemaWithPipeAsync< readonly [TSchema, TItem1, TItem2, TItem3, TItem4, TItem5] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * * @returns A schema with a pipeline. */ export function pipeAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TItem1 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem2 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem3 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem4 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem5 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem6 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item2: | TItem2 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item3: | TItem3 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item4: | TItem4 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item5: | TItem5 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item6: | TItem6 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue > ): SchemaWithPipeAsync< readonly [TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * * @returns A schema with a pipeline. */ export function pipeAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TItem1 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem2 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem3 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem4 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem5 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem6 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem7 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item2: | TItem2 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item3: | TItem3 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item4: | TItem4 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item5: | TItem5 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item6: | TItem6 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item7: | TItem7 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue > ): SchemaWithPipeAsync< readonly [TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * * @returns A schema with a pipeline. */ export function pipeAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TItem1 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem2 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem3 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem4 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem5 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem6 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem7 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem8 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item2: | TItem2 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item3: | TItem3 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item4: | TItem4 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item5: | TItem5 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item6: | TItem6 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item7: | TItem7 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item8: | TItem8 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue > ): SchemaWithPipeAsync< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * * @returns A schema with a pipeline. */ export function pipeAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TItem1 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem2 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem3 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem4 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem5 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem6 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem7 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem8 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem9 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item2: | TItem2 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item3: | TItem3 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item4: | TItem4 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item5: | TItem5 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item6: | TItem6 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item7: | TItem7 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item8: | TItem8 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item9: | TItem9 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue > ): SchemaWithPipeAsync< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * @param item10 The tenth pipe item. * * @returns A schema with a pipeline. */ export function pipeAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TItem1 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem2 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem3 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem4 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem5 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem6 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem7 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem8 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem9 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem10 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item2: | TItem2 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item3: | TItem3 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item4: | TItem4 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item5: | TItem5 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item6: | TItem6 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item7: | TItem7 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item8: | TItem8 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item9: | TItem9 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item10: | TItem10 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue > ): SchemaWithPipeAsync< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * @param item10 The tenth pipe item. * @param item11 The eleventh pipe item. * * @returns A schema with a pipeline. */ export function pipeAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TItem1 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem2 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem3 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem4 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem5 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem6 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem7 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem8 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem9 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem10 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem11 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item2: | TItem2 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item3: | TItem3 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item4: | TItem4 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item5: | TItem5 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item6: | TItem6 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item7: | TItem7 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item8: | TItem8 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item9: | TItem9 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item10: | TItem10 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item11: | TItem11 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue > ): SchemaWithPipeAsync< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, TItem11, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * @param item10 The tenth pipe item. * @param item11 The eleventh pipe item. * @param item12 The twelfth pipe item. * * @returns A schema with a pipeline. */ export function pipeAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TItem1 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem2 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem3 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem4 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem5 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem6 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem7 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem8 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem9 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem10 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem11 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem12 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item2: | TItem2 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item3: | TItem3 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item4: | TItem4 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item5: | TItem5 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item6: | TItem6 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item7: | TItem7 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item8: | TItem8 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item9: | TItem9 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item10: | TItem10 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item11: | TItem11 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item12: | TItem12 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue > ): SchemaWithPipeAsync< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, TItem11, TItem12, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * @param item10 The tenth pipe item. * @param item11 The eleventh pipe item. * @param item12 The twelfth pipe item. * @param item13 The thirteenth pipe item. * * @returns A schema with a pipeline. */ export function pipeAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TItem1 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem2 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem3 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem4 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem5 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem6 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem7 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem8 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem9 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem10 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem11 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem12 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem13 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item2: | TItem2 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item3: | TItem3 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item4: | TItem4 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item5: | TItem5 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item6: | TItem6 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item7: | TItem7 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item8: | TItem8 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item9: | TItem9 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item10: | TItem10 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item11: | TItem11 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item12: | TItem12 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item13: | TItem13 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue > ): SchemaWithPipeAsync< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, TItem11, TItem12, TItem13, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * @param item10 The tenth pipe item. * @param item11 The eleventh pipe item. * @param item12 The twelfth pipe item. * @param item13 The thirteenth pipe item. * @param item14 The fourteenth pipe item. * * @returns A schema with a pipeline. */ export function pipeAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TItem1 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem2 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem3 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem4 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem5 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem6 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem7 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem8 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem9 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem10 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem11 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem12 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem13 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem14 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item2: | TItem2 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item3: | TItem3 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item4: | TItem4 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item5: | TItem5 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item6: | TItem6 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item7: | TItem7 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item8: | TItem8 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item9: | TItem9 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item10: | TItem10 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item11: | TItem11 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item12: | TItem12 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item13: | TItem13 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item14: | TItem14 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue > ): SchemaWithPipeAsync< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, TItem11, TItem12, TItem13, TItem14, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * @param item10 The tenth pipe item. * @param item11 The eleventh pipe item. * @param item12 The twelfth pipe item. * @param item13 The thirteenth pipe item. * @param item14 The fourteenth pipe item. * @param item15 The fifteenth pipe item. * * @returns A schema with a pipeline. */ export function pipeAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TItem1 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem2 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem3 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem4 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem5 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem6 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem7 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem8 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem9 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem10 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem11 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem12 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem13 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem14 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem15 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item2: | TItem2 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item3: | TItem3 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item4: | TItem4 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item5: | TItem5 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item6: | TItem6 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item7: | TItem7 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item8: | TItem8 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item9: | TItem9 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item10: | TItem10 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item11: | TItem11 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item12: | TItem12 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item13: | TItem13 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item14: | TItem14 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item15: | TItem15 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue > ): SchemaWithPipeAsync< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, TItem11, TItem12, TItem13, TItem14, TItem15, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * @param item10 The tenth pipe item. * @param item11 The eleventh pipe item. * @param item12 The twelfth pipe item. * @param item13 The thirteenth pipe item. * @param item14 The fourteenth pipe item. * @param item15 The fifteenth pipe item. * @param item16 The sixteenth pipe item. * * @returns A schema with a pipeline. */ export function pipeAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TItem1 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem2 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem3 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem4 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem5 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem6 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem7 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem8 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem9 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem10 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem11 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem12 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem13 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem14 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem15 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem16 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item2: | TItem2 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item3: | TItem3 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item4: | TItem4 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item5: | TItem5 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item6: | TItem6 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item7: | TItem7 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item8: | TItem8 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item9: | TItem9 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item10: | TItem10 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item11: | TItem11 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item12: | TItem12 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item13: | TItem13 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item14: | TItem14 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item15: | TItem15 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item16: | TItem16 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue > ): SchemaWithPipeAsync< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, TItem11, TItem12, TItem13, TItem14, TItem15, TItem16, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * @param item10 The tenth pipe item. * @param item11 The eleventh pipe item. * @param item12 The twelfth pipe item. * @param item13 The thirteenth pipe item. * @param item14 The fourteenth pipe item. * @param item15 The fifteenth pipe item. * @param item16 The sixteenth pipe item. * @param item17 The seventeenth pipe item. * * @returns A schema with a pipeline. */ export function pipeAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TItem1 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem2 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem3 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem4 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem5 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem6 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem7 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem8 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem9 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem10 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem11 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem12 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem13 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem14 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem15 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem16 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem17 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item2: | TItem2 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item3: | TItem3 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item4: | TItem4 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item5: | TItem5 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item6: | TItem6 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item7: | TItem7 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item8: | TItem8 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item9: | TItem9 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item10: | TItem10 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item11: | TItem11 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item12: | TItem12 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item13: | TItem13 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item14: | TItem14 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item15: | TItem15 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item16: | TItem16 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item17: | TItem17 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue > ): SchemaWithPipeAsync< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, TItem11, TItem12, TItem13, TItem14, TItem15, TItem16, TItem17, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * @param item10 The tenth pipe item. * @param item11 The eleventh pipe item. * @param item12 The twelfth pipe item. * @param item13 The thirteenth pipe item. * @param item14 The fourteenth pipe item. * @param item15 The fifteenth pipe item. * @param item16 The sixteenth pipe item. * @param item17 The seventeenth pipe item. * @param item18 The eighteenth pipe item. * * @returns A schema with a pipeline. */ export function pipeAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TItem1 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem2 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem3 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem4 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem5 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem6 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem7 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem8 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem9 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem10 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem11 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem12 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem13 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem14 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem15 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem16 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem17 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem18 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item2: | TItem2 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item3: | TItem3 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item4: | TItem4 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item5: | TItem5 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item6: | TItem6 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item7: | TItem7 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item8: | TItem8 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item9: | TItem9 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item10: | TItem10 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item11: | TItem11 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item12: | TItem12 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item13: | TItem13 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item14: | TItem14 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item15: | TItem15 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item16: | TItem16 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item17: | TItem17 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item18: | TItem18 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue > ): SchemaWithPipeAsync< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, TItem11, TItem12, TItem13, TItem14, TItem15, TItem16, TItem17, TItem18, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param item1 The first pipe item. * @param item2 The second pipe item. * @param item3 The third pipe item. * @param item4 The fourth pipe item. * @param item5 The fifth pipe item. * @param item6 The sixth pipe item. * @param item7 The seventh pipe item. * @param item8 The eighth pipe item. * @param item9 The ninth pipe item. * @param item10 The tenth pipe item. * @param item11 The eleventh pipe item. * @param item12 The twelfth pipe item. * @param item13 The thirteenth pipe item. * @param item14 The fourteenth pipe item. * @param item15 The fifteenth pipe item. * @param item16 The sixteenth pipe item. * @param item17 The seventeenth pipe item. * @param item18 The eighteenth pipe item. * @param item19 The nineteenth pipe item. * * @returns A schema with a pipeline. */ export function pipeAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TItem1 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem2 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem3 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem4 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem5 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem6 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem7 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem8 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem9 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem10 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem11 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem12 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem13 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem14 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem15 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem16 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem17 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem18 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, const TItem19 extends | PipeItem, unknown, BaseIssue> | PipeItemAsync, unknown, BaseIssue>, >( schema: TSchema, item1: | TItem1 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item2: | TItem2 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item3: | TItem3 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item4: | TItem4 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item5: | TItem5 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item6: | TItem6 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item7: | TItem7 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item8: | TItem8 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item9: | TItem9 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item10: | TItem10 | PipeAction, InferOutput, InferIssue> | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item11: | TItem11 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item12: | TItem12 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item13: | TItem13 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item14: | TItem14 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item15: | TItem15 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item16: | TItem16 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item17: | TItem17 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item18: | TItem18 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue >, item19: | TItem19 | PipeAction< InferOutput, InferOutput, InferIssue > | PipeActionAsync< InferOutput, InferOutput, InferIssue > ): SchemaWithPipeAsync< readonly [ TSchema, TItem1, TItem2, TItem3, TItem4, TItem5, TItem6, TItem7, TItem8, TItem9, TItem10, TItem11, TItem12, TItem13, TItem14, TItem15, TItem16, TItem17, TItem18, TItem19, ] >; /** * Adds a pipeline to a schema, that can validate and transform its input. * * @param schema The root schema. * @param items The pipe items. * * @returns A schema with a pipeline. */ export function pipeAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TItems extends readonly ( | PipeItem, InferOutput, BaseIssue> | PipeItemAsync< InferOutput, InferOutput, BaseIssue > )[], >( schema: TSchema, ...items: TItems ): SchemaWithPipeAsync; // @__NO_SIDE_EFFECTS__ export function pipeAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TItems extends readonly ( | PipeItem> | PipeItemAsync> )[], >( ...pipe: [TSchema, ...TItems] ): SchemaWithPipeAsync { return { ...pipe[0], pipe, async: true, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // Execute pipeline items in sequence for (const item of pipe) { // Exclude metadata items from execution if (item.kind !== 'metadata') { // Mark dataset as untyped and break pipe if there are issues and pipe // item is schema or transformation if ( dataset.issues && (item.kind === 'schema' || item.kind === 'transformation') ) { dataset.typed = false; break; } // Continue pipe execution if there is no reason to abort early if ( !dataset.issues || (!config.abortEarly && !config.abortPipeEarly) ) { // @ts-expect-error dataset = await item['~run'](dataset, config); } } } // Return output dataset // @ts-expect-error return dataset as OutputDataset>; }, }; } ================================================ FILE: library/src/methods/required/index.ts ================================================ export * from './required.ts'; export * from './requiredAsync.ts'; ================================================ FILE: library/src/methods/required/required.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { boolean, type BooleanIssue, type NonOptionalIssue, nullish, number, type NumberIssue, object, type ObjectIssue, objectWithRest, type ObjectWithRestIssue, optional, string, type StringIssue, } from '../../schemas/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { required, type SchemaWithRequired } from './required.ts'; describe('required', () => { const entries = { key1: optional(string()), key2: optional(number()), key3: optional(string()), key4: nullish(number(), () => 123), }; describe('object', () => { const wrapped = object(entries); type Wrapped = typeof wrapped; type Schema1 = SchemaWithRequired; type Schema2 = SchemaWithRequired; describe('should return schema object', () => { test('with undefined keys', () => { expectTypeOf(required(wrapped)).toEqualTypeOf(); expectTypeOf(required(wrapped, undefined)).toEqualTypeOf(); expectTypeOf(required(wrapped, 'message')).toEqualTypeOf< SchemaWithRequired >(); expectTypeOf(required(wrapped, () => 'message')).toEqualTypeOf< SchemaWithRequired string> >(); }); test('with specific keys', () => { expectTypeOf( required(wrapped, ['key1', 'key3']) ).toEqualTypeOf(); expectTypeOf( required(wrapped, ['key1', 'key3'], undefined) ).toEqualTypeOf(); expectTypeOf( required(wrapped, ['key1', 'key3'], 'message') ).toEqualTypeOf< SchemaWithRequired >(); expectTypeOf( required(wrapped, ['key1', 'key3'], () => 'message') ).toEqualTypeOf< SchemaWithRequired string> >(); }); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf<{ key1: string; key2: number; key3: string; key4: number | null; }>(); expectTypeOf>().toEqualTypeOf<{ key1: string; key2?: number; key3: string; key4?: number | null; }>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf<{ key1: string; key2: number; key3: string; key4: number; }>(); expectTypeOf>().toEqualTypeOf<{ key1: string; key2?: number; key3: string; key4: number; }>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< NonOptionalIssue | ObjectIssue | StringIssue | NumberIssue >(); expectTypeOf>().toEqualTypeOf< NonOptionalIssue | ObjectIssue | StringIssue | NumberIssue >(); }); }); }); describe('objectWithRest', () => { const wrapped = objectWithRest(entries, boolean()); type Wrapped = typeof wrapped; type Schema1 = SchemaWithRequired; type Schema2 = SchemaWithRequired; describe('should return schema object', () => { test('with undefined keys', () => { expectTypeOf(required(wrapped)).toEqualTypeOf(); expectTypeOf(required(wrapped, undefined)).toEqualTypeOf(); expectTypeOf(required(wrapped, 'message')).toEqualTypeOf< SchemaWithRequired >(); expectTypeOf(required(wrapped, () => 'message')).toEqualTypeOf< SchemaWithRequired string> >(); }); test('with specific keys', () => { expectTypeOf( required(wrapped, ['key2', 'key3']) ).toEqualTypeOf(); expectTypeOf( required(wrapped, ['key2', 'key3'], undefined) ).toEqualTypeOf(); expectTypeOf( required(wrapped, ['key2', 'key3'], 'message') ).toEqualTypeOf< SchemaWithRequired >(); expectTypeOf( required(wrapped, ['key2', 'key3'], () => 'message') ).toEqualTypeOf< SchemaWithRequired string> >(); }); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf< { key1: string; key2: number; key3: string; key4: number | null; } & { [key: string]: boolean } >(); expectTypeOf>().toEqualTypeOf< { key1?: string; key2: number; key3: string; key4?: number | null; } & { [key: string]: boolean } >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< { key1: string; key2: number; key3: string; key4: number; } & { [key: string]: boolean } >(); expectTypeOf>().toEqualTypeOf< { key1?: string; key2: number; key3: string; key4: number; } & { [key: string]: boolean } >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< | NonOptionalIssue | ObjectWithRestIssue | NumberIssue | StringIssue | BooleanIssue >(); expectTypeOf>().toEqualTypeOf< | NonOptionalIssue | ObjectWithRestIssue | NumberIssue | StringIssue | BooleanIssue >(); }); }); }); }); ================================================ FILE: library/src/methods/required/required.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { boolean, nonOptional, nullish, number, object, objectWithRest, optional, string, } from '../../schemas/index.ts'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssue } from '../../vitest/index.ts'; import { required } from './required.ts'; describe('required', () => { const entries = { key1: optional(string()), key2: optional(number()), key3: optional(string()), key4: nullish(number(), () => 123), }; const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, } as const; describe('object', () => { const wrapped = object(entries); const schema1 = required(wrapped); const schema2 = required(wrapped, ['key1', 'key3']); describe('should return schema object', () => { const baseObjectSchema = { kind: 'schema', type: 'object', reference: object, expects: 'Object', async: false, message: undefined, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } as const; test('with undefined keys and undefined message', () => { const expected: typeof schema1 = { ...baseObjectSchema, entries: { key1: { ...nonOptional(entries.key1), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: { ...nonOptional(entries.key2), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...nonOptional(entries.key3), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: { ...nonOptional(entries.key4), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, }, }; expect(schema1).toStrictEqual(expected); expect(schema1, undefined).toStrictEqual(expected); }); test('with undefined keys and string message', () => { const message = 'message'; const schema = required(wrapped, message); expect(schema).toStrictEqual({ ...baseObjectSchema, entries: { key1: { ...nonOptional(entries.key1, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: { ...nonOptional(entries.key2, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...nonOptional(entries.key3, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: { ...nonOptional(entries.key4, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, }, } satisfies typeof schema); }); test('with undefined keys and function message', () => { const message = () => 'message'; const schema = required(wrapped, message); expect(schema).toStrictEqual({ ...baseObjectSchema, entries: { key1: { ...nonOptional(entries.key1, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: { ...nonOptional(entries.key2, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...nonOptional(entries.key3, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: { ...nonOptional(entries.key4, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, }, } satisfies typeof schema); }); test('with specific keys and undefined message', () => { const expected: typeof schema2 = { ...baseObjectSchema, entries: { key1: { ...nonOptional(entries.key1), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: entries.key2, key3: { ...nonOptional(entries.key3), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: entries.key4, }, }; expect(schema2).toStrictEqual(expected); expect(schema2, undefined).toStrictEqual(expected); }); test('with specific keys and string message', () => { const message = 'message'; const schema = required(wrapped, ['key1', 'key3'], message); expect(schema).toStrictEqual({ ...baseObjectSchema, entries: { key1: { ...nonOptional(entries.key1, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: entries.key2, key3: { ...nonOptional(entries.key3, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: entries.key4, }, } satisfies typeof schema); }); test('with specific keys and function message', () => { const message = () => 'message'; const schema = required(wrapped, ['key1', 'key3'], message); expect(schema).toStrictEqual({ ...baseObjectSchema, entries: { key1: { ...nonOptional(entries.key1, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: entries.key2, key3: { ...nonOptional(entries.key3, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: entries.key4, }, } satisfies typeof schema); }); }); describe('should return dataset without nested issues', () => { test('if required keys are present', () => { const input1 = { key1: 'foo', key2: 123, key3: 'bar', key4: 123 }; expectNoSchemaIssue(schema1, [input1]); expectNoSchemaIssue(schema2, [input1]); const input2 = { key1: 'foo', key3: 'bar' }; expect(schema2['~run']({ value: input2 }, {})).toStrictEqual({ typed: true, value: { ...input2, key4: 123 }, }); }); }); describe('should return dataset with nested issues', () => { test('if required keys are missing', () => { expect(schema1['~run']({ value: {} }, {})).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key2', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key3"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key3', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key4"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key4', value: undefined, }, ], }, ], } satisfies FailureDataset>); const input = { key2: 123, key4: null }; expect(schema2['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: { ...input, key4: 123 }, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key3"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key3', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('if required keys are undefined', () => { const input1 = { key1: undefined, key2: undefined, key3: undefined, key4: undefined, }; expect(schema1['~run']({ value: input1 }, {})).toStrictEqual({ typed: false, value: input1, issues: [ { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input1, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input1, key: 'key2', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input1, key: 'key3', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input1, key: 'key4', value: undefined, }, ], }, ], } satisfies FailureDataset>); const input2 = { key1: undefined, key2: 123, key3: undefined, key4: null, }; expect(schema2['~run']({ value: input2 }, {})).toStrictEqual({ typed: false, value: { ...input2, key4: 123 }, issues: [ { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input2, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input2, key: 'key3', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); }); }); describe('objectWithRest', () => { const rest = boolean(); const wrapped = objectWithRest(entries, rest); const schema1 = required(wrapped); const schema2 = required(wrapped, ['key2', 'key3']); describe('should return schema object', () => { const baseObjectWithRestSchema = { kind: 'schema', type: 'object_with_rest', reference: objectWithRest, expects: 'Object', rest, message: undefined, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } as const; test('with undefined keys and undefined message', () => { const expected: typeof schema1 = { ...baseObjectWithRestSchema, entries: { key1: { ...nonOptional(entries.key1), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: { ...nonOptional(entries.key2), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...nonOptional(entries.key3), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: { ...nonOptional(entries.key4), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, }, }; expect(schema1).toStrictEqual(expected); expect(schema1, undefined).toStrictEqual(expected); }); test('with undefined keys and string message', () => { const message = 'message'; const schema = required(wrapped, message); expect(schema).toStrictEqual({ ...baseObjectWithRestSchema, entries: { key1: { ...nonOptional(entries.key1, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: { ...nonOptional(entries.key2, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...nonOptional(entries.key3, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: { ...nonOptional(entries.key4, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, }, } satisfies typeof schema); }); test('with undefined keys and function message', () => { const message = () => 'message'; const schema = required(wrapped, message); expect(schema).toStrictEqual({ ...baseObjectWithRestSchema, entries: { key1: { ...nonOptional(entries.key1, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: { ...nonOptional(entries.key2, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...nonOptional(entries.key3, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: { ...nonOptional(entries.key4, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, }, } satisfies typeof schema); }); test('with specific keys and undefined message', () => { const expected: typeof schema2 = { ...baseObjectWithRestSchema, entries: { key1: entries.key1, key2: { ...nonOptional(entries.key2), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...nonOptional(entries.key3), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: entries.key4, }, }; expect(schema2).toStrictEqual(expected); expect(schema2, undefined).toStrictEqual(expected); }); test('with specific keys and string message', () => { const message = 'message'; const schema = required(wrapped, ['key2', 'key3'], message); expect(schema).toStrictEqual({ ...baseObjectWithRestSchema, entries: { key1: entries.key1, key2: { ...nonOptional(entries.key2, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...nonOptional(entries.key3, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: entries.key4, }, } satisfies typeof schema); }); test('with specific keys and function message', () => { const message = () => 'message'; const schema = required(wrapped, ['key2', 'key3'], message); expect(schema).toStrictEqual({ ...baseObjectWithRestSchema, entries: { key1: entries.key1, key2: { ...nonOptional(entries.key2, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...nonOptional(entries.key3, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: entries.key4, }, } satisfies typeof schema); }); }); describe('should return dataset without nested issues', () => { test('if required keys are present', () => { const input1 = { key1: 'foo', key2: 123, key3: 'bar', key4: 123, other: true, }; // @ts-expect-error expectNoSchemaIssue(schema1, [input1]); // @ts-expect-error expectNoSchemaIssue(schema2, [input1]); const input2 = { key2: 123, key3: 'bar', other: true }; expect(schema2['~run']({ value: input2 }, {})).toStrictEqual({ typed: true, value: { ...input2, key4: 123 }, }); }); }); describe('should return dataset with nested issues', () => { test('if required keys are missing', () => { expect(schema1['~run']({ value: {} }, {})).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key2', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key3"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key3', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key4"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key4', value: undefined, }, ], }, ], } satisfies FailureDataset>); const input = { key1: 'foo', key4: null, other: true }; expect(schema2['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: { ...input, key4: 123 }, issues: [ { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key2', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key3"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key3', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('if required keys are undefined', () => { const input1 = { key1: undefined, key2: undefined, key3: undefined, key4: undefined, }; expect(schema1['~run']({ value: input1 }, {})).toStrictEqual({ typed: false, value: input1, issues: [ { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input1, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input1, key: 'key2', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input1, key: 'key3', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input1, key: 'key4', value: undefined, }, ], }, ], } satisfies FailureDataset>); const input2 = { key1: 'foo', key2: undefined, key3: undefined, key4: null, other: true, }; expect(schema2['~run']({ value: input2 }, {})).toStrictEqual({ typed: false, value: { ...input2, key4: 123 }, issues: [ { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input2, key: 'key2', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input2, key: 'key3', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); }); }); }); ================================================ FILE: library/src/methods/required/required.ts ================================================ import { type LooseObjectIssue, type LooseObjectSchema, nonOptional, type NonOptionalIssue, type NonOptionalSchema, type ObjectIssue, type ObjectSchema, type ObjectWithRestIssue, type ObjectWithRestSchema, type StrictObjectIssue, type StrictObjectSchema, } from '../../schemas/index.ts'; import type { BaseIssue, BaseSchema, Config, ErrorMessage, InferInput, InferIssue, InferObjectInput, InferObjectOutput, InferOutput, ObjectEntries, ObjectKeys, OutputDataset, SchemaWithoutPipe, StandardProps, UnknownDataset, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; /** * Schema type. */ type Schema = SchemaWithoutPipe< | LooseObjectSchema | undefined> | ObjectSchema | undefined> | ObjectWithRestSchema< ObjectEntries, BaseSchema>, ErrorMessage | undefined > | StrictObjectSchema< ObjectEntries, ErrorMessage | undefined > >; /** * Required entries type. */ type RequiredEntries< TEntries extends ObjectEntries, TKeys extends readonly (keyof TEntries)[] | undefined, TMessage extends ErrorMessage | undefined, > = { [TKey in keyof TEntries]: TKeys extends readonly (keyof TEntries)[] ? TKey extends TKeys[number] ? NonOptionalSchema : TEntries[TKey] : NonOptionalSchema; }; /** * Schema with required type. */ export type SchemaWithRequired< TSchema extends Schema, TKeys extends ObjectKeys | undefined, TMessage extends ErrorMessage | undefined, > = TSchema extends | ObjectSchema | undefined> | StrictObjectSchema< infer TEntries, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: RequiredEntries; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput>, InferObjectOutput> >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => OutputDataset< InferObjectOutput>, NonOptionalIssue | InferIssue >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput< RequiredEntries >; readonly output: InferObjectOutput< RequiredEntries >; readonly issue: NonOptionalIssue | InferIssue; } | undefined; } : TSchema extends LooseObjectSchema< infer TEntries, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: RequiredEntries; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput> & { [key: string]: unknown; }, InferObjectOutput> & { [key: string]: unknown; } >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => OutputDataset< InferObjectOutput> & { [key: string]: unknown; }, NonOptionalIssue | InferIssue >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput< RequiredEntries > & { [key: string]: unknown; }; readonly output: InferObjectOutput< RequiredEntries > & { [key: string]: unknown; }; readonly issue: NonOptionalIssue | InferIssue; } | undefined; } : TSchema extends ObjectWithRestSchema< infer TEntries, infer TRest, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: RequiredEntries; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput> & { [key: string]: InferInput; }, InferObjectOutput> & { [key: string]: InferOutput; } >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => OutputDataset< InferObjectOutput> & { [key: string]: InferOutput; }, NonOptionalIssue | InferIssue >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput< RequiredEntries > & { [key: string]: InferInput; }; readonly output: InferObjectOutput< RequiredEntries > & { [key: string]: InferOutput }; readonly issue: NonOptionalIssue | InferIssue; } | undefined; } : never; /** * Creates a modified copy of an object schema that marks all entries as required. * * @param schema The schema to modify. * * @returns An object schema. */ // @ts-expect-error FIXME: TypeScript incorrectly claims that the overload // signature is not compatible with the implementation signature export function required( schema: TSchema ): SchemaWithRequired; /** * Creates a modified copy of an object schema that marks all entries as required. * * @param schema The schema to modify. * @param message The error message. * * @returns An object schema. */ export function required< const TSchema extends Schema, const TMessage extends ErrorMessage | undefined, >( schema: TSchema, message: TMessage ): SchemaWithRequired; /** * Creates a modified copy of an object schema that marks the selected entries * as required. * * @param schema The schema to modify. * @param keys The selected entries. * * @returns An object schema. */ export function required< const TSchema extends Schema, const TKeys extends ObjectKeys, >(schema: TSchema, keys: TKeys): SchemaWithRequired; /** * Creates a modified copy of an object schema that marks the selected entries * as required. * * @param schema The schema to modify. * @param keys The selected entries. * @param message The error message. * * @returns An object schema. */ export function required< const TSchema extends Schema, const TKeys extends ObjectKeys, const TMessage extends ErrorMessage | undefined, >( schema: TSchema, keys: TKeys, message: TMessage ): SchemaWithRequired; // @__NO_SIDE_EFFECTS__ export function required( schema: Schema, arg2?: ErrorMessage | ObjectKeys, arg3?: ErrorMessage ): SchemaWithRequired< Schema, ObjectKeys | undefined, ErrorMessage | undefined > { // Get keys and message from arguments const keys = Array.isArray(arg2) ? arg2 : undefined; const message = (Array.isArray(arg2) ? arg3 : arg2) as | ErrorMessage | undefined; // Create modified object entries const entries: RequiredEntries< ObjectEntries, ObjectKeys, ErrorMessage | undefined > = {}; for (const key in schema.entries) { // @ts-expect-error entries[key] = !keys || keys.includes(key) ? nonOptional(schema.entries[key], message) : schema.entries[key]; } // Return modified copy of schema return { ...schema, entries, get '~standard'() { return _getStandardProps(this); }, }; } ================================================ FILE: library/src/methods/required/requiredAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { boolean, type BooleanIssue, type NonOptionalIssue, nullishAsync, number, type NumberIssue, objectAsync, type ObjectIssue, objectWithRestAsync, type ObjectWithRestIssue, optional, optionalAsync, string, type StringIssue, } from '../../schemas/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { requiredAsync, type SchemaWithRequiredAsync, } from './requiredAsync.ts'; describe('requiredAsync', () => { const entries = { key1: optional(string()), key2: optional(number()), key3: optionalAsync(string()), key4: nullishAsync(number(), async () => 123), }; describe('objectAsync', () => { const wrapped = objectAsync(entries); type Wrapped = typeof wrapped; type Schema1 = SchemaWithRequiredAsync; type Schema2 = SchemaWithRequiredAsync< Wrapped, ['key1', 'key3'], undefined >; describe('should return schema object', () => { test('with undefined keys', () => { expectTypeOf(requiredAsync(wrapped)).toEqualTypeOf(); expectTypeOf( requiredAsync(wrapped, undefined) ).toEqualTypeOf(); expectTypeOf(requiredAsync(wrapped, 'message')).toEqualTypeOf< SchemaWithRequiredAsync >(); expectTypeOf(requiredAsync(wrapped, () => 'message')).toEqualTypeOf< SchemaWithRequiredAsync string> >(); }); test('with specific keys', () => { expectTypeOf( requiredAsync(wrapped, ['key1', 'key3']) ).toEqualTypeOf(); expectTypeOf( requiredAsync(wrapped, ['key1', 'key3'], undefined) ).toEqualTypeOf(); expectTypeOf( requiredAsync(wrapped, ['key1', 'key3'], 'message') ).toEqualTypeOf< SchemaWithRequiredAsync >(); expectTypeOf( requiredAsync(wrapped, ['key1', 'key3'], () => 'message') ).toEqualTypeOf< SchemaWithRequiredAsync string> >(); }); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf<{ key1: string; key2: number; key3: string; key4: number | null; }>(); expectTypeOf>().toEqualTypeOf<{ key1: string; key2?: number; key3: string; key4?: number | null; }>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf<{ key1: string; key2: number; key3: string; key4: number; }>(); expectTypeOf>().toEqualTypeOf<{ key1: string; key2?: number; key3: string; key4: number; }>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< NonOptionalIssue | ObjectIssue | StringIssue | NumberIssue >(); expectTypeOf>().toEqualTypeOf< NonOptionalIssue | ObjectIssue | StringIssue | NumberIssue >(); }); }); }); describe('objectWithRestAsync', () => { const wrapped = objectWithRestAsync(entries, boolean()); type Wrapped = typeof wrapped; type Schema1 = SchemaWithRequiredAsync; type Schema2 = SchemaWithRequiredAsync< Wrapped, ['key2', 'key3'], undefined >; describe('should return schema object', () => { test('with undefined keys', () => { expectTypeOf(requiredAsync(wrapped)).toEqualTypeOf(); expectTypeOf( requiredAsync(wrapped, undefined) ).toEqualTypeOf(); expectTypeOf(requiredAsync(wrapped, 'message')).toEqualTypeOf< SchemaWithRequiredAsync >(); expectTypeOf(requiredAsync(wrapped, () => 'message')).toEqualTypeOf< SchemaWithRequiredAsync string> >(); }); test('with specific keys', () => { expectTypeOf( requiredAsync(wrapped, ['key2', 'key3']) ).toEqualTypeOf(); expectTypeOf( requiredAsync(wrapped, ['key2', 'key3'], undefined) ).toEqualTypeOf(); expectTypeOf( requiredAsync(wrapped, ['key2', 'key3'], 'message') ).toEqualTypeOf< SchemaWithRequiredAsync >(); expectTypeOf( requiredAsync(wrapped, ['key2', 'key3'], () => 'message') ).toEqualTypeOf< SchemaWithRequiredAsync string> >(); }); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf< { key1: string; key2: number; key3: string; key4: number | null; } & { [key: string]: boolean } >(); expectTypeOf>().toEqualTypeOf< { key1?: string; key2: number; key3: string; key4?: number | null; } & { [key: string]: boolean } >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< { key1: string; key2: number; key3: string; key4: number; } & { [key: string]: boolean } >(); expectTypeOf>().toEqualTypeOf< { key1?: string; key2: number; key3: string; key4: number; } & { [key: string]: boolean } >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< | NonOptionalIssue | ObjectWithRestIssue | NumberIssue | StringIssue | BooleanIssue >(); expectTypeOf>().toEqualTypeOf< | NonOptionalIssue | ObjectWithRestIssue | NumberIssue | StringIssue | BooleanIssue >(); }); }); }); }); ================================================ FILE: library/src/methods/required/requiredAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { boolean, nonOptionalAsync, nullishAsync, number, objectAsync, objectWithRestAsync, optional, optionalAsync, string, } from '../../schemas/index.ts'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssueAsync } from '../../vitest/index.ts'; import { requiredAsync } from './requiredAsync.ts'; describe('requiredAsync', () => { const entries = { key1: optional(string()), key2: optional(number()), key3: optionalAsync(string()), key4: nullishAsync(number(), async () => 123), }; const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, } as const; describe('objectAsync', () => { const wrapped = objectAsync(entries); const schema1 = requiredAsync(wrapped); const schema2 = requiredAsync(wrapped, ['key1', 'key3']); describe('should return schema object', () => { const baseObjectAsync = { kind: 'schema', type: 'object', reference: objectAsync, expects: 'Object', message: undefined, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } as const; test('with undefined keys and undefined message', () => { const expected: typeof schema1 = { ...baseObjectAsync, entries: { key1: { ...nonOptionalAsync(entries.key1), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: { ...nonOptionalAsync(entries.key2), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...nonOptionalAsync(entries.key3), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: { ...nonOptionalAsync(entries.key4), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, }, }; expect(schema1).toStrictEqual(expected); expect(schema1, undefined).toStrictEqual(expected); }); test('with undefined keys and string message', () => { const message = 'message'; const schema = requiredAsync(wrapped, message); expect(schema).toStrictEqual({ ...baseObjectAsync, entries: { key1: { ...nonOptionalAsync(entries.key1, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: { ...nonOptionalAsync(entries.key2, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...nonOptionalAsync(entries.key3, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: { ...nonOptionalAsync(entries.key4, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, }, } satisfies typeof schema); }); test('with undefined keys and function message', () => { const message = () => 'message'; const schema = requiredAsync(wrapped, message); expect(schema).toStrictEqual({ ...baseObjectAsync, entries: { key1: { ...nonOptionalAsync(entries.key1, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: { ...nonOptionalAsync(entries.key2, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...nonOptionalAsync(entries.key3, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: { ...nonOptionalAsync(entries.key4, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, }, } satisfies typeof schema); }); test('with specific keys and undefined message', () => { const expected: typeof schema2 = { ...baseObjectAsync, entries: { key1: { ...nonOptionalAsync(entries.key1), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: entries.key2, key3: { ...nonOptionalAsync(entries.key3), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: entries.key4, }, }; expect(schema2).toStrictEqual(expected); expect(schema2, undefined).toStrictEqual(expected); }); test('with specific keys and string message', () => { const message = 'message'; const schema = requiredAsync(wrapped, ['key1', 'key3'], message); expect(schema).toStrictEqual({ ...baseObjectAsync, entries: { key1: { ...nonOptionalAsync(entries.key1, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: entries.key2, key3: { ...nonOptionalAsync(entries.key3, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: entries.key4, }, } satisfies typeof schema); }); }); describe('should return dataset without nested issues', () => { test('if required keys are present', async () => { const input1 = { key1: 'foo', key2: 123, key3: 'bar', key4: 123 }; await expectNoSchemaIssueAsync(schema1, [input1]); await expectNoSchemaIssueAsync(schema2, [input1]); const input2 = { key1: 'foo', key3: 'bar' }; expect(await schema2['~run']({ value: input2 }, {})).toStrictEqual({ typed: true, value: { ...input2, key4: 123 }, }); }); }); describe('should return dataset with nested issues', () => { test('if required keys are missing', async () => { expect(await schema1['~run']({ value: {} }, {})).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key2', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key3"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key3', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key4"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key4', value: undefined, }, ], }, ], } satisfies FailureDataset>); const input = { key2: 123, key4: null }; expect(await schema2['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: { ...input, key4: 123 }, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key3"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key3', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('if required keys are undefined', async () => { const input1 = { key1: undefined, key2: undefined, key3: undefined, key4: undefined, }; expect(await schema1['~run']({ value: input1 }, {})).toStrictEqual({ typed: false, value: input1, issues: [ { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input1, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input1, key: 'key2', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input1, key: 'key3', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input1, key: 'key4', value: undefined, }, ], }, ], } satisfies FailureDataset>); const input2 = { key1: undefined, key2: 123, key3: undefined, key4: null, }; expect(await schema2['~run']({ value: input2 }, {})).toStrictEqual({ typed: false, value: { ...input2, key4: 123 }, issues: [ { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input2, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input2, key: 'key3', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); }); }); describe('objectWithRestAsync', () => { const rest = boolean(); const wrapped = objectWithRestAsync(entries, rest); const schema1 = requiredAsync(wrapped); const schema2 = requiredAsync(wrapped, ['key2', 'key3']); describe('should return schema object', () => { const baseObjectWithRestAsync = { kind: 'schema', type: 'object_with_rest', reference: objectWithRestAsync, expects: 'Object', rest, message: undefined, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } as const; test('with undefined keys and undefined message', () => { const expected: typeof schema1 = { ...baseObjectWithRestAsync, entries: { key1: { ...nonOptionalAsync(entries.key1), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: { ...nonOptionalAsync(entries.key2), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...nonOptionalAsync(entries.key3), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: { ...nonOptionalAsync(entries.key4), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, }, }; expect(schema1).toStrictEqual(expected); expect(schema1, undefined).toStrictEqual(expected); }); test('with undefined keys and string message', () => { const message = 'message'; const schema = requiredAsync(wrapped, message); expect(schema).toStrictEqual({ ...baseObjectWithRestAsync, entries: { key1: { ...nonOptionalAsync(entries.key1, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: { ...nonOptionalAsync(entries.key2, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...nonOptionalAsync(entries.key3, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: { ...nonOptionalAsync(entries.key4, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, }, rest, message: undefined, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } satisfies typeof schema); }); test('with undefined keys and function message', () => { const message = () => 'message'; const schema = requiredAsync(wrapped, message); expect(schema).toStrictEqual({ ...baseObjectWithRestAsync, entries: { key1: { ...nonOptionalAsync(entries.key1, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key2: { ...nonOptionalAsync(entries.key2, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...nonOptionalAsync(entries.key3, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: { ...nonOptionalAsync(entries.key4, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, }, } satisfies typeof schema); }); test('with specific keys und undefined message', () => { const expected: typeof schema2 = { ...baseObjectWithRestAsync, entries: { key1: entries.key1, key2: { ...nonOptionalAsync(entries.key2), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...nonOptionalAsync(entries.key3), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: entries.key4, }, }; expect(schema2).toStrictEqual(expected); expect(schema2, undefined).toStrictEqual(expected); }); test('with specific keys and string message', () => { const message = 'message'; const schema = requiredAsync(wrapped, ['key2', 'key3'], message); expect(schema).toStrictEqual({ ...baseObjectWithRestAsync, entries: { key1: entries.key1, key2: { ...nonOptionalAsync(entries.key2, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...nonOptionalAsync(entries.key3, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: entries.key4, }, } satisfies typeof schema); }); test('with specific keys and function message', () => { const message = () => 'message'; const schema = requiredAsync(wrapped, ['key2', 'key3'], message); expect(schema).toStrictEqual({ ...baseObjectWithRestAsync, entries: { key1: entries.key1, key2: { ...nonOptionalAsync(entries.key2, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key3: { ...nonOptionalAsync(entries.key3, message), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, key4: entries.key4, }, } satisfies typeof schema); }); }); describe('should return dataset without nested issues', () => { test('if required keys are present', async () => { const input1 = { key1: 'foo', key2: 123, key3: 'bar', key4: 123, other: true, }; // @ts-expect-error await expectNoSchemaIssueAsync(schema1, [input1]); // @ts-expect-error await expectNoSchemaIssueAsync(schema2, [input1]); const input2 = { key2: 123, key3: 'bar', other: true }; expect(await schema2['~run']({ value: input2 }, {})).toStrictEqual({ typed: true, value: { ...input2, key4: 123 }, }); }); }); describe('should return dataset with nested issues', () => { test('if required keys are missing', async () => { expect(await schema1['~run']({ value: {} }, {})).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key2', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key3"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key3', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key4"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key4', value: undefined, }, ], }, ], } satisfies FailureDataset>); const input = { key1: 'foo', key4: null, other: true }; expect(await schema2['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: { ...input, key4: 123 }, issues: [ { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key2', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key3"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key3', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('if required keys are undefined', async () => { const input1 = { key1: undefined, key2: undefined, key3: undefined, key4: undefined, }; expect(await schema1['~run']({ value: input1 }, {})).toStrictEqual({ typed: false, value: input1, issues: [ { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input1, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input1, key: 'key2', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input1, key: 'key3', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input1, key: 'key4', value: undefined, }, ], }, ], } satisfies FailureDataset>); const input2 = { key1: 'foo', key2: undefined, key3: undefined, key4: null, other: true, }; expect(await schema2['~run']({ value: input2 }, {})).toStrictEqual({ typed: false, value: { ...input2, key4: 123 }, issues: [ { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input2, key: 'key2', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'non_optional', input: undefined, expected: '!undefined', received: 'undefined', path: [ { type: 'object', origin: 'value', input: input2, key: 'key3', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); }); }); }); ================================================ FILE: library/src/methods/required/requiredAsync.ts ================================================ import { type LooseObjectIssue, type LooseObjectSchemaAsync, nonOptionalAsync, type NonOptionalIssue, type NonOptionalSchemaAsync, type ObjectIssue, type ObjectSchemaAsync, type ObjectWithRestIssue, type ObjectWithRestSchemaAsync, type StrictObjectIssue, type StrictObjectSchemaAsync, } from '../../schemas/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, Config, ErrorMessage, InferInput, InferIssue, InferObjectInput, InferObjectOutput, InferOutput, ObjectEntriesAsync, ObjectKeys, OutputDataset, SchemaWithoutPipe, StandardProps, UnknownDataset, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; /** * Schema type. */ type Schema = SchemaWithoutPipe< | LooseObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined > | ObjectSchemaAsync | undefined> | ObjectWithRestSchemaAsync< ObjectEntriesAsync, | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined > | StrictObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined > >; /** * Required entries type. */ type RequiredEntries< TEntries extends ObjectEntriesAsync, TKeys extends readonly (keyof TEntries)[] | undefined, TMessage extends ErrorMessage | undefined, > = { [TKey in keyof TEntries]: TKeys extends readonly (keyof TEntries)[] ? TKey extends TKeys[number] ? NonOptionalSchemaAsync : TEntries[TKey] : NonOptionalSchemaAsync; }; /** * Schema with required type. */ export type SchemaWithRequiredAsync< TSchema extends Schema, TKeys extends ObjectKeys | undefined, TMessage extends ErrorMessage | undefined, > = TSchema extends | ObjectSchemaAsync | undefined> | StrictObjectSchemaAsync< infer TEntries, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: RequiredEntries; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput>, InferObjectOutput> >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => Promise< OutputDataset< InferObjectOutput>, NonOptionalIssue | InferIssue > >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput< RequiredEntries >; readonly output: InferObjectOutput< RequiredEntries >; readonly issue: NonOptionalIssue | InferIssue; } | undefined; } : TSchema extends LooseObjectSchemaAsync< infer TEntries, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: RequiredEntries; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput> & { [key: string]: unknown; }, InferObjectOutput> & { [key: string]: unknown; } >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => Promise< OutputDataset< InferObjectOutput> & { [key: string]: unknown; }, NonOptionalIssue | InferIssue > >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput< RequiredEntries > & { [key: string]: unknown; }; readonly output: InferObjectOutput< RequiredEntries > & { [key: string]: unknown; }; readonly issue: NonOptionalIssue | InferIssue; } | undefined; } : TSchema extends ObjectWithRestSchemaAsync< infer TEntries, infer TRest, ErrorMessage | undefined > ? Omit & { /** * The object entries. */ readonly entries: RequiredEntries; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps< InferObjectInput> & { [key: string]: InferInput; }, InferObjectOutput> & { [key: string]: InferOutput; } >; /** * Parses unknown input. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => Promise< OutputDataset< InferObjectOutput> & { [key: string]: InferOutput; }, NonOptionalIssue | InferIssue > >; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: InferObjectInput< RequiredEntries > & { [key: string]: InferInput; }; readonly output: InferObjectOutput< RequiredEntries > & { [key: string]: InferOutput }; readonly issue: NonOptionalIssue | InferIssue; } | undefined; } : never; /** * Creates a modified copy of an object schema that marks all entries as required. * * @param schema The schema to modify. * * @returns An object schema. */ // @ts-expect-error FIXME: TypeScript incorrectly claims that the overload // signature is not compatible with the implementation signature export function requiredAsync( schema: TSchema ): SchemaWithRequiredAsync; /** * Creates a modified copy of an object schema that marks all entries as required. * * @param schema The schema to modify. * @param message The error message. * * @returns An object schema. */ export function requiredAsync< const TSchema extends Schema, const TMessage extends ErrorMessage | undefined, >( schema: TSchema, message: TMessage ): SchemaWithRequiredAsync; /** * Creates a modified copy of an object schema that marks the selected entries * as required. * * @param schema The schema to modify. * @param keys The selected entries. * * @returns An object schema. */ export function requiredAsync< const TSchema extends Schema, const TKeys extends ObjectKeys, >( schema: TSchema, keys: TKeys ): SchemaWithRequiredAsync; /** * Creates a modified copy of an object schema that marks the selected entries * as required. * * @param schema The schema to modify. * @param keys The selected entries. * @param message The error message. * * @returns An object schema. */ export function requiredAsync< const TSchema extends Schema, const TKeys extends ObjectKeys, const TMessage extends ErrorMessage | undefined, >( schema: TSchema, keys: TKeys, message: TMessage ): SchemaWithRequiredAsync; // @__NO_SIDE_EFFECTS__ export function requiredAsync( schema: Schema, arg2?: ErrorMessage | ObjectKeys, arg3?: ErrorMessage ): SchemaWithRequiredAsync< Schema, ObjectKeys | undefined, ErrorMessage | undefined > { // Get keys and message from arguments const keys = Array.isArray(arg2) ? arg2 : undefined; const message = (Array.isArray(arg2) ? arg3 : arg2) as | ErrorMessage | undefined; // Create modified object entries const entries: RequiredEntries< ObjectEntriesAsync, ObjectKeys, ErrorMessage | undefined > = {}; for (const key in schema.entries) { // @ts-expect-error entries[key] = !keys || keys.includes(key) ? nonOptionalAsync(schema.entries[key], message) : schema.entries[key]; } // Return modified copy of schema return { ...schema, entries, get '~standard'() { return _getStandardProps(this); }, }; } ================================================ FILE: library/src/methods/safeParse/index.ts ================================================ export * from './safeParse.ts'; export * from './safeParseAsync.ts'; export * from './types.ts'; ================================================ FILE: library/src/methods/safeParse/safeParse.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { object, string } from '../../schemas/index.ts'; import { pipe } from '../pipe/pipe.ts'; import { safeParse } from './safeParse.ts'; import type { SafeParseResult } from './types.ts'; describe('safeParse', () => { test('should return safe parse result', () => { const schema = object({ key: pipe( string(), transform((input) => input.length) ), }); expectTypeOf(safeParse(schema, { key: 'foo' })).toEqualTypeOf< SafeParseResult >(); }); }); ================================================ FILE: library/src/methods/safeParse/safeParse.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { minLength, transform } from '../../actions/index.ts'; import { object, string } from '../../schemas/index.ts'; import { pipe } from '../pipe/index.ts'; import { safeParse } from './safeParse.ts'; describe('safeParse', () => { test('should return successful output', () => { expect( safeParse( object({ key: pipe( string(), minLength(5), transform((input) => input.length) ), }), { key: 'foobar' } ) ).toStrictEqual({ typed: true, success: true, output: { key: 6 }, issues: undefined, }); }); test('should return typed output with issues', () => { expect( safeParse(object({ key: pipe(string(), minLength(5)) }), { key: 'foo' }) ).toStrictEqual({ typed: true, success: false, output: { key: 'foo' }, issues: [ { kind: 'validation', type: 'min_length', input: 'foo', expected: '>=5', received: '3', message: 'Invalid length: Expected >=5 but received 3', requirement: 5, path: [ { type: 'object', origin: 'value', input: { key: 'foo' }, key: 'key', value: 'foo', }, ], issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }, ], }); }); test('should return untyped output with issues', () => { expect(safeParse(object({ key: string() }), { key: 123 })).toStrictEqual({ typed: false, success: false, output: { key: 123 }, issues: [ { kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', message: 'Invalid type: Expected string but received 123', requirement: undefined, path: [ { type: 'object', origin: 'value', input: { key: 123 }, key: 'key', value: 123, }, ], issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }, ], }); }); }); ================================================ FILE: library/src/methods/safeParse/safeParse.ts ================================================ import { getGlobalConfig } from '../../storages/index.ts'; import type { BaseIssue, BaseSchema, Config, InferIssue, } from '../../types/index.ts'; import type { SafeParseResult } from './types.ts'; /** * Parses an unknown input based on a schema. * * @param schema The schema to be used. * @param input The input to be parsed. * @param config The parse configuration. * * @returns The parse result. */ // @__NO_SIDE_EFFECTS__ export function safeParse< const TSchema extends BaseSchema>, >( schema: TSchema, input: unknown, config?: Config> ): SafeParseResult { const dataset = schema['~run']({ value: input }, getGlobalConfig(config)); return { typed: dataset.typed, success: !dataset.issues, output: dataset.value, issues: dataset.issues, } as SafeParseResult; } ================================================ FILE: library/src/methods/safeParse/safeParseAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { object, string } from '../../schemas/index.ts'; import { pipe } from '../pipe/pipe.ts'; import { safeParseAsync } from './safeParseAsync.ts'; import type { SafeParseResult } from './types.ts'; describe('safeParseAsync', () => { test('should return safe parse result', () => { const schema = object({ key: pipe( string(), transform((input) => input.length) ), }); expectTypeOf(safeParseAsync(schema, { key: 'foo' })).toEqualTypeOf< Promise> >(); }); }); ================================================ FILE: library/src/methods/safeParse/safeParseAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { minLength, transform } from '../../actions/index.ts'; import { objectAsync, string } from '../../schemas/index.ts'; import { pipe } from '../pipe/index.ts'; import { safeParseAsync } from './safeParseAsync.ts'; describe('safeParseAsync', () => { test('should return successful output', async () => { expect( await safeParseAsync( objectAsync({ key: pipe( string(), minLength(5), transform((input) => input.length) ), }), { key: 'foobar' } ) ).toStrictEqual({ typed: true, success: true, output: { key: 6 }, issues: undefined, }); }); test('should return typed output with issues', async () => { expect( await safeParseAsync(objectAsync({ key: pipe(string(), minLength(5)) }), { key: 'foo', }) ).toStrictEqual({ typed: true, success: false, output: { key: 'foo' }, issues: [ { kind: 'validation', type: 'min_length', input: 'foo', expected: '>=5', received: '3', message: 'Invalid length: Expected >=5 but received 3', requirement: 5, path: [ { type: 'object', origin: 'value', input: { key: 'foo' }, key: 'key', value: 'foo', }, ], issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }, ], }); }); test('should return untyped output with issues', async () => { expect( await safeParseAsync(objectAsync({ key: string() }), { key: 123 }) ).toStrictEqual({ typed: false, success: false, output: { key: 123 }, issues: [ { kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', message: 'Invalid type: Expected string but received 123', requirement: undefined, path: [ { type: 'object', origin: 'value', input: { key: 123 }, key: 'key', value: 123, }, ], issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }, ], }); }); }); ================================================ FILE: library/src/methods/safeParse/safeParseAsync.ts ================================================ import { getGlobalConfig } from '../../storages/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, Config, InferIssue, } from '../../types/index.ts'; import type { SafeParseResult } from './types.ts'; /** * Parses an unknown input based on a schema. * * @param schema The schema to be used. * @param input The input to be parsed. * @param config The parse configuration. * * @returns The parse result. */ // @__NO_SIDE_EFFECTS__ export async function safeParseAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, >( schema: TSchema, input: unknown, config?: Config> ): Promise> { const dataset = await schema['~run']( { value: input }, getGlobalConfig(config) ); return { typed: dataset.typed, success: !dataset.issues, output: dataset.value, issues: dataset.issues, } as SafeParseResult; } ================================================ FILE: library/src/methods/safeParse/types.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, InferIssue, InferOutput, } from '../../types/index.ts'; /** * Safe parse result type. */ export type SafeParseResult< TSchema extends | BaseSchema> | BaseSchemaAsync>, > = | { /** * Whether is's typed. */ readonly typed: true; /** * Whether it's successful. */ readonly success: true; /** * The output value. */ readonly output: InferOutput; /** * The issues, if any. */ readonly issues: undefined; } | { readonly typed: true; readonly success: false; readonly output: InferOutput; readonly issues: [InferIssue, ...InferIssue[]]; } | { readonly typed: false; readonly success: false; readonly output: unknown; readonly issues: [InferIssue, ...InferIssue[]]; }; ================================================ FILE: library/src/methods/safeParser/index.ts ================================================ export * from './safeParser.ts'; export * from './safeParserAsync.ts'; ================================================ FILE: library/src/methods/safeParser/safeParser.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { object, string } from '../../schemas/index.ts'; import type { Config, InferIssue } from '../../types/index.ts'; import { pipe } from '../pipe/pipe.ts'; import type { SafeParseResult } from '../safeParse/index.ts'; import { type SafeParser, safeParser } from './safeParser.ts'; describe('safeParser', () => { describe('should return function object', () => { const schema = object({ key: pipe( string(), transform((input) => input.length) ), }); type Schema = typeof schema; test('without config', () => { expectTypeOf(safeParser(schema)).toEqualTypeOf< SafeParser >(); expectTypeOf(safeParser(schema, undefined)).toEqualTypeOf< SafeParser >(); }); test('with config', () => { const config: Config> = { abortEarly: true, }; expectTypeOf(safeParser(schema, config)).toEqualTypeOf< SafeParser >(); }); }); test('should return safe parse result', () => { const schema = object({ key: pipe( string(), transform((input) => input.length) ), }); expectTypeOf(safeParser(schema)({ key: 'foo' })).toEqualTypeOf< SafeParseResult >(); }); }); ================================================ FILE: library/src/methods/safeParser/safeParser.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { minLength, transform } from '../../actions/index.ts'; import { object, string } from '../../schemas/index.ts'; import type { Config, InferIssue } from '../../types/index.ts'; import { pipe } from '../pipe/index.ts'; import { safeParser } from './safeParser.ts'; describe('safeParser', () => { describe('should return function object', () => { const schema = object({ key: pipe( string(), transform((input) => input.length) ), }); test('without config', () => { const func1 = safeParser(schema); expect(func1).toBeInstanceOf(Function); expect(func1.schema).toBe(schema); expect(func1.config).toBeUndefined(); const func2 = safeParser(schema, undefined); expect(func2).toBeInstanceOf(Function); expect(func2.schema).toBe(schema); expect(func2.config).toBeUndefined(); }); test('with config', () => { const config: Config> = { abortEarly: true, }; const func = safeParser(schema, config); expect(func).toBeInstanceOf(Function); expect(func.schema).toBe(schema); expect(func.config).toBe(config); }); }); test('should return successful output', () => { expect( safeParser( object({ key: pipe( string(), minLength(5), transform((input) => input.length) ), }) )({ key: 'foobar' }) ).toStrictEqual({ typed: true, success: true, output: { key: 6 }, issues: undefined, }); }); test('should return typed output with issues', () => { expect( safeParser(object({ key: pipe(string(), minLength(5)) }))({ key: 'foo' }) ).toStrictEqual({ typed: true, success: false, output: { key: 'foo' }, issues: [ { kind: 'validation', type: 'min_length', input: 'foo', expected: '>=5', received: '3', message: 'Invalid length: Expected >=5 but received 3', requirement: 5, path: [ { type: 'object', origin: 'value', input: { key: 'foo' }, key: 'key', value: 'foo', }, ], issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }, ], }); }); test('should return untyped output with issues', () => { expect(safeParser(object({ key: string() }))({ key: 123 })).toStrictEqual({ typed: false, success: false, output: { key: 123 }, issues: [ { kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', message: 'Invalid type: Expected string but received 123', requirement: undefined, path: [ { type: 'object', origin: 'value', input: { key: 123 }, key: 'key', value: 123, }, ], issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }, ], }); }); }); ================================================ FILE: library/src/methods/safeParser/safeParser.ts ================================================ import type { BaseIssue, BaseSchema, Config, InferIssue, } from '../../types/index.ts'; import { safeParse, type SafeParseResult } from '../safeParse/index.ts'; /** * The safe parser interface. */ export interface SafeParser< TSchema extends BaseSchema>, TConfig extends Config> | undefined, > { /** * Parses an unknown input based on the schema. */ (input: unknown): SafeParseResult; /** * The schema to be used. */ readonly schema: TSchema; /** * The parser configuration. */ readonly config: TConfig; } /** * Returns a function that parses an unknown input based on a schema. * * @param schema The schema to be used. * * @returns The parser function. */ export function safeParser< const TSchema extends BaseSchema>, >(schema: TSchema): SafeParser; /** * Returns a function that parses an unknown input based on a schema. * * @param schema The schema to be used. * @param config The parser configuration. * * @returns The parser function. */ export function safeParser< const TSchema extends BaseSchema>, const TConfig extends Config> | undefined, >(schema: TSchema, config: TConfig): SafeParser; // @__NO_SIDE_EFFECTS__ export function safeParser( schema: BaseSchema>, config?: Config>>> ): SafeParser< BaseSchema>, Config> | undefined > { const func: SafeParser< BaseSchema>, Config> | undefined > = (input: unknown) => safeParse(schema, input, config); // @ts-expect-error func.schema = schema; // @ts-expect-error func.config = config; return func; } ================================================ FILE: library/src/methods/safeParser/safeParserAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { object, string } from '../../schemas/index.ts'; import type { Config, InferIssue } from '../../types/index.ts'; import { pipe } from '../pipe/pipe.ts'; import type { SafeParseResult } from '../safeParse/index.ts'; import { type SafeParserAsync, safeParserAsync } from './safeParserAsync.ts'; describe('safeParserAsync', () => { describe('should return function object', () => { const schema = object({ key: pipe( string(), transform((input) => input.length) ), }); type Schema = typeof schema; test('without config', () => { expectTypeOf(safeParserAsync(schema)).toEqualTypeOf< SafeParserAsync >(); expectTypeOf(safeParserAsync(schema, undefined)).toEqualTypeOf< SafeParserAsync >(); }); test('with config', () => { const config: Config> = { abortEarly: true, }; expectTypeOf(safeParserAsync(schema, config)).toEqualTypeOf< SafeParserAsync >(); }); }); test('should return safe parse result', () => { const schema = object({ key: pipe( string(), transform((input) => input.length) ), }); expectTypeOf(safeParserAsync(schema)({ key: 'foo' })).toEqualTypeOf< Promise> >(); }); }); ================================================ FILE: library/src/methods/safeParser/safeParserAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { minLength, transform } from '../../actions/index.ts'; import { objectAsync, string } from '../../schemas/index.ts'; import type { Config, InferIssue } from '../../types/index.ts'; import { pipe } from '../pipe/index.ts'; import { safeParserAsync } from './safeParserAsync.ts'; describe('safeParserAsync', () => { describe('should return function object', () => { const schema = objectAsync({ key: pipe( string(), transform((input) => input.length) ), }); test('without config', () => { const func1 = safeParserAsync(schema); expect(func1).toBeInstanceOf(Function); expect(func1.schema).toBe(schema); expect(func1.config).toBeUndefined(); const func2 = safeParserAsync(schema, undefined); expect(func2).toBeInstanceOf(Function); expect(func2.schema).toBe(schema); expect(func2.config).toBeUndefined(); }); test('with config', () => { const config: Config> = { abortEarly: true, }; const func = safeParserAsync(schema, config); expect(func).toBeInstanceOf(Function); expect(func.schema).toBe(schema); expect(func.config).toBe(config); }); }); test('should return successful output', async () => { expect( await safeParserAsync( objectAsync({ key: pipe( string(), minLength(5), transform((input) => input.length) ), }) )({ key: 'foobar' }) ).toStrictEqual({ typed: true, success: true, output: { key: 6 }, issues: undefined, }); }); test('should return typed output with issues', async () => { expect( await safeParserAsync(objectAsync({ key: pipe(string(), minLength(5)) }))( { key: 'foo', } ) ).toStrictEqual({ typed: true, success: false, output: { key: 'foo' }, issues: [ { kind: 'validation', type: 'min_length', input: 'foo', expected: '>=5', received: '3', message: 'Invalid length: Expected >=5 but received 3', requirement: 5, path: [ { type: 'object', origin: 'value', input: { key: 'foo' }, key: 'key', value: 'foo', }, ], issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }, ], }); }); test('should return untyped output with issues', async () => { expect( await safeParserAsync(objectAsync({ key: string() }))({ key: 123 }) ).toStrictEqual({ typed: false, success: false, output: { key: 123 }, issues: [ { kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', message: 'Invalid type: Expected string but received 123', requirement: undefined, path: [ { type: 'object', origin: 'value', input: { key: 123 }, key: 'key', value: 123, }, ], issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }, ], }); }); }); ================================================ FILE: library/src/methods/safeParser/safeParserAsync.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, Config, InferIssue, } from '../../types/index.ts'; import { safeParseAsync, type SafeParseResult } from '../safeParse/index.ts'; /** * The safe parser async interface. */ export interface SafeParserAsync< TSchema extends | BaseSchema> | BaseSchemaAsync>, TConfig extends Config> | undefined, > { /** * Parses an unknown input based on the schema. */ (input: unknown): Promise>; /** * The schema to be used. */ readonly schema: TSchema; /** * The parser configuration. */ readonly config: TConfig; } /** * Returns a function that parses an unknown input based on a schema. * * @param schema The schema to be used. * * @returns The parser function. */ export function safeParserAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, >(schema: TSchema): SafeParserAsync; /** * Returns a function that parses an unknown input based on a schema. * * @param schema The schema to be used. * @param config The parser configuration. * * @returns The parser function. */ export function safeParserAsync< const TSchema extends | BaseSchema> | BaseSchemaAsync>, const TConfig extends Config> | undefined, >(schema: TSchema, config: TConfig): SafeParserAsync; // @__NO_SIDE_EFFECTS__ export function safeParserAsync( schema: | BaseSchema> | BaseSchemaAsync>, config?: Config< InferIssue< | BaseSchema> | BaseSchemaAsync> > > ): SafeParserAsync< | BaseSchema> | BaseSchemaAsync>, Config> | undefined > { const func: SafeParserAsync< | BaseSchema> | BaseSchemaAsync>, Config> | undefined > = (input: unknown) => safeParseAsync(schema, input, config); // @ts-expect-error func.schema = schema; // @ts-expect-error func.config = config; return func; } ================================================ FILE: library/src/methods/summarize/index.ts ================================================ export * from './summarize.ts'; ================================================ FILE: library/src/methods/summarize/summarize.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { IncludesIssue, MinLengthIssue } from '../../actions/index.ts'; import type { NumberIssue, StringIssue } from '../../schemas/index.ts'; import type { ArrayPathItem, ObjectPathItem } from '../../types/issue.ts'; import { summarize } from './summarize.ts'; describe('summarize', () => { const commonIssueInfo = { abortEarly: undefined, abortPipeEarly: undefined, issues: undefined, lang: undefined, }; test('should return single error without path', () => { const rootIssues1: [StringIssue] = [ { ...commonIssueInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', message: 'Invalid type: Expected string but received 123', path: undefined, }, ]; expect(summarize(rootIssues1)).toBe( '× Invalid type: Expected string but received 123' ); }); test('should return multiple errors without path', () => { const rootIssues2: [ IncludesIssue, MinLengthIssue, ] = [ { ...commonIssueInfo, kind: 'validation', type: 'includes', input: '123', expected: '"foo"', received: '!"foo"', message: 'Invalid content: Expected "foo" but received !"foo"', requirement: 'foo', path: undefined, }, { ...commonIssueInfo, kind: 'validation', type: 'min_length', input: '123', expected: '>=5', received: '3', message: 'Invalid length: Expected >=5 but received 3', requirement: 5, path: undefined, }, ]; expect(summarize(rootIssues2)).toBe( '× Invalid content: Expected "foo" but received !"foo"\n' + '× Invalid length: Expected >=5 but received 3' ); }); test('should return single error with path', () => { const nestedIssue: NumberIssue = { ...commonIssueInfo, kind: 'schema', type: 'number', input: '1', expected: 'number', received: '"1"', message: 'Invalid type: Expected number but received "1"', path: [ { type: 'array', origin: 'value', input: ['1'], key: 0, value: '1', } satisfies ArrayPathItem, ], }; expect(summarize([nestedIssue])).toBe( '× Invalid type: Expected number but received "1"\n → at 0' ); }); test('should return multiple errors with path', () => { const input = { key1: 'bar', key2: '21', }; const nestedIssues: [ IncludesIssue, MinLengthIssue, NumberIssue, ] = [ { ...commonIssueInfo, kind: 'validation', type: 'includes', input: '123', expected: '"foo"', received: '!"foo"', message: 'Invalid content: Expected "foo" but received !"foo"', requirement: 'foo', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: input.key1, } satisfies ObjectPathItem, ], }, { ...commonIssueInfo, kind: 'validation', type: 'min_length', input: '123', expected: '>=5', received: '3', message: 'Invalid length: Expected >=5 but received 3', requirement: 5, path: [ { type: 'object', origin: 'value', input, key: 'key1', value: input.key1, } satisfies ObjectPathItem, ], }, { expected: 'number', input: '21', kind: 'schema', message: 'Invalid type: Expected number but received "21"', path: [ { type: 'object', origin: 'value', input, key: 'key2', value: input.key2, } satisfies ObjectPathItem, ], received: '"21"', type: 'number', }, ]; expect(summarize(nestedIssues)).toBe( '× Invalid content: Expected "foo" but received !"foo"\n' + ' → at key1\n' + '× Invalid length: Expected >=5 but received 3\n' + ' → at key1\n' + '× Invalid type: Expected number but received "21"\n' + ' → at key2' ); }); test('should return single error with dot path', () => { const nestedIssue: NumberIssue = { ...commonIssueInfo, kind: 'schema', type: 'number', input: 'foo', expected: 'number', received: '"foo"', message: 'Invalid type: Expected number but received "foo"', path: [ { type: 'object', origin: 'value', input: { dot: [{ path: 'foo' }] }, key: 'dot', value: [{ path: 'foo' }], } satisfies ObjectPathItem, { type: 'array', origin: 'value', input: [{ path: 'foo' }], key: 0, value: { path: 'foo' }, } satisfies ArrayPathItem, { type: 'object', origin: 'value', input: { path: 'foo' }, key: 'path', value: 'foo', } satisfies ObjectPathItem, ], }; expect(summarize([nestedIssue])).toBe( '× Invalid type: Expected number but received "foo"\n' + ' → at dot.0.path' ); }); }); ================================================ FILE: library/src/methods/summarize/summarize.ts ================================================ import type { BaseIssue } from '../../types/index.ts'; import { getDotPath } from '../../utils/index.ts'; /** * Summarize the error messages of issues in a pretty-printable multi-line string. * * @param issues The list of issues. * * @returns A summary of the issues. * * @beta */ // @__NO_SIDE_EFFECTS__ export function summarize( issues: [BaseIssue, ...BaseIssue[]] ): string { // Create variable to store summary let summary = ''; // Add message of each issue to summary for (const issue of issues) { // Add newline if summary is not empty if (summary) { summary += '\n'; } // Add message to summary summary += `× ${issue.message}`; // Get dot path from issue const dotPath = getDotPath(issue); // If dot path is available, add it to summary if (dotPath) { summary += `\n → at ${dotPath}`; } } // Return summary return summary; } ================================================ FILE: library/src/methods/unwrap/index.ts ================================================ export * from './unwrap.ts'; ================================================ FILE: library/src/methods/unwrap/unwrap.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { exactOptional, exactOptionalAsync, nonNullable, nonNullableAsync, nonNullish, nonNullishAsync, nonOptional, nonOptionalAsync, nullable, nullableAsync, nullish, nullishAsync, optional, optionalAsync, string, undefinedable, undefinedableAsync, } from '../../schemas/index.ts'; import { fallback, fallbackAsync } from '../fallback/index.ts'; import { pipe, pipeAsync } from '../pipe/index.ts'; import { unwrap } from './unwrap.ts'; describe('unwrap', () => { const wrapped = string(); type Wrapped = typeof wrapped; test('should unwrap exactOptional', () => { expectTypeOf(unwrap(exactOptional(wrapped))).toEqualTypeOf(); }); test('should unwrap exactOptionalAsync', () => { expectTypeOf(unwrap(exactOptionalAsync(wrapped))).toEqualTypeOf(); }); test('should unwrap nonNullable', () => { expectTypeOf(unwrap(nonNullable(wrapped))).toEqualTypeOf(); }); test('should unwrap nonNullableAsync', () => { expectTypeOf(unwrap(nonNullableAsync(wrapped))).toEqualTypeOf(); }); test('should unwrap nonNullish', () => { expectTypeOf(unwrap(nonNullish(wrapped))).toEqualTypeOf(); }); test('should unwrap nonNullishAsync', () => { expectTypeOf(unwrap(nonNullishAsync(wrapped))).toEqualTypeOf(); }); test('should unwrap nonOptional', () => { expectTypeOf(unwrap(nonOptional(wrapped))).toEqualTypeOf(); }); test('should unwrap nonOptionalAsync', () => { expectTypeOf(unwrap(nonOptionalAsync(wrapped))).toEqualTypeOf(); }); test('should unwrap nullable', () => { expectTypeOf(unwrap(nullable(wrapped))).toEqualTypeOf(); }); test('should unwrap nullableAsync', () => { expectTypeOf(unwrap(nullableAsync(wrapped))).toEqualTypeOf(); }); test('should unwrap nullish', () => { expectTypeOf(unwrap(nullish(wrapped))).toEqualTypeOf(); }); test('should unwrap nullishAsync', () => { expectTypeOf(unwrap(nullishAsync(wrapped))).toEqualTypeOf(); }); test('should unwrap optional', () => { expectTypeOf(unwrap(optional(wrapped))).toEqualTypeOf(); }); test('should unwrap optionalAsync', () => { expectTypeOf(unwrap(optionalAsync(wrapped))).toEqualTypeOf(); }); test('should unwrap undefinedable', () => { expectTypeOf(unwrap(undefinedable(wrapped))).toEqualTypeOf(); }); test('should unwrap undefinedableAsync', () => { expectTypeOf(unwrap(undefinedableAsync(wrapped))).toEqualTypeOf(); }); test('should unwrap schema with pipe', () => { expectTypeOf(unwrap(pipe(optional(wrapped)))).toEqualTypeOf(); expectTypeOf(unwrap(pipeAsync(optional(wrapped)))).toEqualTypeOf(); expectTypeOf( unwrap(pipeAsync(optionalAsync(wrapped))) ).toEqualTypeOf(); }); test('should unwrap schema with fallback', () => { expectTypeOf( unwrap(fallback(optional(wrapped), 'foo')) ).toEqualTypeOf(); expectTypeOf( unwrap(fallbackAsync(optional(wrapped), 'foo')) ).toEqualTypeOf(); expectTypeOf( unwrap(fallbackAsync(optionalAsync(wrapped), 'foo')) ).toEqualTypeOf(); }); }); ================================================ FILE: library/src/methods/unwrap/unwrap.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { exactOptional, exactOptionalAsync, nonNullable, nonNullableAsync, nonNullish, nonNullishAsync, nonOptional, nonOptionalAsync, nullable, nullableAsync, nullish, nullishAsync, optional, optionalAsync, string, undefinedable, undefinedableAsync, } from '../../schemas/index.ts'; import { fallback, fallbackAsync } from '../fallback/index.ts'; import { pipe, pipeAsync } from '../pipe/index.ts'; import { unwrap } from './unwrap.ts'; describe('unwrap', () => { const wrapped = string(); test('should unwrap exactOptional', () => { expect(unwrap(exactOptional(wrapped))).toBe(wrapped); }); test('should unwrap exactOptionalAsync', () => { expect(unwrap(exactOptionalAsync(wrapped))).toBe(wrapped); }); test('should unwrap nonNullable', () => { expect(unwrap(nonNullable(wrapped))).toBe(wrapped); }); test('should unwrap nonNullableAsync', () => { expect(unwrap(nonNullableAsync(wrapped))).toBe(wrapped); }); test('should unwrap nonNullish', () => { expect(unwrap(nonNullish(wrapped))).toBe(wrapped); }); test('should unwrap nonNullishAsync', () => { expect(unwrap(nonNullishAsync(wrapped))).toBe(wrapped); }); test('should unwrap nonOptional', () => { expect(unwrap(nonOptional(wrapped))).toBe(wrapped); }); test('should unwrap nonOptionalAsync', () => { expect(unwrap(nonOptionalAsync(wrapped))).toBe(wrapped); }); test('should unwrap nullable', () => { expect(unwrap(nullable(wrapped))).toBe(wrapped); }); test('should unwrap nullableAsync', () => { expect(unwrap(nullableAsync(wrapped))).toBe(wrapped); }); test('should unwrap nullish', () => { expect(unwrap(nullish(wrapped))).toBe(wrapped); }); test('should unwrap nullishAsync', () => { expect(unwrap(nullishAsync(wrapped))).toBe(wrapped); }); test('should unwrap optional', () => { expect(unwrap(optional(wrapped))).toBe(wrapped); }); test('should unwrap optionalAsync', () => { expect(unwrap(optionalAsync(wrapped))).toBe(wrapped); }); test('should unwrap undefinedable', () => { expect(unwrap(undefinedable(wrapped))).toBe(wrapped); }); test('should unwrap undefinedableAsync', () => { expect(unwrap(undefinedableAsync(wrapped))).toBe(wrapped); }); test('should unwrap schema with pipe', () => { expect(unwrap(pipe(optional(wrapped)))).toBe(wrapped); expect(unwrap(pipeAsync(optional(wrapped)))).toBe(wrapped); expect(unwrap(pipeAsync(optionalAsync(wrapped)))).toBe(wrapped); }); test('should unwrap schema with fallback', () => { expect(unwrap(fallback(optional(wrapped), 'foo'))).toBe(wrapped); expect(unwrap(fallbackAsync(optional(wrapped), 'foo'))).toBe(wrapped); expect(unwrap(fallbackAsync(optionalAsync(wrapped), 'foo'))).toBe(wrapped); }); }); ================================================ FILE: library/src/methods/unwrap/unwrap.ts ================================================ import type { ExactOptionalSchema, ExactOptionalSchemaAsync, NonNullableIssue, NonNullableSchema, NonNullableSchemaAsync, NonNullishIssue, NonNullishSchema, NonNullishSchemaAsync, NonOptionalIssue, NonOptionalSchema, NonOptionalSchemaAsync, NullableSchema, NullableSchemaAsync, NullishSchema, NullishSchemaAsync, OptionalSchema, OptionalSchemaAsync, UndefinedableSchema, UndefinedableSchemaAsync, } from '../../schemas/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, ErrorMessage, } from '../../types/index.ts'; /** * Unwraps the wrapped schema. * * @param schema The schema to be unwrapped. * * @returns The unwrapped schema. */ // @__NO_SIDE_EFFECTS__ export function unwrap< TSchema extends | ExactOptionalSchema< BaseSchema>, unknown > | ExactOptionalSchemaAsync< | BaseSchema> | BaseSchemaAsync>, unknown > | NonNullableSchema< BaseSchema>, ErrorMessage | undefined > | NonNullableSchemaAsync< | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined > | NonNullishSchema< BaseSchema>, ErrorMessage | undefined > | NonNullishSchemaAsync< | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined > | NonOptionalSchema< BaseSchema>, ErrorMessage | undefined > | NonOptionalSchemaAsync< | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined > | NullableSchema>, unknown> | NullableSchemaAsync< | BaseSchema> | BaseSchemaAsync>, unknown > | NullishSchema>, unknown> | NullishSchemaAsync< | BaseSchema> | BaseSchemaAsync>, unknown > | OptionalSchema>, unknown> | OptionalSchemaAsync< | BaseSchema> | BaseSchemaAsync>, unknown > | UndefinedableSchema< BaseSchema>, unknown > | UndefinedableSchemaAsync< | BaseSchema> | BaseSchemaAsync>, unknown >, >(schema: TSchema): TSchema['wrapped'] { return schema.wrapped; } ================================================ FILE: library/src/regex.ts ================================================ /** * [Base64](https://en.wikipedia.org/wiki/Base64) regex. */ export const BASE64_REGEX: RegExp = /^(?:[\da-z+/]{4})*(?:[\da-z+/]{2}==|[\da-z+/]{3}=)?$/iu; /** * [BIC](https://en.wikipedia.org/wiki/ISO_9362) regex. */ export const BIC_REGEX: RegExp = /^[A-Z]{6}(?!00)[\dA-Z]{2}(?:[\dA-Z]{3})?$/u; /** * [Cuid2](https://github.com/paralleldrive/cuid2) regex. */ export const CUID2_REGEX: RegExp = /^[a-z][\da-z]*$/u; /** * [Decimal](https://en.wikipedia.org/wiki/Decimal) regex. */ // eslint-disable-next-line redos-detector/no-unsafe-regex -- false positive export const DECIMAL_REGEX: RegExp = /^[+-]?(?:\d*\.)?\d+$/u; /** * [Digits](https://en.wikipedia.org/wiki/Numerical_digit) regex. */ export const DIGITS_REGEX: RegExp = /^\d+$/u; /** * [Domain name](https://en.wikipedia.org/wiki/Domain_name) regex. * * Hint: We decided against the `i` flag for better JSON Schema compatibility. * ASCII-only validation. Internationalized domain names (IDNs) are not * supported, including Punycode-encoded labels. */ export const DOMAIN_REGEX: RegExp = /^(?=.{1,253}$)(?:(?![Xx][Nn]--)[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,63}$/u; /** * [Email address](https://en.wikipedia.org/wiki/Email_address) regex. */ export const EMAIL_REGEX: RegExp = /^[\w+-]+(?:\.[\w+-]+)*@[\da-z]+(?:[.-][\da-z]+)*\.[a-z]{2,}$/iu; /** * Emoji regex from [emoji-regex-xs](https://github.com/slevithan/emoji-regex-xs) v1.0.0 (MIT license). * * Hint: We decided against the newer `/^\p{RGI_Emoji}+$/v` regex because it is * not supported in older runtimes and does not match all emoji. */ export const EMOJI_REGEX: RegExp = // eslint-disable-next-line redos-detector/no-unsafe-regex -- false positives /^(?:[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|(?![\p{Emoji_Modifier_Base}\u{1F1E6}-\u{1F1FF}])\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|(?![\p{Emoji_Modifier_Base}\u{1F1E6}-\u{1F1FF}])\p{Emoji_Presentation}))*)+$/u; /** * [Hexadecimal](https://en.wikipedia.org/wiki/Hexadecimal) regex. * * Hint: We decided against the `i` flag for better JSON Schema compatibility. */ export const HEXADECIMAL_REGEX: RegExp = /^(?:0[hx])?[\da-fA-F]+$/u; /** * [Hex color](https://en.wikipedia.org/wiki/Web_colors#Hex_triplet) regex. * * Hint: We decided against the `i` flag for better JSON Schema compatibility. */ export const HEX_COLOR_REGEX: RegExp = /^#(?:[\da-fA-F]{3,4}|[\da-fA-F]{6}|[\da-fA-F]{8})$/u; /** * [IMEI](https://en.wikipedia.org/wiki/International_Mobile_Equipment_Identity) regex. */ export const IMEI_REGEX: RegExp = /^\d{15}$|^\d{2}-\d{6}-\d{6}-\d$/u; /** * [IPv4](https://en.wikipedia.org/wiki/IPv4) regex. */ export const IPV4_REGEX: RegExp = // eslint-disable-next-line redos-detector/no-unsafe-regex -- false positive /^(?:(?:[1-9]|1\d|2[0-4])?\d|25[0-5])(?:\.(?:(?:[1-9]|1\d|2[0-4])?\d|25[0-5])){3}$/u; /** * [IPv6](https://en.wikipedia.org/wiki/IPv6) regex. */ export const IPV6_REGEX: RegExp = /^(?:(?:[\da-f]{1,4}:){7}[\da-f]{1,4}|(?:[\da-f]{1,4}:){1,7}:|(?:[\da-f]{1,4}:){1,6}:[\da-f]{1,4}|(?:[\da-f]{1,4}:){1,5}(?::[\da-f]{1,4}){1,2}|(?:[\da-f]{1,4}:){1,4}(?::[\da-f]{1,4}){1,3}|(?:[\da-f]{1,4}:){1,3}(?::[\da-f]{1,4}){1,4}|(?:[\da-f]{1,4}:){1,2}(?::[\da-f]{1,4}){1,5}|[\da-f]{1,4}:(?::[\da-f]{1,4}){1,6}|:(?:(?::[\da-f]{1,4}){1,7}|:)|fe80:(?::[\da-f]{0,4}){0,4}%[\da-z]+|::(?:f{4}(?::0{1,4})?:)?(?:(?:25[0-5]|(?:2[0-4]|1?\d)?\d)\.){3}(?:25[0-5]|(?:2[0-4]|1?\d)?\d)|(?:[\da-f]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1?\d)?\d)\.){3}(?:25[0-5]|(?:2[0-4]|1?\d)?\d))$/iu; /** * [IP](https://en.wikipedia.org/wiki/IP_address) regex. */ export const IP_REGEX: RegExp = /^(?:(?:[1-9]|1\d|2[0-4])?\d|25[0-5])(?:\.(?:(?:[1-9]|1\d|2[0-4])?\d|25[0-5])){3}$|^(?:(?:[\da-f]{1,4}:){7}[\da-f]{1,4}|(?:[\da-f]{1,4}:){1,7}:|(?:[\da-f]{1,4}:){1,6}:[\da-f]{1,4}|(?:[\da-f]{1,4}:){1,5}(?::[\da-f]{1,4}){1,2}|(?:[\da-f]{1,4}:){1,4}(?::[\da-f]{1,4}){1,3}|(?:[\da-f]{1,4}:){1,3}(?::[\da-f]{1,4}){1,4}|(?:[\da-f]{1,4}:){1,2}(?::[\da-f]{1,4}){1,5}|[\da-f]{1,4}:(?::[\da-f]{1,4}){1,6}|:(?:(?::[\da-f]{1,4}){1,7}|:)|fe80:(?::[\da-f]{0,4}){0,4}%[\da-z]+|::(?:f{4}(?::0{1,4})?:)?(?:(?:25[0-5]|(?:2[0-4]|1?\d)?\d)\.){3}(?:25[0-5]|(?:2[0-4]|1?\d)?\d)|(?:[\da-f]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1?\d)?\d)\.){3}(?:25[0-5]|(?:2[0-4]|1?\d)?\d))$/iu; /** * [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date regex. */ export const ISO_DATE_REGEX: RegExp = /^\d{4}-(?:0[1-9]|1[0-2])-(?:[12]\d|0[1-9]|3[01])$/u; /** * [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) date-time regex. */ export const ISO_DATE_TIME_REGEX: RegExp = /^\d{4}-(?:0[1-9]|1[0-2])-(?:[12]\d|0[1-9]|3[01])[T ](?:0\d|1\d|2[0-3]):[0-5]\d$/u; /** * [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) time regex. */ export const ISO_TIME_REGEX: RegExp = /^(?:0\d|1\d|2[0-3]):[0-5]\d$/u; /** * [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) time with seconds regex. */ export const ISO_TIME_SECOND_REGEX: RegExp = /^(?:0\d|1\d|2[0-3])(?::[0-5]\d){2}$/u; /** * [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) timestamp regex. Allows a * space as a date/time separator and an optional space before the UTC offset. */ export const ISO_TIMESTAMP_REGEX: RegExp = /^\d{4}-(?:0[1-9]|1[0-2])-(?:[12]\d|0[1-9]|3[01])[T ](?:0\d|1\d|2[0-3])(?::[0-5]\d){2}(?:\.\d{1,9})?(?:Z| ?[+-](?:0\d|1\d|2[0-3])(?::?[0-5]\d)?)$/u; /** * [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) week regex. */ export const ISO_WEEK_REGEX: RegExp = /^\d{4}-W(?:0[1-9]|[1-4]\d|5[0-3])$/u; /** * [JWS compact serialization](https://datatracker.ietf.org/doc/html/rfc7515#section-3.1) * regex. * * Hint: Empty payload and signature segments are allowed because the * Base64URL-encoded representation of an empty octet sequence is an empty * string. */ export const JWS_COMPACT_REGEX: RegExp = /^(?:[\w-]{2,3}|(?:[\w-]{4})+(?:[\w-]{2,3})?)\.(?:[\w-]{2,3}|(?:[\w-]{4})+(?:[\w-]{2,3})?)?\.(?:[\w-]{2,3}|(?:[\w-]{4})+(?:[\w-]{2,3})?)?$/u; /** * [ISRC](https://en.wikipedia.org/wiki/International_Standard_Recording_Code) regex. */ export const ISRC_REGEX: RegExp = /^(?:[A-Z]{2}[A-Z\d]{3}\d{7}|[A-Z]{2}-[A-Z\d]{3}-\d{2}-\d{5})$/u; /** * [MAC](https://en.wikipedia.org/wiki/MAC_address) 48 bit regex. * * Hint: We decided against the `i` flag for better JSON Schema compatibility. */ export const MAC48_REGEX: RegExp = /^(?:[\da-fA-F]{2}:){5}[\da-fA-F]{2}$|^(?:[\da-fA-F]{2}-){5}[\da-fA-F]{2}$|^(?:[\da-fA-F]{4}\.){2}[\da-fA-F]{4}$/u; /** * [MAC](https://en.wikipedia.org/wiki/MAC_address) 64 bit regex. * * Hint: We decided against the `i` flag for better JSON Schema compatibility. */ export const MAC64_REGEX: RegExp = /^(?:[\da-fA-F]{2}:){7}[\da-fA-F]{2}$|^(?:[\da-fA-F]{2}-){7}[\da-fA-F]{2}$|^(?:[\da-fA-F]{4}\.){3}[\da-fA-F]{4}$|^(?:[\da-fA-F]{4}:){3}[\da-fA-F]{4}$/u; /** * [MAC](https://en.wikipedia.org/wiki/MAC_address) regex. * * Hint: We decided against the `i` flag for better JSON Schema compatibility. */ export const MAC_REGEX: RegExp = /^(?:[\da-fA-F]{2}:){5}[\da-fA-F]{2}$|^(?:[\da-fA-F]{2}-){5}[\da-fA-F]{2}$|^(?:[\da-fA-F]{4}\.){2}[\da-fA-F]{4}$|^(?:[\da-fA-F]{2}:){7}[\da-fA-F]{2}$|^(?:[\da-fA-F]{2}-){7}[\da-fA-F]{2}$|^(?:[\da-fA-F]{4}\.){3}[\da-fA-F]{4}$|^(?:[\da-fA-F]{4}:){3}[\da-fA-F]{4}$/u; /** * [Nano ID](https://github.com/ai/nanoid) regex. */ export const NANO_ID_REGEX: RegExp = /^[\w-]+$/u; /** * [Octal](https://en.wikipedia.org/wiki/Octal) regex. */ export const OCTAL_REGEX: RegExp = /^(?:0o)?[0-7]+$/u; /** * [RFC 5322 email address](https://datatracker.ietf.org/doc/html/rfc5322#section-3.4.1) regex. * * Hint: This regex was taken from the [HTML Living Standard Specification](https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address) and does not perfectly represent RFC 5322. */ export const RFC_EMAIL_REGEX: RegExp = // eslint-disable-next-line regexp/prefer-w, no-useless-escape, regexp/no-useless-escape, regexp/require-unicode-regexp /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/; /** * [Slug](https://en.wikipedia.org/wiki/Clean_URL#Slug) regex. */ export const SLUG_REGEX: RegExp = /^[\da-z]+(?:[-_][\da-z]+)*$/u; /** * [ULID](https://github.com/ulid/spec) regex. * * Hint: We decided against the `i` flag for better JSON Schema compatibility. */ export const ULID_REGEX: RegExp = /^[\da-hjkmnp-tv-zA-HJKMNP-TV-Z]{26}$/u; /** * [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) regex. */ export const UUID_REGEX: RegExp = /^[\da-f]{8}(?:-[\da-f]{4}){3}-[\da-f]{12}$/iu; ================================================ FILE: library/src/schemas/any/any.test-d.ts ================================================ /* eslint-disable @typescript-eslint/no-explicit-any */ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { any, type AnySchema } from './any.ts'; describe('any', () => { test('should return schema object', () => { expectTypeOf(any()).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/any/any.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue } from '../../vitest/index.ts'; import { any, type AnySchema } from './any.ts'; describe('any', () => { test('should return schema object', () => { expect(any()).toStrictEqual({ kind: 'schema', type: 'any', reference: any, expects: 'any', async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } satisfies AnySchema); }); describe('should return dataset without issues', () => { const schema = any(); // Primitive types test('for bigints', () => { expectNoSchemaIssue(schema, [-1n, 0n, 123n]); }); test('for booleans', () => { expectNoSchemaIssue(schema, [true, false]); }); test('for null', () => { expectNoSchemaIssue(schema, [null]); }); test('for numbers', () => { expectNoSchemaIssue(schema, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectNoSchemaIssue(schema, [undefined]); }); test('for strings', () => { expectNoSchemaIssue(schema, ['', 'foo', '123']); }); test('for symbols', () => { expectNoSchemaIssue(schema, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectNoSchemaIssue(schema, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectNoSchemaIssue(schema, [() => {}, function () {}]); }); test('for objects', () => { expectNoSchemaIssue(schema, [{}, { key: 'value' }]); }); }); }); ================================================ FILE: library/src/schemas/any/any.ts ================================================ /* eslint-disable @typescript-eslint/no-explicit-any */ import type { BaseSchema, SuccessDataset } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; /** * Any schema interface. */ export interface AnySchema extends BaseSchema { /** * The schema type. */ readonly type: 'any'; /** * The schema reference. */ readonly reference: typeof any; /** * The expected property. */ readonly expects: 'any'; } /** * Creates an any schema. * * Hint: This schema function exists only for completeness and is not * recommended in practice. Instead, `unknown` should be used to accept * unknown data. * * @returns An any schema. */ // @__NO_SIDE_EFFECTS__ export function any(): AnySchema { return { kind: 'schema', type: 'any', reference: any, expects: 'any', async: false, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset) { // @ts-expect-error dataset.typed = true; // @ts-expect-error return dataset as SuccessDataset; }, }; } ================================================ FILE: library/src/schemas/any/index.ts ================================================ export * from './any.ts'; ================================================ FILE: library/src/schemas/array/array.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { OptionalSchema } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { array, type ArraySchema } from './array.ts'; import type { ArrayIssue } from './types.ts'; describe('array', () => { describe('should return schema object', () => { const item = string(); type Item = typeof item; test('with undefined message', () => { type Schema = ArraySchema; expectTypeOf(array(item)).toEqualTypeOf(); expectTypeOf(array(item, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(array(item, 'message')).toEqualTypeOf< ArraySchema >(); }); test('with function message', () => { expectTypeOf(array(item, () => 'message')).toEqualTypeOf< ArraySchema string> >(); }); }); describe('should infer correct types', () => { type Schema = ArraySchema< OptionalSchema, 'foo'>, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf< (string | undefined)[] >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< ArrayIssue | StringIssue >(); }); }); }); ================================================ FILE: library/src/schemas/array/array.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { string, type StringIssue } from '../string/index.ts'; import { array, type ArraySchema } from './array.ts'; import type { ArrayIssue } from './types.ts'; describe('array', () => { describe('should return schema object', () => { const item = string(); type Item = typeof item; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'array', reference: array, expects: 'Array', item, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: ArraySchema = { ...baseSchema, message: undefined, }; expect(array(item)).toStrictEqual(schema); expect(array(item, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(array(item, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies ArraySchema); }); test('with function message', () => { const message = () => 'message'; expect(array(item, message)).toStrictEqual({ ...baseSchema, message, } satisfies ArraySchema); }); }); describe('should return dataset without issues', () => { const schema = array(string()); test('for empty array', () => { expectNoSchemaIssue(schema, [[]]); }); test('for simple array', () => { expectNoSchemaIssue(schema, [['foo', 'bar', 'baz']]); }); }); describe('should return dataset with issues', () => { const schema = array(string(), 'message'); const baseIssue: Omit = { kind: 'schema', type: 'array', expected: 'Array', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); describe('should return dataset without nested issues', () => { const schema = array(string()); test('for simple array', () => { expectNoSchemaIssue(schema, [['foo', 'bar', 'baz']]); }); test('for nested array', () => { expectNoSchemaIssue(array(schema), [[['foo', 'bar'], ['baz']]]); }); }); describe('should return dataset with nested issues', () => { const schema = array(string()); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const stringIssue: StringIssue = { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'array', origin: 'value', input: ['foo', 123, 'baz', null], key: 1, value: 123, }, ], }; test('for wrong items', () => { expect( schema['~run']({ value: ['foo', 123, 'baz', null] }, {}) ).toStrictEqual({ typed: false, value: ['foo', 123, 'baz', null], issues: [ stringIssue, { ...baseInfo, kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', path: [ { type: 'array', origin: 'value', input: ['foo', 123, 'baz', null], key: 3, value: null, }, ], }, ], } satisfies FailureDataset>); }); test('with abort early', () => { expect( schema['~run']( { value: ['foo', 123, 'baz', null] }, { abortEarly: true } ) ).toStrictEqual({ typed: false, value: ['foo'], issues: [{ ...stringIssue, abortEarly: true }], } satisfies FailureDataset>); }); test('for wrong nested items', () => { const nestedSchema = array(schema); expect( nestedSchema['~run']({ value: [[123, 'foo'], 'bar', []] }, {}) ).toStrictEqual({ typed: false, value: [[123, 'foo'], 'bar', []], issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'array', origin: 'value', input: [[123, 'foo'], 'bar', []], key: 0, value: [123, 'foo'], }, { type: 'array', origin: 'value', input: [123, 'foo'], key: 0, value: 123, }, ], }, { ...baseInfo, kind: 'schema', type: 'array', input: 'bar', expected: 'Array', received: '"bar"', path: [ { type: 'array', origin: 'value', input: [[123, 'foo'], 'bar', []], key: 1, value: 'bar', }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/array/array.ts ================================================ import type { ArrayPathItem, BaseIssue, BaseSchema, ErrorMessage, InferInput, InferIssue, InferOutput, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { ArrayIssue } from './types.ts'; /** * Array schema interface. */ export interface ArraySchema< TItem extends BaseSchema>, TMessage extends ErrorMessage | undefined, > extends BaseSchema< InferInput[], InferOutput[], ArrayIssue | InferIssue > { /** * The schema type. */ readonly type: 'array'; /** * The schema reference. */ readonly reference: typeof array; /** * The expected property. */ readonly expects: 'Array'; /** * The array item schema. */ readonly item: TItem; /** * The error message. */ readonly message: TMessage; } /** * Creates an array schema. * * @param item The item schema. * * @returns An array schema. */ export function array< const TItem extends BaseSchema>, >(item: TItem): ArraySchema; /** * Creates an array schema. * * @param item The item schema. * @param message The error message. * * @returns An array schema. */ export function array< const TItem extends BaseSchema>, const TMessage extends ErrorMessage | undefined, >(item: TItem, message: TMessage): ArraySchema; // @__NO_SIDE_EFFECTS__ export function array( item: BaseSchema>, message?: ErrorMessage ): ArraySchema< BaseSchema>, ErrorMessage | undefined > { return { kind: 'schema', type: 'array', reference: array, expects: 'Array', async: false, item, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (Array.isArray(input)) { // Set typed to `true` and value to empty array // @ts-expect-error dataset.typed = true; dataset.value = []; // Parse schema of each array item for (let key = 0; key < input.length; key++) { const value = input[key]; const itemDataset = this.item['~run']({ value }, config); // If there are issues, capture them if (itemDataset.issues) { // Create array path item const pathItem: ArrayPathItem = { type: 'array', origin: 'value', input, key, value, }; // Add modified item dataset issues to issues for (const issue of itemDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = itemDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!itemDataset.typed) { dataset.typed = false; } // Add item to dataset // @ts-expect-error dataset.value.push(itemDataset.value); } // Otherwise, add array issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< unknown[], ArrayIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/array/arrayAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { OptionalSchema } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { arrayAsync, type ArraySchemaAsync } from './arrayAsync.ts'; import type { ArrayIssue } from './types.ts'; describe('arrayAsync', () => { describe('should return schema object', () => { const item = string(); type Item = typeof item; test('with undefined message', () => { type Schema = ArraySchemaAsync; expectTypeOf(arrayAsync(item)).toEqualTypeOf(); expectTypeOf(arrayAsync(item, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(arrayAsync(item, 'message')).toEqualTypeOf< ArraySchemaAsync >(); }); test('with function message', () => { expectTypeOf(arrayAsync(item, () => 'message')).toEqualTypeOf< ArraySchemaAsync string> >(); }); }); describe('should infer correct types', () => { type Schema = ArraySchemaAsync< OptionalSchema, 'foo'>, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf< (string | undefined)[] >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< ArrayIssue | StringIssue >(); }); }); }); ================================================ FILE: library/src/schemas/array/arrayAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { string, type StringIssue } from '../string/index.ts'; import { arrayAsync, type ArraySchemaAsync } from './arrayAsync.ts'; import type { ArrayIssue } from './types.ts'; describe('array', () => { describe('should return schema object', () => { const item = string(); type Item = typeof item; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'array', reference: arrayAsync, expects: 'Array', item, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: ArraySchemaAsync = { ...baseSchema, message: undefined, }; expect(arrayAsync(item)).toStrictEqual(schema); expect(arrayAsync(item, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(arrayAsync(item, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies ArraySchemaAsync); }); test('with function message', () => { const message = () => 'message'; expect(arrayAsync(item, message)).toStrictEqual({ ...baseSchema, message, } satisfies ArraySchemaAsync); }); }); describe('should return dataset without issues', () => { const schema = arrayAsync(string()); test('for empty array', async () => { await expectNoSchemaIssueAsync(schema, [[]]); }); test('for simple array', async () => { await expectNoSchemaIssueAsync(schema, [['foo', 'bar', 'baz']]); }); }); describe('should return dataset with issues', () => { const schema = arrayAsync(string(), 'message'); const baseIssue: Omit = { kind: 'schema', type: 'array', expected: 'Array', message: 'message', }; // Primitive types test('for bigints', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', async () => { await expectSchemaIssueAsync(schema, baseIssue, [true, false]); }); test('for null', async () => { await expectSchemaIssueAsync(schema, baseIssue, [null]); }); test('for numbers', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', async () => { await expectSchemaIssueAsync(schema, baseIssue, [undefined]); }); test('for strings', async () => { await expectSchemaIssueAsync(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ Symbol(), Symbol('foo'), ]); }); // Complex types test('for functions', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ // eslint-disable-next-line @typescript-eslint/no-empty-function () => {}, // eslint-disable-next-line @typescript-eslint/no-empty-function function () {}, ]); }); test('for objects', async () => { await expectSchemaIssueAsync(schema, baseIssue, [{}, { key: 'value' }]); }); }); describe('should return dataset without nested issues', () => { const schema = arrayAsync(string()); test('for simple array', async () => { await expectNoSchemaIssueAsync(schema, [['foo', 'bar', 'baz']]); }); test('for nested array', async () => { await expectNoSchemaIssueAsync(arrayAsync(schema), [ [['foo', 'bar'], ['baz']], ]); }); }); describe('should return dataset with nested issues', () => { const schema = arrayAsync(string()); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const stringIssue: StringIssue = { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'array', origin: 'value', input: ['foo', 123, 'baz', null], key: 1, value: 123, }, ], }; test('for wrong items', async () => { expect( await schema['~run']({ value: ['foo', 123, 'baz', null] }, {}) ).toStrictEqual({ typed: false, value: ['foo', 123, 'baz', null], issues: [ stringIssue, { ...baseInfo, kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', path: [ { type: 'array', origin: 'value', input: ['foo', 123, 'baz', null], key: 3, value: null, }, ], }, ], } satisfies FailureDataset>); }); test('with abort early', async () => { expect( await schema['~run']( { value: ['foo', 123, 'baz', null] }, { abortEarly: true } ) ).toStrictEqual({ typed: false, value: ['foo'], issues: [{ ...stringIssue, abortEarly: true }], } satisfies FailureDataset>); }); test('for wrong nested items', async () => { const nestedSchema = arrayAsync(schema); expect( await nestedSchema['~run']({ value: [[123, 'foo'], 'bar', []] }, {}) ).toStrictEqual({ typed: false, value: [[123, 'foo'], 'bar', []], issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'array', origin: 'value', input: [[123, 'foo'], 'bar', []], key: 0, value: [123, 'foo'], }, { type: 'array', origin: 'value', input: [123, 'foo'], key: 0, value: 123, }, ], }, { ...baseInfo, kind: 'schema', type: 'array', input: 'bar', expected: 'Array', received: '"bar"', path: [ { type: 'array', origin: 'value', input: [[123, 'foo'], 'bar', []], key: 1, value: 'bar', }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/array/arrayAsync.ts ================================================ import type { ArrayPathItem, BaseIssue, BaseSchema, BaseSchemaAsync, ErrorMessage, InferInput, InferIssue, InferOutput, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { array } from './array.ts'; import type { ArrayIssue } from './types.ts'; /** * Array schema interface. */ export interface ArraySchemaAsync< TItem extends | BaseSchema> | BaseSchemaAsync>, TMessage extends ErrorMessage | undefined, > extends BaseSchemaAsync< InferInput[], InferOutput[], ArrayIssue | InferIssue > { /** * The schema type. */ readonly type: 'array'; /** * The schema reference. */ readonly reference: typeof array | typeof arrayAsync; /** * The expected property. */ readonly expects: 'Array'; /** * The array item schema. */ readonly item: TItem; /** * The error message. */ readonly message: TMessage; } /** * Creates an array schema. * * @param item The item schema. * * @returns An array schema. */ export function arrayAsync< const TItem extends | BaseSchema> | BaseSchemaAsync>, >(item: TItem): ArraySchemaAsync; /** * Creates an array schema. * * @param item The item schema. * @param message The error message. * * @returns An array schema. */ export function arrayAsync< const TItem extends | BaseSchema> | BaseSchemaAsync>, const TMessage extends ErrorMessage | undefined, >(item: TItem, message: TMessage): ArraySchemaAsync; // @__NO_SIDE_EFFECTS__ export function arrayAsync( item: | BaseSchema> | BaseSchemaAsync>, message?: ErrorMessage ): ArraySchemaAsync< | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined > { return { kind: 'schema', type: 'array', reference: arrayAsync, expects: 'Array', async: true, item, message, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (Array.isArray(input)) { // Set typed to `true` and value to empty array // @ts-expect-error dataset.typed = true; dataset.value = []; // Parse schema of each item async const itemDatasets = await Promise.all( input.map((value) => this.item['~run']({ value }, config)) ); // Process each item dataset for (let key = 0; key < itemDatasets.length; key++) { // Get item dataset const itemDataset = itemDatasets[key]; // If there are issues, capture them if (itemDataset.issues) { // Create array path item const pathItem: ArrayPathItem = { type: 'array', origin: 'value', input, key, value: input[key], }; // Add modified item dataset issues to issues for (const issue of itemDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = itemDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!itemDataset.typed) { dataset.typed = false; } // Add item to dataset // @ts-expect-error dataset.value.push(itemDataset.value); } // Otherwise, add array issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< unknown[], ArrayIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/array/index.ts ================================================ export * from './array.ts'; export * from './arrayAsync.ts'; export * from './types.ts'; ================================================ FILE: library/src/schemas/array/types.ts ================================================ import type { BaseIssue } from '../../types/index.ts'; /** * Array issue interface. */ export interface ArrayIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'array'; /** * The expected property. */ readonly expected: 'Array'; } ================================================ FILE: library/src/schemas/bigint/bigint.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { bigint, type BigintIssue, type BigintSchema } from './bigint.ts'; describe('bigint', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = BigintSchema; expectTypeOf(bigint()).toEqualTypeOf(); expectTypeOf(bigint(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(bigint('message')).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf(bigint(() => 'message')).toEqualTypeOf< BigintSchema<() => string> >(); }); }); describe('should infer correct types', () => { type Schema = BigintSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/bigint/bigint.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { bigint, type BigintIssue, type BigintSchema } from './bigint.ts'; describe('bigint', () => { describe('should return schema object', () => { const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'bigint', reference: bigint, expects: 'bigint', async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: BigintSchema = { ...baseSchema, message: undefined, }; expect(bigint()).toStrictEqual(schema); expect(bigint(undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(bigint('message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies BigintSchema<'message'>); }); test('with function message', () => { const message = () => 'message'; expect(bigint(message)).toStrictEqual({ ...baseSchema, message, } satisfies BigintSchema); }); }); describe('should return dataset without issues', () => { const schema = bigint(); test('for bigint zero', () => { expectNoSchemaIssue(schema, [0n, -0n]); }); test('for positive bigints', () => { expectNoSchemaIssue(schema, [1n, 23n, 456n]); }); test('for negative bigints', () => { expectNoSchemaIssue(schema, [-1n, -23n, -456n]); }); }); describe('should return dataset with issues', () => { const schema = bigint('message'); const baseIssue: Omit = { kind: 'schema', type: 'bigint', expected: 'bigint', message: 'message', }; // Primitive types test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', '0', '-2', '12.34']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); }); ================================================ FILE: library/src/schemas/bigint/bigint.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; /** * Bigint issue interface. */ export interface BigintIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'bigint'; /** * The expected property. */ readonly expected: 'bigint'; } /** * Bigint schema interface. */ export interface BigintSchema< TMessage extends ErrorMessage | undefined, > extends BaseSchema { /** * The schema type. */ readonly type: 'bigint'; /** * The schema reference. */ readonly reference: typeof bigint; /** * The expected property. */ readonly expects: 'bigint'; /** * The error message. */ readonly message: TMessage; } /** * Creates a bigint schema. * * @returns A bigint schema. */ export function bigint(): BigintSchema; /** * Creates a bigint schema. * * @param message The error message. * * @returns A bigint schema. */ export function bigint< const TMessage extends ErrorMessage | undefined, >(message: TMessage): BigintSchema; // @__NO_SIDE_EFFECTS__ export function bigint( message?: ErrorMessage ): BigintSchema | undefined> { return { kind: 'schema', type: 'bigint', reference: bigint, expects: 'bigint', async: false, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { if (typeof dataset.value === 'bigint') { // @ts-expect-error dataset.typed = true; } else { _addIssue(this, 'type', dataset, config); } // @ts-expect-error return dataset as OutputDataset; }, }; } ================================================ FILE: library/src/schemas/bigint/index.ts ================================================ export * from './bigint.ts'; ================================================ FILE: library/src/schemas/blob/blob.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { blob, type BlobIssue, type BlobSchema } from './blob.ts'; describe('blob', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = BlobSchema; expectTypeOf(blob()).toEqualTypeOf(); expectTypeOf(blob(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(blob('message')).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf(blob(() => 'message')).toEqualTypeOf< BlobSchema<() => string> >(); }); }); describe('should infer correct types', () => { type Schema = BlobSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/blob/blob.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { blob, type BlobIssue, type BlobSchema } from './blob.ts'; describe('blob', () => { describe('should return schema object', () => { const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'blob', reference: blob, expects: 'Blob', async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: BlobSchema = { ...baseSchema, message: undefined, }; expect(blob()).toStrictEqual(schema); expect(blob(undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(blob('message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies BlobSchema<'message'>); }); test('with function message', () => { const message = () => 'message'; expect(blob(message)).toStrictEqual({ ...baseSchema, message, } satisfies BlobSchema); }); }); describe('should return dataset without issues', () => { const schema = blob(); test('for Blob objects', () => { expectNoSchemaIssue(schema, [new Blob(), new Blob(['foo'])]); }); test('for File objects', () => { expectNoSchemaIssue(schema, [new File(['foo'], 'foo.jpg')]); }); }); describe('should return dataset with issues', () => { const schema = blob('message'); const baseIssue: Omit = { kind: 'schema', type: 'blob', expected: 'Blob', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'foo', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); }); ================================================ FILE: library/src/schemas/blob/blob.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; /** * Blob issue interface. */ export interface BlobIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'blob'; /** * The expected property. */ readonly expected: 'Blob'; } /** * Blob schema interface. */ export interface BlobSchema< TMessage extends ErrorMessage | undefined, > extends BaseSchema { /** * The schema type. */ readonly type: 'blob'; /** * The schema reference. */ readonly reference: typeof blob; /** * The expected property. */ readonly expects: 'Blob'; /** * The error message. */ readonly message: TMessage; } /** * Creates a blob schema. * * @returns A blob schema. */ export function blob(): BlobSchema; /** * Creates a blob schema. * * @param message The error message. * * @returns A blob schema. */ export function blob< const TMessage extends ErrorMessage | undefined, >(message: TMessage): BlobSchema; // @__NO_SIDE_EFFECTS__ export function blob( message?: ErrorMessage ): BlobSchema | undefined> { return { kind: 'schema', type: 'blob', reference: blob, expects: 'Blob', async: false, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { if (dataset.value instanceof Blob) { // @ts-expect-error dataset.typed = true; } else { _addIssue(this, 'type', dataset, config); } // @ts-expect-error return dataset as OutputDataset; }, }; } ================================================ FILE: library/src/schemas/blob/index.ts ================================================ export * from './blob.ts'; ================================================ FILE: library/src/schemas/boolean/boolean.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { boolean, type BooleanIssue, type BooleanSchema } from './boolean.ts'; describe('boolean', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = BooleanSchema; expectTypeOf(boolean()).toEqualTypeOf(); expectTypeOf(boolean(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(boolean('message')).toEqualTypeOf< BooleanSchema<'message'> >(); }); test('with function message', () => { expectTypeOf(boolean(() => 'message')).toEqualTypeOf< BooleanSchema<() => string> >(); }); }); describe('should infer correct types', () => { type Schema = BooleanSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/boolean/boolean.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { boolean, type BooleanIssue, type BooleanSchema } from './boolean.ts'; describe('boolean', () => { describe('should return schema object', () => { const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'boolean', reference: boolean, expects: 'boolean', async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: BooleanSchema = { ...baseSchema, message: undefined, }; expect(boolean()).toStrictEqual(schema); expect(boolean(undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(boolean('message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies BooleanSchema<'message'>); }); test('with function message', () => { const message = () => 'message'; expect(boolean(message)).toStrictEqual({ ...baseSchema, message, } satisfies BooleanSchema); }); }); describe('should return dataset without issues', () => { const schema = boolean(); test('for true boolean', () => { expectNoSchemaIssue(schema, [true]); }); test('for false boolean', () => { expectNoSchemaIssue(schema, [false]); }); }); describe('should return dataset with issues', () => { const schema = boolean('message'); const baseIssue: Omit = { kind: 'schema', type: 'boolean', expected: 'boolean', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', '0', 'true', 'false']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); }); ================================================ FILE: library/src/schemas/boolean/boolean.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; /** * Boolean issue interface. */ export interface BooleanIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'boolean'; /** * The expected property. */ readonly expected: 'boolean'; } /** * Boolean schema interface. */ export interface BooleanSchema< TMessage extends ErrorMessage | undefined, > extends BaseSchema { /** * The schema type. */ readonly type: 'boolean'; /** * The schema reference. */ readonly reference: typeof boolean; /** * The expected property. */ readonly expects: 'boolean'; /** * The error message. */ readonly message: TMessage; } /** * Creates a boolean schema. * * @returns A boolean schema. */ export function boolean(): BooleanSchema; /** * Creates a boolean schema. * * @param message The error message. * * @returns A boolean schema. */ export function boolean< const TMessage extends ErrorMessage | undefined, >(message: TMessage): BooleanSchema; // @__NO_SIDE_EFFECTS__ export function boolean( message?: ErrorMessage ): BooleanSchema | undefined> { return { kind: 'schema', type: 'boolean', reference: boolean, expects: 'boolean', async: false, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { if (typeof dataset.value === 'boolean') { // @ts-expect-error dataset.typed = true; } else { _addIssue(this, 'type', dataset, config); } // @ts-expect-error return dataset as OutputDataset; }, }; } ================================================ FILE: library/src/schemas/boolean/index.ts ================================================ export * from './boolean.ts'; ================================================ FILE: library/src/schemas/custom/custom.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { custom, type CustomSchema } from './custom.ts'; import type { CustomIssue } from './types.ts'; describe('custom', () => { type PixelString = `${number}px`; const isPixelString = (input: unknown) => typeof input === 'string' && /^\d+px$/u.test(input); describe('should return schema object', () => { test('with undefined message', () => { type Schema = CustomSchema; expectTypeOf(custom(isPixelString)).toEqualTypeOf(); expectTypeOf( custom(isPixelString, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( custom(isPixelString, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( custom string>(isPixelString, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Schema = CustomSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/custom/custom.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { custom, type CustomSchema } from './custom.ts'; import type { CustomIssue } from './types.ts'; describe('custom', () => { type PixelString = `${number}px`; const isPixelString = (input: unknown) => typeof input === 'string' && /^\d+px$/u.test(input); describe('should return schema object', () => { const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'custom', reference: custom, expects: 'unknown', check: isPixelString, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: CustomSchema = { ...baseSchema, message: undefined, }; expect(custom(isPixelString)).toStrictEqual(schema); expect(custom(isPixelString, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(custom(isPixelString, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies CustomSchema); }); test('with function message', () => { const message = () => 'message'; expect(custom(isPixelString, message)).toStrictEqual({ ...baseSchema, message, } satisfies CustomSchema); }); }); describe('should return dataset without issues', () => { const schema = custom(isPixelString); test('for pixel strings', () => { expectNoSchemaIssue(schema, ['0px', '123px', '456789px']); }); }); describe('should return dataset with issues', () => { const schema = custom(isPixelString, 'message'); const baseIssue: Omit = { kind: 'schema', type: 'custom', expected: 'unknown', message: 'message', }; // Special values test('for invalid pixel strings', () => { expectSchemaIssue(schema, baseIssue, ['0', '0p', '0pxl', 'px', 'px0']); }); // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'foo', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); }); ================================================ FILE: library/src/schemas/custom/custom.ts ================================================ import type { BaseSchema, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { CustomIssue } from './types.ts'; /** * Check type. */ type Check = (input: unknown) => boolean; /** * Custom schema interface. */ export interface CustomSchema< TInput, TMessage extends ErrorMessage | undefined, > extends BaseSchema { /** * The schema type. */ readonly type: 'custom'; /** * The schema reference. */ readonly reference: typeof custom; /** * The expected property. */ readonly expects: 'unknown'; /** * The type check function. */ readonly check: Check; /** * The error message. */ readonly message: TMessage; } /** * Creates a custom schema. * * @param check The type check function. * * @returns A custom schema. */ export function custom(check: Check): CustomSchema; /** * Creates a custom schema. * * @param check The type check function. * @param message The error message. * * @returns A custom schema. */ export function custom< TInput, const TMessage extends ErrorMessage | undefined = | ErrorMessage | undefined, >(check: Check, message: TMessage): CustomSchema; // @__NO_SIDE_EFFECTS__ export function custom( check: Check, message?: ErrorMessage ): CustomSchema | undefined> { return { kind: 'schema', type: 'custom', reference: custom, expects: 'unknown', async: false, check, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { if (this.check(dataset.value)) { // @ts-expect-error dataset.typed = true; } else { _addIssue(this, 'type', dataset, config); } // @ts-expect-error return dataset as OutputDataset; }, }; } ================================================ FILE: library/src/schemas/custom/customAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { customAsync, type CustomSchemaAsync } from './customAsync.ts'; import type { CustomIssue } from './types.ts'; describe('customAsync', () => { type PixelString = `${number}px`; const isPixelString = async (input: unknown) => typeof input === 'string' && /^\d+px$/u.test(input); describe('should return schema object', () => { test('with undefined message', () => { type Schema = CustomSchemaAsync; expectTypeOf( customAsync(isPixelString) ).toEqualTypeOf(); expectTypeOf( customAsync(isPixelString, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( customAsync(isPixelString, 'message') ).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf( customAsync string>(isPixelString, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Schema = CustomSchemaAsync; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/custom/customAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { customAsync, type CustomSchemaAsync } from './customAsync.ts'; import type { CustomIssue } from './types.ts'; describe('customAsync', () => { type PixelString = `${number}px`; const isPixelString = async (input: unknown) => typeof input === 'string' && /^\d+px$/u.test(input); describe('should return schema object', () => { const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'custom', reference: customAsync, expects: 'unknown', check: isPixelString, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: CustomSchemaAsync = { ...baseSchema, message: undefined, }; expect(customAsync(isPixelString)).toStrictEqual(schema); expect(customAsync(isPixelString, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(customAsync(isPixelString, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies CustomSchemaAsync); }); test('with function message', () => { const message = () => 'message'; expect(customAsync(isPixelString, message)).toStrictEqual({ ...baseSchema, message, } satisfies CustomSchemaAsync); }); }); describe('should return dataset without issues', () => { const schema = customAsync(isPixelString); test('for pixel strings', async () => { await expectNoSchemaIssueAsync(schema, ['0px', '123px', '456789px']); }); }); describe('should return dataset with issues', () => { const schema = customAsync(isPixelString, 'message'); const baseIssue: Omit = { kind: 'schema', type: 'custom', expected: 'unknown', message: 'message', }; // Special values test('for invalid pixel strings', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ '0', '0p', '0pxl', 'px', 'px0', ]); }); // Primitive types test('for bigints', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', async () => { await expectSchemaIssueAsync(schema, baseIssue, [true, false]); }); test('for null', async () => { await expectSchemaIssueAsync(schema, baseIssue, [null]); }); test('for numbers', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', async () => { await expectSchemaIssueAsync(schema, baseIssue, [undefined]); }); test('for strings', async () => { await expectSchemaIssueAsync(schema, baseIssue, ['', 'foo', '123']); }); test('for symbols', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ Symbol(), Symbol('foo'), ]); }); // Complex types test('for arrays', async () => { await expectSchemaIssueAsync(schema, baseIssue, [[], ['value']]); }); test('for functions', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ // eslint-disable-next-line @typescript-eslint/no-empty-function () => {}, // eslint-disable-next-line @typescript-eslint/no-empty-function function () {}, ]); }); test('for objects', async () => { await expectSchemaIssueAsync(schema, baseIssue, [{}, { key: 'value' }]); }); }); }); ================================================ FILE: library/src/schemas/custom/customAsync.ts ================================================ import type { BaseSchemaAsync, ErrorMessage, MaybePromise, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { custom } from './custom.ts'; import type { CustomIssue } from './types.ts'; /** * Check async type. */ type CheckAsync = (input: unknown) => MaybePromise; /** * Custom schema async interface. */ export interface CustomSchemaAsync< TInput, TMessage extends ErrorMessage | undefined, > extends BaseSchemaAsync { /** * The schema type. */ readonly type: 'custom'; /** * The schema reference. */ readonly reference: typeof custom | typeof customAsync; /** * The expected property. */ readonly expects: 'unknown'; /** * The type check function. */ readonly check: CheckAsync; /** * The error message. */ readonly message: TMessage; } /** * Creates a custom schema. * * @param check The type check function. * * @returns A custom schema. */ export function customAsync( check: CheckAsync ): CustomSchemaAsync; /** * Creates a custom schema. * * @param check The type check function. * @param message The error message. * * @returns A custom schema. */ export function customAsync< TInput, const TMessage extends ErrorMessage | undefined = | ErrorMessage | undefined, >(check: CheckAsync, message: TMessage): CustomSchemaAsync; // @__NO_SIDE_EFFECTS__ export function customAsync( check: CheckAsync, message?: ErrorMessage ): CustomSchemaAsync | undefined> { return { kind: 'schema', type: 'custom', reference: customAsync, expects: 'unknown', async: true, check, message, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { if (await this.check(dataset.value)) { // @ts-expect-error dataset.typed = true; } else { _addIssue(this, 'type', dataset, config); } // @ts-expect-error return dataset as OutputDataset; }, }; } ================================================ FILE: library/src/schemas/custom/index.ts ================================================ export * from './custom.ts'; export * from './customAsync.ts'; export * from './types.ts'; ================================================ FILE: library/src/schemas/custom/types.ts ================================================ import type { BaseIssue } from '../../types/index.ts'; /** * Custom issue interface. */ export interface CustomIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'custom'; /** * The expected property. */ readonly expected: 'unknown'; } ================================================ FILE: library/src/schemas/date/date.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { date, type DateIssue, type DateSchema } from './date.ts'; describe('date', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = DateSchema; expectTypeOf(date()).toEqualTypeOf(); expectTypeOf(date(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(date('message')).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf(date(() => 'message')).toEqualTypeOf< DateSchema<() => string> >(); }); }); describe('should infer correct types', () => { type Schema = DateSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/date/date.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { date, type DateIssue, type DateSchema } from './date.ts'; describe('date', () => { describe('should return schema object', () => { const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'date', reference: date, expects: 'Date', async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: DateSchema = { ...baseSchema, message: undefined, }; expect(date()).toStrictEqual(schema); expect(date(undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(date('message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies DateSchema<'message'>); }); test('with function message', () => { const message = () => 'message'; expect(date(message)).toStrictEqual({ ...baseSchema, message, } satisfies DateSchema); }); }); describe('should return dataset without issues', () => { const schema = date(); test('for current date', () => { expectNoSchemaIssue(schema, [new Date()]); }); test('for past date', () => { expectNoSchemaIssue(schema, [new Date(0)]); }); test('for future date', () => { expectNoSchemaIssue(schema, [new Date(8640000000000000)]); }); }); describe('should return dataset with issues', () => { const schema = date('message'); const baseIssue: Omit = { kind: 'schema', type: 'date', expected: 'Date', message: 'message', }; // Special values test('for invalid dates', () => { expectSchemaIssue(schema, baseIssue, [new Date('foo')], '"Invalid Date"'); }); // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'foo', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); }); ================================================ FILE: library/src/schemas/date/date.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; /** * Date issue interface. */ export interface DateIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'date'; /** * The expected property. */ readonly expected: 'Date'; } /** * Date schema interface. */ export interface DateSchema< TMessage extends ErrorMessage | undefined, > extends BaseSchema { /** * The schema type. */ readonly type: 'date'; /** * The schema reference. */ readonly reference: typeof date; /** * The expected property. */ readonly expects: 'Date'; /** * The error message. */ readonly message: TMessage; } /** * Creates a date schema. * * @returns A date schema. */ export function date(): DateSchema; /** * Creates a date schema. * * @param message The error message. * * @returns A date schema. */ export function date< const TMessage extends ErrorMessage | undefined, >(message: TMessage): DateSchema; // @__NO_SIDE_EFFECTS__ export function date( message?: ErrorMessage ): DateSchema | undefined> { return { kind: 'schema', type: 'date', reference: date, expects: 'Date', async: false, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { if (dataset.value instanceof Date) { // @ts-expect-error if (!isNaN(dataset.value)) { // @ts-expect-error dataset.typed = true; } else { _addIssue(this, 'type', dataset, config, { received: '"Invalid Date"', }); } } else { _addIssue(this, 'type', dataset, config); } // @ts-expect-error return dataset as OutputDataset; }, }; } ================================================ FILE: library/src/schemas/date/index.ts ================================================ export * from './date.ts'; ================================================ FILE: library/src/schemas/enum/enum.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { enum_, type EnumIssue, type EnumSchema } from './enum.ts'; describe('enum_', () => { enum normalEnum { option1 = 'foo', option2 = 'bar', option3 = 'baz', } type NormalEnum = typeof normalEnum; describe('should return schema object', () => { test('with undefined message', () => { type Schema = EnumSchema; expectTypeOf(enum_(normalEnum)).toEqualTypeOf(); expectTypeOf(enum_(normalEnum, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(enum_(normalEnum, 'message')).toEqualTypeOf< EnumSchema >(); }); test('with function message', () => { expectTypeOf(enum_(normalEnum, () => 'message')).toEqualTypeOf< EnumSchema string> >(); }); }); describe('should infer correct types', () => { type NormalEnumSchema = EnumSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); describe('should filter reverse mappings', () => { test('of special enums', () => { enum specialEnum { option1 = 'foo', option2 = 0, option3, 'Infinity', '-Infinity', 'NaN', } type SpecialEnum = typeof specialEnum; type SpecialEnumSchema = EnumSchema; expectTypeOf< InferInput >().toEqualTypeOf(); expectTypeOf< InferOutput >().toEqualTypeOf(); }); test('of normal enum-like object', () => { // eslint-disable-next-line @typescript-eslint/no-unused-vars const normalEnumLike = { option0: 'foo', option1: 1111, option2: 2222, option3: 3333, option4: 4444, option5: 5555, option6: -6666, // No reverse mappings foo: 'option0', // Key is not a number '+1111': 'option1', // Key is not a reverse mapped number 1234: 'option2', // Key does not match with reverse mapped value `2222` '5678': 'option3', // Key does not match with reverse mapped value `3333` // Reverse mappings 4444: 'option4', '5555': 'option5', '-6666': 'option6', } as const; type NormalEnumLike = typeof normalEnumLike; type NormalEnumLikeSchema = EnumSchema; expectTypeOf>().toEqualTypeOf< | 'foo' | 1111 | 2222 | 3333 | 4444 | 5555 | -6666 | 'option0' | 'option1' | 'option2' | 'option3' >(); expectTypeOf>().toEqualTypeOf< | 'foo' | 1111 | 2222 | 3333 | 4444 | 5555 | -6666 | 'option0' | 'option1' | 'option2' | 'option3' >(); }); test('of special enum-like object', () => { // eslint-disable-next-line @typescript-eslint/no-unused-vars const specialEnumLike = { option0: 'foo', option1: 1234, option2: Infinity, option3: -Infinity, option4: NaN, // Reverse mappings '1234': 'option1', Infinity: 'option2', '-Infinity': 'option3', NaN: 'option4', } as const; type SpecialEnumLike = typeof specialEnumLike; type SpecialEnumLikeSchema = EnumSchema; expectTypeOf>().toEqualTypeOf< 'foo' | number >(); expectTypeOf>().toEqualTypeOf< 'foo' | number >(); }); }); }); ================================================ FILE: library/src/schemas/enum/enum.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { enum_, type EnumIssue, type EnumSchema } from './enum.ts'; describe('enum_', () => { enum normalEnum { option1 = 'foo', option2 = 'bar', option3 = 'baz', } type Options = typeof normalEnum; describe('should return schema object', () => { const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'enum', reference: enum_, expects: '("foo" | "bar" | "baz")', enum: normalEnum, options: [normalEnum.option1, normalEnum.option2, normalEnum.option3], async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: EnumSchema = { ...baseSchema, message: undefined, }; expect(enum_(normalEnum)).toStrictEqual(schema); expect(enum_(normalEnum, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(enum_(normalEnum, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies EnumSchema); }); test('with function message', () => { const message = () => 'message'; expect(enum_(normalEnum, message)).toStrictEqual({ ...baseSchema, message, } satisfies EnumSchema); }); }); describe('should return dataset without issues', () => { test('for valid options', () => { expectNoSchemaIssue(enum_(normalEnum), [ normalEnum.option1, normalEnum.option2, normalEnum.option3, ]); }); test('for valid values', () => { // @ts-expect-error expectNoSchemaIssue(enum_(normalEnum), ['foo', 'bar', 'baz']); }); }); describe('should return dataset with issues', () => { const schema = enum_(normalEnum, 'message'); const baseIssue: Omit = { kind: 'schema', type: 'enum', expected: '("foo" | "bar" | "baz")', message: 'message', }; // Special values test('for empty options', () => { enum Empty {} expectSchemaIssue( enum_(Empty, 'message'), { ...baseIssue, expected: 'never' }, ['foo', 'bar', 'baz'] ); }); test('for invalid options', () => { expectSchemaIssue(schema, baseIssue, ['fo', 'fooo', 'foobar']); }); // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'hello', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); describe('should filter reverse mappings', () => { test('of special enums', () => { enum specialEnum { option1 = 'foo', option2 = 0, option3, 'Infinity', '-Infinity', 'NaN', } expect(enum_(specialEnum)).toMatchObject({ enum: specialEnum, expects: '("foo" | 0 | 1 | 2 | 3 | 4)', options: [ specialEnum.option1, specialEnum.option2, specialEnum.option3, specialEnum['Infinity'], specialEnum['-Infinity'], specialEnum['NaN'], ], } satisfies Pick< EnumSchema, 'enum' | 'expects' | 'options' >); }); test('of normal enum-like object', () => { const normalEnumLike = { option0: 'foo', option1: 1111, option2: 2222, option3: 3333, option4: 4444, option5: 5555, option6: -6666, // No reverse mappings foo: 'option0', // Key is not a number '+1111': 'option1', // Key is not a reverse mapped number 1234: 'option2', // Key does not match with reverse mapped value `2222` '5678': 'option3', // Key does not match with reverse mapped value `3333` // Reverse mappings 4444: 'option4', '5555': 'option5', '-6666': 'option6', } as const; expect(enum_(normalEnumLike)).toMatchObject({ enum: normalEnumLike, expects: '("option2" | "option3" | "foo" | 1111 | 2222 | 3333 | 4444 | 5555 | -6666 | "option0" | "option1")', options: [ 'option2', 'option3', 'foo', 1111, 2222, 3333, 4444, 5555, -6666, 'option0', 'option1', ], } satisfies Pick< EnumSchema, 'expects' | 'enum' | 'options' >); }); test('of special enum-like object', () => { const specialEnumLike = { option0: 'foo', option1: 1234, option2: Infinity, option3: -Infinity, option4: NaN, // Reverse mappings '1234': 'option1', Infinity: 'option2', '-Infinity': 'option3', NaN: 'option4', } as const; expect(enum_(specialEnumLike)).toMatchObject({ enum: specialEnumLike, expects: '("foo" | 1234 | Infinity | -Infinity | NaN)', options: ['foo', 1234, Infinity, -Infinity, NaN], } satisfies Pick< EnumSchema, 'expects' | 'enum' | 'options' >); }); }); }); ================================================ FILE: library/src/schemas/enum/enum.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps, _joinExpects, _stringify, } from '../../utils/index.ts'; /** * Enum interface. */ export interface Enum { [key: string]: string | number; } /** * Enum values type. */ export type EnumValues = { [TKey in keyof TEnum]: TKey extends number ? TEnum[TKey] extends string ? TEnum[TEnum[TKey]] extends TKey ? never : TEnum[TKey] : TEnum[TKey] : TKey extends 'NaN' | 'Infinity' | '-Infinity' ? TEnum[TKey] extends string ? TEnum[TEnum[TKey]] extends number ? never : TEnum[TKey] : TEnum[TKey] : TKey extends `+${number}` ? TEnum[TKey] : TKey extends `${infer TNumber extends number}` ? TEnum[TKey] extends string ? TEnum[TEnum[TKey]] extends TNumber ? never : TEnum[TKey] : TEnum[TKey] : TEnum[TKey]; }[keyof TEnum]; /** * Enum issue interface. */ export interface EnumIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'enum'; /** * The expected property. */ readonly expected: string; } /** * Enum schema interface. */ export interface EnumSchema< TEnum extends Enum, TMessage extends ErrorMessage | undefined, > extends BaseSchema, EnumValues, EnumIssue> { /** * The schema type. */ readonly type: 'enum'; /** * The schema reference. */ readonly reference: typeof enum_; /** * The enum object. */ readonly enum: TEnum; /** * The enum options. */ readonly options: EnumValues[]; /** * The error message. */ readonly message: TMessage; } /** * Creates an enum schema. * * @param enum__ The enum object. * * @returns An enum schema. */ export function enum_( enum__: TEnum ): EnumSchema; /** * Creates an enum schema. * * @param enum__ The enum object. * @param message The error message. * * @returns An enum schema. */ export function enum_< const TEnum extends Enum, const TMessage extends ErrorMessage | undefined, >(enum__: TEnum, message: TMessage): EnumSchema; // @__NO_SIDE_EFFECTS__ export function enum_( enum__: Enum, message?: ErrorMessage ): EnumSchema | undefined> { const options: EnumValues[] = []; for (const key in enum__) { if ( `${+key}` !== key || typeof enum__[key] !== 'string' || !Object.is(enum__[enum__[key]], +key) ) { options.push(enum__[key]); } } return { kind: 'schema', type: 'enum', reference: enum_, expects: _joinExpects(options.map(_stringify), '|'), async: false, enum: enum__, options, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // @ts-expect-error if (this.options.includes(dataset.value)) { // @ts-expect-error dataset.typed = true; } else { _addIssue(this, 'type', dataset, config); } // @ts-expect-error return dataset as OutputDataset; }, }; } export { enum_ as enum }; ================================================ FILE: library/src/schemas/enum/index.ts ================================================ export * from './enum.ts'; ================================================ FILE: library/src/schemas/exactOptional/exactOptional.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { TransformAction } from '../../actions/index.ts'; import type { SchemaWithPipe } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { ArrayIssue, ArraySchema } from '../array/index.ts'; import type { ObjectIssue, ObjectSchema } from '../object/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { exactOptional, type ExactOptionalSchema } from './exactOptional.ts'; describe('exactOptional', () => { describe('should return schema object', () => { test('with undefined default', () => { type Schema = ExactOptionalSchema, undefined>; expectTypeOf(exactOptional(string())).toEqualTypeOf(); expectTypeOf(exactOptional(string(), undefined)).toEqualTypeOf(); }); test('with value default', () => { expectTypeOf(exactOptional(string(), 'foo')).toEqualTypeOf< ExactOptionalSchema, 'foo'> >(); }); test('with value getter default', () => { expectTypeOf(exactOptional(string(), () => 'foo')).toEqualTypeOf< ExactOptionalSchema, () => string> >(); }); }); describe('should infer correct types', () => { type Schema1 = ExactOptionalSchema, undefined>; type Schema2 = ExactOptionalSchema, 'foo'>; type Schema3 = ExactOptionalSchema, () => 'foo'>; type Schema4 = ExactOptionalSchema< SchemaWithPipe< [StringSchema, TransformAction] >, 'foo' >; type Schema5 = ExactOptionalSchema< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, { foo: string[] } >; type Schema6 = ExactOptionalSchema< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, () => { foo: string[] } >; test('of input', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); }); }); }); ================================================ FILE: library/src/schemas/exactOptional/exactOptional.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { exactOptional, type ExactOptionalSchema } from './exactOptional.ts'; describe('exactOptional', () => { describe('should return schema object', () => { const baseSchema: Omit< ExactOptionalSchema, string>, 'default' > = { kind: 'schema', type: 'exact_optional', reference: exactOptional, expects: 'string', wrapped: { ...string(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined default', () => { const expected: ExactOptionalSchema< StringSchema, undefined > = { ...baseSchema, default: undefined, }; expect(exactOptional(string())).toStrictEqual(expected); expect(exactOptional(string(), undefined)).toStrictEqual(expected); }); test('with value default', () => { expect(exactOptional(string(), 'foo')).toStrictEqual({ ...baseSchema, default: 'foo', } satisfies ExactOptionalSchema, 'foo'>); }); test('with value getter default', () => { const getter = () => 'foo'; expect(exactOptional(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies ExactOptionalSchema, typeof getter>); }); }); describe('should return dataset without issues', () => { const schema = exactOptional(string()); test('for wrapper type', () => { expectNoSchemaIssue(schema, ['', 'foo', '#$%']); }); }); describe('should return dataset with issues', () => { const schema = exactOptional(string('message')); const baseIssue: Omit = { kind: 'schema', type: 'string', expected: 'string', message: 'message', }; test('for invalid wrapper type', () => { expectSchemaIssue(schema, baseIssue, [123, true, {}]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); }); describe('should return dataset without default', () => { test('for undefined default', () => { expectNoSchemaIssue(exactOptional(string()), ['foo']); expectNoSchemaIssue(exactOptional(string(), undefined), ['foo']); }); test('for wrapper type', () => { expectNoSchemaIssue(exactOptional(string(), 'foo'), ['', 'bar', '#$%']); }); }); }); ================================================ FILE: library/src/schemas/exactOptional/exactOptional.ts ================================================ import type { BaseIssue, BaseSchema, Default, InferInput, InferIssue, InferOutput, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; /** * Exact optional schema interface. */ export interface ExactOptionalSchema< TWrapped extends BaseSchema>, TDefault extends Default, > extends BaseSchema< InferInput, InferOutput, InferIssue > { /** * The schema type. */ readonly type: 'exact_optional'; /** * The schema reference. */ readonly reference: typeof exactOptional; /** * The expected property. */ readonly expects: TWrapped['expects']; /** * The wrapped schema. */ readonly wrapped: TWrapped; /** * The default value. */ readonly default: TDefault; } /** * Creates an exact optional schema. * * @param wrapped The wrapped schema. * * @returns An exact optional schema. */ export function exactOptional< const TWrapped extends BaseSchema>, >(wrapped: TWrapped): ExactOptionalSchema; /** * Creates an exact optional schema. * * @param wrapped The wrapped schema. * @param default_ The default value. * * @returns An exact optional schema. */ export function exactOptional< const TWrapped extends BaseSchema>, const TDefault extends Default, >( wrapped: TWrapped, default_: TDefault ): ExactOptionalSchema; // @__NO_SIDE_EFFECTS__ export function exactOptional( wrapped: BaseSchema>, default_?: unknown ): ExactOptionalSchema< BaseSchema>, unknown > { return { kind: 'schema', type: 'exact_optional', reference: exactOptional, expects: wrapped.expects, async: false, wrapped, default: default_, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { return this.wrapped['~run'](dataset, config); }, }; } ================================================ FILE: library/src/schemas/exactOptional/exactOptionalAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { TransformActionAsync } from '../../actions/index.ts'; import type { SchemaWithPipeAsync } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { ArrayIssue, ArraySchema } from '../array/index.ts'; import type { ObjectIssue, ObjectSchema } from '../object/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { exactOptionalAsync, type ExactOptionalSchemaAsync, } from './exactOptionalAsync.ts'; describe('exactOptionalAsync', () => { describe('should return schema object', () => { test('with undefined default', () => { type Schema = ExactOptionalSchemaAsync< StringSchema, undefined >; expectTypeOf(exactOptionalAsync(string())).toEqualTypeOf(); expectTypeOf( exactOptionalAsync(string(), undefined) ).toEqualTypeOf(); }); test('with value default', () => { expectTypeOf(exactOptionalAsync(string(), 'foo')).toEqualTypeOf< ExactOptionalSchemaAsync, 'foo'> >(); }); test('with value getter default', () => { expectTypeOf(exactOptionalAsync(string(), () => 'foo')).toEqualTypeOf< ExactOptionalSchemaAsync, () => string> >(); }); test('with async value getter default', () => { expectTypeOf( exactOptionalAsync(string(), async () => 'foo') ).toEqualTypeOf< ExactOptionalSchemaAsync, () => Promise> >(); }); }); describe('should infer correct types', () => { type Schema1 = ExactOptionalSchemaAsync, undefined>; type Schema2 = ExactOptionalSchemaAsync, 'foo'>; type Schema3 = ExactOptionalSchemaAsync< StringSchema, () => 'foo' >; type Schema4 = ExactOptionalSchemaAsync< StringSchema, () => Promise<'foo'> >; type Schema5 = ExactOptionalSchemaAsync< SchemaWithPipeAsync< [StringSchema, TransformActionAsync] >, 'foo' >; type Schema6 = ExactOptionalSchemaAsync< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, { foo: string[] } >; type Schema7 = ExactOptionalSchemaAsync< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, () => { foo: string[] } >; type Schema8 = ExactOptionalSchemaAsync< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, () => Promise<{ foo: string[] }> >; test('of input', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); }); }); }); ================================================ FILE: library/src/schemas/exactOptional/exactOptionalAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { exactOptionalAsync, type ExactOptionalSchemaAsync, } from './exactOptionalAsync.ts'; describe('exactOptionalAsync', () => { describe('should return schema object', () => { const baseSchema: Omit< ExactOptionalSchemaAsync, string>, 'default' > = { kind: 'schema', type: 'exact_optional', reference: exactOptionalAsync, expects: 'string', wrapped: { ...string(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined default', () => { const expected: ExactOptionalSchemaAsync< StringSchema, undefined > = { ...baseSchema, default: undefined, }; expect(exactOptionalAsync(string())).toStrictEqual(expected); expect(exactOptionalAsync(string(), undefined)).toStrictEqual(expected); }); test('with value default', () => { expect(exactOptionalAsync(string(), 'foo')).toStrictEqual({ ...baseSchema, default: 'foo', } satisfies ExactOptionalSchemaAsync, 'foo'>); }); test('with value getter default', () => { const getter = () => 'foo'; expect(exactOptionalAsync(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies ExactOptionalSchemaAsync< StringSchema, typeof getter >); }); test('with async value getter default', () => { const getter = async () => 'foo'; expect(exactOptionalAsync(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies ExactOptionalSchemaAsync< StringSchema, typeof getter >); }); }); describe('should return dataset without issues', () => { const schema = exactOptionalAsync(string()); test('for wrapper type', async () => { await expectNoSchemaIssueAsync(schema, ['', 'foo', '#$%']); }); }); describe('should return dataset with issues', () => { const schema = exactOptionalAsync(string('message')); const baseIssue: Omit = { kind: 'schema', type: 'string', expected: 'string', message: 'message', }; test('for invalid wrapper type', async () => { await expectSchemaIssueAsync(schema, baseIssue, [123, true, {}]); }); test('for null', async () => { await expectSchemaIssueAsync(schema, baseIssue, [null]); }); test('for undefined', async () => { await expectSchemaIssueAsync(schema, baseIssue, [undefined]); }); }); describe('should return dataset without default', () => { test('for undefined default', async () => { await expectNoSchemaIssueAsync(exactOptionalAsync(string()), ['foo']); await expectNoSchemaIssueAsync(exactOptionalAsync(string(), undefined), [ 'foo', ]); }); test('for wrapper type', async () => { await expectNoSchemaIssueAsync(exactOptionalAsync(string(), 'foo'), [ '', 'bar', '#$%', ]); }); }); }); ================================================ FILE: library/src/schemas/exactOptional/exactOptionalAsync.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, DefaultAsync, InferInput, InferIssue, InferOutput, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; import type { exactOptional } from './exactOptional.ts'; /** * Exact optional schema async interface. */ export interface ExactOptionalSchemaAsync< TWrapped extends | BaseSchema> | BaseSchemaAsync>, TDefault extends DefaultAsync, > extends BaseSchemaAsync< InferInput, InferOutput, InferIssue > { /** * The schema type. */ readonly type: 'exact_optional'; /** * The schema reference. */ readonly reference: typeof exactOptional | typeof exactOptionalAsync; /** * The expected property. */ readonly expects: TWrapped['expects']; /** * The wrapped schema. */ readonly wrapped: TWrapped; /** * The default value. */ readonly default: TDefault; } /** * Creates an exact optional schema. * * @param wrapped The wrapped schema. * * @returns An exact optional schema. */ export function exactOptionalAsync< const TWrapped extends | BaseSchema> | BaseSchemaAsync>, >(wrapped: TWrapped): ExactOptionalSchemaAsync; /** * Creates an exact optional schema. * * @param wrapped The wrapped schema. * @param default_ The default value. * * @returns An exact optional schema. */ export function exactOptionalAsync< const TWrapped extends | BaseSchema> | BaseSchemaAsync>, const TDefault extends DefaultAsync, >( wrapped: TWrapped, default_: TDefault ): ExactOptionalSchemaAsync; // @__NO_SIDE_EFFECTS__ export function exactOptionalAsync( wrapped: | BaseSchema> | BaseSchemaAsync>, default_?: unknown ): ExactOptionalSchemaAsync< | BaseSchema> | BaseSchemaAsync>, unknown > { return { kind: 'schema', type: 'exact_optional', reference: exactOptionalAsync, expects: wrapped.expects, async: true, wrapped, default: default_, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { return this.wrapped['~run'](dataset, config); }, }; } ================================================ FILE: library/src/schemas/exactOptional/index.ts ================================================ export * from './exactOptional.ts'; export * from './exactOptionalAsync.ts'; ================================================ FILE: library/src/schemas/file/file.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { file, type FileIssue, type FileSchema } from './file.ts'; describe('file', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = FileSchema; expectTypeOf(file()).toEqualTypeOf(); expectTypeOf(file(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(file('message')).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf(file(() => 'message')).toEqualTypeOf< FileSchema<() => string> >(); }); }); describe('should infer correct types', () => { type Schema = FileSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/file/file.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { file, type FileIssue, type FileSchema } from './file.ts'; describe('file', () => { describe('should return schema object', () => { const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'file', reference: file, expects: 'File', async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: FileSchema = { ...baseSchema, message: undefined, }; expect(file()).toStrictEqual(schema); expect(file(undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(file('message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies FileSchema<'message'>); }); test('with function message', () => { const message = () => 'message'; expect(file(message)).toStrictEqual({ ...baseSchema, message, } satisfies FileSchema); }); }); describe('should return dataset without issues', () => { const schema = file(); test('for File objects', () => { expectNoSchemaIssue(schema, [ new File([], 'empty.txt'), new File(['foo'], 'foo.jpg'), ]); }); }); describe('should return dataset with issues', () => { const schema = file('message'); const baseIssue: Omit = { kind: 'schema', type: 'file', expected: 'File', message: 'message', }; // Special values test('for blobs', () => { expectSchemaIssue(schema, baseIssue, [new Blob(), new Blob(['foo'])]); }); // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'foo', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); }); ================================================ FILE: library/src/schemas/file/file.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; /** * File issue interface. */ export interface FileIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'file'; /** * The expected property. */ readonly expected: 'File'; } /** * File schema interface. */ export interface FileSchema< TMessage extends ErrorMessage | undefined, > extends BaseSchema { /** * The schema type. */ readonly type: 'file'; /** * The schema reference. */ readonly reference: typeof file; /** * The expected property. */ readonly expects: 'File'; /** * The error message. */ readonly message: TMessage; } /** * Creates a file schema. * * @returns A file schema. */ export function file(): FileSchema; /** * Creates a file schema. * * @param message The error message. * * @returns A file schema. */ export function file< const TMessage extends ErrorMessage | undefined, >(message: TMessage): FileSchema; // @__NO_SIDE_EFFECTS__ export function file( message?: ErrorMessage ): FileSchema | undefined> { return { kind: 'schema', type: 'file', reference: file, expects: 'File', async: false, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { if (dataset.value instanceof File) { // @ts-expect-error dataset.typed = true; } else { _addIssue(this, 'type', dataset, config); } // @ts-expect-error return dataset as OutputDataset; }, }; } ================================================ FILE: library/src/schemas/file/index.ts ================================================ export * from './file.ts'; ================================================ FILE: library/src/schemas/function/function.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { function_, type FunctionIssue, type FunctionSchema, } from './function.ts'; describe('function', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = FunctionSchema; expectTypeOf(function_()).toEqualTypeOf(); expectTypeOf(function_(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(function_('message')).toEqualTypeOf< FunctionSchema<'message'> >(); }); test('with function message', () => { expectTypeOf(function_(() => 'message')).toEqualTypeOf< FunctionSchema<() => string> >(); }); }); describe('should infer correct types', () => { type Schema = FunctionSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf< (...args: unknown[]) => unknown >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< (...args: unknown[]) => unknown >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/function/function.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { function_, type FunctionIssue, type FunctionSchema, } from './function.ts'; describe('function', () => { describe('should return schema object', () => { const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'function', reference: function_, expects: 'Function', async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: FunctionSchema = { ...baseSchema, message: undefined, }; expect(function_()).toStrictEqual(schema); expect(function_(undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(function_('message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies FunctionSchema<'message'>); }); test('with function message', () => { const message = () => 'message'; expect(function_(message)).toStrictEqual({ ...baseSchema, message, } satisfies FunctionSchema); }); }); describe('should return dataset without issues', () => { const schema = function_(); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectNoSchemaIssue(schema, [() => {}, function () {}]); }); }); describe('should return dataset with issues', () => { const schema = function_('message'); const baseIssue: Omit = { kind: 'schema', type: 'function', expected: 'Function', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'foo', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); }); ================================================ FILE: library/src/schemas/function/function.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; /** * Function issue interface. */ export interface FunctionIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'function'; /** * The expected property. */ readonly expected: 'Function'; } /** * Function schema interface. */ export interface FunctionSchema< TMessage extends ErrorMessage | undefined, > extends BaseSchema< (...args: unknown[]) => unknown, (...args: unknown[]) => unknown, FunctionIssue > { /** * The schema type. */ readonly type: 'function'; /** * The schema reference. */ readonly reference: typeof function_; /** * The expected property. */ readonly expects: 'Function'; /** * The error message. */ readonly message: TMessage; } /** * Creates a function schema. * * @returns A function schema. */ export function function_(): FunctionSchema; /** * Creates a function schema. * * @param message The error message. * * @returns A function schema. */ export function function_< const TMessage extends ErrorMessage | undefined, >(message: TMessage): FunctionSchema; // @__NO_SIDE_EFFECTS__ export function function_( message?: ErrorMessage ): FunctionSchema | undefined> { return { kind: 'schema', type: 'function', reference: function_, expects: 'Function', async: false, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { if (typeof dataset.value === 'function') { // @ts-expect-error dataset.typed = true; } else { _addIssue(this, 'type', dataset, config); } // @ts-expect-error return dataset as OutputDataset< (...args: unknown[]) => unknown, FunctionIssue >; }, }; } export { function_ as function }; ================================================ FILE: library/src/schemas/function/index.ts ================================================ export * from './function.ts'; ================================================ FILE: library/src/schemas/index.ts ================================================ export * from './any/index.ts'; export * from './array/index.ts'; export * from './bigint/index.ts'; export * from './blob/index.ts'; export * from './boolean/index.ts'; export * from './custom/index.ts'; export * from './date/index.ts'; export * from './enum/index.ts'; export * from './exactOptional/index.ts'; export * from './file/index.ts'; export * from './function/index.ts'; export * from './instance/index.ts'; export * from './intersect/index.ts'; export * from './lazy/index.ts'; export * from './literal/index.ts'; export * from './looseObject/index.ts'; export * from './looseTuple/index.ts'; export * from './map/index.ts'; export * from './nan/index.ts'; export * from './never/index.ts'; export * from './nonNullable/index.ts'; export * from './nonNullish/index.ts'; export * from './nonOptional/index.ts'; export * from './null/index.ts'; export * from './nullable/index.ts'; export * from './nullish/index.ts'; export * from './number/index.ts'; export * from './object/index.ts'; export * from './objectWithRest/index.ts'; export * from './optional/index.ts'; export * from './picklist/index.ts'; export * from './promise/index.ts'; export * from './record/index.ts'; export * from './set/index.ts'; export * from './strictObject/index.ts'; export * from './strictTuple/index.ts'; export * from './string/index.ts'; export * from './symbol/index.ts'; export * from './tuple/index.ts'; export * from './tupleWithRest/index.ts'; export * from './undefined/index.ts'; export * from './undefinedable/index.ts'; export * from './union/index.ts'; export * from './unknown/index.ts'; export * from './variant/index.ts'; export * from './void/index.ts'; ================================================ FILE: library/src/schemas/instance/index.ts ================================================ export * from './instance.ts'; ================================================ FILE: library/src/schemas/instance/instance.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { instance, type InstanceIssue, type InstanceSchema, } from './instance.ts'; describe('DateConstructor', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = InstanceSchema; expectTypeOf(instance(Date)).toEqualTypeOf(); expectTypeOf(instance(Date, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(instance(Date, 'message')).toEqualTypeOf< InstanceSchema >(); }); test('with function message', () => { expectTypeOf(instance(Date, () => 'message')).toEqualTypeOf< InstanceSchema string> >(); }); }); describe('should infer correct types', () => { type Schema = InstanceSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/instance/instance.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { instance, type InstanceIssue, type InstanceSchema, } from './instance.ts'; describe('instance', () => { describe('should return schema object', () => { const baseSchema: Omit< InstanceSchema, 'message' > = { kind: 'schema', type: 'instance', reference: instance, expects: 'Date', class: Date, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: InstanceSchema = { ...baseSchema, message: undefined, }; expect(instance(Date)).toStrictEqual(schema); expect(instance(Date, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(instance(Date, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies InstanceSchema); }); test('with function message', () => { const message = () => 'message'; expect(instance(Date, message)).toStrictEqual({ ...baseSchema, message, } satisfies InstanceSchema); }); }); describe('should return dataset without issues', () => { const schema = instance(Date); test('for valid instances', () => { expectNoSchemaIssue(schema, [new Date(), new Date(123456789)]); }); }); describe('should return dataset with issues', () => { const schema = instance(Date, 'message'); const baseIssue: Omit = { kind: 'schema', type: 'instance', expected: 'Date', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'foo', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); }); ================================================ FILE: library/src/schemas/instance/instance.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; /** * Class type. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export type Class = new (...args: any[]) => any; /** * Instance issue interface. */ export interface InstanceIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'instance'; /** * The expected property. */ readonly expected: string; } /** * Instance schema interface. */ export interface InstanceSchema< TClass extends Class, TMessage extends ErrorMessage | undefined, > extends BaseSchema< InstanceType, InstanceType, InstanceIssue > { /** * The schema type. */ readonly type: 'instance'; /** * The schema reference. */ readonly reference: typeof instance; /** * The class of the instance. */ readonly class: TClass; /** * The error message. */ readonly message: TMessage; } /** * Creates an instance schema. * * @param class_ The class of the instance. * * @returns An instance schema. */ export function instance( class_: TClass ): InstanceSchema; /** * Creates an instance schema. * * @param class_ The class of the instance. * @param message The error message. * * @returns An instance schema. */ export function instance< TClass extends Class, const TMessage extends ErrorMessage | undefined, >(class_: TClass, message: TMessage): InstanceSchema; // @__NO_SIDE_EFFECTS__ export function instance( class_: Class, message?: ErrorMessage ): InstanceSchema | undefined> { return { kind: 'schema', type: 'instance', reference: instance, expects: class_.name, async: false, class: class_, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { if (dataset.value instanceof this.class) { // @ts-expect-error dataset.typed = true; } else { _addIssue(this, 'type', dataset, config); } // @ts-expect-error return dataset as OutputDataset, InstanceIssue>; }, }; } ================================================ FILE: library/src/schemas/intersect/index.ts ================================================ export * from './intersect.ts'; export * from './intersectAsync.ts'; export type { IntersectIssue, IntersectOptions, IntersectOptionsAsync, } from './types.ts'; ================================================ FILE: library/src/schemas/intersect/intersect.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { array, type ArrayIssue } from '../array/index.ts'; import { number, type NumberIssue } from '../number/index.ts'; import { object, type ObjectIssue } from '../object/index.ts'; import { optional } from '../optional/optional.ts'; import { string, type StringIssue } from '../string/index.ts'; import { intersect, type IntersectSchema } from './intersect.ts'; import type { IntersectIssue } from './types.ts'; describe('intersect', () => { const options = [ array(object({ key1: string() })), array(object({ key2: optional(number(), 123) })), ] as const; type Options = typeof options; describe('should return schema object', () => { test('with undefined message', () => { type Schema = IntersectSchema; expectTypeOf(intersect(options)).toEqualTypeOf(); expectTypeOf(intersect(options, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(intersect(options, 'message')).toEqualTypeOf< IntersectSchema >(); }); test('with function message', () => { expectTypeOf(intersect(options, () => 'message')).toEqualTypeOf< IntersectSchema string> >(); }); }); describe('should infer correct types', () => { type Schema = IntersectSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf< { key1: string }[] & { key2?: number | undefined }[] >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< { key1: string }[] & { key2: number }[] >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< IntersectIssue | ArrayIssue | ObjectIssue | StringIssue | NumberIssue >(); }); }); }); ================================================ FILE: library/src/schemas/intersect/intersect.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { minLength, minValue, transform } from '../../actions/index.ts'; import { pipe } from '../../methods/index.ts'; import type { FailureDataset, InferIssue, InferOutput, PartialDataset, } from '../../types/index.ts'; import { expectNoSchemaIssue } from '../../vitest/index.ts'; import { array } from '../array/array.ts'; import { date } from '../date/index.ts'; import { number } from '../number/index.ts'; import { object } from '../object/index.ts'; import { string } from '../string/index.ts'; import { intersect, type IntersectSchema } from './intersect.ts'; describe('intersect', () => { describe('should return schema object', () => { const options = [ object({ key1: string() }), object({ key2: number() }), ] as const; type Options = typeof options; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'intersect', reference: intersect, expects: 'Object', options, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: IntersectSchema = { ...baseSchema, message: undefined, }; expect(intersect(options)).toStrictEqual(schema); expect(intersect(options, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(intersect(options, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies IntersectSchema); }); test('with function message', () => { const message = () => 'message'; expect(intersect(options, message)).toStrictEqual({ ...baseSchema, message, } satisfies IntersectSchema); }); }); describe('should return dataset without issues', () => { test('for valid values', () => { expectNoSchemaIssue( intersect([ array(object({ key1: string(), key2: number() })), array(object({ key3: date(), key4: array(string()) })), ]), [ [ { key1: 'foo', key2: 123, key3: new Date(), key4: ['foo', 'bar'] }, { key1: 'bar', key2: -456, key3: new Date(), key4: ['baz'] }, ], ] ); }); }); describe('should return dataset with issues', () => { const baseInfo = { message: expect.any(String), requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for empty options', () => { const schema = intersect([]); const input = 'foo'; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'intersect', input, expected: 'never', received: `"${input}"`, }, ], } satisfies FailureDataset>); }); test('with untyped output', () => { const schema = intersect([string(), number()]); const input = 'foo'; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input, expected: 'number', received: `"${input}"`, }, ], } satisfies FailureDataset>); }); test('with typed output', () => { const schema = intersect([ object({ key1: pipe(string(), minLength(10)) }), object({ key2: pipe(number(), minValue(100)) }), ]); type Schema = typeof schema; const input = { key1: 'foo', key2: -123 }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: true, value: input, issues: [ { ...baseInfo, kind: 'validation', type: 'min_length', input: input.key1, expected: '>=10', received: '3', requirement: 10, path: [ { type: 'object', origin: 'value', input, key: 'key1', value: input.key1, }, ], }, { ...baseInfo, kind: 'validation', type: 'min_value', input: input.key2, expected: '>=100', received: '-123', requirement: 100, path: [ { type: 'object', origin: 'value', input, key: 'key2', value: input.key2, }, ], }, ], } satisfies PartialDataset, InferIssue>); }); test('with abort early', () => { const schema = intersect([ object({ key1: pipe(string(), minLength(10)) }), object({ key2: pipe(number(), minValue(100)) }), ]); const input = { key1: 'foo', key2: -123 }; expect( schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, abortEarly: true, kind: 'validation', type: 'min_length', input: input.key1, expected: '>=10', received: '3', requirement: 10, path: [ { type: 'object', origin: 'value', input, key: 'key1', value: input.key1, }, ], }, ], } satisfies FailureDataset>); }); test('for merge error', () => { const schema = intersect([ object({ key: string() }), object({ key: pipe( string(), transform((input) => input.length) ), }), ]); const input = { key: 'foo' }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'intersect', input: input, expected: 'Object', received: 'unknown', }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/intersect/intersect.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, InferIssue, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps, _joinExpects, } from '../../utils/index.ts'; import type { InferIntersectInput, InferIntersectOutput, IntersectIssue, IntersectOptions, } from './types.ts'; import { _merge } from './utils/index.ts'; /** * Intersect schema interface. */ export interface IntersectSchema< TOptions extends IntersectOptions, TMessage extends ErrorMessage | undefined, > extends BaseSchema< InferIntersectInput, InferIntersectOutput, IntersectIssue | InferIssue > { /** * The schema type. */ readonly type: 'intersect'; /** * The schema reference. */ readonly reference: typeof intersect; /** * The intersect options. */ readonly options: TOptions; /** * The error message. */ readonly message: TMessage; } /** * Creates an intersect schema. * * @param options The intersect options. * * @returns An intersect schema. */ export function intersect( options: TOptions ): IntersectSchema; /** * Creates an intersect schema. * * @param options The intersect options. * @param message The error message. * * @returns An intersect schema. */ export function intersect< const TOptions extends IntersectOptions, const TMessage extends ErrorMessage | undefined, >(options: TOptions, message: TMessage): IntersectSchema; // @__NO_SIDE_EFFECTS__ export function intersect( options: IntersectOptions, message?: ErrorMessage ): IntersectSchema | undefined> { return { kind: 'schema', type: 'intersect', reference: intersect, expects: _joinExpects( options.map((option) => option.expects), '&' ), async: false, options, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // Parse input with schema of options, if not empty if (this.options.length) { // Get input value from dataset const input = dataset.value; // Create variable to store outputs let outputs: unknown[] | undefined; // Set typed initially to `true` // @ts-expect-error dataset.typed = true; // Parse schema of each option and collect outputs for (const schema of this.options) { const optionDataset = schema['~run']({ value: input }, config); // If there are issues, capture them if (optionDataset.issues) { if (dataset.issues) { // @ts-expect-error dataset.issues.push(...optionDataset.issues); } else { // @ts-expect-error dataset.issues = optionDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!optionDataset.typed) { dataset.typed = false; } // Add output of option if necessary if (dataset.typed) { if (outputs) { outputs.push(optionDataset.value); } else { outputs = [optionDataset.value]; } } } // If outputs are typed, merge them if (dataset.typed) { // Set first output as initial output dataset.value = outputs![0]; // Merge outputs into one final output for (let index = 1; index < outputs!.length; index++) { const mergeDataset = _merge(dataset.value, outputs![index]); // If outputs can't be merged, add issue and break loop if (mergeDataset.issue) { _addIssue(this, 'type', dataset, config, { received: 'unknown', }); break; } // Otherwise, set merged output dataset.value = mergeDataset.value; } } // Otherwise, add intersect issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< never, IntersectIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/intersect/intersectAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { array, arrayAsync, type ArrayIssue } from '../array/index.ts'; import { number, type NumberIssue } from '../number/index.ts'; import { object, objectAsync, type ObjectIssue } from '../object/index.ts'; import { optional } from '../optional/optional.ts'; import { string, type StringIssue } from '../string/index.ts'; import { intersectAsync, type IntersectSchemaAsync } from './intersectAsync.ts'; import type { IntersectIssue } from './types.ts'; describe('intersectAsync', () => { const options = [ array(object({ key1: string() })), arrayAsync(objectAsync({ key2: optional(number(), 123) })), ] as const; type Options = typeof options; describe('should return schema object', () => { test('with undefined message', () => { type Schema = IntersectSchemaAsync; expectTypeOf(intersectAsync(options)).toEqualTypeOf(); expectTypeOf(intersectAsync(options, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(intersectAsync(options, 'message')).toEqualTypeOf< IntersectSchemaAsync >(); }); test('with function message', () => { expectTypeOf(intersectAsync(options, () => 'message')).toEqualTypeOf< IntersectSchemaAsync string> >(); }); }); describe('should infer correct types', () => { type Schema = IntersectSchemaAsync; test('of input', () => { expectTypeOf>().toEqualTypeOf< { key1: string }[] & { key2?: number | undefined }[] >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< { key1: string }[] & { key2: number }[] >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< IntersectIssue | ArrayIssue | ObjectIssue | StringIssue | NumberIssue >(); }); }); }); ================================================ FILE: library/src/schemas/intersect/intersectAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { minLength, minValue, transform } from '../../actions/index.ts'; import { pipe } from '../../methods/index.ts'; import type { FailureDataset, InferIssue, InferOutput, PartialDataset, } from '../../types/index.ts'; import { expectNoSchemaIssueAsync } from '../../vitest/index.ts'; import { array } from '../array/array.ts'; import { arrayAsync } from '../array/arrayAsync.ts'; import { date } from '../date/index.ts'; import { number } from '../number/index.ts'; import { object, objectAsync } from '../object/index.ts'; import { string } from '../string/index.ts'; import { intersectAsync, type IntersectSchemaAsync } from './intersectAsync.ts'; describe('intersectAsync', () => { describe('should return schema object', () => { const options = [ object({ key1: string() }), objectAsync({ key2: number() }), ] as const; type Options = typeof options; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'intersect', reference: intersectAsync, expects: 'Object', options, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: IntersectSchemaAsync = { ...baseSchema, message: undefined, }; expect(intersectAsync(options)).toStrictEqual(schema); expect(intersectAsync(options, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(intersectAsync(options, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies IntersectSchemaAsync); }); test('with function message', () => { const message = () => 'message'; expect(intersectAsync(options, message)).toStrictEqual({ ...baseSchema, message, } satisfies IntersectSchemaAsync); }); }); describe('should return dataset without issues', () => { test('for valid values', async () => { await expectNoSchemaIssueAsync( intersectAsync([ array(object({ key1: string(), key2: number() })), arrayAsync(objectAsync({ key3: date(), key4: array(string()) })), ]), [ [ { key1: 'foo', key2: 123, key3: new Date(), key4: ['foo', 'bar'] }, { key1: 'bar', key2: -456, key3: new Date(), key4: ['baz'] }, ], ] ); }); }); describe('should return dataset with issues', () => { const baseInfo = { message: expect.any(String), requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for empty options', async () => { const schema = intersectAsync([]); const input = 'foo'; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'intersect', input, expected: 'never', received: `"${input}"`, }, ], } satisfies FailureDataset>); }); test('with untyped output', async () => { const schema = intersectAsync([string(), number()]); const input = 'foo'; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input, expected: 'number', received: `"${input}"`, }, ], } satisfies FailureDataset>); }); test('with typed output', async () => { const schema = intersectAsync([ object({ key1: pipe(string(), minLength(10)) }), objectAsync({ key2: pipe(number(), minValue(100)) }), ]); type Schema = typeof schema; const input = { key1: 'foo', key2: -123 }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: true, value: input, issues: [ { ...baseInfo, kind: 'validation', type: 'min_length', input: input.key1, expected: '>=10', received: '3', requirement: 10, path: [ { type: 'object', origin: 'value', input, key: 'key1', value: input.key1, }, ], }, { ...baseInfo, kind: 'validation', type: 'min_value', input: input.key2, expected: '>=100', received: '-123', requirement: 100, path: [ { type: 'object', origin: 'value', input, key: 'key2', value: input.key2, }, ], }, ], } satisfies PartialDataset, InferIssue>); }); test('with abort early', async () => { const schema = intersectAsync([ object({ key1: pipe(string(), minLength(10)) }), objectAsync({ key2: pipe(number(), minValue(100)) }), ]); const input = { key1: 'foo', key2: -123 }; expect( await schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, abortEarly: true, kind: 'validation', type: 'min_length', input: input.key1, expected: '>=10', received: '3', requirement: 10, path: [ { type: 'object', origin: 'value', input, key: 'key1', value: input.key1, }, ], }, ], } satisfies FailureDataset>); }); test('for merge error', async () => { const schema = intersectAsync([ object({ key: string() }), objectAsync({ key: pipe( string(), transform((input) => input.length) ), }), ]); const input = { key: 'foo' }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'intersect', input: input, expected: 'Object', received: 'unknown', }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/intersect/intersectAsync.ts ================================================ import type { BaseIssue, BaseSchemaAsync, ErrorMessage, InferIssue, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps, _joinExpects, } from '../../utils/index.ts'; import type { intersect } from './intersect.ts'; import type { InferIntersectInput, InferIntersectOutput, IntersectIssue, IntersectOptionsAsync, } from './types.ts'; import { _merge } from './utils/index.ts'; /** * Intersect schema async interface. */ export interface IntersectSchemaAsync< TOptions extends IntersectOptionsAsync, TMessage extends ErrorMessage | undefined, > extends BaseSchemaAsync< InferIntersectInput, InferIntersectOutput, IntersectIssue | InferIssue > { /** * The schema type. */ readonly type: 'intersect'; /** * The schema reference. */ readonly reference: typeof intersect | typeof intersectAsync; /** * The intersect options. */ readonly options: TOptions; /** * The error message. */ readonly message: TMessage; } /** * Creates an intersect schema. * * @param options The intersect options. * * @returns An intersect schema. */ export function intersectAsync( options: TOptions ): IntersectSchemaAsync; /** * Creates an intersect schema. * * @param options The intersect options. * @param message The error message. * * @returns An intersect schema. */ export function intersectAsync< const TOptions extends IntersectOptionsAsync, const TMessage extends ErrorMessage | undefined, >( options: TOptions, message: TMessage ): IntersectSchemaAsync; // @__NO_SIDE_EFFECTS__ export function intersectAsync( options: IntersectOptionsAsync, message?: ErrorMessage ): IntersectSchemaAsync< IntersectOptionsAsync, ErrorMessage | undefined > { return { kind: 'schema', type: 'intersect', reference: intersectAsync, expects: _joinExpects( options.map((option) => option.expects), '&' ), async: true, options, message, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // Parse input with schema of options, if not empty if (this.options.length) { // Get input value from dataset const input = dataset.value; // Create variable to store outputs let outputs: unknown[] | undefined; // Set typed initially to `true` // @ts-expect-error dataset.typed = true; // Parse schema of each option async const optionDatasets = await Promise.all( this.options.map((schema) => schema['~run']({ value: input }, config)) ); // Collect outputs of option datasets for (const optionDataset of optionDatasets) { // If there are issues, capture them if (optionDataset.issues) { if (dataset.issues) { // @ts-expect-error dataset.issues.push(...optionDataset.issues); } else { // @ts-expect-error dataset.issues = optionDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!optionDataset.typed) { dataset.typed = false; } // Add output of option if necessary if (dataset.typed) { if (outputs) { outputs.push(optionDataset.value); } else { outputs = [optionDataset.value]; } } } // If outputs are typed, merge them if (dataset.typed) { // Set first output as initial output dataset.value = outputs![0]; // Merge outputs into one final output for (let index = 1; index < outputs!.length; index++) { const mergeDataset = _merge(dataset.value, outputs![index]); // If outputs can't be merged, add issue and break loop if (mergeDataset.issue) { _addIssue(this, 'type', dataset, config, { received: 'unknown', }); break; } // Otherwise, set merged output dataset.value = mergeDataset.value; } } // Otherwise, add intersect issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< never, IntersectIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/intersect/types.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, MaybeReadonly, } from '../../types/index.ts'; /** * Intersect issue interface. */ export interface IntersectIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'intersect'; /** * The expected property. */ readonly expected: string; } /** * Intersect options type. */ export type IntersectOptions = MaybeReadonly< BaseSchema>[] >; /** * Intersect options async type. */ export type IntersectOptionsAsync = MaybeReadonly< ( | BaseSchema> | BaseSchemaAsync> )[] >; /** * Infer option type. */ type InferOption = | BaseSchema> | BaseSchemaAsync>; /** * Infer intersect input type. */ export type InferIntersectInput< TOptions extends IntersectOptions | IntersectOptionsAsync, > = TOptions extends readonly [ InferOption, ...infer TRest, ] ? TRest extends readonly [ InferOption, ...InferOption[], ] ? TInput & InferIntersectInput : TInput : never; /** * Infer intersect output type. */ export type InferIntersectOutput< TOptions extends IntersectOptions | IntersectOptionsAsync, > = TOptions extends readonly [ InferOption, ...infer TRest, ] ? TRest extends readonly [ InferOption, ...InferOption[], ] ? TOutput & InferIntersectOutput : TOutput : never; ================================================ FILE: library/src/schemas/intersect/utils/_merge/_merge.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { _merge } from './_merge.ts'; describe('_merge', () => { describe('should return dataset with value', () => { test('for valid primitives', () => { const date = new Date(); expect(_merge(1, 1)).toStrictEqual({ value: 1 }); expect(_merge('foo', 'foo')).toStrictEqual({ value: 'foo' }); expect(_merge(date, date)).toStrictEqual({ value: date }); expect(_merge(new Date(+date), new Date(+date))).toStrictEqual({ value: date, }); }); test('for valid dates', () => { const date = new Date(); expect(_merge(date, date)).toStrictEqual({ value: date }); expect(_merge(new Date(+date), new Date(+date))).toStrictEqual({ value: date, }); }); test('for valid objects', () => { expect(_merge({ key: 1 }, { key: 1 })).toStrictEqual({ value: { key: 1 }, }); expect(_merge({ a: 1 }, { b: 2 })).toStrictEqual({ value: { a: 1, b: 2 }, }); expect(_merge({ key: { a: 1 } }, { key: { b: 2 } })).toStrictEqual({ value: { key: { a: 1, b: 2 } }, }); }); test('for valid arrays', () => { expect(_merge([1, 2, 3], [1, 2, 3])).toStrictEqual({ value: [1, 2, 3] }); expect(_merge([{ a: 1 }, { a: 1 }], [{ b: 2 }, { b: 2 }])).toStrictEqual({ value: [ { a: 1, b: 2 }, { a: 1, b: 2 }, ], }); }); }); describe('should return dataset with issue', () => { test('for invalid primitives', () => { expect(_merge(1, 2)).toStrictEqual({ issue: true }); expect(_merge('foo', 'bar')).toStrictEqual({ issue: true }); expect(_merge(1, 'foo')).toStrictEqual({ issue: true }); }); test('for invalid dates', () => { const date = new Date(); expect(_merge(date, new Date(+date + 1234))).toStrictEqual({ issue: true, }); }); test('for invalid objects', () => { expect(_merge({ key: 1 }, { key: '1' })).toStrictEqual({ issue: true }); }); test('for invalid arrays', () => { expect(_merge([1], [1, 2])).toStrictEqual({ issue: true }); expect(_merge([1], ['1'])).toStrictEqual({ issue: true }); }); }); }); ================================================ FILE: library/src/schemas/intersect/utils/_merge/_merge.ts ================================================ /** * Merge dataset type. */ type MergeDataset = | { value: unknown; issue?: undefined } | { value?: undefined; issue: true }; /** * Merges two values into one single output. * * @param value1 First value. * @param value2 Second value. * * @returns The merge dataset. * * @internal */ // @__NO_SIDE_EFFECTS__ export function _merge(value1: unknown, value2: unknown): MergeDataset { // Continue if data type of values match if (typeof value1 === typeof value2) { // Return first value if both are equal if ( value1 === value2 || (value1 instanceof Date && value2 instanceof Date && +value1 === +value2) ) { return { value: value1 }; } // Return deeply merged object if ( value1 && value2 && value1.constructor === Object && value2.constructor === Object ) { // Deeply merge entries of `value2` into `value1` for (const key in value2) { // @ts-expect-error if (key in value1) { // @ts-expect-error const dataset = _merge(value1[key], value2[key]); // If dataset has issue, return it if (dataset.issue) { return dataset; } // Otherwise, replace merged entry // @ts-expect-error value1[key] = dataset.value; // Otherwise, just add entry } else { // @ts-expect-error value1[key] = value2[key]; } } // Return deeply merged object return { value: value1 }; } // Return deeply merged array if (Array.isArray(value1) && Array.isArray(value2)) { // Continue if arrays have same length if (value1.length === value2.length) { // Merge item of `value2` into `value1` for (let index = 0; index < value1.length; index++) { const dataset = _merge(value1[index], value2[index]); // If dataset has issue, return it if (dataset.issue) { return dataset; } // Otherwise, replace merged items value1[index] = dataset.value; } // Return deeply merged array return { value: value1 }; } } } // Otherwise, return that values can't be merged return { issue: true }; } ================================================ FILE: library/src/schemas/intersect/utils/_merge/index.ts ================================================ export * from './_merge.ts'; ================================================ FILE: library/src/schemas/intersect/utils/index.ts ================================================ export * from './_merge/index.ts'; ================================================ FILE: library/src/schemas/lazy/index.ts ================================================ export * from './lazy.ts'; export * from './lazyAsync.ts'; ================================================ FILE: library/src/schemas/lazy/lazy.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { lazy, type LazySchema } from './lazy.ts'; describe('lazy', () => { test('should return schema object', () => { expectTypeOf(lazy(() => string())).toEqualTypeOf< LazySchema> >(); }); describe('should infer correct types', () => { type Schema = LazySchema>; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/lazy/lazy.test.ts ================================================ import { describe, expect, test, vi } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { lazy, type LazySchema } from './lazy.ts'; describe('lazy', () => { test('should return schema object', () => { const getter = () => string(); expect(lazy(getter)).toStrictEqual({ kind: 'schema', type: 'lazy', reference: lazy, expects: 'unknown', getter, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } satisfies LazySchema>); }); describe('should return dataset without issues', () => { const schema = lazy(() => string()); test('for strings', () => { expectNoSchemaIssue(schema, ['', 'foo', '123']); }); }); describe('should return dataset with issues', () => { const schema = lazy(() => string('message')); const baseIssue: Omit = { kind: 'schema', type: 'string', expected: 'string', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); test('should call getter with input', () => { const getter = vi.fn(() => string()); const dataset = { value: 'foo' }; lazy(getter)['~run'](dataset, {}); expect(getter).toHaveBeenCalledWith(dataset.value); }); }); ================================================ FILE: library/src/schemas/lazy/lazy.ts ================================================ import type { BaseIssue, BaseSchema, InferInput, InferIssue, InferOutput, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; /** * Lazy schema interface. */ export interface LazySchema< TWrapped extends BaseSchema>, > extends BaseSchema< InferInput, InferOutput, InferIssue > { /** * The schema type. */ readonly type: 'lazy'; /** * The schema reference. */ readonly reference: typeof lazy; /** * The expected property. */ readonly expects: 'unknown'; /** * The schema getter. */ readonly getter: (input: unknown) => TWrapped; } /** * Creates a lazy schema. * * @param getter The schema getter. * * @returns A lazy schema. */ // @__NO_SIDE_EFFECTS__ export function lazy< const TWrapped extends BaseSchema>, >(getter: (input: unknown) => TWrapped): LazySchema { return { kind: 'schema', type: 'lazy', reference: lazy, expects: 'unknown', async: false, getter, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { return this.getter(dataset.value)['~run'](dataset, config); }, }; } ================================================ FILE: library/src/schemas/lazy/lazyAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { lazyAsync, type LazySchemaAsync } from './lazyAsync.ts'; describe('lazyAsync', () => { test('should return schema object', () => { expectTypeOf(lazyAsync(async () => string())).toEqualTypeOf< LazySchemaAsync> >(); }); describe('should infer correct types', () => { type Schema = LazySchemaAsync>; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/lazy/lazyAsync.test.ts ================================================ import { describe, expect, test, vi } from 'vitest'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { lazyAsync, type LazySchemaAsync } from './lazyAsync.ts'; describe('lazyAsync', () => { test('should return schema object', () => { const getter = async () => string(); expect(lazyAsync(getter)).toStrictEqual({ kind: 'schema', type: 'lazy', reference: lazyAsync, expects: 'unknown', getter, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } satisfies LazySchemaAsync>); }); describe('should return dataset without issues', () => { const schema = lazyAsync(() => string()); test('for strings', async () => { await expectNoSchemaIssueAsync(schema, ['', 'foo', '123']); }); }); describe('should return dataset with issues', () => { const schema = lazyAsync(() => string('message')); const baseIssue: Omit = { kind: 'schema', type: 'string', expected: 'string', message: 'message', }; // Primitive types test('for bigints', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', async () => { await expectSchemaIssueAsync(schema, baseIssue, [true, false]); }); test('for null', async () => { await expectSchemaIssueAsync(schema, baseIssue, [null]); }); test('for numbers', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', async () => { await expectSchemaIssueAsync(schema, baseIssue, [undefined]); }); test('for symbols', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ Symbol(), Symbol('foo'), ]); }); // Complex types test('for arrays', async () => { await expectSchemaIssueAsync(schema, baseIssue, [[], ['value']]); }); test('for functions', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ // eslint-disable-next-line @typescript-eslint/no-empty-function () => {}, // eslint-disable-next-line @typescript-eslint/no-empty-function function () {}, ]); }); test('for objects', async () => { await expectSchemaIssueAsync(schema, baseIssue, [{}, { key: 'value' }]); }); }); test('should call getter with input', () => { const getter = vi.fn(() => string()); const dataset = { value: 'foo' }; lazyAsync(getter)['~run'](dataset, {}); expect(getter).toHaveBeenCalledWith(dataset.value); }); }); ================================================ FILE: library/src/schemas/lazy/lazyAsync.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, InferInput, InferIssue, InferOutput, MaybePromise, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; import type { lazy } from './lazy.ts'; /** * Lazy schema async interface. */ export interface LazySchemaAsync< TWrapped extends | BaseSchema> | BaseSchemaAsync>, > extends BaseSchemaAsync< InferInput, InferOutput, InferIssue > { /** * The schema type. */ readonly type: 'lazy'; /** * The schema reference. */ readonly reference: typeof lazy | typeof lazyAsync; /** * The expected property. */ readonly expects: 'unknown'; /** * The schema getter. */ readonly getter: (input: unknown) => MaybePromise; } /** * Creates a lazy schema. * * @param getter The schema getter. * * @returns A lazy schema. */ // @__NO_SIDE_EFFECTS__ export function lazyAsync< const TWrapped extends | BaseSchema> | BaseSchemaAsync>, >( getter: (input: unknown) => MaybePromise ): LazySchemaAsync { return { kind: 'schema', type: 'lazy', reference: lazyAsync, expects: 'unknown', async: true, getter, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { return (await this.getter(dataset.value))['~run'](dataset, config); }, }; } ================================================ FILE: library/src/schemas/literal/index.ts ================================================ export * from './literal.ts'; ================================================ FILE: library/src/schemas/literal/literal.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { literal, type LiteralIssue, type LiteralSchema } from './literal.ts'; describe('literal', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = LiteralSchema<'foo', undefined>; expectTypeOf(literal('foo')).toEqualTypeOf(); expectTypeOf(literal('foo', undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(literal(123, 'message')).toEqualTypeOf< LiteralSchema<123, 'message'> >(); }); test('with function message', () => { expectTypeOf(literal(true, () => 'message')).toEqualTypeOf< LiteralSchema string> >(); }); }); describe('should infer correct types', () => { type Schema = LiteralSchema<'foo', undefined>; test('of input', () => { expectTypeOf>().toEqualTypeOf<'foo'>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf<'foo'>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/literal/literal.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { literal, type LiteralIssue, type LiteralSchema } from './literal.ts'; describe('literal', () => { describe('should return schema object', () => { const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'literal', reference: literal, literal: 123, expects: '123', async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: LiteralSchema<123, undefined> = { ...baseSchema, message: undefined, }; expect(literal(123)).toStrictEqual(schema); expect(literal(123, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(literal(123, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies LiteralSchema<123, 'message'>); }); test('with function message', () => { const message = () => 'message'; expect(literal(123, message)).toStrictEqual({ ...baseSchema, message, } satisfies LiteralSchema<123, typeof message>); }); }); describe('should return dataset without issues', () => { test('for valid bigint literal', () => { expectNoSchemaIssue(literal(-1n), [-1n]); expectNoSchemaIssue(literal(0n), [0n]); expectNoSchemaIssue(literal(123n), [123n]); }); test('for valid boolean literal', () => { expectNoSchemaIssue(literal(true), [true]); expectNoSchemaIssue(literal(false), [false]); }); test('for valid number literal', () => { expectNoSchemaIssue(literal(-1), [-1]); expectNoSchemaIssue(literal(0), [0]); expectNoSchemaIssue(literal(123), [123]); expectNoSchemaIssue(literal(45.67), [45.67]); }); test('for valid string literal', () => { expectNoSchemaIssue(literal(''), ['']); expectNoSchemaIssue(literal('foo'), ['foo']); expectNoSchemaIssue(literal('123'), ['123']); }); test('for valid symbol literal', () => { const symbol1 = Symbol(); expectNoSchemaIssue(literal(symbol1), [symbol1]); const symbol2 = Symbol('foo'); expectNoSchemaIssue(literal(symbol2), [symbol2]); }); }); describe('should return dataset with issues', () => { const baseIssue: Omit = { kind: 'schema', type: 'literal', message: 'message', }; test('for invalid bigint literal', () => { expectSchemaIssue( literal(123n, 'message'), { ...baseIssue, expected: '123' }, [ -1n, 0n, 132n, true, false, null, 123, undefined, '123', Symbol('123'), {}, [], // eslint-disable-next-line @typescript-eslint/no-empty-function () => {}, ] ); }); test('for invalid boolean literal', () => { expectSchemaIssue( literal(false, 'message'), { ...baseIssue, expected: 'false' }, // eslint-disable-next-line @typescript-eslint/no-empty-function [0n, true, null, 0, undefined, '', Symbol(), {}, [], () => {}] ); }); test('for invalid number literal', () => { expectSchemaIssue( literal(123, 'message'), { ...baseIssue, expected: '123' }, [ 123n, true, false, null, -123, 0, 45.67, undefined, '123', Symbol('123'), {}, [], // eslint-disable-next-line @typescript-eslint/no-empty-function () => {}, ] ); }); test('for invalid string literal', () => { expectSchemaIssue( literal('123', 'message'), { ...baseIssue, expected: '"123"' }, [ 123n, true, false, null, -123, undefined, '', 'foo', Symbol('123'), {}, [], // eslint-disable-next-line @typescript-eslint/no-empty-function () => {}, ] ); }); test('for invalid symbol literal', () => { expectSchemaIssue( literal(Symbol('123'), 'message'), { ...baseIssue, expected: 'symbol' }, [ 123n, true, false, null, -123, undefined, '123', Symbol(), {}, [], // eslint-disable-next-line @typescript-eslint/no-empty-function () => {}, ] ); }); }); }); ================================================ FILE: library/src/schemas/literal/literal.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps, _stringify } from '../../utils/index.ts'; /** * Literal type. */ export type Literal = bigint | boolean | number | string | symbol; /** * Literal issue interface. */ export interface LiteralIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'literal'; /** * The expected property. */ readonly expected: string; } /** * Literal schema interface. */ export interface LiteralSchema< TLiteral extends Literal, TMessage extends ErrorMessage | undefined, > extends BaseSchema { /** * The schema type. */ readonly type: 'literal'; /** * The schema reference. */ readonly reference: typeof literal; /** * The literal value. */ readonly literal: TLiteral; /** * The error message. */ readonly message: TMessage; } /** * Creates a literal schema. * * @param literal_ The literal value. * * @returns A literal schema. */ export function literal( literal_: TLiteral ): LiteralSchema; /** * Creates a literal schema. * * @param literal_ The literal value. * @param message The error message. * * @returns A literal schema. */ export function literal< const TLiteral extends Literal, const TMessage extends ErrorMessage | undefined, >(literal_: TLiteral, message: TMessage): LiteralSchema; // @__NO_SIDE_EFFECTS__ export function literal( literal_: Literal, message?: ErrorMessage ): LiteralSchema | undefined> { return { kind: 'schema', type: 'literal', reference: literal, expects: _stringify(literal_), async: false, literal: literal_, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { if (dataset.value === this.literal) { // @ts-expect-error dataset.typed = true; } else { _addIssue(this, 'type', dataset, config); } // @ts-expect-error return dataset as OutputDataset; }, }; } ================================================ FILE: library/src/schemas/looseObject/index.ts ================================================ export * from './looseObject.ts'; export * from './looseObjectAsync.ts'; export * from './types.ts'; ================================================ FILE: library/src/schemas/looseObject/looseObject.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { Brand, BrandAction, DescriptionAction, ReadonlyAction, TransformAction, } from '../../actions/index.ts'; import type { SchemaWithPipe } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { AnySchema } from '../any/index.ts'; import type { CustomIssue, CustomSchema } from '../custom/index.ts'; import type { ExactOptionalSchema } from '../exactOptional/index.ts'; import type { NullishSchema } from '../nullish/index.ts'; import type { NumberIssue, NumberSchema } from '../number/index.ts'; import type { ObjectIssue, ObjectSchema } from '../object/index.ts'; import type { OptionalSchema } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import type { UndefinedableSchema } from '../undefinedable/index.ts'; import type { UnknownSchema } from '../unknown/index.ts'; import { looseObject, type LooseObjectSchema } from './looseObject.ts'; import type { LooseObjectIssue } from './types.ts'; describe('looseObject', () => { describe('should return schema object', () => { const entries = { key: string() }; type Entries = typeof entries; test('with undefined message', () => { type Schema = LooseObjectSchema; expectTypeOf(looseObject(entries)).toEqualTypeOf(); expectTypeOf(looseObject(entries, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(looseObject(entries, 'message')).toEqualTypeOf< LooseObjectSchema >(); }); test('with function message', () => { expectTypeOf(looseObject(entries, () => 'message')).toEqualTypeOf< LooseObjectSchema string> >(); }); }); describe('should infer correct types', () => { type Schema = LooseObjectSchema< { key00: StringSchema; key01: AnySchema; key02: UnknownSchema; key03: ObjectSchema<{ key: NumberSchema }, undefined>; key04: SchemaWithPipe< [StringSchema, ReadonlyAction] >; key05: UndefinedableSchema, 'bar'>; key06: SchemaWithPipe< [ OptionalSchema, undefined>, TransformAction, ] >; key07: CustomSchema<`a${string}` | `b${string}`, undefined>; key08: SchemaWithPipe< [StringSchema, BrandAction] >; // ExactOptionalSchema key10: ExactOptionalSchema, undefined>; key11: ExactOptionalSchema, 'foo'>; key12: ExactOptionalSchema, () => 'foo'>; // OptionalSchema key20: OptionalSchema, undefined>; key21: OptionalSchema, 'foo'>; key22: OptionalSchema, () => undefined>; key23: OptionalSchema, () => 'foo'>; // NullishSchema key30: NullishSchema, undefined>; key31: NullishSchema, null>; key32: NullishSchema, 'foo'>; key33: NullishSchema, () => undefined>; key34: NullishSchema, () => null>; key35: NullishSchema, () => 'foo'>; // SchemaWithPipe key40: SchemaWithPipe< [ExactOptionalSchema, undefined>] >; key41: SchemaWithPipe< [ ExactOptionalSchema, undefined>, DescriptionAction, ] >; key42: SchemaWithPipe< [OptionalSchema, undefined>] >; key43: SchemaWithPipe< [ OptionalSchema, undefined>, DescriptionAction, ] >; key44: SchemaWithPipe< [NullishSchema, undefined>] >; key45: SchemaWithPipe< [ NullishSchema, undefined>, DescriptionAction, ] >; key46: SchemaWithPipe< [ NullishSchema, undefined>, TransformAction, ] >; }, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf< { key00: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any key01: any; key02: unknown; key03: { key: number }; key04: string; key05: string | undefined; key06?: string | undefined; key07: `a${string}` | `b${string}`; key08: string; // ExactOptionalSchema key10?: string; key11?: string; key12?: string; // OptionalSchema key20?: string | undefined; key21?: string | undefined; key22?: string | undefined; key23?: string | undefined; // NullishSchema key30?: string | null | undefined; key31?: string | null | undefined; key32?: string | null | undefined; key33?: string | null | undefined; key34?: string | null | undefined; key35?: string | null | undefined; // SchemaWithPipe key40?: string; key41?: string; key42?: string | undefined; key43?: string | undefined; key44?: string | null | undefined; key45?: string | null | undefined; key46?: string | null | undefined; } & { [key: string]: unknown } >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< { key00: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any key01: any; key02: unknown; key03: { key: number }; readonly key04: string; key05: string; key06?: number; key07: `a${string}` | `b${string}`; key08: string & Brand<'foo'>; // ExactOptionalSchema key10?: string; key11: string; key12: string; // OptionalSchema key20?: string | undefined; key21: string; key22: string | undefined; key23: string; // NullishSchema key30?: string | null | undefined; key31: string | null; key32: string; key33: string | undefined; key34: string | null; key35: string; // SchemaWithPipe key40?: string; key41?: string; key42?: string | undefined; key43?: string | undefined; key44?: string | null | undefined; key45?: string | null | undefined; key46?: string[]; } & { [key: string]: unknown } >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< LooseObjectIssue | ObjectIssue | StringIssue | NumberIssue | CustomIssue >(); }); }); }); ================================================ FILE: library/src/schemas/looseObject/looseObject.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { fallback } from '../../methods/index.ts'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { any } from '../any/index.ts'; import { exactOptional } from '../exactOptional/index.ts'; import { nullish } from '../nullish/index.ts'; import { number } from '../number/index.ts'; import { object } from '../object/index.ts'; import { optional } from '../optional/index.ts'; import { string } from '../string/index.ts'; import { unknown } from '../unknown/index.ts'; import { looseObject, type LooseObjectSchema } from './looseObject.ts'; import type { LooseObjectIssue } from './types.ts'; describe('looseObject', () => { describe('should return schema object', () => { const entries = { key: string() }; type Entries = typeof entries; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'loose_object', reference: looseObject, expects: 'Object', entries, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: LooseObjectSchema = { ...baseSchema, message: undefined, }; expect(looseObject(entries)).toStrictEqual(schema); expect(looseObject(entries, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(looseObject(entries, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies LooseObjectSchema); }); test('with function message', () => { const message = () => 'message'; expect(looseObject(entries, message)).toStrictEqual({ ...baseSchema, message, } satisfies LooseObjectSchema); }); }); describe('should return dataset without issues', () => { test('for empty object', () => { expectNoSchemaIssue(looseObject({}), [{}]); }); test('for simple object', () => { expectNoSchemaIssue(looseObject({ key1: string(), key2: number() }), [ { key1: 'foo', key2: 123 }, ]); }); test('for unknown entries', () => { expectNoSchemaIssue(looseObject({ key1: string(), key2: number() }), [ { key1: 'foo', key2: 123, other1: 'bar', other2: null }, ]); }); }); describe('should return dataset with issues', () => { const schema = looseObject({}, 'message'); const baseIssue: Omit = { kind: 'schema', type: 'loose_object', expected: 'Object', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types // TODO: Enable this test again in case we find a reliable way to check for // plain objects // test('for arrays', () => { // expectSchemaIssue(schema, baseIssue, [[], ['value']]); // }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); }); describe('should return dataset without nested issues', () => { test('for simple object', () => { expectNoSchemaIssue(looseObject({ key1: string(), key2: number() }), [ { key1: 'foo', key2: 123 }, ]); }); test('for nested object', () => { expectNoSchemaIssue(looseObject({ nested: object({ key: string() }) }), [ { nested: { key: 'foo' } }, ]); }); test('for missing entries with fallback', () => { expect( looseObject({ key1: fallback(string(), 'foo'), key2: fallback(number(), () => 123), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key1: 'foo', key2: 123 }, }); }); test('for exact optional entry', () => { expectNoSchemaIssue(looseObject({ key: exactOptional(string()) }), [ {}, { key: 'foo' }, ]); }); test('for exact optional entry with default', () => { expect( looseObject({ key: exactOptional(string(), 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( looseObject({ key: exactOptional(string(), () => 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); }); test('for optional entry', () => { expectNoSchemaIssue(looseObject({ key: optional(string()) }), [ {}, { key: undefined }, { key: 'foo' }, ]); }); test('for optional entry with default', () => { expect( looseObject({ key: optional(string(), 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( looseObject({ key: optional(string(), () => 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( looseObject({ key: optional(string(), () => undefined), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); }); test('for nullish entry', () => { expectNoSchemaIssue(looseObject({ key: nullish(number()) }), [ {}, { key: undefined }, { key: null }, { key: 123 }, ]); }); test('for nullish entry with default', () => { expect( looseObject({ key: nullish(string(), 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( looseObject({ key: nullish(string(), null) })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( looseObject({ key: nullish(string(), () => 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( looseObject({ key: nullish(string(), () => null) })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( looseObject({ key: nullish(string(), () => undefined) })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: undefined }, }); }); test('for unknown entries', () => { expectNoSchemaIssue(looseObject({ key1: string(), key2: number() }), [ { key1: 'foo', key2: 123, other1: 'bar', other2: null }, ]); }); }); describe('should return dataset with nested issues', () => { const schema = looseObject({ key1: string(), key2: number(), nested: looseObject({ key1: string(), key2: number() }), }); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for missing entries', () => { const input = { key2: 123 }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'loose_object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'loose_object', input: undefined, expected: '"nested"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'nested', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for missing nested entries', () => { const input = { key1: 'value', nested: {} }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'loose_object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key2', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'loose_object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: {}, }, { type: 'object', origin: 'key', input: input.nested, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'loose_object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: {}, }, { type: 'object', origin: 'key', input: input.nested, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for missing entries with abort early', () => { const input = { key2: 123 }; expect( schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'loose_object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key1', value: undefined, }, ], abortEarly: true, }, ], } satisfies FailureDataset>); }); test('for missing any and unknown entry', () => { const schema = looseObject({ key1: any(), key2: unknown() }); expect(schema['~run']({ value: {} }, {})).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'loose_object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'loose_object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid entries', () => { const input = { key1: false, key2: 123, nested: null }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: false, expected: 'string', received: 'false', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: false, }, ], }, { ...baseInfo, kind: 'schema', type: 'loose_object', input: null, expected: 'Object', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: null, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid nested entries', () => { const input = { key1: 'value', key2: 'value', nested: { key1: 123, key2: null, }, }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: 'value', expected: 'number', received: '"value"', path: [ { type: 'object', origin: 'value', input, key: 'key2', value: input.key2, }, ], }, { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'value', input: input.nested, key: 'key1', value: input.nested.key1, }, ], }, { ...baseInfo, kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'value', input: input.nested, key: 'key2', value: input.nested.key2, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid entries with abort early', () => { const input = { key1: false, key2: 123, nested: null }; expect( schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: false, expected: 'string', received: 'false', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: false, }, ], abortEarly: true, }, ], } satisfies FailureDataset>); }); test('for invalid exact optional entry', () => { const schema = looseObject({ key: exactOptional(string()) }); const input = { key: undefined }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: undefined, expected: 'string', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'key', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/looseObject/looseObject.ts ================================================ import { getDefault, getFallback } from '../../methods/index.ts'; import type { BaseSchema, ErrorMessage, InferObjectInput, InferObjectIssue, InferObjectOutput, ObjectEntries, ObjectPathItem, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps, _isValidObjectKey, } from '../../utils/index.ts'; import type { LooseObjectIssue } from './types.ts'; /** * Loose object schema interface. */ export interface LooseObjectSchema< TEntries extends ObjectEntries, TMessage extends ErrorMessage | undefined, > extends BaseSchema< InferObjectInput & { [key: string]: unknown }, InferObjectOutput & { [key: string]: unknown }, LooseObjectIssue | InferObjectIssue > { /** * The schema type. */ readonly type: 'loose_object'; /** * The schema reference. */ readonly reference: typeof looseObject; /** * The expected property. */ readonly expects: 'Object'; /** * The entries schema. */ readonly entries: TEntries; /** * The error message. */ readonly message: TMessage; } /** * Creates a loose object schema. * * @param entries The entries schema. * * @returns A loose object schema. */ export function looseObject( entries: TEntries ): LooseObjectSchema; /** * Creates a loose object schema. * * @param entries The entries schema. * @param message The error message. * * @returns A loose object schema. */ export function looseObject< const TEntries extends ObjectEntries, const TMessage extends ErrorMessage | undefined, >(entries: TEntries, message: TMessage): LooseObjectSchema; // @__NO_SIDE_EFFECTS__ export function looseObject( entries: ObjectEntries, message?: ErrorMessage ): LooseObjectSchema< ObjectEntries, ErrorMessage | undefined > { return { kind: 'schema', type: 'loose_object', reference: looseObject, expects: 'Object', async: false, entries, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (input && typeof input === 'object') { // Set typed to `true` and value to blank object // @ts-expect-error dataset.typed = true; dataset.value = {}; // Process each object entry of schema for (const key in this.entries) { const valueSchema = this.entries[key]; // If key is present or its an optional schema with a default value, // parse input of key or default value if ( key in input || ((valueSchema.type === 'exact_optional' || valueSchema.type === 'optional' || valueSchema.type === 'nullish') && // @ts-expect-error valueSchema.default !== undefined) ) { const value: unknown = key in input ? // @ts-expect-error input[key] : getDefault(valueSchema); const valueDataset = valueSchema['~run']({ value }, config); // If there are issues, capture them if (valueDataset.issues) { // Create object path item const pathItem: ObjectPathItem = { type: 'object', origin: 'value', input: input as Record, key, value, }; // Add modified entry dataset issues to issues for (const issue of valueDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = valueDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!valueDataset.typed) { dataset.typed = false; } // Add entry to dataset // @ts-expect-error dataset.value[key] = valueDataset.value; // Otherwise, if key is missing but has a fallback, use it // @ts-expect-error } else if (valueSchema.fallback !== undefined) { // @ts-expect-error dataset.value[key] = getFallback(valueSchema); // Otherwise, if key is missing and required, add issue } else if ( valueSchema.type !== 'exact_optional' && valueSchema.type !== 'optional' && valueSchema.type !== 'nullish' ) { _addIssue(this, 'key', dataset, config, { input: undefined, expected: `"${key}"`, path: [ { type: 'object', origin: 'key', input: input as Record, key, // @ts-expect-error value: input[key], }, ], }); // If necessary, abort early if (config.abortEarly) { break; } } } // Add rest to dataset if necessary // Hint: We exclude specific keys for security reasons if (!dataset.issues || !config.abortEarly) { for (const key in input) { if (_isValidObjectKey(input, key) && !(key in this.entries)) { // @ts-expect-error dataset.value[key] = input[key]; } } } // Otherwise, add object issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< InferObjectOutput & { [key: string]: unknown }, LooseObjectIssue | InferObjectIssue >; }, }; } ================================================ FILE: library/src/schemas/looseObject/looseObjectAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { Brand, BrandAction, DescriptionAction, ReadonlyAction, TransformAction, } from '../../actions/index.ts'; import type { SchemaWithPipe, SchemaWithPipeAsync, } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { AnySchema } from '../any/index.ts'; import type { CustomIssue, CustomSchemaAsync } from '../custom/index.ts'; import type { ExactOptionalSchema, ExactOptionalSchemaAsync, } from '../exactOptional/index.ts'; import type { NullishSchema, NullishSchemaAsync } from '../nullish/index.ts'; import type { NumberIssue, NumberSchema } from '../number/index.ts'; import type { ObjectIssue, ObjectSchemaAsync } from '../object/index.ts'; import type { OptionalSchema, OptionalSchemaAsync } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import type { UndefinedableSchema } from '../undefinedable/index.ts'; import type { UnknownSchema } from '../unknown/index.ts'; import { looseObjectAsync, type LooseObjectSchemaAsync, } from './looseObjectAsync.ts'; import type { LooseObjectIssue } from './types.ts'; describe('looseObjectAsync', () => { describe('should return schema object', () => { const entries = { key: string() }; type Entries = typeof entries; test('with undefined message', () => { type Schema = LooseObjectSchemaAsync; expectTypeOf(looseObjectAsync(entries)).toEqualTypeOf(); expectTypeOf( looseObjectAsync(entries, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(looseObjectAsync(entries, 'message')).toEqualTypeOf< LooseObjectSchemaAsync >(); }); test('with function message', () => { expectTypeOf(looseObjectAsync(entries, () => 'message')).toEqualTypeOf< LooseObjectSchemaAsync string> >(); }); }); describe('should infer correct types', () => { type Schema = LooseObjectSchemaAsync< { key00: StringSchema; key01: AnySchema; key02: UnknownSchema; key03: ObjectSchemaAsync<{ key: NumberSchema }, undefined>; key04: SchemaWithPipe< [StringSchema, ReadonlyAction] >; key05: UndefinedableSchema, 'bar'>; key06: SchemaWithPipe< [ OptionalSchema, undefined>, TransformAction, ] >; key07: SchemaWithPipeAsync< [ OptionalSchema, undefined>, TransformAction, ] >; key08: SchemaWithPipeAsync< [ OptionalSchemaAsync, undefined>, TransformAction, ] >; key09: CustomSchemaAsync<`a${string}` | `b${string}`, undefined>; key10: SchemaWithPipe< [StringSchema, BrandAction] >; // ExactOptionalSchema key20: ExactOptionalSchema, undefined>; key21: ExactOptionalSchema, 'foo'>; key22: ExactOptionalSchema, () => 'foo'>; // ExactOptionalSchemaAsync key30: ExactOptionalSchemaAsync, undefined>; key31: ExactOptionalSchemaAsync, 'foo'>; key32: ExactOptionalSchemaAsync, () => 'foo'>; key33: ExactOptionalSchemaAsync< StringSchema, () => Promise<'foo'> >; // OptionalSchema key40: OptionalSchema, undefined>; key41: OptionalSchema, 'foo'>; key42: OptionalSchema, () => undefined>; key43: OptionalSchema, () => 'foo'>; // OptionalSchemaAsync key50: OptionalSchemaAsync, undefined>; key51: OptionalSchemaAsync, 'foo'>; key52: OptionalSchemaAsync, () => undefined>; key53: OptionalSchemaAsync, () => 'foo'>; key54: OptionalSchemaAsync< StringSchema, () => Promise >; key55: OptionalSchemaAsync< StringSchema, () => Promise<'foo'> >; // NullishSchema key60: NullishSchema, undefined>; key61: NullishSchema, null>; key62: NullishSchema, 'foo'>; key63: NullishSchema, () => undefined>; key64: NullishSchema, () => null>; key65: NullishSchema, () => 'foo'>; // NullishSchemaAsync key70: NullishSchemaAsync, undefined>; key71: NullishSchemaAsync, null>; key72: NullishSchemaAsync, 'foo'>; key73: NullishSchemaAsync, () => undefined>; key74: NullishSchemaAsync, () => null>; key75: NullishSchemaAsync, () => 'foo'>; key76: NullishSchemaAsync< StringSchema, () => Promise >; key77: NullishSchemaAsync, () => Promise>; key78: NullishSchemaAsync< StringSchema, () => Promise<'foo'> >; // SchemaWithPipe key80: SchemaWithPipe< [ExactOptionalSchema, undefined>] >; key81: SchemaWithPipe< [ ExactOptionalSchema, undefined>, DescriptionAction, ] >; key82: SchemaWithPipe< [OptionalSchema, undefined>] >; key83: SchemaWithPipe< [ OptionalSchema, undefined>, DescriptionAction, ] >; key84: SchemaWithPipe< [NullishSchema, undefined>] >; key85: SchemaWithPipe< [ NullishSchema, undefined>, DescriptionAction, ] >; key86: SchemaWithPipe< [ NullishSchema, undefined>, TransformAction, ] >; key87: SchemaWithPipeAsync< [ NullishSchemaAsync, undefined>, TransformAction, ] >; }, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf< { key00: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any key01: any; key02: unknown; key03: { key: number }; key04: string; key05: string | undefined; key06?: string | undefined; key07?: string | undefined; key08?: string | undefined; key09: `a${string}` | `b${string}`; key10: string; // ExactOptionalSchema key20?: string; key21?: string; key22?: string; // ExactOptionalSchemaAsync key30?: string; key31?: string; key32?: string; key33?: string; // OptionalSchema key40?: string | undefined; key41?: string | undefined; key42?: string | undefined; key43?: string | undefined; // OptionalSchemaAsync key50?: string | undefined; key51?: string | undefined; key52?: string | undefined; key53?: string | undefined; key54?: string | undefined; key55?: string | undefined; // NullishSchema key60?: string | null | undefined; key61?: string | null | undefined; key62?: string | null | undefined; key63?: string | null | undefined; key64?: string | null | undefined; key65?: string | null | undefined; // NullishSchemaAsync key70?: string | null | undefined; key71?: string | null | undefined; key72?: string | null | undefined; key73?: string | null | undefined; key74?: string | null | undefined; key75?: string | null | undefined; key76?: string | null | undefined; key77?: string | null | undefined; key78?: string | null | undefined; // SchemaWithPipe key80?: string; key81?: string; key82?: string | undefined; key83?: string | undefined; key84?: string | null | undefined; key85?: string | null | undefined; key86?: string | null | undefined; key87?: string | null | undefined; } & { [key: string]: unknown } >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< { key00: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any key01: any; key02: unknown; key03: { key: number }; readonly key04: string; key05: string; key06?: number; key07?: number; key08?: number; key09: `a${string}` | `b${string}`; key10: string & Brand<'foo'>; // ExactOptionalSchema key20?: string; key21: string; key22: string; // ExactOptionalSchemaAsync key30?: string; key31: string; key32: string; key33: string; // OptionalSchema key40?: string | undefined; key41: string; key42: string | undefined; key43: string; // OptionalSchemaAsync key50?: string | undefined; key51: string; key52: string | undefined; key53: string; key54: string | undefined; key55: string; // NullishSchema key60?: string | null | undefined; key61: string | null; key62: string; key63: string | undefined; key64: string | null; key65: string; // NullishSchemaAsync key70?: string | null | undefined; key71: string | null; key72: string; key73: string | undefined; key74: string | null; key75: string; key76: string | undefined; key77: string | null; key78: string; // SchemaWithPipe key80?: string; key81?: string; key82?: string | undefined; key83?: string | undefined; key84?: string | null | undefined; key85?: string | null | undefined; key86?: string[]; key87?: string[]; } & { [key: string]: unknown } >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< LooseObjectIssue | ObjectIssue | StringIssue | NumberIssue | CustomIssue >(); }); }); }); ================================================ FILE: library/src/schemas/looseObject/looseObjectAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { fallback, fallbackAsync } from '../../methods/index.ts'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { any } from '../any/index.ts'; import { exactOptional, exactOptionalAsync } from '../exactOptional/index.ts'; import { nullish, nullishAsync } from '../nullish/index.ts'; import { number } from '../number/index.ts'; import { objectAsync } from '../object/index.ts'; import { optional, optionalAsync } from '../optional/index.ts'; import { string } from '../string/index.ts'; import { unknown } from '../unknown/index.ts'; import { looseObjectAsync, type LooseObjectSchemaAsync, } from './looseObjectAsync.ts'; import type { LooseObjectIssue } from './types.ts'; describe('looseObjectAsync', () => { describe('should return schema object', () => { const entries = { key: string() }; type Entries = typeof entries; const baseSchema: Omit< LooseObjectSchemaAsync, 'message' > = { kind: 'schema', type: 'loose_object', reference: looseObjectAsync, expects: 'Object', entries, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: LooseObjectSchemaAsync = { ...baseSchema, message: undefined, }; expect(looseObjectAsync(entries)).toStrictEqual(schema); expect(looseObjectAsync(entries, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(looseObjectAsync(entries, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies LooseObjectSchemaAsync); }); test('with function message', () => { const message = () => 'message'; expect(looseObjectAsync(entries, message)).toStrictEqual({ ...baseSchema, message, } satisfies LooseObjectSchemaAsync); }); }); describe('should return dataset without issues', () => { test('for empty object', async () => { await expectNoSchemaIssueAsync(looseObjectAsync({}), [{}]); }); test('for simple object', async () => { await expectNoSchemaIssueAsync( looseObjectAsync({ key1: string(), key2: number() }), [{ key1: 'foo', key2: 123 }] ); }); test('for unknown entries', async () => { await expectNoSchemaIssueAsync( looseObjectAsync({ key1: string(), key2: number() }), [{ key1: 'foo', key2: 123, other1: 'bar', other2: null }] ); }); }); describe('should return dataset with issues', () => { const schema = looseObjectAsync({}, 'message'); const baseIssue: Omit = { kind: 'schema', type: 'loose_object', expected: 'Object', message: 'message', }; // Primitive types test('for bigints', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', async () => { await expectSchemaIssueAsync(schema, baseIssue, [true, false]); }); test('for null', async () => { await expectSchemaIssueAsync(schema, baseIssue, [null]); }); test('for numbers', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', async () => { await expectSchemaIssueAsync(schema, baseIssue, [undefined]); }); test('for strings', async () => { await expectSchemaIssueAsync(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ Symbol(), Symbol('foo'), ]); }); // Complex types // TODO: Enable this test again in case we find a reliable way to check for // plain objects // test('for arrays', async () => { // await expectSchemaIssueAsync(schema, baseIssue, [[], ['value']]); // }); test('for functions', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ // eslint-disable-next-line @typescript-eslint/no-empty-function () => {}, // eslint-disable-next-line @typescript-eslint/no-empty-function function () {}, ]); }); }); describe('should return dataset without nested issues', () => { test('for simple object', async () => { await expectNoSchemaIssueAsync( looseObjectAsync({ key1: string(), key2: number() }), [{ key1: 'foo', key2: 123 }] ); }); test('for nested object', async () => { await expectNoSchemaIssueAsync( looseObjectAsync({ nested: objectAsync({ key: string() }) }), [{ nested: { key: 'foo' } }] ); }); test('for missing entries with fallback', async () => { expect( await looseObjectAsync({ key1: fallback(string(), 'foo'), key2: fallback(number(), () => 123), key3: fallbackAsync(string(), 'bar'), key4: fallbackAsync(number(), () => 456), key5: fallbackAsync(string(), async () => 'baz'), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key1: 'foo', key2: 123, key3: 'bar', key4: 456, key5: 'baz' }, }); }); test('for exact optional entry', async () => { await expectNoSchemaIssueAsync( looseObjectAsync({ key: exactOptional(string()) }), [{}, { key: 'foo' }] ); await expectNoSchemaIssueAsync( looseObjectAsync({ key: exactOptionalAsync(string()) }), [{}, { key: 'foo' }] ); }); test('for exact optional entry with default', async () => { // Sync expect( await looseObjectAsync({ key: exactOptional(string(), 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await looseObjectAsync({ key: exactOptional(string(), () => 'foo') })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); // Async expect( await looseObjectAsync({ key: exactOptionalAsync(string(), 'foo') })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await looseObjectAsync({ key: exactOptionalAsync(string(), () => 'foo'), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); }); test('for optional entry', async () => { await expectNoSchemaIssueAsync( looseObjectAsync({ key: optional(string()) }), [{}, { key: undefined }, { key: 'foo' }] ); await expectNoSchemaIssueAsync( looseObjectAsync({ key: optionalAsync(string()) }), [{}, { key: undefined }, { key: 'foo' }] ); }); test('for optional entry with default', async () => { // Sync expect( await looseObjectAsync({ key: optional(string(), 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await looseObjectAsync({ key: optional(string(), () => 'foo') })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await looseObjectAsync({ key: optional(string(), () => undefined), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); // Async expect( await looseObjectAsync({ key: optionalAsync(string(), 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await looseObjectAsync({ key: optionalAsync(string(), () => 'foo') })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await looseObjectAsync({ key: optionalAsync(string(), () => undefined), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); expect( await looseObjectAsync({ key: optionalAsync(string(), async () => 'foo'), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await looseObjectAsync({ key: optionalAsync(string(), async () => undefined), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); }); test('for nullish entry', async () => { await expectNoSchemaIssueAsync( looseObjectAsync({ key: nullish(number()) }), [{}, { key: undefined }, { key: null }, { key: 123 }] ); await expectNoSchemaIssueAsync( looseObjectAsync({ key: nullishAsync(number()) }), [{}, { key: undefined }, { key: null }, { key: 123 }] ); }); test('for nullish entry with default', async () => { // Sync expect( await looseObjectAsync({ key: nullish(string(), 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await looseObjectAsync({ key: nullish(string(), null) })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( await looseObjectAsync({ key: nullish(string(), () => 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await looseObjectAsync({ key: nullish(string(), () => null) })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( await looseObjectAsync({ key: nullish(string(), () => undefined) })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); // Async expect( await looseObjectAsync({ key: nullishAsync(string(), 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await looseObjectAsync({ key: nullishAsync(string(), null) })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( await looseObjectAsync({ key: nullishAsync(string(), () => 'foo') })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await looseObjectAsync({ key: nullishAsync(string(), () => null) })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( await looseObjectAsync({ key: nullishAsync(string(), () => undefined), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); expect( await looseObjectAsync({ key: nullishAsync(string(), async () => 'foo'), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await looseObjectAsync({ key: nullishAsync(string(), async () => null), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( await looseObjectAsync({ key: nullishAsync(string(), async () => undefined), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); }); test('for unknown entries', async () => { await expectNoSchemaIssueAsync( looseObjectAsync({ key1: string(), key2: number() }), [{ key1: 'foo', key2: 123, other1: 'bar', other2: null }] ); }); }); describe('should return dataset with nested issues', () => { const schema = looseObjectAsync({ key1: string(), key2: number(), nested: looseObjectAsync({ key1: string(), key2: number() }), }); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for missing entries', async () => { const input = { key2: 123 }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'loose_object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'loose_object', input: undefined, expected: '"nested"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'nested', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for missing nested entries', async () => { const input = { key1: 'value', nested: {} }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'loose_object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key2', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'loose_object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: {}, }, { type: 'object', origin: 'key', input: input.nested, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'loose_object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: {}, }, { type: 'object', origin: 'key', input: input.nested, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for missing entries with abort early', async () => { const input = { key2: 123 }; expect( await schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'loose_object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key1', value: undefined, }, ], abortEarly: true, }, ], } satisfies FailureDataset>); }); test('for missing any and unknown entry', async () => { const schema = looseObjectAsync({ key1: any(), key2: unknown() }); expect(await schema['~run']({ value: {} }, {})).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'loose_object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'loose_object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid entries', async () => { const input = { key1: false, key2: 123, nested: null }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: false, expected: 'string', received: 'false', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: false, }, ], }, { ...baseInfo, kind: 'schema', type: 'loose_object', input: null, expected: 'Object', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: null, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid nested entries', async () => { const input = { key1: 'value', key2: 'value', nested: { key1: 123, key2: null, }, }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: 'value', expected: 'number', received: '"value"', path: [ { type: 'object', origin: 'value', input, key: 'key2', value: input.key2, }, ], }, { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'value', input: input.nested, key: 'key1', value: input.nested.key1, }, ], }, { ...baseInfo, kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'value', input: input.nested, key: 'key2', value: input.nested.key2, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid entries with abort early', async () => { const input = { key1: false, key2: 123, nested: null }; expect( await schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: false, expected: 'string', received: 'false', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: false, }, ], abortEarly: true, }, ], } satisfies FailureDataset>); }); test('for invalid exact optional entry', async () => { const schema = looseObjectAsync({ key1: exactOptional(string()), key2: exactOptionalAsync(string()), }); const input = { key1: undefined, key2: undefined }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: undefined, expected: 'string', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'string', input: undefined, expected: 'string', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/looseObject/looseObjectAsync.ts ================================================ import { getDefault, getFallback } from '../../methods/index.ts'; import type { BaseSchemaAsync, ErrorMessage, InferObjectInput, InferObjectIssue, InferObjectOutput, ObjectEntriesAsync, ObjectPathItem, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps, _isValidObjectKey, } from '../../utils/index.ts'; import type { looseObject } from './looseObject.ts'; import type { LooseObjectIssue } from './types.ts'; /** * Object schema async interface. */ export interface LooseObjectSchemaAsync< TEntries extends ObjectEntriesAsync, TMessage extends ErrorMessage | undefined, > extends BaseSchemaAsync< InferObjectInput & { [key: string]: unknown }, InferObjectOutput & { [key: string]: unknown }, LooseObjectIssue | InferObjectIssue > { /** * The schema type. */ readonly type: 'loose_object'; /** * The schema reference. */ readonly reference: typeof looseObject | typeof looseObjectAsync; /** * The expected property. */ readonly expects: 'Object'; /** * The entries schema. */ readonly entries: TEntries; /** * The error message. */ readonly message: TMessage; } /** * Creates a loose object schema. * * @param entries The entries schema. * * @returns A loose object schema. */ export function looseObjectAsync( entries: TEntries ): LooseObjectSchemaAsync; /** * Creates a loose object schema. * * @param entries The entries schema. * @param message The error message. * * @returns A loose object schema. */ export function looseObjectAsync< const TEntries extends ObjectEntriesAsync, const TMessage extends ErrorMessage | undefined, >( entries: TEntries, message: TMessage ): LooseObjectSchemaAsync; // @__NO_SIDE_EFFECTS__ export function looseObjectAsync( entries: ObjectEntriesAsync, message?: ErrorMessage ): LooseObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined > { return { kind: 'schema', type: 'loose_object', reference: looseObjectAsync, expects: 'Object', async: true, entries, message, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (input && typeof input === 'object') { // Set typed to `true` and value to blank object // @ts-expect-error dataset.typed = true; dataset.value = {}; // If key is present or its an optional schema with a default value, // parse input of key or default value asynchronously const valueDatasets = await Promise.all( Object.entries(this.entries).map(async ([key, valueSchema]) => { if ( key in input || ((valueSchema.type === 'exact_optional' || valueSchema.type === 'optional' || valueSchema.type === 'nullish') && // @ts-expect-error valueSchema.default !== undefined) ) { const value: unknown = key in input ? // @ts-expect-error input[key] : await getDefault(valueSchema); return [ key, value, valueSchema, await valueSchema['~run']({ value }, config), ] as const; } return [ key, // @ts-expect-error input[key] as unknown, valueSchema, null, ] as const; }) ); // Process each object entry of schema for (const [key, value, valueSchema, valueDataset] of valueDatasets) { // If key is present or its an optional schema with a default value, // process its value dataset if (valueDataset) { // If there are issues, capture them if (valueDataset.issues) { // Create object path item const pathItem: ObjectPathItem = { type: 'object', origin: 'value', input: input as Record, key, value, }; // Add modified entry dataset issues to issues for (const issue of valueDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = valueDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!valueDataset.typed) { dataset.typed = false; } // Add entry to dataset // @ts-expect-error dataset.value[key] = valueDataset.value; // Otherwise, if key is missing but has a fallback, use it // @ts-expect-error } else if (valueSchema.fallback !== undefined) { // @ts-expect-error dataset.value[key] = await getFallback(valueSchema); // Otherwise, if key is missing and required, add issue } else if ( valueSchema.type !== 'exact_optional' && valueSchema.type !== 'optional' && valueSchema.type !== 'nullish' ) { _addIssue(this, 'key', dataset, config, { input: undefined, expected: `"${key}"`, path: [ { type: 'object', origin: 'key', input: input as Record, key, value, }, ], }); // If necessary, abort early if (config.abortEarly) { break; } } } // Add rest to dataset if necessary // Hint: We exclude specific keys for security reasons if (!dataset.issues || !config.abortEarly) { for (const key in input) { if (_isValidObjectKey(input, key) && !(key in this.entries)) { // @ts-expect-error dataset.value[key] = input[key]; } } } // Otherwise, add object issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< InferObjectOutput & { [key: string]: unknown }, LooseObjectIssue | InferObjectIssue >; }, }; } ================================================ FILE: library/src/schemas/looseObject/types.ts ================================================ import type { BaseIssue } from '../../types/index.ts'; /** * Loose object issue interface. */ export interface LooseObjectIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'loose_object'; /** * The expected property. */ readonly expected: 'Object' | `"${string}"`; } ================================================ FILE: library/src/schemas/looseTuple/index.ts ================================================ export * from './looseTuple.ts'; export * from './looseTupleAsync.ts'; export * from './types.ts'; ================================================ FILE: library/src/schemas/looseTuple/looseTuple.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { boolean } from '../boolean/index.ts'; import { number, type NumberIssue, type NumberSchema, } from '../number/index.ts'; import type { OptionalSchema } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { looseTuple, type LooseTupleSchema } from './looseTuple.ts'; import type { LooseTupleIssue } from './types.ts'; describe('looseTuple', () => { describe('should return schema object', () => { const items = [string(), number(), boolean()] as const; type Items = typeof items; test('with undefined message', () => { type Schema = LooseTupleSchema; expectTypeOf(looseTuple(items)).toEqualTypeOf(); expectTypeOf(looseTuple(items, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(looseTuple(items, 'message')).toEqualTypeOf< LooseTupleSchema >(); }); test('with function message', () => { expectTypeOf(looseTuple(items, () => 'message')).toEqualTypeOf< LooseTupleSchema string> >(); }); }); describe('should infer correct types', () => { type Schema = LooseTupleSchema< [OptionalSchema, 'foo'>, NumberSchema], undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf< [string | undefined, number, ...unknown[]] >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< [string, number, ...unknown[]] >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< LooseTupleIssue | StringIssue | NumberIssue >(); }); }); }); ================================================ FILE: library/src/schemas/looseTuple/looseTuple.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { boolean } from '../boolean/index.ts'; import { number } from '../number/index.ts'; import { optional } from '../optional/index.ts'; import { string, type StringIssue } from '../string/index.ts'; import { looseTuple, type LooseTupleSchema } from './looseTuple.ts'; import type { LooseTupleIssue } from './types.ts'; describe('looseTuple', () => { describe('should return schema object', () => { const items = [optional(string()), number()] as const; type Items = typeof items; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'loose_tuple', reference: looseTuple, expects: 'Array', items, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: LooseTupleSchema = { ...baseSchema, message: undefined, }; expect(looseTuple(items)).toStrictEqual(schema); expect(looseTuple(items, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(looseTuple(items, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies LooseTupleSchema); }); test('with function message', () => { const message = () => 'message'; expect(looseTuple(items, message)).toStrictEqual({ ...baseSchema, message, } satisfies LooseTupleSchema); }); }); describe('should return dataset without issues', () => { test('for empty tuple', () => { expectNoSchemaIssue(looseTuple([]), [[]]); }); const schema = looseTuple([optional(string()), number()]); test('for simple tuple', () => { expectNoSchemaIssue(schema, [ ['foo', 123], [undefined, 123], ]); }); test('for unknown items', () => { expectNoSchemaIssue(schema, [['foo', 123, null, true, undefined]]); }); }); describe('should return dataset with issues', () => { const schema = looseTuple([optional(string()), number()], 'message'); const baseIssue: Omit = { kind: 'schema', type: 'loose_tuple', expected: 'Array', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); describe('should return dataset without nested issues', () => { const schema = looseTuple([optional(string()), number()]); test('for simple tuple', () => { expectNoSchemaIssue(schema, [ ['foo', 123], [undefined, 123], ]); }); test('for nested tuple', () => { expectNoSchemaIssue(looseTuple([schema, schema]), [ [ ['foo', 123], [undefined, 123], ], ]); }); test('for unknown items', () => { expectNoSchemaIssue(schema, [['foo', 123, null, true, undefined]]); }); }); describe('should return dataset with nested issues', () => { const schema = looseTuple([string(), number(), boolean()]); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const stringIssue: StringIssue = { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'array', origin: 'value', input: [123, 456, 'true'], key: 0, value: 123, }, ], }; test('for wrong items', () => { const input = [123, 456, 'true']; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ stringIssue, { ...baseInfo, kind: 'schema', type: 'boolean', input: 'true', expected: 'boolean', received: '"true"', path: [ { type: 'array', origin: 'value', input: input, key: 2, value: input[2], }, ], }, ], } satisfies FailureDataset>); }); test('with abort early', () => { expect( schema['~run']({ value: [123, 456, 'true'] }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: [], issues: [{ ...stringIssue, abortEarly: true }], } satisfies FailureDataset>); }); test('for wrong nested items', () => { const nestedSchema = looseTuple([schema, schema]); const input: [[string, string, boolean], null] = [ ['foo', '123', false], null, ]; expect(nestedSchema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: '123', expected: 'number', received: '"123"', path: [ { type: 'array', origin: 'value', input: input, key: 0, value: input[0], }, { type: 'array', origin: 'value', input: input[0], key: 1, value: input[0][1], }, ], }, { ...baseInfo, kind: 'schema', type: 'loose_tuple', input: null, expected: 'Array', received: 'null', path: [ { type: 'array', origin: 'value', input: input, key: 1, value: input[1], }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/looseTuple/looseTuple.ts ================================================ import type { ArrayPathItem, BaseIssue, BaseSchema, ErrorMessage, InferTupleInput, InferTupleIssue, InferTupleOutput, OutputDataset, TupleItems, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { LooseTupleIssue } from './types.ts'; /** * Loose tuple schema interface. */ export interface LooseTupleSchema< TItems extends TupleItems, TMessage extends ErrorMessage | undefined, > extends BaseSchema< [...InferTupleInput, ...unknown[]], [...InferTupleOutput, ...unknown[]], LooseTupleIssue | InferTupleIssue > { /** * The schema type. */ readonly type: 'loose_tuple'; /** * The schema reference. */ readonly reference: typeof looseTuple; /** * The expected property. */ readonly expects: 'Array'; /** * The items schema. */ readonly items: TItems; /** * The error message. */ readonly message: TMessage; } /** * Creates a loose tuple schema. * * @param items The items schema. * * @returns A loose tuple schema. */ export function looseTuple( items: TItems ): LooseTupleSchema; /** * Creates a loose tuple schema. * * @param items The items schema. * @param message The error message. * * @returns A loose tuple schema. */ export function looseTuple< const TItems extends TupleItems, const TMessage extends ErrorMessage | undefined, >(items: TItems, message: TMessage): LooseTupleSchema; // @__NO_SIDE_EFFECTS__ export function looseTuple( items: TupleItems, message?: ErrorMessage ): LooseTupleSchema | undefined> { return { kind: 'schema', type: 'loose_tuple', reference: looseTuple, expects: 'Array', async: false, items, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (Array.isArray(input)) { // Set typed to `true` and value to empty array // @ts-expect-error dataset.typed = true; dataset.value = []; // Parse schema of each tuple item for (let key = 0; key < this.items.length; key++) { const value = input[key]; const itemDataset = this.items[key]['~run']({ value }, config); // If there are issues, capture them if (itemDataset.issues) { // Create tuple path item const pathItem: ArrayPathItem = { type: 'array', origin: 'value', input, key, value, }; // Add modified item dataset issues to issues for (const issue of itemDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = itemDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!itemDataset.typed) { dataset.typed = false; } // Add item to dataset // @ts-expect-error dataset.value.push(itemDataset.value); } // Add rest to dataset if necessary if (!dataset.issues || !config.abortEarly) { for (let key = this.items.length; key < input.length; key++) { // @ts-expect-error dataset.value.push(input[key]); } } // Otherwise, add tuple issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< unknown[], LooseTupleIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/looseTuple/looseTupleAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { boolean } from '../boolean/index.ts'; import { number, type NumberIssue, type NumberSchema, } from '../number/index.ts'; import type { OptionalSchemaAsync } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { looseTupleAsync, type LooseTupleSchemaAsync, } from './looseTupleAsync.ts'; import type { LooseTupleIssue } from './types.ts'; describe('looseTupleAsync', () => { describe('should return schema object', () => { const items = [string(), number(), boolean()] as const; type Items = typeof items; test('with undefined message', () => { type Schema = LooseTupleSchemaAsync; expectTypeOf(looseTupleAsync(items)).toEqualTypeOf(); expectTypeOf(looseTupleAsync(items, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(looseTupleAsync(items, 'message')).toEqualTypeOf< LooseTupleSchemaAsync >(); }); test('with function message', () => { expectTypeOf(looseTupleAsync(items, () => 'message')).toEqualTypeOf< LooseTupleSchemaAsync string> >(); }); }); describe('should infer correct types', () => { type Schema = LooseTupleSchemaAsync< [ OptionalSchemaAsync, 'foo'>, NumberSchema, ], undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf< [string | undefined, number, ...unknown[]] >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< [string, number, ...unknown[]] >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< LooseTupleIssue | StringIssue | NumberIssue >(); }); }); }); ================================================ FILE: library/src/schemas/looseTuple/looseTupleAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { boolean } from '../boolean/index.ts'; import { number } from '../number/index.ts'; import { optionalAsync } from '../optional/index.ts'; import { string, type StringIssue } from '../string/index.ts'; import { looseTupleAsync, type LooseTupleSchemaAsync, } from './looseTupleAsync.ts'; import type { LooseTupleIssue } from './types.ts'; describe('looseTupleAsync', () => { describe('should return schema object', () => { const items = [optionalAsync(string()), number()] as const; type Items = typeof items; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'loose_tuple', reference: looseTupleAsync, expects: 'Array', items, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: LooseTupleSchemaAsync = { ...baseSchema, message: undefined, }; expect(looseTupleAsync(items)).toStrictEqual(schema); expect(looseTupleAsync(items, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(looseTupleAsync(items, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies LooseTupleSchemaAsync); }); test('with function message', () => { const message = () => 'message'; expect(looseTupleAsync(items, message)).toStrictEqual({ ...baseSchema, message, } satisfies LooseTupleSchemaAsync); }); }); describe('should return dataset without issues', () => { test('for empty tuple', async () => { await expectNoSchemaIssueAsync(looseTupleAsync([]), [[]]); }); const schema = looseTupleAsync([optionalAsync(string()), number()]); test('for simple tuple', async () => { await expectNoSchemaIssueAsync(schema, [ ['foo', 123], [undefined, 123], ]); }); test('for unknown items', async () => { await expectNoSchemaIssueAsync(schema, [ ['foo', 123, null, true, undefined], ]); }); }); describe('should return dataset with issues', () => { const schema = looseTupleAsync( [optionalAsync(string()), number()], 'message' ); const baseIssue: Omit = { kind: 'schema', type: 'loose_tuple', expected: 'Array', message: 'message', }; // Primitive types test('for bigints', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', async () => { await expectSchemaIssueAsync(schema, baseIssue, [true, false]); }); test('for null', async () => { await expectSchemaIssueAsync(schema, baseIssue, [null]); }); test('for numbers', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', async () => { await expectSchemaIssueAsync(schema, baseIssue, [undefined]); }); test('for strings', async () => { await expectSchemaIssueAsync(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ Symbol(), Symbol('foo'), ]); }); // Complex types test('for functions', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ // eslint-disable-next-line @typescript-eslint/no-empty-function () => {}, // eslint-disable-next-line @typescript-eslint/no-empty-function function () {}, ]); }); test('for objects', async () => { await expectSchemaIssueAsync(schema, baseIssue, [{}, { key: 'value' }]); }); }); describe('should return dataset without nested issues', () => { const schema = looseTupleAsync([optionalAsync(string()), number()]); test('for simple tuple', async () => { await expectNoSchemaIssueAsync(schema, [ ['foo', 123], [undefined, 123], ]); }); test('for nested tuple', async () => { await expectNoSchemaIssueAsync(looseTupleAsync([schema, schema]), [ [ ['foo', 123], [undefined, 123], ], ]); }); test('for unknown items', async () => { await expectNoSchemaIssueAsync(schema, [ ['foo', 123, null, true, undefined], ]); }); }); describe('should return dataset with nested issues', () => { const schema = looseTupleAsync([string(), number(), boolean()]); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const stringIssue: StringIssue = { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'array', origin: 'value', input: [123, 456, 'true'], key: 0, value: 123, }, ], }; test('for wrong items', async () => { const input = [123, 456, 'true']; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ stringIssue, { ...baseInfo, kind: 'schema', type: 'boolean', input: 'true', expected: 'boolean', received: '"true"', path: [ { type: 'array', origin: 'value', input: input, key: 2, value: input[2], }, ], }, ], } satisfies FailureDataset>); }); test('with abort early', async () => { expect( await schema['~run']( { value: [123, 456, 'true'] }, { abortEarly: true } ) ).toStrictEqual({ typed: false, value: [], issues: [{ ...stringIssue, abortEarly: true }], } satisfies FailureDataset>); }); test('for wrong nested items', async () => { const nestedSchema = looseTupleAsync([schema, schema]); const input: [[string, string, boolean], null] = [ ['foo', '123', false], null, ]; expect(await nestedSchema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: '123', expected: 'number', received: '"123"', path: [ { type: 'array', origin: 'value', input: input, key: 0, value: input[0], }, { type: 'array', origin: 'value', input: input[0], key: 1, value: input[0][1], }, ], }, { ...baseInfo, kind: 'schema', type: 'loose_tuple', input: null, expected: 'Array', received: 'null', path: [ { type: 'array', origin: 'value', input: input, key: 1, value: input[1], }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/looseTuple/looseTupleAsync.ts ================================================ import type { ArrayPathItem, BaseIssue, BaseSchemaAsync, ErrorMessage, InferTupleInput, InferTupleIssue, InferTupleOutput, OutputDataset, TupleItemsAsync, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { looseTuple } from './looseTuple.ts'; import type { LooseTupleIssue } from './types.ts'; /** * Loose tuple schema async interface. */ export interface LooseTupleSchemaAsync< TItems extends TupleItemsAsync, TMessage extends ErrorMessage | undefined, > extends BaseSchemaAsync< [...InferTupleInput, ...unknown[]], [...InferTupleOutput, ...unknown[]], LooseTupleIssue | InferTupleIssue > { /** * The schema type. */ readonly type: 'loose_tuple'; /** * The schema reference. */ readonly reference: typeof looseTuple | typeof looseTupleAsync; /** * The expected property. */ readonly expects: 'Array'; /** * The items schema. */ readonly items: TItems; /** * The error message. */ readonly message: TMessage; } /** * Creates a loose tuple schema. * * @param items The items schema. * * @returns A loose tuple schema. */ export function looseTupleAsync( items: TItems ): LooseTupleSchemaAsync; /** * Creates a loose tuple schema. * * @param items The items schema. * @param message The error message. * * @returns A loose tuple schema. */ export function looseTupleAsync< const TItems extends TupleItemsAsync, const TMessage extends ErrorMessage | undefined, >(items: TItems, message: TMessage): LooseTupleSchemaAsync; // @__NO_SIDE_EFFECTS__ export function looseTupleAsync( items: TupleItemsAsync, message?: ErrorMessage ): LooseTupleSchemaAsync< TupleItemsAsync, ErrorMessage | undefined > { return { kind: 'schema', type: 'loose_tuple', reference: looseTupleAsync, expects: 'Array', async: true, items, message, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (Array.isArray(input)) { // Set typed to `true` and value to empty array // @ts-expect-error dataset.typed = true; dataset.value = []; // Parse schema of each tuple item const itemDatasets = await Promise.all( this.items.map(async (item, key) => { const value = input[key]; return [key, value, await item['~run']({ value }, config)] as const; }) ); // Process each tuple item dataset for (const [key, value, itemDataset] of itemDatasets) { // If there are issues, capture them if (itemDataset.issues) { // Create tuple path item const pathItem: ArrayPathItem = { type: 'array', origin: 'value', input, key, value, }; // Add modified item dataset issues to issues for (const issue of itemDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = itemDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!itemDataset.typed) { dataset.typed = false; } // Add item to dataset // @ts-expect-error dataset.value.push(itemDataset.value); } // Add rest to dataset if necessary if (!dataset.issues || !config.abortEarly) { for (let key = this.items.length; key < input.length; key++) { // @ts-expect-error dataset.value.push(input[key]); } } // Otherwise, add tuple issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< unknown[], LooseTupleIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/looseTuple/types.ts ================================================ import type { BaseIssue } from '../../types/index.ts'; /** * Loose tuple issue interface. */ export interface LooseTupleIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'loose_tuple'; /** * The expected property. */ readonly expected: 'Array'; } ================================================ FILE: library/src/schemas/map/index.ts ================================================ export * from './map.ts'; export * from './mapAsync.ts'; export type { MapIssue } from './types.ts'; ================================================ FILE: library/src/schemas/map/map.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { number, type NumberIssue, type NumberSchema, } from '../number/index.ts'; import type { OptionalSchema } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { map, type MapSchema } from './map.ts'; import type { MapIssue } from './types.ts'; describe('map', () => { describe('should return schema object', () => { const key = number(); type Key = typeof key; const value = string(); type Value = typeof value; test('with undefined message', () => { type Schema = MapSchema; expectTypeOf(map(key, value)).toEqualTypeOf(); expectTypeOf(map(key, value, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(map(key, value, 'message')).toEqualTypeOf< MapSchema >(); }); test('with function message', () => { expectTypeOf(map(key, value, () => 'message')).toEqualTypeOf< MapSchema string> >(); }); }); describe('should infer correct types', () => { type Schema = MapSchema< OptionalSchema, 123>, OptionalSchema, 'foo'>, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf< Map >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< MapIssue | NumberIssue | StringIssue >(); }); }); }); ================================================ FILE: library/src/schemas/map/map.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { number } from '../number/index.ts'; import { string, type StringIssue } from '../string/index.ts'; import { map, type MapSchema } from './map.ts'; import type { MapIssue } from './types.ts'; describe('map', () => { describe('should return schema object', () => { const key = number(); type Key = typeof key; const value = string(); type Value = typeof value; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'map', reference: map, expects: 'Map', key, value, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: MapSchema = { ...baseSchema, message: undefined, }; expect(map(key, value)).toStrictEqual(schema); expect(map(key, value, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(map(key, value, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies MapSchema); }); test('with function message', () => { const message = () => 'message'; expect(map(key, value, message)).toStrictEqual({ ...baseSchema, message, } satisfies MapSchema); }); }); describe('should return dataset without issues', () => { const schema = map(number(), string()); test('for empty map', () => { expectNoSchemaIssue(schema, [new Map()]); }); test('for simple map', () => { expectNoSchemaIssue(schema, [ new Map([ [0, 'foo'], [1, 'bar'], [2, 'baz'], ]), ]); }); }); describe('should return dataset with issues', () => { const schema = map(number(), string(), 'message'); const baseIssue: Omit = { kind: 'schema', type: 'map', expected: 'Map', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); describe('should return dataset without nested issues', () => { const schema = map(number(), string()); test('for simple map', () => { expectNoSchemaIssue(schema, [ new Map([ [0, 'foo'], [1, 'bar'], [2, 'baz'], ]), ]); }); test('for nested map', () => { expectNoSchemaIssue(map(schema, schema), [ new Map([ [ new Map([ [0, 'foo'], [1, 'bar'], ]), new Map([[3, 'baz']]), ], ]), ]); }); }); describe('should return dataset with nested issues', () => { const schema = map(number(), string()); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const input = new Map([ [0, 'foo'], [1, 123], // Invalid value [2, 'baz'], [null, 'bar'], // Invalid key [4, null], // Invalid value ]); const stringIssue: StringIssue = { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'map', origin: 'value', input, key: 1, value: 123, }, ], }; test('for invalid values', () => { expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ stringIssue, { ...baseInfo, kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', path: [ { type: 'map', origin: 'key', input, key: null, value: 'bar', }, ], }, { ...baseInfo, kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', path: [ { type: 'map', origin: 'value', input, key: 4, value: null, }, ], }, ], } satisfies FailureDataset>); }); test('with abort early for invalid key', () => { const input = new Map([ [0, 'foo'], ['1', 'bar'], // Invalid key [2, 'baz'], [3, 123], // Invalid value ]); expect( schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: new Map([[0, 'foo']]), issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: '1', expected: 'number', received: '"1"', path: [ { type: 'map', origin: 'key', input, key: '1', value: 'bar', }, ], abortEarly: true, }, ], } satisfies FailureDataset>); }); test('with abort early for invalid value', () => { expect( schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: new Map([[0, 'foo']]), issues: [{ ...stringIssue, abortEarly: true }], } satisfies FailureDataset>); }); test('for invalid nested values', () => { const nestedSchema = map(schema, schema); const input = new Map([ [ new Map([ [0, 123], [1, 'foo'], ]), new Map(), ], [new Map(), 'bar'], [ new Map(), new Map([ [0, 'foo'], ['1', 'bar'], ]), ], ]); expect(nestedSchema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'map', origin: 'key', input, key: new Map([ [0, 123], [1, 'foo'], ]), value: new Map(), }, { type: 'map', origin: 'value', input: new Map([ [0, 123], [1, 'foo'], ]), key: 0, value: 123, }, ], }, { ...baseInfo, kind: 'schema', type: 'map', input: 'bar', expected: 'Map', received: '"bar"', path: [ { type: 'map', origin: 'value', input, key: new Map(), value: 'bar', }, ], }, { ...baseInfo, kind: 'schema', type: 'number', input: '1', expected: 'number', received: '"1"', path: [ { type: 'map', origin: 'value', input, key: new Map(), value: new Map([ [0, 'foo'], ['1', 'bar'], ]), }, { type: 'map', origin: 'key', input: new Map([ [0, 'foo'], ['1', 'bar'], ]), key: '1', value: 'bar', }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/map/map.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, InferIssue, MapPathItem, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { InferMapInput, InferMapOutput, MapIssue } from './types.ts'; /** * Map schema interface. */ export interface MapSchema< TKey extends BaseSchema>, TValue extends BaseSchema>, TMessage extends ErrorMessage | undefined, > extends BaseSchema< InferMapInput, InferMapOutput, MapIssue | InferIssue | InferIssue > { /** * The schema type. */ readonly type: 'map'; /** * The schema reference. */ readonly reference: typeof map; /** * The expected property. */ readonly expects: 'Map'; /** * The map key schema. */ readonly key: TKey; /** * The map value schema. */ readonly value: TValue; /** * The error message. */ readonly message: TMessage; } /** * Creates a map schema. * * @param key The key schema. * @param value The value schema. * * @returns A map schema. */ export function map< const TKey extends BaseSchema>, const TValue extends BaseSchema>, >(key: TKey, value: TValue): MapSchema; /** * Creates a map schema. * * @param key The key schema. * @param value The value schema. * @param message The error message. * * @returns A map schema. */ export function map< const TKey extends BaseSchema>, const TValue extends BaseSchema>, const TMessage extends ErrorMessage | undefined, >( key: TKey, value: TValue, message: TMessage ): MapSchema; // @__NO_SIDE_EFFECTS__ export function map( key: BaseSchema>, value: BaseSchema>, message?: ErrorMessage ): MapSchema< BaseSchema>, BaseSchema>, ErrorMessage | undefined > { return { kind: 'schema', type: 'map', reference: map, expects: 'Map', async: false, key, value, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (input instanceof Map) { // Set typed to `true` and value to empty map // @ts-expect-error dataset.typed = true; dataset.value = new Map(); // Parse schema of each map entry for (const [inputKey, inputValue] of input) { // Get dataset of key schema const keyDataset = this.key['~run']({ value: inputKey }, config); // If there are issues, capture them if (keyDataset.issues) { // Create map path item const pathItem: MapPathItem = { type: 'map', origin: 'key', input, key: inputKey, value: inputValue, }; // Add modified item dataset issues to issues for (const issue of keyDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = keyDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // Get dataset of value schema const valueDataset = this.value['~run']( { value: inputValue }, config ); // If there are issues, capture them if (valueDataset.issues) { // Create map path item const pathItem: MapPathItem = { type: 'map', origin: 'value', input, key: inputKey, value: inputValue, }; // Add modified item dataset issues to issues for (const issue of valueDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = valueDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, map typed to `false` if (!keyDataset.typed || !valueDataset.typed) { dataset.typed = false; } // Add value to dataset // @ts-expect-error dataset.value.set(keyDataset.value, valueDataset.value); } // Otherwise, add map issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< Map, MapIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/map/mapAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { number, type NumberIssue, type NumberSchema, } from '../number/index.ts'; import type { OptionalSchema, OptionalSchemaAsync } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { mapAsync, type MapSchemaAsync } from './mapAsync.ts'; import type { MapIssue } from './types.ts'; describe('mapAsync', () => { describe('should return schema object', () => { const key = number(); type Key = typeof key; const value = string(); type Value = typeof value; test('with undefined message', () => { type Schema = MapSchemaAsync; expectTypeOf(mapAsync(key, value)).toEqualTypeOf(); expectTypeOf(mapAsync(key, value, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(mapAsync(key, value, 'message')).toEqualTypeOf< MapSchemaAsync >(); }); test('with function message', () => { expectTypeOf(mapAsync(key, value, () => 'message')).toEqualTypeOf< MapSchemaAsync string> >(); }); }); describe('should infer correct types', () => { type Schema = MapSchemaAsync< OptionalSchema, 123>, OptionalSchemaAsync, 'foo'>, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf< Map >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< MapIssue | NumberIssue | StringIssue >(); }); }); }); ================================================ FILE: library/src/schemas/map/mapAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { number } from '../number/index.ts'; import { string, type StringIssue } from '../string/index.ts'; import { mapAsync, type MapSchemaAsync } from './mapAsync.ts'; import type { MapIssue } from './types.ts'; describe('mapAsync', () => { describe('should return schema object', () => { const key = number(); type Key = typeof key; const value = string(); type Value = typeof value; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'map', reference: mapAsync, expects: 'Map', key, value, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: MapSchemaAsync = { ...baseSchema, message: undefined, }; expect(mapAsync(key, value)).toStrictEqual(schema); expect(mapAsync(key, value, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(mapAsync(key, value, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies MapSchemaAsync); }); test('with function message', () => { const message = () => 'message'; expect(mapAsync(key, value, message)).toStrictEqual({ ...baseSchema, message, } satisfies MapSchemaAsync); }); }); describe('should return dataset without issues', () => { const schema = mapAsync(number(), string()); test('for empty mapAsync', async () => { await expectNoSchemaIssueAsync(schema, [new Map()]); }); test('for simple mapAsync', async () => { await expectNoSchemaIssueAsync(schema, [ new Map([ [0, 'foo'], [1, 'bar'], [2, 'baz'], ]), ]); }); }); describe('should return dataset with issues', () => { const schema = mapAsync(number(), string(), 'message'); const baseIssue: Omit = { kind: 'schema', type: 'map', expected: 'Map', message: 'message', }; // Primitive types test('for bigints', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', async () => { await expectSchemaIssueAsync(schema, baseIssue, [true, false]); }); test('for null', async () => { await expectSchemaIssueAsync(schema, baseIssue, [null]); }); test('for numbers', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', async () => { await expectSchemaIssueAsync(schema, baseIssue, [undefined]); }); test('for strings', async () => { await expectSchemaIssueAsync(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ Symbol(), Symbol('foo'), ]); }); // Complex types test('for arrays', async () => { await expectSchemaIssueAsync(schema, baseIssue, [[], ['value']]); }); test('for functions', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ // eslint-disable-next-line @typescript-eslint/no-empty-function () => {}, // eslint-disable-next-line @typescript-eslint/no-empty-function function () {}, ]); }); test('for objects', async () => { await expectSchemaIssueAsync(schema, baseIssue, [{}, { key: 'value' }]); }); }); describe('should return dataset without nested issues', () => { const schema = mapAsync(number(), string()); test('for simple mapAsync', async () => { await expectNoSchemaIssueAsync(schema, [ new Map([ [0, 'foo'], [1, 'bar'], [2, 'baz'], ]), ]); }); test('for nested mapAsync', async () => { await expectNoSchemaIssueAsync(mapAsync(schema, schema), [ new Map([ [ new Map([ [0, 'foo'], [1, 'bar'], ]), new Map([[3, 'baz']]), ], ]), ]); }); }); describe('should return dataset with nested issues', () => { const schema = mapAsync(number(), string()); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const input = new Map([ [0, 'foo'], [1, 123], // Invalid value [2, 'baz'], [null, 'bar'], // Invalid key [4, null], // Invalid value ]); const stringIssue: StringIssue = { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'map', origin: 'value', input, key: 1, value: 123, }, ], }; test('for invalid values', async () => { expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ stringIssue, { ...baseInfo, kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', path: [ { type: 'map', origin: 'key', input, key: null, value: 'bar', }, ], }, { ...baseInfo, kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', path: [ { type: 'map', origin: 'value', input, key: 4, value: null, }, ], }, ], } satisfies FailureDataset>); }); test('with abort early for invalid key', async () => { const input = new Map([ [0, 'foo'], ['1', 'bar'], // Invalid key [2, 'baz'], [3, 123], // Invalid value ]); expect( await schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: new Map([[0, 'foo']]), issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: '1', expected: 'number', received: '"1"', path: [ { type: 'map', origin: 'key', input, key: '1', value: 'bar', }, ], abortEarly: true, }, ], } satisfies FailureDataset>); }); test('with abort early for invalid value', async () => { expect( await schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: new Map([[0, 'foo']]), issues: [{ ...stringIssue, abortEarly: true }], } satisfies FailureDataset>); }); test('for invalid nested values', async () => { const nestedSchema = mapAsync(schema, schema); const input = new Map([ [ new Map([ [0, 123], [1, 'foo'], ]), new Map(), ], [new Map(), 'bar'], [ new Map(), new Map([ [0, 'foo'], ['1', 'bar'], ]), ], ]); expect(await nestedSchema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'map', origin: 'key', input, key: new Map([ [0, 123], [1, 'foo'], ]), value: new Map(), }, { type: 'map', origin: 'value', input: new Map([ [0, 123], [1, 'foo'], ]), key: 0, value: 123, }, ], }, { ...baseInfo, kind: 'schema', type: 'map', input: 'bar', expected: 'Map', received: '"bar"', path: [ { type: 'map', origin: 'value', input, key: new Map(), value: 'bar', }, ], }, { ...baseInfo, kind: 'schema', type: 'number', input: '1', expected: 'number', received: '"1"', path: [ { type: 'map', origin: 'value', input, key: new Map(), value: new Map([ [0, 'foo'], ['1', 'bar'], ]), }, { type: 'map', origin: 'key', input: new Map([ [0, 'foo'], ['1', 'bar'], ]), key: '1', value: 'bar', }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/map/mapAsync.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, ErrorMessage, InferIssue, MapPathItem, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { map } from './map.ts'; import type { InferMapInput, InferMapOutput, MapIssue } from './types.ts'; /** * Map schema async interface. */ export interface MapSchemaAsync< TKey extends | BaseSchema> | BaseSchemaAsync>, TValue extends | BaseSchema> | BaseSchemaAsync>, TMessage extends ErrorMessage | undefined, > extends BaseSchemaAsync< InferMapInput, InferMapOutput, MapIssue | InferIssue | InferIssue > { /** * The schema type. */ readonly type: 'map'; /** * The schema reference. */ readonly reference: typeof map | typeof mapAsync; /** * The expected property. */ readonly expects: 'Map'; /** * The map key schema. */ readonly key: TKey; /** * The map value schema. */ readonly value: TValue; /** * The error message. */ readonly message: TMessage; } /** * Creates a map schema. * * @param key The key schema. * @param value The value schema. * * @returns A map schema. */ export function mapAsync< const TKey extends | BaseSchema> | BaseSchemaAsync>, const TValue extends | BaseSchema> | BaseSchemaAsync>, >(key: TKey, value: TValue): MapSchemaAsync; /** * Creates a map schema. * * @param key The key schema. * @param value The value schema. * @param message The error message. * * @returns A map schema. */ export function mapAsync< const TKey extends | BaseSchema> | BaseSchemaAsync>, const TValue extends | BaseSchema> | BaseSchemaAsync>, const TMessage extends ErrorMessage | undefined, >( key: TKey, value: TValue, message: TMessage ): MapSchemaAsync; // @__NO_SIDE_EFFECTS__ export function mapAsync( key: | BaseSchema> | BaseSchemaAsync>, value: | BaseSchema> | BaseSchemaAsync>, message?: ErrorMessage ): MapSchemaAsync< | BaseSchema> | BaseSchemaAsync>, | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined > { return { kind: 'schema', type: 'map', reference: mapAsync, expects: 'Map', async: true, key, value, message, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (input instanceof Map) { // Set typed to `true` and value to empty map // @ts-expect-error dataset.typed = true; dataset.value = new Map(); // Parse schema of each map entry const datasets = await Promise.all( [...input].map(([inputKey, inputValue]) => Promise.all([ inputKey, inputValue, this.key['~run']({ value: inputKey }, config), this.value['~run']({ value: inputValue }, config), ]) ) ); // Process datasets of each map entry for (const [ inputKey, inputValue, keyDataset, valueDataset, ] of datasets) { // If there are issues, capture them if (keyDataset.issues) { // Create map path item const pathItem: MapPathItem = { type: 'map', origin: 'key', input, key: inputKey, value: inputValue, }; // Add modified item dataset issues to issues for (const issue of keyDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = keyDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If there are issues, capture them if (valueDataset.issues) { // Create map path item const pathItem: MapPathItem = { type: 'map', origin: 'value', input, key: inputKey, value: inputValue, }; // Add modified item dataset issues to issues for (const issue of valueDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = valueDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, map typed to `false` if (!keyDataset.typed || !valueDataset.typed) { dataset.typed = false; } // Add value to dataset // @ts-expect-error dataset.value.set(keyDataset.value, valueDataset.value); } // Otherwise, add map issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< Map, MapIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/map/types.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, InferInput, InferOutput, } from '../../types/index.ts'; /** * Map issue interface. */ export interface MapIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'map'; /** * The expected property. */ readonly expected: 'Map'; } /** * Infer map input type. */ export type InferMapInput< TKey extends | BaseSchema> | BaseSchemaAsync>, TValue extends | BaseSchema> | BaseSchemaAsync>, > = Map, InferInput>; /** * Infer map output type. */ export type InferMapOutput< TKey extends | BaseSchema> | BaseSchemaAsync>, TValue extends | BaseSchema> | BaseSchemaAsync>, > = Map, InferOutput>; ================================================ FILE: library/src/schemas/nan/index.ts ================================================ export * from './nan.ts'; ================================================ FILE: library/src/schemas/nan/nan.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { nan, type NanIssue, type NanSchema } from './nan.ts'; describe('nan', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = NanSchema; expectTypeOf(nan()).toEqualTypeOf(); expectTypeOf(nan(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(nan('message')).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf(nan(() => 'message')).toEqualTypeOf< NanSchema<() => string> >(); }); }); describe('should infer correct types', () => { type Schema = NanSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/nan/nan.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { nan, type NanIssue, type NanSchema } from './nan.ts'; describe('nan', () => { describe('should return schema object', () => { const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'nan', reference: nan, expects: 'NaN', async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: NanSchema = { ...baseSchema, message: undefined, }; expect(nan()).toStrictEqual(schema); expect(nan(undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(nan('message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies NanSchema<'message'>); }); test('with function message', () => { const message = () => 'message'; expect(nan(message)).toStrictEqual({ ...baseSchema, message, } satisfies NanSchema); }); }); describe('should return dataset without issues', () => { const schema = nan(); test('for NaN', () => { expectNoSchemaIssue(schema, [NaN, Number.NaN]); }); }); describe('should return dataset with issues', () => { const schema = nan('message'); const baseIssue: Omit = { kind: 'schema', type: 'nan', expected: 'NaN', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'foo', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); }); ================================================ FILE: library/src/schemas/nan/nan.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; /** * NaN issue interface. */ export interface NanIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'nan'; /** * The expected property. */ readonly expected: 'NaN'; } /** * NaN schema interface. */ export interface NanSchema | undefined> extends BaseSchema { /** * The schema type. */ readonly type: 'nan'; /** * The schema reference. */ readonly reference: typeof nan; /** * The expected property. */ readonly expects: 'NaN'; /** * The error message. */ readonly message: TMessage; } /** * Creates a NaN schema. * * @returns A NaN schema. */ export function nan(): NanSchema; /** * Creates a NaN schema. * * @param message The error message. * * @returns A NaN schema. */ export function nan | undefined>( message: TMessage ): NanSchema; // @__NO_SIDE_EFFECTS__ export function nan( message?: ErrorMessage ): NanSchema | undefined> { return { kind: 'schema', type: 'nan', reference: nan, expects: 'NaN', async: false, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { if (Number.isNaN(dataset.value)) { // @ts-expect-error dataset.typed = true; } else { _addIssue(this, 'type', dataset, config); } // @ts-expect-error return dataset as OutputDataset; }, }; } ================================================ FILE: library/src/schemas/never/index.ts ================================================ export * from './never.ts'; ================================================ FILE: library/src/schemas/never/never.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { never, type NeverIssue, type NeverSchema } from './never.ts'; describe('never', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = NeverSchema; expectTypeOf(never()).toEqualTypeOf(); expectTypeOf(never(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(never('message')).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf(never(() => 'message')).toEqualTypeOf< NeverSchema<() => string> >(); }); }); describe('should infer correct types', () => { type Schema = NeverSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/never/never.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectSchemaIssue } from '../../vitest/index.ts'; import { never, type NeverIssue, type NeverSchema } from './never.ts'; describe('never', () => { describe('should return schema object', () => { const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'never', reference: never, expects: 'never', async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: NeverSchema = { ...baseSchema, message: undefined, }; expect(never()).toStrictEqual(schema); expect(never(undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(never('message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies NeverSchema<'message'>); }); test('with function message', () => { const message = () => 'message'; expect(never(message)).toStrictEqual({ ...baseSchema, message, } satisfies NeverSchema); }); }); describe('should return dataset with issues', () => { const schema = never('message'); const baseIssue: Omit = { kind: 'schema', type: 'never', expected: 'never', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', '0', '-2', '12.34']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); }); ================================================ FILE: library/src/schemas/never/never.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, FailureDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; /** * Never issue interface. */ export interface NeverIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'never'; /** * The expected property. */ readonly expected: 'never'; } /** * Never schema interface. */ export interface NeverSchema< TMessage extends ErrorMessage | undefined, > extends BaseSchema { /** * The schema type. */ readonly type: 'never'; /** * The schema reference. */ readonly reference: typeof never; /** * The expected property. */ readonly expects: 'never'; /** * The error message. */ readonly message: TMessage; } /** * Creates a never schema. * * @returns A never schema. */ export function never(): NeverSchema; /** * Creates a never schema. * * @param message The error message. * * @returns A never schema. */ export function never< const TMessage extends ErrorMessage | undefined, >(message: TMessage): NeverSchema; // @__NO_SIDE_EFFECTS__ export function never( message?: ErrorMessage ): NeverSchema | undefined> { return { kind: 'schema', type: 'never', reference: never, expects: 'never', async: false, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { _addIssue(this, 'type', dataset, config); // @ts-expect-error return dataset as FailureDataset; }, }; } ================================================ FILE: library/src/schemas/nonNullable/index.ts ================================================ export * from './nonNullable.ts'; export * from './nonNullableAsync.ts'; export type { NonNullableIssue } from './types.ts'; ================================================ FILE: library/src/schemas/nonNullable/nonNullable.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { NullSchema } from '../null/index.ts'; import { nullish, type NullishSchema } from '../nullish/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import type { UndefinedIssue, UndefinedSchema, } from '../undefined/undefined.ts'; import type { UnionIssue, UnionSchema } from '../union/index.ts'; import { nonNullable, type NonNullableSchema } from './nonNullable.ts'; import type { NonNullableIssue } from './types.ts'; describe('nonNullable', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = NonNullableSchema< NullishSchema, undefined>, undefined >; expectTypeOf(nonNullable(nullish(string()))).toEqualTypeOf(); expectTypeOf( nonNullable(nullish(string()), undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(nonNullable(nullish(string()), 'message')).toEqualTypeOf< NonNullableSchema< NullishSchema, undefined>, 'message' > >(); }); test('with function message', () => { expectTypeOf( nonNullable(nullish(string()), () => 'message') ).toEqualTypeOf< NonNullableSchema< NullishSchema, undefined>, () => string > >(); }); }); describe('should infer correct types', () => { type Schema = NonNullableSchema< NullishSchema, undefined>, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< NonNullableIssue | StringIssue >(); expectTypeOf< InferIssue< NonNullableSchema< UnionSchema< [ StringSchema, NullSchema, UndefinedSchema, ], undefined >, undefined > > >().toEqualTypeOf< | NonNullableIssue | StringIssue | UndefinedIssue | UnionIssue >(); }); }); }); ================================================ FILE: library/src/schemas/nonNullable/nonNullable.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { pipe } from '../../methods/index.ts'; import type { FailureDataset } from '../../types/index.ts'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { nullish, type NullishSchema } from '../nullish/index.ts'; import { string, type StringSchema } from '../string/index.ts'; import { nonNullable, type NonNullableSchema } from './nonNullable.ts'; import type { NonNullableIssue } from './types.ts'; describe('nonNullable', () => { describe('should return schema object', () => { const wrapped = nullish(string()); const baseSchema: Omit< NonNullableSchema< NullishSchema, undefined>, never >, 'message' > = { kind: 'schema', type: 'non_nullable', reference: nonNullable, expects: '!null', wrapped, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: NonNullableSchema< NullishSchema, undefined>, undefined > = { ...baseSchema, message: undefined, }; expect(nonNullable(wrapped)).toStrictEqual(schema); expect(nonNullable(wrapped, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(nonNullable(wrapped, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies NonNullableSchema< NullishSchema, undefined>, 'message' >); }); test('with function message', () => { const message = () => 'message'; expect(nonNullable(wrapped, message)).toStrictEqual({ ...baseSchema, message, } satisfies NonNullableSchema< NullishSchema, undefined>, typeof message >); }); }); describe('should return dataset without issues', () => { const schema = nonNullable(nullish(string())); test('for valid wrapped types', () => { expectNoSchemaIssue(schema, ['', 'foo', '#$%', undefined]); }); }); describe('should return dataset with issues', () => { const nonNullableIssue: NonNullableIssue = { kind: 'schema', type: 'non_nullable', input: null, received: 'null', expected: '!null', message: 'message', requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for null input', () => { expectSchemaIssue( nonNullable(nullish(string()), 'message'), nonNullableIssue, [null] ); }); test('for null output', () => { expect( nonNullable( pipe( string(), transform(() => null) ), 'message' )['~run']({ value: 'foo' }, {}) ).toStrictEqual({ typed: false, value: null, issues: [nonNullableIssue], } satisfies FailureDataset); }); }); }); ================================================ FILE: library/src/schemas/nonNullable/nonNullable.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { InferNonNullableInput, InferNonNullableIssue, InferNonNullableOutput, NonNullableIssue, } from './types.ts'; /** * Non nullable schema interface. */ export interface NonNullableSchema< TWrapped extends BaseSchema>, TMessage extends ErrorMessage | undefined, > extends BaseSchema< InferNonNullableInput, InferNonNullableOutput, NonNullableIssue | InferNonNullableIssue > { /** * The schema type. */ readonly type: 'non_nullable'; /** * The schema reference. */ readonly reference: typeof nonNullable; /** * The expected property. */ readonly expects: '!null'; /** * The wrapped schema. */ readonly wrapped: TWrapped; /** * The error message. */ readonly message: TMessage; } /** * Creates a non nullable schema. * * @param wrapped The wrapped schema. * * @returns A non nullable schema. */ export function nonNullable< const TWrapped extends BaseSchema>, >(wrapped: TWrapped): NonNullableSchema; /** * Creates a non nullable schema. * * @param wrapped The wrapped schema. * @param message The error message. * * @returns A non nullable schema. */ export function nonNullable< const TWrapped extends BaseSchema>, const TMessage extends ErrorMessage | undefined, >(wrapped: TWrapped, message: TMessage): NonNullableSchema; // @__NO_SIDE_EFFECTS__ export function nonNullable( wrapped: BaseSchema>, message?: ErrorMessage | undefined ): NonNullableSchema< BaseSchema>, ErrorMessage | undefined > { return { kind: 'schema', type: 'non_nullable', reference: nonNullable, expects: '!null', async: false, wrapped, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // If value is not `null`, run wrapped schema if (dataset.value !== null) { // @ts-expect-error dataset = this.wrapped['~run'](dataset, config); } // If value is `null`, add issue to dataset if (dataset.value === null) { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset>; }, }; } ================================================ FILE: library/src/schemas/nonNullable/nonNullableAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { NullSchema } from '../null/index.ts'; import { nullishAsync, type NullishSchemaAsync } from '../nullish/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import type { UndefinedIssue, UndefinedSchema, } from '../undefined/undefined.ts'; import type { UnionIssue, UnionSchema } from '../union/index.ts'; import { nonNullableAsync, type NonNullableSchemaAsync, } from './nonNullableAsync.ts'; import type { NonNullableIssue } from './types.ts'; describe('nonNullableAsync', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = NonNullableSchemaAsync< NullishSchemaAsync, undefined>, undefined >; expectTypeOf( nonNullableAsync(nullishAsync(string())) ).toEqualTypeOf(); expectTypeOf( nonNullableAsync(nullishAsync(string()), undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( nonNullableAsync(nullishAsync(string()), 'message') ).toEqualTypeOf< NonNullableSchemaAsync< NullishSchemaAsync, undefined>, 'message' > >(); }); test('with function message', () => { expectTypeOf( nonNullableAsync(nullishAsync(string()), () => 'message') ).toEqualTypeOf< NonNullableSchemaAsync< NullishSchemaAsync, undefined>, () => string > >(); }); }); describe('should infer correct types', () => { type Schema = NonNullableSchemaAsync< NullishSchemaAsync, undefined>, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< NonNullableIssue | StringIssue >(); expectTypeOf< InferIssue< NonNullableSchemaAsync< UnionSchema< [ StringSchema, NullSchema, UndefinedSchema, ], undefined >, undefined > > >().toEqualTypeOf< | NonNullableIssue | StringIssue | UndefinedIssue | UnionIssue >(); }); }); }); ================================================ FILE: library/src/schemas/nonNullable/nonNullableAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { pipeAsync } from '../../methods/index.ts'; import type { FailureDataset } from '../../types/index.ts'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { nullishAsync, type NullishSchemaAsync } from '../nullish/index.ts'; import { string, type StringSchema } from '../string/index.ts'; import { nonNullableAsync, type NonNullableSchemaAsync, } from './nonNullableAsync.ts'; import type { NonNullableIssue } from './types.ts'; describe('nonNullableAsync', () => { describe('should return schema object', () => { const wrapped = nullishAsync(string()); const baseSchema: Omit< NonNullableSchemaAsync< NullishSchemaAsync, undefined>, never >, 'message' > = { kind: 'schema', type: 'non_nullable', reference: nonNullableAsync, expects: '!null', wrapped, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: NonNullableSchemaAsync< NullishSchemaAsync, undefined>, undefined > = { ...baseSchema, message: undefined, }; expect(nonNullableAsync(wrapped)).toStrictEqual(schema); expect(nonNullableAsync(wrapped, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(nonNullableAsync(wrapped, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies NonNullableSchemaAsync< NullishSchemaAsync, undefined>, 'message' >); }); test('with function message', () => { const message = () => 'message'; expect(nonNullableAsync(wrapped, message)).toStrictEqual({ ...baseSchema, message, } satisfies NonNullableSchemaAsync< NullishSchemaAsync, undefined>, typeof message >); }); }); describe('should return dataset without issues', () => { const schema = nonNullableAsync(nullishAsync(string())); test('for valid wrapped types', async () => { await expectNoSchemaIssueAsync(schema, ['', 'foo', '#$%', undefined]); }); }); describe('should return dataset with issues', () => { const nonNullableIssue: NonNullableIssue = { kind: 'schema', type: 'non_nullable', input: null, received: 'null', expected: '!null', message: 'message', requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for null input', async () => { await expectSchemaIssueAsync( nonNullableAsync(nullishAsync(string()), 'message'), nonNullableIssue, [null] ); }); test('for null output', async () => { expect( await nonNullableAsync( pipeAsync( string(), transform(() => null) ), 'message' )['~run']({ value: 'foo' }, {}) ).toStrictEqual({ typed: false, value: null, issues: [nonNullableIssue], } satisfies FailureDataset); }); }); }); ================================================ FILE: library/src/schemas/nonNullable/nonNullableAsync.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { nonNullable } from './nonNullable.ts'; import type { InferNonNullableInput, InferNonNullableIssue, InferNonNullableOutput, NonNullableIssue, } from './types.ts'; /** * Non nullable schema async interface. */ export interface NonNullableSchemaAsync< TWrapped extends | BaseSchema> | BaseSchemaAsync>, TMessage extends ErrorMessage | undefined, > extends BaseSchemaAsync< InferNonNullableInput, InferNonNullableOutput, NonNullableIssue | InferNonNullableIssue > { /** * The schema type. */ readonly type: 'non_nullable'; /** * The schema reference. */ readonly reference: typeof nonNullable | typeof nonNullableAsync; /** * The expected property. */ readonly expects: '!null'; /** * The wrapped schema. */ readonly wrapped: TWrapped; /** * The error message. */ readonly message: TMessage; } /** * Creates a non nullable schema. * * @param wrapped The wrapped schema. * * @returns A non nullable schema. */ export function nonNullableAsync< const TWrapped extends | BaseSchema> | BaseSchemaAsync>, >(wrapped: TWrapped): NonNullableSchemaAsync; /** * Creates a non nullable schema. * * @param wrapped The wrapped schema. * @param message The error message. * * @returns A non nullable schema. */ export function nonNullableAsync< const TWrapped extends | BaseSchema> | BaseSchemaAsync>, const TMessage extends ErrorMessage | undefined, >( wrapped: TWrapped, message: TMessage ): NonNullableSchemaAsync; // @__NO_SIDE_EFFECTS__ export function nonNullableAsync( wrapped: | BaseSchema> | BaseSchemaAsync>, message?: ErrorMessage | undefined ): NonNullableSchemaAsync< | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined > { return { kind: 'schema', type: 'non_nullable', reference: nonNullableAsync, expects: '!null', async: true, wrapped, message, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // If value is not `null`, run wrapped schema if (dataset.value !== null) { // @ts-expect-error dataset = await this.wrapped['~run'](dataset, config); } // If value is `null`, add issue to dataset if (dataset.value === null) { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset>; }, }; } ================================================ FILE: library/src/schemas/nonNullable/types.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, ErrorMessage, InferInput, InferIssue, InferOutput, NonNullable, } from '../../types/index.ts'; import type { UnionIssue, UnionOptions, UnionOptionsAsync, UnionSchema, UnionSchemaAsync, } from '../union/index.ts'; /** * Non nullable issue interface. */ export interface NonNullableIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'non_nullable'; /** * The expected property. */ readonly expected: '!null'; } /** * Infer non nullable input type. */ export type InferNonNullableInput< TWrapped extends | BaseSchema> | BaseSchemaAsync>, > = NonNullable>; /** * Infer non nullable output type. */ export type InferNonNullableOutput< TWrapped extends | BaseSchema> | BaseSchemaAsync>, > = NonNullable>; /** * Infer non nullable issue type. */ export type InferNonNullableIssue< TWrapped extends | BaseSchema> | BaseSchemaAsync>, > = TWrapped extends | UnionSchema< UnionOptions, ErrorMessage>> | undefined > | UnionSchemaAsync< UnionOptionsAsync, ErrorMessage>> | undefined > ? | Exclude, { type: 'null' | 'union' }> | UnionIssue> : Exclude, { type: 'null' }>; ================================================ FILE: library/src/schemas/nonNullish/index.ts ================================================ export * from './nonNullish.ts'; export * from './nonNullishAsync.ts'; export type { NonNullishIssue } from './types.ts'; ================================================ FILE: library/src/schemas/nonNullish/nonNullish.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { NullSchema } from '../null/index.ts'; import { nullish, type NullishSchema } from '../nullish/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import type { UndefinedSchema } from '../undefined/index.ts'; import type { UnionIssue, UnionSchema } from '../union/index.ts'; import { nonNullish, type NonNullishSchema } from './nonNullish.ts'; import type { NonNullishIssue } from './types.ts'; describe('nonNullish', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = NonNullishSchema< NullishSchema, undefined>, undefined >; expectTypeOf(nonNullish(nullish(string()))).toEqualTypeOf(); expectTypeOf( nonNullish(nullish(string()), undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(nonNullish(nullish(string()), 'message')).toEqualTypeOf< NonNullishSchema< NullishSchema, undefined>, 'message' > >(); }); test('with function message', () => { expectTypeOf( nonNullish(nullish(string()), () => 'message') ).toEqualTypeOf< NonNullishSchema< NullishSchema, undefined>, () => string > >(); }); }); describe('should infer correct types', () => { type Schema = NonNullishSchema< NullishSchema, undefined>, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< NonNullishIssue | StringIssue >(); expectTypeOf< InferIssue< NonNullishSchema< UnionSchema< [ StringSchema, NullSchema, UndefinedSchema, ], undefined >, undefined > > >().toEqualTypeOf< NonNullishIssue | StringIssue | UnionIssue >(); }); }); }); ================================================ FILE: library/src/schemas/nonNullish/nonNullish.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { pipe } from '../../methods/index.ts'; import type { FailureDataset } from '../../types/index.ts'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { nullish, type NullishSchema } from '../nullish/index.ts'; import { string, type StringSchema } from '../string/index.ts'; import { nonNullish, type NonNullishSchema } from './nonNullish.ts'; import type { NonNullishIssue } from './types.ts'; describe('nonNullish', () => { describe('should return schema object', () => { const wrapped = nullish(string()); const baseSchema: Omit< NonNullishSchema< NullishSchema, undefined>, never >, 'message' > = { kind: 'schema', type: 'non_nullish', reference: nonNullish, expects: '(!null & !undefined)', wrapped, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: NonNullishSchema< NullishSchema, undefined>, undefined > = { ...baseSchema, message: undefined, }; expect(nonNullish(wrapped)).toStrictEqual(schema); expect(nonNullish(wrapped, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(nonNullish(wrapped, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies NonNullishSchema< NullishSchema, undefined>, 'message' >); }); test('with function message', () => { const message = () => 'message'; expect(nonNullish(wrapped, message)).toStrictEqual({ ...baseSchema, message, } satisfies NonNullishSchema< NullishSchema, undefined>, typeof message >); }); }); describe('should return dataset without issues', () => { const schema = nonNullish(nullish(string())); test('for valid wrapped types', () => { expectNoSchemaIssue(schema, ['', 'foo', '#$%']); }); }); describe('should return dataset with issues', () => { const baseIssue: Omit = { kind: 'schema', type: 'non_nullish', expected: '(!null & !undefined)', message: 'message', requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for null input', () => { expectSchemaIssue(nonNullish(nullish(string()), 'message'), baseIssue, [ null, ]); }); test('for undefined input', () => { expectSchemaIssue(nonNullish(nullish(string()), 'message'), baseIssue, [ undefined, ]); }); test('for null output', () => { expect( nonNullish( pipe( string(), transform(() => null) ), 'message' )['~run']({ value: 'foo' }, {}) ).toStrictEqual({ typed: false, value: null, issues: [{ ...baseIssue, input: null, received: 'null' }], } satisfies FailureDataset); }); test('for undefined output', () => { expect( nonNullish( pipe( string(), transform(() => undefined) ), 'message' )['~run']({ value: 'foo' }, {}) ).toStrictEqual({ typed: false, value: undefined, issues: [{ ...baseIssue, input: undefined, received: 'undefined' }], } satisfies FailureDataset); }); }); }); ================================================ FILE: library/src/schemas/nonNullish/nonNullish.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { InferNonNullishInput, InferNonNullishIssue, InferNonNullishOutput, NonNullishIssue, } from './types.ts'; /** * Non nullish schema interface. */ export interface NonNullishSchema< TWrapped extends BaseSchema>, TMessage extends ErrorMessage | undefined, > extends BaseSchema< InferNonNullishInput, InferNonNullishOutput, NonNullishIssue | InferNonNullishIssue > { /** * The schema type. */ readonly type: 'non_nullish'; /** * The schema reference. */ readonly reference: typeof nonNullish; /** * The expected property. */ readonly expects: '(!null & !undefined)'; /** * The wrapped schema. */ readonly wrapped: TWrapped; /** * The error message. */ readonly message: TMessage; } /** * Creates a non nullish schema. * * @param wrapped The wrapped schema. * * @returns A non nullish schema. */ export function nonNullish< const TWrapped extends BaseSchema>, >(wrapped: TWrapped): NonNullishSchema; /** * Creates a non nullish schema. * * @param wrapped The wrapped schema. * @param message The error message. * * @returns A non nullish schema. */ export function nonNullish< const TWrapped extends BaseSchema>, const TMessage extends ErrorMessage | undefined, >(wrapped: TWrapped, message: TMessage): NonNullishSchema; // @__NO_SIDE_EFFECTS__ export function nonNullish( wrapped: BaseSchema>, message?: ErrorMessage | undefined ): NonNullishSchema< BaseSchema>, ErrorMessage | undefined > { return { kind: 'schema', type: 'non_nullish', reference: nonNullish, expects: '(!null & !undefined)', async: false, wrapped, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // If value is not `null` and `undefined`, run wrapped schema if (!(dataset.value === null || dataset.value === undefined)) { // @ts-expect-error dataset = this.wrapped['~run'](dataset, config); } // If value is `null` or `undefined`, add issue to dataset if (dataset.value === null || dataset.value === undefined) { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset>; }, }; } ================================================ FILE: library/src/schemas/nonNullish/nonNullishAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { NullSchema } from '../null/index.ts'; import { nullishAsync, type NullishSchemaAsync } from '../nullish/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import type { UndefinedSchema } from '../undefined/index.ts'; import type { UnionIssue, UnionSchema } from '../union/index.ts'; import { nonNullishAsync, type NonNullishSchemaAsync, } from './nonNullishAsync.ts'; import type { NonNullishIssue } from './types.ts'; describe('nonNullishAsync', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = NonNullishSchemaAsync< NullishSchemaAsync, undefined>, undefined >; expectTypeOf( nonNullishAsync(nullishAsync(string())) ).toEqualTypeOf(); expectTypeOf( nonNullishAsync(nullishAsync(string()), undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( nonNullishAsync(nullishAsync(string()), 'message') ).toEqualTypeOf< NonNullishSchemaAsync< NullishSchemaAsync, undefined>, 'message' > >(); }); test('with function message', () => { expectTypeOf( nonNullishAsync(nullishAsync(string()), () => 'message') ).toEqualTypeOf< NonNullishSchemaAsync< NullishSchemaAsync, undefined>, () => string > >(); }); }); describe('should infer correct types', () => { type Schema = NonNullishSchemaAsync< NullishSchemaAsync, undefined>, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< NonNullishIssue | StringIssue >(); expectTypeOf< InferIssue< NonNullishSchemaAsync< UnionSchema< [ StringSchema, NullSchema, UndefinedSchema, ], undefined >, undefined > > >().toEqualTypeOf< NonNullishIssue | StringIssue | UnionIssue >(); }); }); }); ================================================ FILE: library/src/schemas/nonNullish/nonNullishAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { pipeAsync } from '../../methods/index.ts'; import type { FailureDataset } from '../../types/index.ts'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { nullishAsync, type NullishSchemaAsync } from '../nullish/index.ts'; import { string, type StringSchema } from '../string/index.ts'; import { nonNullishAsync, type NonNullishSchemaAsync, } from './nonNullishAsync.ts'; import type { NonNullishIssue } from './types.ts'; describe('nonNullishAsync', () => { describe('should return schema object', () => { const wrapped = nullishAsync(string()); const baseSchema: Omit< NonNullishSchemaAsync< NullishSchemaAsync, undefined>, never >, 'message' > = { kind: 'schema', type: 'non_nullish', reference: nonNullishAsync, expects: '(!null & !undefined)', wrapped, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: NonNullishSchemaAsync< NullishSchemaAsync, undefined>, undefined > = { ...baseSchema, message: undefined, }; expect(nonNullishAsync(wrapped)).toStrictEqual(schema); expect(nonNullishAsync(wrapped, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(nonNullishAsync(wrapped, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies NonNullishSchemaAsync< NullishSchemaAsync, undefined>, 'message' >); }); test('with function message', () => { const message = () => 'message'; expect(nonNullishAsync(wrapped, message)).toStrictEqual({ ...baseSchema, message, } satisfies NonNullishSchemaAsync< NullishSchemaAsync, undefined>, typeof message >); }); }); describe('should return dataset without issues', () => { const schema = nonNullishAsync(nullishAsync(string())); test('for valid wrapped types', async () => { await expectNoSchemaIssueAsync(schema, ['', 'foo', '#$%']); }); }); describe('should return dataset with issues', () => { const baseIssue: Omit = { kind: 'schema', type: 'non_nullish', expected: '(!null & !undefined)', message: 'message', requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for null input', async () => { await expectSchemaIssueAsync( nonNullishAsync(nullishAsync(string()), 'message'), baseIssue, [null] ); }); test('for undefined input', async () => { await expectSchemaIssueAsync( nonNullishAsync(nullishAsync(string()), 'message'), baseIssue, [undefined] ); }); test('for null output', async () => { expect( await nonNullishAsync( pipeAsync( string(), transform(() => null) ), 'message' )['~run']({ value: 'foo' }, {}) ).toStrictEqual({ typed: false, value: null, issues: [{ ...baseIssue, input: null, received: 'null' }], } satisfies FailureDataset); }); test('for undefined output', async () => { expect( await nonNullishAsync( pipeAsync( string(), transform(() => undefined) ), 'message' )['~run']({ value: 'foo' }, {}) ).toStrictEqual({ typed: false, value: undefined, issues: [{ ...baseIssue, input: undefined, received: 'undefined' }], } satisfies FailureDataset); }); }); }); ================================================ FILE: library/src/schemas/nonNullish/nonNullishAsync.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { nonNullish } from './nonNullish.ts'; import type { InferNonNullishInput, InferNonNullishIssue, InferNonNullishOutput, NonNullishIssue, } from './types.ts'; /** * Non nullish schema async interface. */ export interface NonNullishSchemaAsync< TWrapped extends | BaseSchema> | BaseSchemaAsync>, TMessage extends ErrorMessage | undefined, > extends BaseSchemaAsync< InferNonNullishInput, InferNonNullishOutput, NonNullishIssue | InferNonNullishIssue > { /** * The schema type. */ readonly type: 'non_nullish'; /** * The schema reference. */ readonly reference: typeof nonNullish | typeof nonNullishAsync; /** * The expected property. */ readonly expects: '(!null & !undefined)'; /** * The wrapped schema. */ readonly wrapped: TWrapped; /** * The error message. */ readonly message: TMessage; } /** * Creates a non nullish schema. * * @param wrapped The wrapped schema. * * @returns A non nullish schema. */ export function nonNullishAsync< const TWrapped extends | BaseSchema> | BaseSchemaAsync>, >(wrapped: TWrapped): NonNullishSchemaAsync; /** * Creates a non nullish schema. * * @param wrapped The wrapped schema. * @param message The error message. * * @returns A non nullish schema. */ export function nonNullishAsync< const TWrapped extends | BaseSchema> | BaseSchemaAsync>, const TMessage extends ErrorMessage | undefined, >( wrapped: TWrapped, message: TMessage ): NonNullishSchemaAsync; // @__NO_SIDE_EFFECTS__ export function nonNullishAsync( wrapped: | BaseSchema> | BaseSchemaAsync>, message?: ErrorMessage | undefined ): NonNullishSchemaAsync< | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined > { return { kind: 'schema', type: 'non_nullish', reference: nonNullishAsync, expects: '(!null & !undefined)', async: true, wrapped, message, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // If value is not `null` and `undefined`, run wrapped schema if (!(dataset.value === null || dataset.value === undefined)) { // @ts-expect-error dataset = await this.wrapped['~run'](dataset, config); } // If value is `null` or `undefined`, add issue to dataset if (dataset.value === null || dataset.value === undefined) { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset>; }, }; } ================================================ FILE: library/src/schemas/nonNullish/types.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, ErrorMessage, InferInput, InferIssue, InferOutput, NonNullish, } from '../../types/index.ts'; import type { UnionIssue, UnionOptions, UnionOptionsAsync, UnionSchema, UnionSchemaAsync, } from '../union/index.ts'; /** * Non nullish issue interface. */ export interface NonNullishIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'non_nullish'; /** * The expected property. */ readonly expected: '(!null & !undefined)'; } /** * Infer non nullish input type. */ export type InferNonNullishInput< TWrapped extends | BaseSchema> | BaseSchemaAsync>, > = NonNullish>; /** * Infer non nullish output type. */ export type InferNonNullishOutput< TWrapped extends | BaseSchema> | BaseSchemaAsync>, > = NonNullish>; /** * Infer non nullish issue type. */ export type InferNonNullishIssue< TWrapped extends | BaseSchema> | BaseSchemaAsync>, > = TWrapped extends | UnionSchema< UnionOptions, ErrorMessage>> | undefined > | UnionSchemaAsync< UnionOptionsAsync, ErrorMessage>> | undefined > ? | Exclude, { type: 'null' | 'undefined' | 'union' }> | UnionIssue> : Exclude, { type: 'null' | 'undefined' }>; ================================================ FILE: library/src/schemas/nonOptional/index.ts ================================================ export * from './nonOptional.ts'; export * from './nonOptionalAsync.ts'; export type { NonOptionalIssue } from './types.ts'; ================================================ FILE: library/src/schemas/nonOptional/nonOptional.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { NullIssue, NullSchema } from '../null/index.ts'; import { nullish, type NullishSchema } from '../nullish/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import type { UndefinedSchema } from '../undefined/index.ts'; import type { UnionIssue, UnionSchema } from '../union/index.ts'; import { nonOptional, type NonOptionalSchema } from './nonOptional.ts'; import type { NonOptionalIssue } from './types.ts'; describe('nonOptional', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = NonOptionalSchema< NullishSchema, undefined>, undefined >; expectTypeOf(nonOptional(nullish(string()))).toEqualTypeOf(); expectTypeOf( nonOptional(nullish(string()), undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(nonOptional(nullish(string()), 'message')).toEqualTypeOf< NonOptionalSchema< NullishSchema, undefined>, 'message' > >(); }); test('with function message', () => { expectTypeOf( nonOptional(nullish(string()), () => 'message') ).toEqualTypeOf< NonOptionalSchema< NullishSchema, undefined>, () => string > >(); }); }); describe('should infer correct types', () => { type Schema = NonOptionalSchema< NullishSchema, undefined>, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< NonOptionalIssue | StringIssue >(); expectTypeOf< InferIssue< NonOptionalSchema< UnionSchema< [ StringSchema, NullSchema, UndefinedSchema, ], undefined >, undefined > > >().toEqualTypeOf< | NonOptionalIssue | StringIssue | NullIssue | UnionIssue >(); }); }); }); ================================================ FILE: library/src/schemas/nonOptional/nonOptional.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { pipe } from '../../methods/index.ts'; import type { FailureDataset } from '../../types/index.ts'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { nullish, type NullishSchema } from '../nullish/index.ts'; import { string, type StringSchema } from '../string/index.ts'; import { nonOptional, type NonOptionalSchema } from './nonOptional.ts'; import type { NonOptionalIssue } from './types.ts'; describe('nonOptional', () => { describe('should return schema object', () => { const wrapped = nullish(string()); const baseSchema: Omit< NonOptionalSchema< NullishSchema, undefined>, never >, 'message' > = { kind: 'schema', type: 'non_optional', reference: nonOptional, expects: '!undefined', wrapped, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: NonOptionalSchema< NullishSchema, undefined>, undefined > = { ...baseSchema, message: undefined, }; expect(nonOptional(wrapped)).toStrictEqual(schema); expect(nonOptional(wrapped, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(nonOptional(wrapped, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies NonOptionalSchema< NullishSchema, undefined>, 'message' >); }); test('with function message', () => { const message = () => 'message'; expect(nonOptional(wrapped, message)).toStrictEqual({ ...baseSchema, message, } satisfies NonOptionalSchema< NullishSchema, undefined>, typeof message >); }); }); describe('should return dataset without issues', () => { const schema = nonOptional(nullish(string())); test('for valid wrapped types', () => { expectNoSchemaIssue(schema, ['', 'foo', '#$%', null]); }); }); describe('should return dataset with issues', () => { const nonOptionalIssue: NonOptionalIssue = { kind: 'schema', type: 'non_optional', input: undefined, received: 'undefined', expected: '!undefined', message: 'message', requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for undefined input', () => { expectSchemaIssue( nonOptional(nullish(string()), 'message'), nonOptionalIssue, [undefined] ); }); test('for undefined output', () => { expect( nonOptional( pipe( string(), transform(() => undefined) ), 'message' )['~run']({ value: 'foo' }, {}) ).toStrictEqual({ typed: false, value: undefined, issues: [nonOptionalIssue], } satisfies FailureDataset); }); }); }); ================================================ FILE: library/src/schemas/nonOptional/nonOptional.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { InferNonOptionalInput, InferNonOptionalIssue, InferNonOptionalOutput, NonOptionalIssue, } from './types.ts'; /** * Non optional schema interface. */ export interface NonOptionalSchema< TWrapped extends BaseSchema>, TMessage extends ErrorMessage | undefined, > extends BaseSchema< InferNonOptionalInput, InferNonOptionalOutput, NonOptionalIssue | InferNonOptionalIssue > { /** * The schema type. */ readonly type: 'non_optional'; /** * The schema reference. */ readonly reference: typeof nonOptional; /** * The expected property. */ readonly expects: '!undefined'; /** * The wrapped schema. */ readonly wrapped: TWrapped; /** * The error message. */ readonly message: TMessage; } /** * Creates a non optional schema. * * @param wrapped The wrapped schema. * * @returns A non optional schema. */ export function nonOptional< const TWrapped extends BaseSchema>, >(wrapped: TWrapped): NonOptionalSchema; /** * Creates a non optional schema. * * @param wrapped The wrapped schema. * @param message The error message. * * @returns A non optional schema. */ export function nonOptional< const TWrapped extends BaseSchema>, const TMessage extends ErrorMessage | undefined, >(wrapped: TWrapped, message: TMessage): NonOptionalSchema; // @__NO_SIDE_EFFECTS__ export function nonOptional( wrapped: BaseSchema>, message?: ErrorMessage | undefined ): NonOptionalSchema< BaseSchema>, ErrorMessage | undefined > { return { kind: 'schema', type: 'non_optional', reference: nonOptional, expects: '!undefined', async: false, wrapped, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // If value is not `undefined`, run wrapped schema if (dataset.value !== undefined) { // @ts-expect-error dataset = this.wrapped['~run'](dataset, config); } // If value is `undefined`, add issue to dataset if (dataset.value === undefined) { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset>; }, }; } ================================================ FILE: library/src/schemas/nonOptional/nonOptionalAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { NullIssue, NullSchema } from '../null/index.ts'; import { nullishAsync, type NullishSchemaAsync } from '../nullish/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import type { UndefinedSchema } from '../undefined/index.ts'; import type { UnionIssue, UnionSchema } from '../union/index.ts'; import { nonOptionalAsync, type NonOptionalSchemaAsync, } from './nonOptionalAsync.ts'; import type { NonOptionalIssue } from './types.ts'; describe('nonOptionalAsync', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = NonOptionalSchemaAsync< NullishSchemaAsync, undefined>, undefined >; expectTypeOf( nonOptionalAsync(nullishAsync(string())) ).toEqualTypeOf(); expectTypeOf( nonOptionalAsync(nullishAsync(string()), undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf( nonOptionalAsync(nullishAsync(string()), 'message') ).toEqualTypeOf< NonOptionalSchemaAsync< NullishSchemaAsync, undefined>, 'message' > >(); }); test('with function message', () => { expectTypeOf( nonOptionalAsync(nullishAsync(string()), () => 'message') ).toEqualTypeOf< NonOptionalSchemaAsync< NullishSchemaAsync, undefined>, () => string > >(); }); }); describe('should infer correct types', () => { type Schema = NonOptionalSchemaAsync< NullishSchemaAsync, undefined>, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< NonOptionalIssue | StringIssue >(); expectTypeOf< InferIssue< NonOptionalSchemaAsync< UnionSchema< [ StringSchema, NullSchema, UndefinedSchema, ], undefined >, undefined > > >().toEqualTypeOf< | NonOptionalIssue | StringIssue | NullIssue | UnionIssue >(); }); }); }); ================================================ FILE: library/src/schemas/nonOptional/nonOptionalAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { pipeAsync } from '../../methods/index.ts'; import type { FailureDataset } from '../../types/index.ts'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { nullishAsync, type NullishSchemaAsync } from '../nullish/index.ts'; import { string, type StringSchema } from '../string/index.ts'; import { nonOptionalAsync, type NonOptionalSchemaAsync, } from './nonOptionalAsync.ts'; import type { NonOptionalIssue } from './types.ts'; describe('nonOptionalAsync', () => { describe('should return schema object', () => { const wrapped = nullishAsync(string()); const baseSchema: Omit< NonOptionalSchemaAsync< NullishSchemaAsync, undefined>, never >, 'message' > = { kind: 'schema', type: 'non_optional', reference: nonOptionalAsync, expects: '!undefined', wrapped, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: NonOptionalSchemaAsync< NullishSchemaAsync, undefined>, undefined > = { ...baseSchema, message: undefined, }; expect(nonOptionalAsync(wrapped)).toStrictEqual(schema); expect(nonOptionalAsync(wrapped, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(nonOptionalAsync(wrapped, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies NonOptionalSchemaAsync< NullishSchemaAsync, undefined>, 'message' >); }); test('with function message', () => { const message = () => 'message'; expect(nonOptionalAsync(wrapped, message)).toStrictEqual({ ...baseSchema, message, } satisfies NonOptionalSchemaAsync< NullishSchemaAsync, undefined>, typeof message >); }); }); describe('should return dataset without issues', () => { const schema = nonOptionalAsync(nullishAsync(string())); test('for valid wrapped types', async () => { await expectNoSchemaIssueAsync(schema, ['', 'foo', '#$%', null]); }); }); describe('should return dataset with issues', () => { const nonOptionalIssue: NonOptionalIssue = { kind: 'schema', type: 'non_optional', input: undefined, received: 'undefined', expected: '!undefined', message: 'message', requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for undefined input', async () => { await expectSchemaIssueAsync( nonOptionalAsync(nullishAsync(string()), 'message'), nonOptionalIssue, [undefined] ); }); test('for undefined output', async () => { expect( await nonOptionalAsync( pipeAsync( string(), transform(() => undefined) ), 'message' )['~run']({ value: 'foo' }, {}) ).toStrictEqual({ typed: false, value: undefined, issues: [nonOptionalIssue], } satisfies FailureDataset); }); }); }); ================================================ FILE: library/src/schemas/nonOptional/nonOptionalAsync.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { nonOptional } from './nonOptional.ts'; import type { InferNonOptionalInput, InferNonOptionalIssue, InferNonOptionalOutput, NonOptionalIssue, } from './types.ts'; /** * Non optional schema async interface. */ export interface NonOptionalSchemaAsync< TWrapped extends | BaseSchema> | BaseSchemaAsync>, TMessage extends ErrorMessage | undefined, > extends BaseSchemaAsync< InferNonOptionalInput, InferNonOptionalOutput, NonOptionalIssue | InferNonOptionalIssue > { /** * The schema type. */ readonly type: 'non_optional'; /** * The schema reference. */ readonly reference: typeof nonOptional | typeof nonOptionalAsync; /** * The expected property. */ readonly expects: '!undefined'; /** * The wrapped schema. */ readonly wrapped: TWrapped; /** * The error message. */ readonly message: TMessage; } /** * Creates a non optional schema. * * @param wrapped The wrapped schema. * * @returns A non optional schema. */ export function nonOptionalAsync< const TWrapped extends | BaseSchema> | BaseSchemaAsync>, >(wrapped: TWrapped): NonOptionalSchemaAsync; /** * Creates a non optional schema. * * @param wrapped The wrapped schema. * @param message The error message. * * @returns A non optional schema. */ export function nonOptionalAsync< const TWrapped extends | BaseSchema> | BaseSchemaAsync>, const TMessage extends ErrorMessage | undefined, >( wrapped: TWrapped, message: TMessage ): NonOptionalSchemaAsync; // @__NO_SIDE_EFFECTS__ export function nonOptionalAsync( wrapped: | BaseSchema> | BaseSchemaAsync>, message?: ErrorMessage | undefined ): NonOptionalSchemaAsync< | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined > { return { kind: 'schema', type: 'non_optional', reference: nonOptionalAsync, expects: '!undefined', async: true, wrapped, message, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // If value is not `undefined`, run wrapped schema if (dataset.value !== undefined) { // @ts-expect-error dataset = await this.wrapped['~run'](dataset, config); } // If value is `undefined`, add issue to dataset if (dataset.value === undefined) { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset>; }, }; } ================================================ FILE: library/src/schemas/nonOptional/types.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, ErrorMessage, InferInput, InferIssue, InferOutput, NonOptional, } from '../../types/index.ts'; import type { UnionIssue, UnionOptions, UnionOptionsAsync, UnionSchema, UnionSchemaAsync, } from '../union/index.ts'; /** * Non optional issue interface. */ export interface NonOptionalIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'non_optional'; /** * The expected property. */ readonly expected: '!undefined'; } /** * Infer non optional input type. */ export type InferNonOptionalInput< TWrapped extends | BaseSchema> | BaseSchemaAsync>, > = NonOptional>; /** * Infer non optional output type. */ export type InferNonOptionalOutput< TWrapped extends | BaseSchema> | BaseSchemaAsync>, > = NonOptional>; /** * Infer non optional issue type. */ export type InferNonOptionalIssue< TWrapped extends | BaseSchema> | BaseSchemaAsync>, > = TWrapped extends | UnionSchema< UnionOptions, ErrorMessage>> | undefined > | UnionSchemaAsync< UnionOptionsAsync, ErrorMessage>> | undefined > ? | Exclude, { type: 'undefined' | 'union' }> | UnionIssue> : Exclude, { type: 'undefined' }>; ================================================ FILE: library/src/schemas/null/index.ts ================================================ export * from './null.ts'; ================================================ FILE: library/src/schemas/null/null.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { null_, type NullIssue, type NullSchema } from './null.ts'; describe('null', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = NullSchema; expectTypeOf(null_()).toEqualTypeOf(); expectTypeOf(null_(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(null_('message')).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf(null_(() => 'message')).toEqualTypeOf< NullSchema<() => string> >(); }); }); describe('should infer correct types', () => { type Schema = NullSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/null/null.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { null_, type NullIssue, type NullSchema } from './null.ts'; describe('null', () => { describe('should return schema object', () => { const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'null', reference: null_, expects: 'null', async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: NullSchema = { ...baseSchema, message: undefined, }; expect(null_()).toStrictEqual(schema); expect(null_(undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(null_('message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies NullSchema<'message'>); }); test('with function message', () => { const message = () => 'message'; expect(null_(message)).toStrictEqual({ ...baseSchema, message, } satisfies NullSchema); }); }); describe('should return dataset without issues', () => { const schema = null_(); test('for null', () => { expectNoSchemaIssue(schema, [null]); }); }); describe('should return dataset with issues', () => { const schema = null_('message'); const baseIssue: Omit = { kind: 'schema', type: 'null', expected: 'null', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'foo', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); }); ================================================ FILE: library/src/schemas/null/null.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; /** * Null issue interface. */ export interface NullIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'null'; /** * The expected property. */ readonly expected: 'null'; } /** * Null schema interface. */ export interface NullSchema< TMessage extends ErrorMessage | undefined, > extends BaseSchema { /** * The schema type. */ readonly type: 'null'; /** * The schema reference. */ readonly reference: typeof null_; /** * The expected property. */ readonly expects: 'null'; /** * The error message. */ readonly message: TMessage; } /** * Creates a null schema. * * @returns A null schema. */ export function null_(): NullSchema; /** * Creates a null schema. * * @param message The error message. * * @returns A null schema. */ export function null_< const TMessage extends ErrorMessage | undefined, >(message: TMessage): NullSchema; // @__NO_SIDE_EFFECTS__ export function null_( message?: ErrorMessage ): NullSchema | undefined> { return { kind: 'schema', type: 'null', reference: null_, expects: 'null', async: false, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { if (dataset.value === null) { // @ts-expect-error dataset.typed = true; } else { _addIssue(this, 'type', dataset, config); } // @ts-expect-error return dataset as OutputDataset; }, }; } export { null_ as null }; ================================================ FILE: library/src/schemas/nullable/index.ts ================================================ export * from './nullable.ts'; export * from './nullableAsync.ts'; ================================================ FILE: library/src/schemas/nullable/nullable.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { TransformAction } from '../../actions/index.ts'; import type { SchemaWithPipe } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { ArrayIssue, ArraySchema } from '../array/index.ts'; import type { ObjectIssue, ObjectSchema } from '../object/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { nullable, type NullableSchema } from './nullable.ts'; describe('nullable', () => { describe('should return schema object', () => { test('with undefined default', () => { type Schema = NullableSchema, undefined>; expectTypeOf(nullable(string())).toEqualTypeOf(); expectTypeOf(nullable(string(), undefined)).toEqualTypeOf(); }); test('with null default', () => { expectTypeOf(nullable(string(), null)).toEqualTypeOf< NullableSchema, null> >(); }); test('with null getter default', () => { expectTypeOf(nullable(string(), () => null)).toEqualTypeOf< NullableSchema, () => null> >(); }); test('with value default', () => { expectTypeOf(nullable(string(), 'foo')).toEqualTypeOf< NullableSchema, 'foo'> >(); }); test('with value getter default', () => { expectTypeOf(nullable(string(), () => 'foo')).toEqualTypeOf< NullableSchema, () => string> >(); }); }); describe('should infer correct types', () => { type Schema1 = NullableSchema, undefined>; type Schema2 = NullableSchema, null>; type Schema3 = NullableSchema, 'foo'>; type Schema4 = NullableSchema, () => null>; type Schema5 = NullableSchema, () => 'foo'>; type Schema6 = NullableSchema< SchemaWithPipe< [StringSchema, TransformAction] >, 'foo' >; type Schema7 = NullableSchema< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, { foo: string[] } >; type Schema8 = NullableSchema< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, () => { foo: string[] } >; test('of input', () => { type Input = string | null; expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf<{ foo: string[]; } | null>(); expectTypeOf>().toEqualTypeOf<{ foo: string[]; } | null>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); }); }); }); ================================================ FILE: library/src/schemas/nullable/nullable.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { nullable, type NullableSchema } from './nullable.ts'; describe('nullable', () => { describe('should return schema object', () => { const baseSchema: Omit< NullableSchema, string>, 'default' > = { kind: 'schema', type: 'nullable', reference: nullable, expects: '(string | null)', wrapped: { ...string(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined default', () => { const expected: NullableSchema, undefined> = { ...baseSchema, default: undefined, }; expect(nullable(string())).toStrictEqual(expected); expect(nullable(string(), undefined)).toStrictEqual(expected); }); test('with null default', () => { expect(nullable(string(), null)).toStrictEqual({ ...baseSchema, default: null, } satisfies NullableSchema, null>); }); test('with null getter default', () => { const getter = () => null; expect(nullable(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies NullableSchema, typeof getter>); }); test('with value default', () => { expect(nullable(string(), 'foo')).toStrictEqual({ ...baseSchema, default: 'foo', } satisfies NullableSchema, 'foo'>); }); test('with value getter default', () => { const getter = () => 'foo'; expect(nullable(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies NullableSchema, typeof getter>); }); }); describe('should return dataset without issues', () => { const schema = nullable(string()); test('for wrapper type', () => { expectNoSchemaIssue(schema, ['', 'foo', '#$%']); }); test('for null', () => { expectNoSchemaIssue(schema, [null]); }); }); describe('should return dataset with issues', () => { const schema = nullable(string('message')); const baseIssue: Omit = { kind: 'schema', type: 'string', expected: 'string', message: 'message', }; test('for invalid wrapper type', () => { expectSchemaIssue(schema, baseIssue, [123, true, {}]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); }); describe('should return dataset without default', () => { test('for undefined default', () => { expectNoSchemaIssue(nullable(string()), [null, 'foo']); expectNoSchemaIssue(nullable(string(), undefined), [null, 'foo']); }); test('for wrapper type', () => { expectNoSchemaIssue(nullable(string(), 'foo'), ['', 'bar', '#$%']); }); }); describe('should return dataset with default', () => { const schema1 = nullable(string(), null); const schema2 = nullable(string(), 'foo'); const schema3 = nullable(string(), () => null); const schema4 = nullable(string(), () => 'foo'); test('for null', () => { expect(schema1['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: null, }); expect(schema2['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: 'foo', }); expect(schema3['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: null, }); expect(schema4['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: 'foo', }); }); }); }); ================================================ FILE: library/src/schemas/nullable/nullable.ts ================================================ import { getDefault } from '../../methods/index.ts'; import type { BaseIssue, BaseSchema, Default, InferInput, InferIssue, SuccessDataset, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; import type { InferNullableOutput } from './types.ts'; /** * Nullable schema interface. */ export interface NullableSchema< TWrapped extends BaseSchema>, TDefault extends Default, > extends BaseSchema< InferInput | null, InferNullableOutput, InferIssue > { /** * The schema type. */ readonly type: 'nullable'; /** * The schema reference. */ readonly reference: typeof nullable; /** * The expected property. */ readonly expects: `(${TWrapped['expects']} | null)`; /** * The wrapped schema. */ readonly wrapped: TWrapped; /** * The default value. */ readonly default: TDefault; } /** * Creates a nullable schema. * * @param wrapped The wrapped schema. * * @returns A nullable schema. */ export function nullable< const TWrapped extends BaseSchema>, >(wrapped: TWrapped): NullableSchema; /** * Creates a nullable schema. * * @param wrapped The wrapped schema. * @param default_ The default value. * * @returns A nullable schema. */ export function nullable< const TWrapped extends BaseSchema>, const TDefault extends Default, >(wrapped: TWrapped, default_: TDefault): NullableSchema; // @__NO_SIDE_EFFECTS__ export function nullable( wrapped: BaseSchema>, default_?: unknown ): NullableSchema>, unknown> { return { kind: 'schema', type: 'nullable', reference: nullable, expects: `(${wrapped.expects} | null)`, async: false, wrapped, default: default_, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // If value is `null`, override it with default or return dataset if (dataset.value === null) { // If default is specified, override value of dataset if (this.default !== undefined) { dataset.value = getDefault(this, dataset, config); } // If value is still `null`, return dataset if (dataset.value === null) { // @ts-expect-error dataset.typed = true; // @ts-expect-error return dataset as SuccessDataset; } } // Otherwise, return dataset of wrapped schema return this.wrapped['~run'](dataset, config); }, }; } ================================================ FILE: library/src/schemas/nullable/nullableAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { TransformActionAsync } from '../../actions/index.ts'; import type { SchemaWithPipeAsync } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { ArrayIssue, ArraySchema } from '../array/index.ts'; import type { ObjectIssue, ObjectSchema } from '../object/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { nullableAsync, type NullableSchemaAsync } from './nullableAsync.ts'; describe('nullableAsync', () => { describe('should return schema object', () => { test('with undefined default', () => { type Schema = NullableSchemaAsync, undefined>; expectTypeOf(nullableAsync(string())).toEqualTypeOf(); expectTypeOf(nullableAsync(string(), undefined)).toEqualTypeOf(); }); test('with null default', () => { expectTypeOf(nullableAsync(string(), null)).toEqualTypeOf< NullableSchemaAsync, null> >(); }); test('with null getter default', () => { expectTypeOf(nullableAsync(string(), () => null)).toEqualTypeOf< NullableSchemaAsync, () => null> >(); }); test('with async null getter default', () => { expectTypeOf(nullableAsync(string(), async () => null)).toEqualTypeOf< NullableSchemaAsync, () => Promise> >(); }); test('with value default', () => { expectTypeOf(nullableAsync(string(), 'foo')).toEqualTypeOf< NullableSchemaAsync, 'foo'> >(); }); test('with value getter default', () => { expectTypeOf(nullableAsync(string(), () => 'foo')).toEqualTypeOf< NullableSchemaAsync, () => string> >(); }); test('with async value getter default', () => { expectTypeOf(nullableAsync(string(), async () => 'foo')).toEqualTypeOf< NullableSchemaAsync, () => Promise> >(); }); }); describe('should infer correct types', () => { type Schema1 = NullableSchemaAsync, undefined>; type Schema2 = NullableSchemaAsync, null>; type Schema3 = NullableSchemaAsync, 'foo'>; type Schema4 = NullableSchemaAsync, () => null>; type Schema5 = NullableSchemaAsync, () => 'foo'>; type Schema6 = NullableSchemaAsync< StringSchema, () => Promise >; type Schema7 = NullableSchemaAsync< StringSchema, () => Promise<'foo'> >; type Schema8 = NullableSchemaAsync< SchemaWithPipeAsync< [StringSchema, TransformActionAsync] >, 'foo' >; type Schema9 = NullableSchemaAsync< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, { foo: string[] } >; type Schema10 = NullableSchemaAsync< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, () => { foo: string[] } >; type Schema11 = NullableSchemaAsync< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, () => Promise<{ foo: string[] }> >; test('of input', () => { type Input = string | null; expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf<{ foo: string[]; } | null>(); expectTypeOf>().toEqualTypeOf<{ foo: string[]; } | null>(); expectTypeOf>().toEqualTypeOf<{ foo: string[]; } | null>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); }); }); }); ================================================ FILE: library/src/schemas/nullable/nullableAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { nullableAsync, type NullableSchemaAsync } from './nullableAsync.ts'; describe('nullableAsync', () => { describe('should return schema object', () => { const baseSchema: Omit< NullableSchemaAsync, string>, 'default' > = { kind: 'schema', type: 'nullable', reference: nullableAsync, expects: '(string | null)', wrapped: { ...string(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined default', () => { const expected: NullableSchemaAsync< StringSchema, undefined > = { ...baseSchema, default: undefined, }; expect(nullableAsync(string())).toStrictEqual(expected); expect(nullableAsync(string(), undefined)).toStrictEqual(expected); }); test('with null default', () => { expect(nullableAsync(string(), null)).toStrictEqual({ ...baseSchema, default: null, } satisfies NullableSchemaAsync, null>); }); test('with null getter default', () => { const getter = () => null; expect(nullableAsync(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies NullableSchemaAsync, typeof getter>); }); test('with async null getter default', () => { const getter = async () => null; expect(nullableAsync(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies NullableSchemaAsync, typeof getter>); }); test('with value default', () => { expect(nullableAsync(string(), 'foo')).toStrictEqual({ ...baseSchema, default: 'foo', } satisfies NullableSchemaAsync, 'foo'>); }); test('with value getter default', () => { const getter = () => 'foo'; expect(nullableAsync(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies NullableSchemaAsync, typeof getter>); }); test('with async value getter default', () => { const getter = async () => 'foo'; expect(nullableAsync(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies NullableSchemaAsync, typeof getter>); }); }); describe('should return dataset without issues', () => { const schema = nullableAsync(string()); test('for wrapper type', async () => { await expectNoSchemaIssueAsync(schema, ['', 'foo', '#$%']); }); test('for null', async () => { await expectNoSchemaIssueAsync(schema, [null]); }); }); describe('should return dataset with issues', () => { const schema = nullableAsync(string('message')); const baseIssue: Omit = { kind: 'schema', type: 'string', expected: 'string', message: 'message', }; test('for invalid wrapper type', async () => { await expectSchemaIssueAsync(schema, baseIssue, [123, true, {}]); }); test('for undefined', async () => { await expectSchemaIssueAsync(schema, baseIssue, [undefined]); }); }); describe('should return dataset without default', () => { test('for undefined default', async () => { await expectNoSchemaIssueAsync(nullableAsync(string()), [null, 'foo']); await expectNoSchemaIssueAsync(nullableAsync(string(), undefined), [ null, 'foo', ]); }); test('for wrapper type', async () => { await expectNoSchemaIssueAsync(nullableAsync(string(), 'foo'), [ '', 'bar', '#$%', ]); }); }); describe('should return dataset with default', () => { const schema1 = nullableAsync(string(), null); const schema2 = nullableAsync(string(), 'foo'); const schema3 = nullableAsync(string(), () => null); const schema4 = nullableAsync(string(), () => 'foo'); const schema5 = nullableAsync(string(), async () => null); const schema6 = nullableAsync(string(), async () => 'foo'); test('for null', async () => { expect(await schema1['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: null, }); expect(await schema2['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: 'foo', }); expect(await schema3['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: null, }); expect(await schema4['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: 'foo', }); expect(await schema5['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: null, }); expect(await schema6['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: 'foo', }); }); }); }); ================================================ FILE: library/src/schemas/nullable/nullableAsync.ts ================================================ import { getDefault } from '../../methods/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, DefaultAsync, InferInput, InferIssue, SuccessDataset, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; import type { nullable } from './nullable.ts'; import type { InferNullableOutput } from './types.ts'; /** * Nullable schema async interface. */ export interface NullableSchemaAsync< TWrapped extends | BaseSchema> | BaseSchemaAsync>, TDefault extends DefaultAsync, > extends BaseSchemaAsync< InferInput | null, InferNullableOutput, InferIssue > { /** * The schema type. */ readonly type: 'nullable'; /** * The schema reference. */ readonly reference: typeof nullable | typeof nullableAsync; /** * The expected property. */ readonly expects: `(${TWrapped['expects']} | null)`; /** * The wrapped schema. */ readonly wrapped: TWrapped; /** * The default value. */ readonly default: TDefault; } /** * Creates a nullable schema. * * @param wrapped The wrapped schema. * * @returns A nullable schema. */ export function nullableAsync< const TWrapped extends | BaseSchema> | BaseSchemaAsync>, >(wrapped: TWrapped): NullableSchemaAsync; /** * Creates a nullable schema. * * @param wrapped The wrapped schema. * @param default_ The default value. * * @returns A nullable schema. */ export function nullableAsync< const TWrapped extends | BaseSchema> | BaseSchemaAsync>, const TDefault extends DefaultAsync, >( wrapped: TWrapped, default_: TDefault ): NullableSchemaAsync; // @__NO_SIDE_EFFECTS__ export function nullableAsync( wrapped: | BaseSchema> | BaseSchemaAsync>, default_?: unknown ): NullableSchemaAsync< | BaseSchema> | BaseSchemaAsync>, unknown > { return { kind: 'schema', type: 'nullable', reference: nullableAsync, expects: `(${wrapped.expects} | null)`, async: true, wrapped, default: default_, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // If value is `null`, override it with default or return dataset if (dataset.value === null) { // If default is specified, override value of dataset if (this.default !== undefined) { dataset.value = await getDefault(this, dataset, config); } // If value is still `null`, return dataset if (dataset.value === null) { // @ts-expect-error dataset.typed = true; // @ts-expect-error return dataset as SuccessDataset; } } // Otherwise, return dataset of wrapped schema return this.wrapped['~run'](dataset, config); }, }; } ================================================ FILE: library/src/schemas/nullable/types.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, DefaultAsync, DefaultValue, InferOutput, } from '../../types/index.ts'; /** * Infer nullable output type. */ export type InferNullableOutput< TWrapped extends | BaseSchema> | BaseSchemaAsync>, TDefault extends DefaultAsync, > = undefined extends TDefault ? InferOutput | null : InferOutput | Extract, null>; ================================================ FILE: library/src/schemas/nullish/index.ts ================================================ export * from './nullish.ts'; export * from './nullishAsync.ts'; ================================================ FILE: library/src/schemas/nullish/nullish.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { TransformAction } from '../../actions/index.ts'; import type { SchemaWithPipe } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { ArrayIssue, ArraySchema } from '../array/index.ts'; import type { ObjectIssue, ObjectSchema } from '../object/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { nullish, type NullishSchema } from './nullish.ts'; describe('nullish', () => { describe('should return schema object', () => { test('with undefined default', () => { type Schema = NullishSchema, undefined>; expectTypeOf(nullish(string())).toEqualTypeOf(); expectTypeOf(nullish(string(), undefined)).toEqualTypeOf(); }); test('with undefined getter default', () => { expectTypeOf(nullish(string(), () => undefined)).toEqualTypeOf< NullishSchema, () => undefined> >(); }); test('with null default', () => { expectTypeOf(nullish(string(), null)).toEqualTypeOf< NullishSchema, null> >(); }); test('with null getter default', () => { expectTypeOf(nullish(string(), () => null)).toEqualTypeOf< NullishSchema, () => null> >(); }); test('with value default', () => { expectTypeOf(nullish(string(), 'foo')).toEqualTypeOf< NullishSchema, 'foo'> >(); }); test('with value getter default', () => { expectTypeOf(nullish(string(), () => 'foo')).toEqualTypeOf< NullishSchema, () => string> >(); }); }); describe('should infer correct types', () => { type Schema1 = NullishSchema, undefined>; type Schema2 = NullishSchema, null>; type Schema3 = NullishSchema, 'foo'>; type Schema4 = NullishSchema, () => undefined>; type Schema5 = NullishSchema, () => null>; type Schema6 = NullishSchema, () => 'foo'>; type Schema7 = NullishSchema< SchemaWithPipe< [StringSchema, TransformAction] >, 'foo' >; type Schema8 = NullishSchema< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, { foo: string[] } >; type Schema9 = NullishSchema< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, () => { foo: string[] } >; test('of input', () => { type Input = string | null | undefined; expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf< { foo: string[] } | null | undefined >(); expectTypeOf>().toEqualTypeOf< { foo: string[] } | null | undefined >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< string | null | undefined >(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); }); }); }); ================================================ FILE: library/src/schemas/nullish/nullish.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { nullish, type NullishSchema } from './nullish.ts'; describe('nullish', () => { describe('should return schema object', () => { const baseSchema: Omit< NullishSchema, string>, 'default' > = { kind: 'schema', type: 'nullish', reference: nullish, expects: '(string | null | undefined)', wrapped: { ...string(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined default', () => { const expected: NullishSchema, undefined> = { ...baseSchema, default: undefined, }; expect(nullish(string())).toStrictEqual(expected); expect(nullish(string(), undefined)).toStrictEqual(expected); }); test('with undefined getter default', () => { const getter = () => undefined; expect(nullish(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies NullishSchema, typeof getter>); }); test('with null default', () => { expect(nullish(string(), null)).toStrictEqual({ ...baseSchema, default: null, } satisfies NullishSchema, null>); }); test('with null getter default', () => { const getter = () => null; expect(nullish(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies NullishSchema, typeof getter>); }); test('with value default', () => { expect(nullish(string(), 'foo')).toStrictEqual({ ...baseSchema, default: 'foo', } satisfies NullishSchema, 'foo'>); }); test('with value getter default', () => { const getter = () => 'foo'; expect(nullish(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies NullishSchema, typeof getter>); }); }); describe('should return dataset without issues', () => { const schema = nullish(string()); test('for wrapper type', () => { expectNoSchemaIssue(schema, ['', 'foo', '#$%']); }); test('for undefined', () => { expectNoSchemaIssue(schema, [undefined]); }); test('for null', () => { expectNoSchemaIssue(schema, [null]); }); }); describe('should return dataset with issues', () => { const schema = nullish(string('message')); const baseIssue: Omit = { kind: 'schema', type: 'string', expected: 'string', message: 'message', }; test('for invalid wrapper type', () => { expectSchemaIssue(schema, baseIssue, [123, true, {}]); }); }); describe('should return dataset without default', () => { test('for undefined default', () => { expectNoSchemaIssue(nullish(string()), [undefined, null, 'foo']); expectNoSchemaIssue(nullish(string(), undefined), [ undefined, null, 'foo', ]); }); test('for wrapper type', () => { expectNoSchemaIssue(nullish(string(), 'foo'), ['', 'bar', '#$%']); }); }); describe('should return dataset with default', () => { const schema1 = nullish(string(), null); const schema2 = nullish(string(), 'foo'); const schema3 = nullish(string(), () => undefined); const schema4 = nullish(string(), () => null); const schema5 = nullish(string(), () => 'foo'); test('for undefined', () => { expect(schema1['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: null, }); expect(schema2['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: 'foo', }); expect(schema3['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: undefined, }); expect(schema4['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: null, }); expect(schema5['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: 'foo', }); }); test('for null', () => { expect(schema1['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: null, }); expect(schema2['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: 'foo', }); expect(schema3['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: undefined, }); expect(schema4['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: null, }); expect(schema5['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: 'foo', }); }); }); }); ================================================ FILE: library/src/schemas/nullish/nullish.ts ================================================ import { getDefault } from '../../methods/index.ts'; import type { BaseIssue, BaseSchema, Default, InferInput, InferIssue, SuccessDataset, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; import type { InferNullishOutput } from './types.ts'; /** * Nullish schema interface. */ export interface NullishSchema< TWrapped extends BaseSchema>, TDefault extends Default, > extends BaseSchema< InferInput | null | undefined, InferNullishOutput, InferIssue > { /** * The schema type. */ readonly type: 'nullish'; /** * The schema reference. */ readonly reference: typeof nullish; /** * The expected property. */ readonly expects: `(${TWrapped['expects']} | null | undefined)`; /** * The wrapped schema. */ readonly wrapped: TWrapped; /** * The default value. */ readonly default: TDefault; } /** * Creates a nullish schema. * * @param wrapped The wrapped schema. * * @returns A nullish schema. */ export function nullish< const TWrapped extends BaseSchema>, >(wrapped: TWrapped): NullishSchema; /** * Creates a nullish schema. * * @param wrapped The wrapped schema. * @param default_ The default value. * * @returns A nullish schema. */ export function nullish< const TWrapped extends BaseSchema>, const TDefault extends Default, >(wrapped: TWrapped, default_: TDefault): NullishSchema; // @__NO_SIDE_EFFECTS__ export function nullish( wrapped: BaseSchema>, default_?: unknown ): NullishSchema>, unknown> { return { kind: 'schema', type: 'nullish', reference: nullish, expects: `(${wrapped.expects} | null | undefined)`, async: false, wrapped, default: default_, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // If value is `null` or `undefined`, override it with default or return // dataset if (dataset.value === null || dataset.value === undefined) { // If default is specified, override value of dataset if (this.default !== undefined) { dataset.value = getDefault(this, dataset, config); } // If value is still `null` or `undefined`, return dataset if (dataset.value === null || dataset.value === undefined) { // @ts-expect-error dataset.typed = true; // @ts-expect-error return dataset as SuccessDataset; } } // Otherwise, return dataset of wrapped schema return this.wrapped['~run'](dataset, config); }, }; } ================================================ FILE: library/src/schemas/nullish/nullishAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { TransformActionAsync } from '../../actions/index.ts'; import type { SchemaWithPipeAsync } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { ArrayIssue, ArraySchema } from '../array/index.ts'; import type { ObjectIssue, ObjectSchema } from '../object/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { nullishAsync, type NullishSchemaAsync } from './nullishAsync.ts'; describe('nullishAsync', () => { describe('should return schema object', () => { test('with undefined default', () => { type Schema = NullishSchemaAsync, undefined>; expectTypeOf(nullishAsync(string())).toEqualTypeOf(); expectTypeOf(nullishAsync(string(), undefined)).toEqualTypeOf(); }); test('with undefined getter default', () => { expectTypeOf(nullishAsync(string(), () => undefined)).toEqualTypeOf< NullishSchemaAsync, () => undefined> >(); }); test('with async undefined getter default', () => { expectTypeOf(nullishAsync(string(), async () => undefined)).toEqualTypeOf< NullishSchemaAsync, () => Promise> >(); }); test('with null default', () => { expectTypeOf(nullishAsync(string(), null)).toEqualTypeOf< NullishSchemaAsync, null> >(); }); test('with null getter default', () => { expectTypeOf(nullishAsync(string(), () => null)).toEqualTypeOf< NullishSchemaAsync, () => null> >(); }); test('with async null getter default', () => { expectTypeOf(nullishAsync(string(), async () => null)).toEqualTypeOf< NullishSchemaAsync, () => Promise> >(); }); test('with value default', () => { expectTypeOf(nullishAsync(string(), 'foo')).toEqualTypeOf< NullishSchemaAsync, 'foo'> >(); }); test('with value getter default', () => { expectTypeOf(nullishAsync(string(), () => 'foo')).toEqualTypeOf< NullishSchemaAsync, () => string> >(); }); test('with async value getter default', () => { expectTypeOf(nullishAsync(string(), async () => 'foo')).toEqualTypeOf< NullishSchemaAsync, () => Promise> >(); }); }); describe('should infer correct types', () => { type Schema1 = NullishSchemaAsync, undefined>; type Schema2 = NullishSchemaAsync, null>; type Schema3 = NullishSchemaAsync, 'foo'>; type Schema4 = NullishSchemaAsync, () => undefined>; type Schema5 = NullishSchemaAsync, () => null>; type Schema6 = NullishSchemaAsync, () => 'foo'>; type Schema7 = NullishSchemaAsync< StringSchema, () => Promise >; type Schema8 = NullishSchemaAsync< StringSchema, () => Promise >; type Schema9 = NullishSchemaAsync< StringSchema, () => Promise<'foo'> >; type Schema10 = NullishSchemaAsync< SchemaWithPipeAsync< [StringSchema, TransformActionAsync] >, 'foo' >; type Schema11 = NullishSchemaAsync< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, { foo: string[] } >; type Schema12 = NullishSchemaAsync< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, () => { foo: string[] } >; type Schema13 = NullishSchemaAsync< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, () => Promise<{ foo: string[] }> >; test('of input', () => { type Input = string | null | undefined; expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf< { foo: string[] } | null | undefined >(); expectTypeOf>().toEqualTypeOf< { foo: string[] } | null | undefined >(); expectTypeOf>().toEqualTypeOf< { foo: string[] } | null | undefined >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< string | null | undefined >(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); }); }); }); ================================================ FILE: library/src/schemas/nullish/nullishAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { nullishAsync, type NullishSchemaAsync } from './nullishAsync.ts'; describe('nullishAsync', () => { describe('should return schema object', () => { const baseSchema: Omit< NullishSchemaAsync, string>, 'default' > = { kind: 'schema', type: 'nullish', reference: nullishAsync, expects: '(string | null | undefined)', wrapped: { ...string(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined default', () => { const expected: NullishSchemaAsync, undefined> = { ...baseSchema, default: undefined, }; expect(nullishAsync(string())).toStrictEqual(expected); expect(nullishAsync(string(), undefined)).toStrictEqual(expected); }); test('with undefined getter default', () => { const getter = () => undefined; expect(nullishAsync(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies NullishSchemaAsync, typeof getter>); }); test('with async undefined getter default', () => { const getter = async () => undefined; expect(nullishAsync(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies NullishSchemaAsync, typeof getter>); }); test('with null default', () => { expect(nullishAsync(string(), null)).toStrictEqual({ ...baseSchema, default: null, } satisfies NullishSchemaAsync, null>); }); test('with null getter default', () => { const getter = () => null; expect(nullishAsync(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies NullishSchemaAsync, typeof getter>); }); test('with async null getter default', () => { const getter = async () => null; expect(nullishAsync(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies NullishSchemaAsync, typeof getter>); }); test('with value default', () => { expect(nullishAsync(string(), 'foo')).toStrictEqual({ ...baseSchema, default: 'foo', } satisfies NullishSchemaAsync, 'foo'>); }); test('with value getter default', () => { const getter = () => 'foo'; expect(nullishAsync(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies NullishSchemaAsync, typeof getter>); }); test('with async value getter default', () => { const getter = async () => 'foo'; expect(nullishAsync(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies NullishSchemaAsync, typeof getter>); }); }); describe('should return dataset without issues', () => { const schema = nullishAsync(string()); test('for wrapper type', async () => { await expectNoSchemaIssueAsync(schema, ['', 'foo', '#$%']); }); test('for undefined', async () => { await expectNoSchemaIssueAsync(schema, [undefined]); }); test('for null', async () => { await expectNoSchemaIssueAsync(schema, [null]); }); }); describe('should return dataset with issues', () => { const schema = nullishAsync(string('message')); const baseIssue: Omit = { kind: 'schema', type: 'string', expected: 'string', message: 'message', }; test('for invalid wrapper type', async () => { await expectSchemaIssueAsync(schema, baseIssue, [123, true, {}]); }); }); describe('should return dataset without default', () => { test('for undefined default', async () => { await expectNoSchemaIssueAsync(nullishAsync(string()), [ undefined, null, 'foo', ]); await expectNoSchemaIssueAsync(nullishAsync(string(), undefined), [ undefined, null, 'foo', ]); }); test('for wrapper type', async () => { await expectNoSchemaIssueAsync(nullishAsync(string(), 'foo'), [ '', 'bar', '#$%', ]); }); }); describe('should return dataset with default', () => { const schema1 = nullishAsync(string(), null); const schema3 = nullishAsync(string(), 'foo'); const schema4 = nullishAsync(string(), () => undefined); const schema5 = nullishAsync(string(), () => null); const schema6 = nullishAsync(string(), () => 'foo'); const schema7 = nullishAsync(string(), async () => undefined); const schema8 = nullishAsync(string(), async () => null); const schema9 = nullishAsync(string(), async () => 'foo'); test('for undefined', async () => { expect(await schema1['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: null, }); expect(await schema3['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: 'foo', }); expect(await schema4['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: undefined, }); expect(await schema5['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: null, }); expect(await schema6['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: 'foo', }); expect(await schema7['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: undefined, }); expect(await schema8['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: null, }); expect(await schema9['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: 'foo', }); }); test('for null', async () => { expect(await schema1['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: null, }); expect(await schema3['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: 'foo', }); expect(await schema4['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: undefined, }); expect(await schema5['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: null, }); expect(await schema6['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: 'foo', }); expect(await schema7['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: undefined, }); expect(await schema8['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: null, }); expect(await schema9['~run']({ value: null }, {})).toStrictEqual({ typed: true, value: 'foo', }); }); }); }); ================================================ FILE: library/src/schemas/nullish/nullishAsync.ts ================================================ import { getDefault } from '../../methods/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, DefaultAsync, InferInput, InferIssue, SuccessDataset, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; import type { nullish } from './nullish.ts'; import type { InferNullishOutput } from './types.ts'; /** * Nullish schema async interface. */ export interface NullishSchemaAsync< TWrapped extends | BaseSchema> | BaseSchemaAsync>, TDefault extends DefaultAsync, > extends BaseSchemaAsync< InferInput | null | undefined, InferNullishOutput, InferIssue > { /** * The schema type. */ readonly type: 'nullish'; /** * The schema reference. */ readonly reference: typeof nullish | typeof nullishAsync; /** * The expected property. */ readonly expects: `(${TWrapped['expects']} | null | undefined)`; /** * The wrapped schema. */ readonly wrapped: TWrapped; /** * The default value. */ readonly default: TDefault; } /** * Creates a nullish schema. * * @param wrapped The wrapped schema. * * @returns A nullish schema. */ export function nullishAsync< const TWrapped extends | BaseSchema> | BaseSchemaAsync>, >(wrapped: TWrapped): NullishSchemaAsync; /** * Creates a nullish schema. * * @param wrapped The wrapped schema. * @param default_ The default value. * * @returns A nullish schema. */ export function nullishAsync< const TWrapped extends | BaseSchema> | BaseSchemaAsync>, const TDefault extends DefaultAsync, >( wrapped: TWrapped, default_: TDefault ): NullishSchemaAsync; // @__NO_SIDE_EFFECTS__ export function nullishAsync( wrapped: | BaseSchema> | BaseSchemaAsync>, default_?: unknown ): NullishSchemaAsync< | BaseSchema> | BaseSchemaAsync>, unknown > { return { kind: 'schema', type: 'nullish', reference: nullishAsync, expects: `(${wrapped.expects} | null | undefined)`, async: true, wrapped, default: default_, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // If value is `null` or `undefined`, override it with default or return // dataset if (dataset.value === null || dataset.value === undefined) { // If default is specified, override value of dataset if (this.default !== undefined) { dataset.value = await getDefault(this, dataset, config); } // If value is still `null` or `undefined`, return dataset if (dataset.value === null || dataset.value === undefined) { // @ts-expect-error dataset.typed = true; // @ts-expect-error return dataset as SuccessDataset; } } // Otherwise, return dataset of wrapped schema return this.wrapped['~run'](dataset, config); }, }; } ================================================ FILE: library/src/schemas/nullish/types.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, DefaultAsync, DefaultValue, InferOutput, } from '../../types/index.ts'; /** * Infer nullish output type. */ export type InferNullishOutput< TWrapped extends | BaseSchema> | BaseSchemaAsync>, TDefault extends DefaultAsync, > = undefined extends TDefault ? InferOutput | null | undefined : InferOutput | Extract, null | undefined>; ================================================ FILE: library/src/schemas/number/index.ts ================================================ export * from './number.ts'; ================================================ FILE: library/src/schemas/number/number.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { number, type NumberIssue, type NumberSchema } from './number.ts'; describe('number', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = NumberSchema; expectTypeOf(number()).toEqualTypeOf(); expectTypeOf(number(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(number('message')).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf(number(() => 'message')).toEqualTypeOf< NumberSchema<() => string> >(); }); }); describe('should infer correct types', () => { type Schema = NumberSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/number/number.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { number, type NumberIssue, type NumberSchema } from './number.ts'; describe('number', () => { describe('should return schema object', () => { const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'number', reference: number, expects: 'number', async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: NumberSchema = { ...baseSchema, message: undefined, }; expect(number()).toStrictEqual(schema); expect(number(undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(number('message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies NumberSchema<'message'>); }); test('with function message', () => { const message = () => 'message'; expect(number(message)).toStrictEqual({ ...baseSchema, message, } satisfies NumberSchema); }); }); describe('should return dataset without issues', () => { const schema = number(); test('for number zero', () => { expectNoSchemaIssue(schema, [0, -0, 0.0, -0.0]); }); test('for positive integers', () => { expectNoSchemaIssue(schema, [1, 23, 456, Number.MAX_VALUE]); }); test('for negative integers', () => { expectNoSchemaIssue(schema, [-1, -23, -456, Number.MIN_VALUE]); }); test('for positive floats', () => { expectNoSchemaIssue(schema, [0.1, 23.456, 1 / 3]); }); test('for negative floats', () => { expectNoSchemaIssue(schema, [-0.1, -23.456, -1 / 3]); }); test('for infinity numbers', () => { expectNoSchemaIssue(schema, [Infinity, -Infinity]); }); }); describe('should return dataset with issues', () => { const schema = number('message'); const baseIssue: Omit = { kind: 'schema', type: 'number', expected: 'number', message: 'message', }; // Special values test('for NaN', () => { expectSchemaIssue(schema, baseIssue, [NaN]); }); // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', '0', '-2', '12.34']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); }); ================================================ FILE: library/src/schemas/number/number.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; /** * Number issue interface. */ export interface NumberIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'number'; /** * The expected property. */ readonly expected: 'number'; } /** * Number schema interface. */ export interface NumberSchema< TMessage extends ErrorMessage | undefined, > extends BaseSchema { /** * The schema type. */ readonly type: 'number'; /** * The schema reference. */ readonly reference: typeof number; /** * The expected property. */ readonly expects: 'number'; /** * The error message. */ readonly message: TMessage; } /** * Creates a number schema. * * @returns A number schema. */ export function number(): NumberSchema; /** * Creates a number schema. * * @param message The error message. * * @returns A number schema. */ export function number< const TMessage extends ErrorMessage | undefined, >(message: TMessage): NumberSchema; // @__NO_SIDE_EFFECTS__ export function number( message?: ErrorMessage ): NumberSchema | undefined> { return { kind: 'schema', type: 'number', reference: number, expects: 'number', async: false, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { if (typeof dataset.value === 'number' && !isNaN(dataset.value)) { // @ts-expect-error dataset.typed = true; } else { _addIssue(this, 'type', dataset, config); } // @ts-expect-error return dataset as OutputDataset; }, }; } ================================================ FILE: library/src/schemas/object/index.ts ================================================ export * from './object.ts'; export * from './objectAsync.ts'; export * from './types.ts'; ================================================ FILE: library/src/schemas/object/object.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { Brand, BrandAction, DescriptionAction, ReadonlyAction, TransformAction, } from '../../actions/index.ts'; import type { SchemaWithPipe } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { AnySchema } from '../any/index.ts'; import type { CustomIssue, CustomSchema } from '../custom/index.ts'; import type { ExactOptionalSchema } from '../exactOptional/index.ts'; import type { NullishSchema } from '../nullish/index.ts'; import type { NumberIssue, NumberSchema } from '../number/index.ts'; import type { OptionalSchema } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import type { UndefinedableSchema } from '../undefinedable/index.ts'; import type { UnknownSchema } from '../unknown/index.ts'; import { object, type ObjectSchema } from './object.ts'; import type { ObjectIssue } from './types.ts'; describe('object', () => { describe('should return schema object', () => { const entries = { key: string() }; type Entries = typeof entries; test('with undefined message', () => { type Schema = ObjectSchema; expectTypeOf(object(entries)).toEqualTypeOf(); expectTypeOf(object(entries, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(object(entries, 'message')).toEqualTypeOf< ObjectSchema >(); }); test('with function message', () => { expectTypeOf(object(entries, () => 'message')).toEqualTypeOf< ObjectSchema string> >(); }); }); describe('should infer correct types', () => { type Schema = ObjectSchema< { key00: StringSchema; key01: AnySchema; key02: UnknownSchema; key03: ObjectSchema<{ key: NumberSchema }, undefined>; key04: SchemaWithPipe< [StringSchema, ReadonlyAction] >; key05: UndefinedableSchema, 'bar'>; key06: SchemaWithPipe< [ OptionalSchema, undefined>, TransformAction, ] >; key07: CustomSchema<`a${string}` | `b${string}`, undefined>; key08: SchemaWithPipe< [StringSchema, BrandAction] >; // ExactOptionalSchema key10: ExactOptionalSchema, undefined>; key11: ExactOptionalSchema, 'foo'>; key12: ExactOptionalSchema, () => 'foo'>; // OptionalSchema key20: OptionalSchema, undefined>; key21: OptionalSchema, 'foo'>; key22: OptionalSchema, () => undefined>; key23: OptionalSchema, () => 'foo'>; // NullishSchema key30: NullishSchema, undefined>; key31: NullishSchema, null>; key32: NullishSchema, 'foo'>; key33: NullishSchema, () => undefined>; key34: NullishSchema, () => null>; key35: NullishSchema, () => 'foo'>; // SchemaWithPipe key40: SchemaWithPipe< [ExactOptionalSchema, undefined>] >; key41: SchemaWithPipe< [ ExactOptionalSchema, undefined>, DescriptionAction, ] >; key42: SchemaWithPipe< [OptionalSchema, undefined>] >; key43: SchemaWithPipe< [ OptionalSchema, undefined>, DescriptionAction, ] >; key44: SchemaWithPipe< [NullishSchema, undefined>] >; key45: SchemaWithPipe< [ NullishSchema, undefined>, DescriptionAction, ] >; key46: SchemaWithPipe< [ NullishSchema, undefined>, TransformAction, ] >; }, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf<{ key00: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any key01: any; key02: unknown; key03: { key: number }; key04: string; key05: string | undefined; key06?: string | undefined; key07: `a${string}` | `b${string}`; key08: string; // ExactOptionalSchema key10?: string; key11?: string; key12?: string; // OptionalSchema key20?: string | undefined; key21?: string | undefined; key22?: string | undefined; key23?: string | undefined; // NullishSchema key30?: string | null | undefined; key31?: string | null | undefined; key32?: string | null | undefined; key33?: string | null | undefined; key34?: string | null | undefined; key35?: string | null | undefined; // SchemaWithPipe key40?: string; key41?: string; key42?: string | undefined; key43?: string | undefined; key44?: string | null | undefined; key45?: string | null | undefined; key46?: string | null | undefined; }>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf<{ key00: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any key01: any; key02: unknown; key03: { key: number }; readonly key04: string; key05: string; key06?: number; key07: `a${string}` | `b${string}`; key08: string & Brand<'foo'>; // ExactOptionalSchema key10?: string; key11: string; key12: string; // OptionalSchema key20?: string | undefined; key21: string; key22: string | undefined; key23: string; // NullishSchema key30?: string | null | undefined; key31: string | null; key32: string; key33: string | undefined; key34: string | null; key35: string; // SchemaWithPipe key40?: string; key41?: string; key42?: string | undefined; key43?: string | undefined; key44?: string | null | undefined; key45?: string | null | undefined; key46?: string[]; }>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< ObjectIssue | StringIssue | NumberIssue | CustomIssue >(); }); }); }); ================================================ FILE: library/src/schemas/object/object.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { fallback } from '../../methods/index.ts'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { any } from '../any/index.ts'; import { exactOptional } from '../exactOptional/exactOptional.ts'; import { nullish } from '../nullish/index.ts'; import { number } from '../number/index.ts'; import { optional } from '../optional/index.ts'; import { string } from '../string/index.ts'; import { unknown } from '../unknown/index.ts'; import { object, type ObjectSchema } from './object.ts'; import type { ObjectIssue } from './types.ts'; describe('object', () => { describe('should return schema object', () => { const entries = { key: string() }; type Entries = typeof entries; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'object', reference: object, expects: 'Object', entries, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: ObjectSchema = { ...baseSchema, message: undefined, }; expect(object(entries)).toStrictEqual(schema); expect(object(entries, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(object(entries, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies ObjectSchema); }); test('with function message', () => { const message = () => 'message'; expect(object(entries, message)).toStrictEqual({ ...baseSchema, message, } satisfies ObjectSchema); }); }); describe('should return dataset without issues', () => { test('for empty object', () => { expectNoSchemaIssue(object({}), [{}]); }); test('for simple object', () => { expectNoSchemaIssue(object({ key1: string(), key2: number() }), [ { key1: 'foo', key2: 123 }, ]); }); test('for unknown entries', () => { expect( object({ key1: string() })['~run']( { value: { key1: 'foo', key2: 123, key3: null } }, {} ) ).toStrictEqual({ typed: true, value: { key1: 'foo' }, }); }); }); describe('should return dataset with issues', () => { const schema = object({}, 'message'); const baseIssue: Omit = { kind: 'schema', type: 'object', expected: 'Object', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types // TODO: Enable this test again in case we find a reliable way to check for // plain objects // test('for arrays', () => { // expectSchemaIssue(schema, baseIssue, [[], ['value']]); // }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); }); describe('should return dataset without nested issues', () => { test('for simple object', () => { expectNoSchemaIssue(object({ key1: string(), key2: number() }), [ { key1: 'foo', key2: 123 }, ]); }); test('for nested object', () => { expectNoSchemaIssue(object({ nested: object({ key: string() }) }), [ { nested: { key: 'foo' } }, ]); }); test('for missing entries with fallback', () => { expect( object({ key1: fallback(string(), 'foo'), key2: fallback(number(), () => 123), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key1: 'foo', key2: 123 }, }); }); test('for exact optional entry', () => { expectNoSchemaIssue(object({ key: exactOptional(string()) }), [ {}, { key: 'foo' }, ]); }); test('for exact optional entry with default', () => { expect( object({ key: exactOptional(string(), 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( object({ key: exactOptional(string(), () => 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); }); test('for optional entry', () => { expectNoSchemaIssue(object({ key: optional(string()) }), [ {}, { key: undefined }, { key: 'foo' }, ]); }); test('for optional entry with default', () => { expect( object({ key: optional(string(), 'foo') })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( object({ key: optional(string(), () => 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( object({ key: optional(string(), () => undefined), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); }); test('for nullish entry', () => { expectNoSchemaIssue(object({ key: nullish(number()) }), [ {}, { key: undefined }, { key: null }, { key: 123 }, ]); }); test('for nullish entry with default', () => { expect( object({ key: nullish(string(), 'foo') })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( object({ key: nullish(string(), null) })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( object({ key: nullish(string(), () => 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( object({ key: nullish(string(), () => null) })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( object({ key: nullish(string(), () => undefined) })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: undefined }, }); }); test('for unknown entries', () => { expect( object({ key1: string() })['~run']( { value: { key1: 'foo', key2: 123, key3: null } }, {} ) ).toStrictEqual({ typed: true, value: { key1: 'foo' }, }); }); }); describe('should return dataset with nested issues', () => { const schema = object({ key1: string(), key2: number(), nested: object({ key1: string(), key2: number() }), }); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for missing entries', () => { const input = { key2: 123 }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"nested"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'nested', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for missing nested entries', () => { const input = { key1: 'value', nested: {} }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key2', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: {}, }, { type: 'object', origin: 'key', input: input.nested, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: {}, }, { type: 'object', origin: 'key', input: input.nested, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for missing entries with abort early', () => { const input = { key2: 123 }; expect( schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key1', value: undefined, }, ], abortEarly: true, }, ], } satisfies FailureDataset>); }); test('for missing any and unknown entry', () => { const schema = object({ key1: any(), key2: unknown() }); expect(schema['~run']({ value: {} }, {})).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid entries', () => { const input = { key1: false, key2: 123, nested: null }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: false, expected: 'string', received: 'false', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: false, }, ], }, { ...baseInfo, kind: 'schema', type: 'object', input: null, expected: 'Object', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: null, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid nested entries', () => { const input = { key1: 'value', key2: 'value', nested: { key1: 123, key2: null, }, }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: 'value', expected: 'number', received: '"value"', path: [ { type: 'object', origin: 'value', input, key: 'key2', value: input.key2, }, ], }, { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'value', input: input.nested, key: 'key1', value: input.nested.key1, }, ], }, { ...baseInfo, kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'value', input: input.nested, key: 'key2', value: input.nested.key2, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid entries with abort early', () => { const input = { key1: false, key2: 123, nested: null }; expect( schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: false, expected: 'string', received: 'false', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: false, }, ], abortEarly: true, }, ], } satisfies FailureDataset>); }); test('for invalid exact optional entry', () => { const schema = object({ key: exactOptional(string()) }); const input = { key: undefined }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: undefined, expected: 'string', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'key', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/object/object.ts ================================================ import { getDefault, getFallback } from '../../methods/index.ts'; import type { BaseSchema, ErrorMessage, InferObjectInput, InferObjectIssue, InferObjectOutput, ObjectEntries, ObjectPathItem, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { ObjectIssue } from './types.ts'; /** * Object schema interface. */ export interface ObjectSchema< TEntries extends ObjectEntries, TMessage extends ErrorMessage | undefined, > extends BaseSchema< InferObjectInput, InferObjectOutput, ObjectIssue | InferObjectIssue > { /** * The schema type. */ readonly type: 'object'; /** * The schema reference. */ readonly reference: typeof object; /** * The expected property. */ readonly expects: 'Object'; /** * The entries schema. */ readonly entries: TEntries; /** * The error message. */ readonly message: TMessage; } /** * Creates an object schema. * * Hint: This schema removes unknown entries. The output will only include the * entries you specify. To include unknown entries, use `looseObject`. To * return an issue for unknown entries, use `strictObject`. To include and * validate unknown entries, use `objectWithRest`. * * @param entries The entries schema. * * @returns An object schema. */ export function object( entries: TEntries ): ObjectSchema; /** * Creates an object schema. * * Hint: This schema removes unknown entries. The output will only include the * entries you specify. To include unknown entries, use `looseObject`. To * return an issue for unknown entries, use `strictObject`. To include and * validate unknown entries, use `objectWithRest`. * * @param entries The entries schema. * @param message The error message. * * @returns An object schema. */ export function object< const TEntries extends ObjectEntries, const TMessage extends ErrorMessage | undefined, >(entries: TEntries, message: TMessage): ObjectSchema; // @__NO_SIDE_EFFECTS__ export function object( entries: ObjectEntries, message?: ErrorMessage ): ObjectSchema | undefined> { return { kind: 'schema', type: 'object', reference: object, expects: 'Object', async: false, entries, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (input && typeof input === 'object') { // Set typed to `true` and value to blank object // @ts-expect-error dataset.typed = true; dataset.value = {}; // Process each object entry of schema for (const key in this.entries) { const valueSchema = this.entries[key]; // If key is present or its an optional schema with a default value, // parse input of key or default value if ( key in input || ((valueSchema.type === 'exact_optional' || valueSchema.type === 'optional' || valueSchema.type === 'nullish') && // @ts-expect-error valueSchema.default !== undefined) ) { const value: unknown = key in input ? // @ts-expect-error input[key] : getDefault(valueSchema); const valueDataset = valueSchema['~run']({ value }, config); // If there are issues, capture them if (valueDataset.issues) { // Create object path item const pathItem: ObjectPathItem = { type: 'object', origin: 'value', input: input as Record, key, value, }; // Add modified entry dataset issues to issues for (const issue of valueDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = valueDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!valueDataset.typed) { dataset.typed = false; } // Add entry to dataset // @ts-expect-error dataset.value[key] = valueDataset.value; // Otherwise, if key is missing but has a fallback, use it // @ts-expect-error } else if (valueSchema.fallback !== undefined) { // @ts-expect-error dataset.value[key] = getFallback(valueSchema); // Otherwise, if key is missing and required, add issue } else if ( valueSchema.type !== 'exact_optional' && valueSchema.type !== 'optional' && valueSchema.type !== 'nullish' ) { _addIssue(this, 'key', dataset, config, { input: undefined, expected: `"${key}"`, path: [ { type: 'object', origin: 'key', input: input as Record, key, // @ts-expect-error value: input[key], }, ], }); // If necessary, abort early if (config.abortEarly) { break; } } } // Otherwise, add object issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< InferObjectOutput, ObjectIssue | InferObjectIssue >; }, }; } ================================================ FILE: library/src/schemas/object/objectAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { Brand, BrandAction, DescriptionAction, ReadonlyAction, TransformAction, } from '../../actions/index.ts'; import type { SchemaWithPipe, SchemaWithPipeAsync, } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { AnySchema } from '../any/index.ts'; import type { CustomIssue, CustomSchemaAsync } from '../custom/index.ts'; import type { ExactOptionalSchema, ExactOptionalSchemaAsync, } from '../exactOptional/index.ts'; import type { NullishSchema, NullishSchemaAsync } from '../nullish/index.ts'; import type { NumberIssue, NumberSchema } from '../number/index.ts'; import type { OptionalSchema, OptionalSchemaAsync } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import type { UndefinedableSchema } from '../undefinedable/index.ts'; import type { UnknownSchema } from '../unknown/index.ts'; import { objectAsync, type ObjectSchemaAsync } from './objectAsync.ts'; import type { ObjectIssue } from './types.ts'; describe('objectAsync', () => { describe('should return schema objectAsync', () => { const entries = { key: string() }; type Entries = typeof entries; test('with undefined message', () => { type Schema = ObjectSchemaAsync; expectTypeOf(objectAsync(entries)).toEqualTypeOf(); expectTypeOf(objectAsync(entries, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(objectAsync(entries, 'message')).toEqualTypeOf< ObjectSchemaAsync >(); }); test('with function message', () => { expectTypeOf(objectAsync(entries, () => 'message')).toEqualTypeOf< ObjectSchemaAsync string> >(); }); }); describe('should infer correct types', () => { type Schema = ObjectSchemaAsync< { key00: StringSchema; key01: AnySchema; key02: UnknownSchema; key03: ObjectSchemaAsync<{ key: NumberSchema }, undefined>; key04: SchemaWithPipe< [StringSchema, ReadonlyAction] >; key05: UndefinedableSchema, 'bar'>; key06: SchemaWithPipe< [ OptionalSchema, undefined>, TransformAction, ] >; key07: SchemaWithPipeAsync< [ OptionalSchema, undefined>, TransformAction, ] >; key08: SchemaWithPipeAsync< [ OptionalSchemaAsync, undefined>, TransformAction, ] >; key09: CustomSchemaAsync<`a${string}` | `b${string}`, undefined>; key10: SchemaWithPipe< [StringSchema, BrandAction] >; // ExactOptionalSchema key20: ExactOptionalSchema, undefined>; key21: ExactOptionalSchema, 'foo'>; key22: ExactOptionalSchema, () => 'foo'>; // ExactOptionalSchemaAsync key30: ExactOptionalSchemaAsync, undefined>; key31: ExactOptionalSchemaAsync, 'foo'>; key32: ExactOptionalSchemaAsync, () => 'foo'>; key33: ExactOptionalSchemaAsync< StringSchema, () => Promise<'foo'> >; // OptionalSchema key40: OptionalSchema, undefined>; key41: OptionalSchema, 'foo'>; key42: OptionalSchema, () => undefined>; key43: OptionalSchema, () => 'foo'>; // OptionalSchemaAsync key50: OptionalSchemaAsync, undefined>; key51: OptionalSchemaAsync, 'foo'>; key52: OptionalSchemaAsync, () => undefined>; key53: OptionalSchemaAsync, () => 'foo'>; key54: OptionalSchemaAsync< StringSchema, () => Promise >; key55: OptionalSchemaAsync< StringSchema, () => Promise<'foo'> >; // NullishSchema key60: NullishSchema, undefined>; key61: NullishSchema, null>; key62: NullishSchema, 'foo'>; key63: NullishSchema, () => undefined>; key64: NullishSchema, () => null>; key65: NullishSchema, () => 'foo'>; // NullishSchemaAsync key70: NullishSchemaAsync, undefined>; key71: NullishSchemaAsync, null>; key72: NullishSchemaAsync, 'foo'>; key73: NullishSchemaAsync, () => undefined>; key74: NullishSchemaAsync, () => null>; key75: NullishSchemaAsync, () => 'foo'>; key76: NullishSchemaAsync< StringSchema, () => Promise >; key77: NullishSchemaAsync, () => Promise>; key78: NullishSchemaAsync< StringSchema, () => Promise<'foo'> >; // SchemaWithPipe key80: SchemaWithPipe< [ExactOptionalSchema, undefined>] >; key81: SchemaWithPipe< [ ExactOptionalSchema, undefined>, DescriptionAction, ] >; key82: SchemaWithPipe< [OptionalSchema, undefined>] >; key83: SchemaWithPipe< [ OptionalSchema, undefined>, DescriptionAction, ] >; key84: SchemaWithPipe< [NullishSchema, undefined>] >; key85: SchemaWithPipe< [ NullishSchema, undefined>, DescriptionAction, ] >; key86: SchemaWithPipe< [ NullishSchema, undefined>, TransformAction, ] >; key87: SchemaWithPipeAsync< [ NullishSchemaAsync, undefined>, TransformAction, ] >; }, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf<{ key00: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any key01: any; key02: unknown; key03: { key: number }; key04: string; key05: string | undefined; key06?: string | undefined; key07?: string | undefined; key08?: string | undefined; key09: `a${string}` | `b${string}`; key10: string; // ExactOptionalSchema key20?: string; key21?: string; key22?: string; // ExactOptionalSchemaAsync key30?: string; key31?: string; key32?: string; key33?: string; // OptionalSchema key40?: string | undefined; key41?: string | undefined; key42?: string | undefined; key43?: string | undefined; // OptionalSchemaAsync key50?: string | undefined; key51?: string | undefined; key52?: string | undefined; key53?: string | undefined; key54?: string | undefined; key55?: string | undefined; // NullishSchema key60?: string | null | undefined; key61?: string | null | undefined; key62?: string | null | undefined; key63?: string | null | undefined; key64?: string | null | undefined; key65?: string | null | undefined; // NullishSchemaAsync key70?: string | null | undefined; key71?: string | null | undefined; key72?: string | null | undefined; key73?: string | null | undefined; key74?: string | null | undefined; key75?: string | null | undefined; key76?: string | null | undefined; key77?: string | null | undefined; key78?: string | null | undefined; // SchemaWithPipe key80?: string; key81?: string; key82?: string | undefined; key83?: string | undefined; key84?: string | null | undefined; key85?: string | null | undefined; key86?: string | null | undefined; key87?: string | null | undefined; }>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf<{ key00: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any key01: any; key02: unknown; key03: { key: number }; readonly key04: string; key05: string; key06?: number; key07?: number; key08?: number; key09: `a${string}` | `b${string}`; key10: string & Brand<'foo'>; // ExactOptionalSchema key20?: string; key21: string; key22: string; // ExactOptionalSchemaAsync key30?: string; key31: string; key32: string; key33: string; // OptionalSchema key40?: string | undefined; key41: string; key42: string | undefined; key43: string; // OptionalSchemaAsync key50?: string | undefined; key51: string; key52: string | undefined; key53: string; key54: string | undefined; key55: string; // NullishSchema key60?: string | null | undefined; key61: string | null; key62: string; key63: string | undefined; key64: string | null; key65: string; // NullishSchemaAsync key70?: string | null | undefined; key71: string | null; key72: string; key73: string | undefined; key74: string | null; key75: string; key76: string | undefined; key77: string | null; key78: string; // SchemaWithPipe key80?: string; key81?: string; key82?: string | undefined; key83?: string | undefined; key84?: string | null | undefined; key85?: string | null | undefined; key86?: string[]; key87?: string[]; }>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< ObjectIssue | StringIssue | NumberIssue | CustomIssue >(); }); }); }); ================================================ FILE: library/src/schemas/object/objectAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { fallback, fallbackAsync } from '../../methods/index.ts'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { any } from '../any/index.ts'; import { exactOptional, exactOptionalAsync } from '../exactOptional/index.ts'; import { nullish, nullishAsync } from '../nullish/index.ts'; import { number } from '../number/index.ts'; import { optional, optionalAsync } from '../optional/index.ts'; import { string } from '../string/index.ts'; import { unknown } from '../unknown/index.ts'; import { objectAsync, type ObjectSchemaAsync } from './objectAsync.ts'; import type { ObjectIssue } from './types.ts'; describe('objectAsync', () => { describe('should return schema object', () => { const entries = { key: string() }; type Entries = typeof entries; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'object', reference: objectAsync, expects: 'Object', entries, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: ObjectSchemaAsync = { ...baseSchema, message: undefined, }; expect(objectAsync(entries)).toStrictEqual(schema); expect(objectAsync(entries, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(objectAsync(entries, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies ObjectSchemaAsync); }); test('with function message', () => { const message = () => 'message'; expect(objectAsync(entries, message)).toStrictEqual({ ...baseSchema, message, } satisfies ObjectSchemaAsync); }); }); describe('should return dataset without issues', () => { test('for empty object', async () => { await expectNoSchemaIssueAsync(objectAsync({}), [{}]); }); test('for simple object', async () => { await expectNoSchemaIssueAsync( objectAsync({ key1: string(), key2: number() }), [{ key1: 'foo', key2: 123 }] ); }); test('for unknown entries', async () => { expect( await objectAsync({ key1: string() })['~run']( { value: { key1: 'foo', key2: 123, key3: null } }, {} ) ).toStrictEqual({ typed: true, value: { key1: 'foo' }, }); }); }); describe('should return dataset with issues', () => { const schema = objectAsync({}, 'message'); const baseIssue: Omit = { kind: 'schema', type: 'object', expected: 'Object', message: 'message', }; // Primitive types test('for bigints', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', async () => { await expectSchemaIssueAsync(schema, baseIssue, [true, false]); }); test('for null', async () => { await expectSchemaIssueAsync(schema, baseIssue, [null]); }); test('for numbers', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', async () => { await expectSchemaIssueAsync(schema, baseIssue, [undefined]); }); test('for strings', async () => { await expectSchemaIssueAsync(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ Symbol(), Symbol('foo'), ]); }); // Complex types // TODO: Enable this test again in case we find a reliable way to check for // plain objects // test('for arrays', async () => { // await expectSchemaIssueAsync(schema, baseIssue, [[], ['value']]); // }); test('for functions', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ // eslint-disable-next-line @typescript-eslint/no-empty-function () => {}, // eslint-disable-next-line @typescript-eslint/no-empty-function function () {}, ]); }); }); describe('should return dataset without nested issues', () => { test('for simple object', async () => { await expectNoSchemaIssueAsync( objectAsync({ key1: string(), key2: number() }), [{ key1: 'foo', key2: 123 }] ); }); test('for nested object', async () => { await expectNoSchemaIssueAsync( objectAsync({ nested: objectAsync({ key: string() }) }), [{ nested: { key: 'foo' } }] ); }); test('for missing entries with fallback', async () => { expect( await objectAsync({ key1: fallback(string(), 'foo'), key2: fallback(number(), () => 123), key3: fallbackAsync(string(), 'bar'), key4: fallbackAsync(number(), () => 456), key5: fallbackAsync(string(), async () => 'baz'), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key1: 'foo', key2: 123, key3: 'bar', key4: 456, key5: 'baz' }, }); }); test('for exact optional entry', async () => { await expectNoSchemaIssueAsync( objectAsync({ key: exactOptional(string()) }), [{}, { key: 'foo' }] ); await expectNoSchemaIssueAsync( objectAsync({ key: exactOptionalAsync(string()) }), [{}, { key: 'foo' }] ); }); test('for exact optional entry with default', async () => { // Sync expect( await objectAsync({ key: exactOptional(string(), 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectAsync({ key: exactOptional(string(), () => 'foo') })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); // Async expect( await objectAsync({ key: exactOptionalAsync(string(), 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectAsync({ key: exactOptionalAsync(string(), () => 'foo') })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); }); test('for optional entry', async () => { await expectNoSchemaIssueAsync(objectAsync({ key: optional(string()) }), [ {}, { key: undefined }, { key: 'foo' }, ]); await expectNoSchemaIssueAsync( objectAsync({ key: optionalAsync(string()) }), [{}, { key: undefined }, { key: 'foo' }] ); }); test('for optional entry with default', async () => { // Sync expect( await objectAsync({ key: optional(string(), 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectAsync({ key: optional(string(), () => 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectAsync({ key: optional(string(), () => undefined), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); // Async expect( await objectAsync({ key: optionalAsync(string(), 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectAsync({ key: optionalAsync(string(), () => 'foo') })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectAsync({ key: optionalAsync(string(), () => undefined), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); expect( await objectAsync({ key: optionalAsync(string(), async () => 'foo') })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectAsync({ key: optionalAsync(string(), async () => undefined), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); }); test('for nullish entry', async () => { await expectNoSchemaIssueAsync(objectAsync({ key: nullish(number()) }), [ {}, { key: undefined }, { key: null }, { key: 123 }, ]); await expectNoSchemaIssueAsync( objectAsync({ key: nullishAsync(number()) }), [{}, { key: undefined }, { key: null }, { key: 123 }] ); }); test('for nullish entry with default', async () => { // Sync expect( await objectAsync({ key: nullish(string(), 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectAsync({ key: nullish(string(), null) })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( await objectAsync({ key: nullish(string(), () => 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectAsync({ key: nullish(string(), () => null) })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( await objectAsync({ key: nullish(string(), () => undefined) })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: undefined }, }); // Async expect( await objectAsync({ key: nullishAsync(string(), 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectAsync({ key: nullishAsync(string(), null) })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( await objectAsync({ key: nullishAsync(string(), () => 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectAsync({ key: nullishAsync(string(), () => null) })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( await objectAsync({ key: nullishAsync(string(), () => undefined) })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); expect( await objectAsync({ key: nullishAsync(string(), async () => 'foo') })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectAsync({ key: nullishAsync(string(), async () => null) })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( await objectAsync({ key: nullishAsync(string(), async () => undefined), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); }); test('for unknown entries', async () => { expect( await objectAsync({ key1: string() })['~run']( { value: { key1: 'foo', key2: 123, key3: null } }, {} ) ).toStrictEqual({ typed: true, value: { key1: 'foo' }, }); }); }); describe('should return dataset with nested issues', () => { const schema = objectAsync({ key1: string(), key2: number(), nested: objectAsync({ key1: string(), key2: number() }), }); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for missing entries', async () => { const input = { key2: 123 }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"nested"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'nested', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for missing nested entries', async () => { const input = { key1: 'value', nested: {} }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key2', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: {}, }, { type: 'object', origin: 'key', input: input.nested, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: {}, }, { type: 'object', origin: 'key', input: input.nested, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for missing entries with abort early', async () => { const input = { key2: 123 }; expect( await schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key1', value: undefined, }, ], abortEarly: true, }, ], } satisfies FailureDataset>); }); test('for missing any and unknown entry', async () => { const schema = objectAsync({ key1: any(), key2: unknown() }); expect(await schema['~run']({ value: {} }, {})).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid entries', async () => { const input = { key1: false, key2: 123, nested: null }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: false, expected: 'string', received: 'false', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: false, }, ], }, { ...baseInfo, kind: 'schema', type: 'object', input: null, expected: 'Object', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: null, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid nested entries', async () => { const input = { key1: 'value', key2: 'value', nested: { key1: 123, key2: null, }, }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: 'value', expected: 'number', received: '"value"', path: [ { type: 'object', origin: 'value', input, key: 'key2', value: input.key2, }, ], }, { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'value', input: input.nested, key: 'key1', value: input.nested.key1, }, ], }, { ...baseInfo, kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'value', input: input.nested, key: 'key2', value: input.nested.key2, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid entries with abort early', async () => { const input = { key1: false, key2: 123, nested: null }; expect( await schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: false, expected: 'string', received: 'false', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: false, }, ], abortEarly: true, }, ], } satisfies FailureDataset>); }); test('for invalid exact optional entry', async () => { const schema = objectAsync({ key1: exactOptional(string()), key2: exactOptionalAsync(string()), }); const input = { key1: undefined, key2: undefined }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: undefined, expected: 'string', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'string', input: undefined, expected: 'string', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/object/objectAsync.ts ================================================ import { getDefault, getFallback } from '../../methods/index.ts'; import type { BaseSchemaAsync, ErrorMessage, InferObjectInput, InferObjectIssue, InferObjectOutput, ObjectEntriesAsync, ObjectPathItem, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { object } from './object.ts'; import type { ObjectIssue } from './types.ts'; /** * Object schema async interface. */ export interface ObjectSchemaAsync< TEntries extends ObjectEntriesAsync, TMessage extends ErrorMessage | undefined, > extends BaseSchemaAsync< InferObjectInput, InferObjectOutput, ObjectIssue | InferObjectIssue > { /** * The schema type. */ readonly type: 'object'; /** * The schema reference. */ readonly reference: typeof object | typeof objectAsync; /** * The expected property. */ readonly expects: 'Object'; /** * The entries schema. */ readonly entries: TEntries; /** * The error message. */ readonly message: TMessage; } /** * Creates an object schema. * * Hint: This schema removes unknown entries. The output will only include the * entries you specify. To include unknown entries, use `looseObjectAsync`. To * return an issue for unknown entries, use `strictObjectAsync`. To include and * validate unknown entries, use `objectWithRestAsync`. * * @param entries The entries schema. * * @returns An object schema. */ export function objectAsync( entries: TEntries ): ObjectSchemaAsync; /** * Creates an object schema. * * Hint: This schema removes unknown entries. The output will only include the * entries you specify. To include unknown entries, use `looseObjectAsync`. To * return an issue for unknown entries, use `strictObjectAsync`. To include and * validate unknown entries, use `objectWithRestAsync`. * * @param entries The entries schema. * @param message The error message. * * @returns An object schema. */ export function objectAsync< const TEntries extends ObjectEntriesAsync, const TMessage extends ErrorMessage | undefined, >(entries: TEntries, message: TMessage): ObjectSchemaAsync; // @__NO_SIDE_EFFECTS__ export function objectAsync( entries: ObjectEntriesAsync, message?: ErrorMessage ): ObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined > { return { kind: 'schema', type: 'object', reference: objectAsync, expects: 'Object', async: true, entries, message, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (input && typeof input === 'object') { // Set typed to `true` and value to blank object // @ts-expect-error dataset.typed = true; dataset.value = {}; // If key is present or its an optional schema with a default value, // parse input of key or default value asynchronously const valueDatasets = await Promise.all( Object.entries(this.entries).map(async ([key, valueSchema]) => { if ( key in input || ((valueSchema.type === 'exact_optional' || valueSchema.type === 'optional' || valueSchema.type === 'nullish') && // @ts-expect-error valueSchema.default !== undefined) ) { const value: unknown = key in input ? // @ts-expect-error input[key] : await getDefault(valueSchema); return [ key, value, valueSchema, await valueSchema['~run']({ value }, config), ] as const; } return [ key, // @ts-expect-error input[key] as unknown, valueSchema, null, ] as const; }) ); // Process each object entry of schema for (const [key, value, valueSchema, valueDataset] of valueDatasets) { // If key is present or its an optional schema with a default value, // process its value dataset if (valueDataset) { // If there are issues, capture them if (valueDataset.issues) { // Create object path item const pathItem: ObjectPathItem = { type: 'object', origin: 'value', input: input as Record, key, value, }; // Add modified entry dataset issues to issues for (const issue of valueDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = valueDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!valueDataset.typed) { dataset.typed = false; } // Add entry to dataset // @ts-expect-error dataset.value[key] = valueDataset.value; // Otherwise, if key is missing but has a fallback, use it // @ts-expect-error } else if (valueSchema.fallback !== undefined) { // @ts-expect-error dataset.value[key] = await getFallback(valueSchema); // Otherwise, if key is missing and required, add issue } else if ( valueSchema.type !== 'exact_optional' && valueSchema.type !== 'optional' && valueSchema.type !== 'nullish' ) { _addIssue(this, 'key', dataset, config, { input: undefined, expected: `"${key}"`, path: [ { type: 'object', origin: 'key', input: input as Record, key, value, }, ], }); // If necessary, abort early if (config.abortEarly) { break; } } } // Otherwise, add object issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< InferObjectOutput, ObjectIssue | InferObjectIssue >; }, }; } ================================================ FILE: library/src/schemas/object/types.ts ================================================ import type { BaseIssue } from '../../types/index.ts'; /** * Object issue interface. */ export interface ObjectIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'object'; /** * The expected property. */ readonly expected: 'Object' | `"${string}"`; } ================================================ FILE: library/src/schemas/objectWithRest/index.ts ================================================ export * from './objectWithRest.ts'; export * from './objectWithRestAsync.ts'; export * from './types.ts'; ================================================ FILE: library/src/schemas/objectWithRest/objectWithRest.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { Brand, BrandAction, DescriptionAction, ReadonlyAction, TransformAction, } from '../../actions/index.ts'; import type { SchemaWithPipe } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { AnySchema } from '../any/index.ts'; import type { BooleanIssue, BooleanSchema } from '../boolean/index.ts'; import type { CustomIssue, CustomSchema } from '../custom/index.ts'; import type { ExactOptionalSchema } from '../exactOptional/index.ts'; import type { NullishSchema } from '../nullish/index.ts'; import { number, type NumberIssue, type NumberSchema, } from '../number/index.ts'; import type { ObjectIssue, ObjectSchema } from '../object/index.ts'; import type { OptionalSchema } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import type { UndefinedableSchema } from '../undefinedable/index.ts'; import type { UnknownSchema } from '../unknown/index.ts'; import { objectWithRest, type ObjectWithRestSchema } from './objectWithRest.ts'; import type { ObjectWithRestIssue } from './types.ts'; describe('objectWithRest', () => { describe('should return schema object', () => { const entries = { key: string() }; type Entries = typeof entries; const rest = number(); type Rest = typeof rest; test('with undefined message', () => { type Schema = ObjectWithRestSchema; expectTypeOf(objectWithRest(entries, rest)).toEqualTypeOf(); expectTypeOf( objectWithRest(entries, rest, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(objectWithRest(entries, rest, 'message')).toEqualTypeOf< ObjectWithRestSchema >(); }); test('with function message', () => { expectTypeOf( objectWithRest(entries, rest, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Schema = ObjectWithRestSchema< { key00: StringSchema; key01: AnySchema; key02: UnknownSchema; key03: ObjectSchema<{ key: NumberSchema }, undefined>; key04: SchemaWithPipe< [StringSchema, ReadonlyAction] >; key05: UndefinedableSchema, 'bar'>; key06: SchemaWithPipe< [ OptionalSchema, undefined>, TransformAction, ] >; key07: CustomSchema<`a${string}` | `b${string}`, undefined>; key08: SchemaWithPipe< [StringSchema, BrandAction] >; // ExactOptionalSchema key10: ExactOptionalSchema, undefined>; key11: ExactOptionalSchema, 'foo'>; key12: ExactOptionalSchema, () => 'foo'>; // OptionalSchema key20: OptionalSchema, undefined>; key21: OptionalSchema, 'foo'>; key22: OptionalSchema, () => undefined>; key23: OptionalSchema, () => 'foo'>; // NullishSchema key30: NullishSchema, undefined>; key31: NullishSchema, null>; key32: NullishSchema, 'foo'>; key33: NullishSchema, () => undefined>; key34: NullishSchema, () => null>; key35: NullishSchema, () => 'foo'>; // SchemaWithPipe key40: SchemaWithPipe< [ExactOptionalSchema, undefined>] >; key41: SchemaWithPipe< [ ExactOptionalSchema, undefined>, DescriptionAction, ] >; key42: SchemaWithPipe< [OptionalSchema, undefined>] >; key43: SchemaWithPipe< [ OptionalSchema, undefined>, DescriptionAction, ] >; key44: SchemaWithPipe< [NullishSchema, undefined>] >; key45: SchemaWithPipe< [ NullishSchema, undefined>, DescriptionAction, ] >; key46: SchemaWithPipe< [ NullishSchema, undefined>, TransformAction, ] >; }, BooleanSchema, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf< { key00: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any key01: any; key02: unknown; key03: { key: number }; key04: string; key05: string | undefined; key06?: string | undefined; key07: `a${string}` | `b${string}`; key08: string; // ExactOptionalSchema key10?: string; key11?: string; key12?: string; // OptionalSchema key20?: string | undefined; key21?: string | undefined; key22?: string | undefined; key23?: string | undefined; // NullishSchema key30?: string | null | undefined; key31?: string | null | undefined; key32?: string | null | undefined; key33?: string | null | undefined; key34?: string | null | undefined; key35?: string | null | undefined; // SchemaWithPipe key40?: string; key41?: string; key42?: string | undefined; key43?: string | undefined; key44?: string | null | undefined; key45?: string | null | undefined; key46?: string | null | undefined; } & { [key: string]: boolean } >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< { key00: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any key01: any; key02: unknown; key03: { key: number }; readonly key04: string; key05: string; key06?: number; key07: `a${string}` | `b${string}`; key08: string & Brand<'foo'>; // ExactOptionalSchema key10?: string; key11: string; key12: string; // OptionalSchema key20?: string | undefined; key21: string; key22: string | undefined; key23: string; // NullishSchema key30?: string | null | undefined; key31: string | null; key32: string; key33: string | undefined; key34: string | null; key35: string; // SchemaWithPipe key40?: string; key41?: string; key42?: string | undefined; key43?: string | undefined; key44?: string | null | undefined; key45?: string | null | undefined; key46?: string[]; } & { [key: string]: boolean } >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< | ObjectWithRestIssue | ObjectIssue | StringIssue | NumberIssue | BooleanIssue | CustomIssue >(); }); }); }); ================================================ FILE: library/src/schemas/objectWithRest/objectWithRest.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { fallback } from '../../methods/index.ts'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { any } from '../any/index.ts'; import { array } from '../array/array.ts'; import type { ArrayIssue } from '../array/types.ts'; import { boolean } from '../boolean/index.ts'; import { exactOptional } from '../exactOptional/index.ts'; import { never } from '../never/index.ts'; import { nullish } from '../nullish/index.ts'; import { number } from '../number/index.ts'; import { object } from '../object/index.ts'; import { optional } from '../optional/index.ts'; import { string } from '../string/index.ts'; import { unknown } from '../unknown/index.ts'; import { objectWithRest, type ObjectWithRestSchema } from './objectWithRest.ts'; import type { ObjectWithRestIssue } from './types.ts'; describe('objectWithRest', () => { describe('should return schema object', () => { const entries = { key: string() }; type Entries = typeof entries; const rest = number(); type Rest = typeof rest; const baseSchema: Omit< ObjectWithRestSchema, 'message' > = { kind: 'schema', type: 'object_with_rest', reference: objectWithRest, expects: 'Object', entries, rest, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: ObjectWithRestSchema = { ...baseSchema, message: undefined, }; expect(objectWithRest(entries, rest)).toStrictEqual(schema); expect(objectWithRest(entries, rest, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(objectWithRest(entries, rest, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies ObjectWithRestSchema); }); test('with function message', () => { const message = () => 'message'; expect(objectWithRest(entries, rest, message)).toStrictEqual({ ...baseSchema, message, } satisfies ObjectWithRestSchema); }); }); describe('should return dataset without issues', () => { test('for empty object', () => { expectNoSchemaIssue(objectWithRest({}, boolean()), [{}]); }); test('for simple object', () => { expectNoSchemaIssue( objectWithRest({ key1: string(), key2: number() }, boolean()), // @ts-expect-error [{ key1: 'foo', key2: 123, other: true }] ); }); }); describe('should return dataset with issues', () => { const schema = objectWithRest({}, never(), 'message'); const baseIssue: Omit = { kind: 'schema', type: 'object_with_rest', expected: 'Object', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types // TODO: Enable this test again in case we find a reliable way to check for // plain objects // test('for arrays', () => { // expectSchemaIssue(schema, baseIssue, [[], ['value']]); // }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); }); describe('should return dataset without nested issues', () => { test('for simple object', () => { expectNoSchemaIssue( objectWithRest({ key1: string(), key2: number() }, boolean()), // @ts-expect-error [{ key1: 'foo', key2: 123, other: true }] ); }); test('for nested object', () => { expectNoSchemaIssue( objectWithRest( { nested: object({ key: string() }) }, object({ key: number() }) ), // @ts-expect-error [{ nested: { key: 'foo' }, other: { key: 123 } }] ); }); test('for missing entries with fallback', () => { expect( objectWithRest( { key1: fallback(string(), 'foo'), key2: fallback(number(), () => 123), }, boolean() )['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key1: 'foo', key2: 123 }, }); }); test('for exact optional entry', () => { expectNoSchemaIssue( objectWithRest({ key: exactOptional(string()) }, number()), // @ts-expect-error [{}, { key: 'foo' }] ); }); test('for exact optional entry with default', () => { expect( objectWithRest({ key: exactOptional(string(), 'foo') }, number())[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( objectWithRest({ key: exactOptional(string(), () => 'foo') }, number())[ '~run' ]({ value: { other: 123 } }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo', other: 123 }, }); }); test('for optional entry', () => { expectNoSchemaIssue( objectWithRest({ key: optional(string()) }, number()), // @ts-expect-error [{}, { key: undefined, other: 123 }, { key: 'foo' }] ); }); test('for optional entry with default', () => { expect( objectWithRest({ key: optional(string(), 'foo') }, number())['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( objectWithRest({ key: optional(string(), () => 'foo') }, number())[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( objectWithRest({ key: optional(string(), () => undefined) }, number())[ '~run' ]({ value: { other: 123 } }, {}) ).toStrictEqual({ typed: true, value: { key: undefined, other: 123 }, }); }); test('for nullish entry', () => { expectNoSchemaIssue( objectWithRest({ key: nullish(number()) }, number()), // @ts-expect-error [{}, { key: undefined }, { key: null, other: 123 }, { key: 123 }] ); }); test('for nullish entry with default', () => { expect( objectWithRest({ key: nullish(string(), 'foo') }, number())['~run']( { value: { other: 123 } }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo', other: 123 }, }); expect( objectWithRest({ key: nullish(string(), null) }, number())['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( objectWithRest({ key: nullish(string(), () => 'foo') }, number())[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( objectWithRest({ key: nullish(string(), () => null) }, number())[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( objectWithRest({ key: nullish(string(), () => undefined) }, number())[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); }); }); describe('should return dataset with nested issues', () => { const schema = objectWithRest( { key1: string(), key2: number(), nested: objectWithRest({ key1: string(), key2: number() }, number()), }, array(boolean()) ); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for missing entries', () => { const input = { key2: 123, other: [true, false] }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"nested"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'nested', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for missing nested entries', () => { const input = { key1: 'value', nested: { other: 123 } }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key2', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'key', input: input.nested, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'key', input: input.nested, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for missing entries with abort early', () => { const input = { key2: 123 }; expect( schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key1', value: undefined, }, ], abortEarly: true, }, ], } satisfies FailureDataset>); }); test('for missing any and unknown entry', () => { const schema = objectWithRest({ key1: any(), key2: unknown() }, number()); expect(schema['~run']({ value: {} }, {})).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid entries', () => { const input = { key1: false, key2: 123, nested: null, other: [false] }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: false, expected: 'string', received: 'false', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: false, }, ], }, { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: null, expected: 'Object', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: null, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid nested entries', () => { const input = { key1: 'value', key2: 'value', nested: { key1: 123, key2: null, other: 123, }, }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: 'value', expected: 'number', received: '"value"', path: [ { type: 'object', origin: 'value', input, key: 'key2', value: input.key2, }, ], }, { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'value', input: input.nested, key: 'key1', value: input.nested.key1, }, ], }, { ...baseInfo, kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'value', input: input.nested, key: 'key2', value: input.nested.key2, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid entries with abort early', () => { const input = { key1: false, key2: 123, nested: null }; expect( schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: false, expected: 'string', received: 'false', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: false, }, ], abortEarly: true, }, ], } satisfies FailureDataset>); }); test('for invalid exact optional entry', () => { const schema = objectWithRest({ key: exactOptional(string()) }, number()); const input = { key: undefined }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: undefined, expected: 'string', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'key', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); const arrayIssue: ArrayIssue = { ...baseInfo, kind: 'schema', type: 'array', input: null, expected: 'Array', received: 'null', path: [ { type: 'object', origin: 'value', input: { key1: 'foo', key2: 123, nested: { key1: 'foo', key2: 123 }, other1: null, other2: 'bar', }, key: 'other1', value: null, }, ], }; test('for wrong rest', () => { const input = { key1: 'foo', key2: 123, nested: { key1: 'foo', key2: 123 }, other1: null, other2: 'bar', }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ arrayIssue, { ...baseInfo, kind: 'schema', type: 'array', input: 'bar', expected: 'Array', received: '"bar"', path: [ { type: 'object', origin: 'value', input, key: 'other2', value: input.other2, }, ], }, ], } satisfies FailureDataset>); }); test('for wrong rest with abort early', () => { expect( schema['~run']( { value: { key1: 'foo', key2: 123, nested: { key1: 'foo', key2: 123 }, other1: null, other2: 'bar', }, }, { abortEarly: true } ) ).toStrictEqual({ typed: false, value: { key1: 'foo', key2: 123, nested: { key1: 'foo', key2: 123 }, }, issues: [{ ...arrayIssue, abortEarly: true }], } satisfies FailureDataset>); }); test('for wrong nested rest', () => { const input = { key1: 'foo', key2: 123, nested: { key1: 'foo', key2: 123 }, other: ['true'], }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'boolean', input: 'true', expected: 'boolean', received: '"true"', path: [ { type: 'object', origin: 'value', input, key: 'other', value: input.other, }, { type: 'array', origin: 'value', input: input.other, key: 0, value: input.other[0], }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/objectWithRest/objectWithRest.ts ================================================ import { getDefault, getFallback } from '../../methods/index.ts'; import type { BaseIssue, BaseSchema, ErrorMessage, InferInput, InferIssue, InferObjectInput, InferObjectIssue, InferObjectOutput, InferOutput, ObjectEntries, ObjectPathItem, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps, _isValidObjectKey, } from '../../utils/index.ts'; import type { ObjectWithRestIssue } from './types.ts'; /** * Object with rest schema interface. */ export interface ObjectWithRestSchema< TEntries extends ObjectEntries, TRest extends BaseSchema>, TMessage extends ErrorMessage | undefined, > extends BaseSchema< InferObjectInput & { [key: string]: InferInput }, InferObjectOutput & { [key: string]: InferOutput }, ObjectWithRestIssue | InferObjectIssue | InferIssue > { /** * The schema type. */ readonly type: 'object_with_rest'; /** * The schema reference. */ readonly reference: typeof objectWithRest; /** * The expected property. */ readonly expects: 'Object'; /** * The entries schema. */ readonly entries: TEntries; /** * The rest schema. */ readonly rest: TRest; /** * The error message. */ readonly message: TMessage; } /** * Creates an object with rest schema. * * @param entries The entries schema. * @param rest The rest schema. * * @returns An object with rest schema. */ export function objectWithRest< const TEntries extends ObjectEntries, const TRest extends BaseSchema>, >( entries: TEntries, rest: TRest ): ObjectWithRestSchema; /** * Creates an object with rest schema. * * @param entries The entries schema. * @param rest The rest schema. * @param message The error message. * * @returns An object with rest schema. */ export function objectWithRest< const TEntries extends ObjectEntries, const TRest extends BaseSchema>, const TMessage extends ErrorMessage | undefined, >( entries: TEntries, rest: TRest, message: TMessage ): ObjectWithRestSchema; // @__NO_SIDE_EFFECTS__ export function objectWithRest( entries: ObjectEntries, rest: BaseSchema>, message?: ErrorMessage ): ObjectWithRestSchema< ObjectEntries, BaseSchema>, ErrorMessage | undefined > { return { kind: 'schema', type: 'object_with_rest', reference: objectWithRest, expects: 'Object', async: false, entries, rest, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (input && typeof input === 'object') { // Set typed to `true` and value to blank object // @ts-expect-error dataset.typed = true; dataset.value = {}; // Process each object entry of schema for (const key in this.entries) { const valueSchema = this.entries[key]; // If key is present or its an optional schema with a default value, // parse input of key or default value if ( key in input || ((valueSchema.type === 'exact_optional' || valueSchema.type === 'optional' || valueSchema.type === 'nullish') && // @ts-expect-error valueSchema.default !== undefined) ) { const value: unknown = key in input ? // @ts-expect-error input[key] : getDefault(valueSchema); const valueDataset = valueSchema['~run']({ value }, config); // If there are issues, capture them if (valueDataset.issues) { // Create object path item const pathItem: ObjectPathItem = { type: 'object', origin: 'value', input: input as Record, key, value, }; // Add modified entry dataset issues to issues for (const issue of valueDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = valueDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!valueDataset.typed) { dataset.typed = false; } // Add entry to dataset // @ts-expect-error dataset.value[key] = valueDataset.value; // Otherwise, if key is missing but has a fallback, use it // @ts-expect-error } else if (valueSchema.fallback !== undefined) { // @ts-expect-error dataset.value[key] = getFallback(valueSchema); // Otherwise, if key is missing and required, add issue } else if ( valueSchema.type !== 'exact_optional' && valueSchema.type !== 'optional' && valueSchema.type !== 'nullish' ) { _addIssue(this, 'key', dataset, config, { input: undefined, expected: `"${key}"`, path: [ { type: 'object', origin: 'key', input: input as Record, key, // @ts-expect-error value: input[key], }, ], }); // If necessary, abort early if (config.abortEarly) { break; } } } // Parse schema of each rest entry if necessary // Hint: We exclude specific keys for security reasons if (!dataset.issues || !config.abortEarly) { for (const key in input) { if (_isValidObjectKey(input, key) && !(key in this.entries)) { const valueDataset = this.rest['~run']( // @ts-expect-error { value: input[key] }, config ); // If there are issues, capture them if (valueDataset.issues) { // Create object path item const pathItem: ObjectPathItem = { type: 'object', origin: 'value', input: input as Record, key, // @ts-expect-error value: input[key], }; // Add modified entry dataset issues to issues for (const issue of valueDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = valueDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!valueDataset.typed) { dataset.typed = false; } // Add entry to dataset // @ts-expect-error dataset.value[key] = valueDataset.value; } } } // Otherwise, add object issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< InferObjectOutput & { [key: string]: unknown }, | ObjectWithRestIssue | InferObjectIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/objectWithRest/objectWithRestAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { Brand, BrandAction, DescriptionAction, ReadonlyAction, TransformAction, } from '../../actions/index.ts'; import type { SchemaWithPipe, SchemaWithPipeAsync, } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { AnySchema } from '../any/index.ts'; import type { BooleanIssue, BooleanSchema } from '../boolean/index.ts'; import type { CustomIssue, CustomSchemaAsync } from '../custom/index.ts'; import type { ExactOptionalSchema, ExactOptionalSchemaAsync, } from '../exactOptional/index.ts'; import type { NullishSchema, NullishSchemaAsync } from '../nullish/index.ts'; import { number, type NumberIssue, type NumberSchema, } from '../number/index.ts'; import type { ObjectIssue, ObjectSchemaAsync } from '../object/index.ts'; import type { OptionalSchema, OptionalSchemaAsync } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import type { UndefinedableSchema } from '../undefinedable/index.ts'; import type { UnknownSchema } from '../unknown/index.ts'; import { objectWithRestAsync, type ObjectWithRestSchemaAsync, } from './objectWithRestAsync.ts'; import type { ObjectWithRestIssue } from './types.ts'; describe('objectWithRestAsync', () => { describe('should return schema object', () => { const entries = { key: string() }; type Entries = typeof entries; const rest = number(); type Rest = typeof rest; test('with undefined message', () => { type Schema = ObjectWithRestSchemaAsync; expectTypeOf(objectWithRestAsync(entries, rest)).toEqualTypeOf(); expectTypeOf( objectWithRestAsync(entries, rest, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(objectWithRestAsync(entries, rest, 'message')).toEqualTypeOf< ObjectWithRestSchemaAsync >(); }); test('with function message', () => { expectTypeOf( objectWithRestAsync(entries, rest, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Schema = ObjectWithRestSchemaAsync< { key00: StringSchema; key01: AnySchema; key02: UnknownSchema; key03: ObjectSchemaAsync<{ key: NumberSchema }, undefined>; key04: SchemaWithPipe< [StringSchema, ReadonlyAction] >; key05: UndefinedableSchema, 'bar'>; key06: SchemaWithPipe< [ OptionalSchema, undefined>, TransformAction, ] >; key07: SchemaWithPipeAsync< [ OptionalSchema, undefined>, TransformAction, ] >; key08: SchemaWithPipeAsync< [ OptionalSchemaAsync, undefined>, TransformAction, ] >; key09: CustomSchemaAsync<`a${string}` | `b${string}`, undefined>; key10: SchemaWithPipe< [StringSchema, BrandAction] >; // ExactOptionalSchema key20: ExactOptionalSchema, undefined>; key21: ExactOptionalSchema, 'foo'>; key22: ExactOptionalSchema, () => 'foo'>; // ExactOptionalSchemaAsync key30: ExactOptionalSchemaAsync, undefined>; key31: ExactOptionalSchemaAsync, 'foo'>; key32: ExactOptionalSchemaAsync, () => 'foo'>; key33: ExactOptionalSchemaAsync< StringSchema, () => Promise<'foo'> >; // OptionalSchema key40: OptionalSchema, undefined>; key41: OptionalSchema, 'foo'>; key42: OptionalSchema, () => undefined>; key43: OptionalSchema, () => 'foo'>; // OptionalSchemaAsync key50: OptionalSchemaAsync, undefined>; key51: OptionalSchemaAsync, 'foo'>; key52: OptionalSchemaAsync, () => undefined>; key53: OptionalSchemaAsync, () => 'foo'>; key54: OptionalSchemaAsync< StringSchema, () => Promise >; key55: OptionalSchemaAsync< StringSchema, () => Promise<'foo'> >; // NullishSchema key60: NullishSchema, undefined>; key61: NullishSchema, null>; key62: NullishSchema, 'foo'>; key63: NullishSchema, () => undefined>; key64: NullishSchema, () => null>; key65: NullishSchema, () => 'foo'>; // NullishSchemaAsync key70: NullishSchemaAsync, undefined>; key71: NullishSchemaAsync, null>; key72: NullishSchemaAsync, 'foo'>; key73: NullishSchemaAsync, () => undefined>; key74: NullishSchemaAsync, () => null>; key75: NullishSchemaAsync, () => 'foo'>; key76: NullishSchemaAsync< StringSchema, () => Promise >; key77: NullishSchemaAsync, () => Promise>; key78: NullishSchemaAsync< StringSchema, () => Promise<'foo'> >; // SchemaWithPipe key80: SchemaWithPipe< [ExactOptionalSchema, undefined>] >; key81: SchemaWithPipe< [ ExactOptionalSchema, undefined>, DescriptionAction, ] >; key82: SchemaWithPipe< [OptionalSchema, undefined>] >; key83: SchemaWithPipe< [ OptionalSchema, undefined>, DescriptionAction, ] >; key84: SchemaWithPipe< [NullishSchema, undefined>] >; key85: SchemaWithPipe< [ NullishSchema, undefined>, DescriptionAction, ] >; key86: SchemaWithPipe< [ NullishSchema, undefined>, TransformAction, ] >; key87: SchemaWithPipeAsync< [ NullishSchemaAsync, undefined>, TransformAction, ] >; }, BooleanSchema, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf< { key00: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any key01: any; key02: unknown; key03: { key: number }; key04: string; key05: string | undefined; key06?: string | undefined; key07?: string | undefined; key08?: string | undefined; key09: `a${string}` | `b${string}`; key10: string; // ExactOptionalSchema key20?: string; key21?: string; key22?: string; // ExactOptionalSchemaAsync key30?: string; key31?: string; key32?: string; key33?: string; // OptionalSchema key40?: string | undefined; key41?: string | undefined; key42?: string | undefined; key43?: string | undefined; // OptionalSchemaAsync key50?: string | undefined; key51?: string | undefined; key52?: string | undefined; key53?: string | undefined; key54?: string | undefined; key55?: string | undefined; // NullishSchema key60?: string | null | undefined; key61?: string | null | undefined; key62?: string | null | undefined; key63?: string | null | undefined; key64?: string | null | undefined; key65?: string | null | undefined; // NullishSchemaAsync key70?: string | null | undefined; key71?: string | null | undefined; key72?: string | null | undefined; key73?: string | null | undefined; key74?: string | null | undefined; key75?: string | null | undefined; key76?: string | null | undefined; key77?: string | null | undefined; key78?: string | null | undefined; // SchemaWithPipe key80?: string; key81?: string; key82?: string | undefined; key83?: string | undefined; key84?: string | null | undefined; key85?: string | null | undefined; key86?: string | null | undefined; key87?: string | null | undefined; } & { [key: string]: boolean } >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< { key00: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any key01: any; key02: unknown; key03: { key: number }; readonly key04: string; key05: string; key06?: number; key07?: number; key08?: number; key09: `a${string}` | `b${string}`; key10: string & Brand<'foo'>; // ExactOptionalSchema key20?: string; key21: string; key22: string; // ExactOptionalSchemaAsync key30?: string; key31: string; key32: string; key33: string; // OptionalSchema key40?: string | undefined; key41: string; key42: string | undefined; key43: string; // OptionalSchemaAsync key50?: string | undefined; key51: string; key52: string | undefined; key53: string; key54: string | undefined; key55: string; // NullishSchema key60?: string | null | undefined; key61: string | null; key62: string; key63: string | undefined; key64: string | null; key65: string; // NullishSchemaAsync key70?: string | null | undefined; key71: string | null; key72: string; key73: string | undefined; key74: string | null; key75: string; key76: string | undefined; key77: string | null; key78: string; // SchemaWithPipe key80?: string; key81?: string; key82?: string | undefined; key83?: string | undefined; key84?: string | null | undefined; key85?: string | null | undefined; key86?: string[]; key87?: string[]; } & { [key: string]: boolean } >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< | ObjectWithRestIssue | ObjectIssue | StringIssue | NumberIssue | BooleanIssue | CustomIssue >(); }); }); }); ================================================ FILE: library/src/schemas/objectWithRest/objectWithRestAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { fallback, fallbackAsync } from '../../methods/index.ts'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { any } from '../any/index.ts'; import { array } from '../array/array.ts'; import type { ArrayIssue } from '../array/types.ts'; import { boolean } from '../boolean/index.ts'; import { exactOptional, exactOptionalAsync } from '../exactOptional/index.ts'; import { never } from '../never/index.ts'; import { nullish, nullishAsync } from '../nullish/index.ts'; import { number } from '../number/index.ts'; import { object, objectAsync } from '../object/index.ts'; import { optional, optionalAsync } from '../optional/index.ts'; import { string } from '../string/index.ts'; import { unknown } from '../unknown/index.ts'; import { objectWithRestAsync, type ObjectWithRestSchemaAsync, } from './objectWithRestAsync.ts'; import type { ObjectWithRestIssue } from './types.ts'; describe('objectWithRestAsync', () => { describe('should return schema object', () => { const entries = { key: string() }; type Entries = typeof entries; const rest = number(); type Rest = typeof rest; const baseSchema: Omit< ObjectWithRestSchemaAsync, 'message' > = { kind: 'schema', type: 'object_with_rest', reference: objectWithRestAsync, expects: 'Object', entries, rest, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: ObjectWithRestSchemaAsync = { ...baseSchema, message: undefined, }; expect(objectWithRestAsync(entries, rest)).toStrictEqual(schema); expect(objectWithRestAsync(entries, rest, undefined)).toStrictEqual( schema ); }); test('with string message', () => { expect(objectWithRestAsync(entries, rest, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies ObjectWithRestSchemaAsync); }); test('with function message', () => { const message = () => 'message'; expect(objectWithRestAsync(entries, rest, message)).toStrictEqual({ ...baseSchema, message, } satisfies ObjectWithRestSchemaAsync); }); }); describe('should return dataset without issues', () => { test('for empty object', async () => { await expectNoSchemaIssueAsync(objectWithRestAsync({}, boolean()), [{}]); }); test('for simple object', async () => { await expectNoSchemaIssueAsync( objectWithRestAsync({ key1: string(), key2: number() }, boolean()), // @ts-expect-error [{ key1: 'foo', key2: 123, other: true }] ); }); }); describe('should return dataset with issues', () => { const schema = objectWithRestAsync({}, never(), 'message'); const baseIssue: Omit = { kind: 'schema', type: 'object_with_rest', expected: 'Object', message: 'message', }; // Primitive types test('for bigints', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', async () => { await expectSchemaIssueAsync(schema, baseIssue, [true, false]); }); test('for null', async () => { await expectSchemaIssueAsync(schema, baseIssue, [null]); }); test('for numbers', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', async () => { await expectSchemaIssueAsync(schema, baseIssue, [undefined]); }); test('for strings', async () => { await expectSchemaIssueAsync(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ Symbol(), Symbol('foo'), ]); }); // Complex types // TODO: Enable this test again in case we find a reliable way to check for // plain objects // test('for arrays', async () => { // await expectSchemaIssueAsync(schema, baseIssue, [[], ['value']]); // }); test('for functions', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ // eslint-disable-next-line @typescript-eslint/no-empty-function () => {}, // eslint-disable-next-line @typescript-eslint/no-empty-function function () {}, ]); }); }); describe('should return dataset without nested issues', () => { test('for simple object', async () => { await expectNoSchemaIssueAsync( objectWithRestAsync({ key1: string(), key2: number() }, boolean()), // @ts-expect-error [{ key1: 'foo', key2: 123, other: true }] ); }); test('for nested object', async () => { await expectNoSchemaIssueAsync( objectWithRestAsync( { nested: object({ key: string() }) }, objectAsync({ key: number() }) ), // @ts-expect-error [{ nested: { key: 'foo' }, other: { key: 123 } }] ); }); test('for missing entries with fallback', async () => { expect( await objectWithRestAsync( { key1: fallback(string(), 'foo'), key2: fallback(number(), () => 123), key3: fallbackAsync(string(), 'bar'), key4: fallbackAsync(number(), () => 456), key5: fallbackAsync(string(), async () => 'baz'), }, boolean() )['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key1: 'foo', key2: 123, key3: 'bar', key4: 456, key5: 'baz' }, }); }); test('for exact optional entry', async () => { await expectNoSchemaIssueAsync( objectWithRestAsync({ key: exactOptional(string()) }, number()), // @ts-expect-error [{}, { key: 'foo', other: 123 }] ); await expectNoSchemaIssueAsync( objectWithRestAsync({ key: exactOptionalAsync(string()) }, number()), // @ts-expect-error [{}, { key: 'foo' }] ); }); test('for exact optional entry with default', async () => { // Sync expect( await objectWithRestAsync( { key: exactOptional(string(), 'foo') }, number() )['~run']({ value: { other: 123 } }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo', other: 123 }, }); expect( await objectWithRestAsync( { key: exactOptional(string(), () => 'foo') }, number() )['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); // Async expect( await objectWithRestAsync( { key: exactOptionalAsync(string(), 'foo') }, number() )['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectWithRestAsync( { key: exactOptionalAsync(string(), () => 'foo') }, number() )['~run']({ value: { other: 123 } }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo', other: 123 }, }); }); test('for optional entry', async () => { await expectNoSchemaIssueAsync( objectWithRestAsync({ key: optional(string()) }, number()), // @ts-expect-error [{}, { key: undefined, other: 123 }, { key: 'foo' }] ); await expectNoSchemaIssueAsync( objectWithRestAsync({ key: optionalAsync(string()) }, number()), // @ts-expect-error [{}, { key: undefined, other: 123 }, { key: 'foo' }] ); }); test('for optional entry with default', async () => { // Sync expect( await objectWithRestAsync({ key: optional(string(), 'foo') }, number())[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectWithRestAsync( { key: optional(string(), () => 'foo') }, number() )['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectWithRestAsync( { key: optional(string(), () => undefined) }, number() )['~run']({ value: { other: 123 } }, {}) ).toStrictEqual({ typed: true, value: { key: undefined, other: 123 }, }); // Async expect( await objectWithRestAsync( { key: optionalAsync(string(), 'foo') }, number() )['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectWithRestAsync( { key: optionalAsync(string(), () => 'foo') }, number() )['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectWithRestAsync( { key: optionalAsync(string(), () => undefined) }, number() )['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); expect( await objectWithRestAsync( { key: optionalAsync(string(), async () => 'foo') }, number() )['~run']({ value: { other: 123 } }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo', other: 123 }, }); expect( await objectWithRestAsync( { key: optionalAsync(string(), async () => undefined) }, number() )['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); }); test('for nullish entry', async () => { await expectNoSchemaIssueAsync( objectWithRestAsync({ key: nullish(number()) }, number()), // @ts-expect-error [{}, { key: undefined }, { key: null, other: 123 }, { key: 123 }] ); await expectNoSchemaIssueAsync( objectWithRestAsync({ key: nullishAsync(number()) }, number()), // @ts-expect-error [{ other: 123 }, { key: undefined }, { key: null }, { key: 123 }] ); }); test('for nullish entry with default', async () => { // Sync expect( await objectWithRestAsync({ key: nullish(string(), 'foo') }, number())[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectWithRestAsync({ key: nullish(string(), null) }, number())[ '~run' ]({ value: { other: 123 } }, {}) ).toStrictEqual({ typed: true, value: { key: null, other: 123 }, }); expect( await objectWithRestAsync( { key: nullish(string(), () => 'foo') }, number() )['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectWithRestAsync( { key: nullish(string(), () => null) }, number() )['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( await objectWithRestAsync( { key: nullish(string(), () => undefined) }, number() )['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); // Async expect( await objectWithRestAsync( { key: nullishAsync(string(), 'foo') }, number() )['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectWithRestAsync( { key: nullishAsync(string(), null) }, number() )['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( await objectWithRestAsync( { key: nullishAsync(string(), () => 'foo') }, number() )['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectWithRestAsync( { key: nullishAsync(string(), () => null) }, number() )['~run']({ value: { other: 123 } }, {}) ).toStrictEqual({ typed: true, value: { key: null, other: 123 }, }); expect( await objectWithRestAsync( { key: nullishAsync(string(), () => undefined) }, number() )['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); expect( await objectWithRestAsync( { key: nullishAsync(string(), async () => 'foo') }, number() )['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await objectWithRestAsync( { key: nullishAsync(string(), async () => null) }, number() )['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( await objectWithRestAsync( { key: nullishAsync(string(), async () => undefined) }, number() )['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); }); }); describe('should return dataset with nested issues', () => { const schema = objectWithRestAsync( { key1: string(), key2: number(), nested: objectWithRestAsync( { key1: string(), key2: number() }, number() ), }, array(boolean()) ); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for missing entries', async () => { const input = { key2: 123, other: [true, false] }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"nested"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'nested', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for missing nested entries', async () => { const input = { key1: 'value', nested: { other: 123 } }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key2', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'key', input: input.nested, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'key', input: input.nested, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for missing entries with abort early', async () => { const input = { key2: 123 }; expect( await schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key1', value: undefined, }, ], abortEarly: true, }, ], } satisfies FailureDataset>); }); test('for missing any and unknown entry', async () => { const schema = objectWithRestAsync( { key1: any(), key2: unknown() }, number() ); expect(await schema['~run']({ value: {} }, {})).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid entries', async () => { const input = { key1: false, key2: 123, nested: null, other: [false] }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: false, expected: 'string', received: 'false', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: false, }, ], }, { ...baseInfo, kind: 'schema', type: 'object_with_rest', input: null, expected: 'Object', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: null, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid nested entries', async () => { const input = { key1: 'value', key2: 'value', nested: { key1: 123, key2: null, other: 123, }, }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: 'value', expected: 'number', received: '"value"', path: [ { type: 'object', origin: 'value', input, key: 'key2', value: input.key2, }, ], }, { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'value', input: input.nested, key: 'key1', value: input.nested.key1, }, ], }, { ...baseInfo, kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'value', input: input.nested, key: 'key2', value: input.nested.key2, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid entries with abort early', async () => { const input = { key1: false, key2: 123, nested: null }; expect( await schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: false, expected: 'string', received: 'false', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: false, }, ], abortEarly: true, }, ], } satisfies FailureDataset>); }); test('for invalid exact optional entry', async () => { const schema = objectWithRestAsync( { key: exactOptional(string()) }, number() ); const input = { key: undefined }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: undefined, expected: 'string', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'key', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); const arrayIssue: ArrayIssue = { ...baseInfo, kind: 'schema', type: 'array', input: null, expected: 'Array', received: 'null', path: [ { type: 'object', origin: 'value', input: { key1: 'foo', key2: 123, nested: { key1: 'foo', key2: 123 }, other1: null, other2: 'bar', }, key: 'other1', value: null, }, ], }; test('for wrong rest', async () => { const input = { key1: 'foo', key2: 123, nested: { key1: 'foo', key2: 123 }, other1: null, other2: 'bar', }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ arrayIssue, { ...baseInfo, kind: 'schema', type: 'array', input: 'bar', expected: 'Array', received: '"bar"', path: [ { type: 'object', origin: 'value', input, key: 'other2', value: input.other2, }, ], }, ], } satisfies FailureDataset>); }); test('for wrong rest with abort early', async () => { expect( await schema['~run']( { value: { key1: 'foo', key2: 123, nested: { key1: 'foo', key2: 123 }, other1: null, other2: 'bar', }, }, { abortEarly: true } ) ).toStrictEqual({ typed: false, value: { key1: 'foo', key2: 123, nested: { key1: 'foo', key2: 123 }, }, issues: [{ ...arrayIssue, abortEarly: true }], } satisfies FailureDataset>); }); test('for wrong nested rest', async () => { const input = { key1: 'foo', key2: 123, nested: { key1: 'foo', key2: 123 }, other: ['true'], }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'boolean', input: 'true', expected: 'boolean', received: '"true"', path: [ { type: 'object', origin: 'value', input, key: 'other', value: input.other, }, { type: 'array', origin: 'value', input: input.other, key: 0, value: input.other[0], }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/objectWithRest/objectWithRestAsync.ts ================================================ import { getDefault, getFallback } from '../../methods/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, ErrorMessage, InferInput, InferIssue, InferObjectInput, InferObjectIssue, InferObjectOutput, InferOutput, ObjectEntriesAsync, ObjectPathItem, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps, _isValidObjectKey, } from '../../utils/index.ts'; import type { objectWithRest } from './objectWithRest.ts'; import type { ObjectWithRestIssue } from './types.ts'; /** * Object schema async interface. */ export interface ObjectWithRestSchemaAsync< TEntries extends ObjectEntriesAsync, TRest extends | BaseSchema> | BaseSchemaAsync>, TMessage extends ErrorMessage | undefined, > extends BaseSchemaAsync< InferObjectInput & { [key: string]: InferInput }, InferObjectOutput & { [key: string]: InferOutput }, ObjectWithRestIssue | InferObjectIssue | InferIssue > { /** * The schema type. */ readonly type: 'object_with_rest'; /** * The schema reference. */ readonly reference: typeof objectWithRest | typeof objectWithRestAsync; /** * The expected property. */ readonly expects: 'Object'; /** * The entries schema. */ readonly entries: TEntries; /** * The rest schema. */ readonly rest: TRest; /** * The error message. */ readonly message: TMessage; } /** * Creates an object with rest schema. * * @param entries The entries schema. * @param rest The rest schema. * * @returns An object with rest schema. */ export function objectWithRestAsync< const TEntries extends ObjectEntriesAsync, const TRest extends | BaseSchema> | BaseSchemaAsync>, >( entries: TEntries, rest: TRest ): ObjectWithRestSchemaAsync; /** * Creates an object with rest schema. * * @param entries The entries schema. * @param rest The rest schema. * @param message The error message. * * @returns An object with rest schema. */ export function objectWithRestAsync< const TEntries extends ObjectEntriesAsync, const TRest extends | BaseSchema> | BaseSchemaAsync>, const TMessage extends ErrorMessage | undefined, >( entries: TEntries, rest: TRest, message: TMessage ): ObjectWithRestSchemaAsync; // @__NO_SIDE_EFFECTS__ export function objectWithRestAsync( entries: ObjectEntriesAsync, rest: | BaseSchema> | BaseSchemaAsync>, message?: ErrorMessage ): ObjectWithRestSchemaAsync< ObjectEntriesAsync, | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined > { return { kind: 'schema', type: 'object_with_rest', reference: objectWithRestAsync, expects: 'Object', async: true, entries, rest, message, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (input && typeof input === 'object') { // Set typed to `true` and value to blank object // @ts-expect-error dataset.typed = true; dataset.value = {}; // Parse each normal and rest entry const [normalDatasets, restDatasets] = await Promise.all([ // If key is present or its an optional schema with a default value, // parse input of key or default value asynchronously Promise.all( Object.entries(this.entries).map(async ([key, valueSchema]) => { if ( key in input || ((valueSchema.type === 'exact_optional' || valueSchema.type === 'optional' || valueSchema.type === 'nullish') && // @ts-expect-error valueSchema.default !== undefined) ) { const value: unknown = key in input ? // @ts-expect-error input[key] : await getDefault(valueSchema); return [ key, value, valueSchema, await valueSchema['~run']({ value }, config), ] as const; } return [ key, // @ts-expect-error input[key] as unknown, valueSchema, null, ] as const; }) ), // Parse other entries with rest schema asynchronously // Hint: We exclude specific keys for security reasons Promise.all( Object.entries(input) .filter( ([key]) => _isValidObjectKey(input, key) && !(key in this.entries) ) .map( async ([key, value]) => [ key, value, await this.rest['~run']({ value }, config), ] as const ) ), ]); // Process each normal object entry of schema for (const [key, value, valueSchema, valueDataset] of normalDatasets) { // If key is present or its an optional schema with a default value, // process its value dataset if (valueDataset) { // If there are issues, capture them if (valueDataset.issues) { // Create object path item const pathItem: ObjectPathItem = { type: 'object', origin: 'value', input: input as Record, key, value, }; // Add modified entry dataset issues to issues for (const issue of valueDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = valueDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!valueDataset.typed) { dataset.typed = false; } // Add entry to dataset // @ts-expect-error dataset.value[key] = valueDataset.value; // Otherwise, if key is missing but has a fallback, use it // @ts-expect-error } else if (valueSchema.fallback !== undefined) { // @ts-expect-error dataset.value[key] = await getFallback(valueSchema); // Otherwise, if key is missing and required, add issue } else if ( valueSchema.type !== 'exact_optional' && valueSchema.type !== 'optional' && valueSchema.type !== 'nullish' ) { _addIssue(this, 'key', dataset, config, { input: undefined, expected: `"${key}"`, path: [ { type: 'object', origin: 'key', input: input as Record, key, value, }, ], }); // If necessary, abort early if (config.abortEarly) { break; } } } // Process each rest entry of schema if necessary if (!dataset.issues || !config.abortEarly) { for (const [key, value, valueDataset] of restDatasets) { // If there are issues, capture them if (valueDataset.issues) { // Create object path item const pathItem: ObjectPathItem = { type: 'object', origin: 'value', input: input as Record, key, value, }; // Add modified entry dataset issues to issues for (const issue of valueDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = valueDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!valueDataset.typed) { dataset.typed = false; } // Add entry to dataset // @ts-expect-error dataset.value[key] = valueDataset.value; } } // Otherwise, add object issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< InferObjectOutput & { [key: string]: unknown }, | ObjectWithRestIssue | InferObjectIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/objectWithRest/types.ts ================================================ import type { BaseIssue } from '../../types/index.ts'; /** * Object with rest issue interface. */ export interface ObjectWithRestIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'object_with_rest'; /** * The expected property. */ readonly expected: 'Object' | `"${string}"`; } ================================================ FILE: library/src/schemas/optional/index.ts ================================================ export * from './optional.ts'; export * from './optionalAsync.ts'; ================================================ FILE: library/src/schemas/optional/optional.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { TransformAction } from '../../actions/index.ts'; import type { SchemaWithPipe } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { ArrayIssue, ArraySchema } from '../array/index.ts'; import type { ObjectIssue, ObjectSchema } from '../object/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { optional, type OptionalSchema } from './optional.ts'; describe('optional', () => { describe('should return schema object', () => { test('with undefined default', () => { type Schema = OptionalSchema, undefined>; expectTypeOf(optional(string())).toEqualTypeOf(); expectTypeOf(optional(string(), undefined)).toEqualTypeOf(); }); test('with undefined getter default', () => { expectTypeOf(optional(string(), () => undefined)).toEqualTypeOf< OptionalSchema, () => undefined> >(); }); test('with value default', () => { expectTypeOf(optional(string(), 'foo')).toEqualTypeOf< OptionalSchema, 'foo'> >(); }); test('with value getter default', () => { expectTypeOf(optional(string(), () => 'foo')).toEqualTypeOf< OptionalSchema, () => string> >(); }); }); describe('should infer correct types', () => { type Schema1 = OptionalSchema, undefined>; type Schema2 = OptionalSchema, 'foo'>; type Schema3 = OptionalSchema, () => undefined>; type Schema4 = OptionalSchema, () => 'foo'>; type Schema5 = OptionalSchema< SchemaWithPipe< [StringSchema, TransformAction] >, 'foo' >; type Schema6 = OptionalSchema< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, { foo: string[] } >; type Schema7 = OptionalSchema< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, () => { foo: string[] } >; test('of input', () => { type Input = string | undefined; expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf< { foo: string[] } | undefined >(); expectTypeOf>().toEqualTypeOf< { foo: string[] } | undefined >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); }); }); }); ================================================ FILE: library/src/schemas/optional/optional.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { optional, type OptionalSchema } from './optional.ts'; describe('optional', () => { describe('should return schema object', () => { const baseSchema: Omit< OptionalSchema, string>, 'default' > = { kind: 'schema', type: 'optional', reference: optional, expects: '(string | undefined)', wrapped: { ...string(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined default', () => { const expected: OptionalSchema, undefined> = { ...baseSchema, default: undefined, }; expect(optional(string())).toStrictEqual(expected); expect(optional(string(), undefined)).toStrictEqual(expected); }); test('with undefined getter default', () => { const getter = () => undefined; expect(optional(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies OptionalSchema, typeof getter>); }); test('with value default', () => { expect(optional(string(), 'foo')).toStrictEqual({ ...baseSchema, default: 'foo', } satisfies OptionalSchema, 'foo'>); }); test('with value getter default', () => { const getter = () => 'foo'; expect(optional(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies OptionalSchema, typeof getter>); }); }); describe('should return dataset without issues', () => { const schema = optional(string()); test('for wrapper type', () => { expectNoSchemaIssue(schema, ['', 'foo', '#$%']); }); test('for undefined', () => { expectNoSchemaIssue(schema, [undefined]); }); }); describe('should return dataset with issues', () => { const schema = optional(string('message')); const baseIssue: Omit = { kind: 'schema', type: 'string', expected: 'string', message: 'message', }; test('for invalid wrapper type', () => { expectSchemaIssue(schema, baseIssue, [123, true, {}]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); }); describe('should return dataset without default', () => { test('for undefined default', () => { expectNoSchemaIssue(optional(string()), [undefined, 'foo']); expectNoSchemaIssue(optional(string(), undefined), [undefined, 'foo']); }); test('for wrapper type', () => { expectNoSchemaIssue(optional(string(), 'foo'), ['', 'bar', '#$%']); }); }); describe('should return dataset with default', () => { const schema1 = optional(string(), 'foo'); const schema2 = optional(string(), () => undefined); const schema3 = optional(string(), () => 'foo'); test('for undefined', () => { expect(schema1['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: 'foo', }); expect(schema2['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: undefined, }); expect(schema3['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: 'foo', }); }); }); }); ================================================ FILE: library/src/schemas/optional/optional.ts ================================================ import { getDefault } from '../../methods/index.ts'; import type { BaseIssue, BaseSchema, Default, InferInput, InferIssue, SuccessDataset, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; import type { InferOptionalOutput } from './types.ts'; /** * Optional schema interface. */ export interface OptionalSchema< TWrapped extends BaseSchema>, TDefault extends Default, > extends BaseSchema< InferInput | undefined, InferOptionalOutput, InferIssue > { /** * The schema type. */ readonly type: 'optional'; /** * The schema reference. */ readonly reference: typeof optional; /** * The expected property. */ readonly expects: `(${TWrapped['expects']} | undefined)`; /** * The wrapped schema. */ readonly wrapped: TWrapped; /** * The default value. */ readonly default: TDefault; } /** * Creates an optional schema. * * @param wrapped The wrapped schema. * * @returns An optional schema. */ export function optional< const TWrapped extends BaseSchema>, >(wrapped: TWrapped): OptionalSchema; /** * Creates an optional schema. * * @param wrapped The wrapped schema. * @param default_ The default value. * * @returns An optional schema. */ export function optional< const TWrapped extends BaseSchema>, const TDefault extends Default, >(wrapped: TWrapped, default_: TDefault): OptionalSchema; // @__NO_SIDE_EFFECTS__ export function optional( wrapped: BaseSchema>, default_?: unknown ): OptionalSchema>, unknown> { return { kind: 'schema', type: 'optional', reference: optional, expects: `(${wrapped.expects} | undefined)`, async: false, wrapped, default: default_, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // If value is `undefined`, override it with default or return dataset if (dataset.value === undefined) { // If default is specified, override value of dataset if (this.default !== undefined) { dataset.value = getDefault(this, dataset, config); } // If value is still `undefined`, return dataset if (dataset.value === undefined) { // @ts-expect-error dataset.typed = true; // @ts-expect-error return dataset as SuccessDataset; } } // Otherwise, return dataset of wrapped schema return this.wrapped['~run'](dataset, config); }, }; } ================================================ FILE: library/src/schemas/optional/optionalAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { TransformActionAsync } from '../../actions/index.ts'; import type { SchemaWithPipeAsync } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { ArrayIssue, ArraySchema } from '../array/index.ts'; import type { ObjectIssue, ObjectSchema } from '../object/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { optionalAsync, type OptionalSchemaAsync } from './optionalAsync.ts'; describe('optionalAsync', () => { describe('should return schema object', () => { test('with undefined default', () => { type Schema = OptionalSchemaAsync, undefined>; expectTypeOf(optionalAsync(string())).toEqualTypeOf(); expectTypeOf(optionalAsync(string(), undefined)).toEqualTypeOf(); }); test('with undefined getter default', () => { expectTypeOf(optionalAsync(string(), () => undefined)).toEqualTypeOf< OptionalSchemaAsync, () => undefined> >(); }); test('with async undefined getter default', () => { expectTypeOf( optionalAsync(string(), async () => undefined) ).toEqualTypeOf< OptionalSchemaAsync, () => Promise> >(); }); test('with value default', () => { expectTypeOf(optionalAsync(string(), 'foo')).toEqualTypeOf< OptionalSchemaAsync, 'foo'> >(); }); test('with value getter default', () => { expectTypeOf(optionalAsync(string(), () => 'foo')).toEqualTypeOf< OptionalSchemaAsync, () => string> >(); }); test('with async value getter default', () => { expectTypeOf(optionalAsync(string(), async () => 'foo')).toEqualTypeOf< OptionalSchemaAsync, () => Promise> >(); }); }); describe('should infer correct types', () => { type Schema1 = OptionalSchemaAsync, undefined>; type Schema2 = OptionalSchemaAsync, 'foo'>; type Schema3 = OptionalSchemaAsync< StringSchema, () => undefined >; type Schema4 = OptionalSchemaAsync, () => 'foo'>; type Schema5 = OptionalSchemaAsync< StringSchema, () => Promise >; type Schema6 = OptionalSchemaAsync< StringSchema, () => Promise<'foo'> >; type Schema7 = OptionalSchemaAsync< SchemaWithPipeAsync< [StringSchema, TransformActionAsync] >, 'foo' >; type Schema8 = OptionalSchemaAsync< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, { foo: string[] } >; type Schema9 = OptionalSchemaAsync< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, () => { foo: string[] } >; type Schema10 = OptionalSchemaAsync< ObjectSchema< { foo: ArraySchema, undefined> }, undefined >, () => Promise<{ foo: string[] }> >; test('of input', () => { type Input = string | undefined; expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf< { foo: string[] } | undefined >(); expectTypeOf>().toEqualTypeOf< { foo: string[] } | undefined >(); expectTypeOf>().toEqualTypeOf< { foo: string[] } | undefined >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); expectTypeOf>().toEqualTypeOf<{ foo: string[] }>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); expectTypeOf>().toEqualTypeOf< ObjectIssue | ArrayIssue | StringIssue >(); }); }); }); ================================================ FILE: library/src/schemas/optional/optionalAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { optionalAsync, type OptionalSchemaAsync } from './optionalAsync.ts'; describe('optionalAsync', () => { describe('should return schema object', () => { const baseSchema: Omit< OptionalSchemaAsync, string>, 'default' > = { kind: 'schema', type: 'optional', reference: optionalAsync, expects: '(string | undefined)', wrapped: { ...string(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined default', () => { const expected: OptionalSchemaAsync< StringSchema, undefined > = { ...baseSchema, default: undefined, }; expect(optionalAsync(string())).toStrictEqual(expected); expect(optionalAsync(string(), undefined)).toStrictEqual(expected); }); test('with undefined getter default', () => { const getter = () => undefined; expect(optionalAsync(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies OptionalSchemaAsync, typeof getter>); }); test('with async undefined getter default', () => { const getter = async () => undefined; expect(optionalAsync(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies OptionalSchemaAsync, typeof getter>); }); test('with value default', () => { expect(optionalAsync(string(), 'foo')).toStrictEqual({ ...baseSchema, default: 'foo', } satisfies OptionalSchemaAsync, 'foo'>); }); test('with value getter default', () => { const getter = () => 'foo'; expect(optionalAsync(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies OptionalSchemaAsync, typeof getter>); }); test('with async value getter default', () => { const getter = async () => 'foo'; expect(optionalAsync(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies OptionalSchemaAsync, typeof getter>); }); }); describe('should return dataset without issues', () => { const schema = optionalAsync(string()); test('for wrapper type', async () => { await expectNoSchemaIssueAsync(schema, ['', 'foo', '#$%']); }); test('for undefined', async () => { await expectNoSchemaIssueAsync(schema, [undefined]); }); }); describe('should return dataset with issues', () => { const schema = optionalAsync(string('message')); const baseIssue: Omit = { kind: 'schema', type: 'string', expected: 'string', message: 'message', }; test('for invalid wrapper type', async () => { await expectSchemaIssueAsync(schema, baseIssue, [123, true, {}]); }); test('for null', async () => { await expectSchemaIssueAsync(schema, baseIssue, [null]); }); }); describe('should return dataset without default', () => { test('for undefined default', async () => { await expectNoSchemaIssueAsync(optionalAsync(string()), [ undefined, 'foo', ]); await expectNoSchemaIssueAsync(optionalAsync(string(), undefined), [ undefined, 'foo', ]); }); test('for wrapper type', async () => { await expectNoSchemaIssueAsync(optionalAsync(string(), 'foo'), [ '', 'bar', '#$%', ]); }); }); describe('should return dataset with default', () => { const schema1 = optionalAsync(string(), 'foo'); const schema2 = optionalAsync(string(), () => undefined); const schema3 = optionalAsync(string(), () => 'foo'); const schema4 = optionalAsync(string(), async () => undefined); const schema5 = optionalAsync(string(), async () => 'foo'); test('for undefined', async () => { expect(await schema1['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: 'foo', }); expect(await schema2['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: undefined, }); expect(await schema3['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: 'foo', }); expect(await schema4['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: undefined, }); expect(await schema5['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: 'foo', }); }); }); }); ================================================ FILE: library/src/schemas/optional/optionalAsync.ts ================================================ import { getDefault } from '../../methods/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, DefaultAsync, InferInput, InferIssue, SuccessDataset, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; import type { optional } from './optional.ts'; import type { InferOptionalOutput } from './types.ts'; /** * Optional schema async interface. */ export interface OptionalSchemaAsync< TWrapped extends | BaseSchema> | BaseSchemaAsync>, TDefault extends DefaultAsync, > extends BaseSchemaAsync< InferInput | undefined, InferOptionalOutput, InferIssue > { /** * The schema type. */ readonly type: 'optional'; /** * The schema reference. */ readonly reference: typeof optional | typeof optionalAsync; /** * The expected property. */ readonly expects: `(${TWrapped['expects']} | undefined)`; /** * The wrapped schema. */ readonly wrapped: TWrapped; /** * The default value. */ readonly default: TDefault; } /** * Creates an optional schema. * * @param wrapped The wrapped schema. * * @returns An optional schema. */ export function optionalAsync< const TWrapped extends | BaseSchema> | BaseSchemaAsync>, >(wrapped: TWrapped): OptionalSchemaAsync; /** * Creates an optional schema. * * @param wrapped The wrapped schema. * @param default_ The default value. * * @returns An optional schema. */ export function optionalAsync< const TWrapped extends | BaseSchema> | BaseSchemaAsync>, const TDefault extends DefaultAsync, >( wrapped: TWrapped, default_: TDefault ): OptionalSchemaAsync; // @__NO_SIDE_EFFECTS__ export function optionalAsync( wrapped: | BaseSchema> | BaseSchemaAsync>, default_?: unknown ): OptionalSchemaAsync< | BaseSchema> | BaseSchemaAsync>, unknown > { return { kind: 'schema', type: 'optional', reference: optionalAsync, expects: `(${wrapped.expects} | undefined)`, async: true, wrapped, default: default_, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // If value is `undefined`, override it with default or return dataset if (dataset.value === undefined) { // If default is specified, override value of dataset if (this.default !== undefined) { dataset.value = await getDefault(this, dataset, config); } // If value is still `undefined`, return dataset if (dataset.value === undefined) { // @ts-expect-error dataset.typed = true; // @ts-expect-error return dataset as SuccessDataset; } } // Otherwise, return dataset of wrapped schema return this.wrapped['~run'](dataset, config); }, }; } ================================================ FILE: library/src/schemas/optional/types.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, DefaultAsync, DefaultValue, InferOutput, } from '../../types/index.ts'; /** * Infer optional output type. */ export type InferOptionalOutput< TWrapped extends | BaseSchema> | BaseSchemaAsync>, TDefault extends DefaultAsync, > = undefined extends TDefault ? InferOutput | undefined : InferOutput | Extract, undefined>; ================================================ FILE: library/src/schemas/picklist/index.ts ================================================ export * from './picklist.ts'; ================================================ FILE: library/src/schemas/picklist/picklist.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { picklist, type PicklistIssue, type PicklistSchema, } from './picklist.ts'; describe('picklist', () => { const options = ['foo', 'bar', 'baz'] as const; type Options = typeof options; describe('should return schema object', () => { test('with undefined message', () => { type Schema = PicklistSchema; expectTypeOf(picklist(options)).toEqualTypeOf(); expectTypeOf(picklist(options, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(picklist(options, 'message')).toEqualTypeOf< PicklistSchema >(); }); test('with function message', () => { expectTypeOf(picklist(options, () => 'message')).toEqualTypeOf< PicklistSchema string> >(); }); }); describe('should infer correct types', () => { type Schema = PicklistSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf<'foo' | 'bar' | 'baz'>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< 'foo' | 'bar' | 'baz' >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/picklist/picklist.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { picklist, type PicklistIssue, type PicklistSchema, } from './picklist.ts'; describe('picklist', () => { const options = ['foo', 'bar', 'baz'] as const; type Options = typeof options; describe('should return schema object', () => { const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'picklist', reference: picklist, expects: '("foo" | "bar" | "baz")', options, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: PicklistSchema = { ...baseSchema, message: undefined, }; expect(picklist(options)).toStrictEqual(schema); expect(picklist(options, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(picklist(options, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies PicklistSchema); }); test('with function message', () => { const message = () => 'message'; expect(picklist(options, message)).toStrictEqual({ ...baseSchema, message, } satisfies PicklistSchema); }); }); describe('should return dataset without issues', () => { test('for valid options', () => { expectNoSchemaIssue(picklist(options), ['foo', 'bar', 'baz']); }); }); describe('should return dataset with issues', () => { const schema = picklist(options, 'message'); const baseIssue: Omit = { kind: 'schema', type: 'picklist', expected: '("foo" | "bar" | "baz")', message: 'message', }; // Special values test('for empty options', () => { expectSchemaIssue( picklist([], 'message'), { ...baseIssue, expected: 'never' }, ['foo', 'bar', 'baz'] ); }); test('for invalid options', () => { expectSchemaIssue(schema, baseIssue, ['fo', 'fooo', 'foobar']); }); // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'hello', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); }); ================================================ FILE: library/src/schemas/picklist/picklist.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, MaybeReadonly, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps, _joinExpects, _stringify, } from '../../utils/index.ts'; /** * Picklist options type. */ export type PicklistOptions = MaybeReadonly<(string | number | bigint)[]>; /** * Picklist issue interface. */ export interface PicklistIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'picklist'; /** * The expected property. */ readonly expected: string; } /** * Picklist schema interface. */ export interface PicklistSchema< TOptions extends PicklistOptions, TMessage extends ErrorMessage | undefined, > extends BaseSchema { /** * The schema type. */ readonly type: 'picklist'; /** * The schema reference. */ readonly reference: typeof picklist; /** * The picklist options. */ readonly options: TOptions; /** * The error message. */ readonly message: TMessage; } /** * Creates a picklist schema. * * @param options The picklist options. * * @returns A picklist schema. */ export function picklist( options: TOptions ): PicklistSchema; /** * Creates a picklist schema. * * @param options The picklist options. * @param message The error message. * * @returns A picklist schema. */ export function picklist< const TOptions extends PicklistOptions, const TMessage extends ErrorMessage | undefined, >(options: TOptions, message: TMessage): PicklistSchema; // @__NO_SIDE_EFFECTS__ export function picklist( options: PicklistOptions, message?: ErrorMessage ): PicklistSchema | undefined> { return { kind: 'schema', type: 'picklist', reference: picklist, expects: _joinExpects(options.map(_stringify), '|'), async: false, options, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // @ts-expect-error if (this.options.includes(dataset.value)) { // @ts-expect-error dataset.typed = true; } else { _addIssue(this, 'type', dataset, config); } // @ts-expect-error return dataset as OutputDataset; }, }; } ================================================ FILE: library/src/schemas/promise/index.ts ================================================ export * from './promise.ts'; ================================================ FILE: library/src/schemas/promise/promise.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { promise, type PromiseIssue, type PromiseSchema } from './promise.ts'; describe('promise', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = PromiseSchema; expectTypeOf(promise()).toEqualTypeOf(); expectTypeOf(promise(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(promise('message')).toEqualTypeOf< PromiseSchema<'message'> >(); }); test('with function message', () => { expectTypeOf(promise(() => 'message')).toEqualTypeOf< PromiseSchema<() => string> >(); }); }); describe('should infer correct types', () => { type Schema = PromiseSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/promise/promise.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { promise, type PromiseIssue, type PromiseSchema } from './promise.ts'; describe('promise', () => { describe('should return schema object', () => { const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'promise', reference: promise, expects: 'Promise', async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: PromiseSchema = { ...baseSchema, message: undefined, }; expect(promise()).toStrictEqual(schema); expect(promise(undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(promise('message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies PromiseSchema<'message'>); }); test('with function message', () => { const message = () => 'message'; expect(promise(message)).toStrictEqual({ ...baseSchema, message, } satisfies PromiseSchema); }); }); describe('should return dataset without issues', () => { const schema = promise(); test('for Promise objects', () => { expectNoSchemaIssue(schema, [ Promise.resolve(), Promise.resolve('foo'), Promise.all([]), ]); }); }); describe('should return dataset with issues', () => { const schema = promise('message'); const baseIssue: Omit = { kind: 'schema', type: 'promise', expected: 'Promise', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'foo', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); }); ================================================ FILE: library/src/schemas/promise/promise.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; /** * Promise issue interface. */ export interface PromiseIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'promise'; /** * The expected property. */ readonly expected: 'Promise'; } /** * Promise schema interface. */ export interface PromiseSchema< TMessage extends ErrorMessage | undefined, > extends BaseSchema, Promise, PromiseIssue> { /** * The schema type. */ readonly type: 'promise'; /** * The schema reference. */ readonly reference: typeof promise; /** * The expected property. */ readonly expects: 'Promise'; /** * The error message. */ readonly message: TMessage; } /** * Creates a promise schema. * * @returns A promise schema. */ export function promise(): PromiseSchema; /** * Creates a promise schema. * * @param message The error message. * * @returns A promise schema. */ export function promise< const TMessage extends ErrorMessage | undefined, >(message: TMessage): PromiseSchema; // @__NO_SIDE_EFFECTS__ export function promise( message?: ErrorMessage ): PromiseSchema | undefined> { return { kind: 'schema', type: 'promise', reference: promise, expects: 'Promise', async: false, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { if (dataset.value instanceof Promise) { // @ts-expect-error dataset.typed = true; } else { _addIssue(this, 'type', dataset, config); } // @ts-expect-error return dataset as OutputDataset, PromiseIssue>; }, }; } ================================================ FILE: library/src/schemas/record/index.ts ================================================ export * from './record.ts'; export * from './recordAsync.ts'; export type { RecordIssue } from './types.ts'; ================================================ FILE: library/src/schemas/record/record.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { ReadonlyAction } from '../../actions/index.ts'; import type { SchemaWithPipe } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { number, type NumberIssue, type NumberSchema, } from '../number/index.ts'; import type { OptionalSchema } from '../optional/index.ts'; import type { PicklistIssue, PicklistSchema } from '../picklist/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { record, type RecordSchema } from './record.ts'; import type { RecordIssue } from './types.ts'; describe('record', () => { describe('should return schema record', () => { const key = string(); type Key = typeof key; const value = number(); type Value = typeof value; test('with undefined message', () => { type Schema = RecordSchema; expectTypeOf(record(key, value)).toEqualTypeOf(); expectTypeOf(record(key, value, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(record(key, value, 'message')).toEqualTypeOf< RecordSchema >(); }); test('with function message', () => { expectTypeOf(record(key, value, () => 'message')).toEqualTypeOf< RecordSchema string> >(); }); }); describe('should infer correct types', () => { type Schema1 = RecordSchema< StringSchema, OptionalSchema, 123>, undefined >; type Schema2 = RecordSchema< PicklistSchema<['foo', 'bar'], undefined>, OptionalSchema, 'hello'>, undefined >; type Schema3 = RecordSchema< StringSchema, SchemaWithPipe<[StringSchema, ReadonlyAction]>, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf< Partial> >(); expectTypeOf>().toEqualTypeOf< Partial> >(); expectTypeOf>().toEqualTypeOf< Record >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< Record >(); expectTypeOf>().toEqualTypeOf< Partial> >(); expectTypeOf>().toEqualTypeOf< Readonly> >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< RecordIssue | StringIssue | NumberIssue >(); expectTypeOf>().toEqualTypeOf< RecordIssue | PicklistIssue | StringIssue >(); expectTypeOf>().toEqualTypeOf< RecordIssue | StringIssue >(); }); }); }); ================================================ FILE: library/src/schemas/record/record.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { number, type NumberIssue } from '../number/index.ts'; import { optional } from '../optional/index.ts'; import { picklist } from '../picklist/index.ts'; import { string } from '../string/index.ts'; import { record, type RecordSchema } from './record.ts'; import type { RecordIssue } from './types.ts'; describe('record', () => { describe('should return schema record', () => { const key = string(); type Key = typeof key; const value = number(); type Value = typeof value; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'record', reference: record, expects: 'Object', key, value, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: RecordSchema = { ...baseSchema, message: undefined, }; expect(record(key, value)).toStrictEqual(schema); expect(record(key, value, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(record(key, value, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies RecordSchema); }); test('with function message', () => { const message = () => 'message'; expect(record(key, value, message)).toStrictEqual({ ...baseSchema, message, } satisfies RecordSchema); }); }); describe('should return dataset without issues', () => { const schema = record(string(), number()); test('for empty record', () => { expectNoSchemaIssue(schema, [{}]); }); test('for simple record', () => { expectNoSchemaIssue(schema, [{ foo: 1, bar: 2, baz: 3 }]); }); test('for record with __proto__ key', () => { const input = JSON.parse('{"__proto__": 123, "foo": 456}'); expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: true, value: { foo: 456 }, }); }); }); describe('should return dataset with issues', () => { const schema = record(string(), number(), 'message'); const baseIssue: Omit = { kind: 'schema', type: 'record', expected: 'Object', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types // TODO: Enable this test again in case we find a reliable way to check for // plain objects // test('for arrays', () => { // expectSchemaIssue(schema, baseIssue, [[], ['value']]); // }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); }); describe('should return dataset without nested issues', () => { const schema = record(picklist(['foo', 'bar', 'baz']), optional(number())); test('for simple record', () => { expectNoSchemaIssue(schema, [{ foo: 1, bar: 2, baz: 3 }]); }); test('for nested record', () => { expectNoSchemaIssue(record(string(), schema), [ { foo: { foo: 1, bar: 2 }, bar: { baz: 3 } }, ]); }); }); describe('should return dataset with nested issues', () => { const schema = record(picklist(['foo', 'bar', 'baz']), optional(number())); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const input = { foo: 1, bar: '2', // Invalid value baz: undefined, // Invalid value other: 4, // Invalid key }; const numberIssue1: NumberIssue = { ...baseInfo, kind: 'schema', type: 'number', input: '2', expected: 'number', received: '"2"', path: [ { type: 'object', origin: 'value', input, key: 'bar', value: '2', }, ], }; test('for invalid values', () => { expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: { foo: input.foo, bar: input.bar, baz: input.baz, }, issues: [ numberIssue1, { ...baseInfo, kind: 'schema', type: 'picklist', input: 'other', expected: '("foo" | "bar" | "baz")', received: '"other"', path: [ { type: 'object', origin: 'key', input, key: 'other', value: 4, }, ], }, ], } satisfies FailureDataset>); }); test('for first key invalid only', () => { const keySchema = record(picklist(['foo', 'bar']), number()); const input = { invalid: 1 }; expect(keySchema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'picklist', input: 'invalid', expected: '("foo" | "bar")', received: '"invalid"', path: [ { type: 'object', origin: 'key', input, key: 'invalid', value: 1, }, ], }, ], }); }); test('with abort early for invalid key', () => { const input = { foo: 1, other: 2, // Invalid key bar: '3', // Invalid value baz: undefined, // Invalid value }; expect( schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: { foo: 1 }, issues: [ { ...baseInfo, kind: 'schema', type: 'picklist', input: 'other', expected: '("foo" | "bar" | "baz")', received: '"other"', path: [ { type: 'object', origin: 'key', input, key: 'other', value: 2, }, ], abortEarly: true, }, ], } satisfies FailureDataset>); }); test('with abort early for invalid value', () => { expect( schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: { foo: 1 }, issues: [{ ...numberIssue1, abortEarly: true }], } satisfies FailureDataset>); }); test('for invalid nested values', () => { const nestedSchema = record(string(), schema); const input = { key1: { foo: 1, bar: '2', baz: undefined, }, key2: 123, }; expect(nestedSchema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: input.key1.bar, expected: 'number', received: '"2"', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: input.key1, }, { type: 'object', origin: 'value', input: input.key1, key: 'bar', value: input.key1.bar, }, ], }, { ...baseInfo, kind: 'schema', type: 'record', input: input.key2, expected: 'Object', received: '123', path: [ { type: 'object', origin: 'value', input, key: 'key2', value: input.key2, }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/record/record.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, InferIssue, ObjectPathItem, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps, _isValidObjectKey, } from '../../utils/index.ts'; import type { InferRecordInput, InferRecordOutput, RecordIssue, } from './types.ts'; /** * Record schema interface. */ export interface RecordSchema< TKey extends BaseSchema>, TValue extends BaseSchema>, TMessage extends ErrorMessage | undefined, > extends BaseSchema< InferRecordInput, InferRecordOutput, RecordIssue | InferIssue | InferIssue > { /** * The schema type. */ readonly type: 'record'; /** * The schema reference. */ readonly reference: typeof record; /** * The expected property. */ readonly expects: 'Object'; /** * The record key schema. */ readonly key: TKey; /** * The record value schema. */ readonly value: TValue; /** * The error message. */ readonly message: TMessage; } /** * Creates a record schema. * * @param key The key schema. * @param value The value schema. * * @returns A record schema. */ export function record< const TKey extends BaseSchema< string, string | number | symbol, BaseIssue >, const TValue extends BaseSchema>, >(key: TKey, value: TValue): RecordSchema; /** * Creates a record schema. * * @param key The key schema. * @param value The value schema. * @param message The error message. * * @returns A record schema. */ export function record< const TKey extends BaseSchema< string, string | number | symbol, BaseIssue >, const TValue extends BaseSchema>, const TMessage extends ErrorMessage | undefined, >( key: TKey, value: TValue, message: TMessage ): RecordSchema; // @__NO_SIDE_EFFECTS__ export function record( key: BaseSchema>, value: BaseSchema>, message?: ErrorMessage ): RecordSchema< BaseSchema>, BaseSchema>, ErrorMessage | undefined > { return { kind: 'schema', type: 'record', reference: record, expects: 'Object', async: false, key, value, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (input && typeof input === 'object') { // Set typed to `true` and value to empty object // @ts-expect-error dataset.typed = true; dataset.value = {}; // Parse schema of each record entry // Hint: for...in loop always returns keys as strings // Hint: We exclude specific keys for security reasons for (const entryKey in input) { if (_isValidObjectKey(input, entryKey)) { // Get value of record entry const entryValue: unknown = input[entryKey as keyof typeof input]; // Get dataset of key schema const keyDataset = this.key['~run']({ value: entryKey }, config); // If there are issues, capture them if (keyDataset.issues) { // Create record path item const pathItem: ObjectPathItem = { type: 'object', origin: 'key', input: input as Record, key: entryKey, value: entryValue, }; // Add modified item dataset issues to issues for (const issue of keyDataset.issues) { // @ts-expect-error issue.path = [pathItem]; // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = keyDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // Get dataset of value schema const valueDataset = this.value['~run']( { value: entryValue }, config ); // If there are issues, capture them if (valueDataset.issues) { // Create record path item const pathItem: ObjectPathItem = { type: 'object', origin: 'value', input: input as Record, key: entryKey, value: entryValue, }; // Add modified item dataset issues to issues for (const issue of valueDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = valueDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!keyDataset.typed || !valueDataset.typed) { dataset.typed = false; } // If key is typed, add entry to dataset if (keyDataset.typed) { // @ts-expect-error dataset.value[keyDataset.value] = valueDataset.value; } } } // Otherwise, add record issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< Record, RecordIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/record/recordAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { ReadonlyAction } from '../../actions/index.ts'; import type { SchemaWithPipe } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { number, type NumberIssue, type NumberSchema, } from '../number/index.ts'; import type { OptionalSchema } from '../optional/index.ts'; import type { PicklistIssue, PicklistSchema } from '../picklist/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { recordAsync, type RecordSchemaAsync } from './recordAsync.ts'; import type { RecordIssue } from './types.ts'; describe('recordAsync', () => { describe('should return schema recordAsync', () => { const key = string(); type Key = typeof key; const value = number(); type Value = typeof value; test('with undefined message', () => { type Schema = RecordSchemaAsync; expectTypeOf(recordAsync(key, value)).toEqualTypeOf(); expectTypeOf(recordAsync(key, value, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(recordAsync(key, value, 'message')).toEqualTypeOf< RecordSchemaAsync >(); }); test('with function message', () => { expectTypeOf(recordAsync(key, value, () => 'message')).toEqualTypeOf< RecordSchemaAsync string> >(); }); }); describe('should infer correct types', () => { type Schema1 = RecordSchemaAsync< StringSchema, OptionalSchema, 123>, undefined >; type Schema2 = RecordSchemaAsync< PicklistSchema<['foo', 'bar'], undefined>, OptionalSchema, 'hello'>, undefined >; type Schema3 = RecordSchemaAsync< StringSchema, SchemaWithPipe<[StringSchema, ReadonlyAction]>, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf< Partial> >(); expectTypeOf>().toEqualTypeOf< Partial> >(); expectTypeOf>().toEqualTypeOf< Record >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< Record >(); expectTypeOf>().toEqualTypeOf< Partial> >(); expectTypeOf>().toEqualTypeOf< Readonly> >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< RecordIssue | StringIssue | NumberIssue >(); expectTypeOf>().toEqualTypeOf< RecordIssue | PicklistIssue | StringIssue >(); expectTypeOf>().toEqualTypeOf< RecordIssue | StringIssue >(); }); }); }); ================================================ FILE: library/src/schemas/record/recordAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { number, type NumberIssue } from '../number/index.ts'; import { optionalAsync } from '../optional/index.ts'; import { picklist } from '../picklist/index.ts'; import { string } from '../string/index.ts'; import { recordAsync, type RecordSchemaAsync } from './recordAsync.ts'; import type { RecordIssue } from './types.ts'; describe('recordAsync', () => { describe('should return schema record', () => { const key = string(); type Key = typeof key; const value = number(); type Value = typeof value; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'record', reference: recordAsync, expects: 'Object', key, value, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: RecordSchemaAsync = { ...baseSchema, message: undefined, }; expect(recordAsync(key, value)).toStrictEqual(schema); expect(recordAsync(key, value, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(recordAsync(key, value, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies RecordSchemaAsync); }); test('with function message', () => { const message = () => 'message'; expect(recordAsync(key, value, message)).toStrictEqual({ ...baseSchema, message, } satisfies RecordSchemaAsync); }); }); describe('should return dataset without issues', () => { const schema = recordAsync(string(), number()); test('for empty record', async () => { await expectNoSchemaIssueAsync(schema, [{}]); }); test('for simple record', async () => { await expectNoSchemaIssueAsync(schema, [{ foo: 1, bar: 2, baz: 3 }]); }); }); describe('should return dataset with issues', () => { const schema = recordAsync(string(), number(), 'message'); const baseIssue: Omit = { kind: 'schema', type: 'record', expected: 'Object', message: 'message', }; // Primitive types test('for bigints', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', async () => { await expectSchemaIssueAsync(schema, baseIssue, [true, false]); }); test('for null', async () => { await expectSchemaIssueAsync(schema, baseIssue, [null]); }); test('for numbers', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', async () => { await expectSchemaIssueAsync(schema, baseIssue, [undefined]); }); test('for strings', async () => { await expectSchemaIssueAsync(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ Symbol(), Symbol('foo'), ]); }); // Complex types // TODO: Enable this test again in case we find a reliable way to check for // plain objects // test('for arrays', async () => { // await expectSchemaIssueAsync(schema, baseIssue, [[], ['value']]); // }); test('for functions', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ // eslint-disable-next-line @typescript-eslint/no-empty-function () => {}, // eslint-disable-next-line @typescript-eslint/no-empty-function function () {}, ]); }); }); describe('should return dataset without nested issues', () => { const schema = recordAsync( picklist(['foo', 'bar', 'baz']), optionalAsync(number()) ); test('for simple record', async () => { await expectNoSchemaIssueAsync(schema, [{ foo: 1, bar: 2, baz: 3 }]); }); test('for nested record', async () => { await expectNoSchemaIssueAsync(recordAsync(string(), schema), [ { foo: { foo: 1, bar: 2 }, bar: { baz: 3 } }, ]); }); }); describe('should return dataset with nested issues', () => { const schema = recordAsync( picklist(['foo', 'bar', 'baz']), optionalAsync(number()) ); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const input = { foo: 1, bar: '2', baz: undefined, other: 4, }; const numberIssue1: NumberIssue = { ...baseInfo, kind: 'schema', type: 'number', input: '2', expected: 'number', received: '"2"', path: [ { type: 'object', origin: 'value', input, key: 'bar', value: '2', }, ], }; test('for invalid values', async () => { expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: { foo: input.foo, bar: input.bar, baz: input.baz, }, issues: [ numberIssue1, { ...baseInfo, kind: 'schema', type: 'picklist', input: 'other', expected: '("foo" | "bar" | "baz")', received: '"other"', path: [ { type: 'object', origin: 'key', input, key: 'other', value: 4, }, ], }, ], } satisfies FailureDataset>); }); test('with abort early for invalid key', async () => { const input = { foo: 1, other: 2, // Invalid key bar: '3', // Invalid value baz: undefined, // Invalid value }; expect( await schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: { foo: 1 }, issues: [ { ...baseInfo, kind: 'schema', type: 'picklist', input: 'other', expected: '("foo" | "bar" | "baz")', received: '"other"', path: [ { type: 'object', origin: 'key', input, key: 'other', value: 2, }, ], abortEarly: true, }, ], } satisfies FailureDataset>); }); test('with abort early for invalid value', async () => { expect( await schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: { foo: 1 }, issues: [{ ...numberIssue1, abortEarly: true }], } satisfies FailureDataset>); }); test('for invalid nested values', async () => { const nestedSchema = recordAsync(string(), schema); const input = { key1: { foo: 1, bar: '2', baz: undefined, }, key2: 123, }; expect(await nestedSchema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: input.key1.bar, expected: 'number', received: '"2"', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: input.key1, }, { type: 'object', origin: 'value', input: input.key1, key: 'bar', value: input.key1.bar, }, ], }, { ...baseInfo, kind: 'schema', type: 'record', input: input.key2, expected: 'Object', received: '123', path: [ { type: 'object', origin: 'value', input, key: 'key2', value: input.key2, }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/record/recordAsync.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, ErrorMessage, InferIssue, ObjectPathItem, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps, _isValidObjectKey, } from '../../utils/index.ts'; import type { record } from './record.ts'; import type { InferRecordInput, InferRecordOutput, RecordIssue, } from './types.ts'; /** * Record schema async interface. */ export interface RecordSchemaAsync< TKey extends | BaseSchema> | BaseSchemaAsync>, TValue extends | BaseSchema> | BaseSchemaAsync>, TMessage extends ErrorMessage | undefined, > extends BaseSchemaAsync< InferRecordInput, InferRecordOutput, RecordIssue | InferIssue | InferIssue > { /** * The schema type. */ readonly type: 'record'; /** * The schema reference. */ readonly reference: typeof record | typeof recordAsync; /** * The expected property. */ readonly expects: 'Object'; /** * The record key schema. */ readonly key: TKey; /** * The record value schema. */ readonly value: TValue; /** * The error message. */ readonly message: TMessage; } /** * Creates a record schema. * * @param key The key schema. * @param value The value schema. * * @returns A record schema. */ export function recordAsync< const TKey extends | BaseSchema> | BaseSchemaAsync>, const TValue extends | BaseSchema> | BaseSchemaAsync>, >(key: TKey, value: TValue): RecordSchemaAsync; /** * Creates a record schema. * * @param key The key schema. * @param value The value schema. * @param message The error message. * * @returns A record schema. */ export function recordAsync< const TKey extends | BaseSchema> | BaseSchemaAsync>, const TValue extends | BaseSchema> | BaseSchemaAsync>, const TMessage extends ErrorMessage | undefined, >( key: TKey, value: TValue, message: TMessage ): RecordSchemaAsync; // @__NO_SIDE_EFFECTS__ export function recordAsync( key: | BaseSchema> | BaseSchemaAsync>, value: | BaseSchema> | BaseSchemaAsync>, message?: ErrorMessage ): RecordSchemaAsync< | BaseSchema> | BaseSchemaAsync>, | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined > { return { kind: 'schema', type: 'record', reference: recordAsync, expects: 'Object', async: true, key, value, message, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (input && typeof input === 'object') { // Set typed to `true` and value to empty object // @ts-expect-error dataset.typed = true; dataset.value = {}; // Parse schema of each record entry // Hint: `Object.entries(…)` always returns keys as strings // Hint: We exclude specific keys for security reasons const datasets = await Promise.all( Object.entries(input) .filter(([key]) => _isValidObjectKey(input, key)) .map(([entryKey, entryValue]) => Promise.all([ entryKey, entryValue, this.key['~run']({ value: entryKey }, config), this.value['~run']({ value: entryValue }, config), ]) ) ); // Process datasets of each record entry for (const [ entryKey, entryValue, keyDataset, valueDataset, ] of datasets) { // If there are issues, capture them if (keyDataset.issues) { // Create record path item const pathItem: ObjectPathItem = { type: 'object', origin: 'key', input: input as Record, key: entryKey, value: entryValue, }; // Add modified item dataset issues to issues for (const issue of keyDataset.issues) { // @ts-expect-error issue.path = [pathItem]; // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = keyDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If there are issues, capture them if (valueDataset.issues) { // Create record path item const pathItem: ObjectPathItem = { type: 'object', origin: 'value', input: input as Record, key: entryKey, value: entryValue, }; // Add modified item dataset issues to issues for (const issue of valueDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = valueDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!keyDataset.typed || !valueDataset.typed) { dataset.typed = false; } // If key is typed, add entry to dataset if (keyDataset.typed) { // @ts-expect-error dataset.value[keyDataset.value] = valueDataset.value; } } // Otherwise, add record issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< Record, RecordIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/record/types.ts ================================================ import type { Brand, ReadonlyAction } from '../../actions/index.ts'; import type { SchemaWithPipe, SchemaWithPipeAsync, } from '../../methods/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, InferInput, InferOutput, MarkOptional, Prettify, } from '../../types/index.ts'; /** * Record issue interface. */ export interface RecordIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'record'; /** * The expected property. */ readonly expected: 'Object'; } /** * Is literal type. */ type IsLiteral = string extends TKey ? false : number extends TKey ? false : symbol extends TKey ? false : TKey extends Brand ? false : true; /** * Optional keys type. */ type OptionalKeys> = { [TKey in keyof TObject]: IsLiteral extends true ? TKey : never; }[keyof TObject]; /** * With question marks type. * * Hint: We mark an entry as optional if we detect that its key is a literal * type. The reason for this is that it is not technically possible to detect * missing literal keys without restricting the key schema to `string`, `enum` * and `picklist`. However, if `enum` and `picklist` are used, it is better to * use `object` with `entriesFromList` because it already covers the needed * functionality. This decision also reduces the bundle size of `record`, * because it only needs to check the entries of the input and not any missing * keys. */ type WithQuestionMarks< TObject extends Record, > = MarkOptional>; /** * With readonly type. */ type WithReadonly< TValue extends | BaseSchema> | BaseSchemaAsync>, TObject extends WithQuestionMarks>, > = TValue extends | SchemaWithPipe | SchemaWithPipeAsync ? // eslint-disable-next-line @typescript-eslint/no-explicit-any ReadonlyAction extends TPipe[number] ? Readonly : TObject : TObject; /** * Infer record input type. */ export type InferRecordInput< TKey extends | BaseSchema> | BaseSchemaAsync>, TValue extends | BaseSchema> | BaseSchemaAsync>, > = Prettify, InferInput>>>; /** * Infer record output type. */ export type InferRecordOutput< TKey extends | BaseSchema> | BaseSchemaAsync>, TValue extends | BaseSchema> | BaseSchemaAsync>, > = Prettify< WithReadonly< TValue, WithQuestionMarks, InferOutput>> > >; ================================================ FILE: library/src/schemas/set/index.ts ================================================ export * from './set.ts'; export * from './setAsync.ts'; export type { SetIssue } from './types.ts'; ================================================ FILE: library/src/schemas/set/set.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { OptionalSchema } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { set, type SetSchema } from './set.ts'; import type { SetIssue } from './types.ts'; describe('set', () => { describe('should return schema object', () => { const value = string(); type Value = typeof value; test('with undefined message', () => { type Schema = SetSchema; expectTypeOf(set(value)).toEqualTypeOf(); expectTypeOf(set(value, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(set(value, 'message')).toEqualTypeOf< SetSchema >(); }); test('with function message', () => { expectTypeOf(set(value, () => 'message')).toEqualTypeOf< SetSchema string> >(); }); }); describe('should infer correct types', () => { type Schema = SetSchema< OptionalSchema, 'foo'>, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf< Set >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< SetIssue | StringIssue >(); }); }); }); ================================================ FILE: library/src/schemas/set/set.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { string, type StringIssue } from '../string/index.ts'; import { set, type SetSchema } from './set.ts'; import type { SetIssue } from './types.ts'; describe('set', () => { describe('should return schema object', () => { const value = string(); type Value = typeof value; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'set', reference: set, expects: 'Set', value, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: SetSchema = { ...baseSchema, message: undefined, }; expect(set(value)).toStrictEqual(schema); expect(set(value, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(set(value, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies SetSchema); }); test('with function message', () => { const message = () => 'message'; expect(set(value, message)).toStrictEqual({ ...baseSchema, message, } satisfies SetSchema); }); }); describe('should return dataset without issues', () => { const schema = set(string()); test('for empty set', () => { expectNoSchemaIssue(schema, [new Set()]); }); test('for simple set', () => { expectNoSchemaIssue(schema, [new Set(['foo', 'bar', 'baz'])]); }); }); describe('should return dataset with issues', () => { const schema = set(string(), 'message'); const baseIssue: Omit = { kind: 'schema', type: 'set', expected: 'Set', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); describe('should return dataset without nested issues', () => { const schema = set(string()); test('for simple set', () => { expectNoSchemaIssue(schema, [new Set(['foo', 'bar', 'baz'])]); }); test('for nested set', () => { expectNoSchemaIssue(set(schema), [ new Set([new Set(['foo', 'bar']), new Set(['baz'])]), ]); }); }); describe('should return dataset with nested issues', () => { const schema = set(string()); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const stringIssue: StringIssue = { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'set', origin: 'value', input: new Set(['foo', 123, 'baz', null]), key: null, value: 123, }, ], }; test('for wrong values', () => { expect( schema['~run']({ value: new Set(['foo', 123, 'baz', null]) }, {}) ).toStrictEqual({ typed: false, value: new Set(['foo', 123, 'baz', null]), issues: [ stringIssue, { ...baseInfo, kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', path: [ { type: 'set', origin: 'value', input: new Set(['foo', 123, 'baz', null]), key: null, value: null, }, ], }, ], } satisfies FailureDataset>); }); test('with abort early', () => { expect( schema['~run']( { value: new Set(['foo', 123, 'baz', null]) }, { abortEarly: true } ) ).toStrictEqual({ typed: false, value: new Set(['foo']), issues: [{ ...stringIssue, abortEarly: true }], } satisfies FailureDataset>); }); test('for wrong nested values', () => { const nestedSchema = set(schema); const input = new Set([new Set([123, 'foo']), 'bar', new Set()]); expect(nestedSchema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'set', origin: 'value', input, key: null, value: new Set([123, 'foo']), }, { type: 'set', origin: 'value', input: new Set([123, 'foo']), key: null, value: 123, }, ], }, { ...baseInfo, kind: 'schema', type: 'set', input: 'bar', expected: 'Set', received: '"bar"', path: [ { type: 'set', origin: 'value', input, key: null, value: 'bar', }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/set/set.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, InferIssue, OutputDataset, SetPathItem, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { InferSetInput, InferSetOutput, SetIssue } from './types.ts'; /** * Set schema interface. */ export interface SetSchema< TValue extends BaseSchema>, TMessage extends ErrorMessage | undefined, > extends BaseSchema< InferSetInput, InferSetOutput, SetIssue | InferIssue > { /** * The schema type. */ readonly type: 'set'; /** * The schema reference. */ readonly reference: typeof set; /** * The expected property. */ readonly expects: 'Set'; /** * The set value schema. */ readonly value: TValue; /** * The error message. */ readonly message: TMessage; } /** * Creates a set schema. * * @param value The value schema. * * @returns A set schema. */ export function set< const TValue extends BaseSchema>, >(value: TValue): SetSchema; /** * Creates a set schema. * * @param value The value schema. * @param message The error message. * * @returns A set schema. */ export function set< const TValue extends BaseSchema>, const TMessage extends ErrorMessage | undefined, >(value: TValue, message: TMessage): SetSchema; // @__NO_SIDE_EFFECTS__ export function set( value: BaseSchema>, message?: ErrorMessage ): SetSchema< BaseSchema>, ErrorMessage | undefined > { return { kind: 'schema', type: 'set', reference: set, expects: 'Set', async: false, value, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (input instanceof Set) { // Set typed to `true` and value to empty set // @ts-expect-error dataset.typed = true; dataset.value = new Set(); // Parse schema of each set value for (const inputValue of input) { const valueDataset = this.value['~run']( { value: inputValue }, config ); // If there are issues, capture them if (valueDataset.issues) { // Create set path item const pathItem: SetPathItem = { type: 'set', origin: 'value', input, key: null, value: inputValue, }; // Add modified item dataset issues to issues for (const issue of valueDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = valueDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!valueDataset.typed) { dataset.typed = false; } // Add value to dataset // @ts-expect-error dataset.value.add(valueDataset.value); } // Otherwise, add set issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< Set, SetIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/set/setAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { OptionalSchema } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { setAsync, type SetSchemaAsync } from './setAsync.ts'; import type { SetIssue } from './types.ts'; describe('setAsync', () => { describe('should return schema object', () => { const value = string(); type Value = typeof value; test('with undefined message', () => { type Schema = SetSchemaAsync; expectTypeOf(setAsync(value)).toEqualTypeOf(); expectTypeOf(setAsync(value, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(setAsync(value, 'message')).toEqualTypeOf< SetSchemaAsync >(); }); test('with function message', () => { expectTypeOf(setAsync(value, () => 'message')).toEqualTypeOf< SetSchemaAsync string> >(); }); }); describe('should infer correct types', () => { type Schema = SetSchemaAsync< OptionalSchema, 'foo'>, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf< Set >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< SetIssue | StringIssue >(); }); }); }); ================================================ FILE: library/src/schemas/set/setAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { string, type StringIssue } from '../string/index.ts'; import { setAsync, type SetSchemaAsync } from './setAsync.ts'; import type { SetIssue } from './types.ts'; describe('setAsync', () => { describe('should return schema object', () => { const value = string(); type Value = typeof value; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'set', reference: setAsync, expects: 'Set', value, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: SetSchemaAsync = { ...baseSchema, message: undefined, }; expect(setAsync(value)).toStrictEqual(schema); expect(setAsync(value, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(setAsync(value, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies SetSchemaAsync); }); test('with function message', () => { const message = () => 'message'; expect(setAsync(value, message)).toStrictEqual({ ...baseSchema, message, } satisfies SetSchemaAsync); }); }); describe('should return dataset without issues', () => { const schema = setAsync(string()); test('for empty setAsync', async () => { await expectNoSchemaIssueAsync(schema, [new Set()]); }); test('for simple setAsync', async () => { await expectNoSchemaIssueAsync(schema, [new Set(['foo', 'bar', 'baz'])]); }); }); describe('should return dataset with issues', () => { const schema = setAsync(string(), 'message'); const baseIssue: Omit = { kind: 'schema', type: 'set', expected: 'Set', message: 'message', }; // Primitive types test('for bigints', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', async () => { await expectSchemaIssueAsync(schema, baseIssue, [true, false]); }); test('for null', async () => { await expectSchemaIssueAsync(schema, baseIssue, [null]); }); test('for numbers', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', async () => { await expectSchemaIssueAsync(schema, baseIssue, [undefined]); }); test('for strings', async () => { await expectSchemaIssueAsync(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ Symbol(), Symbol('foo'), ]); }); // Complex types test('for arrays', async () => { await expectSchemaIssueAsync(schema, baseIssue, [[], ['value']]); }); test('for functions', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ // eslint-disable-next-line @typescript-eslint/no-empty-function () => {}, // eslint-disable-next-line @typescript-eslint/no-empty-function function () {}, ]); }); test('for objects', async () => { await expectSchemaIssueAsync(schema, baseIssue, [{}, { key: 'value' }]); }); }); describe('should return dataset without nested issues', () => { const schema = setAsync(string()); test('for simple setAsync', async () => { await expectNoSchemaIssueAsync(schema, [new Set(['foo', 'bar', 'baz'])]); }); test('for nested setAsync', async () => { await expectNoSchemaIssueAsync(setAsync(schema), [ new Set([new Set(['foo', 'bar']), new Set(['baz'])]), ]); }); }); describe('should return dataset with nested issues', () => { const schema = setAsync(string()); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const stringIssue: StringIssue = { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'set', origin: 'value', input: new Set(['foo', 123, 'baz', null]), key: null, value: 123, }, ], }; test('for wrong values', async () => { expect( await schema['~run']({ value: new Set(['foo', 123, 'baz', null]) }, {}) ).toStrictEqual({ typed: false, value: new Set(['foo', 123, 'baz', null]), issues: [ stringIssue, { ...baseInfo, kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', path: [ { type: 'set', origin: 'value', input: new Set(['foo', 123, 'baz', null]), key: null, value: null, }, ], }, ], } satisfies FailureDataset>); }); test('with abort early', async () => { expect( await schema['~run']( { value: new Set(['foo', 123, 'baz', null]) }, { abortEarly: true } ) ).toStrictEqual({ typed: false, value: new Set(['foo']), issues: [{ ...stringIssue, abortEarly: true }], } satisfies FailureDataset>); }); test('for wrong nested values', async () => { const nestedSchema = setAsync(schema); const input = new Set([new Set([123, 'foo']), 'bar', new Set()]); expect(await nestedSchema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'set', origin: 'value', input, key: null, value: new Set([123, 'foo']), }, { type: 'set', origin: 'value', input: new Set([123, 'foo']), key: null, value: 123, }, ], }, { ...baseInfo, kind: 'schema', type: 'set', input: 'bar', expected: 'Set', received: '"bar"', path: [ { type: 'set', origin: 'value', input, key: null, value: 'bar', }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/set/setAsync.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, ErrorMessage, InferIssue, OutputDataset, SetPathItem, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { set } from './set.ts'; import type { InferSetInput, InferSetOutput, SetIssue } from './types.ts'; /** * Set schema async interface. */ export interface SetSchemaAsync< TValue extends | BaseSchema> | BaseSchemaAsync>, TMessage extends ErrorMessage | undefined, > extends BaseSchemaAsync< InferSetInput, InferSetOutput, SetIssue | InferIssue > { /** * The schema type. */ readonly type: 'set'; /** * The schema reference. */ readonly reference: typeof set | typeof setAsync; /** * The expected property. */ readonly expects: 'Set'; /** * The set value schema. */ readonly value: TValue; /** * The error message. */ readonly message: TMessage; } /** * Creates a set schema. * * @param value The value schema. * * @returns A set schema. */ export function setAsync< const TValue extends | BaseSchema> | BaseSchemaAsync>, >(value: TValue): SetSchemaAsync; /** * Creates a set schema. * * @param value The value schema. * @param message The error message. * * @returns A set schema. */ export function setAsync< const TValue extends | BaseSchema> | BaseSchemaAsync>, const TMessage extends ErrorMessage | undefined, >(value: TValue, message: TMessage): SetSchemaAsync; // @__NO_SIDE_EFFECTS__ export function setAsync( value: | BaseSchema> | BaseSchemaAsync>, message?: ErrorMessage ): SetSchemaAsync< | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined > { return { kind: 'schema', type: 'set', reference: setAsync, expects: 'Set', async: true, value, message, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (input instanceof Set) { // Set typed to `true` and value to empty set // @ts-expect-error dataset.typed = true; dataset.value = new Set(); // Parse schema of each set value const valueDatasets = await Promise.all( [...input].map( async (inputValue) => [ inputValue, await this.value['~run']({ value: inputValue }, config), ] as const ) ); // Process dataset of each set value for (const [inputValue, valueDataset] of valueDatasets) { // If there are issues, capture them if (valueDataset.issues) { // Create set path item const pathItem: SetPathItem = { type: 'set', origin: 'value', input, key: null, value: inputValue, }; // Add modified item dataset issues to issues for (const issue of valueDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = valueDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!valueDataset.typed) { dataset.typed = false; } // Add value to dataset // @ts-expect-error dataset.value.add(valueDataset.value); } // Otherwise, add set issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< Set, SetIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/set/types.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, InferInput, InferOutput, } from '../../types/index.ts'; /** * Set issue interface. */ export interface SetIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'set'; /** * The expected property. */ readonly expected: 'Set'; } /** * Infer set input type. */ export type InferSetInput< TValue extends | BaseSchema> | BaseSchemaAsync>, > = Set>; /** * Infer set output type. */ export type InferSetOutput< TValue extends | BaseSchema> | BaseSchemaAsync>, > = Set>; ================================================ FILE: library/src/schemas/strictObject/index.ts ================================================ export * from './strictObject.ts'; export * from './strictObjectAsync.ts'; export * from './types.ts'; ================================================ FILE: library/src/schemas/strictObject/strictObject.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { Brand, BrandAction, DescriptionAction, ReadonlyAction, TransformAction, } from '../../actions/index.ts'; import type { SchemaWithPipe } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { AnySchema } from '../any/index.ts'; import type { CustomIssue, CustomSchema } from '../custom/index.ts'; import type { ExactOptionalSchema } from '../exactOptional/index.ts'; import type { NullishSchema } from '../nullish/index.ts'; import type { NumberIssue, NumberSchema } from '../number/index.ts'; import type { ObjectIssue, ObjectSchema } from '../object/index.ts'; import type { OptionalSchema } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import type { UndefinedableSchema } from '../undefinedable/index.ts'; import type { UnknownSchema } from '../unknown/index.ts'; import { strictObject, type StrictObjectSchema } from './strictObject.ts'; import type { StrictObjectIssue } from './types.ts'; describe('strictObject', () => { describe('should return schema object', () => { const entries = { key: string() }; type Entries = typeof entries; test('with undefined message', () => { type Schema = StrictObjectSchema; expectTypeOf(strictObject(entries)).toEqualTypeOf(); expectTypeOf(strictObject(entries, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(strictObject(entries, 'message')).toEqualTypeOf< StrictObjectSchema >(); }); test('with function message', () => { expectTypeOf(strictObject(entries, () => 'message')).toEqualTypeOf< StrictObjectSchema string> >(); }); }); describe('should infer correct types', () => { type Schema = StrictObjectSchema< { key00: StringSchema; key01: AnySchema; key02: UnknownSchema; key03: ObjectSchema<{ key: NumberSchema }, undefined>; key04: SchemaWithPipe< [StringSchema, ReadonlyAction] >; key05: UndefinedableSchema, 'bar'>; key06: SchemaWithPipe< [ OptionalSchema, undefined>, TransformAction, ] >; key07: CustomSchema<`a${string}` | `b${string}`, undefined>; key08: SchemaWithPipe< [StringSchema, BrandAction] >; // ExactOptionalSchema key10: ExactOptionalSchema, undefined>; key11: ExactOptionalSchema, 'foo'>; key12: ExactOptionalSchema, () => 'foo'>; // OptionalSchema key20: OptionalSchema, undefined>; key21: OptionalSchema, 'foo'>; key22: OptionalSchema, () => undefined>; key23: OptionalSchema, () => 'foo'>; // NullishSchema key30: NullishSchema, undefined>; key31: NullishSchema, null>; key32: NullishSchema, 'foo'>; key33: NullishSchema, () => undefined>; key34: NullishSchema, () => null>; key35: NullishSchema, () => 'foo'>; // SchemaWithPipe key40: SchemaWithPipe< [ExactOptionalSchema, undefined>] >; key41: SchemaWithPipe< [ ExactOptionalSchema, undefined>, DescriptionAction, ] >; key42: SchemaWithPipe< [OptionalSchema, undefined>] >; key43: SchemaWithPipe< [ OptionalSchema, undefined>, DescriptionAction, ] >; key44: SchemaWithPipe< [NullishSchema, undefined>] >; key45: SchemaWithPipe< [ NullishSchema, undefined>, DescriptionAction, ] >; key46: SchemaWithPipe< [ NullishSchema, undefined>, TransformAction, ] >; }, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf<{ key00: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any key01: any; key02: unknown; key03: { key: number }; key04: string; key05: string | undefined; key06?: string | undefined; key07: `a${string}` | `b${string}`; key08: string; // ExactOptionalSchema key10?: string; key11?: string; key12?: string; // OptionalSchema key20?: string | undefined; key21?: string | undefined; key22?: string | undefined; key23?: string | undefined; // NullishSchema key30?: string | null | undefined; key31?: string | null | undefined; key32?: string | null | undefined; key33?: string | null | undefined; key34?: string | null | undefined; key35?: string | null | undefined; // SchemaWithPipe key40?: string; key41?: string; key42?: string | undefined; key43?: string | undefined; key44?: string | null | undefined; key45?: string | null | undefined; key46?: string | null | undefined; }>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf<{ key00: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any key01: any; key02: unknown; key03: { key: number }; readonly key04: string; key05: string; key06?: number; key07: `a${string}` | `b${string}`; key08: string & Brand<'foo'>; // ExactOptionalSchema key10?: string; key11: string; key12: string; // OptionalSchema key20?: string | undefined; key21: string; key22: string | undefined; key23: string; // NullishSchema key30?: string | null | undefined; key31: string | null; key32: string; key33: string | undefined; key34: string | null; key35: string; // SchemaWithPipe key40?: string; key41?: string; key42?: string | undefined; key43?: string | undefined; key44?: string | null | undefined; key45?: string | null | undefined; key46?: string[]; }>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< | StrictObjectIssue | ObjectIssue | StringIssue | NumberIssue | CustomIssue >(); }); }); }); ================================================ FILE: library/src/schemas/strictObject/strictObject.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { fallback } from '../../methods/index.ts'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { any } from '../any/index.ts'; import { exactOptional } from '../exactOptional/index.ts'; import { nullish } from '../nullish/index.ts'; import { number } from '../number/index.ts'; import { object } from '../object/index.ts'; import { optional } from '../optional/index.ts'; import { string } from '../string/index.ts'; import { unknown } from '../unknown/index.ts'; import { strictObject, type StrictObjectSchema } from './strictObject.ts'; import type { StrictObjectIssue } from './types.ts'; describe('strictObject', () => { describe('should return schema object', () => { const entries = { key: string() }; type Entries = typeof entries; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'strict_object', reference: strictObject, expects: 'Object', entries, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: StrictObjectSchema = { ...baseSchema, message: undefined, }; expect(strictObject(entries)).toStrictEqual(schema); expect(strictObject(entries, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(strictObject(entries, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies StrictObjectSchema); }); test('with function message', () => { const message = () => 'message'; expect(strictObject(entries, message)).toStrictEqual({ ...baseSchema, message, } satisfies StrictObjectSchema); }); }); describe('should return dataset without issues', () => { test('for empty object', () => { expectNoSchemaIssue(strictObject({}), [{}]); }); test('for simple object', () => { expectNoSchemaIssue(strictObject({ key1: string(), key2: number() }), [ { key1: 'foo', key2: 123 }, ]); }); }); describe('should return dataset with issues', () => { const schema = strictObject({}, 'message'); const baseIssue: Omit = { kind: 'schema', type: 'strict_object', expected: 'Object', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types // TODO: Enable this test again in case we find a reliable way to check for // plain objects // test('for arrays', () => { // expectSchemaIssue(schema, baseIssue, [[], ['value']]); // }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); }); describe('should return dataset without nested issues', () => { test('for simple object', () => { expectNoSchemaIssue(strictObject({ key1: string(), key2: number() }), [ { key1: 'foo', key2: 123 }, ]); }); test('for nested object', () => { expectNoSchemaIssue(strictObject({ nested: object({ key: string() }) }), [ { nested: { key: 'foo' } }, ]); }); test('for missing entries with fallback', () => { expect( strictObject({ key1: fallback(string(), 'foo'), key2: fallback(number(), () => 123), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key1: 'foo', key2: 123 }, }); }); test('for exact optional entry', () => { expectNoSchemaIssue(strictObject({ key: exactOptional(string()) }), [ {}, { key: 'foo' }, ]); }); test('for exact optional entry with default', () => { expect( strictObject({ key: exactOptional(string(), 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( strictObject({ key: exactOptional(string(), () => 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); }); test('for optional entry', () => { expectNoSchemaIssue(strictObject({ key: optional(string()) }), [ {}, { key: undefined }, { key: 'foo' }, ]); }); test('for optional entry with default', () => { expect( strictObject({ key: optional(string(), 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( strictObject({ key: optional(string(), () => 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( strictObject({ key: optional(string(), () => undefined), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); }); test('for nullish entry', () => { expectNoSchemaIssue(strictObject({ key: nullish(number()) }), [ {}, { key: undefined }, { key: null }, { key: 123 }, ]); }); test('for nullish entry with default', () => { expect( strictObject({ key: nullish(string(), 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( strictObject({ key: nullish(string(), null) })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( strictObject({ key: nullish(string(), () => 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( strictObject({ key: nullish(string(), () => null) })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( strictObject({ key: nullish(string(), () => undefined) })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: undefined }, }); }); }); describe('should return dataset with nested issues', () => { const schema = strictObject({ key1: string(), key2: number(), nested: strictObject({ key1: string(), key2: number() }), }); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for missing entries', () => { const input = { key2: 123 }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'strict_object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'strict_object', input: undefined, expected: '"nested"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'nested', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for missing nested entries', () => { const input = { key1: 'value', nested: {} }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'strict_object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key2', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'strict_object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: {}, }, { type: 'object', origin: 'key', input: input.nested, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'strict_object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: {}, }, { type: 'object', origin: 'key', input: input.nested, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for missing entries with abort early', () => { const input = { key2: 123 }; expect( schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'strict_object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key1', value: undefined, }, ], abortEarly: true, }, ], } satisfies FailureDataset>); }); test('for missing any and unknown entry', () => { const schema = strictObject({ key1: any(), key2: unknown() }); expect(schema['~run']({ value: {} }, {})).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'strict_object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'strict_object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid entries', () => { const input = { key1: false, key2: 123, nested: null }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: false, expected: 'string', received: 'false', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: false, }, ], }, { ...baseInfo, kind: 'schema', type: 'strict_object', input: null, expected: 'Object', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: null, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid nested entries', () => { const input = { key1: 'value', key2: 'value', nested: { key1: 123, key2: null, }, }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: 'value', expected: 'number', received: '"value"', path: [ { type: 'object', origin: 'value', input, key: 'key2', value: input.key2, }, ], }, { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'value', input: input.nested, key: 'key1', value: input.nested.key1, }, ], }, { ...baseInfo, kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'value', input: input.nested, key: 'key2', value: input.nested.key2, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid entries with abort early', () => { const input = { key1: false, key2: 123, nested: null }; expect( schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: false, expected: 'string', received: 'false', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: false, }, ], abortEarly: true, }, ], } satisfies FailureDataset>); }); test('for invalid exact optional entry', () => { const schema = strictObject({ key: exactOptional(string()) }); const input = { key: undefined }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: undefined, expected: 'string', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'key', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for unknown entries', () => { const input = { key1: 'foo', key2: 123, nested: { key1: 'foo', key2: 123 }, other1: 'foo', other2: 123, }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: { key1: 'foo', key2: 123, nested: { key1: 'foo', key2: 123 } }, issues: [ { ...baseInfo, kind: 'schema', type: 'strict_object', input: 'other1', expected: 'never', received: '"other1"', path: [ { type: 'object', origin: 'key', input, key: 'other1', value: input.other1, }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/strictObject/strictObject.ts ================================================ import { getDefault, getFallback } from '../../methods/index.ts'; import type { BaseSchema, ErrorMessage, InferObjectInput, InferObjectIssue, InferObjectOutput, ObjectEntries, ObjectPathItem, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { StrictObjectIssue } from './types.ts'; /** * Strict object schema interface. */ export interface StrictObjectSchema< TEntries extends ObjectEntries, TMessage extends ErrorMessage | undefined, > extends BaseSchema< InferObjectInput, InferObjectOutput, StrictObjectIssue | InferObjectIssue > { /** * The schema type. */ readonly type: 'strict_object'; /** * The schema reference. */ readonly reference: typeof strictObject; /** * The expected property. */ readonly expects: 'Object'; /** * The entries schema. */ readonly entries: TEntries; /** * The error message. */ readonly message: TMessage; } /** * Creates a strict object schema. * * @param entries The entries schema. * * @returns A strict object schema. */ export function strictObject( entries: TEntries ): StrictObjectSchema; /** * Creates a strict object schema. * * @param entries The entries schema. * @param message The error message. * * @returns A strict object schema. */ export function strictObject< const TEntries extends ObjectEntries, const TMessage extends ErrorMessage | undefined, >(entries: TEntries, message: TMessage): StrictObjectSchema; // @__NO_SIDE_EFFECTS__ export function strictObject( entries: ObjectEntries, message?: ErrorMessage ): StrictObjectSchema< ObjectEntries, ErrorMessage | undefined > { return { kind: 'schema', type: 'strict_object', reference: strictObject, expects: 'Object', async: false, entries, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (input && typeof input === 'object') { // Set typed to `true` and value to blank object // @ts-expect-error dataset.typed = true; dataset.value = {}; // Process each object entry of schema for (const key in this.entries) { const valueSchema = this.entries[key]; // If key is present or its an optional schema with a default value, // parse input of key or default value if ( key in input || ((valueSchema.type === 'exact_optional' || valueSchema.type === 'optional' || valueSchema.type === 'nullish') && // @ts-expect-error valueSchema.default !== undefined) ) { const value: unknown = key in input ? // @ts-expect-error input[key] : getDefault(valueSchema); const valueDataset = valueSchema['~run']({ value }, config); // If there are issues, capture them if (valueDataset.issues) { // Create object path item const pathItem: ObjectPathItem = { type: 'object', origin: 'value', input: input as Record, key, value, }; // Add modified entry dataset issues to issues for (const issue of valueDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = valueDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!valueDataset.typed) { dataset.typed = false; } // Add entry to dataset // @ts-expect-error dataset.value[key] = valueDataset.value; // Otherwise, if key is missing but has a fallback, use it // @ts-expect-error } else if (valueSchema.fallback !== undefined) { // @ts-expect-error dataset.value[key] = getFallback(valueSchema); // Otherwise, if key is missing and required, add issue } else if ( valueSchema.type !== 'exact_optional' && valueSchema.type !== 'optional' && valueSchema.type !== 'nullish' ) { _addIssue(this, 'key', dataset, config, { input: undefined, expected: `"${key}"`, path: [ { type: 'object', origin: 'key', input: input as Record, key, // @ts-expect-error value: input[key], }, ], }); // If necessary, abort early if (config.abortEarly) { break; } } } // Check input for unknown keys if necessary if (!dataset.issues || !config.abortEarly) { for (const key in input) { if (!(key in this.entries)) { _addIssue(this, 'key', dataset, config, { input: key, expected: 'never', path: [ { type: 'object', origin: 'key', input: input as Record, key, // @ts-expect-error value: input[key], }, ], }); // Hint: We intentionally break the loop after the first unknown // entries. Otherwise, attackers could send large objects to // exhaust device resources. If you want an issue for every // unknown key, use the `objectWithRest` schema with `never` for // the `rest` argument. break; } } } // Otherwise, add object issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< InferObjectOutput, StrictObjectIssue | InferObjectIssue >; }, }; } ================================================ FILE: library/src/schemas/strictObject/strictObjectAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { Brand, BrandAction, DescriptionAction, ReadonlyAction, TransformAction, } from '../../actions/index.ts'; import type { SchemaWithPipe, SchemaWithPipeAsync, } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import type { AnySchema } from '../any/index.ts'; import type { CustomIssue, CustomSchemaAsync } from '../custom/index.ts'; import type { ExactOptionalSchema, ExactOptionalSchemaAsync, } from '../exactOptional/index.ts'; import type { NullishSchema, NullishSchemaAsync } from '../nullish/index.ts'; import type { NumberIssue, NumberSchema } from '../number/index.ts'; import type { ObjectIssue, ObjectSchemaAsync } from '../object/index.ts'; import type { OptionalSchema, OptionalSchemaAsync } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import type { UndefinedableSchema } from '../undefinedable/index.ts'; import type { UnknownSchema } from '../unknown/index.ts'; import { strictObjectAsync, type StrictObjectSchemaAsync, } from './strictObjectAsync.ts'; import type { StrictObjectIssue } from './types.ts'; describe('strictObjectAsync', () => { describe('should return schema object', () => { const entries = { key: string() }; type Entries = typeof entries; test('with undefined message', () => { type Schema = StrictObjectSchemaAsync; expectTypeOf(strictObjectAsync(entries)).toEqualTypeOf(); expectTypeOf( strictObjectAsync(entries, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(strictObjectAsync(entries, 'message')).toEqualTypeOf< StrictObjectSchemaAsync >(); }); test('with function message', () => { expectTypeOf(strictObjectAsync(entries, () => 'message')).toEqualTypeOf< StrictObjectSchemaAsync string> >(); }); }); describe('should infer correct types', () => { type Schema = StrictObjectSchemaAsync< { key00: StringSchema; key01: AnySchema; key02: UnknownSchema; key03: ObjectSchemaAsync<{ key: NumberSchema }, undefined>; key04: SchemaWithPipe< [StringSchema, ReadonlyAction] >; key05: UndefinedableSchema, 'bar'>; key06: SchemaWithPipe< [ OptionalSchema, undefined>, TransformAction, ] >; key07: SchemaWithPipeAsync< [ OptionalSchema, undefined>, TransformAction, ] >; key08: SchemaWithPipeAsync< [ OptionalSchemaAsync, undefined>, TransformAction, ] >; key09: CustomSchemaAsync<`a${string}` | `b${string}`, undefined>; key10: SchemaWithPipe< [StringSchema, BrandAction] >; // ExactOptionalSchema key20: ExactOptionalSchema, undefined>; key21: ExactOptionalSchema, 'foo'>; key22: ExactOptionalSchema, () => 'foo'>; // ExactOptionalSchemaAsync key30: ExactOptionalSchemaAsync, undefined>; key31: ExactOptionalSchemaAsync, 'foo'>; key32: ExactOptionalSchemaAsync, () => 'foo'>; key33: ExactOptionalSchemaAsync< StringSchema, () => Promise<'foo'> >; // OptionalSchema key40: OptionalSchema, undefined>; key41: OptionalSchema, 'foo'>; key42: OptionalSchema, () => undefined>; key43: OptionalSchema, () => 'foo'>; // OptionalSchemaAsync key50: OptionalSchemaAsync, undefined>; key51: OptionalSchemaAsync, 'foo'>; key52: OptionalSchemaAsync, () => undefined>; key53: OptionalSchemaAsync, () => 'foo'>; key54: OptionalSchemaAsync< StringSchema, () => Promise >; key55: OptionalSchemaAsync< StringSchema, () => Promise<'foo'> >; // NullishSchema key60: NullishSchema, undefined>; key61: NullishSchema, null>; key62: NullishSchema, 'foo'>; key63: NullishSchema, () => undefined>; key64: NullishSchema, () => null>; key65: NullishSchema, () => 'foo'>; // NullishSchemaAsync key70: NullishSchemaAsync, undefined>; key71: NullishSchemaAsync, null>; key72: NullishSchemaAsync, 'foo'>; key73: NullishSchemaAsync, () => undefined>; key74: NullishSchemaAsync, () => null>; key75: NullishSchemaAsync, () => 'foo'>; key76: NullishSchemaAsync< StringSchema, () => Promise >; key77: NullishSchemaAsync, () => Promise>; key78: NullishSchemaAsync< StringSchema, () => Promise<'foo'> >; // SchemaWithPipe key80: SchemaWithPipe< [ExactOptionalSchema, undefined>] >; key81: SchemaWithPipe< [ ExactOptionalSchema, undefined>, DescriptionAction, ] >; key82: SchemaWithPipe< [OptionalSchema, undefined>] >; key83: SchemaWithPipe< [ OptionalSchema, undefined>, DescriptionAction, ] >; key84: SchemaWithPipe< [NullishSchema, undefined>] >; key85: SchemaWithPipe< [ NullishSchema, undefined>, DescriptionAction, ] >; key86: SchemaWithPipe< [ NullishSchema, undefined>, TransformAction, ] >; key87: SchemaWithPipeAsync< [ NullishSchemaAsync, undefined>, TransformAction, ] >; }, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf<{ key00: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any key01: any; key02: unknown; key03: { key: number }; key04: string; key05: string | undefined; key06?: string | undefined; key07?: string | undefined; key08?: string | undefined; key09: `a${string}` | `b${string}`; key10: string; // ExactOptionalSchema key20?: string; key21?: string; key22?: string; // ExactOptionalSchemaAsync key30?: string; key31?: string; key32?: string; key33?: string; // OptionalSchema key40?: string | undefined; key41?: string | undefined; key42?: string | undefined; key43?: string | undefined; // OptionalSchemaAsync key50?: string | undefined; key51?: string | undefined; key52?: string | undefined; key53?: string | undefined; key54?: string | undefined; key55?: string | undefined; // NullishSchema key60?: string | null | undefined; key61?: string | null | undefined; key62?: string | null | undefined; key63?: string | null | undefined; key64?: string | null | undefined; key65?: string | null | undefined; // NullishSchemaAsync key70?: string | null | undefined; key71?: string | null | undefined; key72?: string | null | undefined; key73?: string | null | undefined; key74?: string | null | undefined; key75?: string | null | undefined; key76?: string | null | undefined; key77?: string | null | undefined; key78?: string | null | undefined; // SchemaWithPipe key80?: string; key81?: string; key82?: string | undefined; key83?: string | undefined; key84?: string | null | undefined; key85?: string | null | undefined; key86?: string | null | undefined; key87?: string | null | undefined; }>(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf<{ key00: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any key01: any; key02: unknown; key03: { key: number }; readonly key04: string; key05: string; key06?: number; key07?: number; key08?: number; key09: `a${string}` | `b${string}`; key10: string & Brand<'foo'>; // ExactOptionalSchema key20?: string; key21: string; key22: string; // ExactOptionalSchemaAsync key30?: string; key31: string; key32: string; key33: string; // OptionalSchema key40?: string | undefined; key41: string; key42: string | undefined; key43: string; // OptionalSchemaAsync key50?: string | undefined; key51: string; key52: string | undefined; key53: string; key54: string | undefined; key55: string; // NullishSchema key60?: string | null | undefined; key61: string | null; key62: string; key63: string | undefined; key64: string | null; key65: string; // NullishSchemaAsync key70?: string | null | undefined; key71: string | null; key72: string; key73: string | undefined; key74: string | null; key75: string; key76: string | undefined; key77: string | null; key78: string; // SchemaWithPipe key80?: string; key81?: string; key82?: string | undefined; key83?: string | undefined; key84?: string | null | undefined; key85?: string | null | undefined; key86?: string[]; key87?: string[]; }>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< | StrictObjectIssue | ObjectIssue | StringIssue | NumberIssue | CustomIssue >(); }); }); }); ================================================ FILE: library/src/schemas/strictObject/strictObjectAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { fallback, fallbackAsync } from '../../methods/index.ts'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { any } from '../any/index.ts'; import { exactOptional, exactOptionalAsync } from '../exactOptional/index.ts'; import { nullish, nullishAsync } from '../nullish/index.ts'; import { number } from '../number/index.ts'; import { objectAsync } from '../object/index.ts'; import { optional, optionalAsync } from '../optional/index.ts'; import { string } from '../string/index.ts'; import { unknown } from '../unknown/index.ts'; import { strictObjectAsync, type StrictObjectSchemaAsync, } from './strictObjectAsync.ts'; import type { StrictObjectIssue } from './types.ts'; describe('strictObjectAsync', () => { describe('should return schema object', () => { const entries = { key: string() }; type Entries = typeof entries; const baseSchema: Omit< StrictObjectSchemaAsync, 'message' > = { kind: 'schema', type: 'strict_object', reference: strictObjectAsync, expects: 'Object', entries, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: StrictObjectSchemaAsync = { ...baseSchema, message: undefined, }; expect(strictObjectAsync(entries)).toStrictEqual(schema); expect(strictObjectAsync(entries, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(strictObjectAsync(entries, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies StrictObjectSchemaAsync); }); test('with function message', () => { const message = () => 'message'; expect(strictObjectAsync(entries, message)).toStrictEqual({ ...baseSchema, message, } satisfies StrictObjectSchemaAsync); }); }); describe('should return dataset without issues', () => { test('for empty object', async () => { await expectNoSchemaIssueAsync(strictObjectAsync({}), [{}]); }); test('for simple object', async () => { await expectNoSchemaIssueAsync( strictObjectAsync({ key1: string(), key2: number() }), [{ key1: 'foo', key2: 123 }] ); }); }); describe('should return dataset with issues', () => { const schema = strictObjectAsync({}, 'message'); const baseIssue: Omit = { kind: 'schema', type: 'strict_object', expected: 'Object', message: 'message', }; // Primitive types test('for bigints', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', async () => { await expectSchemaIssueAsync(schema, baseIssue, [true, false]); }); test('for null', async () => { await expectSchemaIssueAsync(schema, baseIssue, [null]); }); test('for numbers', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', async () => { await expectSchemaIssueAsync(schema, baseIssue, [undefined]); }); test('for strings', async () => { await expectSchemaIssueAsync(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ Symbol(), Symbol('foo'), ]); }); // Complex types // TODO: Enable this test again in case we find a reliable way to check for // plain objects // test('for arrays', async () => { // await expectSchemaIssueAsync(schema, baseIssue, [[], ['value']]); // }); test('for functions', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ // eslint-disable-next-line @typescript-eslint/no-empty-function () => {}, // eslint-disable-next-line @typescript-eslint/no-empty-function function () {}, ]); }); }); describe('should return dataset without nested issues', () => { test('for simple object', async () => { await expectNoSchemaIssueAsync( strictObjectAsync({ key1: string(), key2: number() }), [{ key1: 'foo', key2: 123 }] ); }); test('for nested object', async () => { await expectNoSchemaIssueAsync( strictObjectAsync({ nested: objectAsync({ key: string() }) }), [{ nested: { key: 'foo' } }] ); }); test('for missing entries with fallback', async () => { expect( await strictObjectAsync({ key1: fallback(string(), 'foo'), key2: fallback(number(), () => 123), key3: fallbackAsync(string(), 'bar'), key4: fallbackAsync(number(), () => 456), key5: fallbackAsync(string(), async () => 'baz'), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key1: 'foo', key2: 123, key3: 'bar', key4: 456, key5: 'baz' }, }); }); test('for exact optional entry', async () => { await expectNoSchemaIssueAsync( strictObjectAsync({ key: exactOptional(string()) }), [{}, { key: 'foo' }] ); await expectNoSchemaIssueAsync( strictObjectAsync({ key: exactOptionalAsync(string()) }), [{}, { key: 'foo' }] ); }); test('for exact optional entry with default', async () => { // Sync expect( await strictObjectAsync({ key: exactOptional(string(), 'foo') })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await strictObjectAsync({ key: exactOptional(string(), () => 'foo') })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); // Async expect( await strictObjectAsync({ key: exactOptionalAsync(string(), 'foo') })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await strictObjectAsync({ key: exactOptionalAsync(string(), () => 'foo'), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); }); test('for optional entry', async () => { await expectNoSchemaIssueAsync( strictObjectAsync({ key: optional(string()) }), [{}, { key: undefined }, { key: 'foo' }] ); await expectNoSchemaIssueAsync( strictObjectAsync({ key: optionalAsync(string()) }), [{}, { key: undefined }, { key: 'foo' }] ); }); test('for optional entry with default', async () => { // Sync expect( await strictObjectAsync({ key: optional(string(), 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await strictObjectAsync({ key: optional(string(), () => 'foo') })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await strictObjectAsync({ key: optional(string(), () => undefined), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); // Async expect( await strictObjectAsync({ key: optionalAsync(string(), 'foo') })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await strictObjectAsync({ key: optionalAsync(string(), () => 'foo') })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await strictObjectAsync({ key: optionalAsync(string(), () => undefined), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); expect( await strictObjectAsync({ key: optionalAsync(string(), async () => 'foo'), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await strictObjectAsync({ key: optionalAsync(string(), async () => undefined), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); }); test('for nullish entry', async () => { await expectNoSchemaIssueAsync( strictObjectAsync({ key: nullish(number()) }), [{}, { key: undefined }, { key: null }, { key: 123 }] ); await expectNoSchemaIssueAsync( strictObjectAsync({ key: nullishAsync(number()) }), [{}, { key: undefined }, { key: null }, { key: 123 }] ); }); test('for nullish entry with default', async () => { // Sync expect( await strictObjectAsync({ key: nullish(string(), 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await strictObjectAsync({ key: nullish(string(), null) })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( await strictObjectAsync({ key: nullish(string(), () => 'foo') })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await strictObjectAsync({ key: nullish(string(), () => null) })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( await strictObjectAsync({ key: nullish(string(), () => undefined) })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); // Async expect( await strictObjectAsync({ key: nullishAsync(string(), 'foo') })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await strictObjectAsync({ key: nullishAsync(string(), null) })['~run']( { value: {} }, {} ) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( await strictObjectAsync({ key: nullishAsync(string(), () => 'foo') })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await strictObjectAsync({ key: nullishAsync(string(), () => null) })[ '~run' ]({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( await strictObjectAsync({ key: nullishAsync(string(), () => undefined), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); expect( await strictObjectAsync({ key: nullishAsync(string(), async () => 'foo'), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: 'foo' }, }); expect( await strictObjectAsync({ key: nullishAsync(string(), async () => null), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: null }, }); expect( await strictObjectAsync({ key: nullishAsync(string(), async () => undefined), })['~run']({ value: {} }, {}) ).toStrictEqual({ typed: true, value: { key: undefined }, }); }); }); describe('should return dataset with nested issues', () => { const schema = strictObjectAsync({ key1: string(), key2: number(), nested: strictObjectAsync({ key1: string(), key2: number() }), }); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for missing entries', async () => { const input = { key2: 123 }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'strict_object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'strict_object', input: undefined, expected: '"nested"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'nested', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for missing nested entries', async () => { const input = { key1: 'value', nested: {} }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'strict_object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key2', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'strict_object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: {}, }, { type: 'object', origin: 'key', input: input.nested, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'strict_object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: {}, }, { type: 'object', origin: 'key', input: input.nested, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for missing entries with abort early', async () => { const input = { key2: 123 }; expect( await schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'strict_object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input, key: 'key1', value: undefined, }, ], abortEarly: true, }, ], } satisfies FailureDataset>); }); test('for missing any and unknown entry', async () => { const schema = strictObjectAsync({ key1: any(), key2: unknown() }); expect(await schema['~run']({ value: {} }, {})).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'strict_object', input: undefined, expected: '"key1"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'strict_object', input: undefined, expected: '"key2"', received: 'undefined', path: [ { type: 'object', origin: 'key', input: {}, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid entries', async () => { const input = { key1: false, key2: 123, nested: null }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: false, expected: 'string', received: 'false', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: false, }, ], }, { ...baseInfo, kind: 'schema', type: 'strict_object', input: null, expected: 'Object', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: null, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid nested entries', async () => { const input = { key1: 'value', key2: 'value', nested: { key1: 123, key2: null, }, }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: 'value', expected: 'number', received: '"value"', path: [ { type: 'object', origin: 'value', input, key: 'key2', value: input.key2, }, ], }, { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'value', input: input.nested, key: 'key1', value: input.nested.key1, }, ], }, { ...baseInfo, kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'object', origin: 'value', input: input.nested, key: 'key2', value: input.nested.key2, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid entries with abort early', async () => { const input = { key1: false, key2: 123, nested: null }; expect( await schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: {}, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: false, expected: 'string', received: 'false', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: false, }, ], abortEarly: true, }, ], } satisfies FailureDataset>); }); test('for invalid exact optional entry', async () => { const schema = strictObjectAsync({ key1: exactOptional(string()), key2: exactOptionalAsync(string()), }); const input = { key1: undefined, key2: undefined }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: undefined, expected: 'string', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'key1', value: undefined, }, ], }, { ...baseInfo, kind: 'schema', type: 'string', input: undefined, expected: 'string', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'key2', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for unknown entries', async () => { const input = { key1: 'foo', key2: 123, nested: { key1: 'foo', key2: 123 }, other1: 'foo', other2: 123, }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: { key1: 'foo', key2: 123, nested: { key1: 'foo', key2: 123 } }, issues: [ { ...baseInfo, kind: 'schema', type: 'strict_object', input: 'other1', expected: 'never', received: '"other1"', path: [ { type: 'object', origin: 'key', input, key: 'other1', value: input.other1, }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/strictObject/strictObjectAsync.ts ================================================ import { getDefault, getFallback } from '../../methods/index.ts'; import type { BaseSchemaAsync, ErrorMessage, InferObjectInput, InferObjectIssue, InferObjectOutput, ObjectEntriesAsync, ObjectPathItem, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { strictObject } from './strictObject.ts'; import type { StrictObjectIssue } from './types.ts'; /** * Strict object schema async interface. */ export interface StrictObjectSchemaAsync< TEntries extends ObjectEntriesAsync, TMessage extends ErrorMessage | undefined, > extends BaseSchemaAsync< InferObjectInput, InferObjectOutput, StrictObjectIssue | InferObjectIssue > { /** * The schema type. */ readonly type: 'strict_object'; /** * The schema reference. */ readonly reference: typeof strictObject | typeof strictObjectAsync; /** * The expected property. */ readonly expects: 'Object'; /** * The entries schema. */ readonly entries: TEntries; /** * The error message. */ readonly message: TMessage; } /** * Creates a strict object schema. * * @param entries The entries schema. * * @returns A strict object schema. */ export function strictObjectAsync( entries: TEntries ): StrictObjectSchemaAsync; /** * Creates a strict object schema. * * @param entries The entries schema. * @param message The error message. * * @returns A strict object schema. */ export function strictObjectAsync< const TEntries extends ObjectEntriesAsync, const TMessage extends ErrorMessage | undefined, >( entries: TEntries, message: TMessage ): StrictObjectSchemaAsync; // @__NO_SIDE_EFFECTS__ export function strictObjectAsync( entries: ObjectEntriesAsync, message?: ErrorMessage ): StrictObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined > { return { kind: 'schema', type: 'strict_object', reference: strictObjectAsync, expects: 'Object', async: true, entries, message, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (input && typeof input === 'object') { // Set typed to `true` and value to blank object // @ts-expect-error dataset.typed = true; dataset.value = {}; // If key is present or its an optional schema with a default value, // parse input of key or default value asynchronously const valueDatasets = await Promise.all( Object.entries(this.entries).map(async ([key, valueSchema]) => { if ( key in input || ((valueSchema.type === 'exact_optional' || valueSchema.type === 'optional' || valueSchema.type === 'nullish') && // @ts-expect-error valueSchema.default !== undefined) ) { const value: unknown = key in input ? // @ts-expect-error input[key] : await getDefault(valueSchema); return [ key, value, valueSchema, await valueSchema['~run']({ value }, config), ] as const; } return [ key, // @ts-expect-error input[key] as unknown, valueSchema, null, ] as const; }) ); // Process each object entry of schema for (const [key, value, valueSchema, valueDataset] of valueDatasets) { // If key is present or its an optional schema with a default value, // process its value dataset if (valueDataset) { // If there are issues, capture them if (valueDataset.issues) { // Create object path item const pathItem: ObjectPathItem = { type: 'object', origin: 'value', input: input as Record, key, value, }; // Add modified entry dataset issues to issues for (const issue of valueDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = valueDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!valueDataset.typed) { dataset.typed = false; } // Add entry to dataset // @ts-expect-error dataset.value[key] = valueDataset.value; // Otherwise, if key is missing but has a fallback, use it // @ts-expect-error } else if (valueSchema.fallback !== undefined) { // @ts-expect-error dataset.value[key] = await getFallback(valueSchema); // Otherwise, if key is missing and required, add issue } else if ( valueSchema.type !== 'exact_optional' && valueSchema.type !== 'optional' && valueSchema.type !== 'nullish' ) { _addIssue(this, 'key', dataset, config, { input: undefined, expected: `"${key}"`, path: [ { type: 'object', origin: 'key', input: input as Record, key, value, }, ], }); // If necessary, abort early if (config.abortEarly) { break; } } } // Check input for unknown keys if necessary if (!dataset.issues || !config.abortEarly) { for (const key in input) { if (!(key in this.entries)) { _addIssue(this, 'key', dataset, config, { input: key, expected: 'never', path: [ { type: 'object', origin: 'key', input: input as Record, key, // @ts-expect-error value: input[key], }, ], }); // Hint: We intentionally break the loop after the first unknown // entries. Otherwise, attackers could send large objects to // exhaust device resources. If you want an issue for every // unknown key, use the `objectWithRest` schema with `never` for // the `rest` argument. break; } } } // Otherwise, add object issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< InferObjectOutput, StrictObjectIssue | InferObjectIssue >; }, }; } ================================================ FILE: library/src/schemas/strictObject/types.ts ================================================ import type { BaseIssue } from '../../types/index.ts'; /** * Strict object issue interface. */ export interface StrictObjectIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'strict_object'; /** * The expected property. */ readonly expected: 'Object' | `"${string}"` | 'never'; } ================================================ FILE: library/src/schemas/strictTuple/index.ts ================================================ export * from './strictTuple.ts'; export * from './strictTupleAsync.ts'; export * from './types.ts'; ================================================ FILE: library/src/schemas/strictTuple/strictTuple.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { boolean } from '../boolean/index.ts'; import { number, type NumberIssue, type NumberSchema, } from '../number/index.ts'; import type { OptionalSchema } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { strictTuple, type StrictTupleSchema } from './strictTuple.ts'; import type { StrictTupleIssue } from './types.ts'; describe('strictTuple', () => { describe('should return schema object', () => { const items = [string(), number(), boolean()] as const; type Items = typeof items; test('with undefined message', () => { type Schema = StrictTupleSchema; expectTypeOf(strictTuple(items)).toEqualTypeOf(); expectTypeOf(strictTuple(items, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(strictTuple(items, 'message')).toEqualTypeOf< StrictTupleSchema >(); }); test('with function message', () => { expectTypeOf(strictTuple(items, () => 'message')).toEqualTypeOf< StrictTupleSchema string> >(); }); }); describe('should infer correct types', () => { type Schema = StrictTupleSchema< [OptionalSchema, 'foo'>, NumberSchema], undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf< [string | undefined, number] >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf<[string, number]>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< StrictTupleIssue | StringIssue | NumberIssue >(); }); }); }); ================================================ FILE: library/src/schemas/strictTuple/strictTuple.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { boolean } from '../boolean/index.ts'; import { number } from '../number/index.ts'; import { optional } from '../optional/index.ts'; import { string, type StringIssue } from '../string/index.ts'; import { strictTuple, type StrictTupleSchema } from './strictTuple.ts'; import type { StrictTupleIssue } from './types.ts'; describe('strictTuple', () => { describe('should return schema object', () => { const items = [optional(string()), number()] as const; type Items = typeof items; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'strict_tuple', reference: strictTuple, expects: 'Array', items, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: StrictTupleSchema = { ...baseSchema, message: undefined, }; expect(strictTuple(items)).toStrictEqual(schema); expect(strictTuple(items, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(strictTuple(items, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies StrictTupleSchema); }); test('with function message', () => { const message = () => 'message'; expect(strictTuple(items, message)).toStrictEqual({ ...baseSchema, message, } satisfies StrictTupleSchema); }); }); describe('should return dataset without issues', () => { test('for empty tuple', () => { expectNoSchemaIssue(strictTuple([]), [[]]); }); test('for simple tuple', () => { expectNoSchemaIssue(strictTuple([optional(string()), number()]), [ ['foo', 123], [undefined, 123], ]); }); }); describe('should return dataset with issues', () => { const schema = strictTuple([optional(string()), number()], 'message'); const baseIssue: Omit = { kind: 'schema', type: 'strict_tuple', expected: 'Array', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); describe('should return dataset without nested issues', () => { const schema = strictTuple([optional(string()), number()]); test('for simple tuple', () => { expectNoSchemaIssue(schema, [ ['foo', 123], [undefined, 123], ]); }); test('for nested tuple', () => { expectNoSchemaIssue(strictTuple([schema, schema]), [ [ ['foo', 123], [undefined, 123], ], ]); }); }); describe('should return dataset with nested issues', () => { const schema = strictTuple([string(), number(), boolean()]); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const stringIssue: StringIssue = { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'array', origin: 'value', input: [123, 456, 'true'], key: 0, value: 123, }, ], }; test('for wrong items', () => { const input = [123, 456, 'true']; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ stringIssue, { ...baseInfo, kind: 'schema', type: 'boolean', input: 'true', expected: 'boolean', received: '"true"', path: [ { type: 'array', origin: 'value', input: input, key: 2, value: input[2], }, ], }, ], } satisfies FailureDataset>); }); test('with abort early', () => { expect( schema['~run']({ value: [123, 456, 'true'] }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: [], issues: [{ ...stringIssue, abortEarly: true }], } satisfies FailureDataset>); }); test('for wrong nested items', () => { const nestedSchema = strictTuple([schema, schema]); const input: [[string, string, boolean], null] = [ ['foo', '123', false], null, ]; expect(nestedSchema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: '123', expected: 'number', received: '"123"', path: [ { type: 'array', origin: 'value', input: input, key: 0, value: input[0], }, { type: 'array', origin: 'value', input: input[0], key: 1, value: input[0][1], }, ], }, { ...baseInfo, kind: 'schema', type: 'strict_tuple', input: null, expected: 'Array', received: 'null', path: [ { type: 'array', origin: 'value', input: input, key: 1, value: input[1], }, ], }, ], } satisfies FailureDataset>); }); test('for unknown items', () => { const input = ['foo', 123, true, null, undefined]; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: ['foo', 123, true], issues: [ { ...baseInfo, kind: 'schema', type: 'strict_tuple', input: null, expected: 'never', received: 'null', path: [ { type: 'array', origin: 'value', input, key: 3, value: input[3], }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/strictTuple/strictTuple.ts ================================================ import type { ArrayPathItem, BaseIssue, BaseSchema, ErrorMessage, InferTupleInput, InferTupleIssue, InferTupleOutput, OutputDataset, TupleItems, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { StrictTupleIssue } from './types.ts'; /** * Strict tuple schema interface. */ export interface StrictTupleSchema< TItems extends TupleItems, TMessage extends ErrorMessage | undefined, > extends BaseSchema< InferTupleInput, InferTupleOutput, StrictTupleIssue | InferTupleIssue > { /** * The schema type. */ readonly type: 'strict_tuple'; /** * The schema reference. */ readonly reference: typeof strictTuple; /** * The expected property. */ readonly expects: 'Array'; /** * The items schema. */ readonly items: TItems; /** * The error message. */ readonly message: TMessage; } /** * Creates a strict tuple schema. * * @param items The items schema. * * @returns A strict tuple schema. */ export function strictTuple( items: TItems ): StrictTupleSchema; /** * Creates a strict tuple schema. * * @param items The items schema. * @param message The error message. * * @returns A strict tuple schema. */ export function strictTuple< const TItems extends TupleItems, const TMessage extends ErrorMessage | undefined, >(items: TItems, message: TMessage): StrictTupleSchema; // @__NO_SIDE_EFFECTS__ export function strictTuple( items: TupleItems, message?: ErrorMessage ): StrictTupleSchema | undefined> { return { kind: 'schema', type: 'strict_tuple', reference: strictTuple, expects: 'Array', async: false, items, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (Array.isArray(input)) { // Set typed to `true` and value to empty array // @ts-expect-error dataset.typed = true; dataset.value = []; // Parse schema of each tuple item for (let key = 0; key < this.items.length; key++) { const value = input[key]; const itemDataset = this.items[key]['~run']({ value }, config); // If there are issues, capture them if (itemDataset.issues) { // Create tuple path item const pathItem: ArrayPathItem = { type: 'array', origin: 'value', input, key, value, }; // Add modified item dataset issues to issues for (const issue of itemDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = itemDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!itemDataset.typed) { dataset.typed = false; } // Add item to dataset // @ts-expect-error dataset.value.push(itemDataset.value); } // Check input for unknown items if necessary if ( !(dataset.issues && config.abortEarly) && this.items.length < input.length ) { _addIssue(this, 'type', dataset, config, { input: input[this.items.length], expected: 'never', path: [ { type: 'array', origin: 'value', input, key: this.items.length, value: input[this.items.length], }, ], }); // Hint: We intentionally only add one issue for unknown items. // Otherwise, attackers could send large arrays to exhaust // device resources. If you want an issue for every unknown item, // use the `tupleWithRest` schema with `never` for the `rest` // argument. } // Otherwise, add tuple issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< unknown[], StrictTupleIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/strictTuple/strictTupleAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { boolean } from '../boolean/index.ts'; import { number, type NumberIssue, type NumberSchema, } from '../number/index.ts'; import type { OptionalSchema } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { strictTupleAsync, type StrictTupleSchemaAsync, } from './strictTupleAsync.ts'; import type { StrictTupleIssue } from './types.ts'; describe('strictTupleAsync', () => { describe('should return schema object', () => { const items = [string(), number(), boolean()] as const; type Items = typeof items; test('with undefined message', () => { type Schema = StrictTupleSchemaAsync; expectTypeOf(strictTupleAsync(items)).toEqualTypeOf(); expectTypeOf(strictTupleAsync(items, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(strictTupleAsync(items, 'message')).toEqualTypeOf< StrictTupleSchemaAsync >(); }); test('with function message', () => { expectTypeOf(strictTupleAsync(items, () => 'message')).toEqualTypeOf< StrictTupleSchemaAsync string> >(); }); }); describe('should infer correct types', () => { type Schema = StrictTupleSchemaAsync< [OptionalSchema, 'foo'>, NumberSchema], undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf< [string | undefined, number] >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf<[string, number]>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< StrictTupleIssue | StringIssue | NumberIssue >(); }); }); }); ================================================ FILE: library/src/schemas/strictTuple/strictTupleAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { boolean } from '../boolean/index.ts'; import { number } from '../number/index.ts'; import { optionalAsync } from '../optional/index.ts'; import { string, type StringIssue } from '../string/index.ts'; import { strictTupleAsync, type StrictTupleSchemaAsync, } from './strictTupleAsync.ts'; import type { StrictTupleIssue } from './types.ts'; describe('strictTupleAsync', () => { describe('should return schema object', () => { const items = [optionalAsync(string()), number()] as const; type Items = typeof items; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'strict_tuple', reference: strictTupleAsync, expects: 'Array', items, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: StrictTupleSchemaAsync = { ...baseSchema, message: undefined, }; expect(strictTupleAsync(items)).toStrictEqual(schema); expect(strictTupleAsync(items, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(strictTupleAsync(items, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies StrictTupleSchemaAsync); }); test('with function message', () => { const message = () => 'message'; expect(strictTupleAsync(items, message)).toStrictEqual({ ...baseSchema, message, } satisfies StrictTupleSchemaAsync); }); }); describe('should return dataset without issues', () => { test('for empty tuple', async () => { await expectNoSchemaIssueAsync(strictTupleAsync([]), [[]]); }); test('for simple tuple', async () => { await expectNoSchemaIssueAsync( strictTupleAsync([optionalAsync(string()), number()]), [ ['foo', 123], [undefined, 123], ] ); }); }); describe('should return dataset with issues', () => { const schema = strictTupleAsync( [optionalAsync(string()), number()], 'message' ); const baseIssue: Omit = { kind: 'schema', type: 'strict_tuple', expected: 'Array', message: 'message', }; // Primitive types test('for bigints', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', async () => { await expectSchemaIssueAsync(schema, baseIssue, [true, false]); }); test('for null', async () => { await expectSchemaIssueAsync(schema, baseIssue, [null]); }); test('for numbers', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', async () => { await expectSchemaIssueAsync(schema, baseIssue, [undefined]); }); test('for strings', async () => { await expectSchemaIssueAsync(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ Symbol(), Symbol('foo'), ]); }); // Complex types test('for functions', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ // eslint-disable-next-line @typescript-eslint/no-empty-function () => {}, // eslint-disable-next-line @typescript-eslint/no-empty-function function () {}, ]); }); test('for objects', async () => { await expectSchemaIssueAsync(schema, baseIssue, [{}, { key: 'value' }]); }); }); describe('should return dataset without nested issues', () => { const schema = strictTupleAsync([optionalAsync(string()), number()]); test('for simple tuple', async () => { await expectNoSchemaIssueAsync(schema, [ ['foo', 123], [undefined, 123], ]); }); test('for nested tuple', async () => { await expectNoSchemaIssueAsync(strictTupleAsync([schema, schema]), [ [ ['foo', 123], [undefined, 123], ], ]); }); }); describe('should return dataset with nested issues', () => { const schema = strictTupleAsync([string(), number(), boolean()]); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const stringIssue: StringIssue = { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'array', origin: 'value', input: [123, 456, 'true'], key: 0, value: 123, }, ], }; test('for wrong items', async () => { const input = [123, 456, 'true']; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ stringIssue, { ...baseInfo, kind: 'schema', type: 'boolean', input: 'true', expected: 'boolean', received: '"true"', path: [ { type: 'array', origin: 'value', input: input, key: 2, value: input[2], }, ], }, ], } satisfies FailureDataset>); }); test('with abort early', async () => { expect( await schema['~run']( { value: [123, 456, 'true'] }, { abortEarly: true } ) ).toStrictEqual({ typed: false, value: [], issues: [{ ...stringIssue, abortEarly: true }], } satisfies FailureDataset>); }); test('for wrong nested items', async () => { const nestedSchema = strictTupleAsync([schema, schema]); const input: [[string, string, boolean], null] = [ ['foo', '123', false], null, ]; expect(await nestedSchema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: '123', expected: 'number', received: '"123"', path: [ { type: 'array', origin: 'value', input: input, key: 0, value: input[0], }, { type: 'array', origin: 'value', input: input[0], key: 1, value: input[0][1], }, ], }, { ...baseInfo, kind: 'schema', type: 'strict_tuple', input: null, expected: 'Array', received: 'null', path: [ { type: 'array', origin: 'value', input: input, key: 1, value: input[1], }, ], }, ], } satisfies FailureDataset>); }); test('for unknown items', async () => { const input = ['foo', 123, true, null, undefined]; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: ['foo', 123, true], issues: [ { ...baseInfo, kind: 'schema', type: 'strict_tuple', input: null, expected: 'never', received: 'null', path: [ { type: 'array', origin: 'value', input, key: 3, value: input[3], }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/strictTuple/strictTupleAsync.ts ================================================ import type { ArrayPathItem, BaseIssue, BaseSchemaAsync, ErrorMessage, InferTupleInput, InferTupleIssue, InferTupleOutput, OutputDataset, TupleItemsAsync, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { strictTuple } from './strictTuple.ts'; import type { StrictTupleIssue } from './types.ts'; /** * Strict tuple schema async interface. */ export interface StrictTupleSchemaAsync< TItems extends TupleItemsAsync, TMessage extends ErrorMessage | undefined, > extends BaseSchemaAsync< InferTupleInput, InferTupleOutput, StrictTupleIssue | InferTupleIssue > { /** * The schema type. */ readonly type: 'strict_tuple'; /** * The schema reference. */ readonly reference: typeof strictTuple | typeof strictTupleAsync; /** * The expected property. */ readonly expects: 'Array'; /** * The items schema. */ readonly items: TItems; /** * The error message. */ readonly message: TMessage; } /** * Creates a strict tuple schema. * * @param items The items schema. * * @returns A strict tuple schema. */ export function strictTupleAsync( items: TItems ): StrictTupleSchemaAsync; /** * Creates a strict tuple schema. * * @param items The items schema. * @param message The error message. * * @returns A strict tuple schema. */ export function strictTupleAsync< const TItems extends TupleItemsAsync, const TMessage extends ErrorMessage | undefined, >(items: TItems, message: TMessage): StrictTupleSchemaAsync; // @__NO_SIDE_EFFECTS__ export function strictTupleAsync( items: TupleItemsAsync, message?: ErrorMessage ): StrictTupleSchemaAsync< TupleItemsAsync, ErrorMessage | undefined > { return { kind: 'schema', type: 'strict_tuple', reference: strictTupleAsync, expects: 'Array', async: true, items, message, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (Array.isArray(input)) { // Set typed to `true` and value to empty array // @ts-expect-error dataset.typed = true; dataset.value = []; // Parse schema of each tuple item const itemDatasets = await Promise.all( this.items.map(async (item, key) => { const value = input[key]; return [key, value, await item['~run']({ value }, config)] as const; }) ); // Process each tuple item dataset for (const [key, value, itemDataset] of itemDatasets) { // If there are issues, capture them if (itemDataset.issues) { // Create tuple path item const pathItem: ArrayPathItem = { type: 'array', origin: 'value', input, key, value, }; // Add modified item dataset issues to issues for (const issue of itemDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = itemDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!itemDataset.typed) { dataset.typed = false; } // Add item to dataset // @ts-expect-error dataset.value.push(itemDataset.value); } // Check input for unknown items if necessary if ( !(dataset.issues && config.abortEarly) && this.items.length < input.length ) { _addIssue(this, 'type', dataset, config, { input: input[this.items.length], expected: 'never', path: [ { type: 'array', origin: 'value', input, key: this.items.length, value: input[this.items.length], }, ], }); // Hint: We intentionally only add one issue for unknown items. // Otherwise, attackers could send large arrays to exhaust // device resources. If you want an issue for every unknown item, // use the `tupleWithRest` schema with `never` for the `rest` // argument. } // Otherwise, add tuple issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< unknown[], StrictTupleIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/strictTuple/types.ts ================================================ import type { BaseIssue } from '../../types/index.ts'; /** * Strict tuple issue interface. */ export interface StrictTupleIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'strict_tuple'; /** * The expected property. */ readonly expected: 'Array' | 'never'; } ================================================ FILE: library/src/schemas/string/index.ts ================================================ export * from './string.ts'; ================================================ FILE: library/src/schemas/string/string.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { string, type StringIssue, type StringSchema } from './string.ts'; describe('string', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = StringSchema; expectTypeOf(string()).toEqualTypeOf(); expectTypeOf(string(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(string('message')).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf(string(() => 'message')).toEqualTypeOf< StringSchema<() => string> >(); }); }); describe('should infer correct types', () => { type Schema = StringSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/string/string.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { string, type StringIssue, type StringSchema } from './string.ts'; describe('string', () => { describe('should return schema object', () => { const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'string', reference: string, expects: 'string', async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: StringSchema = { ...baseSchema, message: undefined, }; expect(string()).toStrictEqual(schema); expect(string(undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(string('message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies StringSchema<'message'>); }); test('with function message', () => { const message = () => 'message'; expect(string(message)).toStrictEqual({ ...baseSchema, message, } satisfies StringSchema); }); }); describe('should return dataset without issues', () => { const schema = string(); test('for empty strings', () => { expectNoSchemaIssue(schema, ['', ' ', '\n']); }); test('for single char', () => { expectNoSchemaIssue(schema, ['a', 'A', '0']); }); test('for multiple chars', () => { expectNoSchemaIssue(schema, ['abc', 'ABC', '123']); }); test('for special chars', () => { expectNoSchemaIssue(schema, ['-', '+', '#', '$', '%']); }); }); describe('should return dataset with issues', () => { const schema = string('message'); const baseIssue: Omit = { kind: 'schema', type: 'string', expected: 'string', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); }); ================================================ FILE: library/src/schemas/string/string.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; /** * String issue interface. */ export interface StringIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'string'; /** * The expected property. */ readonly expected: 'string'; } /** * String schema interface. */ export interface StringSchema< TMessage extends ErrorMessage | undefined, > extends BaseSchema { /** * The schema type. */ readonly type: 'string'; /** * The schema reference. */ readonly reference: typeof string; /** * The expected property. */ readonly expects: 'string'; /** * The error message. */ readonly message: TMessage; } /** * Creates a string schema. * * @returns A string schema. */ export function string(): StringSchema; /** * Creates a string schema. * * @param message The error message. * * @returns A string schema. */ export function string< const TMessage extends ErrorMessage | undefined, >(message: TMessage): StringSchema; // @__NO_SIDE_EFFECTS__ export function string( message?: ErrorMessage ): StringSchema | undefined> { return { kind: 'schema', type: 'string', reference: string, expects: 'string', async: false, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { if (typeof dataset.value === 'string') { // @ts-expect-error dataset.typed = true; } else { _addIssue(this, 'type', dataset, config); } // @ts-expect-error return dataset as OutputDataset; }, }; } ================================================ FILE: library/src/schemas/symbol/index.ts ================================================ export * from './symbol.ts'; ================================================ FILE: library/src/schemas/symbol/symbol.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { symbol, type SymbolIssue, type SymbolSchema } from './symbol.ts'; describe('symbol', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = SymbolSchema; expectTypeOf(symbol()).toEqualTypeOf(); expectTypeOf(symbol(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(symbol('message')).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf(symbol(() => 'message')).toEqualTypeOf< SymbolSchema<() => string> >(); }); }); describe('should infer correct types', () => { type Schema = SymbolSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/symbol/symbol.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { symbol, type SymbolIssue, type SymbolSchema } from './symbol.ts'; describe('symbol', () => { describe('should return schema object', () => { const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'symbol', reference: symbol, expects: 'symbol', async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: SymbolSchema = { ...baseSchema, message: undefined, }; expect(symbol()).toStrictEqual(schema); expect(symbol(undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(symbol('message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies SymbolSchema<'message'>); }); test('with function message', () => { const message = () => 'message'; expect(symbol(message)).toStrictEqual({ ...baseSchema, message, } satisfies SymbolSchema); }); }); describe('should return dataset without issues', () => { const schema = symbol(); test('for symbols', () => { expectNoSchemaIssue(schema, [Symbol(), Symbol('foo')]); }); }); describe('should return dataset with issues', () => { const schema = symbol('message'); const baseIssue: Omit = { kind: 'schema', type: 'symbol', expected: 'symbol', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'foo', '123']); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); }); ================================================ FILE: library/src/schemas/symbol/symbol.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; /** * Symbol issue interface. */ export interface SymbolIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'symbol'; /** * The expected property. */ readonly expected: 'symbol'; } /** * Symbol schema interface. */ export interface SymbolSchema< TMessage extends ErrorMessage | undefined, > extends BaseSchema { /** * The schema type. */ readonly type: 'symbol'; /** * The schema reference. */ readonly reference: typeof symbol; /** * The expected property. */ readonly expects: 'symbol'; /** * The error message. */ readonly message: TMessage; } /** * Creates a symbol schema. * * @returns A symbol schema. */ export function symbol(): SymbolSchema; /** * Creates a symbol schema. * * @param message The error message. * * @returns A symbol schema. */ export function symbol< const TMessage extends ErrorMessage | undefined, >(message: TMessage): SymbolSchema; // @__NO_SIDE_EFFECTS__ export function symbol( message?: ErrorMessage ): SymbolSchema | undefined> { return { kind: 'schema', type: 'symbol', reference: symbol, expects: 'symbol', async: false, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { if (typeof dataset.value === 'symbol') { // @ts-expect-error dataset.typed = true; } else { _addIssue(this, 'type', dataset, config); } // @ts-expect-error return dataset as OutputDataset; }, }; } ================================================ FILE: library/src/schemas/tuple/index.ts ================================================ export * from './tuple.ts'; export * from './tupleAsync.ts'; export * from './types.ts'; ================================================ FILE: library/src/schemas/tuple/tuple.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { boolean } from '../boolean/index.ts'; import { number, type NumberIssue, type NumberSchema, } from '../number/index.ts'; import type { OptionalSchema } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { tuple, type TupleSchema } from './tuple.ts'; import type { TupleIssue } from './types.ts'; describe('tuple', () => { describe('should return schema object', () => { const items = [string(), number(), boolean()] as const; type Items = typeof items; test('with undefined message', () => { type Schema = TupleSchema; expectTypeOf(tuple(items)).toEqualTypeOf(); expectTypeOf(tuple(items, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(tuple(items, 'message')).toEqualTypeOf< TupleSchema >(); }); test('with function message', () => { expectTypeOf(tuple(items, () => 'message')).toEqualTypeOf< TupleSchema string> >(); }); }); describe('should infer correct types', () => { type Schema = TupleSchema< [OptionalSchema, 'foo'>, NumberSchema], undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf< [string | undefined, number] >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf<[string, number]>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< TupleIssue | StringIssue | NumberIssue >(); }); }); }); ================================================ FILE: library/src/schemas/tuple/tuple.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { boolean } from '../boolean/boolean.ts'; import { number } from '../number/index.ts'; import { optional } from '../optional/index.ts'; import { string, type StringIssue } from '../string/index.ts'; import { tuple, type TupleSchema } from './tuple.ts'; import type { TupleIssue } from './types.ts'; describe('tuple', () => { describe('should return schema object', () => { const items = [optional(string()), number()] as const; type Items = typeof items; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'tuple', reference: tuple, expects: 'Array', items, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: TupleSchema = { ...baseSchema, message: undefined, }; expect(tuple(items)).toStrictEqual(schema); expect(tuple(items, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(tuple(items, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies TupleSchema); }); test('with function message', () => { const message = () => 'message'; expect(tuple(items, message)).toStrictEqual({ ...baseSchema, message, } satisfies TupleSchema); }); }); describe('should return dataset without issues', () => { test('for empty tuple', () => { expectNoSchemaIssue(tuple([]), [[]]); }); const schema = tuple([optional(string()), number()]); test('for simple tuple', () => { expectNoSchemaIssue(schema, [ ['foo', 123], [undefined, 123], ]); }); test('for unknown items', () => { expect( schema['~run']({ value: ['foo', 123, null, true, undefined] }, {}) ).toStrictEqual({ typed: true, value: ['foo', 123], }); }); }); describe('should return dataset with issues', () => { const schema = tuple([optional(string()), number()], 'message'); const baseIssue: Omit = { kind: 'schema', type: 'tuple', expected: 'Array', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); describe('should return dataset without nested issues', () => { const schema = tuple([optional(string()), number()]); test('for simple tuple', () => { expectNoSchemaIssue(schema, [ ['foo', 123], [undefined, 123], ]); }); test('for nested tuple', () => { expectNoSchemaIssue(tuple([schema, schema]), [ [ ['foo', 123], [undefined, 123], ], ]); }); test('for unknown items', () => { expect( schema['~run']({ value: ['foo', 123, null, true, undefined] }, {}) ).toStrictEqual({ typed: true, value: ['foo', 123], }); }); }); describe('should return dataset with nested issues', () => { const schema = tuple([string(), number(), boolean()]); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const stringIssue: StringIssue = { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'array', origin: 'value', input: [123, 456, 'true'], key: 0, value: 123, }, ], }; test('for wrong items', () => { const input = [123, 456, 'true']; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ stringIssue, { ...baseInfo, kind: 'schema', type: 'boolean', input: 'true', expected: 'boolean', received: '"true"', path: [ { type: 'array', origin: 'value', input: input, key: 2, value: input[2], }, ], }, ], } satisfies FailureDataset>); }); test('with abort early', () => { expect( schema['~run']({ value: [123, 456, 'true'] }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: [], issues: [{ ...stringIssue, abortEarly: true }], } satisfies FailureDataset>); }); test('for wrong nested items', () => { const nestedSchema = tuple([schema, schema]); const input: [[string, string, boolean], null] = [ ['foo', '123', false], null, ]; expect(nestedSchema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: '123', expected: 'number', received: '"123"', path: [ { type: 'array', origin: 'value', input: input, key: 0, value: input[0], }, { type: 'array', origin: 'value', input: input[0], key: 1, value: input[0][1], }, ], }, { ...baseInfo, kind: 'schema', type: 'tuple', input: null, expected: 'Array', received: 'null', path: [ { type: 'array', origin: 'value', input: input, key: 1, value: input[1], }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/tuple/tuple.ts ================================================ import type { ArrayPathItem, BaseIssue, BaseSchema, ErrorMessage, InferTupleInput, InferTupleIssue, InferTupleOutput, OutputDataset, TupleItems, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { TupleIssue } from './types.ts'; /** * Tuple schema interface. */ export interface TupleSchema< TItems extends TupleItems, TMessage extends ErrorMessage | undefined, > extends BaseSchema< InferTupleInput, InferTupleOutput, TupleIssue | InferTupleIssue > { /** * The schema type. */ readonly type: 'tuple'; /** * The schema reference. */ readonly reference: typeof tuple; /** * The expected property. */ readonly expects: 'Array'; /** * The items schema. */ readonly items: TItems; /** * The error message. */ readonly message: TMessage; } /** * Creates a tuple schema. * * Hint: This schema removes unknown items. The output will only include the * items you specify. To include unknown items, use `looseTuple`. To * return an issue for unknown items, use `strictTuple`. To include and * validate unknown items, use `tupleWithRest`. * * @param items The items schema. * * @returns A tuple schema. */ export function tuple( items: TItems ): TupleSchema; /** * Creates a tuple schema. * * Hint: This schema removes unknown items. The output will only include the * items you specify. To include unknown items, use `looseTuple`. To * return an issue for unknown items, use `strictTuple`. To include and * validate unknown items, use `tupleWithRest`. * * @param items The items schema. * @param message The error message. * * @returns A tuple schema. */ export function tuple< const TItems extends TupleItems, const TMessage extends ErrorMessage | undefined, >(items: TItems, message: TMessage): TupleSchema; // @__NO_SIDE_EFFECTS__ export function tuple( items: TupleItems, message?: ErrorMessage ): TupleSchema | undefined> { return { kind: 'schema', type: 'tuple', reference: tuple, expects: 'Array', async: false, items, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (Array.isArray(input)) { // Set typed to `true` and value to empty array // @ts-expect-error dataset.typed = true; dataset.value = []; // Parse schema of each tuple item for (let key = 0; key < this.items.length; key++) { const value = input[key]; const itemDataset = this.items[key]['~run']({ value }, config); // If there are issues, capture them if (itemDataset.issues) { // Create tuple path item const pathItem: ArrayPathItem = { type: 'array', origin: 'value', input, key, value, }; // Add modified item dataset issues to issues for (const issue of itemDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = itemDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!itemDataset.typed) { dataset.typed = false; } // Add item to dataset // @ts-expect-error dataset.value.push(itemDataset.value); } // Otherwise, add tuple issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< unknown[], TupleIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/tuple/tupleAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { boolean } from '../boolean/index.ts'; import { number, type NumberIssue, type NumberSchema, } from '../number/index.ts'; import type { OptionalSchema } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { tupleAsync, type TupleSchemaAsync } from './tupleAsync.ts'; import type { TupleIssue } from './types.ts'; describe('tupleAsync', () => { describe('should return schema object', () => { const items = [string(), number(), boolean()] as const; type Items = typeof items; test('with undefined message', () => { type Schema = TupleSchemaAsync; expectTypeOf(tupleAsync(items)).toEqualTypeOf(); expectTypeOf(tupleAsync(items, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(tupleAsync(items, 'message')).toEqualTypeOf< TupleSchemaAsync >(); }); test('with function message', () => { expectTypeOf(tupleAsync(items, () => 'message')).toEqualTypeOf< TupleSchemaAsync string> >(); }); }); describe('should infer correct types', () => { type Schema = TupleSchemaAsync< [OptionalSchema, 'foo'>, NumberSchema], undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf< [string | undefined, number] >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf<[string, number]>(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< TupleIssue | StringIssue | NumberIssue >(); }); }); }); ================================================ FILE: library/src/schemas/tuple/tupleAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { boolean } from '../boolean/boolean.ts'; import { number } from '../number/index.ts'; import { optionalAsync } from '../optional/index.ts'; import { string, type StringIssue } from '../string/index.ts'; import { tupleAsync, type TupleSchemaAsync } from './tupleAsync.ts'; import type { TupleIssue } from './types.ts'; describe('tupleAsync', () => { describe('should return schema object', () => { const items = [optionalAsync(string()), number()] as const; type Items = typeof items; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'tuple', reference: tupleAsync, expects: 'Array', items, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: TupleSchemaAsync = { ...baseSchema, message: undefined, }; expect(tupleAsync(items)).toStrictEqual(schema); expect(tupleAsync(items, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(tupleAsync(items, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies TupleSchemaAsync); }); test('with function message', () => { const message = () => 'message'; expect(tupleAsync(items, message)).toStrictEqual({ ...baseSchema, message, } satisfies TupleSchemaAsync); }); }); describe('should return dataset without issues', () => { test('for empty tuple', async () => { await await expectNoSchemaIssueAsync(tupleAsync([]), [[]]); }); const schema = tupleAsync([optionalAsync(string()), number()]); test('for simple tuple', async () => { await await expectNoSchemaIssueAsync(schema, [ ['foo', 123], [undefined, 123], ]); }); test('for unknown items', async () => { expect( await schema['~run']({ value: ['foo', 123, null, true, undefined] }, {}) ).toStrictEqual({ typed: true, value: ['foo', 123], }); }); }); describe('should return dataset with issues', () => { const schema = tupleAsync([optionalAsync(string()), number()], 'message'); const baseIssue: Omit = { kind: 'schema', type: 'tuple', expected: 'Array', message: 'message', }; // Primitive types test('for bigints', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', async () => { await expectSchemaIssueAsync(schema, baseIssue, [true, false]); }); test('for null', async () => { await expectSchemaIssueAsync(schema, baseIssue, [null]); }); test('for numbers', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', async () => { await expectSchemaIssueAsync(schema, baseIssue, [undefined]); }); test('for strings', async () => { await expectSchemaIssueAsync(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ Symbol(), Symbol('foo'), ]); }); // Complex types test('for functions', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ // eslint-disable-next-line @typescript-eslint/no-empty-function () => {}, // eslint-disable-next-line @typescript-eslint/no-empty-function function () {}, ]); }); test('for objects', async () => { await expectSchemaIssueAsync(schema, baseIssue, [{}, { key: 'value' }]); }); }); describe('should return dataset without nested issues', () => { const schema = tupleAsync([optionalAsync(string()), number()]); test('for simple tuple', async () => { await expectNoSchemaIssueAsync(schema, [ ['foo', 123], [undefined, 123], ]); }); test('for nested tuple', async () => { await expectNoSchemaIssueAsync(tupleAsync([schema, schema]), [ [ ['foo', 123], [undefined, 123], ], ]); }); test('for unknown items', async () => { expect( await schema['~run']({ value: ['foo', 123, null, true, undefined] }, {}) ).toStrictEqual({ typed: true, value: ['foo', 123], }); }); }); describe('should return dataset with nested issues', () => { const schema = tupleAsync([string(), number(), boolean()]); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const stringIssue: StringIssue = { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'array', origin: 'value', input: [123, 456, 'true'], key: 0, value: 123, }, ], }; test('for wrong items', async () => { const input = [123, 456, 'true']; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ stringIssue, { ...baseInfo, kind: 'schema', type: 'boolean', input: 'true', expected: 'boolean', received: '"true"', path: [ { type: 'array', origin: 'value', input: input, key: 2, value: input[2], }, ], }, ], } satisfies FailureDataset>); }); test('with abort early', async () => { expect( await schema['~run']( { value: [123, 456, 'true'] }, { abortEarly: true } ) ).toStrictEqual({ typed: false, value: [], issues: [{ ...stringIssue, abortEarly: true }], } satisfies FailureDataset>); }); test('for wrong nested items', async () => { const nestedSchema = tupleAsync([schema, schema]); const input: [[string, string, boolean], null] = [ ['foo', '123', false], null, ]; expect(await nestedSchema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: '123', expected: 'number', received: '"123"', path: [ { type: 'array', origin: 'value', input: input, key: 0, value: input[0], }, { type: 'array', origin: 'value', input: input[0], key: 1, value: input[0][1], }, ], }, { ...baseInfo, kind: 'schema', type: 'tuple', input: null, expected: 'Array', received: 'null', path: [ { type: 'array', origin: 'value', input: input, key: 1, value: input[1], }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/tuple/tupleAsync.ts ================================================ import type { ArrayPathItem, BaseIssue, BaseSchemaAsync, ErrorMessage, InferTupleInput, InferTupleIssue, InferTupleOutput, OutputDataset, TupleItemsAsync, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { tuple } from './tuple.ts'; import type { TupleIssue } from './types.ts'; /** * Tuple schema async interface. */ export interface TupleSchemaAsync< TItems extends TupleItemsAsync, TMessage extends ErrorMessage | undefined, > extends BaseSchemaAsync< InferTupleInput, InferTupleOutput, TupleIssue | InferTupleIssue > { /** * The schema type. */ readonly type: 'tuple'; /** * The schema reference. */ readonly reference: typeof tuple | typeof tupleAsync; /** * The expected property. */ readonly expects: 'Array'; /** * The items schema. */ readonly items: TItems; /** * The error message. */ readonly message: TMessage; } /** * Creates a tuple schema. * * Hint: This schema removes unknown items. The output will only include the * items you specify. To include unknown items, use `looseTupleAsync`. To * return an issue for unknown items, use `strictTupleAsync`. To include and * validate unknown items, use `tupleWithRestAsync`. * * @param items The items schema. * * @returns A tuple schema. */ export function tupleAsync( items: TItems ): TupleSchemaAsync; /** * Creates a tuple schema. * * Hint: This schema removes unknown items. The output will only include the * items you specify. To include unknown items, use `looseTupleAsync`. To * return an issue for unknown items, use `strictTupleAsync`. To include and * validate unknown items, use `tupleWithRestAsync`. * * @param items The items schema. * @param message The error message. * * @returns A tuple schema. */ export function tupleAsync< const TItems extends TupleItemsAsync, const TMessage extends ErrorMessage | undefined, >(items: TItems, message: TMessage): TupleSchemaAsync; // @__NO_SIDE_EFFECTS__ export function tupleAsync( items: TupleItemsAsync, message?: ErrorMessage ): TupleSchemaAsync | undefined> { return { kind: 'schema', type: 'tuple', reference: tupleAsync, expects: 'Array', async: true, items, message, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (Array.isArray(input)) { // Set typed to `true` and value to empty array // @ts-expect-error dataset.typed = true; dataset.value = []; // Parse schema of each tuple item const itemDatasets = await Promise.all( this.items.map(async (item, key) => { const value = input[key]; return [key, value, await item['~run']({ value }, config)] as const; }) ); // Process each tuple item dataset for (const [key, value, itemDataset] of itemDatasets) { // If there are issues, capture them if (itemDataset.issues) { // Create tuple path item const pathItem: ArrayPathItem = { type: 'array', origin: 'value', input, key, value, }; // Add modified item dataset issues to issues for (const issue of itemDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = itemDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!itemDataset.typed) { dataset.typed = false; } // Add item to dataset // @ts-expect-error dataset.value.push(itemDataset.value); } // Otherwise, add tuple issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< unknown[], TupleIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/tuple/types.ts ================================================ import type { BaseIssue } from '../../types/index.ts'; /** * Tuple issue interface. */ export interface TupleIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'tuple'; /** * The expected property. */ readonly expected: 'Array'; } ================================================ FILE: library/src/schemas/tupleWithRest/index.ts ================================================ export * from './tupleWithRest.ts'; export * from './tupleWithRestAsync.ts'; export * from './types.ts'; ================================================ FILE: library/src/schemas/tupleWithRest/tupleWithRest.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { boolean, type BooleanIssue, type BooleanSchema, } from '../boolean/index.ts'; import { null_ } from '../null/index.ts'; import { number, type NumberIssue, type NumberSchema, } from '../number/index.ts'; import type { OptionalSchema } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { tupleWithRest, type TupleWithRestSchema } from './tupleWithRest.ts'; import type { TupleWithRestIssue } from './types.ts'; describe('tupleWithRest', () => { describe('should return schema object', () => { const items = [string(), number(), boolean()] as const; type Items = typeof items; const rest = null_(); type Rest = typeof rest; test('with undefined message', () => { type Schema = TupleWithRestSchema; expectTypeOf(tupleWithRest(items, rest)).toEqualTypeOf(); expectTypeOf( tupleWithRest(items, rest, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(tupleWithRest(items, rest, 'message')).toEqualTypeOf< TupleWithRestSchema >(); }); test('with function message', () => { expectTypeOf(tupleWithRest(items, rest, () => 'message')).toEqualTypeOf< TupleWithRestSchema string> >(); }); }); describe('should infer correct types', () => { type Schema = TupleWithRestSchema< [OptionalSchema, 'foo'>, NumberSchema], OptionalSchema, false>, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf< [string | undefined, number, ...(boolean | undefined)[]] >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< [string, number, ...boolean[]] >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< TupleWithRestIssue | StringIssue | NumberIssue | BooleanIssue >(); }); }); }); ================================================ FILE: library/src/schemas/tupleWithRest/tupleWithRest.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { boolean } from '../boolean/index.ts'; import { null_, type NullIssue } from '../null/index.ts'; import { number } from '../number/index.ts'; import { object } from '../object/index.ts'; import { optional } from '../optional/index.ts'; import { string, type StringIssue } from '../string/index.ts'; import { tupleWithRest, type TupleWithRestSchema } from './tupleWithRest.ts'; import type { TupleWithRestIssue } from './types.ts'; describe('tupleWithRest', () => { describe('should return schema object', () => { const items = [optional(string()), number()] as const; type Items = typeof items; const rest = null_(); type Rest = typeof rest; const baseSchema: Omit< TupleWithRestSchema, 'message' > = { kind: 'schema', type: 'tuple_with_rest', reference: tupleWithRest, expects: 'Array', items, rest, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: TupleWithRestSchema = { ...baseSchema, message: undefined, }; expect(tupleWithRest(items, rest)).toStrictEqual(schema); expect(tupleWithRest(items, rest, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(tupleWithRest(items, rest, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies TupleWithRestSchema); }); test('with function message', () => { const message = () => 'message'; expect(tupleWithRest(items, rest, message)).toStrictEqual({ ...baseSchema, message, } satisfies TupleWithRestSchema); }); }); describe('should return dataset without issues', () => { test('for empty tuple', () => { expectNoSchemaIssue(tupleWithRest([], null_()), [[]]); }); const schema = tupleWithRest([optional(string()), number()], null_()); test('for simple tuple', () => { expectNoSchemaIssue(schema, [ ['foo', 123], [undefined, 123], ]); }); test('for rest items', () => { expectNoSchemaIssue(schema, [ [undefined, 123, null], ['foo', 123, null, null, null, null], ]); }); }); describe('should return dataset with issues', () => { const schema = tupleWithRest( [optional(string()), number()], null_(), 'message' ); const baseIssue: Omit = { kind: 'schema', type: 'tuple_with_rest', expected: 'Array', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectSchemaIssue(schema, baseIssue, [undefined]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); describe('should return dataset without nested issues', () => { const schema = tupleWithRest([optional(string()), number()], null_()); test('for simple tuple', () => { expectNoSchemaIssue(schema, [ ['foo', 123], [undefined, 123], ]); }); test('for nested tuple', () => { expectNoSchemaIssue(tupleWithRest([schema, schema], null_()), [ [['foo', 123], [undefined, 123, null, null], null], ]); }); test('for rest items', () => { expectNoSchemaIssue(schema, [ [undefined, 123, null], ['foo', 123, null, null, null, null], ]); }); }); describe('should return dataset with nested issues', () => { const schema = tupleWithRest([string(), number(), boolean()], null_()); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const input = [123, 456, 'true', null, null, null]; const stringIssue: StringIssue = { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'array', origin: 'value', input, key: 0, value: 123, }, ], }; test('for invalid items', () => { expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ stringIssue, { ...baseInfo, kind: 'schema', type: 'boolean', input: 'true', expected: 'boolean', received: '"true"', path: [ { type: 'array', origin: 'value', input: input, key: 2, value: input[2], }, ], }, ], } satisfies FailureDataset>); }); test('with abort early', () => { expect( schema['~run']({ value: input }, { abortEarly: true }) ).toStrictEqual({ typed: false, value: [], issues: [{ ...stringIssue, abortEarly: true }], } satisfies FailureDataset>); }); test('for invalid nested items', () => { const nestedSchema = tupleWithRest([schema, schema], null_()); const input: [[string, string, boolean], null, null] = [ ['foo', '123', false], null, null, ]; expect(nestedSchema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: '123', expected: 'number', received: '"123"', path: [ { type: 'array', origin: 'value', input: input, key: 0, value: input[0], }, { type: 'array', origin: 'value', input: input[0], key: 1, value: input[0][1], }, ], }, { ...baseInfo, kind: 'schema', type: 'tuple_with_rest', input: null, expected: 'Array', received: 'null', path: [ { type: 'array', origin: 'value', input: input, key: 1, value: input[1], }, ], }, ], } satisfies FailureDataset>); }); const nullIssue: NullIssue = { ...baseInfo, kind: 'schema', type: 'null', input: 'null', expected: 'null', received: '"null"', path: [ { type: 'array', origin: 'value', input: ['foo', 456, true, null, 'null', null, undefined], key: 4, value: 'null', }, ], }; test('for invalid rest', () => { const input = ['foo', 456, true, null, 'null', null, undefined]; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ nullIssue, { ...baseInfo, kind: 'schema', type: 'null', input: undefined, expected: 'null', received: 'undefined', path: [ { type: 'array', origin: 'value', input: input, key: 6, value: input[6], }, ], }, ], } satisfies FailureDataset>); }); test('for invalid rest with abort early', () => { expect( schema['~run']( { value: ['foo', 456, true, null, 'null', null, undefined] }, { abortEarly: true } ) ).toStrictEqual({ typed: false, value: ['foo', 456, true, null], issues: [{ ...nullIssue, abortEarly: true }], } satisfies FailureDataset>); }); test('for invalid nested rest', () => { const nestedSchema = tupleWithRest([string()], object({ key: number() })); const input = [ 'foo', { key: '123' }, { key: 456 }, { key: null }, ] as const; expect(nestedSchema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: '123', expected: 'number', received: '"123"', path: [ { type: 'array', origin: 'value', input: input, key: 1, value: input[1], }, { type: 'object', origin: 'value', input: input[1], key: 'key', value: input[1].key, }, ], }, { ...baseInfo, kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', path: [ { type: 'array', origin: 'value', input: input, key: 3, value: input[3], }, { type: 'object', origin: 'value', input: input[3], key: 'key', value: input[3].key, }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/tupleWithRest/tupleWithRest.ts ================================================ import type { ArrayPathItem, BaseIssue, BaseSchema, ErrorMessage, InferInput, InferIssue, InferOutput, InferTupleInput, InferTupleIssue, InferTupleOutput, OutputDataset, TupleItems, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { TupleWithRestIssue } from './types.ts'; /** * Tuple with rest schema interface. */ export interface TupleWithRestSchema< TItems extends TupleItems, TRest extends BaseSchema>, TMessage extends ErrorMessage | undefined, > extends BaseSchema< [...InferTupleInput, ...InferInput[]], [...InferTupleOutput, ...InferOutput[]], TupleWithRestIssue | InferTupleIssue | InferIssue > { /** * The schema type. */ readonly type: 'tuple_with_rest'; /** * The schema reference. */ readonly reference: typeof tupleWithRest; /** * The expected property. */ readonly expects: 'Array'; /** * The items schema. */ readonly items: TItems; /** * The rest schema. */ readonly rest: TRest; /** * The error message. */ readonly message: TMessage; } /** * Creates a tuple with rest schema. * * @param items The items schema. * @param rest The rest schema. * * @returns A tuple with rest schema. */ export function tupleWithRest< const TItems extends TupleItems, const TRest extends BaseSchema>, >(items: TItems, rest: TRest): TupleWithRestSchema; /** * Creates a tuple with rest schema. * * @param items The items schema. * @param rest The rest schema. * @param message The error message. * * @returns A tuple with rest schema. */ export function tupleWithRest< const TItems extends TupleItems, const TRest extends BaseSchema>, const TMessage extends ErrorMessage | undefined, >( items: TItems, rest: TRest, message: TMessage ): TupleWithRestSchema; // @__NO_SIDE_EFFECTS__ export function tupleWithRest( items: TupleItems, rest: BaseSchema>, message?: ErrorMessage ): TupleWithRestSchema< TupleItems, BaseSchema>, ErrorMessage | undefined > { return { kind: 'schema', type: 'tuple_with_rest', reference: tupleWithRest, expects: 'Array', async: false, items, rest, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (Array.isArray(input)) { // Set typed to `true` and value to empty array // @ts-expect-error dataset.typed = true; dataset.value = []; // Parse schema of each tuple item for (let key = 0; key < this.items.length; key++) { const value = input[key]; const itemDataset = this.items[key]['~run']({ value }, config); // If there are issues, capture them if (itemDataset.issues) { // Create tuple path item const pathItem: ArrayPathItem = { type: 'array', origin: 'value', input, key, value, }; // Add modified item dataset issues to issues for (const issue of itemDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = itemDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!itemDataset.typed) { dataset.typed = false; } // Add item to dataset // @ts-expect-error dataset.value.push(itemDataset.value); } // Parse rest with schema if necessary if (!dataset.issues || !config.abortEarly) { for (let key = this.items.length; key < input.length; key++) { const value = input[key]; const itemDataset = this.rest['~run']({ value }, config); // If there are issues, capture them if (itemDataset.issues) { // Create tuple path item const pathItem: ArrayPathItem = { type: 'array', origin: 'value', input, key, value, }; // Add modified item dataset issues to issues for (const issue of itemDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = itemDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!itemDataset.typed) { dataset.typed = false; } // Add item to dataset // @ts-expect-error dataset.value.push(itemDataset.value); } } // Otherwise, add tuple issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< unknown[], TupleWithRestIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/tupleWithRest/tupleWithRestAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { boolean, type BooleanIssue, type BooleanSchema, } from '../boolean/index.ts'; import { null_ } from '../null/index.ts'; import { number, type NumberIssue, type NumberSchema, } from '../number/index.ts'; import type { OptionalSchema } from '../optional/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { tupleWithRestAsync, type TupleWithRestSchemaAsync, } from './tupleWithRestAsync.ts'; import type { TupleWithRestIssue } from './types.ts'; describe('tupleWithRestAsync', () => { describe('should return schema object', () => { const items = [string(), number(), boolean()] as const; type Items = typeof items; const rest = null_(); type Rest = typeof rest; test('with undefined message', () => { type Schema = TupleWithRestSchemaAsync; expectTypeOf(tupleWithRestAsync(items, rest)).toEqualTypeOf(); expectTypeOf( tupleWithRestAsync(items, rest, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(tupleWithRestAsync(items, rest, 'message')).toEqualTypeOf< TupleWithRestSchemaAsync >(); }); test('with function message', () => { expectTypeOf( tupleWithRestAsync(items, rest, () => 'message') ).toEqualTypeOf string>>(); }); }); describe('should infer correct types', () => { type Schema = TupleWithRestSchemaAsync< [OptionalSchema, 'foo'>, NumberSchema], OptionalSchema, false>, undefined >; test('of input', () => { expectTypeOf>().toEqualTypeOf< [string | undefined, number, ...(boolean | undefined)[]] >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< [string, number, ...boolean[]] >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< TupleWithRestIssue | StringIssue | NumberIssue | BooleanIssue >(); }); }); }); ================================================ FILE: library/src/schemas/tupleWithRest/tupleWithRestAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { FailureDataset, InferIssue } from '../../types/index.ts'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { boolean } from '../boolean/index.ts'; import { null_, type NullIssue } from '../null/index.ts'; import { number } from '../number/index.ts'; import { objectAsync } from '../object/index.ts'; import { optionalAsync } from '../optional/index.ts'; import { string, type StringIssue } from '../string/index.ts'; import { tupleWithRestAsync, type TupleWithRestSchemaAsync, } from './tupleWithRestAsync.ts'; import type { TupleWithRestIssue } from './types.ts'; describe('tupleWithRestAsync', () => { describe('should return schema object', () => { const items = [optionalAsync(string()), number()] as const; type Items = typeof items; const rest = null_(); type Rest = typeof rest; const baseSchema: Omit< TupleWithRestSchemaAsync, 'message' > = { kind: 'schema', type: 'tuple_with_rest', reference: tupleWithRestAsync, expects: 'Array', items, rest, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: TupleWithRestSchemaAsync = { ...baseSchema, message: undefined, }; expect(tupleWithRestAsync(items, rest)).toStrictEqual(schema); expect(tupleWithRestAsync(items, rest, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(tupleWithRestAsync(items, rest, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies TupleWithRestSchemaAsync); }); test('with function message', () => { const message = () => 'message'; expect(tupleWithRestAsync(items, rest, message)).toStrictEqual({ ...baseSchema, message, } satisfies TupleWithRestSchemaAsync); }); }); describe('should return dataset without issues', () => { test('for empty tuple', async () => { await expectNoSchemaIssueAsync(tupleWithRestAsync([], null_()), [[]]); }); const schema = tupleWithRestAsync( [optionalAsync(string()), number()], null_() ); test('for simple tuple', async () => { await expectNoSchemaIssueAsync(schema, [ ['foo', 123], [undefined, 123], ]); }); test('for rest items', async () => { await expectNoSchemaIssueAsync(schema, [ [undefined, 123, null], ['foo', 123, null, null, null, null], ]); }); }); describe('should return dataset with issues', () => { const schema = tupleWithRestAsync( [optionalAsync(string()), number()], null_(), 'message' ); const baseIssue: Omit = { kind: 'schema', type: 'tuple_with_rest', expected: 'Array', message: 'message', }; // Primitive types test('for bigints', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', async () => { await expectSchemaIssueAsync(schema, baseIssue, [true, false]); }); test('for null', async () => { await expectSchemaIssueAsync(schema, baseIssue, [null]); }); test('for numbers', async () => { await expectSchemaIssueAsync(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for undefined', async () => { await expectSchemaIssueAsync(schema, baseIssue, [undefined]); }); test('for strings', async () => { await expectSchemaIssueAsync(schema, baseIssue, ['', 'abc', '123']); }); test('for symbols', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ Symbol(), Symbol('foo'), ]); }); // Complex types test('for functions', async () => { await expectSchemaIssueAsync(schema, baseIssue, [ // eslint-disable-next-line @typescript-eslint/no-empty-function () => {}, // eslint-disable-next-line @typescript-eslint/no-empty-function function () {}, ]); }); test('for objects', async () => { await expectSchemaIssueAsync(schema, baseIssue, [{}, { key: 'value' }]); }); }); describe('should return dataset without nested issues', () => { const schema = tupleWithRestAsync( [optionalAsync(string()), number()], null_() ); test('for simple tuple', async () => { await expectNoSchemaIssueAsync(schema, [ ['foo', 123], [undefined, 123], ]); }); test('for nested tuple', async () => { await expectNoSchemaIssueAsync( tupleWithRestAsync([schema, schema], null_()), [[['foo', 123], [undefined, 123, null, null], null]] ); }); test('for rest items', async () => { await expectNoSchemaIssueAsync(schema, [ [undefined, 123, null], ['foo', 123, null, null, null, null], ]); }); }); describe('should return dataset with nested issues', () => { const schema = tupleWithRestAsync([string(), number(), boolean()], null_()); const baseInfo = { message: expect.any(String), requirement: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const stringIssue: StringIssue = { ...baseInfo, kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', path: [ { type: 'array', origin: 'value', input: [123, 456, 'true', null, null, null], key: 0, value: 123, }, ], }; test('for invalid items', async () => { const input = [123, 456, 'true', null, null, null]; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ stringIssue, { ...baseInfo, kind: 'schema', type: 'boolean', input: 'true', expected: 'boolean', received: '"true"', path: [ { type: 'array', origin: 'value', input: input, key: 2, value: input[2], }, ], }, ], } satisfies FailureDataset>); }); test('with abort early', async () => { expect( await schema['~run']( { value: [123, 456, 'true', null, null, null] }, { abortEarly: true } ) ).toStrictEqual({ typed: false, value: [], issues: [{ ...stringIssue, abortEarly: true }], } satisfies FailureDataset>); }); test('for invalid nested items', async () => { const nestedSchema = tupleWithRestAsync([schema, schema], null_()); const input: [[string, string, boolean], null, null] = [ ['foo', '123', false], null, null, ]; expect(await nestedSchema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: '123', expected: 'number', received: '"123"', path: [ { type: 'array', origin: 'value', input: input, key: 0, value: input[0], }, { type: 'array', origin: 'value', input: input[0], key: 1, value: input[0][1], }, ], }, { ...baseInfo, kind: 'schema', type: 'tuple_with_rest', input: null, expected: 'Array', received: 'null', path: [ { type: 'array', origin: 'value', input: input, key: 1, value: input[1], }, ], }, ], } satisfies FailureDataset>); }); const nullIssue: NullIssue = { ...baseInfo, kind: 'schema', type: 'null', input: 'null', expected: 'null', received: '"null"', path: [ { type: 'array', origin: 'value', input: ['foo', 456, true, null, 'null', null, undefined], key: 4, value: 'null', }, ], }; test('for invalid rest', async () => { const input = ['foo', 456, true, null, 'null', null, undefined]; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ nullIssue, { ...baseInfo, kind: 'schema', type: 'null', input: undefined, expected: 'null', received: 'undefined', path: [ { type: 'array', origin: 'value', input: input, key: 6, value: input[6], }, ], }, ], } satisfies FailureDataset>); }); test('for invalid rest with abort early', async () => { expect( await schema['~run']( { value: ['foo', 456, true, null, 'null', null, undefined] }, { abortEarly: true } ) ).toStrictEqual({ typed: false, value: ['foo', 456, true, null], issues: [{ ...nullIssue, abortEarly: true }], } satisfies FailureDataset>); }); test('for invalid nested rest', async () => { const nestedSchema = tupleWithRestAsync( [string()], objectAsync({ key: number() }) ); const input = [ 'foo', { key: '123' }, { key: 456 }, { key: null }, ] as const; expect(await nestedSchema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'number', input: '123', expected: 'number', received: '"123"', path: [ { type: 'array', origin: 'value', input: input, key: 1, value: input[1], }, { type: 'object', origin: 'value', input: input[1], key: 'key', value: input[1].key, }, ], }, { ...baseInfo, kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', path: [ { type: 'array', origin: 'value', input: input, key: 3, value: input[3], }, { type: 'object', origin: 'value', input: input[3], key: 'key', value: input[3].key, }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/tupleWithRest/tupleWithRestAsync.ts ================================================ import type { ArrayPathItem, BaseIssue, BaseSchema, BaseSchemaAsync, ErrorMessage, InferInput, InferIssue, InferOutput, InferTupleInput, InferTupleIssue, InferTupleOutput, OutputDataset, TupleItemsAsync, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; import type { tupleWithRest } from './tupleWithRest.ts'; import type { TupleWithRestIssue } from './types.ts'; /** * Tuple with rest schema async interface. */ export interface TupleWithRestSchemaAsync< TItems extends TupleItemsAsync, TRest extends | BaseSchema> | BaseSchemaAsync>, TMessage extends ErrorMessage | undefined, > extends BaseSchemaAsync< [...InferTupleInput, ...InferInput[]], [...InferTupleOutput, ...InferOutput[]], TupleWithRestIssue | InferTupleIssue | InferIssue > { /** * The schema type. */ readonly type: 'tuple_with_rest'; /** * The schema reference. */ readonly reference: typeof tupleWithRest | typeof tupleWithRestAsync; /** * The expected property. */ readonly expects: 'Array'; /** * The items schema. */ readonly items: TItems; /** * The rest schema. */ readonly rest: TRest; /** * The error message. */ readonly message: TMessage; } /** * Creates a tuple with rest schema. * * @param items The items schema. * @param rest The rest schema. * * @returns A tuple with rest schema. */ export function tupleWithRestAsync< const TItems extends TupleItemsAsync, const TRest extends | BaseSchema> | BaseSchemaAsync>, >( items: TItems, rest: TRest ): TupleWithRestSchemaAsync; /** * Creates a tuple with rest schema. * * @param items The items schema. * @param rest The rest schema. * @param message The error message. * * @returns A tuple with rest schema. */ export function tupleWithRestAsync< const TItems extends TupleItemsAsync, const TRest extends | BaseSchema> | BaseSchemaAsync>, const TMessage extends ErrorMessage | undefined, >( items: TItems, rest: TRest, message: TMessage ): TupleWithRestSchemaAsync; // @__NO_SIDE_EFFECTS__ export function tupleWithRestAsync( items: TupleItemsAsync, rest: | BaseSchema> | BaseSchemaAsync>, message?: ErrorMessage ): TupleWithRestSchemaAsync< TupleItemsAsync, | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined > { return { kind: 'schema', type: 'tuple_with_rest', reference: tupleWithRestAsync, expects: 'Array', async: true, items, rest, message, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (Array.isArray(input)) { // Set typed to `true` and value to empty array // @ts-expect-error dataset.typed = true; dataset.value = []; // Parse each normal and rest item const [normalDatasets, restDatasets] = await Promise.all([ // Parse schema of each normal item Promise.all( this.items.map(async (item, key) => { const value = input[key]; return [ key, value, await item['~run']({ value }, config), ] as const; }) ), // Parse other items with rest schema Promise.all( input.slice(this.items.length).map(async (value, key) => { return [ key + this.items.length, value, await this.rest['~run']({ value }, config), ] as const; }) ), ]); // Process each tuple item dataset for (const [key, value, itemDataset] of normalDatasets) { // If there are issues, capture them if (itemDataset.issues) { // Create tuple path item const pathItem: ArrayPathItem = { type: 'array', origin: 'value', input, key, value, }; // Add modified item dataset issues to issues for (const issue of itemDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = itemDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!itemDataset.typed) { dataset.typed = false; } // Add item to dataset // @ts-expect-error dataset.value.push(itemDataset.value); } // Parse rest with schema if necessary if (!dataset.issues || !config.abortEarly) { for (const [key, value, itemDataset] of restDatasets) { // If there are issues, capture them if (itemDataset.issues) { // Create tuple path item const pathItem: ArrayPathItem = { type: 'array', origin: 'value', input, key, value, }; // Add modified item dataset issues to issues for (const issue of itemDataset.issues) { if (issue.path) { issue.path.unshift(pathItem); } else { // @ts-expect-error issue.path = [pathItem]; } // @ts-expect-error dataset.issues?.push(issue); } if (!dataset.issues) { // @ts-expect-error dataset.issues = itemDataset.issues; } // If necessary, abort early if (config.abortEarly) { dataset.typed = false; break; } } // If not typed, set typed to `false` if (!itemDataset.typed) { dataset.typed = false; } // Add item to dataset // @ts-expect-error dataset.value.push(itemDataset.value); } } // Otherwise, add tuple issue } else { _addIssue(this, 'type', dataset, config); } // Return output dataset // @ts-expect-error return dataset as OutputDataset< unknown[], TupleWithRestIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/tupleWithRest/types.ts ================================================ import type { BaseIssue } from '../../types/index.ts'; /** * Tuple with rest issue interface. */ export interface TupleWithRestIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'tuple_with_rest'; /** * The expected property. */ readonly expected: 'Array'; } ================================================ FILE: library/src/schemas/undefined/index.ts ================================================ export * from './undefined.ts'; ================================================ FILE: library/src/schemas/undefined/undefined.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { undefined_, type UndefinedIssue, type UndefinedSchema, } from './undefined.ts'; describe('undefined', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = UndefinedSchema; expectTypeOf(undefined_()).toEqualTypeOf(); expectTypeOf(undefined_(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(undefined_('message')).toEqualTypeOf< UndefinedSchema<'message'> >(); }); test('with function message', () => { expectTypeOf(undefined_(() => 'message')).toEqualTypeOf< UndefinedSchema<() => string> >(); }); }); describe('should infer correct types', () => { type Schema = UndefinedSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/undefined/undefined.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { undefined_, type UndefinedIssue, type UndefinedSchema, } from './undefined.ts'; describe('undefined', () => { describe('should return schema object', () => { const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'undefined', reference: undefined_, expects: 'undefined', async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: UndefinedSchema = { ...baseSchema, message: undefined, }; expect(undefined_()).toStrictEqual(schema); expect(undefined_(undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(undefined_('message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies UndefinedSchema<'message'>); }); test('with function message', () => { const message = () => 'message'; expect(undefined_(message)).toStrictEqual({ ...baseSchema, message, } satisfies UndefinedSchema); }); }); describe('should return dataset without issues', () => { const schema = undefined_(); test('for undefined', () => { expectNoSchemaIssue(schema, [undefined]); }); }); describe('should return dataset with issues', () => { const schema = undefined_('message'); const baseIssue: Omit = { kind: 'schema', type: 'undefined', expected: 'undefined', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'foo', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); }); ================================================ FILE: library/src/schemas/undefined/undefined.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; /** * Undefined issue interface. */ export interface UndefinedIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'undefined'; /** * The expected property. */ readonly expected: 'undefined'; } /** * Undefined schema interface. */ export interface UndefinedSchema< TMessage extends ErrorMessage | undefined, > extends BaseSchema { /** * The schema type. */ readonly type: 'undefined'; /** * The schema reference. */ readonly reference: typeof undefined_; /** * The expected property. */ readonly expects: 'undefined'; /** * The error message. */ readonly message: TMessage; } /** * Creates an undefined schema. * * @returns An undefined schema. */ export function undefined_(): UndefinedSchema; /** * Creates an undefined schema. * * @param message The error message. * * @returns An undefined schema. */ export function undefined_< const TMessage extends ErrorMessage | undefined, >(message: TMessage): UndefinedSchema; // @__NO_SIDE_EFFECTS__ export function undefined_( message?: ErrorMessage ): UndefinedSchema | undefined> { return { kind: 'schema', type: 'undefined', reference: undefined_, expects: 'undefined', async: false, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { if (dataset.value === undefined) { // @ts-expect-error dataset.typed = true; } else { _addIssue(this, 'type', dataset, config); } // @ts-expect-error return dataset as OutputDataset; }, }; } export { undefined_ as undefined }; ================================================ FILE: library/src/schemas/undefinedable/index.ts ================================================ export * from './undefinedable.ts'; export * from './undefinedableAsync.ts'; ================================================ FILE: library/src/schemas/undefinedable/types.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, DefaultAsync, DefaultValue, InferOutput, } from '../../types/index.ts'; /** * Infer undefinedable output type. */ export type InferUndefinedableOutput< TWrapped extends | BaseSchema> | BaseSchemaAsync>, TDefault extends DefaultAsync, > = undefined extends TDefault ? InferOutput | undefined : InferOutput | Extract, undefined>; ================================================ FILE: library/src/schemas/undefinedable/undefinedable.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { TransformAction } from '../../actions/index.ts'; import type { SchemaWithPipe } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { undefinedable, type UndefinedableSchema } from './undefinedable.ts'; describe('undefinedable', () => { describe('should return schema object', () => { test('with undefined default', () => { type Schema = UndefinedableSchema, undefined>; expectTypeOf(undefinedable(string())).toEqualTypeOf(); expectTypeOf(undefinedable(string(), undefined)).toEqualTypeOf(); }); test('with undefined getter default', () => { expectTypeOf(undefinedable(string(), () => undefined)).toEqualTypeOf< UndefinedableSchema, () => undefined> >(); }); test('with value default', () => { expectTypeOf(undefinedable(string(), 'foo')).toEqualTypeOf< UndefinedableSchema, 'foo'> >(); }); test('with value getter default', () => { expectTypeOf(undefinedable(string(), () => 'foo')).toEqualTypeOf< UndefinedableSchema, () => string> >(); }); }); describe('should infer correct types', () => { type Schema1 = UndefinedableSchema, undefined>; type Schema2 = UndefinedableSchema, 'foo'>; type Schema3 = UndefinedableSchema< StringSchema, () => undefined >; type Schema4 = UndefinedableSchema, () => 'foo'>; type Schema5 = UndefinedableSchema< SchemaWithPipe< [StringSchema, TransformAction] >, 'foo' >; test('of input', () => { type Input = string | undefined; expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/undefinedable/undefinedable.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { undefinedable, type UndefinedableSchema } from './undefinedable.ts'; describe('undefinedable', () => { describe('should return schema object', () => { const baseSchema: Omit< UndefinedableSchema, string>, 'default' > = { kind: 'schema', type: 'undefinedable', reference: undefinedable, expects: '(string | undefined)', wrapped: { ...string(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined default', () => { const expected: UndefinedableSchema< StringSchema, undefined > = { ...baseSchema, default: undefined, }; expect(undefinedable(string())).toStrictEqual(expected); expect(undefinedable(string(), undefined)).toStrictEqual(expected); }); test('with undefined getter default', () => { const getter = () => undefined; expect(undefinedable(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies UndefinedableSchema, typeof getter>); }); test('with value default', () => { expect(undefinedable(string(), 'foo')).toStrictEqual({ ...baseSchema, default: 'foo', } satisfies UndefinedableSchema, 'foo'>); }); test('with value getter default', () => { const getter = () => 'foo'; expect(undefinedable(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies UndefinedableSchema, typeof getter>); }); }); describe('should return dataset without issues', () => { const schema = undefinedable(string()); test('for wrapper type', () => { expectNoSchemaIssue(schema, ['', 'foo', '#$%']); }); test('for undefined', () => { expectNoSchemaIssue(schema, [undefined]); }); }); describe('should return dataset with issues', () => { const schema = undefinedable(string('message')); const baseIssue: Omit = { kind: 'schema', type: 'string', expected: 'string', message: 'message', }; test('for invalid wrapper type', () => { expectSchemaIssue(schema, baseIssue, [123, true, {}]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); }); describe('should return dataset without default', () => { test('for undefined default', () => { expectNoSchemaIssue(undefinedable(string()), [undefined, 'foo']); expectNoSchemaIssue(undefinedable(string(), undefined), [ undefined, 'foo', ]); }); test('for wrapper type', () => { expectNoSchemaIssue(undefinedable(string(), 'foo'), ['', 'bar', '#$%']); }); }); describe('should return dataset with default', () => { const schema1 = undefinedable(string(), 'foo'); const schema2 = undefinedable(string(), () => undefined); const schema3 = undefinedable(string(), () => 'foo'); test('for undefined', () => { expect(schema1['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: 'foo', }); expect(schema2['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: undefined, }); expect(schema3['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: 'foo', }); }); }); }); ================================================ FILE: library/src/schemas/undefinedable/undefinedable.ts ================================================ import { getDefault } from '../../methods/index.ts'; import type { BaseIssue, BaseSchema, Default, InferInput, InferIssue, SuccessDataset, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; import type { InferUndefinedableOutput } from './types.ts'; /** * Undefinedable schema interface. */ export interface UndefinedableSchema< TWrapped extends BaseSchema>, TDefault extends Default, > extends BaseSchema< InferInput | undefined, InferUndefinedableOutput, InferIssue > { /** * The schema type. */ readonly type: 'undefinedable'; /** * The schema reference. */ readonly reference: typeof undefinedable; /** * The expected property. */ readonly expects: `(${TWrapped['expects']} | undefined)`; /** * The wrapped schema. */ readonly wrapped: TWrapped; /** * The default value. */ readonly default: TDefault; } /** * Creates an undefinedable schema. * * @param wrapped The wrapped schema. * * @returns An undefinedable schema. */ export function undefinedable< const TWrapped extends BaseSchema>, >(wrapped: TWrapped): UndefinedableSchema; /** * Creates an undefinedable schema. * * @param wrapped The wrapped schema. * @param default_ The default value. * * @returns An undefinedable schema. */ export function undefinedable< const TWrapped extends BaseSchema>, const TDefault extends Default, >( wrapped: TWrapped, default_: TDefault ): UndefinedableSchema; // @__NO_SIDE_EFFECTS__ export function undefinedable( wrapped: BaseSchema>, default_?: unknown ): UndefinedableSchema< BaseSchema>, unknown > { return { kind: 'schema', type: 'undefinedable', reference: undefinedable, expects: `(${wrapped.expects} | undefined)`, async: false, wrapped, default: default_, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // If value is `undefined`, override it with default or return dataset if (dataset.value === undefined) { // If default is specified, override value of dataset if (this.default !== undefined) { dataset.value = getDefault(this, dataset, config); } // If value is still `undefined`, return dataset if (dataset.value === undefined) { // @ts-expect-error dataset.typed = true; // @ts-expect-error return dataset as SuccessDataset; } } // Otherwise, return dataset of wrapped schema return this.wrapped['~run'](dataset, config); }, }; } ================================================ FILE: library/src/schemas/undefinedable/undefinedableAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { TransformActionAsync } from '../../actions/index.ts'; import type { SchemaWithPipeAsync } from '../../methods/index.ts'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { undefinedableAsync, type UndefinedableSchemaAsync, } from './undefinedableAsync.ts'; describe('undefinedableAsync', () => { describe('should return schema object', () => { test('with undefined default', () => { type Schema = UndefinedableSchemaAsync< StringSchema, undefined >; expectTypeOf(undefinedableAsync(string())).toEqualTypeOf(); expectTypeOf( undefinedableAsync(string(), undefined) ).toEqualTypeOf(); }); test('with undefined getter default', () => { expectTypeOf(undefinedableAsync(string(), () => undefined)).toEqualTypeOf< UndefinedableSchemaAsync, () => undefined> >(); }); test('with async undefined getter default', () => { expectTypeOf( undefinedableAsync(string(), async () => undefined) ).toEqualTypeOf< UndefinedableSchemaAsync< StringSchema, () => Promise > >(); }); test('with value default', () => { expectTypeOf(undefinedableAsync(string(), 'foo')).toEqualTypeOf< UndefinedableSchemaAsync, 'foo'> >(); }); test('with value getter default', () => { expectTypeOf(undefinedableAsync(string(), () => 'foo')).toEqualTypeOf< UndefinedableSchemaAsync, () => string> >(); }); test('with async value getter default', () => { expectTypeOf( undefinedableAsync(string(), async () => 'foo') ).toEqualTypeOf< UndefinedableSchemaAsync, () => Promise> >(); }); }); describe('should infer correct types', () => { type Schema1 = UndefinedableSchemaAsync, undefined>; type Schema2 = UndefinedableSchemaAsync, 'foo'>; type Schema3 = UndefinedableSchemaAsync< StringSchema, () => undefined >; type Schema4 = UndefinedableSchemaAsync< StringSchema, () => 'foo' >; type Schema5 = UndefinedableSchemaAsync< StringSchema, () => Promise >; type Schema6 = UndefinedableSchemaAsync< StringSchema, () => Promise<'foo'> >; type Schema7 = UndefinedableSchemaAsync< SchemaWithPipeAsync< [StringSchema, TransformActionAsync] >, 'foo' >; test('of input', () => { type Input = string | undefined; expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/undefinedable/undefinedableAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { string, type StringIssue, type StringSchema, } from '../string/index.ts'; import { undefinedableAsync, type UndefinedableSchemaAsync, } from './undefinedableAsync.ts'; describe('undefinedableAsync', () => { describe('should return schema object', () => { const baseSchema: Omit< UndefinedableSchemaAsync, string>, 'default' > = { kind: 'schema', type: 'undefinedable', reference: undefinedableAsync, expects: '(string | undefined)', wrapped: { ...string(), '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined default', () => { const expected: UndefinedableSchemaAsync< StringSchema, undefined > = { ...baseSchema, default: undefined, }; expect(undefinedableAsync(string())).toStrictEqual(expected); expect(undefinedableAsync(string(), undefined)).toStrictEqual(expected); }); test('with undefined getter default', () => { const getter = () => undefined; expect(undefinedableAsync(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies UndefinedableSchemaAsync< StringSchema, typeof getter >); }); test('with async undefined getter default', () => { const getter = async () => undefined; expect(undefinedableAsync(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies UndefinedableSchemaAsync< StringSchema, typeof getter >); }); test('with value default', () => { expect(undefinedableAsync(string(), 'foo')).toStrictEqual({ ...baseSchema, default: 'foo', } satisfies UndefinedableSchemaAsync, 'foo'>); }); test('with value getter default', () => { const getter = () => 'foo'; expect(undefinedableAsync(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies UndefinedableSchemaAsync< StringSchema, typeof getter >); }); test('with async value getter default', () => { const getter = async () => 'foo'; expect(undefinedableAsync(string(), getter)).toStrictEqual({ ...baseSchema, default: getter, } satisfies UndefinedableSchemaAsync< StringSchema, typeof getter >); }); }); describe('should return dataset without issues', () => { const schema = undefinedableAsync(string()); test('for wrapper type', async () => { await expectNoSchemaIssueAsync(schema, ['', 'foo', '#$%']); }); test('for undefined', async () => { await expectNoSchemaIssueAsync(schema, [undefined]); }); }); describe('should return dataset with issues', () => { const schema = undefinedableAsync(string('message')); const baseIssue: Omit = { kind: 'schema', type: 'string', expected: 'string', message: 'message', }; test('for invalid wrapper type', async () => { await expectSchemaIssueAsync(schema, baseIssue, [123, true, {}]); }); test('for null', async () => { await expectSchemaIssueAsync(schema, baseIssue, [null]); }); }); describe('should return dataset without default', () => { test('for undefined default', async () => { await expectNoSchemaIssueAsync(undefinedableAsync(string()), [ undefined, 'foo', ]); await expectNoSchemaIssueAsync(undefinedableAsync(string(), undefined), [ undefined, 'foo', ]); }); test('for wrapper type', async () => { await expectNoSchemaIssueAsync(undefinedableAsync(string(), 'foo'), [ '', 'bar', '#$%', ]); }); }); describe('should return dataset with default', () => { const schema1 = undefinedableAsync(string(), 'foo'); const schema2 = undefinedableAsync(string(), () => undefined); const schema3 = undefinedableAsync(string(), () => 'foo'); const schema4 = undefinedableAsync(string(), async () => undefined); const schema5 = undefinedableAsync(string(), async () => 'foo'); test('for undefined', async () => { expect(await schema1['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: 'foo', }); expect(await schema2['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: undefined, }); expect(await schema3['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: 'foo', }); expect(await schema4['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: undefined, }); expect(await schema5['~run']({ value: undefined }, {})).toStrictEqual({ typed: true, value: 'foo', }); }); }); }); ================================================ FILE: library/src/schemas/undefinedable/undefinedableAsync.ts ================================================ import { getDefault } from '../../methods/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, DefaultAsync, InferInput, InferIssue, SuccessDataset, } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; import type { InferUndefinedableOutput } from './types.ts'; import type { undefinedable } from './undefinedable.ts'; /** * Undefinedable schema async interface. */ export interface UndefinedableSchemaAsync< TWrapped extends | BaseSchema> | BaseSchemaAsync>, TDefault extends DefaultAsync, > extends BaseSchemaAsync< InferInput | undefined, InferUndefinedableOutput, InferIssue > { /** * The schema type. */ readonly type: 'undefinedable'; /** * The schema reference. */ readonly reference: typeof undefinedable | typeof undefinedableAsync; /** * The expected property. */ readonly expects: `(${TWrapped['expects']} | undefined)`; /** * The wrapped schema. */ readonly wrapped: TWrapped; /** * The default value. */ readonly default: TDefault; } /** * Creates an undefinedable schema. * * @param wrapped The wrapped schema. * * @returns An undefinedable schema. */ export function undefinedableAsync< const TWrapped extends | BaseSchema> | BaseSchemaAsync>, >(wrapped: TWrapped): UndefinedableSchemaAsync; /** * Creates an undefinedable schema. * * @param wrapped The wrapped schema. * @param default_ The default value. * * @returns An undefinedable schema. */ export function undefinedableAsync< const TWrapped extends | BaseSchema> | BaseSchemaAsync>, const TDefault extends DefaultAsync, >( wrapped: TWrapped, default_: TDefault ): UndefinedableSchemaAsync; // @__NO_SIDE_EFFECTS__ export function undefinedableAsync( wrapped: | BaseSchema> | BaseSchemaAsync>, default_?: unknown ): UndefinedableSchemaAsync< | BaseSchema> | BaseSchemaAsync>, unknown > { return { kind: 'schema', type: 'undefinedable', reference: undefinedableAsync, expects: `(${wrapped.expects} | undefined)`, async: true, wrapped, default: default_, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // If value is `undefined`, override it with default or return dataset if (dataset.value === undefined) { // If default is specified, override value of dataset if (this.default !== undefined) { dataset.value = await getDefault(this, dataset, config); } // If value is still `undefined`, return dataset if (dataset.value === undefined) { // @ts-expect-error dataset.typed = true; // @ts-expect-error return dataset as SuccessDataset; } } // Otherwise, return dataset of wrapped schema return this.wrapped['~run'](dataset, config); }, }; } ================================================ FILE: library/src/schemas/union/index.ts ================================================ export * from './types.ts'; export * from './union.ts'; export * from './unionAsync.ts'; ================================================ FILE: library/src/schemas/union/types.ts ================================================ import type { BaseIssue } from '../../types/index.ts'; /** * Union issue interface. */ export interface UnionIssue> extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'union'; /** * The expected property. */ readonly expected: string; /** * The sub issues. */ readonly issues?: [TSubIssue, ...TSubIssue[]]; } ================================================ FILE: library/src/schemas/union/union.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { literal, type LiteralIssue } from '../literal/index.ts'; import { number, type NumberIssue } from '../number/index.ts'; import type { UnionIssue } from './types.ts'; import { union, type UnionSchema } from './union.ts'; describe('union', () => { const options = [literal('foo'), literal('bar'), number()] as const; type Options = typeof options; describe('should return schema object', () => { test('with undefined message', () => { type Schema = UnionSchema; expectTypeOf(union(options)).toEqualTypeOf(); expectTypeOf(union(options, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(union(options, 'message')).toEqualTypeOf< UnionSchema >(); }); test('with function message', () => { expectTypeOf(union(options, () => 'message')).toEqualTypeOf< UnionSchema string> >(); }); }); describe('should infer correct types', () => { type Schema = UnionSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf< 'foo' | 'bar' | number >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< 'foo' | 'bar' | number >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< UnionIssue | LiteralIssue | NumberIssue >(); }); }); }); ================================================ FILE: library/src/schemas/union/union.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { email, minLength, url } from '../../actions/index.ts'; import { pipe } from '../../methods/index.ts'; import type { FailureDataset, InferIssue, InferOutput, PartialDataset, } from '../../types/index.ts'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { literal } from '../literal/literal.ts'; import { number } from '../number/index.ts'; import { string } from '../string/index.ts'; import { union, type UnionSchema } from './union.ts'; describe('union', () => { describe('should return schema object', () => { const options = [literal('foo'), literal('bar'), number()] as const; type Options = typeof options; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'union', reference: union, expects: '("foo" | "bar" | number)', options, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: UnionSchema = { ...baseSchema, message: undefined, }; expect(union(options)).toStrictEqual(schema); expect(union(options, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(union(options, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies UnionSchema); }); test('with function message', () => { const message = () => 'message'; expect(union(options, message)).toStrictEqual({ ...baseSchema, message, } satisfies UnionSchema); }); }); describe('should return dataset without issues', () => { test('for valid values', () => { expectNoSchemaIssue(union([literal('foo'), literal('bar'), number()]), [ 'foo', 'bar', 123, ]); }); }); describe('should return dataset with issues', () => { const baseInfo = { message: expect.any(String), requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('with single typed issue', () => { const schema = union([pipe(string(), minLength(5)), number()]); type Schema = typeof schema; expect(schema['~run']({ value: 'foo' }, {})).toStrictEqual({ typed: true, value: 'foo', issues: [ { ...baseInfo, kind: 'validation', type: 'min_length', input: 'foo', expected: '>=5', received: '3', requirement: 5, }, ], } satisfies PartialDataset, InferIssue>); }); test('with multiple typed issues', () => { const schema = union([pipe(string(), email()), pipe(string(), url())]); type Schema = typeof schema; expect(schema['~run']({ value: 'foo' }, {})).toStrictEqual({ typed: true, value: 'foo', issues: [ { ...baseInfo, kind: 'schema', type: 'union', input: 'foo', // TODO: Investigate if there is a better solution for `expected` // and `received` to prevent such situations that are not logical expected: 'string', received: '"foo"', issues: [ { ...baseInfo, kind: 'validation', type: 'email', input: 'foo', expected: null, received: '"foo"', requirement: expect.any(RegExp), }, { ...baseInfo, kind: 'validation', type: 'url', input: 'foo', expected: null, received: '"foo"', requirement: expect.any(Function), }, ], }, ], } satisfies PartialDataset, InferIssue>); }); test('with zero untyped issue', () => { expectSchemaIssue( union([]), { kind: 'schema', type: 'union', expected: 'never', message: expect.any(String), }, ['foo', 123, null, undefined] ); }); test('with single untyped issue', () => { const schema = union([literal('foo')]); expect(schema['~run']({ value: 'bar' }, {})).toStrictEqual({ typed: false, value: 'bar', issues: [ { ...baseInfo, kind: 'schema', type: 'literal', input: 'bar', expected: '"foo"', received: '"bar"', }, ], } satisfies FailureDataset>); }); test('with multiple typed issues', () => { const schema = union([string(), number()]); expect(schema['~run']({ value: null }, {})).toStrictEqual({ typed: false, value: null, issues: [ { ...baseInfo, kind: 'schema', type: 'union', input: null, expected: '(string | number)', received: 'null', issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', }, { ...baseInfo, kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/union/union.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, FailureDataset, InferInput, InferIssue, InferOutput, MaybeReadonly, OutputDataset, PartialDataset, SuccessDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps, _joinExpects, } from '../../utils/index.ts'; import type { UnionIssue } from './types.ts'; import { _subIssues } from './utils/index.ts'; /** * Union options type. */ export type UnionOptions = MaybeReadonly< BaseSchema>[] >; /** * Union schema interface. */ export interface UnionSchema< TOptions extends UnionOptions, TMessage extends | ErrorMessage>> | undefined, > extends BaseSchema< InferInput, InferOutput, UnionIssue> | InferIssue > { /** * The schema type. */ readonly type: 'union'; /** * The schema reference. */ readonly reference: typeof union; /** * The union options. */ readonly options: TOptions; /** * The error message. */ readonly message: TMessage; } /** * Creates an union schema. * * @param options The union options. * * @returns An union schema. */ export function union( options: TOptions ): UnionSchema; /** * Creates an union schema. * * @param options The union options. * @param message The error message. * * @returns An union schema. */ export function union< const TOptions extends UnionOptions, const TMessage extends | ErrorMessage>> | undefined, >(options: TOptions, message: TMessage): UnionSchema; // @__NO_SIDE_EFFECTS__ export function union( options: UnionOptions, message?: ErrorMessage>> ): UnionSchema< UnionOptions, ErrorMessage>> | undefined > { return { kind: 'schema', type: 'union', reference: union, expects: _joinExpects( options.map((option) => option.expects), '|' ), async: false, options, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // Create variables to collect datasets let validDataset: SuccessDataset | undefined; let typedDatasets: | PartialDataset>[] | undefined; let untypedDatasets: FailureDataset>[] | undefined; // Parse schema of each option and collect datasets for (const schema of this.options) { const optionDataset = schema['~run']({ value: dataset.value }, config); // If typed, add it to valid or typed datasets if (optionDataset.typed) { // If there are issues, add it to typed datasets if (optionDataset.issues) { if (typedDatasets) { typedDatasets.push(optionDataset); } else { typedDatasets = [optionDataset]; } // Otherwise, add it as valid dataset and break loop } else { validDataset = optionDataset; break; } // Otherwise, add it to untyped datasets } else { if (untypedDatasets) { untypedDatasets.push(optionDataset); } else { untypedDatasets = [optionDataset]; } } } // If there is a valid dataset, return it if (validDataset) { return validDataset; } // If there are typed datasets process only those if (typedDatasets) { // If there is only one typed dataset, return it if (typedDatasets.length === 1) { return typedDatasets[0]; } // Otherwise, add issue with typed subissues // Hint: If there is more than one typed dataset, we use a general // union issue with subissues because the issues could contradict // each other. _addIssue(this, 'type', dataset, config, { issues: _subIssues(typedDatasets), }); // And set typed to `true` // @ts-expect-error dataset.typed = true; // Otherwise, if there is exactly one untyped dataset, return it } else if (untypedDatasets?.length === 1) { return untypedDatasets[0]; // Otherwise, add issue with untyped subissues } else { // Hint: If there are zero or more than one untyped results, we use a // general union issue with subissues because the issues could // contradict each other. _addIssue(this, 'type', dataset, config, { issues: _subIssues(untypedDatasets), }); } // Return output dataset // @ts-expect-error return dataset as OutputDataset>; }, }; } ================================================ FILE: library/src/schemas/union/unionAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { literal, type LiteralIssue } from '../literal/index.ts'; import { number, type NumberIssue } from '../number/index.ts'; import type { UnionIssue } from './types.ts'; import { unionAsync, type UnionSchemaAsync } from './unionAsync.ts'; describe('unionAsync', () => { const options = [literal('foo'), literal('bar'), number()] as const; type Options = typeof options; describe('should return schema object', () => { test('with undefined message', () => { type Schema = UnionSchemaAsync; expectTypeOf(unionAsync(options)).toEqualTypeOf(); expectTypeOf(unionAsync(options, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(unionAsync(options, 'message')).toEqualTypeOf< UnionSchemaAsync >(); }); test('with function message', () => { expectTypeOf(unionAsync(options, () => 'message')).toEqualTypeOf< UnionSchemaAsync string> >(); }); }); describe('should infer correct types', () => { type Schema = UnionSchemaAsync; test('of input', () => { expectTypeOf>().toEqualTypeOf< 'foo' | 'bar' | number >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< 'foo' | 'bar' | number >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< UnionIssue | LiteralIssue | NumberIssue >(); }); }); }); ================================================ FILE: library/src/schemas/union/unionAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { email, minLength, url } from '../../actions/index.ts'; import { pipe } from '../../methods/index.ts'; import type { FailureDataset, InferIssue, InferOutput, PartialDataset, } from '../../types/index.ts'; import { expectNoSchemaIssueAsync, expectSchemaIssueAsync, } from '../../vitest/index.ts'; import { literal } from '../literal/literal.ts'; import { number } from '../number/index.ts'; import { string } from '../string/index.ts'; import { unionAsync, type UnionSchemaAsync } from './unionAsync.ts'; describe('unionAsync', () => { describe('should return schema object', () => { const options = [literal('foo'), literal('bar'), number()] as const; type Options = typeof options; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'union', reference: unionAsync, expects: '("foo" | "bar" | number)', options, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: UnionSchemaAsync = { ...baseSchema, message: undefined, }; expect(unionAsync(options)).toStrictEqual(schema); expect(unionAsync(options, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(unionAsync(options, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies UnionSchemaAsync); }); test('with function message', () => { const message = () => 'message'; expect(unionAsync(options, message)).toStrictEqual({ ...baseSchema, message, } satisfies UnionSchemaAsync); }); }); describe('should return dataset without issues', () => { test('for valid values', async () => { await expectNoSchemaIssueAsync( unionAsync([literal('foo'), literal('bar'), number()]), ['foo', 'bar', 123] ); }); }); describe('should return dataset with issues', () => { const baseInfo = { message: expect.any(String), requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('with single typed issue', async () => { const schema = unionAsync([pipe(string(), minLength(5)), number()]); type Schema = typeof schema; expect(await schema['~run']({ value: 'foo' }, {})).toStrictEqual({ typed: true, value: 'foo', issues: [ { ...baseInfo, kind: 'validation', type: 'min_length', input: 'foo', expected: '>=5', received: '3', requirement: 5, }, ], } satisfies PartialDataset, InferIssue>); }); test('with multiple typed issues', async () => { const schema = unionAsync([ pipe(string(), email()), pipe(string(), url()), ]); type Schema = typeof schema; expect(await schema['~run']({ value: 'foo' }, {})).toStrictEqual({ typed: true, value: 'foo', issues: [ { ...baseInfo, kind: 'schema', type: 'union', input: 'foo', // TODO: Investigate if there is a better solution for `expected` // and `received` to prevent such situations that are not logical expected: 'string', received: '"foo"', issues: [ { ...baseInfo, kind: 'validation', type: 'email', input: 'foo', expected: null, received: '"foo"', requirement: expect.any(RegExp), }, { ...baseInfo, kind: 'validation', type: 'url', input: 'foo', expected: null, received: '"foo"', requirement: expect.any(Function), }, ], }, ], } satisfies PartialDataset, InferIssue>); }); test('with zero untyped issue', async () => { await expectSchemaIssueAsync( unionAsync([]), { kind: 'schema', type: 'union', expected: 'never', message: expect.any(String), }, ['foo', 123, null, undefined] ); }); test('with single untyped issue', async () => { const schema = unionAsync([literal('foo')]); expect(await schema['~run']({ value: 'bar' }, {})).toStrictEqual({ typed: false, value: 'bar', issues: [ { ...baseInfo, kind: 'schema', type: 'literal', input: 'bar', expected: '"foo"', received: '"bar"', }, ], } satisfies FailureDataset>); }); test('with multiple typed issues', async () => { const schema = unionAsync([string(), number()]); expect(await schema['~run']({ value: null }, {})).toStrictEqual({ typed: false, value: null, issues: [ { ...baseInfo, kind: 'schema', type: 'union', input: null, expected: '(string | number)', received: 'null', issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', }, { ...baseInfo, kind: 'schema', type: 'number', input: null, expected: 'number', received: 'null', }, ], }, ], } satisfies FailureDataset>); }); }); }); ================================================ FILE: library/src/schemas/union/unionAsync.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, ErrorMessage, FailureDataset, InferInput, InferIssue, InferOutput, MaybeReadonly, OutputDataset, PartialDataset, SuccessDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps, _joinExpects, } from '../../utils/index.ts'; import type { UnionIssue } from './types.ts'; import type { union } from './union.ts'; import { _subIssues } from './utils/index.ts'; /** * Union options async type. */ export type UnionOptionsAsync = MaybeReadonly< ( | BaseSchema> | BaseSchemaAsync> )[] >; /** * Union schema async interface. */ export interface UnionSchemaAsync< TOptions extends UnionOptionsAsync, TMessage extends | ErrorMessage>> | undefined, > extends BaseSchemaAsync< InferInput, InferOutput, UnionIssue> | InferIssue > { /** * The schema type. */ readonly type: 'union'; /** * The schema reference. */ readonly reference: typeof union | typeof unionAsync; /** * The union options. */ readonly options: TOptions; /** * The error message. */ readonly message: TMessage; } /** * Creates an union schema. * * @param options The union options. * * @returns An union schema. */ export function unionAsync( options: TOptions ): UnionSchemaAsync; /** * Creates an union schema. * * @param options The union options. * @param message The error message. * * @returns An union schema. */ export function unionAsync< const TOptions extends UnionOptionsAsync, const TMessage extends | ErrorMessage>> | undefined, >(options: TOptions, message: TMessage): UnionSchemaAsync; // @__NO_SIDE_EFFECTS__ export function unionAsync( options: UnionOptionsAsync, message?: ErrorMessage>> ): UnionSchemaAsync< UnionOptionsAsync, ErrorMessage>> | undefined > { return { kind: 'schema', type: 'union', reference: unionAsync, expects: _joinExpects( options.map((option) => option.expects), '|' ), async: true, options, message, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // Create variables to collect datasets let validDataset: SuccessDataset | undefined; let typedDatasets: | PartialDataset>[] | undefined; let untypedDatasets: FailureDataset>[] | undefined; // Parse schema of each option and collect datasets for (const schema of this.options) { const optionDataset = await schema['~run']( { value: dataset.value }, config ); // If typed, add it to valid or typed datasets if (optionDataset.typed) { // If there are issues, add it to typed datasets if (optionDataset.issues) { if (typedDatasets) { typedDatasets.push(optionDataset); } else { typedDatasets = [optionDataset]; } // Otherwise, add it as valid dataset and break loop } else { validDataset = optionDataset; break; } // Otherwise, add it to untyped datasets } else { if (untypedDatasets) { untypedDatasets.push(optionDataset); } else { untypedDatasets = [optionDataset]; } } } // If there is a valid dataset, return it if (validDataset) { return validDataset; } // If there are typed datasets process only those if (typedDatasets) { // If there is only one typed dataset, return it if (typedDatasets.length === 1) { return typedDatasets[0]; } // Otherwise, add issue with typed subissues // Hint: If there is more than one typed dataset, we use a general // union issue with subissues because the issues could contradict // each other. _addIssue(this, 'type', dataset, config, { issues: _subIssues(typedDatasets), }); // And set typed to `true` // @ts-expect-error dataset.typed = true; // Otherwise, if there is exactly one untyped dataset, return it } else if (untypedDatasets?.length === 1) { return untypedDatasets[0]; // Otherwise, add issue with untyped subissues } else { // Hint: If there are zero or more than one untyped results, we use a // general union issue with subissues because the issues could // contradict each other. _addIssue(this, 'type', dataset, config, { issues: _subIssues(untypedDatasets), }); } // Return output dataset // @ts-expect-error return dataset as OutputDataset>; }, }; } ================================================ FILE: library/src/schemas/union/utils/_subIssues/_subIssues.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { EmailIssue, UrlIssue } from '../../../../actions/index.ts'; import type { PartialDataset } from '../../../../types/index.ts'; import { _subIssues } from './_subIssues.ts'; describe('_subIssues', () => { describe('should return undefined', () => { test('for undefined', () => { expect(_subIssues(undefined)).toBeUndefined(); }); test('for empty array', () => { expect(_subIssues([])).toBeUndefined(); }); test('for undefined issues', () => { expect(_subIssues([{ typed: true, value: 'foo' }])).toBeUndefined(); }); }); describe('should return subissues', () => { const baseInfo = { message: expect.any(String), requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const emailIssue: EmailIssue = { ...baseInfo, kind: 'validation', type: 'email', input: 'foo', expected: null, received: '"foo"', requirement: expect.any(RegExp), }; const urlIssue: UrlIssue = { ...baseInfo, kind: 'validation', type: 'url', input: 'foo', expected: null, received: '"foo"', requirement: expect.any(Function), }; test('for single dataset with single issue', () => { expect( _subIssues([ { typed: true, value: 'foo', issues: [emailIssue], } satisfies PartialDataset>, ]) ).toStrictEqual([emailIssue]); }); test('for single dataset with multiple issues', () => { expect( _subIssues([ { typed: true, value: 'foo', issues: [emailIssue, urlIssue], } satisfies PartialDataset< string, EmailIssue | UrlIssue >, ]) ).toStrictEqual([emailIssue, urlIssue]); }); test('for multiple datasets with single issue', () => { expect( _subIssues([ { typed: true, value: 'foo', issues: [emailIssue], }, { typed: true, value: 'foo', issues: [urlIssue], }, ] satisfies PartialDataset< string, EmailIssue | UrlIssue >[]) ).toStrictEqual([emailIssue, urlIssue]); }); test('for multiple datasets with multiple issues', () => { expect( _subIssues([ { typed: true, value: 'foo', issues: [emailIssue, urlIssue], }, { typed: true, value: 'foo', issues: [emailIssue, urlIssue], }, ] satisfies PartialDataset< string, EmailIssue | UrlIssue >[]) ).toStrictEqual([emailIssue, urlIssue, emailIssue, urlIssue]); }); }); }); ================================================ FILE: library/src/schemas/union/utils/_subIssues/_subIssues.ts ================================================ import type { BaseIssue, OutputDataset } from '../../../../types/index.ts'; /** * Returns the sub issues of the provided datasets for the union issue. * * @param datasets The datasets. * * @returns The sub issues. * * @internal */ // @__NO_SIDE_EFFECTS__ export function _subIssues( datasets: OutputDataset>[] | undefined ): [BaseIssue, ...BaseIssue[]] | undefined { let issues: [BaseIssue, ...BaseIssue[]] | undefined; if (datasets) { for (const dataset of datasets) { if (issues) { // Hint: According to the implementation of `union` and `unionAsync`, // `dataset.issues` can never be `undefined`. issues.push(...dataset.issues!); } else { issues = dataset.issues; } } } return issues; } ================================================ FILE: library/src/schemas/union/utils/_subIssues/index.ts ================================================ export * from './_subIssues.ts'; ================================================ FILE: library/src/schemas/union/utils/index.ts ================================================ export * from './_subIssues/index.ts'; ================================================ FILE: library/src/schemas/unknown/index.ts ================================================ export * from './unknown.ts'; ================================================ FILE: library/src/schemas/unknown/unknown.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { unknown, type UnknownSchema } from './unknown.ts'; describe('unknown', () => { test('should return schema object', () => { expectTypeOf(unknown()).toEqualTypeOf(); }); describe('should infer correct types', () => { test('of input', () => { expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/unknown/unknown.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue } from '../../vitest/index.ts'; import { unknown, type UnknownSchema } from './unknown.ts'; describe('unknown', () => { test('should return schema object', () => { expect(unknown()).toStrictEqual({ kind: 'schema', type: 'unknown', reference: unknown, expects: 'unknown', async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), } satisfies UnknownSchema); }); describe('should return dataset without issues', () => { const schema = unknown(); // Primitive types test('for bigints', () => { expectNoSchemaIssue(schema, [-1n, 0n, 123n]); }); test('for booleans', () => { expectNoSchemaIssue(schema, [true, false]); }); test('for null', () => { expectNoSchemaIssue(schema, [null]); }); test('for numbers', () => { expectNoSchemaIssue(schema, [-1, 0, 123, 45.67]); }); test('for undefined', () => { expectNoSchemaIssue(schema, [undefined]); }); test('for strings', () => { expectNoSchemaIssue(schema, ['', 'foo', '123']); }); test('for symbols', () => { expectNoSchemaIssue(schema, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectNoSchemaIssue(schema, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectNoSchemaIssue(schema, [() => {}, function () {}]); }); test('for objects', () => { expectNoSchemaIssue(schema, [{}, { key: 'value' }]); }); }); }); ================================================ FILE: library/src/schemas/unknown/unknown.ts ================================================ import type { BaseSchema, SuccessDataset } from '../../types/index.ts'; import { _getStandardProps } from '../../utils/index.ts'; /** * Unknown schema interface. */ export interface UnknownSchema extends BaseSchema { /** * The schema type. */ readonly type: 'unknown'; /** * The schema reference. */ readonly reference: typeof unknown; /** * The expected property. */ readonly expects: 'unknown'; } /** * Creates a unknown schema. * * @returns A unknown schema. */ // @__NO_SIDE_EFFECTS__ export function unknown(): UnknownSchema { return { kind: 'schema', type: 'unknown', reference: unknown, expects: 'unknown', async: false, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset) { // @ts-expect-error dataset.typed = true; // @ts-expect-error return dataset as SuccessDataset; }, }; } ================================================ FILE: library/src/schemas/variant/index.ts ================================================ export type { VariantIssue, VariantOptions, VariantOptionsAsync, } from './types.ts'; export * from './variant.ts'; export * from './variantAsync.ts'; ================================================ FILE: library/src/schemas/variant/types.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, ErrorMessage, InferIssue, MaybeReadonly, ObjectEntries, ObjectEntriesAsync, OptionalEntrySchema, OptionalEntrySchemaAsync, } from '../../types/index.ts'; import type { LooseObjectIssue, LooseObjectSchema, LooseObjectSchemaAsync, } from '../looseObject/index.ts'; import type { ObjectIssue, ObjectSchema, ObjectSchemaAsync, } from '../object/index.ts'; import type { ObjectWithRestIssue, ObjectWithRestSchema, ObjectWithRestSchemaAsync, } from '../objectWithRest/index.ts'; import type { StrictObjectIssue, StrictObjectSchema, StrictObjectSchemaAsync, } from '../strictObject/index.ts'; import type { variant } from './variant.ts'; import type { variantAsync } from './variantAsync.ts'; /** * Variant issue interface. */ export interface VariantIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'variant'; /** * The expected property. */ readonly expected: string; } /** * Variant option schema interface. */ export interface VariantOptionSchema extends BaseSchema> { readonly type: 'variant'; readonly reference: typeof variant; readonly key: string; readonly options: VariantOptions; readonly message: ErrorMessage | undefined; } /** * Variant option schema async interface. */ export interface VariantOptionSchemaAsync extends BaseSchemaAsync> { readonly type: 'variant'; readonly reference: typeof variant | typeof variantAsync; readonly key: string; readonly options: VariantOptionsAsync; readonly message: ErrorMessage | undefined; } /** * Variant object entries type. */ type VariantObjectEntries = Record< TKey, BaseSchema> | OptionalEntrySchema > & ObjectEntries; /** * Variant object entries async type. */ type VariantObjectEntriesAsync = Record< TKey, | BaseSchema> | BaseSchemaAsync> | OptionalEntrySchema | OptionalEntrySchemaAsync > & ObjectEntriesAsync; /** * Variant option type. */ type VariantOption = | LooseObjectSchema< VariantObjectEntries, ErrorMessage | undefined > | ObjectSchema< VariantObjectEntries, ErrorMessage | undefined > | ObjectWithRestSchema< VariantObjectEntries, BaseSchema>, ErrorMessage | undefined > | StrictObjectSchema< VariantObjectEntries, ErrorMessage | undefined > | VariantOptionSchema; /** * Variant option async type. */ type VariantOptionAsync = | LooseObjectSchemaAsync< VariantObjectEntriesAsync, ErrorMessage | undefined > | ObjectSchemaAsync< VariantObjectEntriesAsync, ErrorMessage | undefined > | ObjectWithRestSchemaAsync< VariantObjectEntriesAsync, | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined > | StrictObjectSchemaAsync< VariantObjectEntriesAsync, ErrorMessage | undefined > | VariantOptionSchemaAsync; /** * Variant options type. */ export type VariantOptions = MaybeReadonly< VariantOption[] >; /** * Variant options async type. */ export type VariantOptionsAsync = MaybeReadonly< (VariantOption | VariantOptionAsync)[] >; /** * Infer variant issue type. */ export type InferVariantIssue< TOptions extends VariantOptions | VariantOptionsAsync, > = Exclude< InferIssue, { type: 'loose_object' | 'object' | 'object_with_rest' } >; ================================================ FILE: library/src/schemas/variant/variant.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { literal, type LiteralIssue } from '../literal/index.ts'; import { object } from '../object/object.ts'; import { strictObject, type StrictObjectIssue } from '../strictObject/index.ts'; import type { VariantIssue } from './types.ts'; import { variant, type VariantSchema } from './variant.ts'; describe('variant', () => { const key = 'type' as const; type Key = typeof key; const options = [ object({ type: literal('foo') }), strictObject({ type: literal('bar') }), ] as const; type Options = typeof options; describe('should return schema object', () => { test('with undefined message', () => { type Schema = VariantSchema; expectTypeOf(variant(key, options)).toEqualTypeOf(); expectTypeOf(variant(key, options, undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(variant(key, options, 'message')).toEqualTypeOf< VariantSchema >(); }); test('with function message', () => { expectTypeOf(variant(key, options, () => 'message')).toEqualTypeOf< VariantSchema string> >(); }); }); describe('should infer correct types', () => { type Schema = VariantSchema; test('of input', () => { expectTypeOf>().toEqualTypeOf< { type: 'foo' } | { type: 'bar' } >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< { type: 'foo' } | { type: 'bar' } >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< VariantIssue | StrictObjectIssue | LiteralIssue >(); }); }); }); ================================================ FILE: library/src/schemas/variant/variant.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { decimal, email, url } from '../../actions/index.ts'; import { pipe } from '../../methods/index.ts'; import { EMAIL_REGEX } from '../../regex.ts'; import type { FailureDataset, InferIssue, InferOutput, PartialDataset, } from '../../types/index.ts'; import { expectNoSchemaIssue } from '../../vitest/index.ts'; import { bigint } from '../bigint/bigint.ts'; import { boolean } from '../boolean/index.ts'; import { exactOptional } from '../exactOptional/index.ts'; import { literal } from '../literal/literal.ts'; import { null_ } from '../null/null.ts'; import { nullish } from '../nullish/index.ts'; import { number } from '../number/index.ts'; import { object } from '../object/index.ts'; import { optional } from '../optional/index.ts'; import { strictObject } from '../strictObject/index.ts'; import { string } from '../string/index.ts'; import { variant, type VariantSchema } from './variant.ts'; describe('variant', () => { describe('should return schema object', () => { const key = 'type' as const; type Key = typeof key; const options = [ object({ type: literal('foo') }), strictObject({ type: literal('bar') }), ] as const; type Options = typeof options; const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'variant', reference: variant, expects: 'Object', key, options, async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: VariantSchema = { ...baseSchema, message: undefined, }; expect(variant(key, options)).toStrictEqual(schema); expect(variant(key, options, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(variant(key, options, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies VariantSchema); }); test('with function message', () => { const message = () => 'message'; expect(variant(key, options, message)).toStrictEqual({ ...baseSchema, message, } satisfies VariantSchema); }); }); describe('should return dataset without issues', () => { test('for simple variants', () => { expectNoSchemaIssue( variant('type', [ object({ type: literal('foo') }), object({ type: literal('bar') }), object({ type: null_() }), ]), [{ type: 'foo' }, { type: 'bar' }, { type: null }] ); }); test('for same discriminators', () => { expectNoSchemaIssue( variant('type', [ object({ type: literal('foo'), other: string() }), object({ type: literal('foo'), other: number() }), object({ type: literal('foo'), other: boolean() }), ]), [ { type: 'foo', other: 'hello' }, { type: 'foo', other: 123 }, { type: 'foo', other: true }, ] ); }); test('for nested variants', () => { expectNoSchemaIssue( variant('type', [ object({ type: literal('foo') }), variant('type', [ object({ type: literal('bar') }), object({ type: null_() }), ]), ]), [{ type: 'foo' }, { type: 'bar' }, { type: null }] ); }); test('for deeply nested variants', () => { expectNoSchemaIssue( variant('type', [ object({ type: literal('foo') }), variant('type', [ object({ type: literal('bar') }), variant('type', [object({ type: null_() })]), ]), ]), [{ type: 'foo' }, { type: 'bar' }, { type: null }] ); }); test('for optional discriminators', () => { expectNoSchemaIssue( variant('type', [ object({ type: literal('foo') }), object({ type: exactOptional(literal('bar')) }), object({ type: literal('baz') }), ]), [{}, { type: 'bar' }] ); expectNoSchemaIssue( variant('type', [ object({ type: literal('foo') }), object({ type: optional(literal('bar')) }), object({ type: literal('baz') }), ]), [{}, { type: undefined }, { type: 'bar' }] ); expectNoSchemaIssue( variant('type', [ object({ type: literal('foo') }), object({ type: nullish(literal('bar')) }), object({ type: literal('baz') }), ]), [{}, { type: null }, { type: undefined }, { type: 'bar' }] ); }); }); describe('should return dataset with issues', () => { const baseInfo = { message: expect.any(String), requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for invalid base type', () => { const schema = variant('type', [ object({ type: literal('foo') }), object({ type: literal('bar') }), ]); expect(schema['~run']({ value: 'foo' }, {})).toStrictEqual({ typed: false, value: 'foo', issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: 'foo', expected: 'Object', received: '"foo"', }, ], } satisfies FailureDataset>); }); test('for empty options', () => { const schema = variant('type', []); const input = { type: 'foo' }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: input.type, expected: 'never', received: `"${input.type}"`, path: [ { type: 'object', origin: 'value', input, key: 'type', value: input.type, }, ], }, ], } satisfies FailureDataset>); }); test('for missing discriminator', () => { const schema = variant('type', [ object({ type: literal('foo') }), object({ type: literal('bar') }), ]); const input = { other: 123 }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: undefined, expected: '("foo" | "bar")', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'type', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid discriminator', () => { const schema = variant('type', [ object({ type: literal('foo') }), object({ type: literal('bar') }), ]); const input = { type: 'baz' }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: input.type, expected: '("foo" | "bar")', received: `"${input.type}"`, path: [ { type: 'object', origin: 'value', input, key: 'type', value: input.type, }, ], }, ], } satisfies FailureDataset>); }); test('for nested missing discriminator', () => { const schema = variant('type', [ object({ type: literal('foo') }), variant('other', [ object({ type: literal('bar'), other: string() }), object({ type: literal('bar'), other: boolean() }), object({ type: literal('baz'), other: number() }), ]), ]); const input = { type: 'bar' }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: undefined, expected: '(string | boolean)', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'other', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for nested invalid discriminator', () => { const schema = variant('type', [ object({ type: literal('foo') }), variant('other', [ object({ type: literal('bar'), other: string() }), object({ type: literal('bar'), other: boolean() }), object({ type: literal('baz'), other: number() }), ]), ]); const input = { type: 'bar', other: 123 }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: input.other, expected: '(string | boolean)', received: `${input.other}`, path: [ { type: 'object', origin: 'value', input, key: 'other', value: input.other, }, ], }, ], } satisfies FailureDataset>); }); test('for first missing invalid discriminator', () => { const schema = variant('type', [ variant('subType1', [ object({ type: literal('foo'), subType1: literal('foo-1'), other1: string(), }), object({ type: literal('bar'), subType1: literal('bar-1'), other2: string(), }), ]), variant('subType2', [ object({ type: literal('foo'), subType2: literal('foo-2'), other3: string(), }), object({ type: literal('bar'), subType2: literal('bar-2'), other4: string(), }), ]), ]); const input = {}; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: undefined, expected: '("foo" | "bar")', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'type', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for first nested missing discriminator', () => { const schema = variant('type', [ variant('subType1', [ object({ type: literal('foo'), subType1: literal('foo-1'), other1: string(), }), object({ type: literal('bar'), subType1: literal('bar-1'), other2: string(), }), ]), variant('subType2', [ object({ type: literal('foo'), subType2: literal('foo-2'), other3: string(), }), object({ type: literal('bar'), subType2: literal('bar-2'), other4: string(), }), ]), ]); const input = { type: 'bar' }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: undefined, expected: '"bar-1"', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'subType1', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for first nested invalid discriminator', () => { const schema = variant('type', [ variant('subType1', [ object({ type: literal('foo'), subType1: literal('foo-1'), other1: string(), }), object({ type: literal('bar'), subType1: literal('bar-1'), other2: string(), }), ]), variant('subType2', [ object({ type: literal('foo'), subType2: literal('foo-2'), other3: string(), }), object({ type: literal('bar'), subType2: literal('bar-2'), other4: string(), }), ]), ]); const input = { type: 'bar', subType2: 'baz-2' }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: input.subType2, expected: '"bar-2"', received: `"${input.subType2}"`, path: [ { type: 'object', origin: 'value', input, key: 'subType2', value: input.subType2, }, ], }, ], } satisfies FailureDataset>); }); test('for first nested invalid discriminator', () => { const schema = variant('type', [ variant('subType1', [ object({ type: literal('foo'), subType1: literal('foo-1'), other1: string(), }), object({ type: literal('bar'), subType1: literal('bar-1'), other2: string(), }), ]), variant('subType2', [ object({ type: literal('foo'), subType2: literal('foo-2'), other3: string(), }), object({ type: literal('bar'), subType2: literal('bar-2'), other4: string(), }), ]), ]); const input = { type: 'bar', subType1: 'invalid', subType2: 'invalid' }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: input.subType1, expected: '"bar-1"', received: `"${input.subType1}"`, path: [ { type: 'object', origin: 'value', input, key: 'subType1', value: input.subType1, }, ], }, ], } satisfies FailureDataset>); }); test('for first nested invalid discriminator', () => { const schema = variant('type', [ variant('subType1', [ variant('subType2', [ object({ type: literal('foo'), subType1: literal('foo-1'), subType2: literal('foo-2'), other1: string(), }), object({ type: literal('bar'), subType1: literal('bar-1'), subType2: literal('bar-2'), other2: string(), }), ]), ]), variant('subType2', [ object({ type: literal('foo'), subType2: literal('foz-2'), other3: string(), }), object({ type: literal('bar'), subType2: literal('baz-2'), other4: string(), }), ]), ]); const input = { type: 'bar', subType1: 'bar-1', subType2: 'invalid' }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: input.subType2, expected: '("bar-2" | "baz-2")', received: `"${input.subType2}"`, path: [ { type: 'object', origin: 'value', input, key: 'subType2', value: input.subType2, }, ], }, ], } satisfies FailureDataset>); }); test('for first nested invalid discriminator', () => { const schema = variant('type', [ variant('subType2', [ object({ type: literal('foo'), subType2: literal('foz-2'), other3: string(), }), object({ type: literal('bar'), subType2: literal('baz-2'), other4: string(), }), ]), variant('subType1', [ variant('subType2', [ object({ type: literal('foo'), subType1: literal('foo-1'), subType2: literal('foo-2'), other1: string(), }), object({ type: literal('bar'), subType1: literal('bar-1'), subType2: literal('bar-2'), other2: string(), }), ]), ]), ]); const input = { type: 'bar', subType1: 'bar-1', subType2: 'invalid' }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: input.subType2, expected: '("baz-2" | "bar-2")', received: `"${input.subType2}"`, path: [ { type: 'object', origin: 'value', input, key: 'subType2', value: input.subType2, }, ], }, ], } satisfies FailureDataset>); }); test('for first nested invalid discriminator', () => { const schema = variant('type', [ variant('subType1', [ object({ type: literal('foo'), subType1: literal('foo-1'), other1: string(), }), object({ type: literal('bar'), subType1: literal('bar-1'), other2: string(), }), variant('subType2', [ object({ type: literal('bar'), subType1: literal('baz-1'), subType2: literal('baz-2'), other5: string(), }), ]), ]), variant('subType2', [ object({ type: literal('foo'), subType2: literal('foo-2'), other3: string(), }), object({ type: literal('bar'), subType2: literal('bar-2'), other4: string(), }), ]), ]); const input = { type: 'bar', subType2: 'baz-2' }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: input.subType2, expected: '"bar-2"', received: `"${input.subType2}"`, path: [ { type: 'object', origin: 'value', input, key: 'subType2', value: input.subType2, }, ], }, ], } satisfies FailureDataset>); }); test('for untyped object', () => { const schema = variant('type', [ object({ type: literal('foo'), other: bigint() }), object({ type: literal('bar'), other: string() }), object({ type: literal('baz'), other: number() }), ]); const input = { type: 'bar', other: null }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: input.other, expected: 'string', received: `${input.other}`, path: [ { type: 'object', origin: 'value', input, key: 'other', value: input.other, }, ], }, ], } satisfies FailureDataset>); }); test('for nested untyped object', () => { const schema = variant('type', [ object({ type: literal('foo') }), variant('type', [ object({ type: literal('bar'), other: string() }), object({ type: literal('baz'), other: number() }), ]), ]); const input = { type: 'bar', other: null }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: input.other, expected: 'string', received: `${input.other}`, path: [ { type: 'object', origin: 'value', input, key: 'other', value: input.other, }, ], }, ], } satisfies FailureDataset>); }); test('for multiple untyped objects', () => { const schema = variant('type', [ object({ type: literal('foo'), other: bigint() }), object({ type: literal('bar'), other: string() }), object({ type: literal('bar'), other: number() }), object({ type: literal('bar'), other: boolean() }), ]); const input = { type: 'bar', other: null }; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: input.other, expected: 'string', received: `${input.other}`, path: [ { type: 'object', origin: 'value', input, key: 'other', value: input.other, }, ], }, ], } satisfies FailureDataset>); }); test('for typed objects', () => { const schema = variant('type', [ object({ type: literal('foo'), other: number() }), object({ type: literal('bar'), other: pipe(string(), email()) }), object({ type: literal('baz'), other: boolean() }), ]); type Schema = typeof schema; const input = { type: 'bar', other: 'hello' } as const; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: true, value: input, issues: [ { ...baseInfo, kind: 'validation', type: 'email', input: input.other, expected: null, received: `"${input.other}"`, requirement: EMAIL_REGEX, path: [ { type: 'object', origin: 'value', input, key: 'other', value: input.other, }, ], }, ], } satisfies PartialDataset, InferIssue>); }); test('for nested typed objects', () => { const schema = variant('type', [ object({ type: literal('foo'), other: number() }), variant('type', [ object({ type: literal('bar'), other: pipe(string(), email()) }), object({ type: literal('baz'), other: boolean() }), ]), ]); type Schema = typeof schema; const input = { type: 'bar', other: 'hello' } as const; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: true, value: input, issues: [ { ...baseInfo, kind: 'validation', type: 'email', input: input.other, expected: null, received: `"${input.other}"`, requirement: EMAIL_REGEX, path: [ { type: 'object', origin: 'value', input, key: 'other', value: input.other, }, ], }, ], } satisfies PartialDataset, InferIssue>); }); test('for multiple typed objects', () => { const schema = variant('type', [ object({ type: literal('foo'), other: number() }), object({ type: literal('foo'), other: pipe(string(), email()) }), object({ type: literal('foo'), other: pipe(string(), url()) }), object({ type: literal('foo'), other: pipe(string(), decimal()) }), object({ type: literal('foo'), other: boolean() }), ]); type Schema = typeof schema; const input = { type: 'foo', other: 'hello' } as const; expect(schema['~run']({ value: input }, {})).toStrictEqual({ typed: true, value: input, issues: [ { ...baseInfo, kind: 'validation', type: 'email', input: input.other, expected: null, received: `"${input.other}"`, requirement: EMAIL_REGEX, path: [ { type: 'object', origin: 'value', input, key: 'other', value: input.other, }, ], }, ], } satisfies PartialDataset, InferIssue>); }); }); }); ================================================ FILE: library/src/schemas/variant/variant.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, InferInput, InferOutput, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps, _joinExpects, } from '../../utils/index.ts'; import type { InferVariantIssue, VariantIssue, VariantOptions, VariantOptionSchema, } from './types.ts'; /** * Variant schema interface. */ export interface VariantSchema< TKey extends string, TOptions extends VariantOptions, TMessage extends ErrorMessage | undefined, > extends BaseSchema< InferInput, InferOutput, VariantIssue | InferVariantIssue > { /** * The schema type. */ readonly type: 'variant'; /** * The schema reference. */ readonly reference: typeof variant; /** * The expected property. */ readonly expects: 'Object'; /** * The discriminator key. */ readonly key: TKey; /** * The variant options. */ readonly options: TOptions; /** * The error message. */ readonly message: TMessage; } /** * Creates a variant schema. * * @param key The discriminator key. * @param options The variant options. * * @returns A variant schema. */ export function variant< const TKey extends string, const TOptions extends VariantOptions, >(key: TKey, options: TOptions): VariantSchema; /** * Creates a variant schema. * * @param key The discriminator key. * @param options The variant options. * @param message The error message. * * @returns An variant schema. */ export function variant< const TKey extends string, const TOptions extends VariantOptions, const TMessage extends ErrorMessage | undefined, >( key: TKey, options: TOptions, message: TMessage ): VariantSchema; // @__NO_SIDE_EFFECTS__ export function variant( key: string, options: VariantOptions, message?: ErrorMessage ): VariantSchema< string, VariantOptions, ErrorMessage | undefined > { return { kind: 'schema', type: 'variant', reference: variant, expects: 'Object', async: false, key, options, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (input && typeof input === 'object') { // Create output dataset variable let outputDataset: | OutputDataset> | undefined; // Create variables to store invalid discriminator information let maxDiscriminatorPriority = 0; let invalidDiscriminatorKey = this.key; let expectedDiscriminators: string[] = []; // Create recursive function to parse nested variant options const parseOptions = ( variant: VariantOptionSchema, allKeys: Set ) => { for (const schema of variant.options) { // If it is a variant schema, parse its options recursively if (schema.type === 'variant') { parseOptions(schema, new Set(allKeys).add(schema.key)); // Otherwise, check discriminators and parse object schema } else { // Create variables to store local discriminator information let keysAreValid = true; let currentPriority = 0; // Check if all discriminator keys are valid and collect // information about invalid discriminator keys if not for (const currentKey of allKeys) { // If any discriminator is invalid, mark keys as invalid const discriminatorSchema = schema.entries[currentKey]; if ( currentKey in input ? discriminatorSchema['~run']( // @ts-expect-error { typed: false, value: input[currentKey] }, { abortEarly: true } ).issues : discriminatorSchema.type !== 'exact_optional' && discriminatorSchema.type !== 'optional' && discriminatorSchema.type !== 'nullish' ) { keysAreValid = false; // If invalid discriminator key is not equal to current key // and if current key has a higher priority or same priority // but is the first one present in input, reset invalid // discriminator information if ( invalidDiscriminatorKey !== currentKey && (maxDiscriminatorPriority < currentPriority || (maxDiscriminatorPriority === currentPriority && currentKey in input && !(invalidDiscriminatorKey in input))) ) { maxDiscriminatorPriority = currentPriority; invalidDiscriminatorKey = currentKey; expectedDiscriminators = []; } // If invalid discriminator key is equal to current key, // store its expected value if (invalidDiscriminatorKey === currentKey) { expectedDiscriminators.push( schema.entries[currentKey].expects ); } // Break loop on first invalid discriminator key break; } // Increase priority for next discriminator key currentPriority++; } // If all discriminators are valid, parse input with schema of option if (keysAreValid) { const optionDataset = schema['~run']({ value: input }, config); // Store output dataset if necessary // Hint: Only the first untyped or typed dataset is returned, and // typed datasets take precedence over untyped ones. if ( !outputDataset || (!outputDataset.typed && optionDataset.typed) ) { outputDataset = optionDataset; } } } // If valid option is found, break loop // Hint: The `break` statement is intentionally placed at the end of // the loop to break any outer loops in case of recursive execution. if (outputDataset && !outputDataset.issues) { break; } } }; // Parse input with nested variant options recursively parseOptions(this, new Set([this.key])); // If any output dataset is available, return it if (outputDataset) { return outputDataset; } // Otherwise, add discriminator issue _addIssue(this, 'type', dataset, config, { // @ts-expect-error input: input[invalidDiscriminatorKey], expected: _joinExpects(expectedDiscriminators, '|'), path: [ { type: 'object', origin: 'value', input: input as Record, key: invalidDiscriminatorKey, // @ts-expect-error value: input[invalidDiscriminatorKey], }, ], }); // Otherwise, add variant issue } else { _addIssue(this, 'type', dataset, config); } // Finally, return output dataset // @ts-expect-error return dataset as OutputDataset< InferOutput[number]>, VariantIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/variant/variantAsync.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { literal, type LiteralIssue } from '../literal/index.ts'; import { object } from '../object/object.ts'; import { strictObjectAsync, type StrictObjectIssue, } from '../strictObject/index.ts'; import type { VariantIssue } from './types.ts'; import { variantAsync, type VariantSchemaAsync } from './variantAsync.ts'; describe('variantAsync', () => { const key = 'type' as const; type Key = typeof key; const options = [ object({ type: literal('foo') }), strictObjectAsync({ type: literal('bar') }), ] as const; type Options = typeof options; describe('should return schema object', () => { test('with undefined message', () => { type Schema = VariantSchemaAsync; expectTypeOf(variantAsync(key, options)).toEqualTypeOf(); expectTypeOf( variantAsync(key, options, undefined) ).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(variantAsync(key, options, 'message')).toEqualTypeOf< VariantSchemaAsync >(); }); test('with function message', () => { expectTypeOf(variantAsync(key, options, () => 'message')).toEqualTypeOf< VariantSchemaAsync string> >(); }); }); describe('should infer correct types', () => { type Schema = VariantSchemaAsync; test('of input', () => { expectTypeOf>().toEqualTypeOf< { type: 'foo' } | { type: 'bar' } >(); }); test('of output', () => { expectTypeOf>().toEqualTypeOf< { type: 'foo' } | { type: 'bar' } >(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf< VariantIssue | StrictObjectIssue | LiteralIssue >(); }); }); }); ================================================ FILE: library/src/schemas/variant/variantAsync.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { decimal, email, url } from '../../actions/index.ts'; import { pipe } from '../../methods/index.ts'; import { EMAIL_REGEX } from '../../regex.ts'; import type { FailureDataset, InferIssue, InferOutput, PartialDataset, } from '../../types/index.ts'; import { expectNoSchemaIssueAsync } from '../../vitest/index.ts'; import { bigint } from '../bigint/bigint.ts'; import { boolean } from '../boolean/index.ts'; import { exactOptional, exactOptionalAsync } from '../exactOptional/index.ts'; import { literal } from '../literal/literal.ts'; import { null_ } from '../null/null.ts'; import { nullish, nullishAsync } from '../nullish/index.ts'; import { number } from '../number/index.ts'; import { object, objectAsync } from '../object/index.ts'; import { optional, optionalAsync } from '../optional/index.ts'; import { strictObjectAsync } from '../strictObject/index.ts'; import { string } from '../string/index.ts'; import { variantAsync, type VariantSchemaAsync } from './variantAsync.ts'; describe('variantAsync', () => { describe('should return schema object', () => { const key = 'type' as const; type Key = typeof key; const options = [ object({ type: literal('foo') }), strictObjectAsync({ type: literal('bar') }), ] as const; type Options = typeof options; const baseSchema: Omit< VariantSchemaAsync, 'message' > = { kind: 'schema', type: 'variant', reference: variantAsync, expects: 'Object', key, options, async: true, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: VariantSchemaAsync = { ...baseSchema, message: undefined, }; expect(variantAsync(key, options)).toStrictEqual(schema); expect(variantAsync(key, options, undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(variantAsync(key, options, 'message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies VariantSchemaAsync); }); test('with function message', () => { const message = () => 'message'; expect(variantAsync(key, options, message)).toStrictEqual({ ...baseSchema, message, } satisfies VariantSchemaAsync); }); }); describe('should return dataset without issues', () => { test('for simple variants', async () => { await expectNoSchemaIssueAsync( variantAsync('type', [ object({ type: literal('foo') }), object({ type: literal('bar') }), objectAsync({ type: null_() }), ]), [{ type: 'foo' }, { type: 'bar' }, { type: null }] ); }); test('for same discriminators', async () => { await expectNoSchemaIssueAsync( variantAsync('type', [ object({ type: literal('foo'), other: string() }), object({ type: literal('foo'), other: number() }), objectAsync({ type: literal('foo'), other: boolean() }), ]), [ { type: 'foo', other: 'hello' }, { type: 'foo', other: 123 }, { type: 'foo', other: true }, ] ); }); test('for nested variants', async () => { await expectNoSchemaIssueAsync( variantAsync('type', [ object({ type: literal('foo') }), variantAsync('type', [ object({ type: literal('bar') }), objectAsync({ type: null_() }), ]), ]), [{ type: 'foo' }, { type: 'bar' }, { type: null }] ); }); test('for deeply nested variants', async () => { await expectNoSchemaIssueAsync( variantAsync('type', [ object({ type: literal('foo') }), variantAsync('type', [ object({ type: literal('bar') }), variantAsync('type', [object({ type: null_() })]), ]), ]), [{ type: 'foo' }, { type: 'bar' }, { type: null }] ); }); test('for optional discriminators', async () => { await expectNoSchemaIssueAsync( variantAsync('type', [ object({ type: literal('foo') }), object({ type: exactOptional(literal('bar')) }), object({ type: literal('baz') }), ]), [{}, { type: 'bar' }] ); await expectNoSchemaIssueAsync( variantAsync('type', [ object({ type: literal('foo') }), objectAsync({ type: exactOptionalAsync(literal('bar')) }), object({ type: literal('baz') }), ]), [{}, { type: 'bar' }] ); await expectNoSchemaIssueAsync( variantAsync('type', [ object({ type: literal('foo') }), object({ type: optional(literal('bar')) }), object({ type: literal('baz') }), ]), [{}, { type: undefined }, { type: 'bar' }] ); await expectNoSchemaIssueAsync( variantAsync('type', [ object({ type: literal('foo') }), objectAsync({ type: optionalAsync(literal('bar')) }), object({ type: literal('baz') }), ]), [{}, { type: undefined }, { type: 'bar' }] ); await expectNoSchemaIssueAsync( variantAsync('type', [ object({ type: literal('foo') }), object({ type: nullish(literal('bar')) }), object({ type: literal('baz') }), ]), [{}, { type: null }, { type: undefined }, { type: 'bar' }] ); await expectNoSchemaIssueAsync( variantAsync('type', [ object({ type: literal('foo') }), objectAsync({ type: nullishAsync(literal('bar')) }), object({ type: literal('baz') }), ]), [{}, { type: null }, { type: undefined }, { type: 'bar' }] ); }); }); describe('should return dataset with issues', () => { const baseInfo = { message: expect.any(String), requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; test('for invalid base type', async () => { const schema = variantAsync('type', [ object({ type: literal('foo') }), objectAsync({ type: literal('bar') }), ]); expect(await schema['~run']({ value: 'foo' }, {})).toStrictEqual({ typed: false, value: 'foo', issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: 'foo', expected: 'Object', received: '"foo"', }, ], } satisfies FailureDataset>); }); test('for empty options', async () => { const schema = variantAsync('type', []); const input = { type: 'foo' }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: input.type, expected: 'never', received: `"${input.type}"`, path: [ { type: 'object', origin: 'value', input, key: 'type', value: input.type, }, ], }, ], } satisfies FailureDataset>); }); test('for missing discriminator', async () => { const schema = variantAsync('type', [ object({ type: literal('foo') }), objectAsync({ type: literal('bar') }), ]); const input = { other: 123 }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: undefined, expected: '("foo" | "bar")', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'type', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for invalid discriminator', async () => { const schema = variantAsync('type', [ object({ type: literal('foo') }), objectAsync({ type: literal('bar') }), ]); const input = { type: 'baz' }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: input.type, expected: '("foo" | "bar")', received: `"${input.type}"`, path: [ { type: 'object', origin: 'value', input, key: 'type', value: input.type, }, ], }, ], } satisfies FailureDataset>); }); test('for nested missing discriminator', async () => { const schema = variantAsync('type', [ object({ type: literal('foo') }), variantAsync('other', [ object({ type: literal('bar'), other: string() }), object({ type: literal('bar'), other: boolean() }), object({ type: literal('baz'), other: number() }), ]), ]); const input = { type: 'bar' }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: undefined, expected: '(string | boolean)', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'other', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for nested invalid discriminator', async () => { const schema = variantAsync('type', [ object({ type: literal('foo') }), variantAsync('other', [ object({ type: literal('bar'), other: string() }), object({ type: literal('bar'), other: boolean() }), object({ type: literal('baz'), other: number() }), ]), ]); const input = { type: 'bar', other: 123 }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: input.other, expected: '(string | boolean)', received: `${input.other}`, path: [ { type: 'object', origin: 'value', input, key: 'other', value: input.other, }, ], }, ], } satisfies FailureDataset>); }); test('for first missing invalid discriminator', async () => { const schema = variantAsync('type', [ variantAsync('subType1', [ object({ type: literal('foo'), subType1: literal('foo-1'), other1: string(), }), object({ type: literal('bar'), subType1: literal('bar-1'), other2: string(), }), ]), variantAsync('subType2', [ object({ type: literal('foo'), subType2: literal('foo-2'), other3: string(), }), object({ type: literal('bar'), subType2: literal('bar-2'), other4: string(), }), ]), ]); const input = {}; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: undefined, expected: '("foo" | "bar")', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'type', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for first nested missing discriminator', async () => { const schema = variantAsync('type', [ variantAsync('subType1', [ object({ type: literal('foo'), subType1: literal('foo-1'), other1: string(), }), object({ type: literal('bar'), subType1: literal('bar-1'), other2: string(), }), ]), variantAsync('subType2', [ object({ type: literal('foo'), subType2: literal('foo-2'), other3: string(), }), object({ type: literal('bar'), subType2: literal('bar-2'), other4: string(), }), ]), ]); const input = { type: 'bar' }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: undefined, expected: '"bar-1"', received: 'undefined', path: [ { type: 'object', origin: 'value', input, key: 'subType1', value: undefined, }, ], }, ], } satisfies FailureDataset>); }); test('for first nested invalid discriminator', async () => { const schema = variantAsync('type', [ variantAsync('subType1', [ object({ type: literal('foo'), subType1: literal('foo-1'), other1: string(), }), object({ type: literal('bar'), subType1: literal('bar-1'), other2: string(), }), ]), variantAsync('subType2', [ object({ type: literal('foo'), subType2: literal('foo-2'), other3: string(), }), object({ type: literal('bar'), subType2: literal('bar-2'), other4: string(), }), ]), ]); const input = { type: 'bar', subType2: 'baz-2' }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: input.subType2, expected: '"bar-2"', received: `"${input.subType2}"`, path: [ { type: 'object', origin: 'value', input, key: 'subType2', value: input.subType2, }, ], }, ], } satisfies FailureDataset>); }); test('for first nested invalid discriminator', async () => { const schema = variantAsync('type', [ variantAsync('subType1', [ object({ type: literal('foo'), subType1: literal('foo-1'), other1: string(), }), object({ type: literal('bar'), subType1: literal('bar-1'), other2: string(), }), ]), variantAsync('subType2', [ object({ type: literal('foo'), subType2: literal('foo-2'), other3: string(), }), object({ type: literal('bar'), subType2: literal('bar-2'), other4: string(), }), ]), ]); const input = { type: 'bar', subType1: 'invalid', subType2: 'invalid' }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: input.subType1, expected: '"bar-1"', received: `"${input.subType1}"`, path: [ { type: 'object', origin: 'value', input, key: 'subType1', value: input.subType1, }, ], }, ], } satisfies FailureDataset>); }); test('for first nested invalid discriminator', async () => { const schema = variantAsync('type', [ variantAsync('subType1', [ variantAsync('subType2', [ object({ type: literal('foo'), subType1: literal('foo-1'), subType2: literal('foo-2'), other1: string(), }), object({ type: literal('bar'), subType1: literal('bar-1'), subType2: literal('bar-2'), other2: string(), }), ]), ]), variantAsync('subType2', [ object({ type: literal('foo'), subType2: literal('foz-2'), other3: string(), }), object({ type: literal('bar'), subType2: literal('baz-2'), other4: string(), }), ]), ]); const input = { type: 'bar', subType1: 'bar-1', subType2: 'invalid' }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: input.subType2, expected: '("bar-2" | "baz-2")', received: `"${input.subType2}"`, path: [ { type: 'object', origin: 'value', input, key: 'subType2', value: input.subType2, }, ], }, ], } satisfies FailureDataset>); }); test('for first nested invalid discriminator', async () => { const schema = variantAsync('type', [ variantAsync('subType2', [ object({ type: literal('foo'), subType2: literal('foz-2'), other3: string(), }), object({ type: literal('bar'), subType2: literal('baz-2'), other4: string(), }), ]), variantAsync('subType1', [ variantAsync('subType2', [ object({ type: literal('foo'), subType1: literal('foo-1'), subType2: literal('foo-2'), other1: string(), }), object({ type: literal('bar'), subType1: literal('bar-1'), subType2: literal('bar-2'), other2: string(), }), ]), ]), ]); const input = { type: 'bar', subType1: 'bar-1', subType2: 'invalid' }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: input.subType2, expected: '("baz-2" | "bar-2")', received: `"${input.subType2}"`, path: [ { type: 'object', origin: 'value', input, key: 'subType2', value: input.subType2, }, ], }, ], } satisfies FailureDataset>); }); test('for first nested invalid discriminator', async () => { const schema = variantAsync('type', [ variantAsync('subType1', [ object({ type: literal('foo'), subType1: literal('foo-1'), other1: string(), }), object({ type: literal('bar'), subType1: literal('bar-1'), other2: string(), }), variantAsync('subType2', [ object({ type: literal('bar'), subType1: literal('baz-1'), subType2: literal('baz-2'), other5: string(), }), ]), ]), variantAsync('subType2', [ object({ type: literal('foo'), subType2: literal('foo-2'), other3: string(), }), object({ type: literal('bar'), subType2: literal('bar-2'), other4: string(), }), ]), ]); const input = { type: 'bar', subType2: 'baz-2' }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'variant', input: input.subType2, expected: '"bar-2"', received: `"${input.subType2}"`, path: [ { type: 'object', origin: 'value', input, key: 'subType2', value: input.subType2, }, ], }, ], } satisfies FailureDataset>); }); test('for untyped object', async () => { const schema = variantAsync('type', [ object({ type: literal('foo'), other: bigint() }), object({ type: literal('bar'), other: string() }), objectAsync({ type: literal('baz'), other: number() }), ]); const input = { type: 'bar', other: null }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: input.other, expected: 'string', received: `${input.other}`, path: [ { type: 'object', origin: 'value', input, key: 'other', value: input.other, }, ], }, ], } satisfies FailureDataset>); }); test('for nested untyped object', async () => { const schema = variantAsync('type', [ object({ type: literal('foo') }), variantAsync('type', [ object({ type: literal('bar'), other: string() }), objectAsync({ type: literal('baz'), other: number() }), ]), ]); const input = { type: 'bar', other: null }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: input.other, expected: 'string', received: `${input.other}`, path: [ { type: 'object', origin: 'value', input, key: 'other', value: input.other, }, ], }, ], } satisfies FailureDataset>); }); test('for multiple untyped objects', async () => { const schema = variantAsync('type', [ object({ type: literal('foo'), other: bigint() }), object({ type: literal('bar'), other: string() }), object({ type: literal('bar'), other: number() }), objectAsync({ type: literal('bar'), other: boolean() }), ]); const input = { type: 'bar', other: null }; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: false, value: input, issues: [ { ...baseInfo, kind: 'schema', type: 'string', input: input.other, expected: 'string', received: `${input.other}`, path: [ { type: 'object', origin: 'value', input, key: 'other', value: input.other, }, ], }, ], } satisfies FailureDataset>); }); test('for typed objects', async () => { const schema = variantAsync('type', [ object({ type: literal('foo'), other: number() }), object({ type: literal('bar'), other: pipe(string(), email()) }), objectAsync({ type: literal('baz'), other: boolean() }), ]); type Schema = typeof schema; const input = { type: 'bar', other: 'hello' } as const; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: true, value: input, issues: [ { ...baseInfo, kind: 'validation', type: 'email', input: input.other, expected: null, received: `"${input.other}"`, requirement: EMAIL_REGEX, path: [ { type: 'object', origin: 'value', input, key: 'other', value: input.other, }, ], }, ], } satisfies PartialDataset, InferIssue>); }); test('for nested typed objects', async () => { const schema = variantAsync('type', [ object({ type: literal('foo'), other: number() }), variantAsync('type', [ object({ type: literal('bar'), other: pipe(string(), email()) }), objectAsync({ type: literal('baz'), other: boolean() }), ]), ]); type Schema = typeof schema; const input = { type: 'bar', other: 'hello' } as const; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: true, value: input, issues: [ { ...baseInfo, kind: 'validation', type: 'email', input: input.other, expected: null, received: `"${input.other}"`, requirement: EMAIL_REGEX, path: [ { type: 'object', origin: 'value', input, key: 'other', value: input.other, }, ], }, ], } satisfies PartialDataset, InferIssue>); }); test('for multiple typed objects', async () => { const schema = variantAsync('type', [ object({ type: literal('foo'), other: number() }), object({ type: literal('foo'), other: pipe(string(), email()) }), object({ type: literal('foo'), other: pipe(string(), url()) }), object({ type: literal('foo'), other: pipe(string(), decimal()) }), objectAsync({ type: literal('foo'), other: boolean() }), ]); type Schema = typeof schema; const input = { type: 'foo', other: 'hello' } as const; expect(await schema['~run']({ value: input }, {})).toStrictEqual({ typed: true, value: input, issues: [ { ...baseInfo, kind: 'validation', type: 'email', input: input.other, expected: null, received: `"${input.other}"`, requirement: EMAIL_REGEX, path: [ { type: 'object', origin: 'value', input, key: 'other', value: input.other, }, ], }, ], } satisfies PartialDataset, InferIssue>); }); }); }); ================================================ FILE: library/src/schemas/variant/variantAsync.ts ================================================ import type { BaseIssue, BaseSchemaAsync, ErrorMessage, InferInput, InferOutput, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps, _joinExpects, } from '../../utils/index.ts'; import type { InferVariantIssue, VariantIssue, VariantOptionsAsync, VariantOptionSchema, VariantOptionSchemaAsync, } from './types.ts'; import type { variant } from './variant.ts'; /** * Variant schema async interface. */ export interface VariantSchemaAsync< TKey extends string, TOptions extends VariantOptionsAsync, TMessage extends ErrorMessage | undefined, > extends BaseSchemaAsync< InferInput, InferOutput, VariantIssue | InferVariantIssue > { /** * The schema type. */ readonly type: 'variant'; /** * The schema reference. */ readonly reference: typeof variant | typeof variantAsync; /** * The expected property. */ readonly expects: 'Object'; /** * The discriminator key. */ readonly key: TKey; /** * The variant options. */ readonly options: TOptions; /** * The error message. */ readonly message: TMessage; } /** * Creates a variant schema. * * @param key The discriminator key. * @param options The variant options. * * @returns A variant schema. */ export function variantAsync< const TKey extends string, const TOptions extends VariantOptionsAsync, >(key: TKey, options: TOptions): VariantSchemaAsync; /** * Creates a variant schema. * * @param key The discriminator key. * @param options The variant options. * @param message The error message. * * @returns An variant schema. */ export function variantAsync< const TKey extends string, const TOptions extends VariantOptionsAsync, const TMessage extends ErrorMessage | undefined, >( key: TKey, options: TOptions, message: TMessage ): VariantSchemaAsync; // @__NO_SIDE_EFFECTS__ export function variantAsync( key: string, options: VariantOptionsAsync, message?: ErrorMessage ): VariantSchemaAsync< string, VariantOptionsAsync, ErrorMessage | undefined > { return { kind: 'schema', type: 'variant', reference: variantAsync, expects: 'Object', async: true, key, options, message, get '~standard'() { return _getStandardProps(this); }, async '~run'(dataset, config) { // Get input value from dataset const input = dataset.value; // If root type is valid, check nested types if (input && typeof input === 'object') { // Create output dataset variable let outputDataset: | OutputDataset> | undefined; // Create variables to store invalid discriminator information let maxDiscriminatorPriority = 0; let invalidDiscriminatorKey = this.key; let expectedDiscriminators: string[] = []; // Create recursive function to parse nested variant options const parseOptions = async ( variant: | VariantOptionSchema | VariantOptionSchemaAsync, allKeys: Set ) => { for (const schema of variant.options) { // If it is a variant schema, parse its options recursively if (schema.type === 'variant') { await parseOptions(schema, new Set(allKeys).add(schema.key)); // Otherwise, check discriminators and parse object schema } else { // Create variables to store local discriminator information let keysAreValid = true; let currentPriority = 0; // Check if all discriminator keys are valid and collect // information about invalid discriminator keys if not for (const currentKey of allKeys) { // If any discriminator is invalid, mark keys as invalid const discriminatorSchema = schema.entries[currentKey]; if ( currentKey in input ? ( await discriminatorSchema['~run']( // @ts-expect-error { typed: false, value: input[currentKey] }, { abortEarly: true } ) ).issues : discriminatorSchema.type !== 'exact_optional' && discriminatorSchema.type !== 'optional' && discriminatorSchema.type !== 'nullish' ) { keysAreValid = false; // If invalid discriminator key is not equal to current key // and if current key has a higher priority or same priority // but is the first one present in input, reset invalid // discriminator information if ( invalidDiscriminatorKey !== currentKey && (maxDiscriminatorPriority < currentPriority || (maxDiscriminatorPriority === currentPriority && currentKey in input && !(invalidDiscriminatorKey in input))) ) { maxDiscriminatorPriority = currentPriority; invalidDiscriminatorKey = currentKey; expectedDiscriminators = []; } // If invalid discriminator key is equal to current key, // store its expected value if (invalidDiscriminatorKey === currentKey) { expectedDiscriminators.push( schema.entries[currentKey].expects ); } // Break loop on first invalid discriminator key break; } // Increase priority for next discriminator key currentPriority++; } // If all discriminators are valid, parse input with schema of option if (keysAreValid) { const optionDataset = await schema['~run']( { value: input }, config ); // Store output dataset if necessary // Hint: Only the first untyped or typed dataset is returned, and // typed datasets take precedence over untyped ones. if ( !outputDataset || (!outputDataset.typed && optionDataset.typed) ) { outputDataset = optionDataset; } } } // If valid option is found, break loop // Hint: The `break` statement is intentionally placed at the end of // the loop to break any outer loops in case of recursive execution. if (outputDataset && !outputDataset.issues) { break; } } }; // Parse input with nested variant options recursively await parseOptions(this, new Set([this.key])); // If any output dataset is available, return it if (outputDataset) { return outputDataset; } // Otherwise, add discriminator issue _addIssue(this, 'type', dataset, config, { // @ts-expect-error input: input[invalidDiscriminatorKey], expected: _joinExpects(expectedDiscriminators, '|'), path: [ { type: 'object', origin: 'value', input: input as Record, key: invalidDiscriminatorKey, // @ts-expect-error value: input[invalidDiscriminatorKey], }, ], }); // Otherwise, add variant issue } else { _addIssue(this, 'type', dataset, config); } // Finally, return output dataset // @ts-expect-error return dataset as OutputDataset< InferOutput[number]>, VariantIssue | BaseIssue >; }, }; } ================================================ FILE: library/src/schemas/void/index.ts ================================================ export * from './void.ts'; ================================================ FILE: library/src/schemas/void/void.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { InferInput, InferIssue, InferOutput } from '../../types/index.ts'; import { void_, type VoidIssue, type VoidSchema } from './void.ts'; describe('void', () => { describe('should return schema object', () => { test('with undefined message', () => { type Schema = VoidSchema; expectTypeOf(void_()).toEqualTypeOf(); expectTypeOf(void_(undefined)).toEqualTypeOf(); }); test('with string message', () => { expectTypeOf(void_('message')).toEqualTypeOf>(); }); test('with function message', () => { expectTypeOf(void_(() => 'message')).toEqualTypeOf< VoidSchema<() => string> >(); }); }); describe('should infer correct types', () => { type Schema = VoidSchema; test('of input', () => { // eslint-disable-next-line @typescript-eslint/no-invalid-void-type expectTypeOf>().toEqualTypeOf(); }); test('of output', () => { // eslint-disable-next-line @typescript-eslint/no-invalid-void-type expectTypeOf>().toEqualTypeOf(); }); test('of issue', () => { expectTypeOf>().toEqualTypeOf(); }); }); }); ================================================ FILE: library/src/schemas/void/void.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { expectNoSchemaIssue, expectSchemaIssue } from '../../vitest/index.ts'; import { void_, type VoidIssue, type VoidSchema } from './void.ts'; describe('void', () => { describe('should return schema object', () => { const baseSchema: Omit, 'message'> = { kind: 'schema', type: 'void', reference: void_, expects: 'void', async: false, '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), }, '~run': expect.any(Function), }; test('with undefined message', () => { const schema: VoidSchema = { ...baseSchema, message: undefined, }; expect(void_()).toStrictEqual(schema); expect(void_(undefined)).toStrictEqual(schema); }); test('with string message', () => { expect(void_('message')).toStrictEqual({ ...baseSchema, message: 'message', } satisfies VoidSchema<'message'>); }); test('with function message', () => { const message = () => 'message'; expect(void_(message)).toStrictEqual({ ...baseSchema, message, } satisfies VoidSchema); }); }); describe('should return dataset without issues', () => { const schema = void_(); test('for undefined', () => { expectNoSchemaIssue(schema, [undefined]); }); }); describe('should return dataset with issues', () => { const schema = void_('message'); const baseIssue: Omit = { kind: 'schema', type: 'void', expected: 'void', message: 'message', }; // Primitive types test('for bigints', () => { expectSchemaIssue(schema, baseIssue, [-1n, 0n, 123n]); }); test('for booleans', () => { expectSchemaIssue(schema, baseIssue, [true, false]); }); test('for numbers', () => { expectSchemaIssue(schema, baseIssue, [-1, 0, 123, 45.67]); }); test('for null', () => { expectSchemaIssue(schema, baseIssue, [null]); }); test('for strings', () => { expectSchemaIssue(schema, baseIssue, ['', 'foo', '123']); }); test('for symbols', () => { expectSchemaIssue(schema, baseIssue, [Symbol(), Symbol('foo')]); }); // Complex types test('for arrays', () => { expectSchemaIssue(schema, baseIssue, [[], ['value']]); }); test('for functions', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expectSchemaIssue(schema, baseIssue, [() => {}, function () {}]); }); test('for objects', () => { expectSchemaIssue(schema, baseIssue, [{}, { key: 'value' }]); }); }); }); ================================================ FILE: library/src/schemas/void/void.ts ================================================ import type { BaseIssue, BaseSchema, ErrorMessage, OutputDataset, } from '../../types/index.ts'; import { _addIssue, _getStandardProps } from '../../utils/index.ts'; /** * Void issue interface. */ export interface VoidIssue extends BaseIssue { /** * The issue kind. */ readonly kind: 'schema'; /** * The issue type. */ readonly type: 'void'; /** * The expected property. */ readonly expected: 'void'; } /** * Void schema interface. */ export interface VoidSchema< TMessage extends ErrorMessage | undefined, > extends BaseSchema { /** * The schema type. */ readonly type: 'void'; /** * The schema reference. */ readonly reference: typeof void_; /** * The expected property. */ readonly expects: 'void'; /** * The error message. */ readonly message: TMessage; } /** * Creates a void schema. * * @returns A void schema. */ export function void_(): VoidSchema; /** * Creates a void schema. * * @param message The error message. * * @returns A void schema. */ export function void_< const TMessage extends ErrorMessage | undefined, >(message: TMessage): VoidSchema; // @__NO_SIDE_EFFECTS__ export function void_( message?: ErrorMessage ): VoidSchema | undefined> { return { kind: 'schema', type: 'void', reference: void_, expects: 'void', async: false, message, get '~standard'() { return _getStandardProps(this); }, '~run'(dataset, config) { if (dataset.value === undefined) { // @ts-expect-error dataset.typed = true; } else { _addIssue(this, 'type', dataset, config); } // @ts-expect-error return dataset as OutputDataset; }, }; } export { void_ as void }; ================================================ FILE: library/src/storages/globalConfig/globalConfig.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { Config } from '../../types/index.ts'; import { deleteGlobalConfig, getGlobalConfig, type GlobalConfig, setGlobalConfig, } from './globalConfig.ts'; describe('config', () => { const initialConfig: Config = { lang: undefined, message: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const customConfig: GlobalConfig = { lang: 'en', abortEarly: true, abortPipeEarly: false, }; test('should be undefined initially', () => { expect(getGlobalConfig()).toStrictEqual(initialConfig); }); test('should set and get global config', () => { setGlobalConfig(customConfig); expect(getGlobalConfig()).toStrictEqual({ ...initialConfig, ...customConfig, }); }); test('should merge config argument', () => { expect(getGlobalConfig({ lang: 'de' })).toStrictEqual({ ...initialConfig, ...customConfig, lang: 'de', }); }); test('should delete global config', () => { deleteGlobalConfig(); expect(getGlobalConfig()).toStrictEqual(initialConfig); }); }); ================================================ FILE: library/src/storages/globalConfig/globalConfig.ts ================================================ import type { BaseIssue, Config } from '../../types/index.ts'; /** * The global config type. */ export type GlobalConfig = Omit, 'message'>; // Create global configuration store let store: GlobalConfig | undefined; /** * Sets the global configuration. * * @param config The configuration. */ export function setGlobalConfig(config: GlobalConfig): void { store = { ...store, ...config }; } /** * Returns the global configuration. * * @param config The config to merge. * * @returns The configuration. */ // @__NO_SIDE_EFFECTS__ export function getGlobalConfig>( config?: Config ): Config { // Hint: The configuration is deliberately not constructed with the spread // operator for performance reasons return { lang: config?.lang ?? store?.lang, message: config?.message, abortEarly: config?.abortEarly ?? store?.abortEarly, abortPipeEarly: config?.abortPipeEarly ?? store?.abortPipeEarly, }; } /** * Deletes the global configuration. */ export function deleteGlobalConfig(): void { store = undefined; } ================================================ FILE: library/src/storages/globalConfig/index.ts ================================================ export * from './globalConfig.ts'; ================================================ FILE: library/src/storages/globalMessage/globalMessage.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { deleteGlobalMessage, getGlobalMessage, setGlobalMessage, } from './globalMessage.ts'; describe('globalMessage', () => { const lang = 'de'; test('should be undefined initially', () => { expect(getGlobalMessage()).toBeUndefined(); expect(getGlobalMessage(lang)).toBeUndefined(); }); test('should set and get string message', () => { const message1 = 'Custom message'; setGlobalMessage(message1); expect(getGlobalMessage()).toBe(message1); setGlobalMessage(message1, lang); expect(getGlobalMessage(lang)).toBe(message1); }); test('should set and get function message', () => { const message2 = () => 'Custom message'; setGlobalMessage(message2); expect(getGlobalMessage()).toBe(message2); setGlobalMessage(message2, lang); expect(getGlobalMessage(lang)).toBe(message2); }); test('should delete global message', () => { deleteGlobalMessage(); expect(getGlobalMessage()).toBeUndefined(); deleteGlobalMessage(lang); expect(getGlobalMessage(lang)).toBeUndefined(); }); }); ================================================ FILE: library/src/storages/globalMessage/globalMessage.ts ================================================ import type { BaseIssue, ErrorMessage } from '../../types/index.ts'; // Create global message store let store: Map>>; /** * Sets a global error message. * * @param message The error message. * @param lang The language of the message. */ export function setGlobalMessage( message: ErrorMessage>, lang?: string ): void { if (!store) store = new Map(); store.set(lang, message); } /** * Returns a global error message. * * @param lang The language of the message. * * @returns The error message. */ // @__NO_SIDE_EFFECTS__ export function getGlobalMessage( lang?: string ): ErrorMessage> | undefined { return store?.get(lang); } /** * Deletes a global error message. * * @param lang The language of the message. */ export function deleteGlobalMessage(lang?: string): void { store?.delete(lang); } ================================================ FILE: library/src/storages/globalMessage/index.ts ================================================ export * from './globalMessage.ts'; ================================================ FILE: library/src/storages/index.ts ================================================ export * from './globalConfig/index.ts'; export * from './globalMessage/index.ts'; export * from './schemaMessage/index.ts'; export * from './specificMessage/index.ts'; ================================================ FILE: library/src/storages/schemaMessage/index.ts ================================================ export * from './schemaMessage.ts'; ================================================ FILE: library/src/storages/schemaMessage/schemaMessage.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { deleteSchemaMessage, getSchemaMessage, setSchemaMessage, } from './schemaMessage.ts'; describe('schemaMessage', () => { const lang = 'de'; test('should be undefined initially', () => { expect(getSchemaMessage()).toBeUndefined(); expect(getSchemaMessage(lang)).toBeUndefined(); }); test('should set and get string message', () => { const message1 = 'Custom message'; setSchemaMessage(message1); expect(getSchemaMessage()).toBe(message1); setSchemaMessage(message1, lang); expect(getSchemaMessage(lang)).toBe(message1); }); test('should set and get function message', () => { const message2 = () => 'Custom message'; setSchemaMessage(message2); expect(getSchemaMessage()).toBe(message2); setSchemaMessage(message2, lang); expect(getSchemaMessage(lang)).toBe(message2); }); test('should delete schema message', () => { deleteSchemaMessage(); expect(getSchemaMessage()).toBeUndefined(); deleteSchemaMessage(lang); expect(getSchemaMessage(lang)).toBeUndefined(); }); }); ================================================ FILE: library/src/storages/schemaMessage/schemaMessage.ts ================================================ import type { BaseIssue, ErrorMessage } from '../../types/index.ts'; // Create schema message store let store: Map>>; /** * Sets a schema error message. * * @param message The error message. * @param lang The language of the message. */ export function setSchemaMessage( message: ErrorMessage>, lang?: string ): void { if (!store) store = new Map(); store.set(lang, message); } /** * Returns a schema error message. * * @param lang The language of the message. * * @returns The error message. */ // @__NO_SIDE_EFFECTS__ export function getSchemaMessage( lang?: string ): ErrorMessage> | undefined { return store?.get(lang); } /** * Deletes a schema error message. * * @param lang The language of the message. */ export function deleteSchemaMessage(lang?: string): void { store?.delete(lang); } ================================================ FILE: library/src/storages/specificMessage/index.ts ================================================ export * from './specificMessage.ts'; ================================================ FILE: library/src/storages/specificMessage/specificMessage.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { string } from '../../schemas/index.ts'; import { deleteSpecificMessage, getSpecificMessage, setSpecificMessage, } from './specificMessage.ts'; describe('schemaMessage', () => { const reference = string; const lang = 'de'; test('should be undefined initially', () => { expect(getSpecificMessage(reference)).toBeUndefined(); expect(getSpecificMessage(reference, lang)).toBeUndefined(); }); test('should set and get string message', () => { const message1 = 'Custom message'; setSpecificMessage(reference, message1); expect(getSpecificMessage(reference)).toBe(message1); setSpecificMessage(reference, message1, lang); expect(getSpecificMessage(reference, lang)).toBe(message1); }); test('should set and get function message', () => { const message2 = () => 'Custom message'; setSpecificMessage(reference, message2); expect(getSpecificMessage(reference)).toBe(message2); setSpecificMessage(reference, message2, lang); expect(getSpecificMessage(reference, lang)).toBe(message2); }); test('should delete schema message', () => { deleteSpecificMessage(reference); expect(getSpecificMessage(reference)).toBeUndefined(); deleteSpecificMessage(reference, lang); expect(getSpecificMessage(reference, lang)).toBeUndefined(); }); }); ================================================ FILE: library/src/storages/specificMessage/specificMessage.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, BaseTransformation, BaseTransformationAsync, BaseValidation, BaseValidationAsync, ErrorMessage, InferIssue, } from '../../types/index.ts'; /** * Reference type. */ type Reference = ( // eslint-disable-next-line @typescript-eslint/no-explicit-any ...args: any[] ) => | BaseSchema> | BaseSchemaAsync> | BaseValidation> | BaseValidationAsync> | BaseTransformation> | BaseTransformationAsync>; // Create specific message store let store: Map< Reference, Map>> >; /** * Sets a specific error message. * * @param reference The identifier reference. * @param message The error message. * @param lang The language of the message. */ export function setSpecificMessage( reference: TReference, message: ErrorMessage>>, lang?: string ): void { if (!store) store = new Map(); if (!store.get(reference)) store.set(reference, new Map()); store.get(reference)!.set(lang, message); } /** * Returns a specific error message. * * @param reference The identifier reference. * @param lang The language of the message. * * @returns The error message. */ // @__NO_SIDE_EFFECTS__ export function getSpecificMessage( reference: TReference, lang?: string ): ErrorMessage>> | undefined { return store?.get(reference)?.get(lang); } /** * Deletes a specific error message. * * @param reference The identifier reference. * @param lang The language of the message. */ export function deleteSpecificMessage( reference: Reference, lang?: string ): void { store?.get(reference)?.delete(lang); } ================================================ FILE: library/src/types/config.ts ================================================ import type { BaseIssue } from './issue.ts'; import type { ErrorMessage } from './other.ts'; /** * Config interface. */ export interface Config> { /** * The selected language. */ readonly lang?: string | undefined; /** * The error message. */ readonly message?: ErrorMessage | undefined; /** * Whether it should be aborted early. */ readonly abortEarly?: boolean | undefined; /** * Whether a pipe should be aborted early. */ readonly abortPipeEarly?: boolean | undefined; } ================================================ FILE: library/src/types/dataset.ts ================================================ import type { BaseIssue } from './issue.ts'; /** * Unknown dataset interface. */ export interface UnknownDataset { /** * Whether is's typed. */ typed?: false; /** * The dataset value. */ value: unknown; /** * The dataset issues. */ issues?: undefined; } /** * Success dataset interface. */ export interface SuccessDataset { /** * Whether is's typed. */ typed: true; /** * The dataset value. */ value: TValue; /** * The dataset issues. */ issues?: undefined; } /** * Partial dataset interface. */ export interface PartialDataset> { /** * Whether is's typed. */ typed: true; /** * The dataset value. */ value: TValue; /** * The dataset issues. */ issues: [TIssue, ...TIssue[]]; } /** * Failure dataset interface. */ export interface FailureDataset> { /** * Whether is's typed. */ typed: false; /** * The dataset value. */ value: unknown; /** * The dataset issues. */ issues: [TIssue, ...TIssue[]]; } /** * Output dataset type. */ export type OutputDataset> = | SuccessDataset | PartialDataset | FailureDataset; ================================================ FILE: library/src/types/index.ts ================================================ export * from './config.ts'; export * from './dataset.ts'; export * from './infer.ts'; export * from './issue.ts'; export * from './metadata.ts'; export * from './object.ts'; export * from './other.ts'; export * from './pipe.ts'; export * from './schema.ts'; export * from './standard.ts'; export * from './transformation.ts'; export * from './tuple.ts'; export * from './utils.ts'; export * from './validation.ts'; ================================================ FILE: library/src/types/infer.ts ================================================ /* eslint-disable @typescript-eslint/no-explicit-any */ import type { BaseIssue } from './issue.ts'; import type { BaseMetadata } from './metadata.ts'; import type { BaseSchema, BaseSchemaAsync } from './schema.ts'; import type { BaseTransformation, BaseTransformationAsync, } from './transformation.ts'; import type { BaseValidation, BaseValidationAsync } from './validation.ts'; /** * Infer input type. */ export type InferInput< TItem extends | BaseSchema> | BaseSchemaAsync> | BaseValidation> | BaseValidationAsync> | BaseTransformation> | BaseTransformationAsync> | BaseMetadata, > = NonNullable['input']; /** * Infer output type. */ export type InferOutput< TItem extends | BaseSchema> | BaseSchemaAsync> | BaseValidation> | BaseValidationAsync> | BaseTransformation> | BaseTransformationAsync> | BaseMetadata, > = NonNullable['output']; /** * Infer issue type. */ export type InferIssue< TItem extends | BaseSchema> | BaseSchemaAsync> | BaseValidation> | BaseValidationAsync> | BaseTransformation> | BaseTransformationAsync> | BaseMetadata, > = NonNullable['issue']; ================================================ FILE: library/src/types/issue.ts ================================================ import type { SchemaWithPipe, SchemaWithPipeAsync } from '../methods/index.ts'; import type { ArrayIssue, ArraySchema, ArraySchemaAsync, ExactOptionalSchema, ExactOptionalSchemaAsync, IntersectIssue, IntersectSchema, IntersectSchemaAsync, LazySchema, LazySchemaAsync, LooseObjectIssue, LooseObjectSchema, LooseObjectSchemaAsync, LooseTupleIssue, LooseTupleSchema, LooseTupleSchemaAsync, MapIssue, MapSchema, MapSchemaAsync, NonNullableIssue, NonNullableSchema, NonNullableSchemaAsync, NonNullishIssue, NonNullishSchema, NonNullishSchemaAsync, NonOptionalIssue, NonOptionalSchema, NonOptionalSchemaAsync, NullableSchema, NullableSchemaAsync, NullishSchema, NullishSchemaAsync, ObjectIssue, ObjectSchema, ObjectSchemaAsync, ObjectWithRestIssue, ObjectWithRestSchema, ObjectWithRestSchemaAsync, OptionalSchema, OptionalSchemaAsync, RecordIssue, RecordSchema, RecordSchemaAsync, SetIssue, SetSchema, SetSchemaAsync, StrictObjectIssue, StrictObjectSchema, StrictObjectSchemaAsync, StrictTupleIssue, StrictTupleSchema, StrictTupleSchemaAsync, TupleIssue, TupleSchema, TupleSchemaAsync, TupleWithRestIssue, TupleWithRestSchema, TupleWithRestSchemaAsync, UndefinedableSchema, UndefinedableSchemaAsync, UnionIssue, UnionSchema, UnionSchemaAsync, VariantIssue, VariantSchema, VariantSchemaAsync, } from '../schemas/index.ts'; import type { Config } from './config.ts'; import type { InferInput } from './infer.ts'; import type { ObjectEntries, ObjectEntriesAsync } from './object.ts'; import type { Default, DefaultAsync, ErrorMessage } from './other.ts'; import type { BaseSchema, BaseSchemaAsync } from './schema.ts'; import type { TupleItems, TupleItemsAsync } from './tuple.ts'; import type { FirstTupleItem, MaybeReadonly } from './utils.ts'; /** * Array path item interface. */ export interface ArrayPathItem { /** * The path item type. */ readonly type: 'array'; /** * The path item origin. */ readonly origin: 'value'; /** * The path item input. */ readonly input: MaybeReadonly; /** * The path item key. */ readonly key: number; /** * The path item value. */ readonly value: unknown; } /** * Map path item interface. */ export interface MapPathItem { /** * The path item type. */ readonly type: 'map'; /** * The path item origin. */ readonly origin: 'key' | 'value'; /** * The path item input. */ readonly input: Map; /** * The path item key. */ readonly key: unknown; /** * The path item value. */ readonly value: unknown; } /** * Object path item interface. */ export interface ObjectPathItem { /** * The path item type. */ readonly type: 'object'; /** * The path item origin. */ readonly origin: 'key' | 'value'; /** * The path item input. */ readonly input: Record; /** * The path item key. */ readonly key: string; /** * The path item value. */ readonly value: unknown; } /** * Set path item interface. */ export interface SetPathItem { /** * The path item type. */ readonly type: 'set'; /** * The path item origin. */ readonly origin: 'value'; /** * The path item input. */ readonly input: Set; /** * The path item key. */ readonly key: null; /** * The path item key. */ readonly value: unknown; } /** * Unknown path item interface. */ export 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. */ export type IssuePathItem = | ArrayPathItem | MapPathItem | ObjectPathItem | SetPathItem | UnknownPathItem; /** * Base issue interface. */ export interface BaseIssue extends Config> { /** * The issue kind. */ readonly kind: 'schema' | 'validation' | 'transformation'; /** * The issue type. */ readonly type: string; /** * The raw input data. */ readonly input: TInput; /** * 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, ...BaseIssue[]] | undefined; } /** * Generic issue type. */ export type GenericIssue = BaseIssue; /** * Dot path type. */ type DotPath< TKey extends string | number | symbol, TSchema extends | BaseSchema> | BaseSchemaAsync>, > = TKey extends string | number ? `${TKey}` | `${TKey}.${IssueDotPath}` : never; /** * Object path type. */ type ObjectPath = { [TKey in keyof TEntries]: DotPath; }[keyof TEntries]; /** * Tuple keys type. */ type TupleKeys = Exclude< keyof TItems, keyof [] >; /** * Tuple path type. */ type TuplePath = { [TKey in TupleKeys]: TItems[TKey] extends | BaseSchema> | BaseSchemaAsync> ? DotPath : never; }[TupleKeys]; /** * Issue dot path type. */ export type IssueDotPath< TSchema extends | BaseSchema> | BaseSchemaAsync>, > = // Pipe (sync) TSchema extends SchemaWithPipe ? IssueDotPath> : // Pipe (async) TSchema extends SchemaWithPipeAsync ? IssueDotPath> : // Array (sync) TSchema extends ArraySchema< infer TItem, ErrorMessage | undefined > ? DotPath : // Array (async) TSchema extends ArraySchemaAsync< infer TItem, ErrorMessage | undefined > ? DotPath : // Intersect, Union or Variant (sync) TSchema extends | IntersectSchema< infer TOptions, ErrorMessage | undefined > | UnionSchema< infer TOptions, ErrorMessage>> | undefined > | VariantSchema< string, infer TOptions, ErrorMessage | undefined > ? IssueDotPath : // Intersect, Union or Variant (async) TSchema extends | IntersectSchemaAsync< infer TOptions, ErrorMessage | undefined > | UnionSchemaAsync< infer TOptions, ErrorMessage>> | undefined > | VariantSchemaAsync< string, infer TOptions, ErrorMessage | undefined > ? IssueDotPath : // Map or Record (sync) TSchema extends | MapSchema< infer TKey, infer TValue, ErrorMessage | undefined > | RecordSchema< infer TKey, infer TValue, ErrorMessage | undefined > ? DotPath, TValue> : // Map or Record (async) TSchema extends | MapSchemaAsync< infer TKey, infer TValue, ErrorMessage | undefined > | RecordSchemaAsync< infer TKey, infer TValue, ErrorMessage | undefined > ? DotPath, TValue> : // Object (sync) TSchema extends | LooseObjectSchema< infer TEntries, ErrorMessage | undefined > | ObjectSchema< infer TEntries, ErrorMessage | undefined > | StrictObjectSchema< infer TEntries, ErrorMessage | undefined > ? ObjectPath : // Object (async) TSchema extends | LooseObjectSchemaAsync< infer TEntries, ErrorMessage | undefined > | ObjectSchemaAsync< infer TEntries, ErrorMessage | undefined > | StrictObjectSchemaAsync< infer TEntries, ErrorMessage | undefined > ? ObjectPath : // Object with Rest (sync) TSchema extends ObjectWithRestSchema< ObjectEntries, BaseSchema>, ErrorMessage | undefined > ? string : // Object with Rest (async) TSchema extends ObjectWithRestSchemaAsync< ObjectEntriesAsync, | BaseSchema> | BaseSchemaAsync< unknown, unknown, BaseIssue >, ErrorMessage | undefined > ? string : // Set (sync) TSchema extends SetSchema< infer TValue, ErrorMessage | undefined > ? DotPath : // Set (async) TSchema extends SetSchemaAsync< infer TValue, ErrorMessage | undefined > ? DotPath : // Tuple (sync) TSchema extends | LooseTupleSchema< infer TItems, | ErrorMessage | undefined > | StrictTupleSchema< infer TItems, | ErrorMessage | undefined > | TupleSchema< infer TItems, ErrorMessage | undefined > ? TuplePath : // Tuple (async) TSchema extends | LooseTupleSchemaAsync< infer TItems, | ErrorMessage | undefined > | StrictTupleSchemaAsync< infer TItems, | ErrorMessage | undefined > | TupleSchemaAsync< infer TItems, ErrorMessage | undefined > ? TuplePath : // Tuple with Rest (sync) TSchema extends TupleWithRestSchema< infer TItems, infer TRest, | ErrorMessage | undefined > ? TuplePath | DotPath : // Tuple with Rest (async) TSchema extends TupleWithRestSchemaAsync< infer TItems, infer TRest, | ErrorMessage | undefined > ? | TuplePath | DotPath : // Wrapped (sync) TSchema extends | ExactOptionalSchema< infer TWrapped, Default< BaseSchema< unknown, unknown, BaseIssue >, never > > | LazySchema | NonNullableSchema< infer TWrapped, | ErrorMessage | undefined > | NonNullishSchema< infer TWrapped, | ErrorMessage | undefined > | NonOptionalSchema< infer TWrapped, | ErrorMessage | undefined > | NullableSchema< infer TWrapped, Default< BaseSchema< unknown, unknown, BaseIssue >, null > > | NullishSchema< infer TWrapped, Default< BaseSchema< unknown, unknown, BaseIssue >, null | undefined > > | OptionalSchema< infer TWrapped, Default< BaseSchema< unknown, unknown, BaseIssue >, undefined > > | UndefinedableSchema< infer TWrapped, Default< BaseSchema< unknown, unknown, BaseIssue >, undefined > > ? IssueDotPath : // Wrapped (async) TSchema extends | ExactOptionalSchemaAsync< infer TWrapped, DefaultAsync< | BaseSchema< unknown, unknown, BaseIssue > | BaseSchemaAsync< unknown, unknown, BaseIssue >, never > > | LazySchemaAsync | NonNullableSchemaAsync< infer TWrapped, | ErrorMessage | undefined > | NonNullishSchemaAsync< infer TWrapped, | ErrorMessage | undefined > | NonOptionalSchemaAsync< infer TWrapped, | ErrorMessage | undefined > | NullableSchemaAsync< infer TWrapped, DefaultAsync< | BaseSchema< unknown, unknown, BaseIssue > | BaseSchemaAsync< unknown, unknown, BaseIssue >, null > > | NullishSchemaAsync< infer TWrapped, DefaultAsync< | BaseSchema< unknown, unknown, BaseIssue > | BaseSchemaAsync< unknown, unknown, BaseIssue >, null | undefined > > | OptionalSchemaAsync< infer TWrapped, DefaultAsync< | BaseSchema< unknown, unknown, BaseIssue > | BaseSchemaAsync< unknown, unknown, BaseIssue >, undefined > > | UndefinedableSchemaAsync< infer TWrapped, DefaultAsync< | BaseSchema< unknown, unknown, BaseIssue > | BaseSchemaAsync< unknown, unknown, BaseIssue >, undefined > > ? IssueDotPath : // Otherwise never; ================================================ FILE: library/src/types/metadata.ts ================================================ /** * Base metadata interface. */ export interface BaseMetadata { /** * The object kind. */ readonly kind: 'metadata'; /** * The metadata type. */ readonly type: string; /** * The metadata reference. */ readonly reference: ( // eslint-disable-next-line @typescript-eslint/no-explicit-any ...args: any[] // eslint-disable-next-line @typescript-eslint/no-explicit-any ) => BaseMetadata; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: TInput; readonly output: TInput; readonly issue: never; } | undefined; } /** * Generic metadata type. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any export type GenericMetadata = BaseMetadata; ================================================ FILE: library/src/types/object.ts ================================================ import type { ReadonlyAction } from '../actions/index.ts'; import type { SchemaWithFallback, SchemaWithFallbackAsync, SchemaWithPipe, SchemaWithPipeAsync, } from '../methods/index.ts'; import type { ExactOptionalSchema, ExactOptionalSchemaAsync, LooseObjectIssue, LooseObjectSchema, LooseObjectSchemaAsync, NullishSchema, NullishSchemaAsync, ObjectIssue, ObjectSchema, ObjectSchemaAsync, ObjectWithRestIssue, ObjectWithRestSchema, ObjectWithRestSchemaAsync, OptionalSchema, OptionalSchemaAsync, StrictObjectIssue, StrictObjectSchema, StrictObjectSchemaAsync, } from '../schemas/index.ts'; import type { InferInput, InferIssue, InferOutput } from './infer.ts'; import type { BaseIssue } from './issue.ts'; import type { ErrorMessage } from './other.ts'; import type { BaseSchema, BaseSchemaAsync } from './schema.ts'; import type { MarkOptional, MaybeReadonly, Prettify } from './utils.ts'; /** * Optional entry schema type. */ export type OptionalEntrySchema = | ExactOptionalSchema< BaseSchema>, unknown > | NullishSchema>, unknown> | OptionalSchema>, unknown>; /** * Optional entry schema async type. */ export type OptionalEntrySchemaAsync = | ExactOptionalSchemaAsync< | BaseSchema> | BaseSchemaAsync>, unknown > | NullishSchemaAsync< | BaseSchema> | BaseSchemaAsync>, unknown > | OptionalSchemaAsync< | BaseSchema> | BaseSchemaAsync>, unknown >; /** * Object entries interface. */ export interface ObjectEntries { [key: string]: | BaseSchema> | SchemaWithFallback< BaseSchema>, unknown > | OptionalEntrySchema; } /** * Object entries async interface. */ export interface ObjectEntriesAsync { [key: string]: | BaseSchema> | BaseSchemaAsync> | SchemaWithFallback< BaseSchema>, unknown > | SchemaWithFallbackAsync< | BaseSchema> | BaseSchemaAsync>, unknown > | OptionalEntrySchema | OptionalEntrySchemaAsync; } /** * Object keys type. */ export type ObjectKeys< TSchema extends | LooseObjectSchema< ObjectEntries, ErrorMessage | undefined > | LooseObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined > | ObjectSchema | undefined> | ObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined > | ObjectWithRestSchema< ObjectEntries, BaseSchema>, ErrorMessage | undefined > | ObjectWithRestSchemaAsync< ObjectEntriesAsync, | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined > | StrictObjectSchema< ObjectEntries, ErrorMessage | undefined > | StrictObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined >, > = MaybeReadonly<[keyof TSchema['entries'], ...(keyof TSchema['entries'])[]]>; /** * Infer entries input type. */ type InferEntriesInput = { -readonly [TKey in keyof TEntries]: InferInput; }; /** * Infer entries output type. */ type InferEntriesOutput = { -readonly [TKey in keyof TEntries]: InferOutput; }; /** * Optional input keys type. */ type OptionalInputKeys = { [TKey in keyof TEntries]: TEntries[TKey] extends | OptionalEntrySchema | OptionalEntrySchemaAsync ? TKey : never; }[keyof TEntries]; /** * Optional output keys type. */ type OptionalOutputKeys = { [TKey in keyof TEntries]: TEntries[TKey] extends | OptionalEntrySchema | OptionalEntrySchemaAsync ? undefined extends TEntries[TKey]['default'] ? TKey : never : never; }[keyof TEntries]; /** * Input with question marks type. */ type InputWithQuestionMarks< TEntries extends ObjectEntries | ObjectEntriesAsync, TObject extends InferEntriesInput, > = MarkOptional>; /** * Output with question marks type. */ type OutputWithQuestionMarks< TEntries extends ObjectEntries | ObjectEntriesAsync, TObject extends InferEntriesOutput, > = MarkOptional>; /** * Readonly output keys type. */ type ReadonlyOutputKeys = { [TKey in keyof TEntries]: TEntries[TKey] extends | SchemaWithPipe | SchemaWithPipeAsync ? // eslint-disable-next-line @typescript-eslint/no-explicit-any ReadonlyAction extends TPipe[number] ? TKey : never : never; }[keyof TEntries]; /** * Output with readonly type. */ type OutputWithReadonly< TEntries extends ObjectEntries | ObjectEntriesAsync, TObject extends OutputWithQuestionMarks< TEntries, InferEntriesOutput >, > = Readonly & Pick>>; /** * Infer object input type. */ export type InferObjectInput< TEntries extends ObjectEntries | ObjectEntriesAsync, > = Prettify>>; /** * Infer object output type. */ export type InferObjectOutput< TEntries extends ObjectEntries | ObjectEntriesAsync, > = Prettify< OutputWithReadonly< TEntries, OutputWithQuestionMarks> > >; /** * Infer object issue type. */ export type InferObjectIssue< TEntries extends ObjectEntries | ObjectEntriesAsync, > = InferIssue; ================================================ FILE: library/src/types/other.ts ================================================ import type { Config } from './config.ts'; import type { UnknownDataset } from './dataset.ts'; import type { InferInput, InferIssue } from './infer.ts'; import type { BaseIssue } from './issue.ts'; import type { BaseSchema, BaseSchemaAsync } from './schema.ts'; import type { MaybeDeepReadonly, MaybePromise } from './utils.ts'; /** * Error message type. */ export type ErrorMessage> = | ((issue: TIssue) => string) | string; /** * Default type. */ export type Default< TWrapped extends BaseSchema>, TInput extends null | undefined, > = | MaybeDeepReadonly | TInput> | (( dataset?: UnknownDataset, config?: Config> ) => MaybeDeepReadonly | TInput>) | undefined; /** * Default async type. */ export type DefaultAsync< TWrapped extends | BaseSchema> | BaseSchemaAsync>, TInput extends null | undefined, > = | MaybeDeepReadonly | TInput> | (( dataset?: UnknownDataset, config?: Config> ) => MaybePromise | TInput>>) | undefined; /** * Default value type. */ export type DefaultValue< TDefault extends | Default< BaseSchema>, null | undefined > | DefaultAsync< | BaseSchema> | BaseSchemaAsync>, null | undefined >, > = TDefault extends DefaultAsync< infer TWrapped extends | BaseSchema> | BaseSchemaAsync>, infer TInput > ? TDefault extends ( dataset?: UnknownDataset, config?: Config> ) => MaybePromise | TInput>> ? Awaited> : TDefault : never; ================================================ FILE: library/src/types/pipe.ts ================================================ import type { BaseIssue } from './issue.ts'; import type { BaseMetadata } from './metadata.ts'; import type { BaseSchema, BaseSchemaAsync } from './schema.ts'; import type { BaseTransformation, BaseTransformationAsync, } from './transformation.ts'; import type { BaseValidation, BaseValidationAsync } from './validation.ts'; /** * Pipe action type. */ export type PipeAction> = | BaseValidation | BaseTransformation | BaseMetadata; /** * Pipe action async type. */ export type PipeActionAsync< TInput, TOutput, TIssue extends BaseIssue, > = | BaseValidationAsync | BaseTransformationAsync; /** * Pipe item type. */ export type PipeItem> = | BaseSchema | PipeAction; /** * Pipe item async type. */ export type PipeItemAsync> = | BaseSchemaAsync | PipeActionAsync; /** * Schema without pipe type. */ export type SchemaWithoutPipe< TSchema extends | BaseSchema> | BaseSchemaAsync>, > = TSchema & { pipe?: never }; /** * Generic pipe action type. */ export type GenericPipeAction< // eslint-disable-next-line @typescript-eslint/no-explicit-any TInput = any, TOutput = TInput, TIssue extends BaseIssue = BaseIssue, > = PipeAction; /** * Generic pipe action async type. */ export type GenericPipeActionAsync< // eslint-disable-next-line @typescript-eslint/no-explicit-any TInput = any, TOutput = TInput, TIssue extends BaseIssue = BaseIssue, > = PipeActionAsync; /** * Generic pipe item type. */ export type GenericPipeItem< // eslint-disable-next-line @typescript-eslint/no-explicit-any TInput = any, TOutput = TInput, TIssue extends BaseIssue = BaseIssue, > = PipeItem; /** * Generic pipe item async type. */ export type GenericPipeItemAsync< // eslint-disable-next-line @typescript-eslint/no-explicit-any TInput = any, TOutput = TInput, TIssue extends BaseIssue = BaseIssue, > = PipeItemAsync; ================================================ FILE: library/src/types/schema.ts ================================================ import type { Config } from './config.ts'; import type { OutputDataset, UnknownDataset } from './dataset.ts'; import type { BaseIssue } from './issue.ts'; import type { StandardProps } from './standard.ts'; /** * Base schema interface. */ export interface BaseSchema< TInput, TOutput, TIssue extends BaseIssue, > { /** * The object kind. */ readonly kind: 'schema'; /** * The schema type. */ readonly type: string; /** * The schema reference. */ readonly reference: ( // eslint-disable-next-line @typescript-eslint/no-explicit-any ...args: any[] ) => BaseSchema>; /** * The expected property. */ readonly expects: string; /** * Whether it's async. */ readonly async: false; /** * The Standard Schema properties. * * @internal */ readonly '~standard': StandardProps; /** * Parses unknown input values. * * @param dataset The input dataset. * @param config The configuration. * * @returns The output dataset. * * @internal */ readonly '~run': ( dataset: UnknownDataset, config: Config> ) => OutputDataset; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: TInput; readonly output: TOutput; readonly issue: TIssue; } | undefined; } /** * Base schema async interface. */ export interface BaseSchemaAsync< TInput, TOutput, TIssue extends BaseIssue, > extends Omit< BaseSchema, 'reference' | 'async' | '~run' > { /** * The schema reference. */ readonly reference: ( // eslint-disable-next-line @typescript-eslint/no-explicit-any ...args: any[] ) => | BaseSchema> | BaseSchemaAsync>; /** * 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> ) => Promise>; } /** * Generic schema type. */ export type GenericSchema< TInput = unknown, TOutput = TInput, TIssue extends BaseIssue = BaseIssue, > = BaseSchema; /** * Generic schema async type. */ export type GenericSchemaAsync< TInput = unknown, TOutput = TInput, TIssue extends BaseIssue = BaseIssue, > = BaseSchemaAsync; ================================================ FILE: library/src/types/standard.ts ================================================ /** * The Standard Schema properties interface. */ export interface StandardProps { /** * 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 | Promise>; /** * Inferred types associated with the schema. */ readonly types?: StandardTypes | undefined; } /** * The result interface of the validate function. */ export type StandardResult = | StandardSuccessResult | StandardFailureResult; /** * The result interface if validation succeeds. */ export interface StandardSuccessResult { /** * The typed output value. */ readonly value: TOutput; /** * The non-existent issues. */ readonly issues?: undefined; } /** * The result interface if validation fails. */ export interface StandardFailureResult { /** * The issues of failed validation. */ readonly issues: readonly StandardIssue[]; } /** * The issue interface of the failure output. */ export 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. */ export interface StandardPathItem { /** * The key of the path item. */ readonly key: PropertyKey; } /** * The Standard Schema types interface. */ export interface StandardTypes { /** * The input type of the schema. */ readonly input: TInput; /** * The output type of the schema. */ readonly output: TOutput; } ================================================ FILE: library/src/types/transformation.ts ================================================ import type { Config } from './config.ts'; import type { OutputDataset, SuccessDataset } from './dataset.ts'; import type { BaseIssue } from './issue.ts'; /** * Base transformation interface. */ export interface BaseTransformation< TInput, TOutput, TIssue extends BaseIssue, > { /** * The object kind. */ readonly kind: 'transformation'; /** * The transformation type. */ readonly type: string; /** * The transformation reference. */ readonly reference: ( // eslint-disable-next-line @typescript-eslint/no-explicit-any ...args: any[] // eslint-disable-next-line @typescript-eslint/no-explicit-any ) => BaseTransformation>; /** * 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, config: Config> ) => OutputDataset | TIssue>; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: TInput; readonly output: TOutput; readonly issue: TIssue; } | undefined; } /** * Base transformation async interface. */ export interface BaseTransformationAsync< TInput, TOutput, TIssue extends BaseIssue, > extends Omit< BaseTransformation, 'reference' | 'async' | '~run' > { /** * The transformation reference. */ readonly reference: ( // eslint-disable-next-line @typescript-eslint/no-explicit-any ...args: any[] ) => // eslint-disable-next-line @typescript-eslint/no-explicit-any | BaseTransformation> // eslint-disable-next-line @typescript-eslint/no-explicit-any | BaseTransformationAsync>; /** * 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, config: Config> ) => Promise | TIssue>>; } /** * Generic transformation type. */ export type GenericTransformation< // eslint-disable-next-line @typescript-eslint/no-explicit-any TInput = any, TOutput = TInput, TIssue extends BaseIssue = BaseIssue, > = BaseTransformation; /** * Generic transformation async type. */ export type GenericTransformationAsync< // eslint-disable-next-line @typescript-eslint/no-explicit-any TInput = any, TOutput = TInput, TIssue extends BaseIssue = BaseIssue, > = BaseTransformationAsync; ================================================ FILE: library/src/types/tuple.ts ================================================ import type { InferInput, InferIssue, InferOutput } from './infer.ts'; import type { BaseIssue } from './issue.ts'; import type { BaseSchema, BaseSchemaAsync } from './schema.ts'; import type { MaybeReadonly } from './utils.ts'; /** * Tuple items type. */ export type TupleItems = MaybeReadonly< BaseSchema>[] >; /** * Tuple items async type. */ export type TupleItemsAsync = MaybeReadonly< ( | BaseSchema> | BaseSchemaAsync> )[] >; /** * Infer tuple input type. */ export type InferTupleInput = { -readonly [TKey in keyof TItems]: InferInput; }; /** * Infer tuple output type. */ export type InferTupleOutput = { -readonly [TKey in keyof TItems]: InferOutput; }; /** * Infer tuple issue type. */ export type InferTupleIssue = InferIssue; ================================================ FILE: library/src/types/utils.ts ================================================ /** * Checks if a type is `any`. */ export type IsAny = 0 extends 1 & Type ? true : false; /** * Checks if a type is `never`. */ export type IsNever = [Type] extends [never] ? true : false; /** * Extracts `null` from a type. */ export type NonNullable = TValue extends null ? never : TValue; /** * Extracts `null` and `undefined` from a type. */ export type NonNullish = TValue extends null | undefined ? never : TValue; /** * Extracts `undefined` from a type. */ export type NonOptional = TValue extends undefined ? never : TValue; /** * Constructs a type that is maybe readonly. */ export type MaybeReadonly = TValue | Readonly; /** * Constructs a type that is deeply readonly. */ export type DeepReadonly = TValue extends | Record | readonly unknown[] ? { readonly [TKey in keyof TValue]: DeepReadonly } : TValue; /** * Constructs a type that is maybe deeply readonly. */ export type MaybeDeepReadonly = TValue | DeepReadonly; /** * Constructs a type that is maybe a promise. */ export type MaybePromise = TValue | Promise; /** * Prettifies a type for better readability. * * Hint: This type has no effect and is only used so that TypeScript displays * the final type in the preview instead of the utility types used. */ export type Prettify = { [TKey in keyof TObject]: TObject[TKey] } & {}; /** * Marks specific keys as optional. */ export type MarkOptional = // Mapping any entry to unknown preserves key order in final output { [TKey in keyof TObject]?: unknown } & Omit & Partial>; /** * Merges two objects. Overlapping entries from the second object overwrite * properties from the first object. */ export type Merge = Omit< TFirstObject, keyof TFirstObject & keyof TSecondObject > & TSecondObject; /** * Extracts first tuple item. */ export type FirstTupleItem = TTuple[0]; /** * Extracts last tuple item. */ export type LastTupleItem = TTuple[TTuple extends readonly [unknown, ...infer TRest] ? TRest['length'] : never]; /** * Converts union to intersection type. */ export type UnionToIntersect = // eslint-disable-next-line @typescript-eslint/no-explicit-any (TUnion extends any ? (arg: TUnion) => void : never) extends ( arg: infer Intersect ) => void ? Intersect : never; /** * Converts union to tuple type using an accumulator. * * For more information: {@link https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-5.html#tail-recursion-elimination-on-conditional-types} */ type UnionToTupleHelper = UnionToIntersect< TUnion extends never ? never : () => TUnion > extends () => infer TLast ? UnionToTupleHelper, [TLast, ...TResult]> : TResult; /** * Converts union to tuple type. */ export type UnionToTuple = UnionToTupleHelper; ================================================ FILE: library/src/types/validation.ts ================================================ import type { Config } from './config.ts'; import type { OutputDataset } from './dataset.ts'; import type { BaseIssue } from './issue.ts'; /** * Base validation interface. */ export interface BaseValidation< TInput, TOutput, TIssue extends BaseIssue, > { /** * The object kind. */ readonly kind: 'validation'; /** * The validation type. */ readonly type: string; /** * The validation reference. */ readonly reference: ( // eslint-disable-next-line @typescript-eslint/no-explicit-any ...args: any[] // eslint-disable-next-line @typescript-eslint/no-explicit-any ) => BaseValidation>; /** * 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>, config: Config> ) => OutputDataset | TIssue>; /** * The input, output and issue type. * * @internal */ readonly '~types'?: | { readonly input: TInput; readonly output: TOutput; readonly issue: TIssue; } | undefined; } /** * Base validation async interface. */ export interface BaseValidationAsync< TInput, TOutput, TIssue extends BaseIssue, > extends Omit< BaseValidation, 'reference' | 'async' | '~run' > { /** * The validation reference. */ readonly reference: ( // eslint-disable-next-line @typescript-eslint/no-explicit-any ...args: any[] ) => // eslint-disable-next-line @typescript-eslint/no-explicit-any | BaseValidation> // eslint-disable-next-line @typescript-eslint/no-explicit-any | BaseValidationAsync>; /** * 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>, config: Config> ) => Promise | TIssue>>; } /** * Generic validation type. */ export type GenericValidation< // eslint-disable-next-line @typescript-eslint/no-explicit-any TInput = any, TOutput = TInput, TIssue extends BaseIssue = BaseIssue, > = BaseValidation; /** * Generic validation async type. */ export type GenericValidationAsync< // eslint-disable-next-line @typescript-eslint/no-explicit-any TInput = any, TOutput = TInput, TIssue extends BaseIssue = BaseIssue, > = BaseValidationAsync; ================================================ FILE: library/src/utils/ValiError/ValiError.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { minLength, type MinLengthIssue, url, type UrlIssue, } from '../../actions/index.ts'; import { pipe } from '../../methods/index.ts'; import { string, type StringIssue } from '../../schemas/index.ts'; import { ValiError } from './ValiError.ts'; describe('ValiError', () => { test('should infer issues from schema', () => { // eslint-disable-next-line @typescript-eslint/no-unused-vars const schema = pipe(string(), minLength(10), url()); const error = new ValiError([ { kind: 'validation', type: 'min_length', input: 'foo', expected: '>=10', received: '3', message: 'Invalid length: Expected >=10 but received 3', requirement: 10, }, ]); type Issue = StringIssue | MinLengthIssue | UrlIssue; expectTypeOf(error.issues).toEqualTypeOf<[Issue, ...Issue[]]>(); }); }); ================================================ FILE: library/src/utils/ValiError/ValiError.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { MinLengthIssue, UrlIssue } from '../../actions/index.ts'; import { ValiError } from './ValiError.ts'; describe('ValiError', () => { test('should create error instance', () => { const minLengthIssue: MinLengthIssue = { kind: 'validation', type: 'min_length', input: 'foo', expected: '>=10', received: '3', message: 'Invalid length: Expected >=10 but received 3', requirement: 10, }; const urlIssue: UrlIssue = { kind: 'validation', type: 'url', input: 'foo', expected: null, received: '"foo"', message: 'Invalid URL: Received "foo"', requirement: expect.any(Function), }; const error = new ValiError([minLengthIssue, urlIssue]); expect(error).toBeInstanceOf(ValiError); expect(error.name).toBe('ValiError'); expect(error.message).toBe(minLengthIssue.message); expect(error.issues).toStrictEqual([minLengthIssue, urlIssue]); }); }); ================================================ FILE: library/src/utils/ValiError/ValiError.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, InferIssue, } from '../../types/index.ts'; /** * A Valibot error with useful information. */ export class ValiError< TSchema extends | BaseSchema> | BaseSchemaAsync>, > extends Error { /** * The error issues. */ public readonly issues: [InferIssue, ...InferIssue[]]; /** * Creates a Valibot error with useful information. * * @param issues The error issues. */ // @__NO_SIDE_EFFECTS__ constructor(issues: [InferIssue, ...InferIssue[]]) { super(issues[0].message); this.name = 'ValiError'; this.issues = issues; } } ================================================ FILE: library/src/utils/ValiError/index.ts ================================================ export * from './ValiError.ts'; ================================================ FILE: library/src/utils/_addIssue/_addIssue.test.ts ================================================ import { afterEach, describe, expect, test } from 'vitest'; import { decimal, type DecimalIssue, minLength, type MinLengthIssue, url, } from '../../actions/index.ts'; import { DECIMAL_REGEX } from '../../regex.ts'; import { number, type NumberIssue, string } from '../../schemas/index.ts'; import { deleteGlobalMessage, deleteSchemaMessage, deleteSpecificMessage, setGlobalMessage, setSchemaMessage, setSpecificMessage, } from '../../storages/index.ts'; import type { BaseIssue, FailureDataset, IssuePathItem, PartialDataset, SuccessDataset, UnknownDataset, } from '../../types/index.ts'; import { _addIssue } from './_addIssue.ts'; describe('_addIssue', () => { describe('should add issue to dataset', () => { const baseInfo = { path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; type MinLength1Issue = MinLengthIssue; const minLengthIssue: MinLength1Issue = { ...baseInfo, kind: 'validation', type: 'min_length', input: '', expected: '>=1', received: '0', message: 'Invalid length: Expected >=1 but received 0', requirement: 1, }; const dataset: SuccessDataset = { typed: true, value: '' }; test('for issue one', () => { _addIssue(minLength(1), 'length', dataset, {}, { received: '0' }); expect(dataset).toStrictEqual({ typed: true, value: '', issues: [minLengthIssue], } satisfies PartialDataset); }); const decimalIssue: DecimalIssue = { ...baseInfo, kind: 'validation', type: 'decimal', input: '', expected: null, received: '""', message: 'Invalid decimal: Received ""', requirement: DECIMAL_REGEX, }; test('for issue two', () => { _addIssue(decimal(), 'decimal', dataset, {}); expect(dataset).toStrictEqual({ typed: true, value: '', issues: [minLengthIssue, decimalIssue], } satisfies PartialDataset< string, MinLength1Issue | DecimalIssue >); }); }); describe('should generate default message', () => { test('with expected and received', () => { const dataset: UnknownDataset = { value: null }; _addIssue(string(), 'type', dataset, {}); // @ts-expect-error expect(dataset.issues?.[0].message).toBe( 'Invalid type: Expected string but received null' ); }); test('with only received', () => { const dataset: SuccessDataset = { typed: true, value: 'foo', }; _addIssue(url(), 'URL', dataset, {}); // @ts-expect-error expect(dataset.issues?.[0].message).toBe('Invalid URL: Received "foo"'); }); }); describe('should include custom message', () => { const contextMessage = 'context message'; const configMessage = 'config message'; const specificMessage = 'specific message'; const schemaMessage = 'schema message'; const globalMessage = 'global message'; afterEach(() => { deleteGlobalMessage(); deleteSchemaMessage(); deleteSpecificMessage(string); }); test('from context object', () => { setSpecificMessage(string, specificMessage); setSchemaMessage(() => schemaMessage); setGlobalMessage(globalMessage); const dataset: UnknownDataset = { value: null }; _addIssue(string(contextMessage), 'type', dataset, { message: () => configMessage, }); // @ts-expect-error expect(dataset.issues?.[0].message).toBe(contextMessage); }); test('from context object with empty string', () => { setSpecificMessage(string, specificMessage); setSchemaMessage(() => schemaMessage); setGlobalMessage(globalMessage); const dataset: UnknownDataset = { value: null }; _addIssue(string(''), 'type', dataset, { message: () => configMessage, }); // @ts-expect-error expect(dataset.issues?.[0].message).toBe(''); }); test('from specific storage', () => { setSpecificMessage(string, specificMessage); setSchemaMessage(() => schemaMessage); setGlobalMessage(globalMessage); const dataset: UnknownDataset = { value: null }; _addIssue(string(), 'type', dataset, { message: () => configMessage, }); // @ts-expect-error expect(dataset.issues?.[0].message).toBe(specificMessage); }); test('from specific storage with empty string', () => { setSpecificMessage(string, ''); setSchemaMessage(() => schemaMessage); setGlobalMessage(globalMessage); const dataset: UnknownDataset = { value: null }; _addIssue(string(), 'type', dataset, { message: () => configMessage, }); // @ts-expect-error expect(dataset.issues?.[0].message).toBe(''); }); test('from schema storage', () => { setSchemaMessage(() => schemaMessage); setGlobalMessage(globalMessage); const dataset: UnknownDataset = { value: null }; _addIssue(string(), 'type', dataset, { message: () => configMessage, }); // @ts-expect-error expect(dataset.issues?.[0].message).toBe(schemaMessage); }); test('from schema storage with empty string', () => { setSchemaMessage(() => ''); setGlobalMessage(globalMessage); const dataset: UnknownDataset = { value: null }; _addIssue(string(), 'type', dataset, { message: () => configMessage, }); // @ts-expect-error expect(dataset.issues?.[0].message).toBe(''); }); test('not from schema storage', () => { setSchemaMessage(() => schemaMessage); setGlobalMessage(globalMessage); const dataset: SuccessDataset = { typed: true, value: 'foo', }; _addIssue(url(), 'type', dataset, { message: () => configMessage, }); // @ts-expect-error expect(dataset.issues?.[0].message).not.toBe(schemaMessage); }); test('from config object', () => { setGlobalMessage(globalMessage); const dataset: UnknownDataset = { value: null }; _addIssue(string(), 'type', dataset, { message: () => configMessage, }); // @ts-expect-error expect(dataset.issues?.[0].message).toBe(configMessage); }); test('from config object with empty string', () => { setGlobalMessage(globalMessage); const dataset: UnknownDataset = { value: null }; _addIssue(string(), 'type', dataset, { message: () => '', }); // @ts-expect-error expect(dataset.issues?.[0].message).toBe(''); }); test('from global storage', () => { setGlobalMessage(globalMessage); const dataset: UnknownDataset = { value: null }; _addIssue(string(), 'type', dataset, {}); // @ts-expect-error expect(dataset.issues?.[0].message).toBe(globalMessage); }); test('from global storage with empty string', () => { setGlobalMessage(''); const dataset: UnknownDataset = { value: null }; _addIssue(string(), 'type', dataset, {}); // @ts-expect-error expect(dataset.issues?.[0].message).toBe(''); }); }); test('should include configuration', () => { const dataset: UnknownDataset = { value: null }; const config = { lang: 'en', abortEarly: true, abortPipeEarly: true, }; _addIssue(string(), 'type', dataset, config); expect(dataset.issues?.[0]).toMatchObject(config); }); test('should include other information', () => { const dataset: UnknownDataset = { value: null }; const other = { received: '"foo"', expected: '"bar"', path: [ { type: 'object', origin: 'value', input: { key: 'foo' }, key: 'key', value: 'foo', }, ] satisfies [IssuePathItem], issues: [ { kind: 'schema', type: 'special', input: 'foo', expected: '"baz"', received: '"foo"', message: 'Custom messsage', }, ] satisfies [BaseIssue], }; _addIssue(string(), 'type', dataset, {}, other); expect(dataset.issues?.[0]).toMatchObject({ ...other, message: 'Invalid type: Expected "bar" but received "foo"', }); }); test('should set typed if schema to false', () => { const dataset: SuccessDataset = { typed: true, value: NaN, }; _addIssue(number(), 'type', dataset, {}); expect(dataset).toStrictEqual({ typed: false, value: NaN, issues: expect.any(Array), } satisfies FailureDataset); }); }); ================================================ FILE: library/src/utils/_addIssue/_addIssue.ts ================================================ import { getGlobalMessage, getSchemaMessage, getSpecificMessage, } from '../../storages/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, BaseTransformation, BaseTransformationAsync, BaseValidation, BaseValidationAsync, Config, ErrorMessage, InferInput, InferIssue, IssuePathItem, OutputDataset, UnknownDataset, } from '../../types/index.ts'; import { _stringify } from '../_stringify/index.ts'; /** * Context type. */ type Context = | BaseSchema> | BaseSchemaAsync> // eslint-disable-next-line @typescript-eslint/no-explicit-any | BaseValidation> // eslint-disable-next-line @typescript-eslint/no-explicit-any | BaseValidationAsync> // eslint-disable-next-line @typescript-eslint/no-explicit-any | BaseTransformation> // eslint-disable-next-line @typescript-eslint/no-explicit-any | BaseTransformationAsync>; /** * Other interface. */ interface Other { input?: unknown | undefined; expected?: string | undefined; received?: string | undefined; message?: ErrorMessage> | undefined; path?: [IssuePathItem, ...IssuePathItem[]] | undefined; issues?: | [BaseIssue>, ...BaseIssue>[]] | undefined; } /** * Adds an issue to the dataset. * * @param context The issue context. * @param label The issue label. * @param dataset The input dataset. * @param config The configuration. * @param other The optional props. * * @internal */ export function _addIssue( context: TContext & { expects?: string | null; requirement?: unknown; message?: | ErrorMessage, { type: TContext['type'] }>> | undefined; }, label: string, dataset: UnknownDataset | OutputDataset>, config: Config>, other?: Other ): void { // Get expected and received string const input = other && 'input' in other ? other.input : dataset.value; const expected = other?.expected ?? context.expects ?? null; const received = other?.received ?? _stringify(input); // Create issue object // Hint: The issue is deliberately not constructed with the spread operator // for performance reasons const issue: BaseIssue = { kind: context.kind, type: context.type, input, expected, received, message: `Invalid ${label}: ${ expected ? `Expected ${expected} but r` : 'R' }eceived ${received}`, requirement: context.requirement, path: other?.path, issues: other?.issues, lang: config.lang, abortEarly: config.abortEarly, abortPipeEarly: config.abortPipeEarly, }; // Check if context is a schema const isSchema = context.kind === 'schema'; // Get custom issue message const message = other?.message ?? context.message ?? getSpecificMessage(context.reference, issue.lang) ?? (isSchema ? getSchemaMessage(issue.lang) : null) ?? config.message ?? getGlobalMessage(issue.lang); // If custom message if specified, override default message if (message !== undefined) { // @ts-expect-error issue.message = typeof message === 'function' ? // @ts-expect-error message(issue) : message; } // If context is a schema, set typed to `false` if (isSchema) { dataset.typed = false; } // Add issue to dataset if (dataset.issues) { dataset.issues.push(issue); } else { // @ts-expect-error dataset.issues = [issue]; } } ================================================ FILE: library/src/utils/_addIssue/index.ts ================================================ export * from './_addIssue.ts'; ================================================ FILE: library/src/utils/_cloneDataset/_cloneDataset.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { BaseIssue, FailureDataset, PartialDataset, SuccessDataset, } from '../../types/index.ts'; import { _cloneDataset } from './_cloneDataset.ts'; describe('_cloneDataset', () => { test('should clone success dataset', () => { const value = { key: 'foo' }; const dataset: SuccessDataset = { typed: true, value, }; const clonedDataset = _cloneDataset(dataset); expect(clonedDataset).toStrictEqual({ typed: true, value, issues: undefined, }); expect(clonedDataset).not.toBe(dataset); expect(clonedDataset.value).toBe(value); }); test('should clone partial dataset issues array', () => { const issue: BaseIssue = { kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', message: 'Invalid type: Expected string but received 123', requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const dataset: PartialDataset> = { typed: true, value: 'foo', issues: [issue], }; const clonedDataset = _cloneDataset(dataset); expect(clonedDataset).toStrictEqual(dataset); expect(clonedDataset).not.toBe(dataset); expect(clonedDataset.issues).toBeDefined(); expect(clonedDataset.issues).not.toBe(dataset.issues); expect(clonedDataset.issues![0]).toBe(issue); }); test('should clone failure dataset issues array', () => { const issue: BaseIssue = { kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', message: 'Invalid type: Expected string but received 123', requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, }; const dataset: FailureDataset> = { typed: false, value: 123, issues: [issue], }; const clonedDataset = _cloneDataset(dataset); expect(clonedDataset).toStrictEqual(dataset); expect(clonedDataset).not.toBe(dataset); expect(clonedDataset.issues).toBeDefined(); expect(clonedDataset.issues).not.toBe(dataset.issues); }); }); ================================================ FILE: library/src/utils/_cloneDataset/_cloneDataset.ts ================================================ import type { BaseIssue, OutputDataset } from '../../types/index.ts'; /** * Creates a shallow copy of a dataset. * * Hint: The `value` is copied by reference, but the `issues` array is cloned * to avoid reusing mutable dataset state across multiple runs. Mutating a * returned object or array value can therefore affect later cache hits that * reuse the same cached output. * * @param dataset The output dataset. * * @returns The copied output dataset. */ // @__NO_SIDE_EFFECTS__ export function _cloneDataset>( dataset: OutputDataset ): OutputDataset { // Hint: We assign the known dataset properties directly instead of using the // spread operator for better runtime performance. // @ts-expect-error return { typed: dataset.typed, value: dataset.value, issues: dataset.issues && [...dataset.issues], }; } ================================================ FILE: library/src/utils/_cloneDataset/index.ts ================================================ export * from './_cloneDataset.ts'; ================================================ FILE: library/src/utils/_getByteCount/_getByteCount.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { _getByteCount } from './_getByteCount.ts'; describe('_getByteCount', () => { test('should return byte count', () => { expect(_getByteCount('hello world')).toBe(11); expect(_getByteCount('😀')).toBe(4); expect(_getByteCount('🧑🏻‍💻')).toBe(15); expect(_getByteCount('𝄞')).toBe(4); expect(_getByteCount('สวัสดี')).toBe(18); }); }); ================================================ FILE: library/src/utils/_getByteCount/_getByteCount.ts ================================================ let textEncoder: TextEncoder; /** * Returns the byte count of the input. * * @param input The input to be measured. * * @returns The byte count. * * @internal */ // @__NO_SIDE_EFFECTS__ export function _getByteCount(input: string): number { if (!textEncoder) { textEncoder = new TextEncoder(); } return textEncoder.encode(input).length; } ================================================ FILE: library/src/utils/_getByteCount/index.ts ================================================ export * from './_getByteCount.ts'; ================================================ FILE: library/src/utils/_getGraphemeCount/_getGraphemeCount.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { _getGraphemeCount } from './_getGraphemeCount.ts'; describe('_getGraphemeCount', () => { test('should return grapheme count', () => { expect(_getGraphemeCount('hello world')).toBe(11); expect(_getGraphemeCount('😀')).toBe(1); expect(_getGraphemeCount('🧑🏻‍💻')).toBe(1); expect(_getGraphemeCount('𝄞')).toBe(1); expect(_getGraphemeCount('สวัสดี')).toBe(4); }); }); ================================================ FILE: library/src/utils/_getGraphemeCount/_getGraphemeCount.ts ================================================ let segmenter: Intl.Segmenter; /** * Returns the grapheme count of the input. * * @param input The input to be measured. * * @returns The grapheme count. * * @internal */ // @__NO_SIDE_EFFECTS__ export function _getGraphemeCount(input: string): number { if (!segmenter) { segmenter = new Intl.Segmenter(); } const segments = segmenter.segment(input); let count = 0; // eslint-disable-next-line @typescript-eslint/no-unused-vars for (const _ of segments) { count++; } return count; } ================================================ FILE: library/src/utils/_getGraphemeCount/index.ts ================================================ export * from './_getGraphemeCount.ts'; ================================================ FILE: library/src/utils/_getLastMetadata/_getLastMetadata.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { email, title } from '../../actions/index.ts'; import { pipe } from '../../methods/index.ts'; import { string } from '../../schemas/index.ts'; import { _getLastMetadata } from './_getLastMetadata.ts'; describe('_getLastMetadata', () => { describe('should return undefined', () => { test('for schema without a pipeline', () => { expect(_getLastMetadata(string(), 'title')).toBeUndefined(); }); test('for schema with an empty pipeline', () => { expect(_getLastMetadata(pipe(string()), 'title')).toBeUndefined(); }); test('for schema without metadata', () => { expect( _getLastMetadata(pipe(string(), email()), 'title') ).toBeUndefined(); }); }); describe('should return last top-level metadata', () => { test('for simple schema with single metadata', () => { expect(_getLastMetadata(pipe(string(), title('foo')), 'title')).toBe( 'foo' ); }); test('for simple schema with multiple metadata', () => { expect( _getLastMetadata(pipe(string(), title('foo'), title('bar')), 'title') ).toBe('bar'); }); test('for schema with nested pipelines', () => { expect( _getLastMetadata( pipe(string(), title('foo'), pipe(string(), title('bar'))), 'title' ) ).toBe('foo'); expect( _getLastMetadata( pipe(string(), email(), pipe(string(), title('foo'))), 'title' ) ).toBe('foo'); expect( _getLastMetadata( pipe(pipe(string(), title('foo')), title('bar')), 'title' ) ).toBe('bar'); expect( _getLastMetadata(pipe(pipe(string(), title('foo')), email()), 'title') ).toBe('foo'); }); test('for schema with deeply nested pipelines', () => { expect( _getLastMetadata( pipe(pipe(pipe(string(), title('foo'))), email()), 'title' ) ).toBe('foo'); expect( _getLastMetadata( pipe(pipe(pipe(string(), title('foo')), title('bar')), email()), 'title' ) ).toBe('bar'); }); test('for nested schema without matching metadata', () => { expect( _getLastMetadata( pipe(pipe(string(), title('found')), pipe(string(), email())), 'title' ) ).toBe('found'); }); }); }); ================================================ FILE: library/src/utils/_getLastMetadata/_getLastMetadata.ts ================================================ import type { DescriptionAction, TitleAction } from '../../actions/index.ts'; import type { SchemaWithPipe, SchemaWithPipeAsync, } from '../../methods/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, PipeItem, PipeItemAsync, } from '../../types/index.ts'; /** * Metadata action type. */ type MetadataAction = | TitleAction | DescriptionAction; /** * Schema type. */ type Schema = | BaseSchema> | BaseSchemaAsync> | SchemaWithPipe< readonly [ BaseSchema>, // eslint-disable-next-line @typescript-eslint/no-explicit-any ...(PipeItem> | MetadataAction)[], ] > | SchemaWithPipeAsync< readonly [ ( | BaseSchema> | BaseSchemaAsync> ), ...( | PipeItem> // eslint-disable-line @typescript-eslint/no-explicit-any | PipeItemAsync> // eslint-disable-line @typescript-eslint/no-explicit-any | MetadataAction )[], ] >; /** * Returns the last top-level value of a given metadata type from a schema * using a breadth-first search that starts with the last item in the pipeline. * * @param schema The schema to search. * @param type The metadata type. * * @returns The value, if any. * * @internal */ // @__NO_SIDE_EFFECTS__ export function _getLastMetadata( schema: Schema, type: 'title' | 'description' ): string | undefined { if ('pipe' in schema) { const nestedSchemas: Schema[] = []; for (let index = schema.pipe.length - 1; index >= 0; index--) { const item = schema.pipe[index]; if (item.kind === 'schema' && 'pipe' in item) { nestedSchemas.push(item); } else if (item.kind === 'metadata' && item.type === type) { // @ts-expect-error return item[type]; } } for (const nestedSchema of nestedSchemas) { const result = _getLastMetadata(nestedSchema, type); if (result !== undefined) { return result; } } } } ================================================ FILE: library/src/utils/_getLastMetadata/index.ts ================================================ export * from './_getLastMetadata.ts'; ================================================ FILE: library/src/utils/_getStandardProps/_getStandardProps.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { transform } from '../../actions/index.ts'; import { pipe } from '../../methods/index.ts'; import { object, string } from '../../schemas/index.ts'; import type { StandardProps } from '../../types/index.ts'; import { _getStandardProps } from './_getStandardProps.ts'; describe('_getStandardProps', () => { test('should return spec properties', () => { expectTypeOf(_getStandardProps(string())).toEqualTypeOf< StandardProps >(); expectTypeOf( _getStandardProps(pipe(string(), transform(Number))) ).toEqualTypeOf>(); expectTypeOf( _getStandardProps( pipe( object({ foo: string() }), transform((input) => ({ ...input, bar: 123 })) ) ) ).toEqualTypeOf< StandardProps<{ foo: string }, { foo: string; bar: number }> >(); }); }); ================================================ FILE: library/src/utils/_getStandardProps/_getStandardProps.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { email, endsWith } from '../../actions/index.ts'; import { pipe } from '../../methods/index.ts'; import { array, object, string } from '../../schemas/index.ts'; import { deleteGlobalConfig, setGlobalConfig } from '../../storages/index.ts'; import type { StandardFailureResult, StandardProps, StandardSuccessResult, } from '../../types/index.ts'; import { _getStandardProps } from './_getStandardProps.ts'; describe('_getStandardProps', () => { test('should return spec properties', () => { expect(_getStandardProps(string())).toStrictEqual({ version: 1, vendor: 'valibot', validate: expect.any(Function), } satisfies StandardProps); }); test('should validate simple input', () => { const props = _getStandardProps(string()); expect(props.validate('foo')).toMatchObject({ value: 'foo', } satisfies StandardSuccessResult); expect(props.validate(null)).toMatchObject({ issues: [ { message: 'Invalid type: Expected string but received null', }, ], } satisfies StandardFailureResult); expect(props.validate(123)).toMatchObject({ issues: [ { message: 'Invalid type: Expected string but received 123', }, ], } satisfies StandardFailureResult); }); test('should validate complex input', () => { const props = _getStandardProps( object({ nested: array(object({ key: string() })) }) ); const input1 = { nested: [{ key: 'foo' }, { key: 'bar' }] }; expect(props.validate(input1)).toMatchObject({ value: input1, } satisfies StandardSuccessResult<{ nested: { key: string }[] }>); const input2 = { nested: [{ key: 'foo' }, { key: 123 }] }; expect(props.validate(input2)).toMatchObject({ issues: [ { message: 'Invalid type: Expected string but received 123', path: [{ key: 'nested' }, { key: 1 }, { key: 'key' }], }, ], } satisfies StandardFailureResult); }); test('should use global config', () => { const props = _getStandardProps( pipe(string(), email(), endsWith('@example.com')) ); expect(props.validate('foo')).toMatchObject({ issues: [ { message: 'Invalid email: Received "foo"', }, { message: 'Invalid end: Expected "@example.com" but received "foo"', }, ], } satisfies StandardFailureResult); setGlobalConfig({ abortPipeEarly: true }); expect(props.validate('foo')).toMatchObject({ issues: [ { message: 'Invalid email: Received "foo"', }, ], } satisfies StandardFailureResult); deleteGlobalConfig(); }); }); ================================================ FILE: library/src/utils/_getStandardProps/_getStandardProps.ts ================================================ import { getGlobalConfig } from '../../storages/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, InferInput, InferOutput, StandardProps, StandardResult, } from '../../types/index.ts'; /** * Returns the Standard Schema properties. * * @param context The schema context. * * @returns The Standard Schema properties. */ // @__NO_SIDE_EFFECTS__ export function _getStandardProps< TSchema extends | BaseSchema> | BaseSchemaAsync>, >(context: TSchema): StandardProps, InferOutput> { return { version: 1, vendor: 'valibot', validate(value) { return context['~run']({ value }, getGlobalConfig()) as | StandardResult> | Promise>>; }, }; } ================================================ FILE: library/src/utils/_getStandardProps/index.ts ================================================ export * from './_getStandardProps.ts'; ================================================ FILE: library/src/utils/_getWordCount/_getWordCount.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { _getWordCount } from './_getWordCount.ts'; describe('_getWordCount', () => { test('should return word count', () => { expect(_getWordCount('en', '')).toBe(0); expect(_getWordCount('en', 'h')).toBe(1); expect(_getWordCount('en', 'hello')).toBe(1); expect(_getWordCount('en', 'hello world')).toBe(2); expect(_getWordCount('en', '🧑🏻‍💻')).toBe(0); expect(_getWordCount('th', 'สวัสดี')).toBe(1); }); // TODO: This test is failing in CI, but works locally 😑 // test('should take locale into account', () => { // expect(_getWordCount('zh', 'foo:bar baz:qux')).toBe(4); // expect(_getWordCount('he', 'foo:bar baz:qux')).toBe(4); // expect(_getWordCount('sv', 'foo:bar baz:qux')).toBe(2); // expect(_getWordCount('fi', 'foo:bar baz:qux')).toBe(2); // }); }); ================================================ FILE: library/src/utils/_getWordCount/_getWordCount.ts ================================================ let store: Map; /** * Returns the word count of the input. * * @param locales The locales to be used. * @param input The input to be measured. * * @returns The word count. * * @internal */ // @__NO_SIDE_EFFECTS__ export function _getWordCount( locales: Intl.LocalesArgument, input: string ): number { if (!store) { store = new Map(); } if (!store.get(locales)) { store.set(locales, new Intl.Segmenter(locales, { granularity: 'word' })); } const segments = store.get(locales)!.segment(input); let count = 0; for (const segment of segments) { if (segment.isWordLike) { count++; } } return count; } ================================================ FILE: library/src/utils/_getWordCount/index.ts ================================================ export * from './_getWordCount.ts'; ================================================ FILE: library/src/utils/_isLuhnAlgo/_isLuhnAlgo.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { _isLuhnAlgo } from './_isLuhnAlgo.ts'; describe('_isLuhnAlgo', () => { test('should return true', () => { expect(_isLuhnAlgo('536498459191226')).toBe(true); expect(_isLuhnAlgo('860548042618881')).toBe(true); expect(_isLuhnAlgo('304517506893326')).toBe(true); expect(_isLuhnAlgo('378282246310005')).toBe(true); expect(_isLuhnAlgo('6011000990139424')).toBe(true); expect(_isLuhnAlgo('7238493252455')).toBe(true); expect(_isLuhnAlgo('8924578427422')).toBe(true); }); test('should return false', () => { expect(_isLuhnAlgo('53649845919122')).toBe(false); expect(_isLuhnAlgo('5146713835430')).toBe(false); expect(_isLuhnAlgo('72348235235')).toBe(false); expect(_isLuhnAlgo('83793719357')).toBe(false); expect(_isLuhnAlgo('892457842742223')).toBe(false); }); }); ================================================ FILE: library/src/utils/_isLuhnAlgo/_isLuhnAlgo.ts ================================================ /** * Non-digit regex. */ const NON_DIGIT_REGEX = /\D/gu; /** * Checks whether a string with numbers corresponds to the luhn algorithm. * * @param input The input to be checked. * * @returns Whether input is valid. * * @internal */ // @__NO_SIDE_EFFECTS__ export function _isLuhnAlgo(input: string): boolean { // Remove any non-digit chars const number = input.replace(NON_DIGIT_REGEX, ''); // Create necessary variables let length = number.length; let bit = 1; let sum = 0; // Calculate sum of algorithm while (length) { const value = +number[--length]; bit ^= 1; sum += bit ? [0, 2, 4, 6, 8, 1, 3, 5, 7, 9][value] : value; } // Return whether its valid return sum % 10 === 0; } ================================================ FILE: library/src/utils/_isLuhnAlgo/index.ts ================================================ export * from './_isLuhnAlgo.ts'; ================================================ FILE: library/src/utils/_isValidObjectKey/_isValidObjectKey.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { _isValidObjectKey } from './_isValidObjectKey.ts'; describe('_isValidObjectKey', () => { test('should return true for allowed keys', () => { const object = { foo: 1, bar: 2, 123: 3 }; expect(_isValidObjectKey(object, 'foo')).toBe(true); expect(_isValidObjectKey(object, 'bar')).toBe(true); expect(_isValidObjectKey(object, '123')).toBe(true); }); test('should return false for inherited keys', () => { const object = Object.create({ foo: 1, bar: 2, 123: 3 }); expect(_isValidObjectKey(object, 'foo')).toBe(false); expect(_isValidObjectKey(object, 'bar')).toBe(false); expect(_isValidObjectKey(object, '123')).toBe(false); }); test('should return false for disallowed keys', () => { const object = { __proto__: 1, prototype: 2, constructor: 3 }; expect(_isValidObjectKey(object, '__proto__')).toBe(false); expect(_isValidObjectKey(object, 'prototype')).toBe(false); expect(_isValidObjectKey(object, 'constructor')).toBe(false); }); }); ================================================ FILE: library/src/utils/_isValidObjectKey/_isValidObjectKey.ts ================================================ /** * Disallows inherited object properties and prevents object prototype * pollution by disallowing certain keys. * * @param object The object to check. * @param key The key to check. * * @returns Whether the key is allowed. * * @internal */ // @__NO_SIDE_EFFECTS__ export function _isValidObjectKey(object: object, key: string): boolean { return ( Object.hasOwn(object, key) && key !== '__proto__' && key !== 'prototype' && key !== 'constructor' ); } ================================================ FILE: library/src/utils/_isValidObjectKey/index.ts ================================================ export * from './_isValidObjectKey.ts'; ================================================ FILE: library/src/utils/_joinExpects/_joinExpects.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { _joinExpects } from './_joinExpects.ts'; describe('_joinExpects', () => { test('should remove duplicates', () => { expect(_joinExpects(['"foo"', '"foo"'], '|')).toBe('"foo"'); expect(_joinExpects(['"foo"', 'string', '"foo"'], '&')).toBe( '("foo" & string)' ); }); test('should join multiple items', () => { expect(_joinExpects(['"foo"', 'string'], '&')).toBe('("foo" & string)'); expect(_joinExpects(['"foo"', 'number', 'boolean', 'Object'], '|')).toBe( '("foo" | number | boolean | Object)' ); }); test('should return first item if only one', () => { expect(_joinExpects(['"foo"'], '|')).toBe('"foo"'); expect(_joinExpects(['string'], '&')).toBe('string'); }); test('should return "never" if empty', () => { expect(_joinExpects([], '|')).toBe('never'); expect(_joinExpects([], '&')).toBe('never'); }); }); ================================================ FILE: library/src/utils/_joinExpects/_joinExpects.ts ================================================ /** * Joins multiple `expects` values with the given separator. * * @param values The `expects` values. * @param separator The separator. * * @returns The joined `expects` property. * * @internal */ // @__NO_SIDE_EFFECTS__ export function _joinExpects(values: string[], separator: '&' | '|'): string { // Create list without duplicates const list = [...new Set(values)]; // If list has more than one item, join them if (list.length > 1) { return `(${list.join(` ${separator} `)})`; } // Otherwise, return first item or "never" return list[0] ?? 'never'; } ================================================ FILE: library/src/utils/_joinExpects/index.ts ================================================ export * from './_joinExpects.ts'; ================================================ FILE: library/src/utils/_stringify/_stringify.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { _stringify } from './_stringify.ts'; describe('_stringify', () => { test('should return string literal', () => { expect(_stringify('hello')).toBe('"hello"'); }); test('should return number literal', () => { expect(_stringify(123)).toBe('123'); }); test('should return bigint literal', () => { expect(_stringify(123n)).toBe('123'); }); test('should return boolean literal', () => { expect(_stringify(true)).toBe('true'); expect(_stringify(false)).toBe('false'); }); test('should return type of symbol', () => { expect(_stringify(Symbol('foo'))).toBe('symbol'); }); test('should return type of undefined', () => { expect(_stringify(undefined)).toBe('undefined'); }); test('should return Object constructor name', () => { expect(_stringify({})).toBe('Object'); }); test('should return Array constructor name', () => { expect(_stringify([])).toBe('Array'); }); test('should return Function constructor name', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function expect(_stringify(() => {})).toBe('Function'); }); test('should return Date constructor name', () => { expect(_stringify(new Date())).toBe('Date'); }); test('should return null as string', () => { expect(_stringify(null)).toBe('null'); expect(_stringify(Object.create(null))).toBe('null'); // eslint-disable-next-line @typescript-eslint/no-empty-function function EmptyObject() {} EmptyObject.prototype = Object.create(null); // @ts-expect-error const emptyObject = new EmptyObject(); expect(_stringify(emptyObject)).toBe('null'); }); }); ================================================ FILE: library/src/utils/_stringify/_stringify.ts ================================================ /** * Stringifies an unknown input to a literal or type string. * * @param input The unknown input. * * @returns A literal or type string. * * @internal */ // @__NO_SIDE_EFFECTS__ export function _stringify(input: unknown): string { const type = typeof input; if (type === 'string') { return `"${input}"`; } // TODO: Should we add "n" suffix to bigints? if (type === 'number' || type === 'bigint' || type === 'boolean') { return `${input}`; } if (type === 'object' || type === 'function') { return (input && Object.getPrototypeOf(input)?.constructor?.name) ?? 'null'; } return type; } ================================================ FILE: library/src/utils/_stringify/index.ts ================================================ export * from './_stringify.ts'; ================================================ FILE: library/src/utils/entriesFromList/entriesFromList.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { arrayAsync, string } from '../../schemas/index.ts'; import { entriesFromList } from './entriesFromList.ts'; describe('entriesFromList', () => { describe('should return object entries', () => { const symbol = Symbol(); test('for sync schemas', () => { const schema = string(); expectTypeOf(entriesFromList(['foo', 123, symbol], schema)).toEqualTypeOf< Record<'foo' | 123 | typeof symbol, typeof schema> >(); }); test('for async schemas', () => { const schema = arrayAsync(string()); expectTypeOf(entriesFromList(['foo', 123, symbol], schema)).toEqualTypeOf< Record<'foo' | 123 | typeof symbol, typeof schema> >(); }); }); }); ================================================ FILE: library/src/utils/entriesFromList/entriesFromList.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { arrayAsync, string } from '../../schemas/index.ts'; import { entriesFromList } from './entriesFromList.ts'; describe('entriesFromList', () => { describe('should return object entries', () => { const symbol = Symbol(); test('for sync schemas', () => { const schema = string(); expect(entriesFromList(['foo', 123, symbol], schema)).toStrictEqual({ foo: schema, [123]: schema, [symbol]: schema, }); }); test('for async schemas', () => { const schema = arrayAsync(string()); expect(entriesFromList(['foo', 123, symbol], schema)).toStrictEqual({ foo: schema, [123]: schema, [symbol]: schema, }); }); }); }); ================================================ FILE: library/src/utils/entriesFromList/entriesFromList.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, } from '../../types/index.ts'; /** * Creates an object entries definition from a list of keys and a schema. * * @param list A list of keys. * @param schema The schema of the keys. * * @returns The object entries. */ // @__NO_SIDE_EFFECTS__ export function entriesFromList< const TList extends readonly (string | number | symbol)[], const TSchema extends | BaseSchema> | BaseSchemaAsync>, >(list: TList, schema: TSchema): Record { // @ts-expect-error const entries: Record = {}; for (const key of list) { entries[key as TList[number]] = schema; } return entries; } ================================================ FILE: library/src/utils/entriesFromList/index.ts ================================================ export * from './entriesFromList.ts'; ================================================ FILE: library/src/utils/entriesFromObjects/entriesFromObjects.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import { boolean, type BooleanSchema, number, type NumberSchema, object, objectAsync, string, type StringSchema, } from '../../schemas/index.ts'; import { entriesFromObjects } from './entriesFromObjects.ts'; describe('entriesFromObjects', () => { describe('should return objects entries', () => { const schema1 = object({ foo: string(), bar: string() }); const schema2 = objectAsync({ baz: number(), qux: number() }); const schema3 = object({ foo: boolean(), baz: boolean() }); test('for missing schema', () => { expectTypeOf( // @ts-expect-error entriesFromObjects([]) ).toEqualTypeOf(); }); test('for single schema', () => { expectTypeOf(entriesFromObjects([schema1])).toEqualTypeOf<{ readonly foo: StringSchema; readonly bar: StringSchema; }>(); }); test('for multiple schemes', () => { expectTypeOf(entriesFromObjects([schema1, schema2])).toEqualTypeOf<{ readonly foo: StringSchema; readonly bar: StringSchema; readonly baz: NumberSchema; readonly qux: NumberSchema; }>(); }); test('with overwrites', () => { expectTypeOf( entriesFromObjects([schema1, schema2, schema3]) ).toEqualTypeOf<{ readonly bar: StringSchema; readonly qux: NumberSchema; readonly foo: BooleanSchema; readonly baz: BooleanSchema; }>(); }); test('for empty entries', () => { // eslint-disable-next-line @typescript-eslint/no-empty-object-type expectTypeOf(entriesFromObjects([object({})])).toEqualTypeOf<{}>(); expectTypeOf( entriesFromObjects([object({}), objectAsync({})]) // eslint-disable-next-line @typescript-eslint/no-empty-object-type ).toEqualTypeOf<{}>(); }); }); }); ================================================ FILE: library/src/utils/entriesFromObjects/entriesFromObjects.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { boolean, number, object, objectAsync, string, } from '../../schemas/index.ts'; import { entriesFromObjects } from './entriesFromObjects.ts'; describe('entriesFromObjects', () => { describe('should return objects entries', () => { const schema1 = object({ foo: string(), bar: string() }); const schema2 = objectAsync({ baz: number(), qux: number() }); const schema3 = object({ foo: boolean(), baz: boolean() }); test('for missing schema', () => { expect( // @ts-expect-error entriesFromObjects([]) ).toStrictEqual({}); }); test('for single schema', () => { expect(entriesFromObjects([schema1])).toStrictEqual(schema1.entries); }); test('for multiple schemes', () => { expect(entriesFromObjects([schema1, schema2])).toStrictEqual({ ...schema1.entries, ...schema2.entries, }); }); test('with overwrites', () => { expect(entriesFromObjects([schema1, schema2, schema3])).toStrictEqual({ ...schema1.entries, ...schema2.entries, ...schema3.entries, }); }); test('for empty entries', () => { expect(entriesFromObjects([object({})])).toStrictEqual({}); expect(entriesFromObjects([object({}), objectAsync({})])).toStrictEqual( {} ); }); }); }); ================================================ FILE: library/src/utils/entriesFromObjects/entriesFromObjects.ts ================================================ import type { LooseObjectIssue, LooseObjectSchema, LooseObjectSchemaAsync, ObjectIssue, ObjectSchema, ObjectSchemaAsync, ObjectWithRestIssue, ObjectWithRestSchema, ObjectWithRestSchemaAsync, StrictObjectIssue, StrictObjectSchema, StrictObjectSchemaAsync, } from '../../schemas/index.ts'; import type { BaseIssue, BaseSchema, BaseSchemaAsync, ErrorMessage, Merge, ObjectEntries, ObjectEntriesAsync, Prettify, } from '../../types/index.ts'; /** * Schema type. */ type Schema = | LooseObjectSchema | undefined> | LooseObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined > | ObjectSchema | undefined> | ObjectSchemaAsync | undefined> | ObjectWithRestSchema< ObjectEntries, BaseSchema>, ErrorMessage | undefined > | ObjectWithRestSchemaAsync< ObjectEntriesAsync, | BaseSchema> | BaseSchemaAsync>, ErrorMessage | undefined > | StrictObjectSchema< ObjectEntries, ErrorMessage | undefined > | StrictObjectSchemaAsync< ObjectEntriesAsync, ErrorMessage | undefined >; /** * Recursive merge type. */ type RecursiveMerge = TSchemas extends readonly [infer TFirstSchema extends Schema] ? TFirstSchema['entries'] : TSchemas extends readonly [ infer TFirstSchema extends Schema, ...infer TRestSchemas extends readonly [Schema, ...Schema[]], ] ? Merge> : never; /** * Merged entries types. */ type MergedEntries = Prettify< RecursiveMerge >; /** * Creates a new object entries definition from existing object schemas. * * @param schemas The schemas to merge the entries from. * * @returns The object entries from the schemas. */ export function entriesFromObjects< const TSchemas extends readonly [Schema, ...Schema[]], >(schemas: TSchemas): MergedEntries; // @__NO_SIDE_EFFECTS__ export function entriesFromObjects( schemas: [Schema, ...Schema[]] ): MergedEntries<[Schema, ...Schema[]]> { const entries = {}; for (const schema of schemas) { Object.assign(entries, schema.entries); } // @ts-expect-error return entries; } ================================================ FILE: library/src/utils/entriesFromObjects/index.ts ================================================ export * from './entriesFromObjects.ts'; ================================================ FILE: library/src/utils/getDotPath/getDotPath.test-d.ts ================================================ import { describe, expectTypeOf, test } from 'vitest'; import type { ArraySchema, NumberIssue, NumberSchema, ObjectSchema, } from '../../schemas/index.ts'; import type { ArrayPathItem, ObjectPathItem } from '../../types/index.ts'; import { getDotPath } from './getDotPath.ts'; describe('getDotPath', () => { const issue: NumberIssue = { kind: 'schema', type: 'number', input: 'foo', expected: 'number', received: '"foo"', message: 'Invalid type: Expected number but received "foo"', path: [ { type: 'object', origin: 'value', input: { dot: [{ path: 'foo' }] }, key: 'dot', value: [{ path: 'foo' }], } satisfies ObjectPathItem, { type: 'array', origin: 'value', input: [{ path: 'foo' }], key: 0, value: { path: 'foo' }, } satisfies ArrayPathItem, { type: 'object', origin: 'value', input: { path: 'foo' }, key: 'path', value: 'foo', } satisfies ObjectPathItem, ], abortEarly: undefined, abortPipeEarly: undefined, issues: undefined, lang: undefined, }; test('should return generic dot path', () => { expectTypeOf(getDotPath(issue)).toEqualTypeOf(); }); test('should return specific dot path', () => { type Schema = ObjectSchema< { dot: ArraySchema< ObjectSchema<{ path: NumberSchema }, undefined>, undefined >; }, undefined >; expectTypeOf(getDotPath(issue)).toEqualTypeOf< 'dot' | `dot.${number}` | `dot.${number}.path` | null >(); }); }); ================================================ FILE: library/src/utils/getDotPath/getDotPath.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { getDotPath } from './getDotPath.ts'; describe('getDotPath', () => { test('should return null if path is undefined', () => { expect( getDotPath({ kind: 'schema', type: 'string', input: undefined, expected: 'string', received: 'undefined', message: 'Invalid type: Expected string but received undefined', path: undefined, }) ).toBeNull(); }); test('should return null if path contains item without key', () => { expect( getDotPath({ kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', message: 'Invalid type: Expected string but received 123', path: [ { type: 'set', origin: 'value', input: new Set(['foo', 123, 'baz', null]), key: null, value: 123, }, ], }) ).toBeNull(); }); test('should return null if path contains key that is not string or number', () => { const key = new Map([['foo', 'bar']]); const input = new Map, { title: unknown }>([ [key, { title: 123 }], ]); expect( getDotPath({ kind: 'schema', type: 'string', input: 123, expected: 'string', received: '123', message: 'Invalid type: Expected string but received 123', path: [ { type: 'map', origin: 'value', input, key, value: input.get(key), }, { type: 'object', origin: 'value', input: input.get(key)!, key: 'title', value: input.get(key)!.title, }, ], }) ).toBeNull(); }); test('should return the dot path if it can be created', () => { const input = { nested: [{ dot: [{ path: undefined }] }] }; expect( getDotPath({ kind: 'schema', type: 'number', input: undefined, expected: 'number', received: 'undefined', message: 'Invalid type: Expected number but received undefined', path: [ { type: 'object', origin: 'value', input, key: 'nested', value: input.nested, }, { type: 'array', origin: 'value', input: input.nested, key: 0, value: input.nested[0], }, { type: 'object', origin: 'value', input: input.nested[0], key: 'dot', value: input.nested[0].dot, }, { type: 'array', origin: 'value', input: input.nested[0].dot, key: 0, value: input.nested[0].dot[0], }, { type: 'object', origin: 'value', input: input.nested[0].dot[0], key: 'path', value: input.nested[0].dot[0].path, }, ], }) ).toBe('nested.0.dot.0.path'); }); }); ================================================ FILE: library/src/utils/getDotPath/getDotPath.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, InferIssue, IssueDotPath, } from '../../types/index.ts'; /** * Creates and returns the dot path of an issue if possible. * * @param issue The issue to get the dot path from. * * @returns The dot path or null. */ export function getDotPath(issue: BaseIssue): string | null; /** * Creates and returns the dot path of an issue if possible. * * @param issue The issue to get the dot path from. * * @returns The dot path or null. */ export function getDotPath< TSchema extends | BaseSchema> | BaseSchemaAsync>, >(issue: InferIssue): IssueDotPath | null; // @__NO_SIDE_EFFECTS__ export function getDotPath(issue: BaseIssue): string | null { if (issue.path) { let key = ''; for (const item of issue.path) { if (typeof item.key === 'string' || typeof item.key === 'number') { if (key) { key += `.${item.key}`; } else { key += item.key; } } else { return null; } } return key; } return null; } ================================================ FILE: library/src/utils/getDotPath/index.ts ================================================ export * from './getDotPath.ts'; ================================================ FILE: library/src/utils/index.ts ================================================ export * from './_addIssue/index.ts'; export * from './_cloneDataset/index.ts'; export * from './_getByteCount/index.ts'; export * from './_getGraphemeCount/index.ts'; export * from './_getLastMetadata/index.ts'; export * from './_getStandardProps/index.ts'; export * from './_getWordCount/index.ts'; export * from './_isLuhnAlgo/index.ts'; export * from './_isValidObjectKey/index.ts'; export * from './_joinExpects/index.ts'; export * from './_stringify/index.ts'; export * from './entriesFromList/index.ts'; export * from './entriesFromObjects/index.ts'; export * from './getDotPath/index.ts'; export * from './isOfKind/index.ts'; export * from './isOfType/index.ts'; export * from './isValiError/index.ts'; export * from './ValiError/index.ts'; ================================================ FILE: library/src/utils/isOfKind/index.ts ================================================ export * from './isOfKind.ts'; ================================================ FILE: library/src/utils/isOfKind/isOfKind.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { decimal, trim } from '../../actions/index.ts'; import { string } from '../../schemas/index.ts'; import { isOfKind } from './isOfKind.ts'; describe('isOfKind', () => { test('should check string schema', () => { const schema = string(); expect(isOfKind('schema', schema)).toBe(true); // @ts-expect-error expect(isOfKind('validation', schema)).toBe(false); // @ts-expect-error expect(isOfKind('transformation', schema)).toBe(false); }); test('should check decimal action', () => { const action = decimal(); expect(isOfKind('validation', action)).toBe(true); // @ts-expect-error expect(isOfKind('schema', action)).toBe(false); // @ts-expect-error expect(isOfKind('transformation', action)).toBe(false); }); test('should check trim action', () => { const action = trim(); expect(isOfKind('transformation', action)).toBe(true); // @ts-expect-error expect(isOfKind('schema', action)).toBe(false); // @ts-expect-error expect(isOfKind('validation', action)).toBe(false); }); }); ================================================ FILE: library/src/utils/isOfKind/isOfKind.ts ================================================ /** * A generic type guard to check the kind of an object. * * @param kind The kind to check for. * @param object The object to check. * * @returns Whether it matches. */ // @__NO_SIDE_EFFECTS__ export function isOfKind< const TKind extends TObject['kind'], const TObject extends { kind: string }, >(kind: TKind, object: TObject): object is Extract { return object.kind === kind; } ================================================ FILE: library/src/utils/isOfType/index.ts ================================================ export * from './isOfType.ts'; ================================================ FILE: library/src/utils/isOfType/isOfType.test.ts ================================================ import { describe, expect, test } from 'vitest'; import { number, object, string } from '../../schemas/index.ts'; import { isOfType } from './isOfType.ts'; describe('isOfType', () => { test('should check string schema', () => { const schema = string(); expect(isOfType('string', schema)).toBe(true); // @ts-expect-error expect(isOfType('number', schema)).toBe(false); // @ts-expect-error expect(isOfType('object', schema)).toBe(false); }); test('should check number schema', () => { const schema = number(); expect(isOfType('number', schema)).toBe(true); // @ts-expect-error expect(isOfType('string', schema)).toBe(false); // @ts-expect-error expect(isOfType('object', schema)).toBe(false); }); test('should check object schema', () => { const schema = object({ key: string() }); expect(isOfType('object', schema)).toBe(true); // @ts-expect-error expect(isOfType('string', schema)).toBe(false); // @ts-expect-error expect(isOfType('number', schema)).toBe(false); }); }); ================================================ FILE: library/src/utils/isOfType/isOfType.ts ================================================ /** * A generic type guard to check the type of an object. * * @param type The type to check for. * @param object The object to check. * * @returns Whether it matches. */ // @__NO_SIDE_EFFECTS__ export function isOfType< const TType extends TObject['type'], const TObject extends { type: string }, >(type: TType, object: TObject): object is Extract { return object.type === type; } ================================================ FILE: library/src/utils/isValiError/index.ts ================================================ export * from './isValiError.ts'; ================================================ FILE: library/src/utils/isValiError/isValiError.test.ts ================================================ import { describe, expect, test } from 'vitest'; import type { StringIssue } from '../../schemas/index.ts'; import { ValiError } from '../../utils/index.ts'; import { isValiError } from './isValiError.ts'; describe('isValiError', () => { test('should return true if ValiError', () => { expect( isValiError( new ValiError([ { kind: 'schema', type: 'string', input: null, expected: 'string', received: 'null', message: 'Invalid type: Expected string but received null', } satisfies StringIssue, ]) ) ).toBe(true); }); test('should return false if other error', () => { expect(isValiError(new Error())).toBe(false); expect(isValiError(new TypeError())).toBe(false); expect(isValiError(new RangeError())).toBe(false); }); }); ================================================ FILE: library/src/utils/isValiError/isValiError.ts ================================================ import type { BaseIssue, BaseSchema, BaseSchemaAsync, } from '../../types/index.ts'; import { ValiError } from '../../utils/index.ts'; /** * A type guard to check if an error is a ValiError. * * @param error The error to check. * * @returns Whether its a ValiError. */ // @__NO_SIDE_EFFECTS__ export function isValiError< TSchema extends | BaseSchema> | BaseSchemaAsync>, >(error: unknown): error is ValiError { return error instanceof ValiError; } ================================================ FILE: library/src/vitest/expectActionIssue.ts ================================================ import { expect } from 'vitest'; import type { BaseIssue, BaseValidation, InferInput, InferIssue, PartialDataset, } from '../types/index.ts'; import { _stringify } from '../utils/index.ts'; /** * Expect an action issue to be returned. * * @param action The action to test. * @param baseIssue The base issue data. * @param values The values to test. * @param getReceived Received value getter. */ export function expectActionIssue< // eslint-disable-next-line @typescript-eslint/no-explicit-any TAction extends BaseValidation>, >( action: TAction, baseIssue: Omit, 'input' | 'received'>, values: InferInput[], getReceived?: (value: InferInput) => string ): void { for (const value of values) { expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: true, value, issues: [ { requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, input: value, received: getReceived?.(value) ?? _stringify(value), ...baseIssue, }, ], } satisfies PartialDataset>); } } ================================================ FILE: library/src/vitest/expectActionIssueAsync.ts ================================================ import { expect } from 'vitest'; import type { BaseIssue, BaseValidationAsync, InferInput, InferIssue, PartialDataset, } from '../types/index.ts'; import { _stringify } from '../utils/index.ts'; /** * Expect an action issue to be returned. * * @param action The action to test. * @param baseIssue The base issue data. * @param values The values to test. * @param getReceived Received value getter. */ export async function expectActionIssueAsync< // eslint-disable-next-line @typescript-eslint/no-explicit-any TAction extends BaseValidationAsync>, >( action: TAction, baseIssue: Omit, 'input' | 'received'>, values: InferInput[], getReceived?: (value: InferInput) => string ): Promise { for (const value of values) { expect(await action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: true, value, issues: [ { requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, input: value, received: getReceived?.(value) ?? _stringify(value), ...baseIssue, }, ], } satisfies PartialDataset>); } } ================================================ FILE: library/src/vitest/expectNoActionIssue.ts ================================================ import { expect } from 'vitest'; import type { BaseIssue, BaseValidation, InferInput } from '../types/index.ts'; /** * Expect no action issue to be returned. * * @param action The action to test. * @param values The values to test. */ export function expectNoActionIssue< // eslint-disable-next-line @typescript-eslint/no-explicit-any TAction extends BaseValidation>, >(action: TAction, values: InferInput[]): void { for (const value of values) { expect(action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: true, value, }); } } ================================================ FILE: library/src/vitest/expectNoActionIssueAsync.ts ================================================ import { expect } from 'vitest'; import type { BaseIssue, BaseValidationAsync, InferInput, } from '../types/index.ts'; /** * Expect no action issue to be returned. * * @param action The action to test. * @param values The values to test. */ export async function expectNoActionIssueAsync< // eslint-disable-next-line @typescript-eslint/no-explicit-any TAction extends BaseValidationAsync>, >(action: TAction, values: InferInput[]): Promise { for (const value of values) { expect(await action['~run']({ typed: true, value }, {})).toStrictEqual({ typed: true, value, }); } } ================================================ FILE: library/src/vitest/expectNoSchemaIssue.ts ================================================ import { expect } from 'vitest'; import type { BaseIssue, BaseSchema, InferInput } from '../types/index.ts'; /** * Expect no schema issue to be returned. * * @param schema The schema to test. * @param values The values to test. */ export function expectNoSchemaIssue< TSchema extends BaseSchema>, >(schema: TSchema, values: InferInput[]): void { for (const value of values) { expect(schema['~run']({ value }, {})).toStrictEqual({ typed: true, value, }); } } ================================================ FILE: library/src/vitest/expectNoSchemaIssueAsync.ts ================================================ import { expect } from 'vitest'; import type { BaseIssue, BaseSchemaAsync, InferInput } from '../types/index.ts'; /** * Expect no schema issue to be returned. * * @param schema The schema to test. * @param values The values to test. */ export async function expectNoSchemaIssueAsync< TSchema extends BaseSchemaAsync>, >(schema: TSchema, values: InferInput[]): Promise { for (const value of values) { expect(await schema['~run']({ value }, {})).toStrictEqual({ typed: true, value, }); } } ================================================ FILE: library/src/vitest/expectSchemaIssue.ts ================================================ import { expect } from 'vitest'; import type { BaseIssue, BaseSchema, FailureDataset, InferIssue, } from '../types/index.ts'; import { _stringify } from '../utils/index.ts'; /** * Expect an schema issue to be returned. * * @param schema The schema to test. * @param baseIssue The base issue data. * @param values The values to test. * @param received The received value. */ export function expectSchemaIssue< TSchema extends BaseSchema>, >( schema: TSchema, baseIssue: Omit, 'input' | 'received'>, values: unknown[], received?: string ): void { for (const value of values) { expect(schema['~run']({ value }, {})).toStrictEqual({ typed: false, value, issues: [ { requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, ...baseIssue, input: value, received: received ?? _stringify(value), }, ], } satisfies FailureDataset>); } } ================================================ FILE: library/src/vitest/expectSchemaIssueAsync.ts ================================================ import { expect } from 'vitest'; import type { BaseIssue, BaseSchemaAsync, FailureDataset, InferIssue, } from '../types/index.ts'; import { _stringify } from '../utils/index.ts'; /** * Expect an schema issue to be returned. * * @param schema The schema to test. * @param baseIssue The base issue data. * @param values The values to test. */ export async function expectSchemaIssueAsync< TSchema extends BaseSchemaAsync>, >( schema: TSchema, baseIssue: Omit, 'input' | 'received'>, values: unknown[] ): Promise { for (const value of values) { expect(await schema['~run']({ value }, {})).toStrictEqual({ typed: false, value, issues: [ { requirement: undefined, path: undefined, issues: undefined, lang: undefined, abortEarly: undefined, abortPipeEarly: undefined, ...baseIssue, input: value, received: _stringify(value), }, ], } satisfies FailureDataset>); } } ================================================ FILE: library/src/vitest/index.ts ================================================ export * from './expectActionIssue.ts'; export * from './expectActionIssueAsync.ts'; export * from './expectNoActionIssue.ts'; export * from './expectNoActionIssueAsync.ts'; export * from './expectNoSchemaIssue.ts'; export * from './expectNoSchemaIssueAsync.ts'; export * from './expectSchemaIssue.ts'; export * from './expectSchemaIssueAsync.ts'; ================================================ FILE: library/tsconfig.json ================================================ { "compilerOptions": { "allowImportingTsExtensions": true, "declaration": true, "exactOptionalPropertyTypes": true, "isolatedDeclarations": true, "lib": ["ESNext", "DOM"], "module": "ESNext", "moduleResolution": "node", "noEmit": true, "skipLibCheck": true, "strict": true, "target": "ES2020" }, "include": ["src"] } ================================================ FILE: library/tsdown.config.ts ================================================ import { defineConfig } from 'tsdown'; export default defineConfig([ { entry: ['./src/index.ts'], clean: true, format: ['es', 'cjs'], minify: false, dts: true, outDir: './dist', }, { entry: ['./src/index.ts'], clean: true, format: ['es', 'cjs'], minify: true, dts: false, outDir: './dist', outExtensions: ({ format }) => ({ js: format === 'cjs' ? '.min.cjs' : '.min.mjs', }), }, ]); ================================================ FILE: library/vitest.config.ts ================================================ import { defineConfig } from 'vitest/config'; export default defineConfig({ test: { environment: 'jsdom', isolate: false, coverage: { include: ['src'], exclude: [ 'src/types', 'src/vitest', 'src/regex.ts', '**/index.ts', '**/types.ts', '**/*.test.ts', '**/*.test-d.ts', '**/.DS_Store', ], }, }, }); ================================================ FILE: package.json ================================================ { "name": "valibot", "description": "The modular and type safe schema library for validating structural data", "version": "0.0.0", "license": "MIT", "author": "Fabian Hiller", "homepage": "https://valibot.dev", "repository": { "type": "git", "url": "https://github.com/open-circle/valibot" }, "private": true, "scripts": { "test": "pnpm -r run test", "lint": "pnpm -r run lint", "format": "pnpm -r run format", "format.check": "pnpm -r run format.check", "build": "pnpm -r --filter='!website' run build" }, "devDependencies": { "@trivago/prettier-plugin-sort-imports": "^6.0.0", "prettier": "^3.6.2", "prettier-plugin-tailwindcss": "^0.7.1", "typescript": "^5.9.3" } } ================================================ FILE: packages/i18n/.gitignore ================================================ index.ts index.mjs index.cjs index.d.mts index.d.cts ar az ca cs de el es fa fi fr hu id it ja ko kr mn nb nl pl pt ro ru sk sl sv tr uk vi zh-CN zh-TW ================================================ FILE: packages/i18n/CHANGELOG.md ================================================ # Changelog All notable changes to the library will be documented in this file. ## v1.1.0 (March 17, 2026) - Add Greek (el) translations (pull request #1311) - Add Slovak (sk) translations (pull request #1334) - Add Finnish (fi) translations (pull request #1318) - Add Azerbaijani (az) translations (pull request #1409) - Add Mongolian (mn) translations (pull request #1224) - Add new and missing actions to translations (pull request #1306) - Change Valibot peer dependency to `^1.3.0` - Fix ISO 639-1 code for Korean (`ko`) (pull request #1306) ## v1.0.0 (March 19, 2025) - Add new and missing actions to translations - Add Farsi (fa) translations (pull request #838) - Add Czech (cs) translations (pull request #886) - Add Vietnamese (vi) translations (pull request #951) - Change Romanian (ro) translations (pull request #1070) - Change Valibot peer dependency to v1.0.0 ## v0.17.0 (July 26, 2024) - Add Indonesian (id) translations (pull request #683) ## v0.16.0 (June 19, 2024) - Add Polish (pl) translations (pull request #584) - Add Catalan (ca) translations (pull request #652) ## v0.15.0 (June 07, 2024) - Migrate i18n library to Valibot v0.31.0 - Change peer dependency to `>=0.31.0 <1` ## v0.14.0 (June 07, 2024) - Add Italian (it) translations (pull request #605) - Add Swedish (sv) translations (pull request #606) ## v0.13.0 (May 18, 2024) - Add Spanish (es) translations (pull request #581) ## v0.12.0 (May 11, 2024) - Add Hungarian (hu) translations (pull request #560) ## v0.11.0 (April 30, 2024) - Add Arabic (ar) translations (pull request #527) - Add Turkish (tr) translations (pull request #549) ## v0.10.0 (April 09, 2024) - Add Portuguese (pt) translations (pull request #509) ## v0.9.0 (March 09, 2024) - Add Romanian (ro) translations (pull request #472) - Remove translation for deprecated `equal` validation (issue #474) - Change peer dependency to `>=0.30.0 <1` ## v0.8.0 (March 04, 2024) - Change peer dependency to `>=0.29.0 <1` (pull request #468) ## v0.7.0 (February 19, 2024) - Add Norwegian (nb) translations (pull request #439) ## v0.6.0 (February 16, 2024) - Add Dutch (nl) translations (pull request #438) ## v0.5.0 (February 12, 2024) - Add Russian (ru) translations (pull request #434) ## v0.4.0 (February 11, 2024) - Add Japanese (ja) translations (pull request #431) - Add Korean (kr) translations (pull request #429) ## v0.3.0 (February 09, 2024) - Add Chinese (zh-CN) translations (pull request #419) - Add Chinese (zh-TW) translations (pull request #427) - Add Slovenian (sl) translations (pull request #422) ## v0.2.0 (February 06, 2024) - Add French (fr) translations (pull request #418) - Add Ukrainian (uk) translations (pull request #423) ## v0.1.0 (February 05, 2024) - Initial release ================================================ FILE: packages/i18n/LICENSE.md ================================================ MIT License Copyright (c) Fabian Hiller Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: packages/i18n/README.md ================================================ # Valibot i18n The official i18n translations for Valibot. See the [internationalization guide](https://valibot.dev/guides/internationalization/) for more details. ## Current status Valibot ships English messages by default, so this package publishes translated submodules for the languages below. | Language | Pull Request | Status | | ---------------- | -------------------- | ------ | | Arabic (ar) | [#527][pr-527-url] | ✅ | | Azerbaijani (az) | [#1409][pr-1409-url] | ✅ | | Catalan (ca) | [#652][pr-652-url] | ✅ | | Chinese (zh-CN) | [#419][pr-419-url] | ✅ | | Chinese (zh-TW) | [#427][pr-427-url] | ✅ | | Czech (cs) | [#886][pr-886-url] | ✅ | | Dutch (nl) | [#438][pr-438-url] | ✅ | | English (en) | [#397][pr-397-url] | ✅ | | Farsi (fa) | [#838][pr-838-url] | ✅ | | Finnish (fi) | [#1318][pr-1318-url] | ✅ | | French (fr) | [#418][pr-418-url] | ✅ | | German (de) | [#397][pr-397-url] | ✅ | | Greek (el) | [#1311][pr-1311-url] | ✅ | | Hungarian (hu) | [#560][pr-560-url] | ✅ | | Indonesian (id) | [#683][pr-683-url] | ✅ | | Italian (it) | [#605][pr-605-url] | ✅ | | Japanese (ja) | [#431][pr-431-url] | ✅ | | Korean (ko) | [#1306][pr-1306-url] | ✅ | | Mongolian (mn) | [#1224][pr-1224-url] | ✅ | | Norwegian (nb) | [#439][pr-439-url] | ✅ | | Polish (pl) | [#584][pr-584-url] | ✅ | | Portuguese (pt) | [#509][pr-509-url] | ✅ | | Romanian (ro) | [#472][pr-472-url] | ✅ | | Russian (ru) | [#434][pr-434-url] | ✅ | | Slovak (sk) | [#1334][pr-1334-url] | ✅ | | Slovenian (sl) | [#422][pr-422-url] | ✅ | | Spanish (es) | [#581][pr-581-url] | ✅ | | Swedish (sv) | [#606][pr-606-url] | ✅ | | Turkish (tr) | [#549][pr-549-url] | ✅ | | Ukrainian (uk) | [#423][pr-423-url] | ✅ | | Vietnamese (vi) | [#951][pr-951-url] | ✅ | The deprecated `kr` submodule remains available as an alias of `ko` for compatibility, but new integrations should use `ko`. [pr-397-url]: https://github.com/open-circle/valibot/pull/397 [pr-418-url]: https://github.com/open-circle/valibot/pull/418 [pr-419-url]: https://github.com/open-circle/valibot/pull/419 [pr-422-url]: https://github.com/open-circle/valibot/pull/422 [pr-423-url]: https://github.com/open-circle/valibot/pull/423 [pr-427-url]: https://github.com/open-circle/valibot/pull/427 [pr-431-url]: https://github.com/open-circle/valibot/pull/431 [pr-434-url]: https://github.com/open-circle/valibot/pull/434 [pr-438-url]: https://github.com/open-circle/valibot/pull/438 [pr-439-url]: https://github.com/open-circle/valibot/pull/439 [pr-472-url]: https://github.com/open-circle/valibot/pull/472 [pr-509-url]: https://github.com/open-circle/valibot/pull/509 [pr-527-url]: https://github.com/open-circle/valibot/pull/527 [pr-549-url]: https://github.com/open-circle/valibot/pull/549 [pr-560-url]: https://github.com/open-circle/valibot/pull/560 [pr-581-url]: https://github.com/open-circle/valibot/pull/581 [pr-584-url]: https://github.com/open-circle/valibot/pull/584 [pr-605-url]: https://github.com/open-circle/valibot/pull/605 [pr-606-url]: https://github.com/open-circle/valibot/pull/606 [pr-652-url]: https://github.com/open-circle/valibot/pull/652 [pr-683-url]: https://github.com/open-circle/valibot/pull/683 [pr-838-url]: https://github.com/open-circle/valibot/pull/838 [pr-886-url]: https://github.com/open-circle/valibot/pull/886 [pr-951-url]: https://github.com/open-circle/valibot/pull/951 [pr-1224-url]: https://github.com/open-circle/valibot/pull/1224 [pr-1306-url]: https://github.com/open-circle/valibot/pull/1306 [pr-1311-url]: https://github.com/open-circle/valibot/pull/1311 [pr-1318-url]: https://github.com/open-circle/valibot/pull/1318 [pr-1334-url]: https://github.com/open-circle/valibot/pull/1334 [pr-1409-url]: https://github.com/open-circle/valibot/pull/1409 ## Getting started Step 1: Clone repository ```bash git clone git@github.com:open-circle/valibot.git ``` Step 2: Install dependencies ```bash pnpm install ``` Step 3: Build core library ```bash cd ./library && pnpm build ``` Step 4: Change to directory ```bash cd ../packages/i18n ``` ## Add language 1. Add the ISO code to `src/types.ts` 2. Duplicate `src/en.ts` and change file name to ISO code 3. Change ISO code and translate messages in new file 4. Import new language file in `scripts/build-npm.ts` and `scripts/build-jsr.ts` 5. Add the new import to the `languages` array 6. Update the "Current status" table in this README ## Build library Execute build script ```bash pnpm build.npm # for npm pnpm build.jsr # for JSR ``` ================================================ FILE: packages/i18n/jsr.json ================================================ { "name": "@valibot/i18n", "version": "1.1.0", "exclude": [ "scripts", "src", "CHANGELOG.md", "package.json", "tsconfig.json", "!index.ts", "!ar", "!az", "!ca", "!cs", "!de", "!el", "!es", "!fa", "!fi", "!fr", "!hu", "!id", "!it", "!ja", "!ko", "!kr", "!mn", "!nb", "!nl", "!pl", "!pt", "!ro", "!ru", "!sk", "!sl", "!sv", "!tr", "!uk", "!vi", "!zh-CN", "!zh-TW" ], "exports": { ".": "./index.ts", "./ar": "./ar/index.ts", "./ar/schema": "./ar/schema.ts", "./ar/base64": "./ar/base64.ts", "./ar/bic": "./ar/bic.ts", "./ar/bytes": "./ar/bytes.ts", "./ar/check": "./ar/check.ts", "./ar/checkAsync": "./ar/checkAsync.ts", "./ar/checkItems": "./ar/checkItems.ts", "./ar/checkItemsAsync": "./ar/checkItemsAsync.ts", "./ar/creditCard": "./ar/creditCard.ts", "./ar/cuid2": "./ar/cuid2.ts", "./ar/decimal": "./ar/decimal.ts", "./ar/digits": "./ar/digits.ts", "./ar/domain": "./ar/domain.ts", "./ar/email": "./ar/email.ts", "./ar/emoji": "./ar/emoji.ts", "./ar/empty": "./ar/empty.ts", "./ar/endsWith": "./ar/endsWith.ts", "./ar/entries": "./ar/entries.ts", "./ar/everyItem": "./ar/everyItem.ts", "./ar/excludes": "./ar/excludes.ts", "./ar/finite": "./ar/finite.ts", "./ar/graphemes": "./ar/graphemes.ts", "./ar/gtValue": "./ar/gtValue.ts", "./ar/guard": "./ar/guard.ts", "./ar/hash": "./ar/hash.ts", "./ar/hexadecimal": "./ar/hexadecimal.ts", "./ar/hexColor": "./ar/hexColor.ts", "./ar/imei": "./ar/imei.ts", "./ar/includes": "./ar/includes.ts", "./ar/integer": "./ar/integer.ts", "./ar/ip": "./ar/ip.ts", "./ar/ipv4": "./ar/ipv4.ts", "./ar/ipv6": "./ar/ipv6.ts", "./ar/isbn": "./ar/isbn.ts", "./ar/isoDate": "./ar/isoDate.ts", "./ar/isoDateTime": "./ar/isoDateTime.ts", "./ar/isoTime": "./ar/isoTime.ts", "./ar/isoTimeSecond": "./ar/isoTimeSecond.ts", "./ar/isoTimestamp": "./ar/isoTimestamp.ts", "./ar/isoWeek": "./ar/isoWeek.ts", "./ar/isrc": "./ar/isrc.ts", "./ar/jwsCompact": "./ar/jwsCompact.ts", "./ar/length": "./ar/length.ts", "./ar/ltValue": "./ar/ltValue.ts", "./ar/mac": "./ar/mac.ts", "./ar/mac48": "./ar/mac48.ts", "./ar/mac64": "./ar/mac64.ts", "./ar/maxBytes": "./ar/maxBytes.ts", "./ar/maxEntries": "./ar/maxEntries.ts", "./ar/maxGraphemes": "./ar/maxGraphemes.ts", "./ar/maxLength": "./ar/maxLength.ts", "./ar/maxSize": "./ar/maxSize.ts", "./ar/maxValue": "./ar/maxValue.ts", "./ar/maxWords": "./ar/maxWords.ts", "./ar/mimeType": "./ar/mimeType.ts", "./ar/minBytes": "./ar/minBytes.ts", "./ar/minEntries": "./ar/minEntries.ts", "./ar/minGraphemes": "./ar/minGraphemes.ts", "./ar/minLength": "./ar/minLength.ts", "./ar/minSize": "./ar/minSize.ts", "./ar/minValue": "./ar/minValue.ts", "./ar/minWords": "./ar/minWords.ts", "./ar/multipleOf": "./ar/multipleOf.ts", "./ar/nanoid": "./ar/nanoid.ts", "./ar/nonEmpty": "./ar/nonEmpty.ts", "./ar/notBytes": "./ar/notBytes.ts", "./ar/notEntries": "./ar/notEntries.ts", "./ar/notGraphemes": "./ar/notGraphemes.ts", "./ar/notLength": "./ar/notLength.ts", "./ar/notSize": "./ar/notSize.ts", "./ar/notValue": "./ar/notValue.ts", "./ar/notValues": "./ar/notValues.ts", "./ar/notWords": "./ar/notWords.ts", "./ar/octal": "./ar/octal.ts", "./ar/parseBoolean": "./ar/parseBoolean.ts", "./ar/parseJson": "./ar/parseJson.ts", "./ar/partialCheck": "./ar/partialCheck.ts", "./ar/rawCheck": "./ar/rawCheck.ts", "./ar/rawTransform": "./ar/rawTransform.ts", "./ar/regex": "./ar/regex.ts", "./ar/rfcEmail": "./ar/rfcEmail.ts", "./ar/safeInteger": "./ar/safeInteger.ts", "./ar/size": "./ar/size.ts", "./ar/slug": "./ar/slug.ts", "./ar/someItem": "./ar/someItem.ts", "./ar/startsWith": "./ar/startsWith.ts", "./ar/stringifyJson": "./ar/stringifyJson.ts", "./ar/toBigint": "./ar/toBigint.ts", "./ar/toDate": "./ar/toDate.ts", "./ar/toNumber": "./ar/toNumber.ts", "./ar/toString": "./ar/toString.ts", "./ar/ulid": "./ar/ulid.ts", "./ar/url": "./ar/url.ts", "./ar/uuid": "./ar/uuid.ts", "./ar/value": "./ar/value.ts", "./ar/values": "./ar/values.ts", "./ar/words": "./ar/words.ts", "./az": "./az/index.ts", "./az/schema": "./az/schema.ts", "./az/base64": "./az/base64.ts", "./az/bic": "./az/bic.ts", "./az/bytes": "./az/bytes.ts", "./az/check": "./az/check.ts", "./az/checkAsync": "./az/checkAsync.ts", "./az/checkItems": "./az/checkItems.ts", "./az/checkItemsAsync": "./az/checkItemsAsync.ts", "./az/creditCard": "./az/creditCard.ts", "./az/cuid2": "./az/cuid2.ts", "./az/decimal": "./az/decimal.ts", "./az/digits": "./az/digits.ts", "./az/domain": "./az/domain.ts", "./az/email": "./az/email.ts", "./az/emoji": "./az/emoji.ts", "./az/empty": "./az/empty.ts", "./az/endsWith": "./az/endsWith.ts", "./az/entries": "./az/entries.ts", "./az/everyItem": "./az/everyItem.ts", "./az/excludes": "./az/excludes.ts", "./az/finite": "./az/finite.ts", "./az/graphemes": "./az/graphemes.ts", "./az/gtValue": "./az/gtValue.ts", "./az/guard": "./az/guard.ts", "./az/hash": "./az/hash.ts", "./az/hexadecimal": "./az/hexadecimal.ts", "./az/hexColor": "./az/hexColor.ts", "./az/imei": "./az/imei.ts", "./az/includes": "./az/includes.ts", "./az/integer": "./az/integer.ts", "./az/ip": "./az/ip.ts", "./az/ipv4": "./az/ipv4.ts", "./az/ipv6": "./az/ipv6.ts", "./az/isbn": "./az/isbn.ts", "./az/isoDate": "./az/isoDate.ts", "./az/isoDateTime": "./az/isoDateTime.ts", "./az/isoTime": "./az/isoTime.ts", "./az/isoTimeSecond": "./az/isoTimeSecond.ts", "./az/isoTimestamp": "./az/isoTimestamp.ts", "./az/isoWeek": "./az/isoWeek.ts", "./az/isrc": "./az/isrc.ts", "./az/jwsCompact": "./az/jwsCompact.ts", "./az/length": "./az/length.ts", "./az/ltValue": "./az/ltValue.ts", "./az/mac": "./az/mac.ts", "./az/mac48": "./az/mac48.ts", "./az/mac64": "./az/mac64.ts", "./az/maxBytes": "./az/maxBytes.ts", "./az/maxEntries": "./az/maxEntries.ts", "./az/maxGraphemes": "./az/maxGraphemes.ts", "./az/maxLength": "./az/maxLength.ts", "./az/maxSize": "./az/maxSize.ts", "./az/maxValue": "./az/maxValue.ts", "./az/maxWords": "./az/maxWords.ts", "./az/mimeType": "./az/mimeType.ts", "./az/minBytes": "./az/minBytes.ts", "./az/minEntries": "./az/minEntries.ts", "./az/minGraphemes": "./az/minGraphemes.ts", "./az/minLength": "./az/minLength.ts", "./az/minSize": "./az/minSize.ts", "./az/minValue": "./az/minValue.ts", "./az/minWords": "./az/minWords.ts", "./az/multipleOf": "./az/multipleOf.ts", "./az/nanoid": "./az/nanoid.ts", "./az/nonEmpty": "./az/nonEmpty.ts", "./az/notBytes": "./az/notBytes.ts", "./az/notEntries": "./az/notEntries.ts", "./az/notGraphemes": "./az/notGraphemes.ts", "./az/notLength": "./az/notLength.ts", "./az/notSize": "./az/notSize.ts", "./az/notValue": "./az/notValue.ts", "./az/notValues": "./az/notValues.ts", "./az/notWords": "./az/notWords.ts", "./az/octal": "./az/octal.ts", "./az/parseBoolean": "./az/parseBoolean.ts", "./az/parseJson": "./az/parseJson.ts", "./az/partialCheck": "./az/partialCheck.ts", "./az/rawCheck": "./az/rawCheck.ts", "./az/rawTransform": "./az/rawTransform.ts", "./az/regex": "./az/regex.ts", "./az/rfcEmail": "./az/rfcEmail.ts", "./az/safeInteger": "./az/safeInteger.ts", "./az/size": "./az/size.ts", "./az/slug": "./az/slug.ts", "./az/someItem": "./az/someItem.ts", "./az/startsWith": "./az/startsWith.ts", "./az/stringifyJson": "./az/stringifyJson.ts", "./az/toBigint": "./az/toBigint.ts", "./az/toDate": "./az/toDate.ts", "./az/toNumber": "./az/toNumber.ts", "./az/toString": "./az/toString.ts", "./az/ulid": "./az/ulid.ts", "./az/url": "./az/url.ts", "./az/uuid": "./az/uuid.ts", "./az/value": "./az/value.ts", "./az/values": "./az/values.ts", "./az/words": "./az/words.ts", "./ca": "./ca/index.ts", "./ca/schema": "./ca/schema.ts", "./ca/base64": "./ca/base64.ts", "./ca/bic": "./ca/bic.ts", "./ca/bytes": "./ca/bytes.ts", "./ca/check": "./ca/check.ts", "./ca/checkAsync": "./ca/checkAsync.ts", "./ca/checkItems": "./ca/checkItems.ts", "./ca/checkItemsAsync": "./ca/checkItemsAsync.ts", "./ca/creditCard": "./ca/creditCard.ts", "./ca/cuid2": "./ca/cuid2.ts", "./ca/decimal": "./ca/decimal.ts", "./ca/digits": "./ca/digits.ts", "./ca/domain": "./ca/domain.ts", "./ca/email": "./ca/email.ts", "./ca/emoji": "./ca/emoji.ts", "./ca/empty": "./ca/empty.ts", "./ca/endsWith": "./ca/endsWith.ts", "./ca/entries": "./ca/entries.ts", "./ca/everyItem": "./ca/everyItem.ts", "./ca/excludes": "./ca/excludes.ts", "./ca/finite": "./ca/finite.ts", "./ca/graphemes": "./ca/graphemes.ts", "./ca/gtValue": "./ca/gtValue.ts", "./ca/guard": "./ca/guard.ts", "./ca/hash": "./ca/hash.ts", "./ca/hexadecimal": "./ca/hexadecimal.ts", "./ca/hexColor": "./ca/hexColor.ts", "./ca/imei": "./ca/imei.ts", "./ca/includes": "./ca/includes.ts", "./ca/integer": "./ca/integer.ts", "./ca/ip": "./ca/ip.ts", "./ca/ipv4": "./ca/ipv4.ts", "./ca/ipv6": "./ca/ipv6.ts", "./ca/isbn": "./ca/isbn.ts", "./ca/isoDate": "./ca/isoDate.ts", "./ca/isoDateTime": "./ca/isoDateTime.ts", "./ca/isoTime": "./ca/isoTime.ts", "./ca/isoTimeSecond": "./ca/isoTimeSecond.ts", "./ca/isoTimestamp": "./ca/isoTimestamp.ts", "./ca/isoWeek": "./ca/isoWeek.ts", "./ca/isrc": "./ca/isrc.ts", "./ca/jwsCompact": "./ca/jwsCompact.ts", "./ca/length": "./ca/length.ts", "./ca/ltValue": "./ca/ltValue.ts", "./ca/mac": "./ca/mac.ts", "./ca/mac48": "./ca/mac48.ts", "./ca/mac64": "./ca/mac64.ts", "./ca/maxBytes": "./ca/maxBytes.ts", "./ca/maxEntries": "./ca/maxEntries.ts", "./ca/maxGraphemes": "./ca/maxGraphemes.ts", "./ca/maxLength": "./ca/maxLength.ts", "./ca/maxSize": "./ca/maxSize.ts", "./ca/maxValue": "./ca/maxValue.ts", "./ca/maxWords": "./ca/maxWords.ts", "./ca/mimeType": "./ca/mimeType.ts", "./ca/minBytes": "./ca/minBytes.ts", "./ca/minEntries": "./ca/minEntries.ts", "./ca/minGraphemes": "./ca/minGraphemes.ts", "./ca/minLength": "./ca/minLength.ts", "./ca/minSize": "./ca/minSize.ts", "./ca/minValue": "./ca/minValue.ts", "./ca/minWords": "./ca/minWords.ts", "./ca/multipleOf": "./ca/multipleOf.ts", "./ca/nanoid": "./ca/nanoid.ts", "./ca/nonEmpty": "./ca/nonEmpty.ts", "./ca/notBytes": "./ca/notBytes.ts", "./ca/notEntries": "./ca/notEntries.ts", "./ca/notGraphemes": "./ca/notGraphemes.ts", "./ca/notLength": "./ca/notLength.ts", "./ca/notSize": "./ca/notSize.ts", "./ca/notValue": "./ca/notValue.ts", "./ca/notValues": "./ca/notValues.ts", "./ca/notWords": "./ca/notWords.ts", "./ca/octal": "./ca/octal.ts", "./ca/parseBoolean": "./ca/parseBoolean.ts", "./ca/parseJson": "./ca/parseJson.ts", "./ca/partialCheck": "./ca/partialCheck.ts", "./ca/rawCheck": "./ca/rawCheck.ts", "./ca/rawTransform": "./ca/rawTransform.ts", "./ca/regex": "./ca/regex.ts", "./ca/rfcEmail": "./ca/rfcEmail.ts", "./ca/safeInteger": "./ca/safeInteger.ts", "./ca/size": "./ca/size.ts", "./ca/slug": "./ca/slug.ts", "./ca/someItem": "./ca/someItem.ts", "./ca/startsWith": "./ca/startsWith.ts", "./ca/stringifyJson": "./ca/stringifyJson.ts", "./ca/toBigint": "./ca/toBigint.ts", "./ca/toDate": "./ca/toDate.ts", "./ca/toNumber": "./ca/toNumber.ts", "./ca/toString": "./ca/toString.ts", "./ca/ulid": "./ca/ulid.ts", "./ca/url": "./ca/url.ts", "./ca/uuid": "./ca/uuid.ts", "./ca/value": "./ca/value.ts", "./ca/values": "./ca/values.ts", "./ca/words": "./ca/words.ts", "./cs": "./cs/index.ts", "./cs/schema": "./cs/schema.ts", "./cs/base64": "./cs/base64.ts", "./cs/bic": "./cs/bic.ts", "./cs/bytes": "./cs/bytes.ts", "./cs/check": "./cs/check.ts", "./cs/checkAsync": "./cs/checkAsync.ts", "./cs/checkItems": "./cs/checkItems.ts", "./cs/checkItemsAsync": "./cs/checkItemsAsync.ts", "./cs/creditCard": "./cs/creditCard.ts", "./cs/cuid2": "./cs/cuid2.ts", "./cs/decimal": "./cs/decimal.ts", "./cs/digits": "./cs/digits.ts", "./cs/domain": "./cs/domain.ts", "./cs/email": "./cs/email.ts", "./cs/emoji": "./cs/emoji.ts", "./cs/empty": "./cs/empty.ts", "./cs/endsWith": "./cs/endsWith.ts", "./cs/entries": "./cs/entries.ts", "./cs/everyItem": "./cs/everyItem.ts", "./cs/excludes": "./cs/excludes.ts", "./cs/finite": "./cs/finite.ts", "./cs/graphemes": "./cs/graphemes.ts", "./cs/gtValue": "./cs/gtValue.ts", "./cs/guard": "./cs/guard.ts", "./cs/hash": "./cs/hash.ts", "./cs/hexadecimal": "./cs/hexadecimal.ts", "./cs/hexColor": "./cs/hexColor.ts", "./cs/imei": "./cs/imei.ts", "./cs/includes": "./cs/includes.ts", "./cs/integer": "./cs/integer.ts", "./cs/ip": "./cs/ip.ts", "./cs/ipv4": "./cs/ipv4.ts", "./cs/ipv6": "./cs/ipv6.ts", "./cs/isbn": "./cs/isbn.ts", "./cs/isoDate": "./cs/isoDate.ts", "./cs/isoDateTime": "./cs/isoDateTime.ts", "./cs/isoTime": "./cs/isoTime.ts", "./cs/isoTimeSecond": "./cs/isoTimeSecond.ts", "./cs/isoTimestamp": "./cs/isoTimestamp.ts", "./cs/isoWeek": "./cs/isoWeek.ts", "./cs/isrc": "./cs/isrc.ts", "./cs/jwsCompact": "./cs/jwsCompact.ts", "./cs/length": "./cs/length.ts", "./cs/ltValue": "./cs/ltValue.ts", "./cs/mac": "./cs/mac.ts", "./cs/mac48": "./cs/mac48.ts", "./cs/mac64": "./cs/mac64.ts", "./cs/maxBytes": "./cs/maxBytes.ts", "./cs/maxEntries": "./cs/maxEntries.ts", "./cs/maxGraphemes": "./cs/maxGraphemes.ts", "./cs/maxLength": "./cs/maxLength.ts", "./cs/maxSize": "./cs/maxSize.ts", "./cs/maxValue": "./cs/maxValue.ts", "./cs/maxWords": "./cs/maxWords.ts", "./cs/mimeType": "./cs/mimeType.ts", "./cs/minBytes": "./cs/minBytes.ts", "./cs/minEntries": "./cs/minEntries.ts", "./cs/minGraphemes": "./cs/minGraphemes.ts", "./cs/minLength": "./cs/minLength.ts", "./cs/minSize": "./cs/minSize.ts", "./cs/minValue": "./cs/minValue.ts", "./cs/minWords": "./cs/minWords.ts", "./cs/multipleOf": "./cs/multipleOf.ts", "./cs/nanoid": "./cs/nanoid.ts", "./cs/nonEmpty": "./cs/nonEmpty.ts", "./cs/notBytes": "./cs/notBytes.ts", "./cs/notEntries": "./cs/notEntries.ts", "./cs/notGraphemes": "./cs/notGraphemes.ts", "./cs/notLength": "./cs/notLength.ts", "./cs/notSize": "./cs/notSize.ts", "./cs/notValue": "./cs/notValue.ts", "./cs/notValues": "./cs/notValues.ts", "./cs/notWords": "./cs/notWords.ts", "./cs/octal": "./cs/octal.ts", "./cs/parseBoolean": "./cs/parseBoolean.ts", "./cs/parseJson": "./cs/parseJson.ts", "./cs/partialCheck": "./cs/partialCheck.ts", "./cs/rawCheck": "./cs/rawCheck.ts", "./cs/rawTransform": "./cs/rawTransform.ts", "./cs/regex": "./cs/regex.ts", "./cs/rfcEmail": "./cs/rfcEmail.ts", "./cs/safeInteger": "./cs/safeInteger.ts", "./cs/size": "./cs/size.ts", "./cs/slug": "./cs/slug.ts", "./cs/someItem": "./cs/someItem.ts", "./cs/startsWith": "./cs/startsWith.ts", "./cs/stringifyJson": "./cs/stringifyJson.ts", "./cs/toBigint": "./cs/toBigint.ts", "./cs/toDate": "./cs/toDate.ts", "./cs/toNumber": "./cs/toNumber.ts", "./cs/toString": "./cs/toString.ts", "./cs/ulid": "./cs/ulid.ts", "./cs/url": "./cs/url.ts", "./cs/uuid": "./cs/uuid.ts", "./cs/value": "./cs/value.ts", "./cs/values": "./cs/values.ts", "./cs/words": "./cs/words.ts", "./de": "./de/index.ts", "./de/schema": "./de/schema.ts", "./de/base64": "./de/base64.ts", "./de/bic": "./de/bic.ts", "./de/bytes": "./de/bytes.ts", "./de/check": "./de/check.ts", "./de/checkAsync": "./de/checkAsync.ts", "./de/checkItems": "./de/checkItems.ts", "./de/checkItemsAsync": "./de/checkItemsAsync.ts", "./de/creditCard": "./de/creditCard.ts", "./de/cuid2": "./de/cuid2.ts", "./de/decimal": "./de/decimal.ts", "./de/digits": "./de/digits.ts", "./de/domain": "./de/domain.ts", "./de/email": "./de/email.ts", "./de/emoji": "./de/emoji.ts", "./de/empty": "./de/empty.ts", "./de/endsWith": "./de/endsWith.ts", "./de/entries": "./de/entries.ts", "./de/everyItem": "./de/everyItem.ts", "./de/excludes": "./de/excludes.ts", "./de/finite": "./de/finite.ts", "./de/graphemes": "./de/graphemes.ts", "./de/gtValue": "./de/gtValue.ts", "./de/guard": "./de/guard.ts", "./de/hash": "./de/hash.ts", "./de/hexadecimal": "./de/hexadecimal.ts", "./de/hexColor": "./de/hexColor.ts", "./de/imei": "./de/imei.ts", "./de/includes": "./de/includes.ts", "./de/integer": "./de/integer.ts", "./de/ip": "./de/ip.ts", "./de/ipv4": "./de/ipv4.ts", "./de/ipv6": "./de/ipv6.ts", "./de/isbn": "./de/isbn.ts", "./de/isoDate": "./de/isoDate.ts", "./de/isoDateTime": "./de/isoDateTime.ts", "./de/isoTime": "./de/isoTime.ts", "./de/isoTimeSecond": "./de/isoTimeSecond.ts", "./de/isoTimestamp": "./de/isoTimestamp.ts", "./de/isoWeek": "./de/isoWeek.ts", "./de/isrc": "./de/isrc.ts", "./de/jwsCompact": "./de/jwsCompact.ts", "./de/length": "./de/length.ts", "./de/ltValue": "./de/ltValue.ts", "./de/mac": "./de/mac.ts", "./de/mac48": "./de/mac48.ts", "./de/mac64": "./de/mac64.ts", "./de/maxBytes": "./de/maxBytes.ts", "./de/maxEntries": "./de/maxEntries.ts", "./de/maxGraphemes": "./de/maxGraphemes.ts", "./de/maxLength": "./de/maxLength.ts", "./de/maxSize": "./de/maxSize.ts", "./de/maxValue": "./de/maxValue.ts", "./de/maxWords": "./de/maxWords.ts", "./de/mimeType": "./de/mimeType.ts", "./de/minBytes": "./de/minBytes.ts", "./de/minEntries": "./de/minEntries.ts", "./de/minGraphemes": "./de/minGraphemes.ts", "./de/minLength": "./de/minLength.ts", "./de/minSize": "./de/minSize.ts", "./de/minValue": "./de/minValue.ts", "./de/minWords": "./de/minWords.ts", "./de/multipleOf": "./de/multipleOf.ts", "./de/nanoid": "./de/nanoid.ts", "./de/nonEmpty": "./de/nonEmpty.ts", "./de/notBytes": "./de/notBytes.ts", "./de/notEntries": "./de/notEntries.ts", "./de/notGraphemes": "./de/notGraphemes.ts", "./de/notLength": "./de/notLength.ts", "./de/notSize": "./de/notSize.ts", "./de/notValue": "./de/notValue.ts", "./de/notValues": "./de/notValues.ts", "./de/notWords": "./de/notWords.ts", "./de/octal": "./de/octal.ts", "./de/parseBoolean": "./de/parseBoolean.ts", "./de/parseJson": "./de/parseJson.ts", "./de/partialCheck": "./de/partialCheck.ts", "./de/rawCheck": "./de/rawCheck.ts", "./de/rawTransform": "./de/rawTransform.ts", "./de/regex": "./de/regex.ts", "./de/rfcEmail": "./de/rfcEmail.ts", "./de/safeInteger": "./de/safeInteger.ts", "./de/size": "./de/size.ts", "./de/slug": "./de/slug.ts", "./de/someItem": "./de/someItem.ts", "./de/startsWith": "./de/startsWith.ts", "./de/stringifyJson": "./de/stringifyJson.ts", "./de/toBigint": "./de/toBigint.ts", "./de/toDate": "./de/toDate.ts", "./de/toNumber": "./de/toNumber.ts", "./de/toString": "./de/toString.ts", "./de/ulid": "./de/ulid.ts", "./de/url": "./de/url.ts", "./de/uuid": "./de/uuid.ts", "./de/value": "./de/value.ts", "./de/values": "./de/values.ts", "./de/words": "./de/words.ts", "./el": "./el/index.ts", "./el/schema": "./el/schema.ts", "./el/base64": "./el/base64.ts", "./el/bic": "./el/bic.ts", "./el/bytes": "./el/bytes.ts", "./el/check": "./el/check.ts", "./el/checkAsync": "./el/checkAsync.ts", "./el/checkItems": "./el/checkItems.ts", "./el/checkItemsAsync": "./el/checkItemsAsync.ts", "./el/creditCard": "./el/creditCard.ts", "./el/cuid2": "./el/cuid2.ts", "./el/decimal": "./el/decimal.ts", "./el/digits": "./el/digits.ts", "./el/domain": "./el/domain.ts", "./el/email": "./el/email.ts", "./el/emoji": "./el/emoji.ts", "./el/empty": "./el/empty.ts", "./el/endsWith": "./el/endsWith.ts", "./el/entries": "./el/entries.ts", "./el/everyItem": "./el/everyItem.ts", "./el/excludes": "./el/excludes.ts", "./el/finite": "./el/finite.ts", "./el/graphemes": "./el/graphemes.ts", "./el/gtValue": "./el/gtValue.ts", "./el/guard": "./el/guard.ts", "./el/hash": "./el/hash.ts", "./el/hexadecimal": "./el/hexadecimal.ts", "./el/hexColor": "./el/hexColor.ts", "./el/imei": "./el/imei.ts", "./el/includes": "./el/includes.ts", "./el/integer": "./el/integer.ts", "./el/ip": "./el/ip.ts", "./el/ipv4": "./el/ipv4.ts", "./el/ipv6": "./el/ipv6.ts", "./el/isbn": "./el/isbn.ts", "./el/isoDate": "./el/isoDate.ts", "./el/isoDateTime": "./el/isoDateTime.ts", "./el/isoTime": "./el/isoTime.ts", "./el/isoTimeSecond": "./el/isoTimeSecond.ts", "./el/isoTimestamp": "./el/isoTimestamp.ts", "./el/isoWeek": "./el/isoWeek.ts", "./el/isrc": "./el/isrc.ts", "./el/jwsCompact": "./el/jwsCompact.ts", "./el/length": "./el/length.ts", "./el/ltValue": "./el/ltValue.ts", "./el/mac": "./el/mac.ts", "./el/mac48": "./el/mac48.ts", "./el/mac64": "./el/mac64.ts", "./el/maxBytes": "./el/maxBytes.ts", "./el/maxEntries": "./el/maxEntries.ts", "./el/maxGraphemes": "./el/maxGraphemes.ts", "./el/maxLength": "./el/maxLength.ts", "./el/maxSize": "./el/maxSize.ts", "./el/maxValue": "./el/maxValue.ts", "./el/maxWords": "./el/maxWords.ts", "./el/mimeType": "./el/mimeType.ts", "./el/minBytes": "./el/minBytes.ts", "./el/minEntries": "./el/minEntries.ts", "./el/minGraphemes": "./el/minGraphemes.ts", "./el/minLength": "./el/minLength.ts", "./el/minSize": "./el/minSize.ts", "./el/minValue": "./el/minValue.ts", "./el/minWords": "./el/minWords.ts", "./el/multipleOf": "./el/multipleOf.ts", "./el/nanoid": "./el/nanoid.ts", "./el/nonEmpty": "./el/nonEmpty.ts", "./el/notBytes": "./el/notBytes.ts", "./el/notEntries": "./el/notEntries.ts", "./el/notGraphemes": "./el/notGraphemes.ts", "./el/notLength": "./el/notLength.ts", "./el/notSize": "./el/notSize.ts", "./el/notValue": "./el/notValue.ts", "./el/notValues": "./el/notValues.ts", "./el/notWords": "./el/notWords.ts", "./el/octal": "./el/octal.ts", "./el/parseBoolean": "./el/parseBoolean.ts", "./el/parseJson": "./el/parseJson.ts", "./el/partialCheck": "./el/partialCheck.ts", "./el/rawCheck": "./el/rawCheck.ts", "./el/rawTransform": "./el/rawTransform.ts", "./el/regex": "./el/regex.ts", "./el/rfcEmail": "./el/rfcEmail.ts", "./el/safeInteger": "./el/safeInteger.ts", "./el/size": "./el/size.ts", "./el/slug": "./el/slug.ts", "./el/someItem": "./el/someItem.ts", "./el/startsWith": "./el/startsWith.ts", "./el/stringifyJson": "./el/stringifyJson.ts", "./el/toBigint": "./el/toBigint.ts", "./el/toDate": "./el/toDate.ts", "./el/toNumber": "./el/toNumber.ts", "./el/toString": "./el/toString.ts", "./el/ulid": "./el/ulid.ts", "./el/url": "./el/url.ts", "./el/uuid": "./el/uuid.ts", "./el/value": "./el/value.ts", "./el/values": "./el/values.ts", "./el/words": "./el/words.ts", "./es": "./es/index.ts", "./es/schema": "./es/schema.ts", "./es/base64": "./es/base64.ts", "./es/bic": "./es/bic.ts", "./es/bytes": "./es/bytes.ts", "./es/check": "./es/check.ts", "./es/checkAsync": "./es/checkAsync.ts", "./es/checkItems": "./es/checkItems.ts", "./es/checkItemsAsync": "./es/checkItemsAsync.ts", "./es/creditCard": "./es/creditCard.ts", "./es/cuid2": "./es/cuid2.ts", "./es/decimal": "./es/decimal.ts", "./es/digits": "./es/digits.ts", "./es/domain": "./es/domain.ts", "./es/email": "./es/email.ts", "./es/emoji": "./es/emoji.ts", "./es/empty": "./es/empty.ts", "./es/endsWith": "./es/endsWith.ts", "./es/entries": "./es/entries.ts", "./es/everyItem": "./es/everyItem.ts", "./es/excludes": "./es/excludes.ts", "./es/finite": "./es/finite.ts", "./es/graphemes": "./es/graphemes.ts", "./es/gtValue": "./es/gtValue.ts", "./es/guard": "./es/guard.ts", "./es/hash": "./es/hash.ts", "./es/hexadecimal": "./es/hexadecimal.ts", "./es/hexColor": "./es/hexColor.ts", "./es/imei": "./es/imei.ts", "./es/includes": "./es/includes.ts", "./es/integer": "./es/integer.ts", "./es/ip": "./es/ip.ts", "./es/ipv4": "./es/ipv4.ts", "./es/ipv6": "./es/ipv6.ts", "./es/isbn": "./es/isbn.ts", "./es/isoDate": "./es/isoDate.ts", "./es/isoDateTime": "./es/isoDateTime.ts", "./es/isoTime": "./es/isoTime.ts", "./es/isoTimeSecond": "./es/isoTimeSecond.ts", "./es/isoTimestamp": "./es/isoTimestamp.ts", "./es/isoWeek": "./es/isoWeek.ts", "./es/isrc": "./es/isrc.ts", "./es/jwsCompact": "./es/jwsCompact.ts", "./es/length": "./es/length.ts", "./es/ltValue": "./es/ltValue.ts", "./es/mac": "./es/mac.ts", "./es/mac48": "./es/mac48.ts", "./es/mac64": "./es/mac64.ts", "./es/maxBytes": "./es/maxBytes.ts", "./es/maxEntries": "./es/maxEntries.ts", "./es/maxGraphemes": "./es/maxGraphemes.ts", "./es/maxLength": "./es/maxLength.ts", "./es/maxSize": "./es/maxSize.ts", "./es/maxValue": "./es/maxValue.ts", "./es/maxWords": "./es/maxWords.ts", "./es/mimeType": "./es/mimeType.ts", "./es/minBytes": "./es/minBytes.ts", "./es/minEntries": "./es/minEntries.ts", "./es/minGraphemes": "./es/minGraphemes.ts", "./es/minLength": "./es/minLength.ts", "./es/minSize": "./es/minSize.ts", "./es/minValue": "./es/minValue.ts", "./es/minWords": "./es/minWords.ts", "./es/multipleOf": "./es/multipleOf.ts", "./es/nanoid": "./es/nanoid.ts", "./es/nonEmpty": "./es/nonEmpty.ts", "./es/notBytes": "./es/notBytes.ts", "./es/notEntries": "./es/notEntries.ts", "./es/notGraphemes": "./es/notGraphemes.ts", "./es/notLength": "./es/notLength.ts", "./es/notSize": "./es/notSize.ts", "./es/notValue": "./es/notValue.ts", "./es/notValues": "./es/notValues.ts", "./es/notWords": "./es/notWords.ts", "./es/octal": "./es/octal.ts", "./es/parseBoolean": "./es/parseBoolean.ts", "./es/parseJson": "./es/parseJson.ts", "./es/partialCheck": "./es/partialCheck.ts", "./es/rawCheck": "./es/rawCheck.ts", "./es/rawTransform": "./es/rawTransform.ts", "./es/regex": "./es/regex.ts", "./es/rfcEmail": "./es/rfcEmail.ts", "./es/safeInteger": "./es/safeInteger.ts", "./es/size": "./es/size.ts", "./es/slug": "./es/slug.ts", "./es/someItem": "./es/someItem.ts", "./es/startsWith": "./es/startsWith.ts", "./es/stringifyJson": "./es/stringifyJson.ts", "./es/toBigint": "./es/toBigint.ts", "./es/toDate": "./es/toDate.ts", "./es/toNumber": "./es/toNumber.ts", "./es/toString": "./es/toString.ts", "./es/ulid": "./es/ulid.ts", "./es/url": "./es/url.ts", "./es/uuid": "./es/uuid.ts", "./es/value": "./es/value.ts", "./es/values": "./es/values.ts", "./es/words": "./es/words.ts", "./fa": "./fa/index.ts", "./fa/schema": "./fa/schema.ts", "./fa/base64": "./fa/base64.ts", "./fa/bic": "./fa/bic.ts", "./fa/bytes": "./fa/bytes.ts", "./fa/check": "./fa/check.ts", "./fa/checkAsync": "./fa/checkAsync.ts", "./fa/checkItems": "./fa/checkItems.ts", "./fa/checkItemsAsync": "./fa/checkItemsAsync.ts", "./fa/creditCard": "./fa/creditCard.ts", "./fa/cuid2": "./fa/cuid2.ts", "./fa/decimal": "./fa/decimal.ts", "./fa/digits": "./fa/digits.ts", "./fa/domain": "./fa/domain.ts", "./fa/email": "./fa/email.ts", "./fa/emoji": "./fa/emoji.ts", "./fa/empty": "./fa/empty.ts", "./fa/endsWith": "./fa/endsWith.ts", "./fa/entries": "./fa/entries.ts", "./fa/everyItem": "./fa/everyItem.ts", "./fa/excludes": "./fa/excludes.ts", "./fa/finite": "./fa/finite.ts", "./fa/graphemes": "./fa/graphemes.ts", "./fa/gtValue": "./fa/gtValue.ts", "./fa/guard": "./fa/guard.ts", "./fa/hash": "./fa/hash.ts", "./fa/hexadecimal": "./fa/hexadecimal.ts", "./fa/hexColor": "./fa/hexColor.ts", "./fa/imei": "./fa/imei.ts", "./fa/includes": "./fa/includes.ts", "./fa/integer": "./fa/integer.ts", "./fa/ip": "./fa/ip.ts", "./fa/ipv4": "./fa/ipv4.ts", "./fa/ipv6": "./fa/ipv6.ts", "./fa/isbn": "./fa/isbn.ts", "./fa/isoDate": "./fa/isoDate.ts", "./fa/isoDateTime": "./fa/isoDateTime.ts", "./fa/isoTime": "./fa/isoTime.ts", "./fa/isoTimeSecond": "./fa/isoTimeSecond.ts", "./fa/isoTimestamp": "./fa/isoTimestamp.ts", "./fa/isoWeek": "./fa/isoWeek.ts", "./fa/isrc": "./fa/isrc.ts", "./fa/jwsCompact": "./fa/jwsCompact.ts", "./fa/length": "./fa/length.ts", "./fa/ltValue": "./fa/ltValue.ts", "./fa/mac": "./fa/mac.ts", "./fa/mac48": "./fa/mac48.ts", "./fa/mac64": "./fa/mac64.ts", "./fa/maxBytes": "./fa/maxBytes.ts", "./fa/maxEntries": "./fa/maxEntries.ts", "./fa/maxGraphemes": "./fa/maxGraphemes.ts", "./fa/maxLength": "./fa/maxLength.ts", "./fa/maxSize": "./fa/maxSize.ts", "./fa/maxValue": "./fa/maxValue.ts", "./fa/maxWords": "./fa/maxWords.ts", "./fa/mimeType": "./fa/mimeType.ts", "./fa/minBytes": "./fa/minBytes.ts", "./fa/minEntries": "./fa/minEntries.ts", "./fa/minGraphemes": "./fa/minGraphemes.ts", "./fa/minLength": "./fa/minLength.ts", "./fa/minSize": "./fa/minSize.ts", "./fa/minValue": "./fa/minValue.ts", "./fa/minWords": "./fa/minWords.ts", "./fa/multipleOf": "./fa/multipleOf.ts", "./fa/nanoid": "./fa/nanoid.ts", "./fa/nonEmpty": "./fa/nonEmpty.ts", "./fa/notBytes": "./fa/notBytes.ts", "./fa/notEntries": "./fa/notEntries.ts", "./fa/notGraphemes": "./fa/notGraphemes.ts", "./fa/notLength": "./fa/notLength.ts", "./fa/notSize": "./fa/notSize.ts", "./fa/notValue": "./fa/notValue.ts", "./fa/notValues": "./fa/notValues.ts", "./fa/notWords": "./fa/notWords.ts", "./fa/octal": "./fa/octal.ts", "./fa/parseBoolean": "./fa/parseBoolean.ts", "./fa/parseJson": "./fa/parseJson.ts", "./fa/partialCheck": "./fa/partialCheck.ts", "./fa/rawCheck": "./fa/rawCheck.ts", "./fa/rawTransform": "./fa/rawTransform.ts", "./fa/regex": "./fa/regex.ts", "./fa/rfcEmail": "./fa/rfcEmail.ts", "./fa/safeInteger": "./fa/safeInteger.ts", "./fa/size": "./fa/size.ts", "./fa/slug": "./fa/slug.ts", "./fa/someItem": "./fa/someItem.ts", "./fa/startsWith": "./fa/startsWith.ts", "./fa/stringifyJson": "./fa/stringifyJson.ts", "./fa/toBigint": "./fa/toBigint.ts", "./fa/toDate": "./fa/toDate.ts", "./fa/toNumber": "./fa/toNumber.ts", "./fa/toString": "./fa/toString.ts", "./fa/ulid": "./fa/ulid.ts", "./fa/url": "./fa/url.ts", "./fa/uuid": "./fa/uuid.ts", "./fa/value": "./fa/value.ts", "./fa/values": "./fa/values.ts", "./fa/words": "./fa/words.ts", "./fi": "./fi/index.ts", "./fi/schema": "./fi/schema.ts", "./fi/base64": "./fi/base64.ts", "./fi/bic": "./fi/bic.ts", "./fi/bytes": "./fi/bytes.ts", "./fi/check": "./fi/check.ts", "./fi/checkAsync": "./fi/checkAsync.ts", "./fi/checkItems": "./fi/checkItems.ts", "./fi/checkItemsAsync": "./fi/checkItemsAsync.ts", "./fi/creditCard": "./fi/creditCard.ts", "./fi/cuid2": "./fi/cuid2.ts", "./fi/decimal": "./fi/decimal.ts", "./fi/digits": "./fi/digits.ts", "./fi/domain": "./fi/domain.ts", "./fi/email": "./fi/email.ts", "./fi/emoji": "./fi/emoji.ts", "./fi/empty": "./fi/empty.ts", "./fi/endsWith": "./fi/endsWith.ts", "./fi/entries": "./fi/entries.ts", "./fi/everyItem": "./fi/everyItem.ts", "./fi/excludes": "./fi/excludes.ts", "./fi/finite": "./fi/finite.ts", "./fi/graphemes": "./fi/graphemes.ts", "./fi/gtValue": "./fi/gtValue.ts", "./fi/guard": "./fi/guard.ts", "./fi/hash": "./fi/hash.ts", "./fi/hexColor": "./fi/hexColor.ts", "./fi/hexadecimal": "./fi/hexadecimal.ts", "./fi/imei": "./fi/imei.ts", "./fi/includes": "./fi/includes.ts", "./fi/integer": "./fi/integer.ts", "./fi/ip": "./fi/ip.ts", "./fi/ipv4": "./fi/ipv4.ts", "./fi/ipv6": "./fi/ipv6.ts", "./fi/isbn": "./fi/isbn.ts", "./fi/isoDate": "./fi/isoDate.ts", "./fi/isoDateTime": "./fi/isoDateTime.ts", "./fi/isoTime": "./fi/isoTime.ts", "./fi/isoTimeSecond": "./fi/isoTimeSecond.ts", "./fi/isoTimestamp": "./fi/isoTimestamp.ts", "./fi/isoWeek": "./fi/isoWeek.ts", "./fi/isrc": "./fi/isrc.ts", "./fi/jwsCompact": "./fi/jwsCompact.ts", "./fi/length": "./fi/length.ts", "./fi/ltValue": "./fi/ltValue.ts", "./fi/mac": "./fi/mac.ts", "./fi/mac48": "./fi/mac48.ts", "./fi/mac64": "./fi/mac64.ts", "./fi/maxBytes": "./fi/maxBytes.ts", "./fi/maxEntries": "./fi/maxEntries.ts", "./fi/maxGraphemes": "./fi/maxGraphemes.ts", "./fi/maxLength": "./fi/maxLength.ts", "./fi/maxSize": "./fi/maxSize.ts", "./fi/maxValue": "./fi/maxValue.ts", "./fi/maxWords": "./fi/maxWords.ts", "./fi/mimeType": "./fi/mimeType.ts", "./fi/minBytes": "./fi/minBytes.ts", "./fi/minEntries": "./fi/minEntries.ts", "./fi/minGraphemes": "./fi/minGraphemes.ts", "./fi/minLength": "./fi/minLength.ts", "./fi/minSize": "./fi/minSize.ts", "./fi/minValue": "./fi/minValue.ts", "./fi/minWords": "./fi/minWords.ts", "./fi/multipleOf": "./fi/multipleOf.ts", "./fi/nanoid": "./fi/nanoid.ts", "./fi/nonEmpty": "./fi/nonEmpty.ts", "./fi/notBytes": "./fi/notBytes.ts", "./fi/notEntries": "./fi/notEntries.ts", "./fi/notGraphemes": "./fi/notGraphemes.ts", "./fi/notLength": "./fi/notLength.ts", "./fi/notSize": "./fi/notSize.ts", "./fi/notValue": "./fi/notValue.ts", "./fi/notValues": "./fi/notValues.ts", "./fi/notWords": "./fi/notWords.ts", "./fi/octal": "./fi/octal.ts", "./fi/parseBoolean": "./fi/parseBoolean.ts", "./fi/parseJson": "./fi/parseJson.ts", "./fi/partialCheck": "./fi/partialCheck.ts", "./fi/rawCheck": "./fi/rawCheck.ts", "./fi/rawTransform": "./fi/rawTransform.ts", "./fi/regex": "./fi/regex.ts", "./fi/rfcEmail": "./fi/rfcEmail.ts", "./fi/safeInteger": "./fi/safeInteger.ts", "./fi/size": "./fi/size.ts", "./fi/slug": "./fi/slug.ts", "./fi/someItem": "./fi/someItem.ts", "./fi/startsWith": "./fi/startsWith.ts", "./fi/stringifyJson": "./fi/stringifyJson.ts", "./fi/toBigint": "./fi/toBigint.ts", "./fi/toDate": "./fi/toDate.ts", "./fi/toNumber": "./fi/toNumber.ts", "./fi/toString": "./fi/toString.ts", "./fi/ulid": "./fi/ulid.ts", "./fi/url": "./fi/url.ts", "./fi/uuid": "./fi/uuid.ts", "./fi/value": "./fi/value.ts", "./fi/values": "./fi/values.ts", "./fi/words": "./fi/words.ts", "./fr": "./fr/index.ts", "./fr/schema": "./fr/schema.ts", "./fr/base64": "./fr/base64.ts", "./fr/bic": "./fr/bic.ts", "./fr/bytes": "./fr/bytes.ts", "./fr/check": "./fr/check.ts", "./fr/checkAsync": "./fr/checkAsync.ts", "./fr/checkItems": "./fr/checkItems.ts", "./fr/checkItemsAsync": "./fr/checkItemsAsync.ts", "./fr/creditCard": "./fr/creditCard.ts", "./fr/cuid2": "./fr/cuid2.ts", "./fr/decimal": "./fr/decimal.ts", "./fr/digits": "./fr/digits.ts", "./fr/domain": "./fr/domain.ts", "./fr/email": "./fr/email.ts", "./fr/emoji": "./fr/emoji.ts", "./fr/empty": "./fr/empty.ts", "./fr/endsWith": "./fr/endsWith.ts", "./fr/entries": "./fr/entries.ts", "./fr/everyItem": "./fr/everyItem.ts", "./fr/excludes": "./fr/excludes.ts", "./fr/finite": "./fr/finite.ts", "./fr/graphemes": "./fr/graphemes.ts", "./fr/gtValue": "./fr/gtValue.ts", "./fr/guard": "./fr/guard.ts", "./fr/hash": "./fr/hash.ts", "./fr/hexadecimal": "./fr/hexadecimal.ts", "./fr/hexColor": "./fr/hexColor.ts", "./fr/imei": "./fr/imei.ts", "./fr/includes": "./fr/includes.ts", "./fr/integer": "./fr/integer.ts", "./fr/ip": "./fr/ip.ts", "./fr/ipv4": "./fr/ipv4.ts", "./fr/ipv6": "./fr/ipv6.ts", "./fr/isbn": "./fr/isbn.ts", "./fr/isoDate": "./fr/isoDate.ts", "./fr/isoDateTime": "./fr/isoDateTime.ts", "./fr/isoTime": "./fr/isoTime.ts", "./fr/isoTimeSecond": "./fr/isoTimeSecond.ts", "./fr/isoTimestamp": "./fr/isoTimestamp.ts", "./fr/isoWeek": "./fr/isoWeek.ts", "./fr/isrc": "./fr/isrc.ts", "./fr/jwsCompact": "./fr/jwsCompact.ts", "./fr/length": "./fr/length.ts", "./fr/ltValue": "./fr/ltValue.ts", "./fr/mac": "./fr/mac.ts", "./fr/mac48": "./fr/mac48.ts", "./fr/mac64": "./fr/mac64.ts", "./fr/maxBytes": "./fr/maxBytes.ts", "./fr/maxEntries": "./fr/maxEntries.ts", "./fr/maxGraphemes": "./fr/maxGraphemes.ts", "./fr/maxLength": "./fr/maxLength.ts", "./fr/maxSize": "./fr/maxSize.ts", "./fr/maxValue": "./fr/maxValue.ts", "./fr/maxWords": "./fr/maxWords.ts", "./fr/mimeType": "./fr/mimeType.ts", "./fr/minBytes": "./fr/minBytes.ts", "./fr/minEntries": "./fr/minEntries.ts", "./fr/minGraphemes": "./fr/minGraphemes.ts", "./fr/minLength": "./fr/minLength.ts", "./fr/minSize": "./fr/minSize.ts", "./fr/minValue": "./fr/minValue.ts", "./fr/minWords": "./fr/minWords.ts", "./fr/multipleOf": "./fr/multipleOf.ts", "./fr/nanoid": "./fr/nanoid.ts", "./fr/nonEmpty": "./fr/nonEmpty.ts", "./fr/notBytes": "./fr/notBytes.ts", "./fr/notEntries": "./fr/notEntries.ts", "./fr/notGraphemes": "./fr/notGraphemes.ts", "./fr/notLength": "./fr/notLength.ts", "./fr/notSize": "./fr/notSize.ts", "./fr/notValue": "./fr/notValue.ts", "./fr/notValues": "./fr/notValues.ts", "./fr/notWords": "./fr/notWords.ts", "./fr/octal": "./fr/octal.ts", "./fr/parseBoolean": "./fr/parseBoolean.ts", "./fr/parseJson": "./fr/parseJson.ts", "./fr/partialCheck": "./fr/partialCheck.ts", "./fr/rawCheck": "./fr/rawCheck.ts", "./fr/rawTransform": "./fr/rawTransform.ts", "./fr/regex": "./fr/regex.ts", "./fr/rfcEmail": "./fr/rfcEmail.ts", "./fr/safeInteger": "./fr/safeInteger.ts", "./fr/size": "./fr/size.ts", "./fr/slug": "./fr/slug.ts", "./fr/someItem": "./fr/someItem.ts", "./fr/startsWith": "./fr/startsWith.ts", "./fr/stringifyJson": "./fr/stringifyJson.ts", "./fr/toBigint": "./fr/toBigint.ts", "./fr/toDate": "./fr/toDate.ts", "./fr/toNumber": "./fr/toNumber.ts", "./fr/toString": "./fr/toString.ts", "./fr/ulid": "./fr/ulid.ts", "./fr/url": "./fr/url.ts", "./fr/uuid": "./fr/uuid.ts", "./fr/value": "./fr/value.ts", "./fr/values": "./fr/values.ts", "./fr/words": "./fr/words.ts", "./hu": "./hu/index.ts", "./hu/schema": "./hu/schema.ts", "./hu/base64": "./hu/base64.ts", "./hu/bic": "./hu/bic.ts", "./hu/bytes": "./hu/bytes.ts", "./hu/check": "./hu/check.ts", "./hu/checkAsync": "./hu/checkAsync.ts", "./hu/checkItems": "./hu/checkItems.ts", "./hu/checkItemsAsync": "./hu/checkItemsAsync.ts", "./hu/creditCard": "./hu/creditCard.ts", "./hu/cuid2": "./hu/cuid2.ts", "./hu/decimal": "./hu/decimal.ts", "./hu/digits": "./hu/digits.ts", "./hu/domain": "./hu/domain.ts", "./hu/email": "./hu/email.ts", "./hu/emoji": "./hu/emoji.ts", "./hu/empty": "./hu/empty.ts", "./hu/endsWith": "./hu/endsWith.ts", "./hu/entries": "./hu/entries.ts", "./hu/everyItem": "./hu/everyItem.ts", "./hu/excludes": "./hu/excludes.ts", "./hu/finite": "./hu/finite.ts", "./hu/graphemes": "./hu/graphemes.ts", "./hu/gtValue": "./hu/gtValue.ts", "./hu/guard": "./hu/guard.ts", "./hu/hash": "./hu/hash.ts", "./hu/hexadecimal": "./hu/hexadecimal.ts", "./hu/hexColor": "./hu/hexColor.ts", "./hu/imei": "./hu/imei.ts", "./hu/includes": "./hu/includes.ts", "./hu/integer": "./hu/integer.ts", "./hu/ip": "./hu/ip.ts", "./hu/ipv4": "./hu/ipv4.ts", "./hu/ipv6": "./hu/ipv6.ts", "./hu/isbn": "./hu/isbn.ts", "./hu/isoDate": "./hu/isoDate.ts", "./hu/isoDateTime": "./hu/isoDateTime.ts", "./hu/isoTime": "./hu/isoTime.ts", "./hu/isoTimeSecond": "./hu/isoTimeSecond.ts", "./hu/isoTimestamp": "./hu/isoTimestamp.ts", "./hu/isoWeek": "./hu/isoWeek.ts", "./hu/isrc": "./hu/isrc.ts", "./hu/jwsCompact": "./hu/jwsCompact.ts", "./hu/length": "./hu/length.ts", "./hu/ltValue": "./hu/ltValue.ts", "./hu/mac": "./hu/mac.ts", "./hu/mac48": "./hu/mac48.ts", "./hu/mac64": "./hu/mac64.ts", "./hu/maxBytes": "./hu/maxBytes.ts", "./hu/maxEntries": "./hu/maxEntries.ts", "./hu/maxGraphemes": "./hu/maxGraphemes.ts", "./hu/maxLength": "./hu/maxLength.ts", "./hu/maxSize": "./hu/maxSize.ts", "./hu/maxValue": "./hu/maxValue.ts", "./hu/maxWords": "./hu/maxWords.ts", "./hu/mimeType": "./hu/mimeType.ts", "./hu/minBytes": "./hu/minBytes.ts", "./hu/minEntries": "./hu/minEntries.ts", "./hu/minGraphemes": "./hu/minGraphemes.ts", "./hu/minLength": "./hu/minLength.ts", "./hu/minSize": "./hu/minSize.ts", "./hu/minValue": "./hu/minValue.ts", "./hu/minWords": "./hu/minWords.ts", "./hu/multipleOf": "./hu/multipleOf.ts", "./hu/nanoid": "./hu/nanoid.ts", "./hu/nonEmpty": "./hu/nonEmpty.ts", "./hu/notBytes": "./hu/notBytes.ts", "./hu/notEntries": "./hu/notEntries.ts", "./hu/notGraphemes": "./hu/notGraphemes.ts", "./hu/notLength": "./hu/notLength.ts", "./hu/notSize": "./hu/notSize.ts", "./hu/notValue": "./hu/notValue.ts", "./hu/notValues": "./hu/notValues.ts", "./hu/notWords": "./hu/notWords.ts", "./hu/octal": "./hu/octal.ts", "./hu/parseBoolean": "./hu/parseBoolean.ts", "./hu/parseJson": "./hu/parseJson.ts", "./hu/partialCheck": "./hu/partialCheck.ts", "./hu/rawCheck": "./hu/rawCheck.ts", "./hu/rawTransform": "./hu/rawTransform.ts", "./hu/regex": "./hu/regex.ts", "./hu/rfcEmail": "./hu/rfcEmail.ts", "./hu/safeInteger": "./hu/safeInteger.ts", "./hu/size": "./hu/size.ts", "./hu/slug": "./hu/slug.ts", "./hu/someItem": "./hu/someItem.ts", "./hu/startsWith": "./hu/startsWith.ts", "./hu/stringifyJson": "./hu/stringifyJson.ts", "./hu/toBigint": "./hu/toBigint.ts", "./hu/toDate": "./hu/toDate.ts", "./hu/toNumber": "./hu/toNumber.ts", "./hu/toString": "./hu/toString.ts", "./hu/ulid": "./hu/ulid.ts", "./hu/url": "./hu/url.ts", "./hu/uuid": "./hu/uuid.ts", "./hu/value": "./hu/value.ts", "./hu/values": "./hu/values.ts", "./hu/words": "./hu/words.ts", "./id": "./id/index.ts", "./id/schema": "./id/schema.ts", "./id/base64": "./id/base64.ts", "./id/bic": "./id/bic.ts", "./id/bytes": "./id/bytes.ts", "./id/check": "./id/check.ts", "./id/checkAsync": "./id/checkAsync.ts", "./id/checkItems": "./id/checkItems.ts", "./id/checkItemsAsync": "./id/checkItemsAsync.ts", "./id/creditCard": "./id/creditCard.ts", "./id/cuid2": "./id/cuid2.ts", "./id/decimal": "./id/decimal.ts", "./id/digits": "./id/digits.ts", "./id/domain": "./id/domain.ts", "./id/email": "./id/email.ts", "./id/emoji": "./id/emoji.ts", "./id/empty": "./id/empty.ts", "./id/endsWith": "./id/endsWith.ts", "./id/entries": "./id/entries.ts", "./id/everyItem": "./id/everyItem.ts", "./id/excludes": "./id/excludes.ts", "./id/finite": "./id/finite.ts", "./id/graphemes": "./id/graphemes.ts", "./id/gtValue": "./id/gtValue.ts", "./id/guard": "./id/guard.ts", "./id/hash": "./id/hash.ts", "./id/hexadecimal": "./id/hexadecimal.ts", "./id/hexColor": "./id/hexColor.ts", "./id/imei": "./id/imei.ts", "./id/includes": "./id/includes.ts", "./id/integer": "./id/integer.ts", "./id/ip": "./id/ip.ts", "./id/ipv4": "./id/ipv4.ts", "./id/ipv6": "./id/ipv6.ts", "./id/isbn": "./id/isbn.ts", "./id/isoDate": "./id/isoDate.ts", "./id/isoDateTime": "./id/isoDateTime.ts", "./id/isoTime": "./id/isoTime.ts", "./id/isoTimeSecond": "./id/isoTimeSecond.ts", "./id/isoTimestamp": "./id/isoTimestamp.ts", "./id/isoWeek": "./id/isoWeek.ts", "./id/isrc": "./id/isrc.ts", "./id/jwsCompact": "./id/jwsCompact.ts", "./id/length": "./id/length.ts", "./id/ltValue": "./id/ltValue.ts", "./id/mac": "./id/mac.ts", "./id/mac48": "./id/mac48.ts", "./id/mac64": "./id/mac64.ts", "./id/maxBytes": "./id/maxBytes.ts", "./id/maxEntries": "./id/maxEntries.ts", "./id/maxGraphemes": "./id/maxGraphemes.ts", "./id/maxLength": "./id/maxLength.ts", "./id/maxSize": "./id/maxSize.ts", "./id/maxValue": "./id/maxValue.ts", "./id/maxWords": "./id/maxWords.ts", "./id/mimeType": "./id/mimeType.ts", "./id/minBytes": "./id/minBytes.ts", "./id/minEntries": "./id/minEntries.ts", "./id/minGraphemes": "./id/minGraphemes.ts", "./id/minLength": "./id/minLength.ts", "./id/minSize": "./id/minSize.ts", "./id/minValue": "./id/minValue.ts", "./id/minWords": "./id/minWords.ts", "./id/multipleOf": "./id/multipleOf.ts", "./id/nanoid": "./id/nanoid.ts", "./id/nonEmpty": "./id/nonEmpty.ts", "./id/notBytes": "./id/notBytes.ts", "./id/notEntries": "./id/notEntries.ts", "./id/notGraphemes": "./id/notGraphemes.ts", "./id/notLength": "./id/notLength.ts", "./id/notSize": "./id/notSize.ts", "./id/notValue": "./id/notValue.ts", "./id/notValues": "./id/notValues.ts", "./id/notWords": "./id/notWords.ts", "./id/octal": "./id/octal.ts", "./id/parseBoolean": "./id/parseBoolean.ts", "./id/parseJson": "./id/parseJson.ts", "./id/partialCheck": "./id/partialCheck.ts", "./id/rawCheck": "./id/rawCheck.ts", "./id/rawTransform": "./id/rawTransform.ts", "./id/regex": "./id/regex.ts", "./id/rfcEmail": "./id/rfcEmail.ts", "./id/safeInteger": "./id/safeInteger.ts", "./id/size": "./id/size.ts", "./id/slug": "./id/slug.ts", "./id/someItem": "./id/someItem.ts", "./id/startsWith": "./id/startsWith.ts", "./id/stringifyJson": "./id/stringifyJson.ts", "./id/toBigint": "./id/toBigint.ts", "./id/toDate": "./id/toDate.ts", "./id/toNumber": "./id/toNumber.ts", "./id/toString": "./id/toString.ts", "./id/ulid": "./id/ulid.ts", "./id/url": "./id/url.ts", "./id/uuid": "./id/uuid.ts", "./id/value": "./id/value.ts", "./id/values": "./id/values.ts", "./id/words": "./id/words.ts", "./it": "./it/index.ts", "./it/schema": "./it/schema.ts", "./it/base64": "./it/base64.ts", "./it/bic": "./it/bic.ts", "./it/bytes": "./it/bytes.ts", "./it/check": "./it/check.ts", "./it/checkAsync": "./it/checkAsync.ts", "./it/checkItems": "./it/checkItems.ts", "./it/checkItemsAsync": "./it/checkItemsAsync.ts", "./it/creditCard": "./it/creditCard.ts", "./it/cuid2": "./it/cuid2.ts", "./it/decimal": "./it/decimal.ts", "./it/digits": "./it/digits.ts", "./it/domain": "./it/domain.ts", "./it/email": "./it/email.ts", "./it/emoji": "./it/emoji.ts", "./it/empty": "./it/empty.ts", "./it/endsWith": "./it/endsWith.ts", "./it/entries": "./it/entries.ts", "./it/everyItem": "./it/everyItem.ts", "./it/excludes": "./it/excludes.ts", "./it/finite": "./it/finite.ts", "./it/graphemes": "./it/graphemes.ts", "./it/gtValue": "./it/gtValue.ts", "./it/guard": "./it/guard.ts", "./it/hash": "./it/hash.ts", "./it/hexadecimal": "./it/hexadecimal.ts", "./it/hexColor": "./it/hexColor.ts", "./it/imei": "./it/imei.ts", "./it/includes": "./it/includes.ts", "./it/integer": "./it/integer.ts", "./it/ip": "./it/ip.ts", "./it/ipv4": "./it/ipv4.ts", "./it/ipv6": "./it/ipv6.ts", "./it/isbn": "./it/isbn.ts", "./it/isoDate": "./it/isoDate.ts", "./it/isoDateTime": "./it/isoDateTime.ts", "./it/isoTime": "./it/isoTime.ts", "./it/isoTimeSecond": "./it/isoTimeSecond.ts", "./it/isoTimestamp": "./it/isoTimestamp.ts", "./it/isoWeek": "./it/isoWeek.ts", "./it/isrc": "./it/isrc.ts", "./it/jwsCompact": "./it/jwsCompact.ts", "./it/length": "./it/length.ts", "./it/ltValue": "./it/ltValue.ts", "./it/mac": "./it/mac.ts", "./it/mac48": "./it/mac48.ts", "./it/mac64": "./it/mac64.ts", "./it/maxBytes": "./it/maxBytes.ts", "./it/maxEntries": "./it/maxEntries.ts", "./it/maxGraphemes": "./it/maxGraphemes.ts", "./it/maxLength": "./it/maxLength.ts", "./it/maxSize": "./it/maxSize.ts", "./it/maxValue": "./it/maxValue.ts", "./it/maxWords": "./it/maxWords.ts", "./it/mimeType": "./it/mimeType.ts", "./it/minBytes": "./it/minBytes.ts", "./it/minEntries": "./it/minEntries.ts", "./it/minGraphemes": "./it/minGraphemes.ts", "./it/minLength": "./it/minLength.ts", "./it/minSize": "./it/minSize.ts", "./it/minValue": "./it/minValue.ts", "./it/minWords": "./it/minWords.ts", "./it/multipleOf": "./it/multipleOf.ts", "./it/nanoid": "./it/nanoid.ts", "./it/nonEmpty": "./it/nonEmpty.ts", "./it/notBytes": "./it/notBytes.ts", "./it/notEntries": "./it/notEntries.ts", "./it/notGraphemes": "./it/notGraphemes.ts", "./it/notLength": "./it/notLength.ts", "./it/notSize": "./it/notSize.ts", "./it/notValue": "./it/notValue.ts", "./it/notValues": "./it/notValues.ts", "./it/notWords": "./it/notWords.ts", "./it/octal": "./it/octal.ts", "./it/parseBoolean": "./it/parseBoolean.ts", "./it/parseJson": "./it/parseJson.ts", "./it/partialCheck": "./it/partialCheck.ts", "./it/rawCheck": "./it/rawCheck.ts", "./it/rawTransform": "./it/rawTransform.ts", "./it/regex": "./it/regex.ts", "./it/rfcEmail": "./it/rfcEmail.ts", "./it/safeInteger": "./it/safeInteger.ts", "./it/size": "./it/size.ts", "./it/slug": "./it/slug.ts", "./it/someItem": "./it/someItem.ts", "./it/startsWith": "./it/startsWith.ts", "./it/stringifyJson": "./it/stringifyJson.ts", "./it/toBigint": "./it/toBigint.ts", "./it/toDate": "./it/toDate.ts", "./it/toNumber": "./it/toNumber.ts", "./it/toString": "./it/toString.ts", "./it/ulid": "./it/ulid.ts", "./it/url": "./it/url.ts", "./it/uuid": "./it/uuid.ts", "./it/value": "./it/value.ts", "./it/values": "./it/values.ts", "./it/words": "./it/words.ts", "./ja": "./ja/index.ts", "./ja/schema": "./ja/schema.ts", "./ja/base64": "./ja/base64.ts", "./ja/bic": "./ja/bic.ts", "./ja/bytes": "./ja/bytes.ts", "./ja/check": "./ja/check.ts", "./ja/checkAsync": "./ja/checkAsync.ts", "./ja/checkItems": "./ja/checkItems.ts", "./ja/checkItemsAsync": "./ja/checkItemsAsync.ts", "./ja/creditCard": "./ja/creditCard.ts", "./ja/cuid2": "./ja/cuid2.ts", "./ja/decimal": "./ja/decimal.ts", "./ja/digits": "./ja/digits.ts", "./ja/domain": "./ja/domain.ts", "./ja/email": "./ja/email.ts", "./ja/emoji": "./ja/emoji.ts", "./ja/empty": "./ja/empty.ts", "./ja/endsWith": "./ja/endsWith.ts", "./ja/entries": "./ja/entries.ts", "./ja/everyItem": "./ja/everyItem.ts", "./ja/excludes": "./ja/excludes.ts", "./ja/finite": "./ja/finite.ts", "./ja/graphemes": "./ja/graphemes.ts", "./ja/gtValue": "./ja/gtValue.ts", "./ja/guard": "./ja/guard.ts", "./ja/hash": "./ja/hash.ts", "./ja/hexadecimal": "./ja/hexadecimal.ts", "./ja/hexColor": "./ja/hexColor.ts", "./ja/imei": "./ja/imei.ts", "./ja/includes": "./ja/includes.ts", "./ja/integer": "./ja/integer.ts", "./ja/ip": "./ja/ip.ts", "./ja/ipv4": "./ja/ipv4.ts", "./ja/ipv6": "./ja/ipv6.ts", "./ja/isbn": "./ja/isbn.ts", "./ja/isoDate": "./ja/isoDate.ts", "./ja/isoDateTime": "./ja/isoDateTime.ts", "./ja/isoTime": "./ja/isoTime.ts", "./ja/isoTimeSecond": "./ja/isoTimeSecond.ts", "./ja/isoTimestamp": "./ja/isoTimestamp.ts", "./ja/isoWeek": "./ja/isoWeek.ts", "./ja/isrc": "./ja/isrc.ts", "./ja/jwsCompact": "./ja/jwsCompact.ts", "./ja/length": "./ja/length.ts", "./ja/ltValue": "./ja/ltValue.ts", "./ja/mac": "./ja/mac.ts", "./ja/mac48": "./ja/mac48.ts", "./ja/mac64": "./ja/mac64.ts", "./ja/maxBytes": "./ja/maxBytes.ts", "./ja/maxEntries": "./ja/maxEntries.ts", "./ja/maxGraphemes": "./ja/maxGraphemes.ts", "./ja/maxLength": "./ja/maxLength.ts", "./ja/maxSize": "./ja/maxSize.ts", "./ja/maxValue": "./ja/maxValue.ts", "./ja/maxWords": "./ja/maxWords.ts", "./ja/mimeType": "./ja/mimeType.ts", "./ja/minBytes": "./ja/minBytes.ts", "./ja/minEntries": "./ja/minEntries.ts", "./ja/minGraphemes": "./ja/minGraphemes.ts", "./ja/minLength": "./ja/minLength.ts", "./ja/minSize": "./ja/minSize.ts", "./ja/minValue": "./ja/minValue.ts", "./ja/minWords": "./ja/minWords.ts", "./ja/multipleOf": "./ja/multipleOf.ts", "./ja/nanoid": "./ja/nanoid.ts", "./ja/nonEmpty": "./ja/nonEmpty.ts", "./ja/notBytes": "./ja/notBytes.ts", "./ja/notEntries": "./ja/notEntries.ts", "./ja/notGraphemes": "./ja/notGraphemes.ts", "./ja/notLength": "./ja/notLength.ts", "./ja/notSize": "./ja/notSize.ts", "./ja/notValue": "./ja/notValue.ts", "./ja/notValues": "./ja/notValues.ts", "./ja/notWords": "./ja/notWords.ts", "./ja/octal": "./ja/octal.ts", "./ja/parseBoolean": "./ja/parseBoolean.ts", "./ja/parseJson": "./ja/parseJson.ts", "./ja/partialCheck": "./ja/partialCheck.ts", "./ja/rawCheck": "./ja/rawCheck.ts", "./ja/rawTransform": "./ja/rawTransform.ts", "./ja/regex": "./ja/regex.ts", "./ja/rfcEmail": "./ja/rfcEmail.ts", "./ja/safeInteger": "./ja/safeInteger.ts", "./ja/size": "./ja/size.ts", "./ja/slug": "./ja/slug.ts", "./ja/someItem": "./ja/someItem.ts", "./ja/startsWith": "./ja/startsWith.ts", "./ja/stringifyJson": "./ja/stringifyJson.ts", "./ja/toBigint": "./ja/toBigint.ts", "./ja/toDate": "./ja/toDate.ts", "./ja/toNumber": "./ja/toNumber.ts", "./ja/toString": "./ja/toString.ts", "./ja/ulid": "./ja/ulid.ts", "./ja/url": "./ja/url.ts", "./ja/uuid": "./ja/uuid.ts", "./ja/value": "./ja/value.ts", "./ja/values": "./ja/values.ts", "./ja/words": "./ja/words.ts", "./ko": "./ko/index.ts", "./ko/schema": "./ko/schema.ts", "./ko/base64": "./ko/base64.ts", "./ko/bic": "./ko/bic.ts", "./ko/bytes": "./ko/bytes.ts", "./ko/check": "./ko/check.ts", "./ko/checkAsync": "./ko/checkAsync.ts", "./ko/checkItems": "./ko/checkItems.ts", "./ko/checkItemsAsync": "./ko/checkItemsAsync.ts", "./ko/creditCard": "./ko/creditCard.ts", "./ko/cuid2": "./ko/cuid2.ts", "./ko/decimal": "./ko/decimal.ts", "./ko/digits": "./ko/digits.ts", "./ko/domain": "./ko/domain.ts", "./ko/email": "./ko/email.ts", "./ko/emoji": "./ko/emoji.ts", "./ko/empty": "./ko/empty.ts", "./ko/endsWith": "./ko/endsWith.ts", "./ko/entries": "./ko/entries.ts", "./ko/everyItem": "./ko/everyItem.ts", "./ko/excludes": "./ko/excludes.ts", "./ko/finite": "./ko/finite.ts", "./ko/graphemes": "./ko/graphemes.ts", "./ko/gtValue": "./ko/gtValue.ts", "./ko/guard": "./ko/guard.ts", "./ko/hash": "./ko/hash.ts", "./ko/hexadecimal": "./ko/hexadecimal.ts", "./ko/hexColor": "./ko/hexColor.ts", "./ko/imei": "./ko/imei.ts", "./ko/includes": "./ko/includes.ts", "./ko/integer": "./ko/integer.ts", "./ko/ip": "./ko/ip.ts", "./ko/ipv4": "./ko/ipv4.ts", "./ko/ipv6": "./ko/ipv6.ts", "./ko/isbn": "./ko/isbn.ts", "./ko/isoDate": "./ko/isoDate.ts", "./ko/isoDateTime": "./ko/isoDateTime.ts", "./ko/isoTime": "./ko/isoTime.ts", "./ko/isoTimeSecond": "./ko/isoTimeSecond.ts", "./ko/isoTimestamp": "./ko/isoTimestamp.ts", "./ko/isoWeek": "./ko/isoWeek.ts", "./ko/isrc": "./ko/isrc.ts", "./ko/jwsCompact": "./ko/jwsCompact.ts", "./ko/length": "./ko/length.ts", "./ko/ltValue": "./ko/ltValue.ts", "./ko/mac": "./ko/mac.ts", "./ko/mac48": "./ko/mac48.ts", "./ko/mac64": "./ko/mac64.ts", "./ko/maxBytes": "./ko/maxBytes.ts", "./ko/maxEntries": "./ko/maxEntries.ts", "./ko/maxGraphemes": "./ko/maxGraphemes.ts", "./ko/maxLength": "./ko/maxLength.ts", "./ko/maxSize": "./ko/maxSize.ts", "./ko/maxValue": "./ko/maxValue.ts", "./ko/maxWords": "./ko/maxWords.ts", "./ko/mimeType": "./ko/mimeType.ts", "./ko/minBytes": "./ko/minBytes.ts", "./ko/minEntries": "./ko/minEntries.ts", "./ko/minGraphemes": "./ko/minGraphemes.ts", "./ko/minLength": "./ko/minLength.ts", "./ko/minSize": "./ko/minSize.ts", "./ko/minValue": "./ko/minValue.ts", "./ko/minWords": "./ko/minWords.ts", "./ko/multipleOf": "./ko/multipleOf.ts", "./ko/nanoid": "./ko/nanoid.ts", "./ko/nonEmpty": "./ko/nonEmpty.ts", "./ko/notBytes": "./ko/notBytes.ts", "./ko/notEntries": "./ko/notEntries.ts", "./ko/notGraphemes": "./ko/notGraphemes.ts", "./ko/notLength": "./ko/notLength.ts", "./ko/notSize": "./ko/notSize.ts", "./ko/notValue": "./ko/notValue.ts", "./ko/notValues": "./ko/notValues.ts", "./ko/notWords": "./ko/notWords.ts", "./ko/octal": "./ko/octal.ts", "./ko/parseBoolean": "./ko/parseBoolean.ts", "./ko/parseJson": "./ko/parseJson.ts", "./ko/partialCheck": "./ko/partialCheck.ts", "./ko/rawCheck": "./ko/rawCheck.ts", "./ko/rawTransform": "./ko/rawTransform.ts", "./ko/regex": "./ko/regex.ts", "./ko/rfcEmail": "./ko/rfcEmail.ts", "./ko/safeInteger": "./ko/safeInteger.ts", "./ko/size": "./ko/size.ts", "./ko/slug": "./ko/slug.ts", "./ko/someItem": "./ko/someItem.ts", "./ko/startsWith": "./ko/startsWith.ts", "./ko/stringifyJson": "./ko/stringifyJson.ts", "./ko/toBigint": "./ko/toBigint.ts", "./ko/toDate": "./ko/toDate.ts", "./ko/toNumber": "./ko/toNumber.ts", "./ko/toString": "./ko/toString.ts", "./ko/ulid": "./ko/ulid.ts", "./ko/url": "./ko/url.ts", "./ko/uuid": "./ko/uuid.ts", "./ko/value": "./ko/value.ts", "./ko/values": "./ko/values.ts", "./ko/words": "./ko/words.ts", "./kr": "./kr/index.ts", "./kr/schema": "./kr/schema.ts", "./kr/base64": "./kr/base64.ts", "./kr/bic": "./kr/bic.ts", "./kr/bytes": "./kr/bytes.ts", "./kr/check": "./kr/check.ts", "./kr/checkAsync": "./kr/checkAsync.ts", "./kr/checkItems": "./kr/checkItems.ts", "./kr/checkItemsAsync": "./kr/checkItemsAsync.ts", "./kr/creditCard": "./kr/creditCard.ts", "./kr/cuid2": "./kr/cuid2.ts", "./kr/decimal": "./kr/decimal.ts", "./kr/digits": "./kr/digits.ts", "./kr/domain": "./kr/domain.ts", "./kr/email": "./kr/email.ts", "./kr/emoji": "./kr/emoji.ts", "./kr/empty": "./kr/empty.ts", "./kr/endsWith": "./kr/endsWith.ts", "./kr/entries": "./kr/entries.ts", "./kr/everyItem": "./kr/everyItem.ts", "./kr/excludes": "./kr/excludes.ts", "./kr/finite": "./kr/finite.ts", "./kr/graphemes": "./kr/graphemes.ts", "./kr/gtValue": "./kr/gtValue.ts", "./kr/guard": "./kr/guard.ts", "./kr/hash": "./kr/hash.ts", "./kr/hexadecimal": "./kr/hexadecimal.ts", "./kr/hexColor": "./kr/hexColor.ts", "./kr/imei": "./kr/imei.ts", "./kr/includes": "./kr/includes.ts", "./kr/integer": "./kr/integer.ts", "./kr/ip": "./kr/ip.ts", "./kr/ipv4": "./kr/ipv4.ts", "./kr/ipv6": "./kr/ipv6.ts", "./kr/isbn": "./kr/isbn.ts", "./kr/isoDate": "./kr/isoDate.ts", "./kr/isoDateTime": "./kr/isoDateTime.ts", "./kr/isoTime": "./kr/isoTime.ts", "./kr/isoTimeSecond": "./kr/isoTimeSecond.ts", "./kr/isoTimestamp": "./kr/isoTimestamp.ts", "./kr/isoWeek": "./kr/isoWeek.ts", "./kr/isrc": "./kr/isrc.ts", "./kr/jwsCompact": "./kr/jwsCompact.ts", "./kr/length": "./kr/length.ts", "./kr/ltValue": "./kr/ltValue.ts", "./kr/mac": "./kr/mac.ts", "./kr/mac48": "./kr/mac48.ts", "./kr/mac64": "./kr/mac64.ts", "./kr/maxBytes": "./kr/maxBytes.ts", "./kr/maxEntries": "./kr/maxEntries.ts", "./kr/maxGraphemes": "./kr/maxGraphemes.ts", "./kr/maxLength": "./kr/maxLength.ts", "./kr/maxSize": "./kr/maxSize.ts", "./kr/maxValue": "./kr/maxValue.ts", "./kr/maxWords": "./kr/maxWords.ts", "./kr/mimeType": "./kr/mimeType.ts", "./kr/minBytes": "./kr/minBytes.ts", "./kr/minEntries": "./kr/minEntries.ts", "./kr/minGraphemes": "./kr/minGraphemes.ts", "./kr/minLength": "./kr/minLength.ts", "./kr/minSize": "./kr/minSize.ts", "./kr/minValue": "./kr/minValue.ts", "./kr/minWords": "./kr/minWords.ts", "./kr/multipleOf": "./kr/multipleOf.ts", "./kr/nanoid": "./kr/nanoid.ts", "./kr/nonEmpty": "./kr/nonEmpty.ts", "./kr/notBytes": "./kr/notBytes.ts", "./kr/notEntries": "./kr/notEntries.ts", "./kr/notGraphemes": "./kr/notGraphemes.ts", "./kr/notLength": "./kr/notLength.ts", "./kr/notSize": "./kr/notSize.ts", "./kr/notValue": "./kr/notValue.ts", "./kr/notValues": "./kr/notValues.ts", "./kr/notWords": "./kr/notWords.ts", "./kr/octal": "./kr/octal.ts", "./kr/parseBoolean": "./kr/parseBoolean.ts", "./kr/parseJson": "./kr/parseJson.ts", "./kr/partialCheck": "./kr/partialCheck.ts", "./kr/rawCheck": "./kr/rawCheck.ts", "./kr/rawTransform": "./kr/rawTransform.ts", "./kr/regex": "./kr/regex.ts", "./kr/rfcEmail": "./kr/rfcEmail.ts", "./kr/safeInteger": "./kr/safeInteger.ts", "./kr/size": "./kr/size.ts", "./kr/slug": "./kr/slug.ts", "./kr/someItem": "./kr/someItem.ts", "./kr/startsWith": "./kr/startsWith.ts", "./kr/stringifyJson": "./kr/stringifyJson.ts", "./kr/toBigint": "./kr/toBigint.ts", "./kr/toDate": "./kr/toDate.ts", "./kr/toNumber": "./kr/toNumber.ts", "./kr/toString": "./kr/toString.ts", "./kr/ulid": "./kr/ulid.ts", "./kr/url": "./kr/url.ts", "./kr/uuid": "./kr/uuid.ts", "./kr/value": "./kr/value.ts", "./kr/values": "./kr/values.ts", "./kr/words": "./kr/words.ts", "./mn": "./mn/index.ts", "./mn/schema": "./mn/schema.ts", "./mn/base64": "./mn/base64.ts", "./mn/bic": "./mn/bic.ts", "./mn/bytes": "./mn/bytes.ts", "./mn/check": "./mn/check.ts", "./mn/checkAsync": "./mn/checkAsync.ts", "./mn/checkItems": "./mn/checkItems.ts", "./mn/checkItemsAsync": "./mn/checkItemsAsync.ts", "./mn/creditCard": "./mn/creditCard.ts", "./mn/cuid2": "./mn/cuid2.ts", "./mn/decimal": "./mn/decimal.ts", "./mn/digits": "./mn/digits.ts", "./mn/domain": "./mn/domain.ts", "./mn/email": "./mn/email.ts", "./mn/emoji": "./mn/emoji.ts", "./mn/empty": "./mn/empty.ts", "./mn/endsWith": "./mn/endsWith.ts", "./mn/entries": "./mn/entries.ts", "./mn/everyItem": "./mn/everyItem.ts", "./mn/excludes": "./mn/excludes.ts", "./mn/finite": "./mn/finite.ts", "./mn/graphemes": "./mn/graphemes.ts", "./mn/gtValue": "./mn/gtValue.ts", "./mn/guard": "./mn/guard.ts", "./mn/hash": "./mn/hash.ts", "./mn/hexColor": "./mn/hexColor.ts", "./mn/hexadecimal": "./mn/hexadecimal.ts", "./mn/imei": "./mn/imei.ts", "./mn/includes": "./mn/includes.ts", "./mn/integer": "./mn/integer.ts", "./mn/ip": "./mn/ip.ts", "./mn/ipv4": "./mn/ipv4.ts", "./mn/ipv6": "./mn/ipv6.ts", "./mn/isbn": "./mn/isbn.ts", "./mn/isoDate": "./mn/isoDate.ts", "./mn/isoDateTime": "./mn/isoDateTime.ts", "./mn/isoTime": "./mn/isoTime.ts", "./mn/isoTimeSecond": "./mn/isoTimeSecond.ts", "./mn/isoTimestamp": "./mn/isoTimestamp.ts", "./mn/isoWeek": "./mn/isoWeek.ts", "./mn/isrc": "./mn/isrc.ts", "./mn/jwsCompact": "./mn/jwsCompact.ts", "./mn/length": "./mn/length.ts", "./mn/ltValue": "./mn/ltValue.ts", "./mn/mac": "./mn/mac.ts", "./mn/mac48": "./mn/mac48.ts", "./mn/mac64": "./mn/mac64.ts", "./mn/maxBytes": "./mn/maxBytes.ts", "./mn/maxEntries": "./mn/maxEntries.ts", "./mn/maxGraphemes": "./mn/maxGraphemes.ts", "./mn/maxLength": "./mn/maxLength.ts", "./mn/maxSize": "./mn/maxSize.ts", "./mn/maxValue": "./mn/maxValue.ts", "./mn/maxWords": "./mn/maxWords.ts", "./mn/mimeType": "./mn/mimeType.ts", "./mn/minBytes": "./mn/minBytes.ts", "./mn/minEntries": "./mn/minEntries.ts", "./mn/minGraphemes": "./mn/minGraphemes.ts", "./mn/minLength": "./mn/minLength.ts", "./mn/minSize": "./mn/minSize.ts", "./mn/minValue": "./mn/minValue.ts", "./mn/minWords": "./mn/minWords.ts", "./mn/multipleOf": "./mn/multipleOf.ts", "./mn/nanoid": "./mn/nanoid.ts", "./mn/nonEmpty": "./mn/nonEmpty.ts", "./mn/notBytes": "./mn/notBytes.ts", "./mn/notEntries": "./mn/notEntries.ts", "./mn/notGraphemes": "./mn/notGraphemes.ts", "./mn/notLength": "./mn/notLength.ts", "./mn/notSize": "./mn/notSize.ts", "./mn/notValue": "./mn/notValue.ts", "./mn/notValues": "./mn/notValues.ts", "./mn/notWords": "./mn/notWords.ts", "./mn/octal": "./mn/octal.ts", "./mn/parseBoolean": "./mn/parseBoolean.ts", "./mn/parseJson": "./mn/parseJson.ts", "./mn/partialCheck": "./mn/partialCheck.ts", "./mn/rawCheck": "./mn/rawCheck.ts", "./mn/rawTransform": "./mn/rawTransform.ts", "./mn/regex": "./mn/regex.ts", "./mn/rfcEmail": "./mn/rfcEmail.ts", "./mn/safeInteger": "./mn/safeInteger.ts", "./mn/size": "./mn/size.ts", "./mn/slug": "./mn/slug.ts", "./mn/someItem": "./mn/someItem.ts", "./mn/startsWith": "./mn/startsWith.ts", "./mn/stringifyJson": "./mn/stringifyJson.ts", "./mn/toBigint": "./mn/toBigint.ts", "./mn/toDate": "./mn/toDate.ts", "./mn/toNumber": "./mn/toNumber.ts", "./mn/toString": "./mn/toString.ts", "./mn/ulid": "./mn/ulid.ts", "./mn/url": "./mn/url.ts", "./mn/uuid": "./mn/uuid.ts", "./mn/value": "./mn/value.ts", "./mn/values": "./mn/values.ts", "./mn/words": "./mn/words.ts", "./nb": "./nb/index.ts", "./nb/schema": "./nb/schema.ts", "./nb/base64": "./nb/base64.ts", "./nb/bic": "./nb/bic.ts", "./nb/bytes": "./nb/bytes.ts", "./nb/check": "./nb/check.ts", "./nb/checkAsync": "./nb/checkAsync.ts", "./nb/checkItems": "./nb/checkItems.ts", "./nb/checkItemsAsync": "./nb/checkItemsAsync.ts", "./nb/creditCard": "./nb/creditCard.ts", "./nb/cuid2": "./nb/cuid2.ts", "./nb/decimal": "./nb/decimal.ts", "./nb/digits": "./nb/digits.ts", "./nb/domain": "./nb/domain.ts", "./nb/email": "./nb/email.ts", "./nb/emoji": "./nb/emoji.ts", "./nb/empty": "./nb/empty.ts", "./nb/endsWith": "./nb/endsWith.ts", "./nb/entries": "./nb/entries.ts", "./nb/everyItem": "./nb/everyItem.ts", "./nb/excludes": "./nb/excludes.ts", "./nb/finite": "./nb/finite.ts", "./nb/graphemes": "./nb/graphemes.ts", "./nb/gtValue": "./nb/gtValue.ts", "./nb/guard": "./nb/guard.ts", "./nb/hash": "./nb/hash.ts", "./nb/hexadecimal": "./nb/hexadecimal.ts", "./nb/hexColor": "./nb/hexColor.ts", "./nb/imei": "./nb/imei.ts", "./nb/includes": "./nb/includes.ts", "./nb/integer": "./nb/integer.ts", "./nb/ip": "./nb/ip.ts", "./nb/ipv4": "./nb/ipv4.ts", "./nb/ipv6": "./nb/ipv6.ts", "./nb/isbn": "./nb/isbn.ts", "./nb/isoDate": "./nb/isoDate.ts", "./nb/isoDateTime": "./nb/isoDateTime.ts", "./nb/isoTime": "./nb/isoTime.ts", "./nb/isoTimeSecond": "./nb/isoTimeSecond.ts", "./nb/isoTimestamp": "./nb/isoTimestamp.ts", "./nb/isoWeek": "./nb/isoWeek.ts", "./nb/isrc": "./nb/isrc.ts", "./nb/jwsCompact": "./nb/jwsCompact.ts", "./nb/length": "./nb/length.ts", "./nb/ltValue": "./nb/ltValue.ts", "./nb/mac": "./nb/mac.ts", "./nb/mac48": "./nb/mac48.ts", "./nb/mac64": "./nb/mac64.ts", "./nb/maxBytes": "./nb/maxBytes.ts", "./nb/maxEntries": "./nb/maxEntries.ts", "./nb/maxGraphemes": "./nb/maxGraphemes.ts", "./nb/maxLength": "./nb/maxLength.ts", "./nb/maxSize": "./nb/maxSize.ts", "./nb/maxValue": "./nb/maxValue.ts", "./nb/maxWords": "./nb/maxWords.ts", "./nb/mimeType": "./nb/mimeType.ts", "./nb/minBytes": "./nb/minBytes.ts", "./nb/minEntries": "./nb/minEntries.ts", "./nb/minGraphemes": "./nb/minGraphemes.ts", "./nb/minLength": "./nb/minLength.ts", "./nb/minSize": "./nb/minSize.ts", "./nb/minValue": "./nb/minValue.ts", "./nb/minWords": "./nb/minWords.ts", "./nb/multipleOf": "./nb/multipleOf.ts", "./nb/nanoid": "./nb/nanoid.ts", "./nb/nonEmpty": "./nb/nonEmpty.ts", "./nb/notBytes": "./nb/notBytes.ts", "./nb/notEntries": "./nb/notEntries.ts", "./nb/notGraphemes": "./nb/notGraphemes.ts", "./nb/notLength": "./nb/notLength.ts", "./nb/notSize": "./nb/notSize.ts", "./nb/notValue": "./nb/notValue.ts", "./nb/notValues": "./nb/notValues.ts", "./nb/notWords": "./nb/notWords.ts", "./nb/octal": "./nb/octal.ts", "./nb/parseBoolean": "./nb/parseBoolean.ts", "./nb/parseJson": "./nb/parseJson.ts", "./nb/partialCheck": "./nb/partialCheck.ts", "./nb/rawCheck": "./nb/rawCheck.ts", "./nb/rawTransform": "./nb/rawTransform.ts", "./nb/regex": "./nb/regex.ts", "./nb/rfcEmail": "./nb/rfcEmail.ts", "./nb/safeInteger": "./nb/safeInteger.ts", "./nb/size": "./nb/size.ts", "./nb/slug": "./nb/slug.ts", "./nb/someItem": "./nb/someItem.ts", "./nb/startsWith": "./nb/startsWith.ts", "./nb/stringifyJson": "./nb/stringifyJson.ts", "./nb/toBigint": "./nb/toBigint.ts", "./nb/toDate": "./nb/toDate.ts", "./nb/toNumber": "./nb/toNumber.ts", "./nb/toString": "./nb/toString.ts", "./nb/ulid": "./nb/ulid.ts", "./nb/url": "./nb/url.ts", "./nb/uuid": "./nb/uuid.ts", "./nb/value": "./nb/value.ts", "./nb/values": "./nb/values.ts", "./nb/words": "./nb/words.ts", "./nl": "./nl/index.ts", "./nl/schema": "./nl/schema.ts", "./nl/base64": "./nl/base64.ts", "./nl/bic": "./nl/bic.ts", "./nl/bytes": "./nl/bytes.ts", "./nl/check": "./nl/check.ts", "./nl/checkAsync": "./nl/checkAsync.ts", "./nl/checkItems": "./nl/checkItems.ts", "./nl/checkItemsAsync": "./nl/checkItemsAsync.ts", "./nl/creditCard": "./nl/creditCard.ts", "./nl/cuid2": "./nl/cuid2.ts", "./nl/decimal": "./nl/decimal.ts", "./nl/digits": "./nl/digits.ts", "./nl/domain": "./nl/domain.ts", "./nl/email": "./nl/email.ts", "./nl/emoji": "./nl/emoji.ts", "./nl/empty": "./nl/empty.ts", "./nl/endsWith": "./nl/endsWith.ts", "./nl/entries": "./nl/entries.ts", "./nl/everyItem": "./nl/everyItem.ts", "./nl/excludes": "./nl/excludes.ts", "./nl/finite": "./nl/finite.ts", "./nl/graphemes": "./nl/graphemes.ts", "./nl/gtValue": "./nl/gtValue.ts", "./nl/guard": "./nl/guard.ts", "./nl/hash": "./nl/hash.ts", "./nl/hexadecimal": "./nl/hexadecimal.ts", "./nl/hexColor": "./nl/hexColor.ts", "./nl/imei": "./nl/imei.ts", "./nl/includes": "./nl/includes.ts", "./nl/integer": "./nl/integer.ts", "./nl/ip": "./nl/ip.ts", "./nl/ipv4": "./nl/ipv4.ts", "./nl/ipv6": "./nl/ipv6.ts", "./nl/isbn": "./nl/isbn.ts", "./nl/isoDate": "./nl/isoDate.ts", "./nl/isoDateTime": "./nl/isoDateTime.ts", "./nl/isoTime": "./nl/isoTime.ts", "./nl/isoTimeSecond": "./nl/isoTimeSecond.ts", "./nl/isoTimestamp": "./nl/isoTimestamp.ts", "./nl/isoWeek": "./nl/isoWeek.ts", "./nl/isrc": "./nl/isrc.ts", "./nl/jwsCompact": "./nl/jwsCompact.ts", "./nl/length": "./nl/length.ts", "./nl/ltValue": "./nl/ltValue.ts", "./nl/mac": "./nl/mac.ts", "./nl/mac48": "./nl/mac48.ts", "./nl/mac64": "./nl/mac64.ts", "./nl/maxBytes": "./nl/maxBytes.ts", "./nl/maxEntries": "./nl/maxEntries.ts", "./nl/maxGraphemes": "./nl/maxGraphemes.ts", "./nl/maxLength": "./nl/maxLength.ts", "./nl/maxSize": "./nl/maxSize.ts", "./nl/maxValue": "./nl/maxValue.ts", "./nl/maxWords": "./nl/maxWords.ts", "./nl/mimeType": "./nl/mimeType.ts", "./nl/minBytes": "./nl/minBytes.ts", "./nl/minEntries": "./nl/minEntries.ts", "./nl/minGraphemes": "./nl/minGraphemes.ts", "./nl/minLength": "./nl/minLength.ts", "./nl/minSize": "./nl/minSize.ts", "./nl/minValue": "./nl/minValue.ts", "./nl/minWords": "./nl/minWords.ts", "./nl/multipleOf": "./nl/multipleOf.ts", "./nl/nanoid": "./nl/nanoid.ts", "./nl/nonEmpty": "./nl/nonEmpty.ts", "./nl/notBytes": "./nl/notBytes.ts", "./nl/notEntries": "./nl/notEntries.ts", "./nl/notGraphemes": "./nl/notGraphemes.ts", "./nl/notLength": "./nl/notLength.ts", "./nl/notSize": "./nl/notSize.ts", "./nl/notValue": "./nl/notValue.ts", "./nl/notValues": "./nl/notValues.ts", "./nl/notWords": "./nl/notWords.ts", "./nl/octal": "./nl/octal.ts", "./nl/parseBoolean": "./nl/parseBoolean.ts", "./nl/parseJson": "./nl/parseJson.ts", "./nl/partialCheck": "./nl/partialCheck.ts", "./nl/rawCheck": "./nl/rawCheck.ts", "./nl/rawTransform": "./nl/rawTransform.ts", "./nl/regex": "./nl/regex.ts", "./nl/rfcEmail": "./nl/rfcEmail.ts", "./nl/safeInteger": "./nl/safeInteger.ts", "./nl/size": "./nl/size.ts", "./nl/slug": "./nl/slug.ts", "./nl/someItem": "./nl/someItem.ts", "./nl/startsWith": "./nl/startsWith.ts", "./nl/stringifyJson": "./nl/stringifyJson.ts", "./nl/toBigint": "./nl/toBigint.ts", "./nl/toDate": "./nl/toDate.ts", "./nl/toNumber": "./nl/toNumber.ts", "./nl/toString": "./nl/toString.ts", "./nl/ulid": "./nl/ulid.ts", "./nl/url": "./nl/url.ts", "./nl/uuid": "./nl/uuid.ts", "./nl/value": "./nl/value.ts", "./nl/values": "./nl/values.ts", "./nl/words": "./nl/words.ts", "./pl": "./pl/index.ts", "./pl/schema": "./pl/schema.ts", "./pl/base64": "./pl/base64.ts", "./pl/bic": "./pl/bic.ts", "./pl/bytes": "./pl/bytes.ts", "./pl/check": "./pl/check.ts", "./pl/checkAsync": "./pl/checkAsync.ts", "./pl/checkItems": "./pl/checkItems.ts", "./pl/checkItemsAsync": "./pl/checkItemsAsync.ts", "./pl/creditCard": "./pl/creditCard.ts", "./pl/cuid2": "./pl/cuid2.ts", "./pl/decimal": "./pl/decimal.ts", "./pl/digits": "./pl/digits.ts", "./pl/domain": "./pl/domain.ts", "./pl/email": "./pl/email.ts", "./pl/emoji": "./pl/emoji.ts", "./pl/empty": "./pl/empty.ts", "./pl/endsWith": "./pl/endsWith.ts", "./pl/entries": "./pl/entries.ts", "./pl/everyItem": "./pl/everyItem.ts", "./pl/excludes": "./pl/excludes.ts", "./pl/finite": "./pl/finite.ts", "./pl/graphemes": "./pl/graphemes.ts", "./pl/gtValue": "./pl/gtValue.ts", "./pl/guard": "./pl/guard.ts", "./pl/hash": "./pl/hash.ts", "./pl/hexadecimal": "./pl/hexadecimal.ts", "./pl/hexColor": "./pl/hexColor.ts", "./pl/imei": "./pl/imei.ts", "./pl/includes": "./pl/includes.ts", "./pl/integer": "./pl/integer.ts", "./pl/ip": "./pl/ip.ts", "./pl/ipv4": "./pl/ipv4.ts", "./pl/ipv6": "./pl/ipv6.ts", "./pl/isbn": "./pl/isbn.ts", "./pl/isoDate": "./pl/isoDate.ts", "./pl/isoDateTime": "./pl/isoDateTime.ts", "./pl/isoTime": "./pl/isoTime.ts", "./pl/isoTimeSecond": "./pl/isoTimeSecond.ts", "./pl/isoTimestamp": "./pl/isoTimestamp.ts", "./pl/isoWeek": "./pl/isoWeek.ts", "./pl/isrc": "./pl/isrc.ts", "./pl/jwsCompact": "./pl/jwsCompact.ts", "./pl/length": "./pl/length.ts", "./pl/ltValue": "./pl/ltValue.ts", "./pl/mac": "./pl/mac.ts", "./pl/mac48": "./pl/mac48.ts", "./pl/mac64": "./pl/mac64.ts", "./pl/maxBytes": "./pl/maxBytes.ts", "./pl/maxEntries": "./pl/maxEntries.ts", "./pl/maxGraphemes": "./pl/maxGraphemes.ts", "./pl/maxLength": "./pl/maxLength.ts", "./pl/maxSize": "./pl/maxSize.ts", "./pl/maxValue": "./pl/maxValue.ts", "./pl/maxWords": "./pl/maxWords.ts", "./pl/mimeType": "./pl/mimeType.ts", "./pl/minBytes": "./pl/minBytes.ts", "./pl/minEntries": "./pl/minEntries.ts", "./pl/minGraphemes": "./pl/minGraphemes.ts", "./pl/minLength": "./pl/minLength.ts", "./pl/minSize": "./pl/minSize.ts", "./pl/minValue": "./pl/minValue.ts", "./pl/minWords": "./pl/minWords.ts", "./pl/multipleOf": "./pl/multipleOf.ts", "./pl/nanoid": "./pl/nanoid.ts", "./pl/nonEmpty": "./pl/nonEmpty.ts", "./pl/notBytes": "./pl/notBytes.ts", "./pl/notEntries": "./pl/notEntries.ts", "./pl/notGraphemes": "./pl/notGraphemes.ts", "./pl/notLength": "./pl/notLength.ts", "./pl/notSize": "./pl/notSize.ts", "./pl/notValue": "./pl/notValue.ts", "./pl/notValues": "./pl/notValues.ts", "./pl/notWords": "./pl/notWords.ts", "./pl/octal": "./pl/octal.ts", "./pl/parseBoolean": "./pl/parseBoolean.ts", "./pl/parseJson": "./pl/parseJson.ts", "./pl/partialCheck": "./pl/partialCheck.ts", "./pl/rawCheck": "./pl/rawCheck.ts", "./pl/rawTransform": "./pl/rawTransform.ts", "./pl/regex": "./pl/regex.ts", "./pl/rfcEmail": "./pl/rfcEmail.ts", "./pl/safeInteger": "./pl/safeInteger.ts", "./pl/size": "./pl/size.ts", "./pl/slug": "./pl/slug.ts", "./pl/someItem": "./pl/someItem.ts", "./pl/startsWith": "./pl/startsWith.ts", "./pl/stringifyJson": "./pl/stringifyJson.ts", "./pl/toBigint": "./pl/toBigint.ts", "./pl/toDate": "./pl/toDate.ts", "./pl/toNumber": "./pl/toNumber.ts", "./pl/toString": "./pl/toString.ts", "./pl/ulid": "./pl/ulid.ts", "./pl/url": "./pl/url.ts", "./pl/uuid": "./pl/uuid.ts", "./pl/value": "./pl/value.ts", "./pl/values": "./pl/values.ts", "./pl/words": "./pl/words.ts", "./pt": "./pt/index.ts", "./pt/schema": "./pt/schema.ts", "./pt/base64": "./pt/base64.ts", "./pt/bic": "./pt/bic.ts", "./pt/bytes": "./pt/bytes.ts", "./pt/check": "./pt/check.ts", "./pt/checkAsync": "./pt/checkAsync.ts", "./pt/checkItems": "./pt/checkItems.ts", "./pt/checkItemsAsync": "./pt/checkItemsAsync.ts", "./pt/creditCard": "./pt/creditCard.ts", "./pt/cuid2": "./pt/cuid2.ts", "./pt/decimal": "./pt/decimal.ts", "./pt/digits": "./pt/digits.ts", "./pt/domain": "./pt/domain.ts", "./pt/email": "./pt/email.ts", "./pt/emoji": "./pt/emoji.ts", "./pt/empty": "./pt/empty.ts", "./pt/endsWith": "./pt/endsWith.ts", "./pt/entries": "./pt/entries.ts", "./pt/everyItem": "./pt/everyItem.ts", "./pt/excludes": "./pt/excludes.ts", "./pt/finite": "./pt/finite.ts", "./pt/graphemes": "./pt/graphemes.ts", "./pt/gtValue": "./pt/gtValue.ts", "./pt/guard": "./pt/guard.ts", "./pt/hash": "./pt/hash.ts", "./pt/hexadecimal": "./pt/hexadecimal.ts", "./pt/hexColor": "./pt/hexColor.ts", "./pt/imei": "./pt/imei.ts", "./pt/includes": "./pt/includes.ts", "./pt/integer": "./pt/integer.ts", "./pt/ip": "./pt/ip.ts", "./pt/ipv4": "./pt/ipv4.ts", "./pt/ipv6": "./pt/ipv6.ts", "./pt/isbn": "./pt/isbn.ts", "./pt/isoDate": "./pt/isoDate.ts", "./pt/isoDateTime": "./pt/isoDateTime.ts", "./pt/isoTime": "./pt/isoTime.ts", "./pt/isoTimeSecond": "./pt/isoTimeSecond.ts", "./pt/isoTimestamp": "./pt/isoTimestamp.ts", "./pt/isoWeek": "./pt/isoWeek.ts", "./pt/isrc": "./pt/isrc.ts", "./pt/jwsCompact": "./pt/jwsCompact.ts", "./pt/length": "./pt/length.ts", "./pt/ltValue": "./pt/ltValue.ts", "./pt/mac": "./pt/mac.ts", "./pt/mac48": "./pt/mac48.ts", "./pt/mac64": "./pt/mac64.ts", "./pt/maxBytes": "./pt/maxBytes.ts", "./pt/maxEntries": "./pt/maxEntries.ts", "./pt/maxGraphemes": "./pt/maxGraphemes.ts", "./pt/maxLength": "./pt/maxLength.ts", "./pt/maxSize": "./pt/maxSize.ts", "./pt/maxValue": "./pt/maxValue.ts", "./pt/maxWords": "./pt/maxWords.ts", "./pt/mimeType": "./pt/mimeType.ts", "./pt/minBytes": "./pt/minBytes.ts", "./pt/minEntries": "./pt/minEntries.ts", "./pt/minGraphemes": "./pt/minGraphemes.ts", "./pt/minLength": "./pt/minLength.ts", "./pt/minSize": "./pt/minSize.ts", "./pt/minValue": "./pt/minValue.ts", "./pt/minWords": "./pt/minWords.ts", "./pt/multipleOf": "./pt/multipleOf.ts", "./pt/nanoid": "./pt/nanoid.ts", "./pt/nonEmpty": "./pt/nonEmpty.ts", "./pt/notBytes": "./pt/notBytes.ts", "./pt/notEntries": "./pt/notEntries.ts", "./pt/notGraphemes": "./pt/notGraphemes.ts", "./pt/notLength": "./pt/notLength.ts", "./pt/notSize": "./pt/notSize.ts", "./pt/notValue": "./pt/notValue.ts", "./pt/notValues": "./pt/notValues.ts", "./pt/notWords": "./pt/notWords.ts", "./pt/octal": "./pt/octal.ts", "./pt/parseBoolean": "./pt/parseBoolean.ts", "./pt/parseJson": "./pt/parseJson.ts", "./pt/partialCheck": "./pt/partialCheck.ts", "./pt/rawCheck": "./pt/rawCheck.ts", "./pt/rawTransform": "./pt/rawTransform.ts", "./pt/regex": "./pt/regex.ts", "./pt/rfcEmail": "./pt/rfcEmail.ts", "./pt/safeInteger": "./pt/safeInteger.ts", "./pt/size": "./pt/size.ts", "./pt/slug": "./pt/slug.ts", "./pt/someItem": "./pt/someItem.ts", "./pt/startsWith": "./pt/startsWith.ts", "./pt/stringifyJson": "./pt/stringifyJson.ts", "./pt/toBigint": "./pt/toBigint.ts", "./pt/toDate": "./pt/toDate.ts", "./pt/toNumber": "./pt/toNumber.ts", "./pt/toString": "./pt/toString.ts", "./pt/ulid": "./pt/ulid.ts", "./pt/url": "./pt/url.ts", "./pt/uuid": "./pt/uuid.ts", "./pt/value": "./pt/value.ts", "./pt/values": "./pt/values.ts", "./pt/words": "./pt/words.ts", "./ro": "./ro/index.ts", "./ro/schema": "./ro/schema.ts", "./ro/base64": "./ro/base64.ts", "./ro/bic": "./ro/bic.ts", "./ro/bytes": "./ro/bytes.ts", "./ro/check": "./ro/check.ts", "./ro/checkAsync": "./ro/checkAsync.ts", "./ro/checkItems": "./ro/checkItems.ts", "./ro/checkItemsAsync": "./ro/checkItemsAsync.ts", "./ro/creditCard": "./ro/creditCard.ts", "./ro/cuid2": "./ro/cuid2.ts", "./ro/decimal": "./ro/decimal.ts", "./ro/digits": "./ro/digits.ts", "./ro/domain": "./ro/domain.ts", "./ro/email": "./ro/email.ts", "./ro/emoji": "./ro/emoji.ts", "./ro/empty": "./ro/empty.ts", "./ro/endsWith": "./ro/endsWith.ts", "./ro/entries": "./ro/entries.ts", "./ro/everyItem": "./ro/everyItem.ts", "./ro/excludes": "./ro/excludes.ts", "./ro/finite": "./ro/finite.ts", "./ro/graphemes": "./ro/graphemes.ts", "./ro/gtValue": "./ro/gtValue.ts", "./ro/guard": "./ro/guard.ts", "./ro/hash": "./ro/hash.ts", "./ro/hexadecimal": "./ro/hexadecimal.ts", "./ro/hexColor": "./ro/hexColor.ts", "./ro/imei": "./ro/imei.ts", "./ro/includes": "./ro/includes.ts", "./ro/integer": "./ro/integer.ts", "./ro/ip": "./ro/ip.ts", "./ro/ipv4": "./ro/ipv4.ts", "./ro/ipv6": "./ro/ipv6.ts", "./ro/isbn": "./ro/isbn.ts", "./ro/isoDate": "./ro/isoDate.ts", "./ro/isoDateTime": "./ro/isoDateTime.ts", "./ro/isoTime": "./ro/isoTime.ts", "./ro/isoTimeSecond": "./ro/isoTimeSecond.ts", "./ro/isoTimestamp": "./ro/isoTimestamp.ts", "./ro/isoWeek": "./ro/isoWeek.ts", "./ro/isrc": "./ro/isrc.ts", "./ro/jwsCompact": "./ro/jwsCompact.ts", "./ro/length": "./ro/length.ts", "./ro/ltValue": "./ro/ltValue.ts", "./ro/mac": "./ro/mac.ts", "./ro/mac48": "./ro/mac48.ts", "./ro/mac64": "./ro/mac64.ts", "./ro/maxBytes": "./ro/maxBytes.ts", "./ro/maxEntries": "./ro/maxEntries.ts", "./ro/maxGraphemes": "./ro/maxGraphemes.ts", "./ro/maxLength": "./ro/maxLength.ts", "./ro/maxSize": "./ro/maxSize.ts", "./ro/maxValue": "./ro/maxValue.ts", "./ro/maxWords": "./ro/maxWords.ts", "./ro/mimeType": "./ro/mimeType.ts", "./ro/minBytes": "./ro/minBytes.ts", "./ro/minEntries": "./ro/minEntries.ts", "./ro/minGraphemes": "./ro/minGraphemes.ts", "./ro/minLength": "./ro/minLength.ts", "./ro/minSize": "./ro/minSize.ts", "./ro/minValue": "./ro/minValue.ts", "./ro/minWords": "./ro/minWords.ts", "./ro/multipleOf": "./ro/multipleOf.ts", "./ro/nanoid": "./ro/nanoid.ts", "./ro/nonEmpty": "./ro/nonEmpty.ts", "./ro/notBytes": "./ro/notBytes.ts", "./ro/notEntries": "./ro/notEntries.ts", "./ro/notGraphemes": "./ro/notGraphemes.ts", "./ro/notLength": "./ro/notLength.ts", "./ro/notSize": "./ro/notSize.ts", "./ro/notValue": "./ro/notValue.ts", "./ro/notValues": "./ro/notValues.ts", "./ro/notWords": "./ro/notWords.ts", "./ro/octal": "./ro/octal.ts", "./ro/parseBoolean": "./ro/parseBoolean.ts", "./ro/parseJson": "./ro/parseJson.ts", "./ro/partialCheck": "./ro/partialCheck.ts", "./ro/rawCheck": "./ro/rawCheck.ts", "./ro/rawTransform": "./ro/rawTransform.ts", "./ro/regex": "./ro/regex.ts", "./ro/rfcEmail": "./ro/rfcEmail.ts", "./ro/safeInteger": "./ro/safeInteger.ts", "./ro/size": "./ro/size.ts", "./ro/slug": "./ro/slug.ts", "./ro/someItem": "./ro/someItem.ts", "./ro/startsWith": "./ro/startsWith.ts", "./ro/stringifyJson": "./ro/stringifyJson.ts", "./ro/toBigint": "./ro/toBigint.ts", "./ro/toDate": "./ro/toDate.ts", "./ro/toNumber": "./ro/toNumber.ts", "./ro/toString": "./ro/toString.ts", "./ro/ulid": "./ro/ulid.ts", "./ro/url": "./ro/url.ts", "./ro/uuid": "./ro/uuid.ts", "./ro/value": "./ro/value.ts", "./ro/values": "./ro/values.ts", "./ro/words": "./ro/words.ts", "./ru": "./ru/index.ts", "./ru/schema": "./ru/schema.ts", "./ru/base64": "./ru/base64.ts", "./ru/bic": "./ru/bic.ts", "./ru/bytes": "./ru/bytes.ts", "./ru/check": "./ru/check.ts", "./ru/checkAsync": "./ru/checkAsync.ts", "./ru/checkItems": "./ru/checkItems.ts", "./ru/checkItemsAsync": "./ru/checkItemsAsync.ts", "./ru/creditCard": "./ru/creditCard.ts", "./ru/cuid2": "./ru/cuid2.ts", "./ru/decimal": "./ru/decimal.ts", "./ru/digits": "./ru/digits.ts", "./ru/domain": "./ru/domain.ts", "./ru/email": "./ru/email.ts", "./ru/emoji": "./ru/emoji.ts", "./ru/empty": "./ru/empty.ts", "./ru/endsWith": "./ru/endsWith.ts", "./ru/entries": "./ru/entries.ts", "./ru/everyItem": "./ru/everyItem.ts", "./ru/excludes": "./ru/excludes.ts", "./ru/finite": "./ru/finite.ts", "./ru/graphemes": "./ru/graphemes.ts", "./ru/gtValue": "./ru/gtValue.ts", "./ru/guard": "./ru/guard.ts", "./ru/hash": "./ru/hash.ts", "./ru/hexadecimal": "./ru/hexadecimal.ts", "./ru/hexColor": "./ru/hexColor.ts", "./ru/imei": "./ru/imei.ts", "./ru/includes": "./ru/includes.ts", "./ru/integer": "./ru/integer.ts", "./ru/ip": "./ru/ip.ts", "./ru/ipv4": "./ru/ipv4.ts", "./ru/ipv6": "./ru/ipv6.ts", "./ru/isbn": "./ru/isbn.ts", "./ru/isoDate": "./ru/isoDate.ts", "./ru/isoDateTime": "./ru/isoDateTime.ts", "./ru/isoTime": "./ru/isoTime.ts", "./ru/isoTimeSecond": "./ru/isoTimeSecond.ts", "./ru/isoTimestamp": "./ru/isoTimestamp.ts", "./ru/isoWeek": "./ru/isoWeek.ts", "./ru/isrc": "./ru/isrc.ts", "./ru/jwsCompact": "./ru/jwsCompact.ts", "./ru/length": "./ru/length.ts", "./ru/ltValue": "./ru/ltValue.ts", "./ru/mac": "./ru/mac.ts", "./ru/mac48": "./ru/mac48.ts", "./ru/mac64": "./ru/mac64.ts", "./ru/maxBytes": "./ru/maxBytes.ts", "./ru/maxEntries": "./ru/maxEntries.ts", "./ru/maxGraphemes": "./ru/maxGraphemes.ts", "./ru/maxLength": "./ru/maxLength.ts", "./ru/maxSize": "./ru/maxSize.ts", "./ru/maxValue": "./ru/maxValue.ts", "./ru/maxWords": "./ru/maxWords.ts", "./ru/mimeType": "./ru/mimeType.ts", "./ru/minBytes": "./ru/minBytes.ts", "./ru/minEntries": "./ru/minEntries.ts", "./ru/minGraphemes": "./ru/minGraphemes.ts", "./ru/minLength": "./ru/minLength.ts", "./ru/minSize": "./ru/minSize.ts", "./ru/minValue": "./ru/minValue.ts", "./ru/minWords": "./ru/minWords.ts", "./ru/multipleOf": "./ru/multipleOf.ts", "./ru/nanoid": "./ru/nanoid.ts", "./ru/nonEmpty": "./ru/nonEmpty.ts", "./ru/notBytes": "./ru/notBytes.ts", "./ru/notEntries": "./ru/notEntries.ts", "./ru/notGraphemes": "./ru/notGraphemes.ts", "./ru/notLength": "./ru/notLength.ts", "./ru/notSize": "./ru/notSize.ts", "./ru/notValue": "./ru/notValue.ts", "./ru/notValues": "./ru/notValues.ts", "./ru/notWords": "./ru/notWords.ts", "./ru/octal": "./ru/octal.ts", "./ru/parseBoolean": "./ru/parseBoolean.ts", "./ru/parseJson": "./ru/parseJson.ts", "./ru/partialCheck": "./ru/partialCheck.ts", "./ru/rawCheck": "./ru/rawCheck.ts", "./ru/rawTransform": "./ru/rawTransform.ts", "./ru/regex": "./ru/regex.ts", "./ru/rfcEmail": "./ru/rfcEmail.ts", "./ru/safeInteger": "./ru/safeInteger.ts", "./ru/size": "./ru/size.ts", "./ru/slug": "./ru/slug.ts", "./ru/someItem": "./ru/someItem.ts", "./ru/startsWith": "./ru/startsWith.ts", "./ru/stringifyJson": "./ru/stringifyJson.ts", "./ru/toBigint": "./ru/toBigint.ts", "./ru/toDate": "./ru/toDate.ts", "./ru/toNumber": "./ru/toNumber.ts", "./ru/toString": "./ru/toString.ts", "./ru/ulid": "./ru/ulid.ts", "./ru/url": "./ru/url.ts", "./ru/uuid": "./ru/uuid.ts", "./ru/value": "./ru/value.ts", "./ru/values": "./ru/values.ts", "./ru/words": "./ru/words.ts", "./sk": "./sk/index.ts", "./sk/schema": "./sk/schema.ts", "./sk/base64": "./sk/base64.ts", "./sk/bic": "./sk/bic.ts", "./sk/bytes": "./sk/bytes.ts", "./sk/check": "./sk/check.ts", "./sk/checkAsync": "./sk/checkAsync.ts", "./sk/checkItems": "./sk/checkItems.ts", "./sk/checkItemsAsync": "./sk/checkItemsAsync.ts", "./sk/creditCard": "./sk/creditCard.ts", "./sk/cuid2": "./sk/cuid2.ts", "./sk/decimal": "./sk/decimal.ts", "./sk/digits": "./sk/digits.ts", "./sk/domain": "./sk/domain.ts", "./sk/email": "./sk/email.ts", "./sk/emoji": "./sk/emoji.ts", "./sk/empty": "./sk/empty.ts", "./sk/endsWith": "./sk/endsWith.ts", "./sk/entries": "./sk/entries.ts", "./sk/everyItem": "./sk/everyItem.ts", "./sk/excludes": "./sk/excludes.ts", "./sk/finite": "./sk/finite.ts", "./sk/graphemes": "./sk/graphemes.ts", "./sk/gtValue": "./sk/gtValue.ts", "./sk/guard": "./sk/guard.ts", "./sk/hash": "./sk/hash.ts", "./sk/hexColor": "./sk/hexColor.ts", "./sk/hexadecimal": "./sk/hexadecimal.ts", "./sk/imei": "./sk/imei.ts", "./sk/includes": "./sk/includes.ts", "./sk/integer": "./sk/integer.ts", "./sk/ip": "./sk/ip.ts", "./sk/ipv4": "./sk/ipv4.ts", "./sk/ipv6": "./sk/ipv6.ts", "./sk/isbn": "./sk/isbn.ts", "./sk/isoDate": "./sk/isoDate.ts", "./sk/isoDateTime": "./sk/isoDateTime.ts", "./sk/isoTime": "./sk/isoTime.ts", "./sk/isoTimeSecond": "./sk/isoTimeSecond.ts", "./sk/isoTimestamp": "./sk/isoTimestamp.ts", "./sk/isoWeek": "./sk/isoWeek.ts", "./sk/isrc": "./sk/isrc.ts", "./sk/jwsCompact": "./sk/jwsCompact.ts", "./sk/length": "./sk/length.ts", "./sk/ltValue": "./sk/ltValue.ts", "./sk/mac": "./sk/mac.ts", "./sk/mac48": "./sk/mac48.ts", "./sk/mac64": "./sk/mac64.ts", "./sk/maxBytes": "./sk/maxBytes.ts", "./sk/maxEntries": "./sk/maxEntries.ts", "./sk/maxGraphemes": "./sk/maxGraphemes.ts", "./sk/maxLength": "./sk/maxLength.ts", "./sk/maxSize": "./sk/maxSize.ts", "./sk/maxValue": "./sk/maxValue.ts", "./sk/maxWords": "./sk/maxWords.ts", "./sk/mimeType": "./sk/mimeType.ts", "./sk/minBytes": "./sk/minBytes.ts", "./sk/minEntries": "./sk/minEntries.ts", "./sk/minGraphemes": "./sk/minGraphemes.ts", "./sk/minLength": "./sk/minLength.ts", "./sk/minSize": "./sk/minSize.ts", "./sk/minValue": "./sk/minValue.ts", "./sk/minWords": "./sk/minWords.ts", "./sk/multipleOf": "./sk/multipleOf.ts", "./sk/nanoid": "./sk/nanoid.ts", "./sk/nonEmpty": "./sk/nonEmpty.ts", "./sk/notBytes": "./sk/notBytes.ts", "./sk/notEntries": "./sk/notEntries.ts", "./sk/notGraphemes": "./sk/notGraphemes.ts", "./sk/notLength": "./sk/notLength.ts", "./sk/notSize": "./sk/notSize.ts", "./sk/notValue": "./sk/notValue.ts", "./sk/notValues": "./sk/notValues.ts", "./sk/notWords": "./sk/notWords.ts", "./sk/octal": "./sk/octal.ts", "./sk/parseBoolean": "./sk/parseBoolean.ts", "./sk/parseJson": "./sk/parseJson.ts", "./sk/partialCheck": "./sk/partialCheck.ts", "./sk/rawCheck": "./sk/rawCheck.ts", "./sk/rawTransform": "./sk/rawTransform.ts", "./sk/regex": "./sk/regex.ts", "./sk/rfcEmail": "./sk/rfcEmail.ts", "./sk/safeInteger": "./sk/safeInteger.ts", "./sk/size": "./sk/size.ts", "./sk/slug": "./sk/slug.ts", "./sk/someItem": "./sk/someItem.ts", "./sk/startsWith": "./sk/startsWith.ts", "./sk/stringifyJson": "./sk/stringifyJson.ts", "./sk/toBigint": "./sk/toBigint.ts", "./sk/toDate": "./sk/toDate.ts", "./sk/toNumber": "./sk/toNumber.ts", "./sk/toString": "./sk/toString.ts", "./sk/ulid": "./sk/ulid.ts", "./sk/url": "./sk/url.ts", "./sk/uuid": "./sk/uuid.ts", "./sk/value": "./sk/value.ts", "./sk/values": "./sk/values.ts", "./sk/words": "./sk/words.ts", "./sl": "./sl/index.ts", "./sl/schema": "./sl/schema.ts", "./sl/base64": "./sl/base64.ts", "./sl/bic": "./sl/bic.ts", "./sl/bytes": "./sl/bytes.ts", "./sl/check": "./sl/check.ts", "./sl/checkAsync": "./sl/checkAsync.ts", "./sl/checkItems": "./sl/checkItems.ts", "./sl/checkItemsAsync": "./sl/checkItemsAsync.ts", "./sl/creditCard": "./sl/creditCard.ts", "./sl/cuid2": "./sl/cuid2.ts", "./sl/decimal": "./sl/decimal.ts", "./sl/digits": "./sl/digits.ts", "./sl/domain": "./sl/domain.ts", "./sl/email": "./sl/email.ts", "./sl/emoji": "./sl/emoji.ts", "./sl/empty": "./sl/empty.ts", "./sl/endsWith": "./sl/endsWith.ts", "./sl/entries": "./sl/entries.ts", "./sl/everyItem": "./sl/everyItem.ts", "./sl/excludes": "./sl/excludes.ts", "./sl/finite": "./sl/finite.ts", "./sl/graphemes": "./sl/graphemes.ts", "./sl/gtValue": "./sl/gtValue.ts", "./sl/guard": "./sl/guard.ts", "./sl/hash": "./sl/hash.ts", "./sl/hexadecimal": "./sl/hexadecimal.ts", "./sl/hexColor": "./sl/hexColor.ts", "./sl/imei": "./sl/imei.ts", "./sl/includes": "./sl/includes.ts", "./sl/integer": "./sl/integer.ts", "./sl/ip": "./sl/ip.ts", "./sl/ipv4": "./sl/ipv4.ts", "./sl/ipv6": "./sl/ipv6.ts", "./sl/isbn": "./sl/isbn.ts", "./sl/isoDate": "./sl/isoDate.ts", "./sl/isoDateTime": "./sl/isoDateTime.ts", "./sl/isoTime": "./sl/isoTime.ts", "./sl/isoTimeSecond": "./sl/isoTimeSecond.ts", "./sl/isoTimestamp": "./sl/isoTimestamp.ts", "./sl/isoWeek": "./sl/isoWeek.ts", "./sl/isrc": "./sl/isrc.ts", "./sl/jwsCompact": "./sl/jwsCompact.ts", "./sl/length": "./sl/length.ts", "./sl/ltValue": "./sl/ltValue.ts", "./sl/mac": "./sl/mac.ts", "./sl/mac48": "./sl/mac48.ts", "./sl/mac64": "./sl/mac64.ts", "./sl/maxBytes": "./sl/maxBytes.ts", "./sl/maxEntries": "./sl/maxEntries.ts", "./sl/maxGraphemes": "./sl/maxGraphemes.ts", "./sl/maxLength": "./sl/maxLength.ts", "./sl/maxSize": "./sl/maxSize.ts", "./sl/maxValue": "./sl/maxValue.ts", "./sl/maxWords": "./sl/maxWords.ts", "./sl/mimeType": "./sl/mimeType.ts", "./sl/minBytes": "./sl/minBytes.ts", "./sl/minEntries": "./sl/minEntries.ts", "./sl/minGraphemes": "./sl/minGraphemes.ts", "./sl/minLength": "./sl/minLength.ts", "./sl/minSize": "./sl/minSize.ts", "./sl/minValue": "./sl/minValue.ts", "./sl/minWords": "./sl/minWords.ts", "./sl/multipleOf": "./sl/multipleOf.ts", "./sl/nanoid": "./sl/nanoid.ts", "./sl/nonEmpty": "./sl/nonEmpty.ts", "./sl/notBytes": "./sl/notBytes.ts", "./sl/notEntries": "./sl/notEntries.ts", "./sl/notGraphemes": "./sl/notGraphemes.ts", "./sl/notLength": "./sl/notLength.ts", "./sl/notSize": "./sl/notSize.ts", "./sl/notValue": "./sl/notValue.ts", "./sl/notValues": "./sl/notValues.ts", "./sl/notWords": "./sl/notWords.ts", "./sl/octal": "./sl/octal.ts", "./sl/parseBoolean": "./sl/parseBoolean.ts", "./sl/parseJson": "./sl/parseJson.ts", "./sl/partialCheck": "./sl/partialCheck.ts", "./sl/rawCheck": "./sl/rawCheck.ts", "./sl/rawTransform": "./sl/rawTransform.ts", "./sl/regex": "./sl/regex.ts", "./sl/rfcEmail": "./sl/rfcEmail.ts", "./sl/safeInteger": "./sl/safeInteger.ts", "./sl/size": "./sl/size.ts", "./sl/slug": "./sl/slug.ts", "./sl/someItem": "./sl/someItem.ts", "./sl/startsWith": "./sl/startsWith.ts", "./sl/stringifyJson": "./sl/stringifyJson.ts", "./sl/toBigint": "./sl/toBigint.ts", "./sl/toDate": "./sl/toDate.ts", "./sl/toNumber": "./sl/toNumber.ts", "./sl/toString": "./sl/toString.ts", "./sl/ulid": "./sl/ulid.ts", "./sl/url": "./sl/url.ts", "./sl/uuid": "./sl/uuid.ts", "./sl/value": "./sl/value.ts", "./sl/values": "./sl/values.ts", "./sl/words": "./sl/words.ts", "./sv": "./sv/index.ts", "./sv/schema": "./sv/schema.ts", "./sv/base64": "./sv/base64.ts", "./sv/bic": "./sv/bic.ts", "./sv/bytes": "./sv/bytes.ts", "./sv/check": "./sv/check.ts", "./sv/checkAsync": "./sv/checkAsync.ts", "./sv/checkItems": "./sv/checkItems.ts", "./sv/checkItemsAsync": "./sv/checkItemsAsync.ts", "./sv/creditCard": "./sv/creditCard.ts", "./sv/cuid2": "./sv/cuid2.ts", "./sv/decimal": "./sv/decimal.ts", "./sv/digits": "./sv/digits.ts", "./sv/domain": "./sv/domain.ts", "./sv/email": "./sv/email.ts", "./sv/emoji": "./sv/emoji.ts", "./sv/empty": "./sv/empty.ts", "./sv/endsWith": "./sv/endsWith.ts", "./sv/entries": "./sv/entries.ts", "./sv/everyItem": "./sv/everyItem.ts", "./sv/excludes": "./sv/excludes.ts", "./sv/finite": "./sv/finite.ts", "./sv/graphemes": "./sv/graphemes.ts", "./sv/gtValue": "./sv/gtValue.ts", "./sv/guard": "./sv/guard.ts", "./sv/hash": "./sv/hash.ts", "./sv/hexadecimal": "./sv/hexadecimal.ts", "./sv/hexColor": "./sv/hexColor.ts", "./sv/imei": "./sv/imei.ts", "./sv/includes": "./sv/includes.ts", "./sv/integer": "./sv/integer.ts", "./sv/ip": "./sv/ip.ts", "./sv/ipv4": "./sv/ipv4.ts", "./sv/ipv6": "./sv/ipv6.ts", "./sv/isbn": "./sv/isbn.ts", "./sv/isoDate": "./sv/isoDate.ts", "./sv/isoDateTime": "./sv/isoDateTime.ts", "./sv/isoTime": "./sv/isoTime.ts", "./sv/isoTimeSecond": "./sv/isoTimeSecond.ts", "./sv/isoTimestamp": "./sv/isoTimestamp.ts", "./sv/isoWeek": "./sv/isoWeek.ts", "./sv/isrc": "./sv/isrc.ts", "./sv/jwsCompact": "./sv/jwsCompact.ts", "./sv/length": "./sv/length.ts", "./sv/ltValue": "./sv/ltValue.ts", "./sv/mac": "./sv/mac.ts", "./sv/mac48": "./sv/mac48.ts", "./sv/mac64": "./sv/mac64.ts", "./sv/maxBytes": "./sv/maxBytes.ts", "./sv/maxEntries": "./sv/maxEntries.ts", "./sv/maxGraphemes": "./sv/maxGraphemes.ts", "./sv/maxLength": "./sv/maxLength.ts", "./sv/maxSize": "./sv/maxSize.ts", "./sv/maxValue": "./sv/maxValue.ts", "./sv/maxWords": "./sv/maxWords.ts", "./sv/mimeType": "./sv/mimeType.ts", "./sv/minBytes": "./sv/minBytes.ts", "./sv/minEntries": "./sv/minEntries.ts", "./sv/minGraphemes": "./sv/minGraphemes.ts", "./sv/minLength": "./sv/minLength.ts", "./sv/minSize": "./sv/minSize.ts", "./sv/minValue": "./sv/minValue.ts", "./sv/minWords": "./sv/minWords.ts", "./sv/multipleOf": "./sv/multipleOf.ts", "./sv/nanoid": "./sv/nanoid.ts", "./sv/nonEmpty": "./sv/nonEmpty.ts", "./sv/notBytes": "./sv/notBytes.ts", "./sv/notEntries": "./sv/notEntries.ts", "./sv/notGraphemes": "./sv/notGraphemes.ts", "./sv/notLength": "./sv/notLength.ts", "./sv/notSize": "./sv/notSize.ts", "./sv/notValue": "./sv/notValue.ts", "./sv/notValues": "./sv/notValues.ts", "./sv/notWords": "./sv/notWords.ts", "./sv/octal": "./sv/octal.ts", "./sv/parseBoolean": "./sv/parseBoolean.ts", "./sv/parseJson": "./sv/parseJson.ts", "./sv/partialCheck": "./sv/partialCheck.ts", "./sv/rawCheck": "./sv/rawCheck.ts", "./sv/rawTransform": "./sv/rawTransform.ts", "./sv/regex": "./sv/regex.ts", "./sv/rfcEmail": "./sv/rfcEmail.ts", "./sv/safeInteger": "./sv/safeInteger.ts", "./sv/size": "./sv/size.ts", "./sv/slug": "./sv/slug.ts", "./sv/someItem": "./sv/someItem.ts", "./sv/startsWith": "./sv/startsWith.ts", "./sv/stringifyJson": "./sv/stringifyJson.ts", "./sv/toBigint": "./sv/toBigint.ts", "./sv/toDate": "./sv/toDate.ts", "./sv/toNumber": "./sv/toNumber.ts", "./sv/toString": "./sv/toString.ts", "./sv/ulid": "./sv/ulid.ts", "./sv/url": "./sv/url.ts", "./sv/uuid": "./sv/uuid.ts", "./sv/value": "./sv/value.ts", "./sv/values": "./sv/values.ts", "./sv/words": "./sv/words.ts", "./tr": "./tr/index.ts", "./tr/schema": "./tr/schema.ts", "./tr/base64": "./tr/base64.ts", "./tr/bic": "./tr/bic.ts", "./tr/bytes": "./tr/bytes.ts", "./tr/check": "./tr/check.ts", "./tr/checkAsync": "./tr/checkAsync.ts", "./tr/checkItems": "./tr/checkItems.ts", "./tr/checkItemsAsync": "./tr/checkItemsAsync.ts", "./tr/creditCard": "./tr/creditCard.ts", "./tr/cuid2": "./tr/cuid2.ts", "./tr/decimal": "./tr/decimal.ts", "./tr/digits": "./tr/digits.ts", "./tr/domain": "./tr/domain.ts", "./tr/email": "./tr/email.ts", "./tr/emoji": "./tr/emoji.ts", "./tr/empty": "./tr/empty.ts", "./tr/endsWith": "./tr/endsWith.ts", "./tr/entries": "./tr/entries.ts", "./tr/everyItem": "./tr/everyItem.ts", "./tr/excludes": "./tr/excludes.ts", "./tr/finite": "./tr/finite.ts", "./tr/graphemes": "./tr/graphemes.ts", "./tr/gtValue": "./tr/gtValue.ts", "./tr/guard": "./tr/guard.ts", "./tr/hash": "./tr/hash.ts", "./tr/hexadecimal": "./tr/hexadecimal.ts", "./tr/hexColor": "./tr/hexColor.ts", "./tr/imei": "./tr/imei.ts", "./tr/includes": "./tr/includes.ts", "./tr/integer": "./tr/integer.ts", "./tr/ip": "./tr/ip.ts", "./tr/ipv4": "./tr/ipv4.ts", "./tr/ipv6": "./tr/ipv6.ts", "./tr/isbn": "./tr/isbn.ts", "./tr/isoDate": "./tr/isoDate.ts", "./tr/isoDateTime": "./tr/isoDateTime.ts", "./tr/isoTime": "./tr/isoTime.ts", "./tr/isoTimeSecond": "./tr/isoTimeSecond.ts", "./tr/isoTimestamp": "./tr/isoTimestamp.ts", "./tr/isoWeek": "./tr/isoWeek.ts", "./tr/isrc": "./tr/isrc.ts", "./tr/jwsCompact": "./tr/jwsCompact.ts", "./tr/length": "./tr/length.ts", "./tr/ltValue": "./tr/ltValue.ts", "./tr/mac": "./tr/mac.ts", "./tr/mac48": "./tr/mac48.ts", "./tr/mac64": "./tr/mac64.ts", "./tr/maxBytes": "./tr/maxBytes.ts", "./tr/maxEntries": "./tr/maxEntries.ts", "./tr/maxGraphemes": "./tr/maxGraphemes.ts", "./tr/maxLength": "./tr/maxLength.ts", "./tr/maxSize": "./tr/maxSize.ts", "./tr/maxValue": "./tr/maxValue.ts", "./tr/maxWords": "./tr/maxWords.ts", "./tr/mimeType": "./tr/mimeType.ts", "./tr/minBytes": "./tr/minBytes.ts", "./tr/minEntries": "./tr/minEntries.ts", "./tr/minGraphemes": "./tr/minGraphemes.ts", "./tr/minLength": "./tr/minLength.ts", "./tr/minSize": "./tr/minSize.ts", "./tr/minValue": "./tr/minValue.ts", "./tr/minWords": "./tr/minWords.ts", "./tr/multipleOf": "./tr/multipleOf.ts", "./tr/nanoid": "./tr/nanoid.ts", "./tr/nonEmpty": "./tr/nonEmpty.ts", "./tr/notBytes": "./tr/notBytes.ts", "./tr/notEntries": "./tr/notEntries.ts", "./tr/notGraphemes": "./tr/notGraphemes.ts", "./tr/notLength": "./tr/notLength.ts", "./tr/notSize": "./tr/notSize.ts", "./tr/notValue": "./tr/notValue.ts", "./tr/notValues": "./tr/notValues.ts", "./tr/notWords": "./tr/notWords.ts", "./tr/octal": "./tr/octal.ts", "./tr/parseBoolean": "./tr/parseBoolean.ts", "./tr/parseJson": "./tr/parseJson.ts", "./tr/partialCheck": "./tr/partialCheck.ts", "./tr/rawCheck": "./tr/rawCheck.ts", "./tr/rawTransform": "./tr/rawTransform.ts", "./tr/regex": "./tr/regex.ts", "./tr/rfcEmail": "./tr/rfcEmail.ts", "./tr/safeInteger": "./tr/safeInteger.ts", "./tr/size": "./tr/size.ts", "./tr/slug": "./tr/slug.ts", "./tr/someItem": "./tr/someItem.ts", "./tr/startsWith": "./tr/startsWith.ts", "./tr/stringifyJson": "./tr/stringifyJson.ts", "./tr/toBigint": "./tr/toBigint.ts", "./tr/toDate": "./tr/toDate.ts", "./tr/toNumber": "./tr/toNumber.ts", "./tr/toString": "./tr/toString.ts", "./tr/ulid": "./tr/ulid.ts", "./tr/url": "./tr/url.ts", "./tr/uuid": "./tr/uuid.ts", "./tr/value": "./tr/value.ts", "./tr/values": "./tr/values.ts", "./tr/words": "./tr/words.ts", "./uk": "./uk/index.ts", "./uk/schema": "./uk/schema.ts", "./uk/base64": "./uk/base64.ts", "./uk/bic": "./uk/bic.ts", "./uk/bytes": "./uk/bytes.ts", "./uk/check": "./uk/check.ts", "./uk/checkAsync": "./uk/checkAsync.ts", "./uk/checkItems": "./uk/checkItems.ts", "./uk/checkItemsAsync": "./uk/checkItemsAsync.ts", "./uk/creditCard": "./uk/creditCard.ts", "./uk/cuid2": "./uk/cuid2.ts", "./uk/decimal": "./uk/decimal.ts", "./uk/digits": "./uk/digits.ts", "./uk/domain": "./uk/domain.ts", "./uk/email": "./uk/email.ts", "./uk/emoji": "./uk/emoji.ts", "./uk/empty": "./uk/empty.ts", "./uk/endsWith": "./uk/endsWith.ts", "./uk/entries": "./uk/entries.ts", "./uk/everyItem": "./uk/everyItem.ts", "./uk/excludes": "./uk/excludes.ts", "./uk/finite": "./uk/finite.ts", "./uk/graphemes": "./uk/graphemes.ts", "./uk/gtValue": "./uk/gtValue.ts", "./uk/guard": "./uk/guard.ts", "./uk/hash": "./uk/hash.ts", "./uk/hexadecimal": "./uk/hexadecimal.ts", "./uk/hexColor": "./uk/hexColor.ts", "./uk/imei": "./uk/imei.ts", "./uk/includes": "./uk/includes.ts", "./uk/integer": "./uk/integer.ts", "./uk/ip": "./uk/ip.ts", "./uk/ipv4": "./uk/ipv4.ts", "./uk/ipv6": "./uk/ipv6.ts", "./uk/isbn": "./uk/isbn.ts", "./uk/isoDate": "./uk/isoDate.ts", "./uk/isoDateTime": "./uk/isoDateTime.ts", "./uk/isoTime": "./uk/isoTime.ts", "./uk/isoTimeSecond": "./uk/isoTimeSecond.ts", "./uk/isoTimestamp": "./uk/isoTimestamp.ts", "./uk/isoWeek": "./uk/isoWeek.ts", "./uk/isrc": "./uk/isrc.ts", "./uk/jwsCompact": "./uk/jwsCompact.ts", "./uk/length": "./uk/length.ts", "./uk/ltValue": "./uk/ltValue.ts", "./uk/mac": "./uk/mac.ts", "./uk/mac48": "./uk/mac48.ts", "./uk/mac64": "./uk/mac64.ts", "./uk/maxBytes": "./uk/maxBytes.ts", "./uk/maxEntries": "./uk/maxEntries.ts", "./uk/maxGraphemes": "./uk/maxGraphemes.ts", "./uk/maxLength": "./uk/maxLength.ts", "./uk/maxSize": "./uk/maxSize.ts", "./uk/maxValue": "./uk/maxValue.ts", "./uk/maxWords": "./uk/maxWords.ts", "./uk/mimeType": "./uk/mimeType.ts", "./uk/minBytes": "./uk/minBytes.ts", "./uk/minEntries": "./uk/minEntries.ts", "./uk/minGraphemes": "./uk/minGraphemes.ts", "./uk/minLength": "./uk/minLength.ts", "./uk/minSize": "./uk/minSize.ts", "./uk/minValue": "./uk/minValue.ts", "./uk/minWords": "./uk/minWords.ts", "./uk/multipleOf": "./uk/multipleOf.ts", "./uk/nanoid": "./uk/nanoid.ts", "./uk/nonEmpty": "./uk/nonEmpty.ts", "./uk/notBytes": "./uk/notBytes.ts", "./uk/notEntries": "./uk/notEntries.ts", "./uk/notGraphemes": "./uk/notGraphemes.ts", "./uk/notLength": "./uk/notLength.ts", "./uk/notSize": "./uk/notSize.ts", "./uk/notValue": "./uk/notValue.ts", "./uk/notValues": "./uk/notValues.ts", "./uk/notWords": "./uk/notWords.ts", "./uk/octal": "./uk/octal.ts", "./uk/parseBoolean": "./uk/parseBoolean.ts", "./uk/parseJson": "./uk/parseJson.ts", "./uk/partialCheck": "./uk/partialCheck.ts", "./uk/rawCheck": "./uk/rawCheck.ts", "./uk/rawTransform": "./uk/rawTransform.ts", "./uk/regex": "./uk/regex.ts", "./uk/rfcEmail": "./uk/rfcEmail.ts", "./uk/safeInteger": "./uk/safeInteger.ts", "./uk/size": "./uk/size.ts", "./uk/slug": "./uk/slug.ts", "./uk/someItem": "./uk/someItem.ts", "./uk/startsWith": "./uk/startsWith.ts", "./uk/stringifyJson": "./uk/stringifyJson.ts", "./uk/toBigint": "./uk/toBigint.ts", "./uk/toDate": "./uk/toDate.ts", "./uk/toNumber": "./uk/toNumber.ts", "./uk/toString": "./uk/toString.ts", "./uk/ulid": "./uk/ulid.ts", "./uk/url": "./uk/url.ts", "./uk/uuid": "./uk/uuid.ts", "./uk/value": "./uk/value.ts", "./uk/values": "./uk/values.ts", "./uk/words": "./uk/words.ts", "./vi": "./vi/index.ts", "./vi/schema": "./vi/schema.ts", "./vi/base64": "./vi/base64.ts", "./vi/bic": "./vi/bic.ts", "./vi/bytes": "./vi/bytes.ts", "./vi/check": "./vi/check.ts", "./vi/checkAsync": "./vi/checkAsync.ts", "./vi/checkItems": "./vi/checkItems.ts", "./vi/checkItemsAsync": "./vi/checkItemsAsync.ts", "./vi/creditCard": "./vi/creditCard.ts", "./vi/cuid2": "./vi/cuid2.ts", "./vi/decimal": "./vi/decimal.ts", "./vi/digits": "./vi/digits.ts", "./vi/domain": "./vi/domain.ts", "./vi/email": "./vi/email.ts", "./vi/emoji": "./vi/emoji.ts", "./vi/empty": "./vi/empty.ts", "./vi/endsWith": "./vi/endsWith.ts", "./vi/entries": "./vi/entries.ts", "./vi/everyItem": "./vi/everyItem.ts", "./vi/excludes": "./vi/excludes.ts", "./vi/finite": "./vi/finite.ts", "./vi/graphemes": "./vi/graphemes.ts", "./vi/gtValue": "./vi/gtValue.ts", "./vi/guard": "./vi/guard.ts", "./vi/hash": "./vi/hash.ts", "./vi/hexadecimal": "./vi/hexadecimal.ts", "./vi/hexColor": "./vi/hexColor.ts", "./vi/imei": "./vi/imei.ts", "./vi/includes": "./vi/includes.ts", "./vi/integer": "./vi/integer.ts", "./vi/ip": "./vi/ip.ts", "./vi/ipv4": "./vi/ipv4.ts", "./vi/ipv6": "./vi/ipv6.ts", "./vi/isbn": "./vi/isbn.ts", "./vi/isoDate": "./vi/isoDate.ts", "./vi/isoDateTime": "./vi/isoDateTime.ts", "./vi/isoTime": "./vi/isoTime.ts", "./vi/isoTimeSecond": "./vi/isoTimeSecond.ts", "./vi/isoTimestamp": "./vi/isoTimestamp.ts", "./vi/isoWeek": "./vi/isoWeek.ts", "./vi/isrc": "./vi/isrc.ts", "./vi/jwsCompact": "./vi/jwsCompact.ts", "./vi/length": "./vi/length.ts", "./vi/ltValue": "./vi/ltValue.ts", "./vi/mac": "./vi/mac.ts", "./vi/mac48": "./vi/mac48.ts", "./vi/mac64": "./vi/mac64.ts", "./vi/maxBytes": "./vi/maxBytes.ts", "./vi/maxEntries": "./vi/maxEntries.ts", "./vi/maxGraphemes": "./vi/maxGraphemes.ts", "./vi/maxLength": "./vi/maxLength.ts", "./vi/maxSize": "./vi/maxSize.ts", "./vi/maxValue": "./vi/maxValue.ts", "./vi/maxWords": "./vi/maxWords.ts", "./vi/mimeType": "./vi/mimeType.ts", "./vi/minBytes": "./vi/minBytes.ts", "./vi/minEntries": "./vi/minEntries.ts", "./vi/minGraphemes": "./vi/minGraphemes.ts", "./vi/minLength": "./vi/minLength.ts", "./vi/minSize": "./vi/minSize.ts", "./vi/minValue": "./vi/minValue.ts", "./vi/minWords": "./vi/minWords.ts", "./vi/multipleOf": "./vi/multipleOf.ts", "./vi/nanoid": "./vi/nanoid.ts", "./vi/nonEmpty": "./vi/nonEmpty.ts", "./vi/notBytes": "./vi/notBytes.ts", "./vi/notEntries": "./vi/notEntries.ts", "./vi/notGraphemes": "./vi/notGraphemes.ts", "./vi/notLength": "./vi/notLength.ts", "./vi/notSize": "./vi/notSize.ts", "./vi/notValue": "./vi/notValue.ts", "./vi/notValues": "./vi/notValues.ts", "./vi/notWords": "./vi/notWords.ts", "./vi/octal": "./vi/octal.ts", "./vi/parseBoolean": "./vi/parseBoolean.ts", "./vi/parseJson": "./vi/parseJson.ts", "./vi/partialCheck": "./vi/partialCheck.ts", "./vi/rawCheck": "./vi/rawCheck.ts", "./vi/rawTransform": "./vi/rawTransform.ts", "./vi/regex": "./vi/regex.ts", "./vi/rfcEmail": "./vi/rfcEmail.ts", "./vi/safeInteger": "./vi/safeInteger.ts", "./vi/size": "./vi/size.ts", "./vi/slug": "./vi/slug.ts", "./vi/someItem": "./vi/someItem.ts", "./vi/startsWith": "./vi/startsWith.ts", "./vi/stringifyJson": "./vi/stringifyJson.ts", "./vi/toBigint": "./vi/toBigint.ts", "./vi/toDate": "./vi/toDate.ts", "./vi/toNumber": "./vi/toNumber.ts", "./vi/toString": "./vi/toString.ts", "./vi/ulid": "./vi/ulid.ts", "./vi/url": "./vi/url.ts", "./vi/uuid": "./vi/uuid.ts", "./vi/value": "./vi/value.ts", "./vi/values": "./vi/values.ts", "./vi/words": "./vi/words.ts", "./zh-CN": "./zh-CN/index.ts", "./zh-CN/schema": "./zh-CN/schema.ts", "./zh-CN/base64": "./zh-CN/base64.ts", "./zh-CN/bic": "./zh-CN/bic.ts", "./zh-CN/bytes": "./zh-CN/bytes.ts", "./zh-CN/check": "./zh-CN/check.ts", "./zh-CN/checkAsync": "./zh-CN/checkAsync.ts", "./zh-CN/checkItems": "./zh-CN/checkItems.ts", "./zh-CN/checkItemsAsync": "./zh-CN/checkItemsAsync.ts", "./zh-CN/creditCard": "./zh-CN/creditCard.ts", "./zh-CN/cuid2": "./zh-CN/cuid2.ts", "./zh-CN/decimal": "./zh-CN/decimal.ts", "./zh-CN/digits": "./zh-CN/digits.ts", "./zh-CN/domain": "./zh-CN/domain.ts", "./zh-CN/email": "./zh-CN/email.ts", "./zh-CN/emoji": "./zh-CN/emoji.ts", "./zh-CN/empty": "./zh-CN/empty.ts", "./zh-CN/endsWith": "./zh-CN/endsWith.ts", "./zh-CN/entries": "./zh-CN/entries.ts", "./zh-CN/everyItem": "./zh-CN/everyItem.ts", "./zh-CN/excludes": "./zh-CN/excludes.ts", "./zh-CN/finite": "./zh-CN/finite.ts", "./zh-CN/graphemes": "./zh-CN/graphemes.ts", "./zh-CN/gtValue": "./zh-CN/gtValue.ts", "./zh-CN/guard": "./zh-CN/guard.ts", "./zh-CN/hash": "./zh-CN/hash.ts", "./zh-CN/hexadecimal": "./zh-CN/hexadecimal.ts", "./zh-CN/hexColor": "./zh-CN/hexColor.ts", "./zh-CN/imei": "./zh-CN/imei.ts", "./zh-CN/includes": "./zh-CN/includes.ts", "./zh-CN/integer": "./zh-CN/integer.ts", "./zh-CN/ip": "./zh-CN/ip.ts", "./zh-CN/ipv4": "./zh-CN/ipv4.ts", "./zh-CN/ipv6": "./zh-CN/ipv6.ts", "./zh-CN/isbn": "./zh-CN/isbn.ts", "./zh-CN/isoDate": "./zh-CN/isoDate.ts", "./zh-CN/isoDateTime": "./zh-CN/isoDateTime.ts", "./zh-CN/isoTime": "./zh-CN/isoTime.ts", "./zh-CN/isoTimeSecond": "./zh-CN/isoTimeSecond.ts", "./zh-CN/isoTimestamp": "./zh-CN/isoTimestamp.ts", "./zh-CN/isoWeek": "./zh-CN/isoWeek.ts", "./zh-CN/isrc": "./zh-CN/isrc.ts", "./zh-CN/jwsCompact": "./zh-CN/jwsCompact.ts", "./zh-CN/length": "./zh-CN/length.ts", "./zh-CN/ltValue": "./zh-CN/ltValue.ts", "./zh-CN/mac": "./zh-CN/mac.ts", "./zh-CN/mac48": "./zh-CN/mac48.ts", "./zh-CN/mac64": "./zh-CN/mac64.ts", "./zh-CN/maxBytes": "./zh-CN/maxBytes.ts", "./zh-CN/maxEntries": "./zh-CN/maxEntries.ts", "./zh-CN/maxGraphemes": "./zh-CN/maxGraphemes.ts", "./zh-CN/maxLength": "./zh-CN/maxLength.ts", "./zh-CN/maxSize": "./zh-CN/maxSize.ts", "./zh-CN/maxValue": "./zh-CN/maxValue.ts", "./zh-CN/maxWords": "./zh-CN/maxWords.ts", "./zh-CN/mimeType": "./zh-CN/mimeType.ts", "./zh-CN/minBytes": "./zh-CN/minBytes.ts", "./zh-CN/minEntries": "./zh-CN/minEntries.ts", "./zh-CN/minGraphemes": "./zh-CN/minGraphemes.ts", "./zh-CN/minLength": "./zh-CN/minLength.ts", "./zh-CN/minSize": "./zh-CN/minSize.ts", "./zh-CN/minValue": "./zh-CN/minValue.ts", "./zh-CN/minWords": "./zh-CN/minWords.ts", "./zh-CN/multipleOf": "./zh-CN/multipleOf.ts", "./zh-CN/nanoid": "./zh-CN/nanoid.ts", "./zh-CN/nonEmpty": "./zh-CN/nonEmpty.ts", "./zh-CN/notBytes": "./zh-CN/notBytes.ts", "./zh-CN/notEntries": "./zh-CN/notEntries.ts", "./zh-CN/notGraphemes": "./zh-CN/notGraphemes.ts", "./zh-CN/notLength": "./zh-CN/notLength.ts", "./zh-CN/notSize": "./zh-CN/notSize.ts", "./zh-CN/notValue": "./zh-CN/notValue.ts", "./zh-CN/notValues": "./zh-CN/notValues.ts", "./zh-CN/notWords": "./zh-CN/notWords.ts", "./zh-CN/octal": "./zh-CN/octal.ts", "./zh-CN/parseBoolean": "./zh-CN/parseBoolean.ts", "./zh-CN/parseJson": "./zh-CN/parseJson.ts", "./zh-CN/partialCheck": "./zh-CN/partialCheck.ts", "./zh-CN/rawCheck": "./zh-CN/rawCheck.ts", "./zh-CN/rawTransform": "./zh-CN/rawTransform.ts", "./zh-CN/regex": "./zh-CN/regex.ts", "./zh-CN/rfcEmail": "./zh-CN/rfcEmail.ts", "./zh-CN/safeInteger": "./zh-CN/safeInteger.ts", "./zh-CN/size": "./zh-CN/size.ts", "./zh-CN/slug": "./zh-CN/slug.ts", "./zh-CN/someItem": "./zh-CN/someItem.ts", "./zh-CN/startsWith": "./zh-CN/startsWith.ts", "./zh-CN/stringifyJson": "./zh-CN/stringifyJson.ts", "./zh-CN/toBigint": "./zh-CN/toBigint.ts", "./zh-CN/toDate": "./zh-CN/toDate.ts", "./zh-CN/toNumber": "./zh-CN/toNumber.ts", "./zh-CN/toString": "./zh-CN/toString.ts", "./zh-CN/ulid": "./zh-CN/ulid.ts", "./zh-CN/url": "./zh-CN/url.ts", "./zh-CN/uuid": "./zh-CN/uuid.ts", "./zh-CN/value": "./zh-CN/value.ts", "./zh-CN/values": "./zh-CN/values.ts", "./zh-CN/words": "./zh-CN/words.ts", "./zh-TW": "./zh-TW/index.ts", "./zh-TW/schema": "./zh-TW/schema.ts", "./zh-TW/base64": "./zh-TW/base64.ts", "./zh-TW/bic": "./zh-TW/bic.ts", "./zh-TW/bytes": "./zh-TW/bytes.ts", "./zh-TW/check": "./zh-TW/check.ts", "./zh-TW/checkAsync": "./zh-TW/checkAsync.ts", "./zh-TW/checkItems": "./zh-TW/checkItems.ts", "./zh-TW/checkItemsAsync": "./zh-TW/checkItemsAsync.ts", "./zh-TW/creditCard": "./zh-TW/creditCard.ts", "./zh-TW/cuid2": "./zh-TW/cuid2.ts", "./zh-TW/decimal": "./zh-TW/decimal.ts", "./zh-TW/digits": "./zh-TW/digits.ts", "./zh-TW/domain": "./zh-TW/domain.ts", "./zh-TW/email": "./zh-TW/email.ts", "./zh-TW/emoji": "./zh-TW/emoji.ts", "./zh-TW/empty": "./zh-TW/empty.ts", "./zh-TW/endsWith": "./zh-TW/endsWith.ts", "./zh-TW/entries": "./zh-TW/entries.ts", "./zh-TW/everyItem": "./zh-TW/everyItem.ts", "./zh-TW/excludes": "./zh-TW/excludes.ts", "./zh-TW/finite": "./zh-TW/finite.ts", "./zh-TW/graphemes": "./zh-TW/graphemes.ts", "./zh-TW/gtValue": "./zh-TW/gtValue.ts", "./zh-TW/guard": "./zh-TW/guard.ts", "./zh-TW/hash": "./zh-TW/hash.ts", "./zh-TW/hexadecimal": "./zh-TW/hexadecimal.ts", "./zh-TW/hexColor": "./zh-TW/hexColor.ts", "./zh-TW/imei": "./zh-TW/imei.ts", "./zh-TW/includes": "./zh-TW/includes.ts", "./zh-TW/integer": "./zh-TW/integer.ts", "./zh-TW/ip": "./zh-TW/ip.ts", "./zh-TW/ipv4": "./zh-TW/ipv4.ts", "./zh-TW/ipv6": "./zh-TW/ipv6.ts", "./zh-TW/isbn": "./zh-TW/isbn.ts", "./zh-TW/isoDate": "./zh-TW/isoDate.ts", "./zh-TW/isoDateTime": "./zh-TW/isoDateTime.ts", "./zh-TW/isoTime": "./zh-TW/isoTime.ts", "./zh-TW/isoTimeSecond": "./zh-TW/isoTimeSecond.ts", "./zh-TW/isoTimestamp": "./zh-TW/isoTimestamp.ts", "./zh-TW/isoWeek": "./zh-TW/isoWeek.ts", "./zh-TW/isrc": "./zh-TW/isrc.ts", "./zh-TW/jwsCompact": "./zh-TW/jwsCompact.ts", "./zh-TW/length": "./zh-TW/length.ts", "./zh-TW/ltValue": "./zh-TW/ltValue.ts", "./zh-TW/mac": "./zh-TW/mac.ts", "./zh-TW/mac48": "./zh-TW/mac48.ts", "./zh-TW/mac64": "./zh-TW/mac64.ts", "./zh-TW/maxBytes": "./zh-TW/maxBytes.ts", "./zh-TW/maxEntries": "./zh-TW/maxEntries.ts", "./zh-TW/maxGraphemes": "./zh-TW/maxGraphemes.ts", "./zh-TW/maxLength": "./zh-TW/maxLength.ts", "./zh-TW/maxSize": "./zh-TW/maxSize.ts", "./zh-TW/maxValue": "./zh-TW/maxValue.ts", "./zh-TW/maxWords": "./zh-TW/maxWords.ts", "./zh-TW/mimeType": "./zh-TW/mimeType.ts", "./zh-TW/minBytes": "./zh-TW/minBytes.ts", "./zh-TW/minEntries": "./zh-TW/minEntries.ts", "./zh-TW/minGraphemes": "./zh-TW/minGraphemes.ts", "./zh-TW/minLength": "./zh-TW/minLength.ts", "./zh-TW/minSize": "./zh-TW/minSize.ts", "./zh-TW/minValue": "./zh-TW/minValue.ts", "./zh-TW/minWords": "./zh-TW/minWords.ts", "./zh-TW/multipleOf": "./zh-TW/multipleOf.ts", "./zh-TW/nanoid": "./zh-TW/nanoid.ts", "./zh-TW/nonEmpty": "./zh-TW/nonEmpty.ts", "./zh-TW/notBytes": "./zh-TW/notBytes.ts", "./zh-TW/notEntries": "./zh-TW/notEntries.ts", "./zh-TW/notGraphemes": "./zh-TW/notGraphemes.ts", "./zh-TW/notLength": "./zh-TW/notLength.ts", "./zh-TW/notSize": "./zh-TW/notSize.ts", "./zh-TW/notValue": "./zh-TW/notValue.ts", "./zh-TW/notValues": "./zh-TW/notValues.ts", "./zh-TW/notWords": "./zh-TW/notWords.ts", "./zh-TW/octal": "./zh-TW/octal.ts", "./zh-TW/parseBoolean": "./zh-TW/parseBoolean.ts", "./zh-TW/parseJson": "./zh-TW/parseJson.ts", "./zh-TW/partialCheck": "./zh-TW/partialCheck.ts", "./zh-TW/rawCheck": "./zh-TW/rawCheck.ts", "./zh-TW/rawTransform": "./zh-TW/rawTransform.ts", "./zh-TW/regex": "./zh-TW/regex.ts", "./zh-TW/rfcEmail": "./zh-TW/rfcEmail.ts", "./zh-TW/safeInteger": "./zh-TW/safeInteger.ts", "./zh-TW/size": "./zh-TW/size.ts", "./zh-TW/slug": "./zh-TW/slug.ts", "./zh-TW/someItem": "./zh-TW/someItem.ts", "./zh-TW/startsWith": "./zh-TW/startsWith.ts", "./zh-TW/stringifyJson": "./zh-TW/stringifyJson.ts", "./zh-TW/toBigint": "./zh-TW/toBigint.ts", "./zh-TW/toDate": "./zh-TW/toDate.ts", "./zh-TW/toNumber": "./zh-TW/toNumber.ts", "./zh-TW/toString": "./zh-TW/toString.ts", "./zh-TW/ulid": "./zh-TW/ulid.ts", "./zh-TW/url": "./zh-TW/url.ts", "./zh-TW/uuid": "./zh-TW/uuid.ts", "./zh-TW/value": "./zh-TW/value.ts", "./zh-TW/values": "./zh-TW/values.ts", "./zh-TW/words": "./zh-TW/words.ts" } } ================================================ FILE: packages/i18n/package.json ================================================ { "name": "@valibot/i18n", "description": "The official i18n translations for Valibot", "version": "1.1.0", "license": "MIT", "author": "Fabian Hiller", "homepage": "https://valibot.dev", "repository": { "type": "git", "url": "https://github.com/open-circle/valibot" }, "keywords": [ "valibot", "i18n", "translations", "internationalization" ], "type": "module", "main": "./index.mjs", "types": "./index.d.mts", "sideEffects": true, "publishConfig": { "access": "public" }, "scripts": { "lint": "tsc --noEmit", "build.npm": "tsm ./scripts/build-npm.ts", "build.jsr": "tsm ./scripts/build-jsr.ts" }, "devDependencies": { "@types/node": "^24.10.1", "tsm": "^2.3.0", "typescript": "^5.9.3", "valibot": "^1.3.0" }, "peerDependencies": { "valibot": "^1.3.0" }, "files": [ "index.ts", "index.mjs", "index.cjs", "index.d.mts", "index.d.cts", "ar", "az", "ca", "cs", "de", "el", "es", "fa", "fi", "fr", "hu", "id", "it", "ja", "ko", "kr", "mn", "nb", "nl", "pl", "pt", "ro", "ru", "sk", "sl", "sv", "tr", "uk", "vi", "zh-CN", "zh-TW" ], "exports": { ".": { "import": { "types": "./index.d.mts", "default": "./index.mjs" }, "require": { "types": "./index.d.cts", "default": "./index.cjs" } }, "./ar": { "import": { "types": "./ar/index.d.mts", "default": "./ar/index.mjs" }, "require": { "types": "./ar/index.d.cts", "default": "./ar/index.cjs" } }, "./ar/schema": { "import": { "types": "./ar/schema.d.mts", "default": "./ar/schema.mjs" }, "require": { "types": "./ar/schema.d.cts", "default": "./ar/schema.cjs" } }, "./ar/base64": { "import": { "types": "./ar/base64.d.mts", "default": "./ar/base64.mjs" }, "require": { "types": "./ar/base64.d.cts", "default": "./ar/base64.cjs" } }, "./ar/bic": { "import": { "types": "./ar/bic.d.mts", "default": "./ar/bic.mjs" }, "require": { "types": "./ar/bic.d.cts", "default": "./ar/bic.cjs" } }, "./ar/bytes": { "import": { "types": "./ar/bytes.d.mts", "default": "./ar/bytes.mjs" }, "require": { "types": "./ar/bytes.d.cts", "default": "./ar/bytes.cjs" } }, "./ar/check": { "import": { "types": "./ar/check.d.mts", "default": "./ar/check.mjs" }, "require": { "types": "./ar/check.d.cts", "default": "./ar/check.cjs" } }, "./ar/checkAsync": { "import": { "types": "./ar/checkAsync.d.mts", "default": "./ar/checkAsync.mjs" }, "require": { "types": "./ar/checkAsync.d.cts", "default": "./ar/checkAsync.cjs" } }, "./ar/checkItems": { "import": { "types": "./ar/checkItems.d.mts", "default": "./ar/checkItems.mjs" }, "require": { "types": "./ar/checkItems.d.cts", "default": "./ar/checkItems.cjs" } }, "./ar/checkItemsAsync": { "import": { "types": "./ar/checkItemsAsync.d.mts", "default": "./ar/checkItemsAsync.mjs" }, "require": { "types": "./ar/checkItemsAsync.d.cts", "default": "./ar/checkItemsAsync.cjs" } }, "./ar/creditCard": { "import": { "types": "./ar/creditCard.d.mts", "default": "./ar/creditCard.mjs" }, "require": { "types": "./ar/creditCard.d.cts", "default": "./ar/creditCard.cjs" } }, "./ar/cuid2": { "import": { "types": "./ar/cuid2.d.mts", "default": "./ar/cuid2.mjs" }, "require": { "types": "./ar/cuid2.d.cts", "default": "./ar/cuid2.cjs" } }, "./ar/decimal": { "import": { "types": "./ar/decimal.d.mts", "default": "./ar/decimal.mjs" }, "require": { "types": "./ar/decimal.d.cts", "default": "./ar/decimal.cjs" } }, "./ar/digits": { "import": { "types": "./ar/digits.d.mts", "default": "./ar/digits.mjs" }, "require": { "types": "./ar/digits.d.cts", "default": "./ar/digits.cjs" } }, "./ar/domain": { "import": { "types": "./ar/domain.d.mts", "default": "./ar/domain.mjs" }, "require": { "types": "./ar/domain.d.cts", "default": "./ar/domain.cjs" } }, "./ar/email": { "import": { "types": "./ar/email.d.mts", "default": "./ar/email.mjs" }, "require": { "types": "./ar/email.d.cts", "default": "./ar/email.cjs" } }, "./ar/emoji": { "import": { "types": "./ar/emoji.d.mts", "default": "./ar/emoji.mjs" }, "require": { "types": "./ar/emoji.d.cts", "default": "./ar/emoji.cjs" } }, "./ar/empty": { "import": { "types": "./ar/empty.d.mts", "default": "./ar/empty.mjs" }, "require": { "types": "./ar/empty.d.cts", "default": "./ar/empty.cjs" } }, "./ar/endsWith": { "import": { "types": "./ar/endsWith.d.mts", "default": "./ar/endsWith.mjs" }, "require": { "types": "./ar/endsWith.d.cts", "default": "./ar/endsWith.cjs" } }, "./ar/entries": { "import": { "types": "./ar/entries.d.mts", "default": "./ar/entries.mjs" }, "require": { "types": "./ar/entries.d.cts", "default": "./ar/entries.cjs" } }, "./ar/everyItem": { "import": { "types": "./ar/everyItem.d.mts", "default": "./ar/everyItem.mjs" }, "require": { "types": "./ar/everyItem.d.cts", "default": "./ar/everyItem.cjs" } }, "./ar/excludes": { "import": { "types": "./ar/excludes.d.mts", "default": "./ar/excludes.mjs" }, "require": { "types": "./ar/excludes.d.cts", "default": "./ar/excludes.cjs" } }, "./ar/finite": { "import": { "types": "./ar/finite.d.mts", "default": "./ar/finite.mjs" }, "require": { "types": "./ar/finite.d.cts", "default": "./ar/finite.cjs" } }, "./ar/graphemes": { "import": { "types": "./ar/graphemes.d.mts", "default": "./ar/graphemes.mjs" }, "require": { "types": "./ar/graphemes.d.cts", "default": "./ar/graphemes.cjs" } }, "./ar/gtValue": { "import": { "types": "./ar/gtValue.d.mts", "default": "./ar/gtValue.mjs" }, "require": { "types": "./ar/gtValue.d.cts", "default": "./ar/gtValue.cjs" } }, "./ar/guard": { "import": { "types": "./ar/guard.d.mts", "default": "./ar/guard.mjs" }, "require": { "types": "./ar/guard.d.cts", "default": "./ar/guard.cjs" } }, "./ar/hash": { "import": { "types": "./ar/hash.d.mts", "default": "./ar/hash.mjs" }, "require": { "types": "./ar/hash.d.cts", "default": "./ar/hash.cjs" } }, "./ar/hexadecimal": { "import": { "types": "./ar/hexadecimal.d.mts", "default": "./ar/hexadecimal.mjs" }, "require": { "types": "./ar/hexadecimal.d.cts", "default": "./ar/hexadecimal.cjs" } }, "./ar/hexColor": { "import": { "types": "./ar/hexColor.d.mts", "default": "./ar/hexColor.mjs" }, "require": { "types": "./ar/hexColor.d.cts", "default": "./ar/hexColor.cjs" } }, "./ar/imei": { "import": { "types": "./ar/imei.d.mts", "default": "./ar/imei.mjs" }, "require": { "types": "./ar/imei.d.cts", "default": "./ar/imei.cjs" } }, "./ar/includes": { "import": { "types": "./ar/includes.d.mts", "default": "./ar/includes.mjs" }, "require": { "types": "./ar/includes.d.cts", "default": "./ar/includes.cjs" } }, "./ar/integer": { "import": { "types": "./ar/integer.d.mts", "default": "./ar/integer.mjs" }, "require": { "types": "./ar/integer.d.cts", "default": "./ar/integer.cjs" } }, "./ar/ip": { "import": { "types": "./ar/ip.d.mts", "default": "./ar/ip.mjs" }, "require": { "types": "./ar/ip.d.cts", "default": "./ar/ip.cjs" } }, "./ar/ipv4": { "import": { "types": "./ar/ipv4.d.mts", "default": "./ar/ipv4.mjs" }, "require": { "types": "./ar/ipv4.d.cts", "default": "./ar/ipv4.cjs" } }, "./ar/ipv6": { "import": { "types": "./ar/ipv6.d.mts", "default": "./ar/ipv6.mjs" }, "require": { "types": "./ar/ipv6.d.cts", "default": "./ar/ipv6.cjs" } }, "./ar/isbn": { "import": { "types": "./ar/isbn.d.mts", "default": "./ar/isbn.mjs" }, "require": { "types": "./ar/isbn.d.cts", "default": "./ar/isbn.cjs" } }, "./ar/isoDate": { "import": { "types": "./ar/isoDate.d.mts", "default": "./ar/isoDate.mjs" }, "require": { "types": "./ar/isoDate.d.cts", "default": "./ar/isoDate.cjs" } }, "./ar/isoDateTime": { "import": { "types": "./ar/isoDateTime.d.mts", "default": "./ar/isoDateTime.mjs" }, "require": { "types": "./ar/isoDateTime.d.cts", "default": "./ar/isoDateTime.cjs" } }, "./ar/isoTime": { "import": { "types": "./ar/isoTime.d.mts", "default": "./ar/isoTime.mjs" }, "require": { "types": "./ar/isoTime.d.cts", "default": "./ar/isoTime.cjs" } }, "./ar/isoTimeSecond": { "import": { "types": "./ar/isoTimeSecond.d.mts", "default": "./ar/isoTimeSecond.mjs" }, "require": { "types": "./ar/isoTimeSecond.d.cts", "default": "./ar/isoTimeSecond.cjs" } }, "./ar/isoTimestamp": { "import": { "types": "./ar/isoTimestamp.d.mts", "default": "./ar/isoTimestamp.mjs" }, "require": { "types": "./ar/isoTimestamp.d.cts", "default": "./ar/isoTimestamp.cjs" } }, "./ar/isoWeek": { "import": { "types": "./ar/isoWeek.d.mts", "default": "./ar/isoWeek.mjs" }, "require": { "types": "./ar/isoWeek.d.cts", "default": "./ar/isoWeek.cjs" } }, "./ar/isrc": { "import": { "types": "./ar/isrc.d.mts", "default": "./ar/isrc.mjs" }, "require": { "types": "./ar/isrc.d.cts", "default": "./ar/isrc.cjs" } }, "./ar/jwsCompact": { "import": { "types": "./ar/jwsCompact.d.mts", "default": "./ar/jwsCompact.mjs" }, "require": { "types": "./ar/jwsCompact.d.cts", "default": "./ar/jwsCompact.cjs" } }, "./ar/length": { "import": { "types": "./ar/length.d.mts", "default": "./ar/length.mjs" }, "require": { "types": "./ar/length.d.cts", "default": "./ar/length.cjs" } }, "./ar/ltValue": { "import": { "types": "./ar/ltValue.d.mts", "default": "./ar/ltValue.mjs" }, "require": { "types": "./ar/ltValue.d.cts", "default": "./ar/ltValue.cjs" } }, "./ar/mac": { "import": { "types": "./ar/mac.d.mts", "default": "./ar/mac.mjs" }, "require": { "types": "./ar/mac.d.cts", "default": "./ar/mac.cjs" } }, "./ar/mac48": { "import": { "types": "./ar/mac48.d.mts", "default": "./ar/mac48.mjs" }, "require": { "types": "./ar/mac48.d.cts", "default": "./ar/mac48.cjs" } }, "./ar/mac64": { "import": { "types": "./ar/mac64.d.mts", "default": "./ar/mac64.mjs" }, "require": { "types": "./ar/mac64.d.cts", "default": "./ar/mac64.cjs" } }, "./ar/maxBytes": { "import": { "types": "./ar/maxBytes.d.mts", "default": "./ar/maxBytes.mjs" }, "require": { "types": "./ar/maxBytes.d.cts", "default": "./ar/maxBytes.cjs" } }, "./ar/maxEntries": { "import": { "types": "./ar/maxEntries.d.mts", "default": "./ar/maxEntries.mjs" }, "require": { "types": "./ar/maxEntries.d.cts", "default": "./ar/maxEntries.cjs" } }, "./ar/maxGraphemes": { "import": { "types": "./ar/maxGraphemes.d.mts", "default": "./ar/maxGraphemes.mjs" }, "require": { "types": "./ar/maxGraphemes.d.cts", "default": "./ar/maxGraphemes.cjs" } }, "./ar/maxLength": { "import": { "types": "./ar/maxLength.d.mts", "default": "./ar/maxLength.mjs" }, "require": { "types": "./ar/maxLength.d.cts", "default": "./ar/maxLength.cjs" } }, "./ar/maxSize": { "import": { "types": "./ar/maxSize.d.mts", "default": "./ar/maxSize.mjs" }, "require": { "types": "./ar/maxSize.d.cts", "default": "./ar/maxSize.cjs" } }, "./ar/maxValue": { "import": { "types": "./ar/maxValue.d.mts", "default": "./ar/maxValue.mjs" }, "require": { "types": "./ar/maxValue.d.cts", "default": "./ar/maxValue.cjs" } }, "./ar/maxWords": { "import": { "types": "./ar/maxWords.d.mts", "default": "./ar/maxWords.mjs" }, "require": { "types": "./ar/maxWords.d.cts", "default": "./ar/maxWords.cjs" } }, "./ar/mimeType": { "import": { "types": "./ar/mimeType.d.mts", "default": "./ar/mimeType.mjs" }, "require": { "types": "./ar/mimeType.d.cts", "default": "./ar/mimeType.cjs" } }, "./ar/minBytes": { "import": { "types": "./ar/minBytes.d.mts", "default": "./ar/minBytes.mjs" }, "require": { "types": "./ar/minBytes.d.cts", "default": "./ar/minBytes.cjs" } }, "./ar/minEntries": { "import": { "types": "./ar/minEntries.d.mts", "default": "./ar/minEntries.mjs" }, "require": { "types": "./ar/minEntries.d.cts", "default": "./ar/minEntries.cjs" } }, "./ar/minGraphemes": { "import": { "types": "./ar/minGraphemes.d.mts", "default": "./ar/minGraphemes.mjs" }, "require": { "types": "./ar/minGraphemes.d.cts", "default": "./ar/minGraphemes.cjs" } }, "./ar/minLength": { "import": { "types": "./ar/minLength.d.mts", "default": "./ar/minLength.mjs" }, "require": { "types": "./ar/minLength.d.cts", "default": "./ar/minLength.cjs" } }, "./ar/minSize": { "import": { "types": "./ar/minSize.d.mts", "default": "./ar/minSize.mjs" }, "require": { "types": "./ar/minSize.d.cts", "default": "./ar/minSize.cjs" } }, "./ar/minValue": { "import": { "types": "./ar/minValue.d.mts", "default": "./ar/minValue.mjs" }, "require": { "types": "./ar/minValue.d.cts", "default": "./ar/minValue.cjs" } }, "./ar/minWords": { "import": { "types": "./ar/minWords.d.mts", "default": "./ar/minWords.mjs" }, "require": { "types": "./ar/minWords.d.cts", "default": "./ar/minWords.cjs" } }, "./ar/multipleOf": { "import": { "types": "./ar/multipleOf.d.mts", "default": "./ar/multipleOf.mjs" }, "require": { "types": "./ar/multipleOf.d.cts", "default": "./ar/multipleOf.cjs" } }, "./ar/nanoid": { "import": { "types": "./ar/nanoid.d.mts", "default": "./ar/nanoid.mjs" }, "require": { "types": "./ar/nanoid.d.cts", "default": "./ar/nanoid.cjs" } }, "./ar/nonEmpty": { "import": { "types": "./ar/nonEmpty.d.mts", "default": "./ar/nonEmpty.mjs" }, "require": { "types": "./ar/nonEmpty.d.cts", "default": "./ar/nonEmpty.cjs" } }, "./ar/notBytes": { "import": { "types": "./ar/notBytes.d.mts", "default": "./ar/notBytes.mjs" }, "require": { "types": "./ar/notBytes.d.cts", "default": "./ar/notBytes.cjs" } }, "./ar/notEntries": { "import": { "types": "./ar/notEntries.d.mts", "default": "./ar/notEntries.mjs" }, "require": { "types": "./ar/notEntries.d.cts", "default": "./ar/notEntries.cjs" } }, "./ar/notGraphemes": { "import": { "types": "./ar/notGraphemes.d.mts", "default": "./ar/notGraphemes.mjs" }, "require": { "types": "./ar/notGraphemes.d.cts", "default": "./ar/notGraphemes.cjs" } }, "./ar/notLength": { "import": { "types": "./ar/notLength.d.mts", "default": "./ar/notLength.mjs" }, "require": { "types": "./ar/notLength.d.cts", "default": "./ar/notLength.cjs" } }, "./ar/notSize": { "import": { "types": "./ar/notSize.d.mts", "default": "./ar/notSize.mjs" }, "require": { "types": "./ar/notSize.d.cts", "default": "./ar/notSize.cjs" } }, "./ar/notValue": { "import": { "types": "./ar/notValue.d.mts", "default": "./ar/notValue.mjs" }, "require": { "types": "./ar/notValue.d.cts", "default": "./ar/notValue.cjs" } }, "./ar/notValues": { "import": { "types": "./ar/notValues.d.mts", "default": "./ar/notValues.mjs" }, "require": { "types": "./ar/notValues.d.cts", "default": "./ar/notValues.cjs" } }, "./ar/notWords": { "import": { "types": "./ar/notWords.d.mts", "default": "./ar/notWords.mjs" }, "require": { "types": "./ar/notWords.d.cts", "default": "./ar/notWords.cjs" } }, "./ar/octal": { "import": { "types": "./ar/octal.d.mts", "default": "./ar/octal.mjs" }, "require": { "types": "./ar/octal.d.cts", "default": "./ar/octal.cjs" } }, "./ar/parseBoolean": { "import": { "types": "./ar/parseBoolean.d.mts", "default": "./ar/parseBoolean.mjs" }, "require": { "types": "./ar/parseBoolean.d.cts", "default": "./ar/parseBoolean.cjs" } }, "./ar/parseJson": { "import": { "types": "./ar/parseJson.d.mts", "default": "./ar/parseJson.mjs" }, "require": { "types": "./ar/parseJson.d.cts", "default": "./ar/parseJson.cjs" } }, "./ar/partialCheck": { "import": { "types": "./ar/partialCheck.d.mts", "default": "./ar/partialCheck.mjs" }, "require": { "types": "./ar/partialCheck.d.cts", "default": "./ar/partialCheck.cjs" } }, "./ar/rawCheck": { "import": { "types": "./ar/rawCheck.d.mts", "default": "./ar/rawCheck.mjs" }, "require": { "types": "./ar/rawCheck.d.cts", "default": "./ar/rawCheck.cjs" } }, "./ar/rawTransform": { "import": { "types": "./ar/rawTransform.d.mts", "default": "./ar/rawTransform.mjs" }, "require": { "types": "./ar/rawTransform.d.cts", "default": "./ar/rawTransform.cjs" } }, "./ar/regex": { "import": { "types": "./ar/regex.d.mts", "default": "./ar/regex.mjs" }, "require": { "types": "./ar/regex.d.cts", "default": "./ar/regex.cjs" } }, "./ar/rfcEmail": { "import": { "types": "./ar/rfcEmail.d.mts", "default": "./ar/rfcEmail.mjs" }, "require": { "types": "./ar/rfcEmail.d.cts", "default": "./ar/rfcEmail.cjs" } }, "./ar/safeInteger": { "import": { "types": "./ar/safeInteger.d.mts", "default": "./ar/safeInteger.mjs" }, "require": { "types": "./ar/safeInteger.d.cts", "default": "./ar/safeInteger.cjs" } }, "./ar/size": { "import": { "types": "./ar/size.d.mts", "default": "./ar/size.mjs" }, "require": { "types": "./ar/size.d.cts", "default": "./ar/size.cjs" } }, "./ar/slug": { "import": { "types": "./ar/slug.d.mts", "default": "./ar/slug.mjs" }, "require": { "types": "./ar/slug.d.cts", "default": "./ar/slug.cjs" } }, "./ar/someItem": { "import": { "types": "./ar/someItem.d.mts", "default": "./ar/someItem.mjs" }, "require": { "types": "./ar/someItem.d.cts", "default": "./ar/someItem.cjs" } }, "./ar/startsWith": { "import": { "types": "./ar/startsWith.d.mts", "default": "./ar/startsWith.mjs" }, "require": { "types": "./ar/startsWith.d.cts", "default": "./ar/startsWith.cjs" } }, "./ar/stringifyJson": { "import": { "types": "./ar/stringifyJson.d.mts", "default": "./ar/stringifyJson.mjs" }, "require": { "types": "./ar/stringifyJson.d.cts", "default": "./ar/stringifyJson.cjs" } }, "./ar/toBigint": { "import": { "types": "./ar/toBigint.d.mts", "default": "./ar/toBigint.mjs" }, "require": { "types": "./ar/toBigint.d.cts", "default": "./ar/toBigint.cjs" } }, "./ar/toDate": { "import": { "types": "./ar/toDate.d.mts", "default": "./ar/toDate.mjs" }, "require": { "types": "./ar/toDate.d.cts", "default": "./ar/toDate.cjs" } }, "./ar/toNumber": { "import": { "types": "./ar/toNumber.d.mts", "default": "./ar/toNumber.mjs" }, "require": { "types": "./ar/toNumber.d.cts", "default": "./ar/toNumber.cjs" } }, "./ar/toString": { "import": { "types": "./ar/toString.d.mts", "default": "./ar/toString.mjs" }, "require": { "types": "./ar/toString.d.cts", "default": "./ar/toString.cjs" } }, "./ar/ulid": { "import": { "types": "./ar/ulid.d.mts", "default": "./ar/ulid.mjs" }, "require": { "types": "./ar/ulid.d.cts", "default": "./ar/ulid.cjs" } }, "./ar/url": { "import": { "types": "./ar/url.d.mts", "default": "./ar/url.mjs" }, "require": { "types": "./ar/url.d.cts", "default": "./ar/url.cjs" } }, "./ar/uuid": { "import": { "types": "./ar/uuid.d.mts", "default": "./ar/uuid.mjs" }, "require": { "types": "./ar/uuid.d.cts", "default": "./ar/uuid.cjs" } }, "./ar/value": { "import": { "types": "./ar/value.d.mts", "default": "./ar/value.mjs" }, "require": { "types": "./ar/value.d.cts", "default": "./ar/value.cjs" } }, "./ar/values": { "import": { "types": "./ar/values.d.mts", "default": "./ar/values.mjs" }, "require": { "types": "./ar/values.d.cts", "default": "./ar/values.cjs" } }, "./ar/words": { "import": { "types": "./ar/words.d.mts", "default": "./ar/words.mjs" }, "require": { "types": "./ar/words.d.cts", "default": "./ar/words.cjs" } }, "./az": { "import": { "types": "./az/index.d.mts", "default": "./az/index.mjs" }, "require": { "types": "./az/index.d.cts", "default": "./az/index.cjs" } }, "./az/schema": { "import": { "types": "./az/schema.d.mts", "default": "./az/schema.mjs" }, "require": { "types": "./az/schema.d.cts", "default": "./az/schema.cjs" } }, "./az/base64": { "import": { "types": "./az/base64.d.mts", "default": "./az/base64.mjs" }, "require": { "types": "./az/base64.d.cts", "default": "./az/base64.cjs" } }, "./az/bic": { "import": { "types": "./az/bic.d.mts", "default": "./az/bic.mjs" }, "require": { "types": "./az/bic.d.cts", "default": "./az/bic.cjs" } }, "./az/bytes": { "import": { "types": "./az/bytes.d.mts", "default": "./az/bytes.mjs" }, "require": { "types": "./az/bytes.d.cts", "default": "./az/bytes.cjs" } }, "./az/check": { "import": { "types": "./az/check.d.mts", "default": "./az/check.mjs" }, "require": { "types": "./az/check.d.cts", "default": "./az/check.cjs" } }, "./az/checkAsync": { "import": { "types": "./az/checkAsync.d.mts", "default": "./az/checkAsync.mjs" }, "require": { "types": "./az/checkAsync.d.cts", "default": "./az/checkAsync.cjs" } }, "./az/checkItems": { "import": { "types": "./az/checkItems.d.mts", "default": "./az/checkItems.mjs" }, "require": { "types": "./az/checkItems.d.cts", "default": "./az/checkItems.cjs" } }, "./az/checkItemsAsync": { "import": { "types": "./az/checkItemsAsync.d.mts", "default": "./az/checkItemsAsync.mjs" }, "require": { "types": "./az/checkItemsAsync.d.cts", "default": "./az/checkItemsAsync.cjs" } }, "./az/creditCard": { "import": { "types": "./az/creditCard.d.mts", "default": "./az/creditCard.mjs" }, "require": { "types": "./az/creditCard.d.cts", "default": "./az/creditCard.cjs" } }, "./az/cuid2": { "import": { "types": "./az/cuid2.d.mts", "default": "./az/cuid2.mjs" }, "require": { "types": "./az/cuid2.d.cts", "default": "./az/cuid2.cjs" } }, "./az/decimal": { "import": { "types": "./az/decimal.d.mts", "default": "./az/decimal.mjs" }, "require": { "types": "./az/decimal.d.cts", "default": "./az/decimal.cjs" } }, "./az/digits": { "import": { "types": "./az/digits.d.mts", "default": "./az/digits.mjs" }, "require": { "types": "./az/digits.d.cts", "default": "./az/digits.cjs" } }, "./az/domain": { "import": { "types": "./az/domain.d.mts", "default": "./az/domain.mjs" }, "require": { "types": "./az/domain.d.cts", "default": "./az/domain.cjs" } }, "./az/email": { "import": { "types": "./az/email.d.mts", "default": "./az/email.mjs" }, "require": { "types": "./az/email.d.cts", "default": "./az/email.cjs" } }, "./az/emoji": { "import": { "types": "./az/emoji.d.mts", "default": "./az/emoji.mjs" }, "require": { "types": "./az/emoji.d.cts", "default": "./az/emoji.cjs" } }, "./az/empty": { "import": { "types": "./az/empty.d.mts", "default": "./az/empty.mjs" }, "require": { "types": "./az/empty.d.cts", "default": "./az/empty.cjs" } }, "./az/endsWith": { "import": { "types": "./az/endsWith.d.mts", "default": "./az/endsWith.mjs" }, "require": { "types": "./az/endsWith.d.cts", "default": "./az/endsWith.cjs" } }, "./az/entries": { "import": { "types": "./az/entries.d.mts", "default": "./az/entries.mjs" }, "require": { "types": "./az/entries.d.cts", "default": "./az/entries.cjs" } }, "./az/everyItem": { "import": { "types": "./az/everyItem.d.mts", "default": "./az/everyItem.mjs" }, "require": { "types": "./az/everyItem.d.cts", "default": "./az/everyItem.cjs" } }, "./az/excludes": { "import": { "types": "./az/excludes.d.mts", "default": "./az/excludes.mjs" }, "require": { "types": "./az/excludes.d.cts", "default": "./az/excludes.cjs" } }, "./az/finite": { "import": { "types": "./az/finite.d.mts", "default": "./az/finite.mjs" }, "require": { "types": "./az/finite.d.cts", "default": "./az/finite.cjs" } }, "./az/graphemes": { "import": { "types": "./az/graphemes.d.mts", "default": "./az/graphemes.mjs" }, "require": { "types": "./az/graphemes.d.cts", "default": "./az/graphemes.cjs" } }, "./az/gtValue": { "import": { "types": "./az/gtValue.d.mts", "default": "./az/gtValue.mjs" }, "require": { "types": "./az/gtValue.d.cts", "default": "./az/gtValue.cjs" } }, "./az/guard": { "import": { "types": "./az/guard.d.mts", "default": "./az/guard.mjs" }, "require": { "types": "./az/guard.d.cts", "default": "./az/guard.cjs" } }, "./az/hash": { "import": { "types": "./az/hash.d.mts", "default": "./az/hash.mjs" }, "require": { "types": "./az/hash.d.cts", "default": "./az/hash.cjs" } }, "./az/hexadecimal": { "import": { "types": "./az/hexadecimal.d.mts", "default": "./az/hexadecimal.mjs" }, "require": { "types": "./az/hexadecimal.d.cts", "default": "./az/hexadecimal.cjs" } }, "./az/hexColor": { "import": { "types": "./az/hexColor.d.mts", "default": "./az/hexColor.mjs" }, "require": { "types": "./az/hexColor.d.cts", "default": "./az/hexColor.cjs" } }, "./az/imei": { "import": { "types": "./az/imei.d.mts", "default": "./az/imei.mjs" }, "require": { "types": "./az/imei.d.cts", "default": "./az/imei.cjs" } }, "./az/includes": { "import": { "types": "./az/includes.d.mts", "default": "./az/includes.mjs" }, "require": { "types": "./az/includes.d.cts", "default": "./az/includes.cjs" } }, "./az/integer": { "import": { "types": "./az/integer.d.mts", "default": "./az/integer.mjs" }, "require": { "types": "./az/integer.d.cts", "default": "./az/integer.cjs" } }, "./az/ip": { "import": { "types": "./az/ip.d.mts", "default": "./az/ip.mjs" }, "require": { "types": "./az/ip.d.cts", "default": "./az/ip.cjs" } }, "./az/ipv4": { "import": { "types": "./az/ipv4.d.mts", "default": "./az/ipv4.mjs" }, "require": { "types": "./az/ipv4.d.cts", "default": "./az/ipv4.cjs" } }, "./az/ipv6": { "import": { "types": "./az/ipv6.d.mts", "default": "./az/ipv6.mjs" }, "require": { "types": "./az/ipv6.d.cts", "default": "./az/ipv6.cjs" } }, "./az/isbn": { "import": { "types": "./az/isbn.d.mts", "default": "./az/isbn.mjs" }, "require": { "types": "./az/isbn.d.cts", "default": "./az/isbn.cjs" } }, "./az/isoDate": { "import": { "types": "./az/isoDate.d.mts", "default": "./az/isoDate.mjs" }, "require": { "types": "./az/isoDate.d.cts", "default": "./az/isoDate.cjs" } }, "./az/isoDateTime": { "import": { "types": "./az/isoDateTime.d.mts", "default": "./az/isoDateTime.mjs" }, "require": { "types": "./az/isoDateTime.d.cts", "default": "./az/isoDateTime.cjs" } }, "./az/isoTime": { "import": { "types": "./az/isoTime.d.mts", "default": "./az/isoTime.mjs" }, "require": { "types": "./az/isoTime.d.cts", "default": "./az/isoTime.cjs" } }, "./az/isoTimeSecond": { "import": { "types": "./az/isoTimeSecond.d.mts", "default": "./az/isoTimeSecond.mjs" }, "require": { "types": "./az/isoTimeSecond.d.cts", "default": "./az/isoTimeSecond.cjs" } }, "./az/isoTimestamp": { "import": { "types": "./az/isoTimestamp.d.mts", "default": "./az/isoTimestamp.mjs" }, "require": { "types": "./az/isoTimestamp.d.cts", "default": "./az/isoTimestamp.cjs" } }, "./az/isoWeek": { "import": { "types": "./az/isoWeek.d.mts", "default": "./az/isoWeek.mjs" }, "require": { "types": "./az/isoWeek.d.cts", "default": "./az/isoWeek.cjs" } }, "./az/isrc": { "import": { "types": "./az/isrc.d.mts", "default": "./az/isrc.mjs" }, "require": { "types": "./az/isrc.d.cts", "default": "./az/isrc.cjs" } }, "./az/jwsCompact": { "import": { "types": "./az/jwsCompact.d.mts", "default": "./az/jwsCompact.mjs" }, "require": { "types": "./az/jwsCompact.d.cts", "default": "./az/jwsCompact.cjs" } }, "./az/length": { "import": { "types": "./az/length.d.mts", "default": "./az/length.mjs" }, "require": { "types": "./az/length.d.cts", "default": "./az/length.cjs" } }, "./az/ltValue": { "import": { "types": "./az/ltValue.d.mts", "default": "./az/ltValue.mjs" }, "require": { "types": "./az/ltValue.d.cts", "default": "./az/ltValue.cjs" } }, "./az/mac": { "import": { "types": "./az/mac.d.mts", "default": "./az/mac.mjs" }, "require": { "types": "./az/mac.d.cts", "default": "./az/mac.cjs" } }, "./az/mac48": { "import": { "types": "./az/mac48.d.mts", "default": "./az/mac48.mjs" }, "require": { "types": "./az/mac48.d.cts", "default": "./az/mac48.cjs" } }, "./az/mac64": { "import": { "types": "./az/mac64.d.mts", "default": "./az/mac64.mjs" }, "require": { "types": "./az/mac64.d.cts", "default": "./az/mac64.cjs" } }, "./az/maxBytes": { "import": { "types": "./az/maxBytes.d.mts", "default": "./az/maxBytes.mjs" }, "require": { "types": "./az/maxBytes.d.cts", "default": "./az/maxBytes.cjs" } }, "./az/maxEntries": { "import": { "types": "./az/maxEntries.d.mts", "default": "./az/maxEntries.mjs" }, "require": { "types": "./az/maxEntries.d.cts", "default": "./az/maxEntries.cjs" } }, "./az/maxGraphemes": { "import": { "types": "./az/maxGraphemes.d.mts", "default": "./az/maxGraphemes.mjs" }, "require": { "types": "./az/maxGraphemes.d.cts", "default": "./az/maxGraphemes.cjs" } }, "./az/maxLength": { "import": { "types": "./az/maxLength.d.mts", "default": "./az/maxLength.mjs" }, "require": { "types": "./az/maxLength.d.cts", "default": "./az/maxLength.cjs" } }, "./az/maxSize": { "import": { "types": "./az/maxSize.d.mts", "default": "./az/maxSize.mjs" }, "require": { "types": "./az/maxSize.d.cts", "default": "./az/maxSize.cjs" } }, "./az/maxValue": { "import": { "types": "./az/maxValue.d.mts", "default": "./az/maxValue.mjs" }, "require": { "types": "./az/maxValue.d.cts", "default": "./az/maxValue.cjs" } }, "./az/maxWords": { "import": { "types": "./az/maxWords.d.mts", "default": "./az/maxWords.mjs" }, "require": { "types": "./az/maxWords.d.cts", "default": "./az/maxWords.cjs" } }, "./az/mimeType": { "import": { "types": "./az/mimeType.d.mts", "default": "./az/mimeType.mjs" }, "require": { "types": "./az/mimeType.d.cts", "default": "./az/mimeType.cjs" } }, "./az/minBytes": { "import": { "types": "./az/minBytes.d.mts", "default": "./az/minBytes.mjs" }, "require": { "types": "./az/minBytes.d.cts", "default": "./az/minBytes.cjs" } }, "./az/minEntries": { "import": { "types": "./az/minEntries.d.mts", "default": "./az/minEntries.mjs" }, "require": { "types": "./az/minEntries.d.cts", "default": "./az/minEntries.cjs" } }, "./az/minGraphemes": { "import": { "types": "./az/minGraphemes.d.mts", "default": "./az/minGraphemes.mjs" }, "require": { "types": "./az/minGraphemes.d.cts", "default": "./az/minGraphemes.cjs" } }, "./az/minLength": { "import": { "types": "./az/minLength.d.mts", "default": "./az/minLength.mjs" }, "require": { "types": "./az/minLength.d.cts", "default": "./az/minLength.cjs" } }, "./az/minSize": { "import": { "types": "./az/minSize.d.mts", "default": "./az/minSize.mjs" }, "require": { "types": "./az/minSize.d.cts", "default": "./az/minSize.cjs" } }, "./az/minValue": { "import": { "types": "./az/minValue.d.mts", "default": "./az/minValue.mjs" }, "require": { "types": "./az/minValue.d.cts", "default": "./az/minValue.cjs" } }, "./az/minWords": { "import": { "types": "./az/minWords.d.mts", "default": "./az/minWords.mjs" }, "require": { "types": "./az/minWords.d.cts", "default": "./az/minWords.cjs" } }, "./az/multipleOf": { "import": { "types": "./az/multipleOf.d.mts", "default": "./az/multipleOf.mjs" }, "require": { "types": "./az/multipleOf.d.cts", "default": "./az/multipleOf.cjs" } }, "./az/nanoid": { "import": { "types": "./az/nanoid.d.mts", "default": "./az/nanoid.mjs" }, "require": { "types": "./az/nanoid.d.cts", "default": "./az/nanoid.cjs" } }, "./az/nonEmpty": { "import": { "types": "./az/nonEmpty.d.mts", "default": "./az/nonEmpty.mjs" }, "require": { "types": "./az/nonEmpty.d.cts", "default": "./az/nonEmpty.cjs" } }, "./az/notBytes": { "import": { "types": "./az/notBytes.d.mts", "default": "./az/notBytes.mjs" }, "require": { "types": "./az/notBytes.d.cts", "default": "./az/notBytes.cjs" } }, "./az/notEntries": { "import": { "types": "./az/notEntries.d.mts", "default": "./az/notEntries.mjs" }, "require": { "types": "./az/notEntries.d.cts", "default": "./az/notEntries.cjs" } }, "./az/notGraphemes": { "import": { "types": "./az/notGraphemes.d.mts", "default": "./az/notGraphemes.mjs" }, "require": { "types": "./az/notGraphemes.d.cts", "default": "./az/notGraphemes.cjs" } }, "./az/notLength": { "import": { "types": "./az/notLength.d.mts", "default": "./az/notLength.mjs" }, "require": { "types": "./az/notLength.d.cts", "default": "./az/notLength.cjs" } }, "./az/notSize": { "import": { "types": "./az/notSize.d.mts", "default": "./az/notSize.mjs" }, "require": { "types": "./az/notSize.d.cts", "default": "./az/notSize.cjs" } }, "./az/notValue": { "import": { "types": "./az/notValue.d.mts", "default": "./az/notValue.mjs" }, "require": { "types": "./az/notValue.d.cts", "default": "./az/notValue.cjs" } }, "./az/notValues": { "import": { "types": "./az/notValues.d.mts", "default": "./az/notValues.mjs" }, "require": { "types": "./az/notValues.d.cts", "default": "./az/notValues.cjs" } }, "./az/notWords": { "import": { "types": "./az/notWords.d.mts", "default": "./az/notWords.mjs" }, "require": { "types": "./az/notWords.d.cts", "default": "./az/notWords.cjs" } }, "./az/octal": { "import": { "types": "./az/octal.d.mts", "default": "./az/octal.mjs" }, "require": { "types": "./az/octal.d.cts", "default": "./az/octal.cjs" } }, "./az/parseBoolean": { "import": { "types": "./az/parseBoolean.d.mts", "default": "./az/parseBoolean.mjs" }, "require": { "types": "./az/parseBoolean.d.cts", "default": "./az/parseBoolean.cjs" } }, "./az/parseJson": { "import": { "types": "./az/parseJson.d.mts", "default": "./az/parseJson.mjs" }, "require": { "types": "./az/parseJson.d.cts", "default": "./az/parseJson.cjs" } }, "./az/partialCheck": { "import": { "types": "./az/partialCheck.d.mts", "default": "./az/partialCheck.mjs" }, "require": { "types": "./az/partialCheck.d.cts", "default": "./az/partialCheck.cjs" } }, "./az/rawCheck": { "import": { "types": "./az/rawCheck.d.mts", "default": "./az/rawCheck.mjs" }, "require": { "types": "./az/rawCheck.d.cts", "default": "./az/rawCheck.cjs" } }, "./az/rawTransform": { "import": { "types": "./az/rawTransform.d.mts", "default": "./az/rawTransform.mjs" }, "require": { "types": "./az/rawTransform.d.cts", "default": "./az/rawTransform.cjs" } }, "./az/regex": { "import": { "types": "./az/regex.d.mts", "default": "./az/regex.mjs" }, "require": { "types": "./az/regex.d.cts", "default": "./az/regex.cjs" } }, "./az/rfcEmail": { "import": { "types": "./az/rfcEmail.d.mts", "default": "./az/rfcEmail.mjs" }, "require": { "types": "./az/rfcEmail.d.cts", "default": "./az/rfcEmail.cjs" } }, "./az/safeInteger": { "import": { "types": "./az/safeInteger.d.mts", "default": "./az/safeInteger.mjs" }, "require": { "types": "./az/safeInteger.d.cts", "default": "./az/safeInteger.cjs" } }, "./az/size": { "import": { "types": "./az/size.d.mts", "default": "./az/size.mjs" }, "require": { "types": "./az/size.d.cts", "default": "./az/size.cjs" } }, "./az/slug": { "import": { "types": "./az/slug.d.mts", "default": "./az/slug.mjs" }, "require": { "types": "./az/slug.d.cts", "default": "./az/slug.cjs" } }, "./az/someItem": { "import": { "types": "./az/someItem.d.mts", "default": "./az/someItem.mjs" }, "require": { "types": "./az/someItem.d.cts", "default": "./az/someItem.cjs" } }, "./az/startsWith": { "import": { "types": "./az/startsWith.d.mts", "default": "./az/startsWith.mjs" }, "require": { "types": "./az/startsWith.d.cts", "default": "./az/startsWith.cjs" } }, "./az/stringifyJson": { "import": { "types": "./az/stringifyJson.d.mts", "default": "./az/stringifyJson.mjs" }, "require": { "types": "./az/stringifyJson.d.cts", "default": "./az/stringifyJson.cjs" } }, "./az/toBigint": { "import": { "types": "./az/toBigint.d.mts", "default": "./az/toBigint.mjs" }, "require": { "types": "./az/toBigint.d.cts", "default": "./az/toBigint.cjs" } }, "./az/toDate": { "import": { "types": "./az/toDate.d.mts", "default": "./az/toDate.mjs" }, "require": { "types": "./az/toDate.d.cts", "default": "./az/toDate.cjs" } }, "./az/toNumber": { "import": { "types": "./az/toNumber.d.mts", "default": "./az/toNumber.mjs" }, "require": { "types": "./az/toNumber.d.cts", "default": "./az/toNumber.cjs" } }, "./az/toString": { "import": { "types": "./az/toString.d.mts", "default": "./az/toString.mjs" }, "require": { "types": "./az/toString.d.cts", "default": "./az/toString.cjs" } }, "./az/ulid": { "import": { "types": "./az/ulid.d.mts", "default": "./az/ulid.mjs" }, "require": { "types": "./az/ulid.d.cts", "default": "./az/ulid.cjs" } }, "./az/url": { "import": { "types": "./az/url.d.mts", "default": "./az/url.mjs" }, "require": { "types": "./az/url.d.cts", "default": "./az/url.cjs" } }, "./az/uuid": { "import": { "types": "./az/uuid.d.mts", "default": "./az/uuid.mjs" }, "require": { "types": "./az/uuid.d.cts", "default": "./az/uuid.cjs" } }, "./az/value": { "import": { "types": "./az/value.d.mts", "default": "./az/value.mjs" }, "require": { "types": "./az/value.d.cts", "default": "./az/value.cjs" } }, "./az/values": { "import": { "types": "./az/values.d.mts", "default": "./az/values.mjs" }, "require": { "types": "./az/values.d.cts", "default": "./az/values.cjs" } }, "./az/words": { "import": { "types": "./az/words.d.mts", "default": "./az/words.mjs" }, "require": { "types": "./az/words.d.cts", "default": "./az/words.cjs" } }, "./ca": { "import": { "types": "./ca/index.d.mts", "default": "./ca/index.mjs" }, "require": { "types": "./ca/index.d.cts", "default": "./ca/index.cjs" } }, "./ca/schema": { "import": { "types": "./ca/schema.d.mts", "default": "./ca/schema.mjs" }, "require": { "types": "./ca/schema.d.cts", "default": "./ca/schema.cjs" } }, "./ca/base64": { "import": { "types": "./ca/base64.d.mts", "default": "./ca/base64.mjs" }, "require": { "types": "./ca/base64.d.cts", "default": "./ca/base64.cjs" } }, "./ca/bic": { "import": { "types": "./ca/bic.d.mts", "default": "./ca/bic.mjs" }, "require": { "types": "./ca/bic.d.cts", "default": "./ca/bic.cjs" } }, "./ca/bytes": { "import": { "types": "./ca/bytes.d.mts", "default": "./ca/bytes.mjs" }, "require": { "types": "./ca/bytes.d.cts", "default": "./ca/bytes.cjs" } }, "./ca/check": { "import": { "types": "./ca/check.d.mts", "default": "./ca/check.mjs" }, "require": { "types": "./ca/check.d.cts", "default": "./ca/check.cjs" } }, "./ca/checkAsync": { "import": { "types": "./ca/checkAsync.d.mts", "default": "./ca/checkAsync.mjs" }, "require": { "types": "./ca/checkAsync.d.cts", "default": "./ca/checkAsync.cjs" } }, "./ca/checkItems": { "import": { "types": "./ca/checkItems.d.mts", "default": "./ca/checkItems.mjs" }, "require": { "types": "./ca/checkItems.d.cts", "default": "./ca/checkItems.cjs" } }, "./ca/checkItemsAsync": { "import": { "types": "./ca/checkItemsAsync.d.mts", "default": "./ca/checkItemsAsync.mjs" }, "require": { "types": "./ca/checkItemsAsync.d.cts", "default": "./ca/checkItemsAsync.cjs" } }, "./ca/creditCard": { "import": { "types": "./ca/creditCard.d.mts", "default": "./ca/creditCard.mjs" }, "require": { "types": "./ca/creditCard.d.cts", "default": "./ca/creditCard.cjs" } }, "./ca/cuid2": { "import": { "types": "./ca/cuid2.d.mts", "default": "./ca/cuid2.mjs" }, "require": { "types": "./ca/cuid2.d.cts", "default": "./ca/cuid2.cjs" } }, "./ca/decimal": { "import": { "types": "./ca/decimal.d.mts", "default": "./ca/decimal.mjs" }, "require": { "types": "./ca/decimal.d.cts", "default": "./ca/decimal.cjs" } }, "./ca/digits": { "import": { "types": "./ca/digits.d.mts", "default": "./ca/digits.mjs" }, "require": { "types": "./ca/digits.d.cts", "default": "./ca/digits.cjs" } }, "./ca/domain": { "import": { "types": "./ca/domain.d.mts", "default": "./ca/domain.mjs" }, "require": { "types": "./ca/domain.d.cts", "default": "./ca/domain.cjs" } }, "./ca/email": { "import": { "types": "./ca/email.d.mts", "default": "./ca/email.mjs" }, "require": { "types": "./ca/email.d.cts", "default": "./ca/email.cjs" } }, "./ca/emoji": { "import": { "types": "./ca/emoji.d.mts", "default": "./ca/emoji.mjs" }, "require": { "types": "./ca/emoji.d.cts", "default": "./ca/emoji.cjs" } }, "./ca/empty": { "import": { "types": "./ca/empty.d.mts", "default": "./ca/empty.mjs" }, "require": { "types": "./ca/empty.d.cts", "default": "./ca/empty.cjs" } }, "./ca/endsWith": { "import": { "types": "./ca/endsWith.d.mts", "default": "./ca/endsWith.mjs" }, "require": { "types": "./ca/endsWith.d.cts", "default": "./ca/endsWith.cjs" } }, "./ca/entries": { "import": { "types": "./ca/entries.d.mts", "default": "./ca/entries.mjs" }, "require": { "types": "./ca/entries.d.cts", "default": "./ca/entries.cjs" } }, "./ca/everyItem": { "import": { "types": "./ca/everyItem.d.mts", "default": "./ca/everyItem.mjs" }, "require": { "types": "./ca/everyItem.d.cts", "default": "./ca/everyItem.cjs" } }, "./ca/excludes": { "import": { "types": "./ca/excludes.d.mts", "default": "./ca/excludes.mjs" }, "require": { "types": "./ca/excludes.d.cts", "default": "./ca/excludes.cjs" } }, "./ca/finite": { "import": { "types": "./ca/finite.d.mts", "default": "./ca/finite.mjs" }, "require": { "types": "./ca/finite.d.cts", "default": "./ca/finite.cjs" } }, "./ca/graphemes": { "import": { "types": "./ca/graphemes.d.mts", "default": "./ca/graphemes.mjs" }, "require": { "types": "./ca/graphemes.d.cts", "default": "./ca/graphemes.cjs" } }, "./ca/gtValue": { "import": { "types": "./ca/gtValue.d.mts", "default": "./ca/gtValue.mjs" }, "require": { "types": "./ca/gtValue.d.cts", "default": "./ca/gtValue.cjs" } }, "./ca/guard": { "import": { "types": "./ca/guard.d.mts", "default": "./ca/guard.mjs" }, "require": { "types": "./ca/guard.d.cts", "default": "./ca/guard.cjs" } }, "./ca/hash": { "import": { "types": "./ca/hash.d.mts", "default": "./ca/hash.mjs" }, "require": { "types": "./ca/hash.d.cts", "default": "./ca/hash.cjs" } }, "./ca/hexadecimal": { "import": { "types": "./ca/hexadecimal.d.mts", "default": "./ca/hexadecimal.mjs" }, "require": { "types": "./ca/hexadecimal.d.cts", "default": "./ca/hexadecimal.cjs" } }, "./ca/hexColor": { "import": { "types": "./ca/hexColor.d.mts", "default": "./ca/hexColor.mjs" }, "require": { "types": "./ca/hexColor.d.cts", "default": "./ca/hexColor.cjs" } }, "./ca/imei": { "import": { "types": "./ca/imei.d.mts", "default": "./ca/imei.mjs" }, "require": { "types": "./ca/imei.d.cts", "default": "./ca/imei.cjs" } }, "./ca/includes": { "import": { "types": "./ca/includes.d.mts", "default": "./ca/includes.mjs" }, "require": { "types": "./ca/includes.d.cts", "default": "./ca/includes.cjs" } }, "./ca/integer": { "import": { "types": "./ca/integer.d.mts", "default": "./ca/integer.mjs" }, "require": { "types": "./ca/integer.d.cts", "default": "./ca/integer.cjs" } }, "./ca/ip": { "import": { "types": "./ca/ip.d.mts", "default": "./ca/ip.mjs" }, "require": { "types": "./ca/ip.d.cts", "default": "./ca/ip.cjs" } }, "./ca/ipv4": { "import": { "types": "./ca/ipv4.d.mts", "default": "./ca/ipv4.mjs" }, "require": { "types": "./ca/ipv4.d.cts", "default": "./ca/ipv4.cjs" } }, "./ca/ipv6": { "import": { "types": "./ca/ipv6.d.mts", "default": "./ca/ipv6.mjs" }, "require": { "types": "./ca/ipv6.d.cts", "default": "./ca/ipv6.cjs" } }, "./ca/isbn": { "import": { "types": "./ca/isbn.d.mts", "default": "./ca/isbn.mjs" }, "require": { "types": "./ca/isbn.d.cts", "default": "./ca/isbn.cjs" } }, "./ca/isoDate": { "import": { "types": "./ca/isoDate.d.mts", "default": "./ca/isoDate.mjs" }, "require": { "types": "./ca/isoDate.d.cts", "default": "./ca/isoDate.cjs" } }, "./ca/isoDateTime": { "import": { "types": "./ca/isoDateTime.d.mts", "default": "./ca/isoDateTime.mjs" }, "require": { "types": "./ca/isoDateTime.d.cts", "default": "./ca/isoDateTime.cjs" } }, "./ca/isoTime": { "import": { "types": "./ca/isoTime.d.mts", "default": "./ca/isoTime.mjs" }, "require": { "types": "./ca/isoTime.d.cts", "default": "./ca/isoTime.cjs" } }, "./ca/isoTimeSecond": { "import": { "types": "./ca/isoTimeSecond.d.mts", "default": "./ca/isoTimeSecond.mjs" }, "require": { "types": "./ca/isoTimeSecond.d.cts", "default": "./ca/isoTimeSecond.cjs" } }, "./ca/isoTimestamp": { "import": { "types": "./ca/isoTimestamp.d.mts", "default": "./ca/isoTimestamp.mjs" }, "require": { "types": "./ca/isoTimestamp.d.cts", "default": "./ca/isoTimestamp.cjs" } }, "./ca/isoWeek": { "import": { "types": "./ca/isoWeek.d.mts", "default": "./ca/isoWeek.mjs" }, "require": { "types": "./ca/isoWeek.d.cts", "default": "./ca/isoWeek.cjs" } }, "./ca/isrc": { "import": { "types": "./ca/isrc.d.mts", "default": "./ca/isrc.mjs" }, "require": { "types": "./ca/isrc.d.cts", "default": "./ca/isrc.cjs" } }, "./ca/jwsCompact": { "import": { "types": "./ca/jwsCompact.d.mts", "default": "./ca/jwsCompact.mjs" }, "require": { "types": "./ca/jwsCompact.d.cts", "default": "./ca/jwsCompact.cjs" } }, "./ca/length": { "import": { "types": "./ca/length.d.mts", "default": "./ca/length.mjs" }, "require": { "types": "./ca/length.d.cts", "default": "./ca/length.cjs" } }, "./ca/ltValue": { "import": { "types": "./ca/ltValue.d.mts", "default": "./ca/ltValue.mjs" }, "require": { "types": "./ca/ltValue.d.cts", "default": "./ca/ltValue.cjs" } }, "./ca/mac": { "import": { "types": "./ca/mac.d.mts", "default": "./ca/mac.mjs" }, "require": { "types": "./ca/mac.d.cts", "default": "./ca/mac.cjs" } }, "./ca/mac48": { "import": { "types": "./ca/mac48.d.mts", "default": "./ca/mac48.mjs" }, "require": { "types": "./ca/mac48.d.cts", "default": "./ca/mac48.cjs" } }, "./ca/mac64": { "import": { "types": "./ca/mac64.d.mts", "default": "./ca/mac64.mjs" }, "require": { "types": "./ca/mac64.d.cts", "default": "./ca/mac64.cjs" } }, "./ca/maxBytes": { "import": { "types": "./ca/maxBytes.d.mts", "default": "./ca/maxBytes.mjs" }, "require": { "types": "./ca/maxBytes.d.cts", "default": "./ca/maxBytes.cjs" } }, "./ca/maxEntries": { "import": { "types": "./ca/maxEntries.d.mts", "default": "./ca/maxEntries.mjs" }, "require": { "types": "./ca/maxEntries.d.cts", "default": "./ca/maxEntries.cjs" } }, "./ca/maxGraphemes": { "import": { "types": "./ca/maxGraphemes.d.mts", "default": "./ca/maxGraphemes.mjs" }, "require": { "types": "./ca/maxGraphemes.d.cts", "default": "./ca/maxGraphemes.cjs" } }, "./ca/maxLength": { "import": { "types": "./ca/maxLength.d.mts", "default": "./ca/maxLength.mjs" }, "require": { "types": "./ca/maxLength.d.cts", "default": "./ca/maxLength.cjs" } }, "./ca/maxSize": { "import": { "types": "./ca/maxSize.d.mts", "default": "./ca/maxSize.mjs" }, "require": { "types": "./ca/maxSize.d.cts", "default": "./ca/maxSize.cjs" } }, "./ca/maxValue": { "import": { "types": "./ca/maxValue.d.mts", "default": "./ca/maxValue.mjs" }, "require": { "types": "./ca/maxValue.d.cts", "default": "./ca/maxValue.cjs" } }, "./ca/maxWords": { "import": { "types": "./ca/maxWords.d.mts", "default": "./ca/maxWords.mjs" }, "require": { "types": "./ca/maxWords.d.cts", "default": "./ca/maxWords.cjs" } }, "./ca/mimeType": { "import": { "types": "./ca/mimeType.d.mts", "default": "./ca/mimeType.mjs" }, "require": { "types": "./ca/mimeType.d.cts", "default": "./ca/mimeType.cjs" } }, "./ca/minBytes": { "import": { "types": "./ca/minBytes.d.mts", "default": "./ca/minBytes.mjs" }, "require": { "types": "./ca/minBytes.d.cts", "default": "./ca/minBytes.cjs" } }, "./ca/minEntries": { "import": { "types": "./ca/minEntries.d.mts", "default": "./ca/minEntries.mjs" }, "require": { "types": "./ca/minEntries.d.cts", "default": "./ca/minEntries.cjs" } }, "./ca/minGraphemes": { "import": { "types": "./ca/minGraphemes.d.mts", "default": "./ca/minGraphemes.mjs" }, "require": { "types": "./ca/minGraphemes.d.cts", "default": "./ca/minGraphemes.cjs" } }, "./ca/minLength": { "import": { "types": "./ca/minLength.d.mts", "default": "./ca/minLength.mjs" }, "require": { "types": "./ca/minLength.d.cts", "default": "./ca/minLength.cjs" } }, "./ca/minSize": { "import": { "types": "./ca/minSize.d.mts", "default": "./ca/minSize.mjs" }, "require": { "types": "./ca/minSize.d.cts", "default": "./ca/minSize.cjs" } }, "./ca/minValue": { "import": { "types": "./ca/minValue.d.mts", "default": "./ca/minValue.mjs" }, "require": { "types": "./ca/minValue.d.cts", "default": "./ca/minValue.cjs" } }, "./ca/minWords": { "import": { "types": "./ca/minWords.d.mts", "default": "./ca/minWords.mjs" }, "require": { "types": "./ca/minWords.d.cts", "default": "./ca/minWords.cjs" } }, "./ca/multipleOf": { "import": { "types": "./ca/multipleOf.d.mts", "default": "./ca/multipleOf.mjs" }, "require": { "types": "./ca/multipleOf.d.cts", "default": "./ca/multipleOf.cjs" } }, "./ca/nanoid": { "import": { "types": "./ca/nanoid.d.mts", "default": "./ca/nanoid.mjs" }, "require": { "types": "./ca/nanoid.d.cts", "default": "./ca/nanoid.cjs" } }, "./ca/nonEmpty": { "import": { "types": "./ca/nonEmpty.d.mts", "default": "./ca/nonEmpty.mjs" }, "require": { "types": "./ca/nonEmpty.d.cts", "default": "./ca/nonEmpty.cjs" } }, "./ca/notBytes": { "import": { "types": "./ca/notBytes.d.mts", "default": "./ca/notBytes.mjs" }, "require": { "types": "./ca/notBytes.d.cts", "default": "./ca/notBytes.cjs" } }, "./ca/notEntries": { "import": { "types": "./ca/notEntries.d.mts", "default": "./ca/notEntries.mjs" }, "require": { "types": "./ca/notEntries.d.cts", "default": "./ca/notEntries.cjs" } }, "./ca/notGraphemes": { "import": { "types": "./ca/notGraphemes.d.mts", "default": "./ca/notGraphemes.mjs" }, "require": { "types": "./ca/notGraphemes.d.cts", "default": "./ca/notGraphemes.cjs" } }, "./ca/notLength": { "import": { "types": "./ca/notLength.d.mts", "default": "./ca/notLength.mjs" }, "require": { "types": "./ca/notLength.d.cts", "default": "./ca/notLength.cjs" } }, "./ca/notSize": { "import": { "types": "./ca/notSize.d.mts", "default": "./ca/notSize.mjs" }, "require": { "types": "./ca/notSize.d.cts", "default": "./ca/notSize.cjs" } }, "./ca/notValue": { "import": { "types": "./ca/notValue.d.mts", "default": "./ca/notValue.mjs" }, "require": { "types": "./ca/notValue.d.cts", "default": "./ca/notValue.cjs" } }, "./ca/notValues": { "import": { "types": "./ca/notValues.d.mts", "default": "./ca/notValues.mjs" }, "require": { "types": "./ca/notValues.d.cts", "default": "./ca/notValues.cjs" } }, "./ca/notWords": { "import": { "types": "./ca/notWords.d.mts", "default": "./ca/notWords.mjs" }, "require": { "types": "./ca/notWords.d.cts", "default": "./ca/notWords.cjs" } }, "./ca/octal": { "import": { "types": "./ca/octal.d.mts", "default": "./ca/octal.mjs" }, "require": { "types": "./ca/octal.d.cts", "default": "./ca/octal.cjs" } }, "./ca/parseBoolean": { "import": { "types": "./ca/parseBoolean.d.mts", "default": "./ca/parseBoolean.mjs" }, "require": { "types": "./ca/parseBoolean.d.cts", "default": "./ca/parseBoolean.cjs" } }, "./ca/parseJson": { "import": { "types": "./ca/parseJson.d.mts", "default": "./ca/parseJson.mjs" }, "require": { "types": "./ca/parseJson.d.cts", "default": "./ca/parseJson.cjs" } }, "./ca/partialCheck": { "import": { "types": "./ca/partialCheck.d.mts", "default": "./ca/partialCheck.mjs" }, "require": { "types": "./ca/partialCheck.d.cts", "default": "./ca/partialCheck.cjs" } }, "./ca/rawCheck": { "import": { "types": "./ca/rawCheck.d.mts", "default": "./ca/rawCheck.mjs" }, "require": { "types": "./ca/rawCheck.d.cts", "default": "./ca/rawCheck.cjs" } }, "./ca/rawTransform": { "import": { "types": "./ca/rawTransform.d.mts", "default": "./ca/rawTransform.mjs" }, "require": { "types": "./ca/rawTransform.d.cts", "default": "./ca/rawTransform.cjs" } }, "./ca/regex": { "import": { "types": "./ca/regex.d.mts", "default": "./ca/regex.mjs" }, "require": { "types": "./ca/regex.d.cts", "default": "./ca/regex.cjs" } }, "./ca/rfcEmail": { "import": { "types": "./ca/rfcEmail.d.mts", "default": "./ca/rfcEmail.mjs" }, "require": { "types": "./ca/rfcEmail.d.cts", "default": "./ca/rfcEmail.cjs" } }, "./ca/safeInteger": { "import": { "types": "./ca/safeInteger.d.mts", "default": "./ca/safeInteger.mjs" }, "require": { "types": "./ca/safeInteger.d.cts", "default": "./ca/safeInteger.cjs" } }, "./ca/size": { "import": { "types": "./ca/size.d.mts", "default": "./ca/size.mjs" }, "require": { "types": "./ca/size.d.cts", "default": "./ca/size.cjs" } }, "./ca/slug": { "import": { "types": "./ca/slug.d.mts", "default": "./ca/slug.mjs" }, "require": { "types": "./ca/slug.d.cts", "default": "./ca/slug.cjs" } }, "./ca/someItem": { "import": { "types": "./ca/someItem.d.mts", "default": "./ca/someItem.mjs" }, "require": { "types": "./ca/someItem.d.cts", "default": "./ca/someItem.cjs" } }, "./ca/startsWith": { "import": { "types": "./ca/startsWith.d.mts", "default": "./ca/startsWith.mjs" }, "require": { "types": "./ca/startsWith.d.cts", "default": "./ca/startsWith.cjs" } }, "./ca/stringifyJson": { "import": { "types": "./ca/stringifyJson.d.mts", "default": "./ca/stringifyJson.mjs" }, "require": { "types": "./ca/stringifyJson.d.cts", "default": "./ca/stringifyJson.cjs" } }, "./ca/toBigint": { "import": { "types": "./ca/toBigint.d.mts", "default": "./ca/toBigint.mjs" }, "require": { "types": "./ca/toBigint.d.cts", "default": "./ca/toBigint.cjs" } }, "./ca/toDate": { "import": { "types": "./ca/toDate.d.mts", "default": "./ca/toDate.mjs" }, "require": { "types": "./ca/toDate.d.cts", "default": "./ca/toDate.cjs" } }, "./ca/toNumber": { "import": { "types": "./ca/toNumber.d.mts", "default": "./ca/toNumber.mjs" }, "require": { "types": "./ca/toNumber.d.cts", "default": "./ca/toNumber.cjs" } }, "./ca/toString": { "import": { "types": "./ca/toString.d.mts", "default": "./ca/toString.mjs" }, "require": { "types": "./ca/toString.d.cts", "default": "./ca/toString.cjs" } }, "./ca/ulid": { "import": { "types": "./ca/ulid.d.mts", "default": "./ca/ulid.mjs" }, "require": { "types": "./ca/ulid.d.cts", "default": "./ca/ulid.cjs" } }, "./ca/url": { "import": { "types": "./ca/url.d.mts", "default": "./ca/url.mjs" }, "require": { "types": "./ca/url.d.cts", "default": "./ca/url.cjs" } }, "./ca/uuid": { "import": { "types": "./ca/uuid.d.mts", "default": "./ca/uuid.mjs" }, "require": { "types": "./ca/uuid.d.cts", "default": "./ca/uuid.cjs" } }, "./ca/value": { "import": { "types": "./ca/value.d.mts", "default": "./ca/value.mjs" }, "require": { "types": "./ca/value.d.cts", "default": "./ca/value.cjs" } }, "./ca/values": { "import": { "types": "./ca/values.d.mts", "default": "./ca/values.mjs" }, "require": { "types": "./ca/values.d.cts", "default": "./ca/values.cjs" } }, "./ca/words": { "import": { "types": "./ca/words.d.mts", "default": "./ca/words.mjs" }, "require": { "types": "./ca/words.d.cts", "default": "./ca/words.cjs" } }, "./cs": { "import": { "types": "./cs/index.d.mts", "default": "./cs/index.mjs" }, "require": { "types": "./cs/index.d.cts", "default": "./cs/index.cjs" } }, "./cs/schema": { "import": { "types": "./cs/schema.d.mts", "default": "./cs/schema.mjs" }, "require": { "types": "./cs/schema.d.cts", "default": "./cs/schema.cjs" } }, "./cs/base64": { "import": { "types": "./cs/base64.d.mts", "default": "./cs/base64.mjs" }, "require": { "types": "./cs/base64.d.cts", "default": "./cs/base64.cjs" } }, "./cs/bic": { "import": { "types": "./cs/bic.d.mts", "default": "./cs/bic.mjs" }, "require": { "types": "./cs/bic.d.cts", "default": "./cs/bic.cjs" } }, "./cs/bytes": { "import": { "types": "./cs/bytes.d.mts", "default": "./cs/bytes.mjs" }, "require": { "types": "./cs/bytes.d.cts", "default": "./cs/bytes.cjs" } }, "./cs/check": { "import": { "types": "./cs/check.d.mts", "default": "./cs/check.mjs" }, "require": { "types": "./cs/check.d.cts", "default": "./cs/check.cjs" } }, "./cs/checkAsync": { "import": { "types": "./cs/checkAsync.d.mts", "default": "./cs/checkAsync.mjs" }, "require": { "types": "./cs/checkAsync.d.cts", "default": "./cs/checkAsync.cjs" } }, "./cs/checkItems": { "import": { "types": "./cs/checkItems.d.mts", "default": "./cs/checkItems.mjs" }, "require": { "types": "./cs/checkItems.d.cts", "default": "./cs/checkItems.cjs" } }, "./cs/checkItemsAsync": { "import": { "types": "./cs/checkItemsAsync.d.mts", "default": "./cs/checkItemsAsync.mjs" }, "require": { "types": "./cs/checkItemsAsync.d.cts", "default": "./cs/checkItemsAsync.cjs" } }, "./cs/creditCard": { "import": { "types": "./cs/creditCard.d.mts", "default": "./cs/creditCard.mjs" }, "require": { "types": "./cs/creditCard.d.cts", "default": "./cs/creditCard.cjs" } }, "./cs/cuid2": { "import": { "types": "./cs/cuid2.d.mts", "default": "./cs/cuid2.mjs" }, "require": { "types": "./cs/cuid2.d.cts", "default": "./cs/cuid2.cjs" } }, "./cs/decimal": { "import": { "types": "./cs/decimal.d.mts", "default": "./cs/decimal.mjs" }, "require": { "types": "./cs/decimal.d.cts", "default": "./cs/decimal.cjs" } }, "./cs/digits": { "import": { "types": "./cs/digits.d.mts", "default": "./cs/digits.mjs" }, "require": { "types": "./cs/digits.d.cts", "default": "./cs/digits.cjs" } }, "./cs/domain": { "import": { "types": "./cs/domain.d.mts", "default": "./cs/domain.mjs" }, "require": { "types": "./cs/domain.d.cts", "default": "./cs/domain.cjs" } }, "./cs/email": { "import": { "types": "./cs/email.d.mts", "default": "./cs/email.mjs" }, "require": { "types": "./cs/email.d.cts", "default": "./cs/email.cjs" } }, "./cs/emoji": { "import": { "types": "./cs/emoji.d.mts", "default": "./cs/emoji.mjs" }, "require": { "types": "./cs/emoji.d.cts", "default": "./cs/emoji.cjs" } }, "./cs/empty": { "import": { "types": "./cs/empty.d.mts", "default": "./cs/empty.mjs" }, "require": { "types": "./cs/empty.d.cts", "default": "./cs/empty.cjs" } }, "./cs/endsWith": { "import": { "types": "./cs/endsWith.d.mts", "default": "./cs/endsWith.mjs" }, "require": { "types": "./cs/endsWith.d.cts", "default": "./cs/endsWith.cjs" } }, "./cs/entries": { "import": { "types": "./cs/entries.d.mts", "default": "./cs/entries.mjs" }, "require": { "types": "./cs/entries.d.cts", "default": "./cs/entries.cjs" } }, "./cs/everyItem": { "import": { "types": "./cs/everyItem.d.mts", "default": "./cs/everyItem.mjs" }, "require": { "types": "./cs/everyItem.d.cts", "default": "./cs/everyItem.cjs" } }, "./cs/excludes": { "import": { "types": "./cs/excludes.d.mts", "default": "./cs/excludes.mjs" }, "require": { "types": "./cs/excludes.d.cts", "default": "./cs/excludes.cjs" } }, "./cs/finite": { "import": { "types": "./cs/finite.d.mts", "default": "./cs/finite.mjs" }, "require": { "types": "./cs/finite.d.cts", "default": "./cs/finite.cjs" } }, "./cs/graphemes": { "import": { "types": "./cs/graphemes.d.mts", "default": "./cs/graphemes.mjs" }, "require": { "types": "./cs/graphemes.d.cts", "default": "./cs/graphemes.cjs" } }, "./cs/gtValue": { "import": { "types": "./cs/gtValue.d.mts", "default": "./cs/gtValue.mjs" }, "require": { "types": "./cs/gtValue.d.cts", "default": "./cs/gtValue.cjs" } }, "./cs/guard": { "import": { "types": "./cs/guard.d.mts", "default": "./cs/guard.mjs" }, "require": { "types": "./cs/guard.d.cts", "default": "./cs/guard.cjs" } }, "./cs/hash": { "import": { "types": "./cs/hash.d.mts", "default": "./cs/hash.mjs" }, "require": { "types": "./cs/hash.d.cts", "default": "./cs/hash.cjs" } }, "./cs/hexadecimal": { "import": { "types": "./cs/hexadecimal.d.mts", "default": "./cs/hexadecimal.mjs" }, "require": { "types": "./cs/hexadecimal.d.cts", "default": "./cs/hexadecimal.cjs" } }, "./cs/hexColor": { "import": { "types": "./cs/hexColor.d.mts", "default": "./cs/hexColor.mjs" }, "require": { "types": "./cs/hexColor.d.cts", "default": "./cs/hexColor.cjs" } }, "./cs/imei": { "import": { "types": "./cs/imei.d.mts", "default": "./cs/imei.mjs" }, "require": { "types": "./cs/imei.d.cts", "default": "./cs/imei.cjs" } }, "./cs/includes": { "import": { "types": "./cs/includes.d.mts", "default": "./cs/includes.mjs" }, "require": { "types": "./cs/includes.d.cts", "default": "./cs/includes.cjs" } }, "./cs/integer": { "import": { "types": "./cs/integer.d.mts", "default": "./cs/integer.mjs" }, "require": { "types": "./cs/integer.d.cts", "default": "./cs/integer.cjs" } }, "./cs/ip": { "import": { "types": "./cs/ip.d.mts", "default": "./cs/ip.mjs" }, "require": { "types": "./cs/ip.d.cts", "default": "./cs/ip.cjs" } }, "./cs/ipv4": { "import": { "types": "./cs/ipv4.d.mts", "default": "./cs/ipv4.mjs" }, "require": { "types": "./cs/ipv4.d.cts", "default": "./cs/ipv4.cjs" } }, "./cs/ipv6": { "import": { "types": "./cs/ipv6.d.mts", "default": "./cs/ipv6.mjs" }, "require": { "types": "./cs/ipv6.d.cts", "default": "./cs/ipv6.cjs" } }, "./cs/isbn": { "import": { "types": "./cs/isbn.d.mts", "default": "./cs/isbn.mjs" }, "require": { "types": "./cs/isbn.d.cts", "default": "./cs/isbn.cjs" } }, "./cs/isoDate": { "import": { "types": "./cs/isoDate.d.mts", "default": "./cs/isoDate.mjs" }, "require": { "types": "./cs/isoDate.d.cts", "default": "./cs/isoDate.cjs" } }, "./cs/isoDateTime": { "import": { "types": "./cs/isoDateTime.d.mts", "default": "./cs/isoDateTime.mjs" }, "require": { "types": "./cs/isoDateTime.d.cts", "default": "./cs/isoDateTime.cjs" } }, "./cs/isoTime": { "import": { "types": "./cs/isoTime.d.mts", "default": "./cs/isoTime.mjs" }, "require": { "types": "./cs/isoTime.d.cts", "default": "./cs/isoTime.cjs" } }, "./cs/isoTimeSecond": { "import": { "types": "./cs/isoTimeSecond.d.mts", "default": "./cs/isoTimeSecond.mjs" }, "require": { "types": "./cs/isoTimeSecond.d.cts", "default": "./cs/isoTimeSecond.cjs" } }, "./cs/isoTimestamp": { "import": { "types": "./cs/isoTimestamp.d.mts", "default": "./cs/isoTimestamp.mjs" }, "require": { "types": "./cs/isoTimestamp.d.cts", "default": "./cs/isoTimestamp.cjs" } }, "./cs/isoWeek": { "import": { "types": "./cs/isoWeek.d.mts", "default": "./cs/isoWeek.mjs" }, "require": { "types": "./cs/isoWeek.d.cts", "default": "./cs/isoWeek.cjs" } }, "./cs/isrc": { "import": { "types": "./cs/isrc.d.mts", "default": "./cs/isrc.mjs" }, "require": { "types": "./cs/isrc.d.cts", "default": "./cs/isrc.cjs" } }, "./cs/jwsCompact": { "import": { "types": "./cs/jwsCompact.d.mts", "default": "./cs/jwsCompact.mjs" }, "require": { "types": "./cs/jwsCompact.d.cts", "default": "./cs/jwsCompact.cjs" } }, "./cs/length": { "import": { "types": "./cs/length.d.mts", "default": "./cs/length.mjs" }, "require": { "types": "./cs/length.d.cts", "default": "./cs/length.cjs" } }, "./cs/ltValue": { "import": { "types": "./cs/ltValue.d.mts", "default": "./cs/ltValue.mjs" }, "require": { "types": "./cs/ltValue.d.cts", "default": "./cs/ltValue.cjs" } }, "./cs/mac": { "import": { "types": "./cs/mac.d.mts", "default": "./cs/mac.mjs" }, "require": { "types": "./cs/mac.d.cts", "default": "./cs/mac.cjs" } }, "./cs/mac48": { "import": { "types": "./cs/mac48.d.mts", "default": "./cs/mac48.mjs" }, "require": { "types": "./cs/mac48.d.cts", "default": "./cs/mac48.cjs" } }, "./cs/mac64": { "import": { "types": "./cs/mac64.d.mts", "default": "./cs/mac64.mjs" }, "require": { "types": "./cs/mac64.d.cts", "default": "./cs/mac64.cjs" } }, "./cs/maxBytes": { "import": { "types": "./cs/maxBytes.d.mts", "default": "./cs/maxBytes.mjs" }, "require": { "types": "./cs/maxBytes.d.cts", "default": "./cs/maxBytes.cjs" } }, "./cs/maxEntries": { "import": { "types": "./cs/maxEntries.d.mts", "default": "./cs/maxEntries.mjs" }, "require": { "types": "./cs/maxEntries.d.cts", "default": "./cs/maxEntries.cjs" } }, "./cs/maxGraphemes": { "import": { "types": "./cs/maxGraphemes.d.mts", "default": "./cs/maxGraphemes.mjs" }, "require": { "types": "./cs/maxGraphemes.d.cts", "default": "./cs/maxGraphemes.cjs" } }, "./cs/maxLength": { "import": { "types": "./cs/maxLength.d.mts", "default": "./cs/maxLength.mjs" }, "require": { "types": "./cs/maxLength.d.cts", "default": "./cs/maxLength.cjs" } }, "./cs/maxSize": { "import": { "types": "./cs/maxSize.d.mts", "default": "./cs/maxSize.mjs" }, "require": { "types": "./cs/maxSize.d.cts", "default": "./cs/maxSize.cjs" } }, "./cs/maxValue": { "import": { "types": "./cs/maxValue.d.mts", "default": "./cs/maxValue.mjs" }, "require": { "types": "./cs/maxValue.d.cts", "default": "./cs/maxValue.cjs" } }, "./cs/maxWords": { "import": { "types": "./cs/maxWords.d.mts", "default": "./cs/maxWords.mjs" }, "require": { "types": "./cs/maxWords.d.cts", "default": "./cs/maxWords.cjs" } }, "./cs/mimeType": { "import": { "types": "./cs/mimeType.d.mts", "default": "./cs/mimeType.mjs" }, "require": { "types": "./cs/mimeType.d.cts", "default": "./cs/mimeType.cjs" } }, "./cs/minBytes": { "import": { "types": "./cs/minBytes.d.mts", "default": "./cs/minBytes.mjs" }, "require": { "types": "./cs/minBytes.d.cts", "default": "./cs/minBytes.cjs" } }, "./cs/minEntries": { "import": { "types": "./cs/minEntries.d.mts", "default": "./cs/minEntries.mjs" }, "require": { "types": "./cs/minEntries.d.cts", "default": "./cs/minEntries.cjs" } }, "./cs/minGraphemes": { "import": { "types": "./cs/minGraphemes.d.mts", "default": "./cs/minGraphemes.mjs" }, "require": { "types": "./cs/minGraphemes.d.cts", "default": "./cs/minGraphemes.cjs" } }, "./cs/minLength": { "import": { "types": "./cs/minLength.d.mts", "default": "./cs/minLength.mjs" }, "require": { "types": "./cs/minLength.d.cts", "default": "./cs/minLength.cjs" } }, "./cs/minSize": { "import": { "types": "./cs/minSize.d.mts", "default": "./cs/minSize.mjs" }, "require": { "types": "./cs/minSize.d.cts", "default": "./cs/minSize.cjs" } }, "./cs/minValue": { "import": { "types": "./cs/minValue.d.mts", "default": "./cs/minValue.mjs" }, "require": { "types": "./cs/minValue.d.cts", "default": "./cs/minValue.cjs" } }, "./cs/minWords": { "import": { "types": "./cs/minWords.d.mts", "default": "./cs/minWords.mjs" }, "require": { "types": "./cs/minWords.d.cts", "default": "./cs/minWords.cjs" } }, "./cs/multipleOf": { "import": { "types": "./cs/multipleOf.d.mts", "default": "./cs/multipleOf.mjs" }, "require": { "types": "./cs/multipleOf.d.cts", "default": "./cs/multipleOf.cjs" } }, "./cs/nanoid": { "import": { "types": "./cs/nanoid.d.mts", "default": "./cs/nanoid.mjs" }, "require": { "types": "./cs/nanoid.d.cts", "default": "./cs/nanoid.cjs" } }, "./cs/nonEmpty": { "import": { "types": "./cs/nonEmpty.d.mts", "default": "./cs/nonEmpty.mjs" }, "require": { "types": "./cs/nonEmpty.d.cts", "default": "./cs/nonEmpty.cjs" } }, "./cs/notBytes": { "import": { "types": "./cs/notBytes.d.mts", "default": "./cs/notBytes.mjs" }, "require": { "types": "./cs/notBytes.d.cts", "default": "./cs/notBytes.cjs" } }, "./cs/notEntries": { "import": { "types": "./cs/notEntries.d.mts", "default": "./cs/notEntries.mjs" }, "require": { "types": "./cs/notEntries.d.cts", "default": "./cs/notEntries.cjs" } }, "./cs/notGraphemes": { "import": { "types": "./cs/notGraphemes.d.mts", "default": "./cs/notGraphemes.mjs" }, "require": { "types": "./cs/notGraphemes.d.cts", "default": "./cs/notGraphemes.cjs" } }, "./cs/notLength": { "import": { "types": "./cs/notLength.d.mts", "default": "./cs/notLength.mjs" }, "require": { "types": "./cs/notLength.d.cts", "default": "./cs/notLength.cjs" } }, "./cs/notSize": { "import": { "types": "./cs/notSize.d.mts", "default": "./cs/notSize.mjs" }, "require": { "types": "./cs/notSize.d.cts", "default": "./cs/notSize.cjs" } }, "./cs/notValue": { "import": { "types": "./cs/notValue.d.mts", "default": "./cs/notValue.mjs" }, "require": { "types": "./cs/notValue.d.cts", "default": "./cs/notValue.cjs" } }, "./cs/notValues": { "import": { "types": "./cs/notValues.d.mts", "default": "./cs/notValues.mjs" }, "require": { "types": "./cs/notValues.d.cts", "default": "./cs/notValues.cjs" } }, "./cs/notWords": { "import": { "types": "./cs/notWords.d.mts", "default": "./cs/notWords.mjs" }, "require": { "types": "./cs/notWords.d.cts", "default": "./cs/notWords.cjs" } }, "./cs/octal": { "import": { "types": "./cs/octal.d.mts", "default": "./cs/octal.mjs" }, "require": { "types": "./cs/octal.d.cts", "default": "./cs/octal.cjs" } }, "./cs/parseBoolean": { "import": { "types": "./cs/parseBoolean.d.mts", "default": "./cs/parseBoolean.mjs" }, "require": { "types": "./cs/parseBoolean.d.cts", "default": "./cs/parseBoolean.cjs" } }, "./cs/parseJson": { "import": { "types": "./cs/parseJson.d.mts", "default": "./cs/parseJson.mjs" }, "require": { "types": "./cs/parseJson.d.cts", "default": "./cs/parseJson.cjs" } }, "./cs/partialCheck": { "import": { "types": "./cs/partialCheck.d.mts", "default": "./cs/partialCheck.mjs" }, "require": { "types": "./cs/partialCheck.d.cts", "default": "./cs/partialCheck.cjs" } }, "./cs/rawCheck": { "import": { "types": "./cs/rawCheck.d.mts", "default": "./cs/rawCheck.mjs" }, "require": { "types": "./cs/rawCheck.d.cts", "default": "./cs/rawCheck.cjs" } }, "./cs/rawTransform": { "import": { "types": "./cs/rawTransform.d.mts", "default": "./cs/rawTransform.mjs" }, "require": { "types": "./cs/rawTransform.d.cts", "default": "./cs/rawTransform.cjs" } }, "./cs/regex": { "import": { "types": "./cs/regex.d.mts", "default": "./cs/regex.mjs" }, "require": { "types": "./cs/regex.d.cts", "default": "./cs/regex.cjs" } }, "./cs/rfcEmail": { "import": { "types": "./cs/rfcEmail.d.mts", "default": "./cs/rfcEmail.mjs" }, "require": { "types": "./cs/rfcEmail.d.cts", "default": "./cs/rfcEmail.cjs" } }, "./cs/safeInteger": { "import": { "types": "./cs/safeInteger.d.mts", "default": "./cs/safeInteger.mjs" }, "require": { "types": "./cs/safeInteger.d.cts", "default": "./cs/safeInteger.cjs" } }, "./cs/size": { "import": { "types": "./cs/size.d.mts", "default": "./cs/size.mjs" }, "require": { "types": "./cs/size.d.cts", "default": "./cs/size.cjs" } }, "./cs/slug": { "import": { "types": "./cs/slug.d.mts", "default": "./cs/slug.mjs" }, "require": { "types": "./cs/slug.d.cts", "default": "./cs/slug.cjs" } }, "./cs/someItem": { "import": { "types": "./cs/someItem.d.mts", "default": "./cs/someItem.mjs" }, "require": { "types": "./cs/someItem.d.cts", "default": "./cs/someItem.cjs" } }, "./cs/startsWith": { "import": { "types": "./cs/startsWith.d.mts", "default": "./cs/startsWith.mjs" }, "require": { "types": "./cs/startsWith.d.cts", "default": "./cs/startsWith.cjs" } }, "./cs/stringifyJson": { "import": { "types": "./cs/stringifyJson.d.mts", "default": "./cs/stringifyJson.mjs" }, "require": { "types": "./cs/stringifyJson.d.cts", "default": "./cs/stringifyJson.cjs" } }, "./cs/toBigint": { "import": { "types": "./cs/toBigint.d.mts", "default": "./cs/toBigint.mjs" }, "require": { "types": "./cs/toBigint.d.cts", "default": "./cs/toBigint.cjs" } }, "./cs/toDate": { "import": { "types": "./cs/toDate.d.mts", "default": "./cs/toDate.mjs" }, "require": { "types": "./cs/toDate.d.cts", "default": "./cs/toDate.cjs" } }, "./cs/toNumber": { "import": { "types": "./cs/toNumber.d.mts", "default": "./cs/toNumber.mjs" }, "require": { "types": "./cs/toNumber.d.cts", "default": "./cs/toNumber.cjs" } }, "./cs/toString": { "import": { "types": "./cs/toString.d.mts", "default": "./cs/toString.mjs" }, "require": { "types": "./cs/toString.d.cts", "default": "./cs/toString.cjs" } }, "./cs/ulid": { "import": { "types": "./cs/ulid.d.mts", "default": "./cs/ulid.mjs" }, "require": { "types": "./cs/ulid.d.cts", "default": "./cs/ulid.cjs" } }, "./cs/url": { "import": { "types": "./cs/url.d.mts", "default": "./cs/url.mjs" }, "require": { "types": "./cs/url.d.cts", "default": "./cs/url.cjs" } }, "./cs/uuid": { "import": { "types": "./cs/uuid.d.mts", "default": "./cs/uuid.mjs" }, "require": { "types": "./cs/uuid.d.cts", "default": "./cs/uuid.cjs" } }, "./cs/value": { "import": { "types": "./cs/value.d.mts", "default": "./cs/value.mjs" }, "require": { "types": "./cs/value.d.cts", "default": "./cs/value.cjs" } }, "./cs/values": { "import": { "types": "./cs/values.d.mts", "default": "./cs/values.mjs" }, "require": { "types": "./cs/values.d.cts", "default": "./cs/values.cjs" } }, "./cs/words": { "import": { "types": "./cs/words.d.mts", "default": "./cs/words.mjs" }, "require": { "types": "./cs/words.d.cts", "default": "./cs/words.cjs" } }, "./de": { "import": { "types": "./de/index.d.mts", "default": "./de/index.mjs" }, "require": { "types": "./de/index.d.cts", "default": "./de/index.cjs" } }, "./de/schema": { "import": { "types": "./de/schema.d.mts", "default": "./de/schema.mjs" }, "require": { "types": "./de/schema.d.cts", "default": "./de/schema.cjs" } }, "./de/base64": { "import": { "types": "./de/base64.d.mts", "default": "./de/base64.mjs" }, "require": { "types": "./de/base64.d.cts", "default": "./de/base64.cjs" } }, "./de/bic": { "import": { "types": "./de/bic.d.mts", "default": "./de/bic.mjs" }, "require": { "types": "./de/bic.d.cts", "default": "./de/bic.cjs" } }, "./de/bytes": { "import": { "types": "./de/bytes.d.mts", "default": "./de/bytes.mjs" }, "require": { "types": "./de/bytes.d.cts", "default": "./de/bytes.cjs" } }, "./de/check": { "import": { "types": "./de/check.d.mts", "default": "./de/check.mjs" }, "require": { "types": "./de/check.d.cts", "default": "./de/check.cjs" } }, "./de/checkAsync": { "import": { "types": "./de/checkAsync.d.mts", "default": "./de/checkAsync.mjs" }, "require": { "types": "./de/checkAsync.d.cts", "default": "./de/checkAsync.cjs" } }, "./de/checkItems": { "import": { "types": "./de/checkItems.d.mts", "default": "./de/checkItems.mjs" }, "require": { "types": "./de/checkItems.d.cts", "default": "./de/checkItems.cjs" } }, "./de/checkItemsAsync": { "import": { "types": "./de/checkItemsAsync.d.mts", "default": "./de/checkItemsAsync.mjs" }, "require": { "types": "./de/checkItemsAsync.d.cts", "default": "./de/checkItemsAsync.cjs" } }, "./de/creditCard": { "import": { "types": "./de/creditCard.d.mts", "default": "./de/creditCard.mjs" }, "require": { "types": "./de/creditCard.d.cts", "default": "./de/creditCard.cjs" } }, "./de/cuid2": { "import": { "types": "./de/cuid2.d.mts", "default": "./de/cuid2.mjs" }, "require": { "types": "./de/cuid2.d.cts", "default": "./de/cuid2.cjs" } }, "./de/decimal": { "import": { "types": "./de/decimal.d.mts", "default": "./de/decimal.mjs" }, "require": { "types": "./de/decimal.d.cts", "default": "./de/decimal.cjs" } }, "./de/digits": { "import": { "types": "./de/digits.d.mts", "default": "./de/digits.mjs" }, "require": { "types": "./de/digits.d.cts", "default": "./de/digits.cjs" } }, "./de/domain": { "import": { "types": "./de/domain.d.mts", "default": "./de/domain.mjs" }, "require": { "types": "./de/domain.d.cts", "default": "./de/domain.cjs" } }, "./de/email": { "import": { "types": "./de/email.d.mts", "default": "./de/email.mjs" }, "require": { "types": "./de/email.d.cts", "default": "./de/email.cjs" } }, "./de/emoji": { "import": { "types": "./de/emoji.d.mts", "default": "./de/emoji.mjs" }, "require": { "types": "./de/emoji.d.cts", "default": "./de/emoji.cjs" } }, "./de/empty": { "import": { "types": "./de/empty.d.mts", "default": "./de/empty.mjs" }, "require": { "types": "./de/empty.d.cts", "default": "./de/empty.cjs" } }, "./de/endsWith": { "import": { "types": "./de/endsWith.d.mts", "default": "./de/endsWith.mjs" }, "require": { "types": "./de/endsWith.d.cts", "default": "./de/endsWith.cjs" } }, "./de/entries": { "import": { "types": "./de/entries.d.mts", "default": "./de/entries.mjs" }, "require": { "types": "./de/entries.d.cts", "default": "./de/entries.cjs" } }, "./de/everyItem": { "import": { "types": "./de/everyItem.d.mts", "default": "./de/everyItem.mjs" }, "require": { "types": "./de/everyItem.d.cts", "default": "./de/everyItem.cjs" } }, "./de/excludes": { "import": { "types": "./de/excludes.d.mts", "default": "./de/excludes.mjs" }, "require": { "types": "./de/excludes.d.cts", "default": "./de/excludes.cjs" } }, "./de/finite": { "import": { "types": "./de/finite.d.mts", "default": "./de/finite.mjs" }, "require": { "types": "./de/finite.d.cts", "default": "./de/finite.cjs" } }, "./de/graphemes": { "import": { "types": "./de/graphemes.d.mts", "default": "./de/graphemes.mjs" }, "require": { "types": "./de/graphemes.d.cts", "default": "./de/graphemes.cjs" } }, "./de/gtValue": { "import": { "types": "./de/gtValue.d.mts", "default": "./de/gtValue.mjs" }, "require": { "types": "./de/gtValue.d.cts", "default": "./de/gtValue.cjs" } }, "./de/guard": { "import": { "types": "./de/guard.d.mts", "default": "./de/guard.mjs" }, "require": { "types": "./de/guard.d.cts", "default": "./de/guard.cjs" } }, "./de/hash": { "import": { "types": "./de/hash.d.mts", "default": "./de/hash.mjs" }, "require": { "types": "./de/hash.d.cts", "default": "./de/hash.cjs" } }, "./de/hexadecimal": { "import": { "types": "./de/hexadecimal.d.mts", "default": "./de/hexadecimal.mjs" }, "require": { "types": "./de/hexadecimal.d.cts", "default": "./de/hexadecimal.cjs" } }, "./de/hexColor": { "import": { "types": "./de/hexColor.d.mts", "default": "./de/hexColor.mjs" }, "require": { "types": "./de/hexColor.d.cts", "default": "./de/hexColor.cjs" } }, "./de/imei": { "import": { "types": "./de/imei.d.mts", "default": "./de/imei.mjs" }, "require": { "types": "./de/imei.d.cts", "default": "./de/imei.cjs" } }, "./de/includes": { "import": { "types": "./de/includes.d.mts", "default": "./de/includes.mjs" }, "require": { "types": "./de/includes.d.cts", "default": "./de/includes.cjs" } }, "./de/integer": { "import": { "types": "./de/integer.d.mts", "default": "./de/integer.mjs" }, "require": { "types": "./de/integer.d.cts", "default": "./de/integer.cjs" } }, "./de/ip": { "import": { "types": "./de/ip.d.mts", "default": "./de/ip.mjs" }, "require": { "types": "./de/ip.d.cts", "default": "./de/ip.cjs" } }, "./de/ipv4": { "import": { "types": "./de/ipv4.d.mts", "default": "./de/ipv4.mjs" }, "require": { "types": "./de/ipv4.d.cts", "default": "./de/ipv4.cjs" } }, "./de/ipv6": { "import": { "types": "./de/ipv6.d.mts", "default": "./de/ipv6.mjs" }, "require": { "types": "./de/ipv6.d.cts", "default": "./de/ipv6.cjs" } }, "./de/isbn": { "import": { "types": "./de/isbn.d.mts", "default": "./de/isbn.mjs" }, "require": { "types": "./de/isbn.d.cts", "default": "./de/isbn.cjs" } }, "./de/isoDate": { "import": { "types": "./de/isoDate.d.mts", "default": "./de/isoDate.mjs" }, "require": { "types": "./de/isoDate.d.cts", "default": "./de/isoDate.cjs" } }, "./de/isoDateTime": { "import": { "types": "./de/isoDateTime.d.mts", "default": "./de/isoDateTime.mjs" }, "require": { "types": "./de/isoDateTime.d.cts", "default": "./de/isoDateTime.cjs" } }, "./de/isoTime": { "import": { "types": "./de/isoTime.d.mts", "default": "./de/isoTime.mjs" }, "require": { "types": "./de/isoTime.d.cts", "default": "./de/isoTime.cjs" } }, "./de/isoTimeSecond": { "import": { "types": "./de/isoTimeSecond.d.mts", "default": "./de/isoTimeSecond.mjs" }, "require": { "types": "./de/isoTimeSecond.d.cts", "default": "./de/isoTimeSecond.cjs" } }, "./de/isoTimestamp": { "import": { "types": "./de/isoTimestamp.d.mts", "default": "./de/isoTimestamp.mjs" }, "require": { "types": "./de/isoTimestamp.d.cts", "default": "./de/isoTimestamp.cjs" } }, "./de/isoWeek": { "import": { "types": "./de/isoWeek.d.mts", "default": "./de/isoWeek.mjs" }, "require": { "types": "./de/isoWeek.d.cts", "default": "./de/isoWeek.cjs" } }, "./de/isrc": { "import": { "types": "./de/isrc.d.mts", "default": "./de/isrc.mjs" }, "require": { "types": "./de/isrc.d.cts", "default": "./de/isrc.cjs" } }, "./de/jwsCompact": { "import": { "types": "./de/jwsCompact.d.mts", "default": "./de/jwsCompact.mjs" }, "require": { "types": "./de/jwsCompact.d.cts", "default": "./de/jwsCompact.cjs" } }, "./de/length": { "import": { "types": "./de/length.d.mts", "default": "./de/length.mjs" }, "require": { "types": "./de/length.d.cts", "default": "./de/length.cjs" } }, "./de/ltValue": { "import": { "types": "./de/ltValue.d.mts", "default": "./de/ltValue.mjs" }, "require": { "types": "./de/ltValue.d.cts", "default": "./de/ltValue.cjs" } }, "./de/mac": { "import": { "types": "./de/mac.d.mts", "default": "./de/mac.mjs" }, "require": { "types": "./de/mac.d.cts", "default": "./de/mac.cjs" } }, "./de/mac48": { "import": { "types": "./de/mac48.d.mts", "default": "./de/mac48.mjs" }, "require": { "types": "./de/mac48.d.cts", "default": "./de/mac48.cjs" } }, "./de/mac64": { "import": { "types": "./de/mac64.d.mts", "default": "./de/mac64.mjs" }, "require": { "types": "./de/mac64.d.cts", "default": "./de/mac64.cjs" } }, "./de/maxBytes": { "import": { "types": "./de/maxBytes.d.mts", "default": "./de/maxBytes.mjs" }, "require": { "types": "./de/maxBytes.d.cts", "default": "./de/maxBytes.cjs" } }, "./de/maxEntries": { "import": { "types": "./de/maxEntries.d.mts", "default": "./de/maxEntries.mjs" }, "require": { "types": "./de/maxEntries.d.cts", "default": "./de/maxEntries.cjs" } }, "./de/maxGraphemes": { "import": { "types": "./de/maxGraphemes.d.mts", "default": "./de/maxGraphemes.mjs" }, "require": { "types": "./de/maxGraphemes.d.cts", "default": "./de/maxGraphemes.cjs" } }, "./de/maxLength": { "import": { "types": "./de/maxLength.d.mts", "default": "./de/maxLength.mjs" }, "require": { "types": "./de/maxLength.d.cts", "default": "./de/maxLength.cjs" } }, "./de/maxSize": { "import": { "types": "./de/maxSize.d.mts", "default": "./de/maxSize.mjs" }, "require": { "types": "./de/maxSize.d.cts", "default": "./de/maxSize.cjs" } }, "./de/maxValue": { "import": { "types": "./de/maxValue.d.mts", "default": "./de/maxValue.mjs" }, "require": { "types": "./de/maxValue.d.cts", "default": "./de/maxValue.cjs" } }, "./de/maxWords": { "import": { "types": "./de/maxWords.d.mts", "default": "./de/maxWords.mjs" }, "require": { "types": "./de/maxWords.d.cts", "default": "./de/maxWords.cjs" } }, "./de/mimeType": { "import": { "types": "./de/mimeType.d.mts", "default": "./de/mimeType.mjs" }, "require": { "types": "./de/mimeType.d.cts", "default": "./de/mimeType.cjs" } }, "./de/minBytes": { "import": { "types": "./de/minBytes.d.mts", "default": "./de/minBytes.mjs" }, "require": { "types": "./de/minBytes.d.cts", "default": "./de/minBytes.cjs" } }, "./de/minEntries": { "import": { "types": "./de/minEntries.d.mts", "default": "./de/minEntries.mjs" }, "require": { "types": "./de/minEntries.d.cts", "default": "./de/minEntries.cjs" } }, "./de/minGraphemes": { "import": { "types": "./de/minGraphemes.d.mts", "default": "./de/minGraphemes.mjs" }, "require": { "types": "./de/minGraphemes.d.cts", "default": "./de/minGraphemes.cjs" } }, "./de/minLength": { "import": { "types": "./de/minLength.d.mts", "default": "./de/minLength.mjs" }, "require": { "types": "./de/minLength.d.cts", "default": "./de/minLength.cjs" } }, "./de/minSize": { "import": { "types": "./de/minSize.d.mts", "default": "./de/minSize.mjs" }, "require": { "types": "./de/minSize.d.cts", "default": "./de/minSize.cjs" } }, "./de/minValue": { "import": { "types": "./de/minValue.d.mts", "default": "./de/minValue.mjs" }, "require": { "types": "./de/minValue.d.cts", "default": "./de/minValue.cjs" } }, "./de/minWords": { "import": { "types": "./de/minWords.d.mts", "default": "./de/minWords.mjs" }, "require": { "types": "./de/minWords.d.cts", "default": "./de/minWords.cjs" } }, "./de/multipleOf": { "import": { "types": "./de/multipleOf.d.mts", "default": "./de/multipleOf.mjs" }, "require": { "types": "./de/multipleOf.d.cts", "default": "./de/multipleOf.cjs" } }, "./de/nanoid": { "import": { "types": "./de/nanoid.d.mts", "default": "./de/nanoid.mjs" }, "require": { "types": "./de/nanoid.d.cts", "default": "./de/nanoid.cjs" } }, "./de/nonEmpty": { "import": { "types": "./de/nonEmpty.d.mts", "default": "./de/nonEmpty.mjs" }, "require": { "types": "./de/nonEmpty.d.cts", "default": "./de/nonEmpty.cjs" } }, "./de/notBytes": { "import": { "types": "./de/notBytes.d.mts", "default": "./de/notBytes.mjs" }, "require": { "types": "./de/notBytes.d.cts", "default": "./de/notBytes.cjs" } }, "./de/notEntries": { "import": { "types": "./de/notEntries.d.mts", "default": "./de/notEntries.mjs" }, "require": { "types": "./de/notEntries.d.cts", "default": "./de/notEntries.cjs" } }, "./de/notGraphemes": { "import": { "types": "./de/notGraphemes.d.mts", "default": "./de/notGraphemes.mjs" }, "require": { "types": "./de/notGraphemes.d.cts", "default": "./de/notGraphemes.cjs" } }, "./de/notLength": { "import": { "types": "./de/notLength.d.mts", "default": "./de/notLength.mjs" }, "require": { "types": "./de/notLength.d.cts", "default": "./de/notLength.cjs" } }, "./de/notSize": { "import": { "types": "./de/notSize.d.mts", "default": "./de/notSize.mjs" }, "require": { "types": "./de/notSize.d.cts", "default": "./de/notSize.cjs" } }, "./de/notValue": { "import": { "types": "./de/notValue.d.mts", "default": "./de/notValue.mjs" }, "require": { "types": "./de/notValue.d.cts", "default": "./de/notValue.cjs" } }, "./de/notValues": { "import": { "types": "./de/notValues.d.mts", "default": "./de/notValues.mjs" }, "require": { "types": "./de/notValues.d.cts", "default": "./de/notValues.cjs" } }, "./de/notWords": { "import": { "types": "./de/notWords.d.mts", "default": "./de/notWords.mjs" }, "require": { "types": "./de/notWords.d.cts", "default": "./de/notWords.cjs" } }, "./de/octal": { "import": { "types": "./de/octal.d.mts", "default": "./de/octal.mjs" }, "require": { "types": "./de/octal.d.cts", "default": "./de/octal.cjs" } }, "./de/parseBoolean": { "import": { "types": "./de/parseBoolean.d.mts", "default": "./de/parseBoolean.mjs" }, "require": { "types": "./de/parseBoolean.d.cts", "default": "./de/parseBoolean.cjs" } }, "./de/parseJson": { "import": { "types": "./de/parseJson.d.mts", "default": "./de/parseJson.mjs" }, "require": { "types": "./de/parseJson.d.cts", "default": "./de/parseJson.cjs" } }, "./de/partialCheck": { "import": { "types": "./de/partialCheck.d.mts", "default": "./de/partialCheck.mjs" }, "require": { "types": "./de/partialCheck.d.cts", "default": "./de/partialCheck.cjs" } }, "./de/rawCheck": { "import": { "types": "./de/rawCheck.d.mts", "default": "./de/rawCheck.mjs" }, "require": { "types": "./de/rawCheck.d.cts", "default": "./de/rawCheck.cjs" } }, "./de/rawTransform": { "import": { "types": "./de/rawTransform.d.mts", "default": "./de/rawTransform.mjs" }, "require": { "types": "./de/rawTransform.d.cts", "default": "./de/rawTransform.cjs" } }, "./de/regex": { "import": { "types": "./de/regex.d.mts", "default": "./de/regex.mjs" }, "require": { "types": "./de/regex.d.cts", "default": "./de/regex.cjs" } }, "./de/rfcEmail": { "import": { "types": "./de/rfcEmail.d.mts", "default": "./de/rfcEmail.mjs" }, "require": { "types": "./de/rfcEmail.d.cts", "default": "./de/rfcEmail.cjs" } }, "./de/safeInteger": { "import": { "types": "./de/safeInteger.d.mts", "default": "./de/safeInteger.mjs" }, "require": { "types": "./de/safeInteger.d.cts", "default": "./de/safeInteger.cjs" } }, "./de/size": { "import": { "types": "./de/size.d.mts", "default": "./de/size.mjs" }, "require": { "types": "./de/size.d.cts", "default": "./de/size.cjs" } }, "./de/slug": { "import": { "types": "./de/slug.d.mts", "default": "./de/slug.mjs" }, "require": { "types": "./de/slug.d.cts", "default": "./de/slug.cjs" } }, "./de/someItem": { "import": { "types": "./de/someItem.d.mts", "default": "./de/someItem.mjs" }, "require": { "types": "./de/someItem.d.cts", "default": "./de/someItem.cjs" } }, "./de/startsWith": { "import": { "types": "./de/startsWith.d.mts", "default": "./de/startsWith.mjs" }, "require": { "types": "./de/startsWith.d.cts", "default": "./de/startsWith.cjs" } }, "./de/stringifyJson": { "import": { "types": "./de/stringifyJson.d.mts", "default": "./de/stringifyJson.mjs" }, "require": { "types": "./de/stringifyJson.d.cts", "default": "./de/stringifyJson.cjs" } }, "./de/toBigint": { "import": { "types": "./de/toBigint.d.mts", "default": "./de/toBigint.mjs" }, "require": { "types": "./de/toBigint.d.cts", "default": "./de/toBigint.cjs" } }, "./de/toDate": { "import": { "types": "./de/toDate.d.mts", "default": "./de/toDate.mjs" }, "require": { "types": "./de/toDate.d.cts", "default": "./de/toDate.cjs" } }, "./de/toNumber": { "import": { "types": "./de/toNumber.d.mts", "default": "./de/toNumber.mjs" }, "require": { "types": "./de/toNumber.d.cts", "default": "./de/toNumber.cjs" } }, "./de/toString": { "import": { "types": "./de/toString.d.mts", "default": "./de/toString.mjs" }, "require": { "types": "./de/toString.d.cts", "default": "./de/toString.cjs" } }, "./de/ulid": { "import": { "types": "./de/ulid.d.mts", "default": "./de/ulid.mjs" }, "require": { "types": "./de/ulid.d.cts", "default": "./de/ulid.cjs" } }, "./de/url": { "import": { "types": "./de/url.d.mts", "default": "./de/url.mjs" }, "require": { "types": "./de/url.d.cts", "default": "./de/url.cjs" } }, "./de/uuid": { "import": { "types": "./de/uuid.d.mts", "default": "./de/uuid.mjs" }, "require": { "types": "./de/uuid.d.cts", "default": "./de/uuid.cjs" } }, "./de/value": { "import": { "types": "./de/value.d.mts", "default": "./de/value.mjs" }, "require": { "types": "./de/value.d.cts", "default": "./de/value.cjs" } }, "./de/values": { "import": { "types": "./de/values.d.mts", "default": "./de/values.mjs" }, "require": { "types": "./de/values.d.cts", "default": "./de/values.cjs" } }, "./de/words": { "import": { "types": "./de/words.d.mts", "default": "./de/words.mjs" }, "require": { "types": "./de/words.d.cts", "default": "./de/words.cjs" } }, "./el": { "import": { "types": "./el/index.d.mts", "default": "./el/index.mjs" }, "require": { "types": "./el/index.d.cts", "default": "./el/index.cjs" } }, "./el/schema": { "import": { "types": "./el/schema.d.mts", "default": "./el/schema.mjs" }, "require": { "types": "./el/schema.d.cts", "default": "./el/schema.cjs" } }, "./el/base64": { "import": { "types": "./el/base64.d.mts", "default": "./el/base64.mjs" }, "require": { "types": "./el/base64.d.cts", "default": "./el/base64.cjs" } }, "./el/bic": { "import": { "types": "./el/bic.d.mts", "default": "./el/bic.mjs" }, "require": { "types": "./el/bic.d.cts", "default": "./el/bic.cjs" } }, "./el/bytes": { "import": { "types": "./el/bytes.d.mts", "default": "./el/bytes.mjs" }, "require": { "types": "./el/bytes.d.cts", "default": "./el/bytes.cjs" } }, "./el/check": { "import": { "types": "./el/check.d.mts", "default": "./el/check.mjs" }, "require": { "types": "./el/check.d.cts", "default": "./el/check.cjs" } }, "./el/checkAsync": { "import": { "types": "./el/checkAsync.d.mts", "default": "./el/checkAsync.mjs" }, "require": { "types": "./el/checkAsync.d.cts", "default": "./el/checkAsync.cjs" } }, "./el/checkItems": { "import": { "types": "./el/checkItems.d.mts", "default": "./el/checkItems.mjs" }, "require": { "types": "./el/checkItems.d.cts", "default": "./el/checkItems.cjs" } }, "./el/checkItemsAsync": { "import": { "types": "./el/checkItemsAsync.d.mts", "default": "./el/checkItemsAsync.mjs" }, "require": { "types": "./el/checkItemsAsync.d.cts", "default": "./el/checkItemsAsync.cjs" } }, "./el/creditCard": { "import": { "types": "./el/creditCard.d.mts", "default": "./el/creditCard.mjs" }, "require": { "types": "./el/creditCard.d.cts", "default": "./el/creditCard.cjs" } }, "./el/cuid2": { "import": { "types": "./el/cuid2.d.mts", "default": "./el/cuid2.mjs" }, "require": { "types": "./el/cuid2.d.cts", "default": "./el/cuid2.cjs" } }, "./el/decimal": { "import": { "types": "./el/decimal.d.mts", "default": "./el/decimal.mjs" }, "require": { "types": "./el/decimal.d.cts", "default": "./el/decimal.cjs" } }, "./el/digits": { "import": { "types": "./el/digits.d.mts", "default": "./el/digits.mjs" }, "require": { "types": "./el/digits.d.cts", "default": "./el/digits.cjs" } }, "./el/domain": { "import": { "types": "./el/domain.d.mts", "default": "./el/domain.mjs" }, "require": { "types": "./el/domain.d.cts", "default": "./el/domain.cjs" } }, "./el/email": { "import": { "types": "./el/email.d.mts", "default": "./el/email.mjs" }, "require": { "types": "./el/email.d.cts", "default": "./el/email.cjs" } }, "./el/emoji": { "import": { "types": "./el/emoji.d.mts", "default": "./el/emoji.mjs" }, "require": { "types": "./el/emoji.d.cts", "default": "./el/emoji.cjs" } }, "./el/empty": { "import": { "types": "./el/empty.d.mts", "default": "./el/empty.mjs" }, "require": { "types": "./el/empty.d.cts", "default": "./el/empty.cjs" } }, "./el/endsWith": { "import": { "types": "./el/endsWith.d.mts", "default": "./el/endsWith.mjs" }, "require": { "types": "./el/endsWith.d.cts", "default": "./el/endsWith.cjs" } }, "./el/entries": { "import": { "types": "./el/entries.d.mts", "default": "./el/entries.mjs" }, "require": { "types": "./el/entries.d.cts", "default": "./el/entries.cjs" } }, "./el/everyItem": { "import": { "types": "./el/everyItem.d.mts", "default": "./el/everyItem.mjs" }, "require": { "types": "./el/everyItem.d.cts", "default": "./el/everyItem.cjs" } }, "./el/excludes": { "import": { "types": "./el/excludes.d.mts", "default": "./el/excludes.mjs" }, "require": { "types": "./el/excludes.d.cts", "default": "./el/excludes.cjs" } }, "./el/finite": { "import": { "types": "./el/finite.d.mts", "default": "./el/finite.mjs" }, "require": { "types": "./el/finite.d.cts", "default": "./el/finite.cjs" } }, "./el/graphemes": { "import": { "types": "./el/graphemes.d.mts", "default": "./el/graphemes.mjs" }, "require": { "types": "./el/graphemes.d.cts", "default": "./el/graphemes.cjs" } }, "./el/gtValue": { "import": { "types": "./el/gtValue.d.mts", "default": "./el/gtValue.mjs" }, "require": { "types": "./el/gtValue.d.cts", "default": "./el/gtValue.cjs" } }, "./el/guard": { "import": { "types": "./el/guard.d.mts", "default": "./el/guard.mjs" }, "require": { "types": "./el/guard.d.cts", "default": "./el/guard.cjs" } }, "./el/hash": { "import": { "types": "./el/hash.d.mts", "default": "./el/hash.mjs" }, "require": { "types": "./el/hash.d.cts", "default": "./el/hash.cjs" } }, "./el/hexadecimal": { "import": { "types": "./el/hexadecimal.d.mts", "default": "./el/hexadecimal.mjs" }, "require": { "types": "./el/hexadecimal.d.cts", "default": "./el/hexadecimal.cjs" } }, "./el/hexColor": { "import": { "types": "./el/hexColor.d.mts", "default": "./el/hexColor.mjs" }, "require": { "types": "./el/hexColor.d.cts", "default": "./el/hexColor.cjs" } }, "./el/imei": { "import": { "types": "./el/imei.d.mts", "default": "./el/imei.mjs" }, "require": { "types": "./el/imei.d.cts", "default": "./el/imei.cjs" } }, "./el/includes": { "import": { "types": "./el/includes.d.mts", "default": "./el/includes.mjs" }, "require": { "types": "./el/includes.d.cts", "default": "./el/includes.cjs" } }, "./el/integer": { "import": { "types": "./el/integer.d.mts", "default": "./el/integer.mjs" }, "require": { "types": "./el/integer.d.cts", "default": "./el/integer.cjs" } }, "./el/ip": { "import": { "types": "./el/ip.d.mts", "default": "./el/ip.mjs" }, "require": { "types": "./el/ip.d.cts", "default": "./el/ip.cjs" } }, "./el/ipv4": { "import": { "types": "./el/ipv4.d.mts", "default": "./el/ipv4.mjs" }, "require": { "types": "./el/ipv4.d.cts", "default": "./el/ipv4.cjs" } }, "./el/ipv6": { "import": { "types": "./el/ipv6.d.mts", "default": "./el/ipv6.mjs" }, "require": { "types": "./el/ipv6.d.cts", "default": "./el/ipv6.cjs" } }, "./el/isbn": { "import": { "types": "./el/isbn.d.mts", "default": "./el/isbn.mjs" }, "require": { "types": "./el/isbn.d.cts", "default": "./el/isbn.cjs" } }, "./el/isoDate": { "import": { "types": "./el/isoDate.d.mts", "default": "./el/isoDate.mjs" }, "require": { "types": "./el/isoDate.d.cts", "default": "./el/isoDate.cjs" } }, "./el/isoDateTime": { "import": { "types": "./el/isoDateTime.d.mts", "default": "./el/isoDateTime.mjs" }, "require": { "types": "./el/isoDateTime.d.cts", "default": "./el/isoDateTime.cjs" } }, "./el/isoTime": { "import": { "types": "./el/isoTime.d.mts", "default": "./el/isoTime.mjs" }, "require": { "types": "./el/isoTime.d.cts", "default": "./el/isoTime.cjs" } }, "./el/isoTimeSecond": { "import": { "types": "./el/isoTimeSecond.d.mts", "default": "./el/isoTimeSecond.mjs" }, "require": { "types": "./el/isoTimeSecond.d.cts", "default": "./el/isoTimeSecond.cjs" } }, "./el/isoTimestamp": { "import": { "types": "./el/isoTimestamp.d.mts", "default": "./el/isoTimestamp.mjs" }, "require": { "types": "./el/isoTimestamp.d.cts", "default": "./el/isoTimestamp.cjs" } }, "./el/isoWeek": { "import": { "types": "./el/isoWeek.d.mts", "default": "./el/isoWeek.mjs" }, "require": { "types": "./el/isoWeek.d.cts", "default": "./el/isoWeek.cjs" } }, "./el/isrc": { "import": { "types": "./el/isrc.d.mts", "default": "./el/isrc.mjs" }, "require": { "types": "./el/isrc.d.cts", "default": "./el/isrc.cjs" } }, "./el/jwsCompact": { "import": { "types": "./el/jwsCompact.d.mts", "default": "./el/jwsCompact.mjs" }, "require": { "types": "./el/jwsCompact.d.cts", "default": "./el/jwsCompact.cjs" } }, "./el/length": { "import": { "types": "./el/length.d.mts", "default": "./el/length.mjs" }, "require": { "types": "./el/length.d.cts", "default": "./el/length.cjs" } }, "./el/ltValue": { "import": { "types": "./el/ltValue.d.mts", "default": "./el/ltValue.mjs" }, "require": { "types": "./el/ltValue.d.cts", "default": "./el/ltValue.cjs" } }, "./el/mac": { "import": { "types": "./el/mac.d.mts", "default": "./el/mac.mjs" }, "require": { "types": "./el/mac.d.cts", "default": "./el/mac.cjs" } }, "./el/mac48": { "import": { "types": "./el/mac48.d.mts", "default": "./el/mac48.mjs" }, "require": { "types": "./el/mac48.d.cts", "default": "./el/mac48.cjs" } }, "./el/mac64": { "import": { "types": "./el/mac64.d.mts", "default": "./el/mac64.mjs" }, "require": { "types": "./el/mac64.d.cts", "default": "./el/mac64.cjs" } }, "./el/maxBytes": { "import": { "types": "./el/maxBytes.d.mts", "default": "./el/maxBytes.mjs" }, "require": { "types": "./el/maxBytes.d.cts", "default": "./el/maxBytes.cjs" } }, "./el/maxEntries": { "import": { "types": "./el/maxEntries.d.mts", "default": "./el/maxEntries.mjs" }, "require": { "types": "./el/maxEntries.d.cts", "default": "./el/maxEntries.cjs" } }, "./el/maxGraphemes": { "import": { "types": "./el/maxGraphemes.d.mts", "default": "./el/maxGraphemes.mjs" }, "require": { "types": "./el/maxGraphemes.d.cts", "default": "./el/maxGraphemes.cjs" } }, "./el/maxLength": { "import": { "types": "./el/maxLength.d.mts", "default": "./el/maxLength.mjs" }, "require": { "types": "./el/maxLength.d.cts", "default": "./el/maxLength.cjs" } }, "./el/maxSize": { "import": { "types": "./el/maxSize.d.mts", "default": "./el/maxSize.mjs" }, "require": { "types": "./el/maxSize.d.cts", "default": "./el/maxSize.cjs" } }, "./el/maxValue": { "import": { "types": "./el/maxValue.d.mts", "default": "./el/maxValue.mjs" }, "require": { "types": "./el/maxValue.d.cts", "default": "./el/maxValue.cjs" } }, "./el/maxWords": { "import": { "types": "./el/maxWords.d.mts", "default": "./el/maxWords.mjs" }, "require": { "types": "./el/maxWords.d.cts", "default": "./el/maxWords.cjs" } }, "./el/mimeType": { "import": { "types": "./el/mimeType.d.mts", "default": "./el/mimeType.mjs" }, "require": { "types": "./el/mimeType.d.cts", "default": "./el/mimeType.cjs" } }, "./el/minBytes": { "import": { "types": "./el/minBytes.d.mts", "default": "./el/minBytes.mjs" }, "require": { "types": "./el/minBytes.d.cts", "default": "./el/minBytes.cjs" } }, "./el/minEntries": { "import": { "types": "./el/minEntries.d.mts", "default": "./el/minEntries.mjs" }, "require": { "types": "./el/minEntries.d.cts", "default": "./el/minEntries.cjs" } }, "./el/minGraphemes": { "import": { "types": "./el/minGraphemes.d.mts", "default": "./el/minGraphemes.mjs" }, "require": { "types": "./el/minGraphemes.d.cts", "default": "./el/minGraphemes.cjs" } }, "./el/minLength": { "import": { "types": "./el/minLength.d.mts", "default": "./el/minLength.mjs" }, "require": { "types": "./el/minLength.d.cts", "default": "./el/minLength.cjs" } }, "./el/minSize": { "import": { "types": "./el/minSize.d.mts", "default": "./el/minSize.mjs" }, "require": { "types": "./el/minSize.d.cts", "default": "./el/minSize.cjs" } }, "./el/minValue": { "import": { "types": "./el/minValue.d.mts", "default": "./el/minValue.mjs" }, "require": { "types": "./el/minValue.d.cts", "default": "./el/minValue.cjs" } }, "./el/minWords": { "import": { "types": "./el/minWords.d.mts", "default": "./el/minWords.mjs" }, "require": { "types": "./el/minWords.d.cts", "default": "./el/minWords.cjs" } }, "./el/multipleOf": { "import": { "types": "./el/multipleOf.d.mts", "default": "./el/multipleOf.mjs" }, "require": { "types": "./el/multipleOf.d.cts", "default": "./el/multipleOf.cjs" } }, "./el/nanoid": { "import": { "types": "./el/nanoid.d.mts", "default": "./el/nanoid.mjs" }, "require": { "types": "./el/nanoid.d.cts", "default": "./el/nanoid.cjs" } }, "./el/nonEmpty": { "import": { "types": "./el/nonEmpty.d.mts", "default": "./el/nonEmpty.mjs" }, "require": { "types": "./el/nonEmpty.d.cts", "default": "./el/nonEmpty.cjs" } }, "./el/notBytes": { "import": { "types": "./el/notBytes.d.mts", "default": "./el/notBytes.mjs" }, "require": { "types": "./el/notBytes.d.cts", "default": "./el/notBytes.cjs" } }, "./el/notEntries": { "import": { "types": "./el/notEntries.d.mts", "default": "./el/notEntries.mjs" }, "require": { "types": "./el/notEntries.d.cts", "default": "./el/notEntries.cjs" } }, "./el/notGraphemes": { "import": { "types": "./el/notGraphemes.d.mts", "default": "./el/notGraphemes.mjs" }, "require": { "types": "./el/notGraphemes.d.cts", "default": "./el/notGraphemes.cjs" } }, "./el/notLength": { "import": { "types": "./el/notLength.d.mts", "default": "./el/notLength.mjs" }, "require": { "types": "./el/notLength.d.cts", "default": "./el/notLength.cjs" } }, "./el/notSize": { "import": { "types": "./el/notSize.d.mts", "default": "./el/notSize.mjs" }, "require": { "types": "./el/notSize.d.cts", "default": "./el/notSize.cjs" } }, "./el/notValue": { "import": { "types": "./el/notValue.d.mts", "default": "./el/notValue.mjs" }, "require": { "types": "./el/notValue.d.cts", "default": "./el/notValue.cjs" } }, "./el/notValues": { "import": { "types": "./el/notValues.d.mts", "default": "./el/notValues.mjs" }, "require": { "types": "./el/notValues.d.cts", "default": "./el/notValues.cjs" } }, "./el/notWords": { "import": { "types": "./el/notWords.d.mts", "default": "./el/notWords.mjs" }, "require": { "types": "./el/notWords.d.cts", "default": "./el/notWords.cjs" } }, "./el/octal": { "import": { "types": "./el/octal.d.mts", "default": "./el/octal.mjs" }, "require": { "types": "./el/octal.d.cts", "default": "./el/octal.cjs" } }, "./el/parseBoolean": { "import": { "types": "./el/parseBoolean.d.mts", "default": "./el/parseBoolean.mjs" }, "require": { "types": "./el/parseBoolean.d.cts", "default": "./el/parseBoolean.cjs" } }, "./el/parseJson": { "import": { "types": "./el/parseJson.d.mts", "default": "./el/parseJson.mjs" }, "require": { "types": "./el/parseJson.d.cts", "default": "./el/parseJson.cjs" } }, "./el/partialCheck": { "import": { "types": "./el/partialCheck.d.mts", "default": "./el/partialCheck.mjs" }, "require": { "types": "./el/partialCheck.d.cts", "default": "./el/partialCheck.cjs" } }, "./el/rawCheck": { "import": { "types": "./el/rawCheck.d.mts", "default": "./el/rawCheck.mjs" }, "require": { "types": "./el/rawCheck.d.cts", "default": "./el/rawCheck.cjs" } }, "./el/rawTransform": { "import": { "types": "./el/rawTransform.d.mts", "default": "./el/rawTransform.mjs" }, "require": { "types": "./el/rawTransform.d.cts", "default": "./el/rawTransform.cjs" } }, "./el/regex": { "import": { "types": "./el/regex.d.mts", "default": "./el/regex.mjs" }, "require": { "types": "./el/regex.d.cts", "default": "./el/regex.cjs" } }, "./el/rfcEmail": { "import": { "types": "./el/rfcEmail.d.mts", "default": "./el/rfcEmail.mjs" }, "require": { "types": "./el/rfcEmail.d.cts", "default": "./el/rfcEmail.cjs" } }, "./el/safeInteger": { "import": { "types": "./el/safeInteger.d.mts", "default": "./el/safeInteger.mjs" }, "require": { "types": "./el/safeInteger.d.cts", "default": "./el/safeInteger.cjs" } }, "./el/size": { "import": { "types": "./el/size.d.mts", "default": "./el/size.mjs" }, "require": { "types": "./el/size.d.cts", "default": "./el/size.cjs" } }, "./el/slug": { "import": { "types": "./el/slug.d.mts", "default": "./el/slug.mjs" }, "require": { "types": "./el/slug.d.cts", "default": "./el/slug.cjs" } }, "./el/someItem": { "import": { "types": "./el/someItem.d.mts", "default": "./el/someItem.mjs" }, "require": { "types": "./el/someItem.d.cts", "default": "./el/someItem.cjs" } }, "./el/startsWith": { "import": { "types": "./el/startsWith.d.mts", "default": "./el/startsWith.mjs" }, "require": { "types": "./el/startsWith.d.cts", "default": "./el/startsWith.cjs" } }, "./el/stringifyJson": { "import": { "types": "./el/stringifyJson.d.mts", "default": "./el/stringifyJson.mjs" }, "require": { "types": "./el/stringifyJson.d.cts", "default": "./el/stringifyJson.cjs" } }, "./el/toBigint": { "import": { "types": "./el/toBigint.d.mts", "default": "./el/toBigint.mjs" }, "require": { "types": "./el/toBigint.d.cts", "default": "./el/toBigint.cjs" } }, "./el/toDate": { "import": { "types": "./el/toDate.d.mts", "default": "./el/toDate.mjs" }, "require": { "types": "./el/toDate.d.cts", "default": "./el/toDate.cjs" } }, "./el/toNumber": { "import": { "types": "./el/toNumber.d.mts", "default": "./el/toNumber.mjs" }, "require": { "types": "./el/toNumber.d.cts", "default": "./el/toNumber.cjs" } }, "./el/toString": { "import": { "types": "./el/toString.d.mts", "default": "./el/toString.mjs" }, "require": { "types": "./el/toString.d.cts", "default": "./el/toString.cjs" } }, "./el/ulid": { "import": { "types": "./el/ulid.d.mts", "default": "./el/ulid.mjs" }, "require": { "types": "./el/ulid.d.cts", "default": "./el/ulid.cjs" } }, "./el/url": { "import": { "types": "./el/url.d.mts", "default": "./el/url.mjs" }, "require": { "types": "./el/url.d.cts", "default": "./el/url.cjs" } }, "./el/uuid": { "import": { "types": "./el/uuid.d.mts", "default": "./el/uuid.mjs" }, "require": { "types": "./el/uuid.d.cts", "default": "./el/uuid.cjs" } }, "./el/value": { "import": { "types": "./el/value.d.mts", "default": "./el/value.mjs" }, "require": { "types": "./el/value.d.cts", "default": "./el/value.cjs" } }, "./el/values": { "import": { "types": "./el/values.d.mts", "default": "./el/values.mjs" }, "require": { "types": "./el/values.d.cts", "default": "./el/values.cjs" } }, "./el/words": { "import": { "types": "./el/words.d.mts", "default": "./el/words.mjs" }, "require": { "types": "./el/words.d.cts", "default": "./el/words.cjs" } }, "./es": { "import": { "types": "./es/index.d.mts", "default": "./es/index.mjs" }, "require": { "types": "./es/index.d.cts", "default": "./es/index.cjs" } }, "./es/schema": { "import": { "types": "./es/schema.d.mts", "default": "./es/schema.mjs" }, "require": { "types": "./es/schema.d.cts", "default": "./es/schema.cjs" } }, "./es/base64": { "import": { "types": "./es/base64.d.mts", "default": "./es/base64.mjs" }, "require": { "types": "./es/base64.d.cts", "default": "./es/base64.cjs" } }, "./es/bic": { "import": { "types": "./es/bic.d.mts", "default": "./es/bic.mjs" }, "require": { "types": "./es/bic.d.cts", "default": "./es/bic.cjs" } }, "./es/bytes": { "import": { "types": "./es/bytes.d.mts", "default": "./es/bytes.mjs" }, "require": { "types": "./es/bytes.d.cts", "default": "./es/bytes.cjs" } }, "./es/check": { "import": { "types": "./es/check.d.mts", "default": "./es/check.mjs" }, "require": { "types": "./es/check.d.cts", "default": "./es/check.cjs" } }, "./es/checkAsync": { "import": { "types": "./es/checkAsync.d.mts", "default": "./es/checkAsync.mjs" }, "require": { "types": "./es/checkAsync.d.cts", "default": "./es/checkAsync.cjs" } }, "./es/checkItems": { "import": { "types": "./es/checkItems.d.mts", "default": "./es/checkItems.mjs" }, "require": { "types": "./es/checkItems.d.cts", "default": "./es/checkItems.cjs" } }, "./es/checkItemsAsync": { "import": { "types": "./es/checkItemsAsync.d.mts", "default": "./es/checkItemsAsync.mjs" }, "require": { "types": "./es/checkItemsAsync.d.cts", "default": "./es/checkItemsAsync.cjs" } }, "./es/creditCard": { "import": { "types": "./es/creditCard.d.mts", "default": "./es/creditCard.mjs" }, "require": { "types": "./es/creditCard.d.cts", "default": "./es/creditCard.cjs" } }, "./es/cuid2": { "import": { "types": "./es/cuid2.d.mts", "default": "./es/cuid2.mjs" }, "require": { "types": "./es/cuid2.d.cts", "default": "./es/cuid2.cjs" } }, "./es/decimal": { "import": { "types": "./es/decimal.d.mts", "default": "./es/decimal.mjs" }, "require": { "types": "./es/decimal.d.cts", "default": "./es/decimal.cjs" } }, "./es/digits": { "import": { "types": "./es/digits.d.mts", "default": "./es/digits.mjs" }, "require": { "types": "./es/digits.d.cts", "default": "./es/digits.cjs" } }, "./es/domain": { "import": { "types": "./es/domain.d.mts", "default": "./es/domain.mjs" }, "require": { "types": "./es/domain.d.cts", "default": "./es/domain.cjs" } }, "./es/email": { "import": { "types": "./es/email.d.mts", "default": "./es/email.mjs" }, "require": { "types": "./es/email.d.cts", "default": "./es/email.cjs" } }, "./es/emoji": { "import": { "types": "./es/emoji.d.mts", "default": "./es/emoji.mjs" }, "require": { "types": "./es/emoji.d.cts", "default": "./es/emoji.cjs" } }, "./es/empty": { "import": { "types": "./es/empty.d.mts", "default": "./es/empty.mjs" }, "require": { "types": "./es/empty.d.cts", "default": "./es/empty.cjs" } }, "./es/endsWith": { "import": { "types": "./es/endsWith.d.mts", "default": "./es/endsWith.mjs" }, "require": { "types": "./es/endsWith.d.cts", "default": "./es/endsWith.cjs" } }, "./es/entries": { "import": { "types": "./es/entries.d.mts", "default": "./es/entries.mjs" }, "require": { "types": "./es/entries.d.cts", "default": "./es/entries.cjs" } }, "./es/everyItem": { "import": { "types": "./es/everyItem.d.mts", "default": "./es/everyItem.mjs" }, "require": { "types": "./es/everyItem.d.cts", "default": "./es/everyItem.cjs" } }, "./es/excludes": { "import": { "types": "./es/excludes.d.mts", "default": "./es/excludes.mjs" }, "require": { "types": "./es/excludes.d.cts", "default": "./es/excludes.cjs" } }, "./es/finite": { "import": { "types": "./es/finite.d.mts", "default": "./es/finite.mjs" }, "require": { "types": "./es/finite.d.cts", "default": "./es/finite.cjs" } }, "./es/graphemes": { "import": { "types": "./es/graphemes.d.mts", "default": "./es/graphemes.mjs" }, "require": { "types": "./es/graphemes.d.cts", "default": "./es/graphemes.cjs" } }, "./es/gtValue": { "import": { "types": "./es/gtValue.d.mts", "default": "./es/gtValue.mjs" }, "require": { "types": "./es/gtValue.d.cts", "default": "./es/gtValue.cjs" } }, "./es/guard": { "import": { "types": "./es/guard.d.mts", "default": "./es/guard.mjs" }, "require": { "types": "./es/guard.d.cts", "default": "./es/guard.cjs" } }, "./es/hash": { "import": { "types": "./es/hash.d.mts", "default": "./es/hash.mjs" }, "require": { "types": "./es/hash.d.cts", "default": "./es/hash.cjs" } }, "./es/hexadecimal": { "import": { "types": "./es/hexadecimal.d.mts", "default": "./es/hexadecimal.mjs" }, "require": { "types": "./es/hexadecimal.d.cts", "default": "./es/hexadecimal.cjs" } }, "./es/hexColor": { "import": { "types": "./es/hexColor.d.mts", "default": "./es/hexColor.mjs" }, "require": { "types": "./es/hexColor.d.cts", "default": "./es/hexColor.cjs" } }, "./es/imei": { "import": { "types": "./es/imei.d.mts", "default": "./es/imei.mjs" }, "require": { "types": "./es/imei.d.cts", "default": "./es/imei.cjs" } }, "./es/includes": { "import": { "types": "./es/includes.d.mts", "default": "./es/includes.mjs" }, "require": { "types": "./es/includes.d.cts", "default": "./es/includes.cjs" } }, "./es/integer": { "import": { "types": "./es/integer.d.mts", "default": "./es/integer.mjs" }, "require": { "types": "./es/integer.d.cts", "default": "./es/integer.cjs" } }, "./es/ip": { "import": { "types": "./es/ip.d.mts", "default": "./es/ip.mjs" }, "require": { "types": "./es/ip.d.cts", "default": "./es/ip.cjs" } }, "./es/ipv4": { "import": { "types": "./es/ipv4.d.mts", "default": "./es/ipv4.mjs" }, "require": { "types": "./es/ipv4.d.cts", "default": "./es/ipv4.cjs" } }, "./es/ipv6": { "import": { "types": "./es/ipv6.d.mts", "default": "./es/ipv6.mjs" }, "require": { "types": "./es/ipv6.d.cts", "default": "./es/ipv6.cjs" } }, "./es/isbn": { "import": { "types": "./es/isbn.d.mts", "default": "./es/isbn.mjs" }, "require": { "types": "./es/isbn.d.cts", "default": "./es/isbn.cjs" } }, "./es/isoDate": { "import": { "types": "./es/isoDate.d.mts", "default": "./es/isoDate.mjs" }, "require": { "types": "./es/isoDate.d.cts", "default": "./es/isoDate.cjs" } }, "./es/isoDateTime": { "import": { "types": "./es/isoDateTime.d.mts", "default": "./es/isoDateTime.mjs" }, "require": { "types": "./es/isoDateTime.d.cts", "default": "./es/isoDateTime.cjs" } }, "./es/isoTime": { "import": { "types": "./es/isoTime.d.mts", "default": "./es/isoTime.mjs" }, "require": { "types": "./es/isoTime.d.cts", "default": "./es/isoTime.cjs" } }, "./es/isoTimeSecond": { "import": { "types": "./es/isoTimeSecond.d.mts", "default": "./es/isoTimeSecond.mjs" }, "require": { "types": "./es/isoTimeSecond.d.cts", "default": "./es/isoTimeSecond.cjs" } }, "./es/isoTimestamp": { "import": { "types": "./es/isoTimestamp.d.mts", "default": "./es/isoTimestamp.mjs" }, "require": { "types": "./es/isoTimestamp.d.cts", "default": "./es/isoTimestamp.cjs" } }, "./es/isoWeek": { "import": { "types": "./es/isoWeek.d.mts", "default": "./es/isoWeek.mjs" }, "require": { "types": "./es/isoWeek.d.cts", "default": "./es/isoWeek.cjs" } }, "./es/isrc": { "import": { "types": "./es/isrc.d.mts", "default": "./es/isrc.mjs" }, "require": { "types": "./es/isrc.d.cts", "default": "./es/isrc.cjs" } }, "./es/jwsCompact": { "import": { "types": "./es/jwsCompact.d.mts", "default": "./es/jwsCompact.mjs" }, "require": { "types": "./es/jwsCompact.d.cts", "default": "./es/jwsCompact.cjs" } }, "./es/length": { "import": { "types": "./es/length.d.mts", "default": "./es/length.mjs" }, "require": { "types": "./es/length.d.cts", "default": "./es/length.cjs" } }, "./es/ltValue": { "import": { "types": "./es/ltValue.d.mts", "default": "./es/ltValue.mjs" }, "require": { "types": "./es/ltValue.d.cts", "default": "./es/ltValue.cjs" } }, "./es/mac": { "import": { "types": "./es/mac.d.mts", "default": "./es/mac.mjs" }, "require": { "types": "./es/mac.d.cts", "default": "./es/mac.cjs" } }, "./es/mac48": { "import": { "types": "./es/mac48.d.mts", "default": "./es/mac48.mjs" }, "require": { "types": "./es/mac48.d.cts", "default": "./es/mac48.cjs" } }, "./es/mac64": { "import": { "types": "./es/mac64.d.mts", "default": "./es/mac64.mjs" }, "require": { "types": "./es/mac64.d.cts", "default": "./es/mac64.cjs" } }, "./es/maxBytes": { "import": { "types": "./es/maxBytes.d.mts", "default": "./es/maxBytes.mjs" }, "require": { "types": "./es/maxBytes.d.cts", "default": "./es/maxBytes.cjs" } }, "./es/maxEntries": { "import": { "types": "./es/maxEntries.d.mts", "default": "./es/maxEntries.mjs" }, "require": { "types": "./es/maxEntries.d.cts", "default": "./es/maxEntries.cjs" } }, "./es/maxGraphemes": { "import": { "types": "./es/maxGraphemes.d.mts", "default": "./es/maxGraphemes.mjs" }, "require": { "types": "./es/maxGraphemes.d.cts", "default": "./es/maxGraphemes.cjs" } }, "./es/maxLength": { "import": { "types": "./es/maxLength.d.mts", "default": "./es/maxLength.mjs" }, "require": { "types": "./es/maxLength.d.cts", "default": "./es/maxLength.cjs" } }, "./es/maxSize": { "import": { "types": "./es/maxSize.d.mts", "default": "./es/maxSize.mjs" }, "require": { "types": "./es/maxSize.d.cts", "default": "./es/maxSize.cjs" } }, "./es/maxValue": { "import": { "types": "./es/maxValue.d.mts", "default": "./es/maxValue.mjs" }, "require": { "types": "./es/maxValue.d.cts", "default": "./es/maxValue.cjs" } }, "./es/maxWords": { "import": { "types": "./es/maxWords.d.mts", "default": "./es/maxWords.mjs" }, "require": { "types": "./es/maxWords.d.cts", "default": "./es/maxWords.cjs" } }, "./es/mimeType": { "import": { "types": "./es/mimeType.d.mts", "default": "./es/mimeType.mjs" }, "require": { "types": "./es/mimeType.d.cts", "default": "./es/mimeType.cjs" } }, "./es/minBytes": { "import": { "types": "./es/minBytes.d.mts", "default": "./es/minBytes.mjs" }, "require": { "types": "./es/minBytes.d.cts", "default": "./es/minBytes.cjs" } }, "./es/minEntries": { "import": { "types": "./es/minEntries.d.mts", "default": "./es/minEntries.mjs" }, "require": { "types": "./es/minEntries.d.cts", "default": "./es/minEntries.cjs" } }, "./es/minGraphemes": { "import": { "types": "./es/minGraphemes.d.mts", "default": "./es/minGraphemes.mjs" }, "require": { "types": "./es/minGraphemes.d.cts", "default": "./es/minGraphemes.cjs" } }, "./es/minLength": { "import": { "types": "./es/minLength.d.mts", "default": "./es/minLength.mjs" }, "require": { "types": "./es/minLength.d.cts", "default": "./es/minLength.cjs" } }, "./es/minSize": { "import": { "types": "./es/minSize.d.mts", "default": "./es/minSize.mjs" }, "require": { "types": "./es/minSize.d.cts", "default": "./es/minSize.cjs" } }, "./es/minValue": { "import": { "types": "./es/minValue.d.mts", "default": "./es/minValue.mjs" }, "require": { "types": "./es/minValue.d.cts", "default": "./es/minValue.cjs" } }, "./es/minWords": { "import": { "types": "./es/minWords.d.mts", "default": "./es/minWords.mjs" }, "require": { "types": "./es/minWords.d.cts", "default": "./es/minWords.cjs" } }, "./es/multipleOf": { "import": { "types": "./es/multipleOf.d.mts", "default": "./es/multipleOf.mjs" }, "require": { "types": "./es/multipleOf.d.cts", "default": "./es/multipleOf.cjs" } }, "./es/nanoid": { "import": { "types": "./es/nanoid.d.mts", "default": "./es/nanoid.mjs" }, "require": { "types": "./es/nanoid.d.cts", "default": "./es/nanoid.cjs" } }, "./es/nonEmpty": { "import": { "types": "./es/nonEmpty.d.mts", "default": "./es/nonEmpty.mjs" }, "require": { "types": "./es/nonEmpty.d.cts", "default": "./es/nonEmpty.cjs" } }, "./es/notBytes": { "import": { "types": "./es/notBytes.d.mts", "default": "./es/notBytes.mjs" }, "require": { "types": "./es/notBytes.d.cts", "default": "./es/notBytes.cjs" } }, "./es/notEntries": { "import": { "types": "./es/notEntries.d.mts", "default": "./es/notEntries.mjs" }, "require": { "types": "./es/notEntries.d.cts", "default": "./es/notEntries.cjs" } }, "./es/notGraphemes": { "import": { "types": "./es/notGraphemes.d.mts", "default": "./es/notGraphemes.mjs" }, "require": { "types": "./es/notGraphemes.d.cts", "default": "./es/notGraphemes.cjs" } }, "./es/notLength": { "import": { "types": "./es/notLength.d.mts", "default": "./es/notLength.mjs" }, "require": { "types": "./es/notLength.d.cts", "default": "./es/notLength.cjs" } }, "./es/notSize": { "import": { "types": "./es/notSize.d.mts", "default": "./es/notSize.mjs" }, "require": { "types": "./es/notSize.d.cts", "default": "./es/notSize.cjs" } }, "./es/notValue": { "import": { "types": "./es/notValue.d.mts", "default": "./es/notValue.mjs" }, "require": { "types": "./es/notValue.d.cts", "default": "./es/notValue.cjs" } }, "./es/notValues": { "import": { "types": "./es/notValues.d.mts", "default": "./es/notValues.mjs" }, "require": { "types": "./es/notValues.d.cts", "default": "./es/notValues.cjs" } }, "./es/notWords": { "import": { "types": "./es/notWords.d.mts", "default": "./es/notWords.mjs" }, "require": { "types": "./es/notWords.d.cts", "default": "./es/notWords.cjs" } }, "./es/octal": { "import": { "types": "./es/octal.d.mts", "default": "./es/octal.mjs" }, "require": { "types": "./es/octal.d.cts", "default": "./es/octal.cjs" } }, "./es/parseBoolean": { "import": { "types": "./es/parseBoolean.d.mts", "default": "./es/parseBoolean.mjs" }, "require": { "types": "./es/parseBoolean.d.cts", "default": "./es/parseBoolean.cjs" } }, "./es/parseJson": { "import": { "types": "./es/parseJson.d.mts", "default": "./es/parseJson.mjs" }, "require": { "types": "./es/parseJson.d.cts", "default": "./es/parseJson.cjs" } }, "./es/partialCheck": { "import": { "types": "./es/partialCheck.d.mts", "default": "./es/partialCheck.mjs" }, "require": { "types": "./es/partialCheck.d.cts", "default": "./es/partialCheck.cjs" } }, "./es/rawCheck": { "import": { "types": "./es/rawCheck.d.mts", "default": "./es/rawCheck.mjs" }, "require": { "types": "./es/rawCheck.d.cts", "default": "./es/rawCheck.cjs" } }, "./es/rawTransform": { "import": { "types": "./es/rawTransform.d.mts", "default": "./es/rawTransform.mjs" }, "require": { "types": "./es/rawTransform.d.cts", "default": "./es/rawTransform.cjs" } }, "./es/regex": { "import": { "types": "./es/regex.d.mts", "default": "./es/regex.mjs" }, "require": { "types": "./es/regex.d.cts", "default": "./es/regex.cjs" } }, "./es/rfcEmail": { "import": { "types": "./es/rfcEmail.d.mts", "default": "./es/rfcEmail.mjs" }, "require": { "types": "./es/rfcEmail.d.cts", "default": "./es/rfcEmail.cjs" } }, "./es/safeInteger": { "import": { "types": "./es/safeInteger.d.mts", "default": "./es/safeInteger.mjs" }, "require": { "types": "./es/safeInteger.d.cts", "default": "./es/safeInteger.cjs" } }, "./es/size": { "import": { "types": "./es/size.d.mts", "default": "./es/size.mjs" }, "require": { "types": "./es/size.d.cts", "default": "./es/size.cjs" } }, "./es/slug": { "import": { "types": "./es/slug.d.mts", "default": "./es/slug.mjs" }, "require": { "types": "./es/slug.d.cts", "default": "./es/slug.cjs" } }, "./es/someItem": { "import": { "types": "./es/someItem.d.mts", "default": "./es/someItem.mjs" }, "require": { "types": "./es/someItem.d.cts", "default": "./es/someItem.cjs" } }, "./es/startsWith": { "import": { "types": "./es/startsWith.d.mts", "default": "./es/startsWith.mjs" }, "require": { "types": "./es/startsWith.d.cts", "default": "./es/startsWith.cjs" } }, "./es/stringifyJson": { "import": { "types": "./es/stringifyJson.d.mts", "default": "./es/stringifyJson.mjs" }, "require": { "types": "./es/stringifyJson.d.cts", "default": "./es/stringifyJson.cjs" } }, "./es/toBigint": { "import": { "types": "./es/toBigint.d.mts", "default": "./es/toBigint.mjs" }, "require": { "types": "./es/toBigint.d.cts", "default": "./es/toBigint.cjs" } }, "./es/toDate": { "import": { "types": "./es/toDate.d.mts", "default": "./es/toDate.mjs" }, "require": { "types": "./es/toDate.d.cts", "default": "./es/toDate.cjs" } }, "./es/toNumber": { "import": { "types": "./es/toNumber.d.mts", "default": "./es/toNumber.mjs" }, "require": { "types": "./es/toNumber.d.cts", "default": "./es/toNumber.cjs" } }, "./es/toString": { "import": { "types": "./es/toString.d.mts", "default": "./es/toString.mjs" }, "require": { "types": "./es/toString.d.cts", "default": "./es/toString.cjs" } }, "./es/ulid": { "import": { "types": "./es/ulid.d.mts", "default": "./es/ulid.mjs" }, "require": { "types": "./es/ulid.d.cts", "default": "./es/ulid.cjs" } }, "./es/url": { "import": { "types": "./es/url.d.mts", "default": "./es/url.mjs" }, "require": { "types": "./es/url.d.cts", "default": "./es/url.cjs" } }, "./es/uuid": { "import": { "types": "./es/uuid.d.mts", "default": "./es/uuid.mjs" }, "require": { "types": "./es/uuid.d.cts", "default": "./es/uuid.cjs" } }, "./es/value": { "import": { "types": "./es/value.d.mts", "default": "./es/value.mjs" }, "require": { "types": "./es/value.d.cts", "default": "./es/value.cjs" } }, "./es/values": { "import": { "types": "./es/values.d.mts", "default": "./es/values.mjs" }, "require": { "types": "./es/values.d.cts", "default": "./es/values.cjs" } }, "./es/words": { "import": { "types": "./es/words.d.mts", "default": "./es/words.mjs" }, "require": { "types": "./es/words.d.cts", "default": "./es/words.cjs" } }, "./fa": { "import": { "types": "./fa/index.d.mts", "default": "./fa/index.mjs" }, "require": { "types": "./fa/index.d.cts", "default": "./fa/index.cjs" } }, "./fa/schema": { "import": { "types": "./fa/schema.d.mts", "default": "./fa/schema.mjs" }, "require": { "types": "./fa/schema.d.cts", "default": "./fa/schema.cjs" } }, "./fa/base64": { "import": { "types": "./fa/base64.d.mts", "default": "./fa/base64.mjs" }, "require": { "types": "./fa/base64.d.cts", "default": "./fa/base64.cjs" } }, "./fa/bic": { "import": { "types": "./fa/bic.d.mts", "default": "./fa/bic.mjs" }, "require": { "types": "./fa/bic.d.cts", "default": "./fa/bic.cjs" } }, "./fa/bytes": { "import": { "types": "./fa/bytes.d.mts", "default": "./fa/bytes.mjs" }, "require": { "types": "./fa/bytes.d.cts", "default": "./fa/bytes.cjs" } }, "./fa/check": { "import": { "types": "./fa/check.d.mts", "default": "./fa/check.mjs" }, "require": { "types": "./fa/check.d.cts", "default": "./fa/check.cjs" } }, "./fa/checkAsync": { "import": { "types": "./fa/checkAsync.d.mts", "default": "./fa/checkAsync.mjs" }, "require": { "types": "./fa/checkAsync.d.cts", "default": "./fa/checkAsync.cjs" } }, "./fa/checkItems": { "import": { "types": "./fa/checkItems.d.mts", "default": "./fa/checkItems.mjs" }, "require": { "types": "./fa/checkItems.d.cts", "default": "./fa/checkItems.cjs" } }, "./fa/checkItemsAsync": { "import": { "types": "./fa/checkItemsAsync.d.mts", "default": "./fa/checkItemsAsync.mjs" }, "require": { "types": "./fa/checkItemsAsync.d.cts", "default": "./fa/checkItemsAsync.cjs" } }, "./fa/creditCard": { "import": { "types": "./fa/creditCard.d.mts", "default": "./fa/creditCard.mjs" }, "require": { "types": "./fa/creditCard.d.cts", "default": "./fa/creditCard.cjs" } }, "./fa/cuid2": { "import": { "types": "./fa/cuid2.d.mts", "default": "./fa/cuid2.mjs" }, "require": { "types": "./fa/cuid2.d.cts", "default": "./fa/cuid2.cjs" } }, "./fa/decimal": { "import": { "types": "./fa/decimal.d.mts", "default": "./fa/decimal.mjs" }, "require": { "types": "./fa/decimal.d.cts", "default": "./fa/decimal.cjs" } }, "./fa/digits": { "import": { "types": "./fa/digits.d.mts", "default": "./fa/digits.mjs" }, "require": { "types": "./fa/digits.d.cts", "default": "./fa/digits.cjs" } }, "./fa/domain": { "import": { "types": "./fa/domain.d.mts", "default": "./fa/domain.mjs" }, "require": { "types": "./fa/domain.d.cts", "default": "./fa/domain.cjs" } }, "./fa/email": { "import": { "types": "./fa/email.d.mts", "default": "./fa/email.mjs" }, "require": { "types": "./fa/email.d.cts", "default": "./fa/email.cjs" } }, "./fa/emoji": { "import": { "types": "./fa/emoji.d.mts", "default": "./fa/emoji.mjs" }, "require": { "types": "./fa/emoji.d.cts", "default": "./fa/emoji.cjs" } }, "./fa/empty": { "import": { "types": "./fa/empty.d.mts", "default": "./fa/empty.mjs" }, "require": { "types": "./fa/empty.d.cts", "default": "./fa/empty.cjs" } }, "./fa/endsWith": { "import": { "types": "./fa/endsWith.d.mts", "default": "./fa/endsWith.mjs" }, "require": { "types": "./fa/endsWith.d.cts", "default": "./fa/endsWith.cjs" } }, "./fa/entries": { "import": { "types": "./fa/entries.d.mts", "default": "./fa/entries.mjs" }, "require": { "types": "./fa/entries.d.cts", "default": "./fa/entries.cjs" } }, "./fa/everyItem": { "import": { "types": "./fa/everyItem.d.mts", "default": "./fa/everyItem.mjs" }, "require": { "types": "./fa/everyItem.d.cts", "default": "./fa/everyItem.cjs" } }, "./fa/excludes": { "import": { "types": "./fa/excludes.d.mts", "default": "./fa/excludes.mjs" }, "require": { "types": "./fa/excludes.d.cts", "default": "./fa/excludes.cjs" } }, "./fa/finite": { "import": { "types": "./fa/finite.d.mts", "default": "./fa/finite.mjs" }, "require": { "types": "./fa/finite.d.cts", "default": "./fa/finite.cjs" } }, "./fa/graphemes": { "import": { "types": "./fa/graphemes.d.mts", "default": "./fa/graphemes.mjs" }, "require": { "types": "./fa/graphemes.d.cts", "default": "./fa/graphemes.cjs" } }, "./fa/gtValue": { "import": { "types": "./fa/gtValue.d.mts", "default": "./fa/gtValue.mjs" }, "require": { "types": "./fa/gtValue.d.cts", "default": "./fa/gtValue.cjs" } }, "./fa/guard": { "import": { "types": "./fa/guard.d.mts", "default": "./fa/guard.mjs" }, "require": { "types": "./fa/guard.d.cts", "default": "./fa/guard.cjs" } }, "./fa/hash": { "import": { "types": "./fa/hash.d.mts", "default": "./fa/hash.mjs" }, "require": { "types": "./fa/hash.d.cts", "default": "./fa/hash.cjs" } }, "./fa/hexadecimal": { "import": { "types": "./fa/hexadecimal.d.mts", "default": "./fa/hexadecimal.mjs" }, "require": { "types": "./fa/hexadecimal.d.cts", "default": "./fa/hexadecimal.cjs" } }, "./fa/hexColor": { "import": { "types": "./fa/hexColor.d.mts", "default": "./fa/hexColor.mjs" }, "require": { "types": "./fa/hexColor.d.cts", "default": "./fa/hexColor.cjs" } }, "./fa/imei": { "import": { "types": "./fa/imei.d.mts", "default": "./fa/imei.mjs" }, "require": { "types": "./fa/imei.d.cts", "default": "./fa/imei.cjs" } }, "./fa/includes": { "import": { "types": "./fa/includes.d.mts", "default": "./fa/includes.mjs" }, "require": { "types": "./fa/includes.d.cts", "default": "./fa/includes.cjs" } }, "./fa/integer": { "import": { "types": "./fa/integer.d.mts", "default": "./fa/integer.mjs" }, "require": { "types": "./fa/integer.d.cts", "default": "./fa/integer.cjs" } }, "./fa/ip": { "import": { "types": "./fa/ip.d.mts", "default": "./fa/ip.mjs" }, "require": { "types": "./fa/ip.d.cts", "default": "./fa/ip.cjs" } }, "./fa/ipv4": { "import": { "types": "./fa/ipv4.d.mts", "default": "./fa/ipv4.mjs" }, "require": { "types": "./fa/ipv4.d.cts", "default": "./fa/ipv4.cjs" } }, "./fa/ipv6": { "import": { "types": "./fa/ipv6.d.mts", "default": "./fa/ipv6.mjs" }, "require": { "types": "./fa/ipv6.d.cts", "default": "./fa/ipv6.cjs" } }, "./fa/isbn": { "import": { "types": "./fa/isbn.d.mts", "default": "./fa/isbn.mjs" }, "require": { "types": "./fa/isbn.d.cts", "default": "./fa/isbn.cjs" } }, "./fa/isoDate": { "import": { "types": "./fa/isoDate.d.mts", "default": "./fa/isoDate.mjs" }, "require": { "types": "./fa/isoDate.d.cts", "default": "./fa/isoDate.cjs" } }, "./fa/isoDateTime": { "import": { "types": "./fa/isoDateTime.d.mts", "default": "./fa/isoDateTime.mjs" }, "require": { "types": "./fa/isoDateTime.d.cts", "default": "./fa/isoDateTime.cjs" } }, "./fa/isoTime": { "import": { "types": "./fa/isoTime.d.mts", "default": "./fa/isoTime.mjs" }, "require": { "types": "./fa/isoTime.d.cts", "default": "./fa/isoTime.cjs" } }, "./fa/isoTimeSecond": { "import": { "types": "./fa/isoTimeSecond.d.mts", "default": "./fa/isoTimeSecond.mjs" }, "require": { "types": "./fa/isoTimeSecond.d.cts", "default": "./fa/isoTimeSecond.cjs" } }, "./fa/isoTimestamp": { "import": { "types": "./fa/isoTimestamp.d.mts", "default": "./fa/isoTimestamp.mjs" }, "require": { "types": "./fa/isoTimestamp.d.cts", "default": "./fa/isoTimestamp.cjs" } }, "./fa/isoWeek": { "import": { "types": "./fa/isoWeek.d.mts", "default": "./fa/isoWeek.mjs" }, "require": { "types": "./fa/isoWeek.d.cts", "default": "./fa/isoWeek.cjs" } }, "./fa/isrc": { "import": { "types": "./fa/isrc.d.mts", "default": "./fa/isrc.mjs" }, "require": { "types": "./fa/isrc.d.cts", "default": "./fa/isrc.cjs" } }, "./fa/jwsCompact": { "import": { "types": "./fa/jwsCompact.d.mts", "default": "./fa/jwsCompact.mjs" }, "require": { "types": "./fa/jwsCompact.d.cts", "default": "./fa/jwsCompact.cjs" } }, "./fa/length": { "import": { "types": "./fa/length.d.mts", "default": "./fa/length.mjs" }, "require": { "types": "./fa/length.d.cts", "default": "./fa/length.cjs" } }, "./fa/ltValue": { "import": { "types": "./fa/ltValue.d.mts", "default": "./fa/ltValue.mjs" }, "require": { "types": "./fa/ltValue.d.cts", "default": "./fa/ltValue.cjs" } }, "./fa/mac": { "import": { "types": "./fa/mac.d.mts", "default": "./fa/mac.mjs" }, "require": { "types": "./fa/mac.d.cts", "default": "./fa/mac.cjs" } }, "./fa/mac48": { "import": { "types": "./fa/mac48.d.mts", "default": "./fa/mac48.mjs" }, "require": { "types": "./fa/mac48.d.cts", "default": "./fa/mac48.cjs" } }, "./fa/mac64": { "import": { "types": "./fa/mac64.d.mts", "default": "./fa/mac64.mjs" }, "require": { "types": "./fa/mac64.d.cts", "default": "./fa/mac64.cjs" } }, "./fa/maxBytes": { "import": { "types": "./fa/maxBytes.d.mts", "default": "./fa/maxBytes.mjs" }, "require": { "types": "./fa/maxBytes.d.cts", "default": "./fa/maxBytes.cjs" } }, "./fa/maxEntries": { "import": { "types": "./fa/maxEntries.d.mts", "default": "./fa/maxEntries.mjs" }, "require": { "types": "./fa/maxEntries.d.cts", "default": "./fa/maxEntries.cjs" } }, "./fa/maxGraphemes": { "import": { "types": "./fa/maxGraphemes.d.mts", "default": "./fa/maxGraphemes.mjs" }, "require": { "types": "./fa/maxGraphemes.d.cts", "default": "./fa/maxGraphemes.cjs" } }, "./fa/maxLength": { "import": { "types": "./fa/maxLength.d.mts", "default": "./fa/maxLength.mjs" }, "require": { "types": "./fa/maxLength.d.cts", "default": "./fa/maxLength.cjs" } }, "./fa/maxSize": { "import": { "types": "./fa/maxSize.d.mts", "default": "./fa/maxSize.mjs" }, "require": { "types": "./fa/maxSize.d.cts", "default": "./fa/maxSize.cjs" } }, "./fa/maxValue": { "import": { "types": "./fa/maxValue.d.mts", "default": "./fa/maxValue.mjs" }, "require": { "types": "./fa/maxValue.d.cts", "default": "./fa/maxValue.cjs" } }, "./fa/maxWords": { "import": { "types": "./fa/maxWords.d.mts", "default": "./fa/maxWords.mjs" }, "require": { "types": "./fa/maxWords.d.cts", "default": "./fa/maxWords.cjs" } }, "./fa/mimeType": { "import": { "types": "./fa/mimeType.d.mts", "default": "./fa/mimeType.mjs" }, "require": { "types": "./fa/mimeType.d.cts", "default": "./fa/mimeType.cjs" } }, "./fa/minBytes": { "import": { "types": "./fa/minBytes.d.mts", "default": "./fa/minBytes.mjs" }, "require": { "types": "./fa/minBytes.d.cts", "default": "./fa/minBytes.cjs" } }, "./fa/minEntries": { "import": { "types": "./fa/minEntries.d.mts", "default": "./fa/minEntries.mjs" }, "require": { "types": "./fa/minEntries.d.cts", "default": "./fa/minEntries.cjs" } }, "./fa/minGraphemes": { "import": { "types": "./fa/minGraphemes.d.mts", "default": "./fa/minGraphemes.mjs" }, "require": { "types": "./fa/minGraphemes.d.cts", "default": "./fa/minGraphemes.cjs" } }, "./fa/minLength": { "import": { "types": "./fa/minLength.d.mts", "default": "./fa/minLength.mjs" }, "require": { "types": "./fa/minLength.d.cts", "default": "./fa/minLength.cjs" } }, "./fa/minSize": { "import": { "types": "./fa/minSize.d.mts", "default": "./fa/minSize.mjs" }, "require": { "types": "./fa/minSize.d.cts", "default": "./fa/minSize.cjs" } }, "./fa/minValue": { "import": { "types": "./fa/minValue.d.mts", "default": "./fa/minValue.mjs" }, "require": { "types": "./fa/minValue.d.cts", "default": "./fa/minValue.cjs" } }, "./fa/minWords": { "import": { "types": "./fa/minWords.d.mts", "default": "./fa/minWords.mjs" }, "require": { "types": "./fa/minWords.d.cts", "default": "./fa/minWords.cjs" } }, "./fa/multipleOf": { "import": { "types": "./fa/multipleOf.d.mts", "default": "./fa/multipleOf.mjs" }, "require": { "types": "./fa/multipleOf.d.cts", "default": "./fa/multipleOf.cjs" } }, "./fa/nanoid": { "import": { "types": "./fa/nanoid.d.mts", "default": "./fa/nanoid.mjs" }, "require": { "types": "./fa/nanoid.d.cts", "default": "./fa/nanoid.cjs" } }, "./fa/nonEmpty": { "import": { "types": "./fa/nonEmpty.d.mts", "default": "./fa/nonEmpty.mjs" }, "require": { "types": "./fa/nonEmpty.d.cts", "default": "./fa/nonEmpty.cjs" } }, "./fa/notBytes": { "import": { "types": "./fa/notBytes.d.mts", "default": "./fa/notBytes.mjs" }, "require": { "types": "./fa/notBytes.d.cts", "default": "./fa/notBytes.cjs" } }, "./fa/notEntries": { "import": { "types": "./fa/notEntries.d.mts", "default": "./fa/notEntries.mjs" }, "require": { "types": "./fa/notEntries.d.cts", "default": "./fa/notEntries.cjs" } }, "./fa/notGraphemes": { "import": { "types": "./fa/notGraphemes.d.mts", "default": "./fa/notGraphemes.mjs" }, "require": { "types": "./fa/notGraphemes.d.cts", "default": "./fa/notGraphemes.cjs" } }, "./fa/notLength": { "import": { "types": "./fa/notLength.d.mts", "default": "./fa/notLength.mjs" }, "require": { "types": "./fa/notLength.d.cts", "default": "./fa/notLength.cjs" } }, "./fa/notSize": { "import": { "types": "./fa/notSize.d.mts", "default": "./fa/notSize.mjs" }, "require": { "types": "./fa/notSize.d.cts", "default": "./fa/notSize.cjs" } }, "./fa/notValue": { "import": { "types": "./fa/notValue.d.mts", "default": "./fa/notValue.mjs" }, "require": { "types": "./fa/notValue.d.cts", "default": "./fa/notValue.cjs" } }, "./fa/notValues": { "import": { "types": "./fa/notValues.d.mts", "default": "./fa/notValues.mjs" }, "require": { "types": "./fa/notValues.d.cts", "default": "./fa/notValues.cjs" } }, "./fa/notWords": { "import": { "types": "./fa/notWords.d.mts", "default": "./fa/notWords.mjs" }, "require": { "types": "./fa/notWords.d.cts", "default": "./fa/notWords.cjs" } }, "./fa/octal": { "import": { "types": "./fa/octal.d.mts", "default": "./fa/octal.mjs" }, "require": { "types": "./fa/octal.d.cts", "default": "./fa/octal.cjs" } }, "./fa/parseBoolean": { "import": { "types": "./fa/parseBoolean.d.mts", "default": "./fa/parseBoolean.mjs" }, "require": { "types": "./fa/parseBoolean.d.cts", "default": "./fa/parseBoolean.cjs" } }, "./fa/parseJson": { "import": { "types": "./fa/parseJson.d.mts", "default": "./fa/parseJson.mjs" }, "require": { "types": "./fa/parseJson.d.cts", "default": "./fa/parseJson.cjs" } }, "./fa/partialCheck": { "import": { "types": "./fa/partialCheck.d.mts", "default": "./fa/partialCheck.mjs" }, "require": { "types": "./fa/partialCheck.d.cts", "default": "./fa/partialCheck.cjs" } }, "./fa/rawCheck": { "import": { "types": "./fa/rawCheck.d.mts", "default": "./fa/rawCheck.mjs" }, "require": { "types": "./fa/rawCheck.d.cts", "default": "./fa/rawCheck.cjs" } }, "./fa/rawTransform": { "import": { "types": "./fa/rawTransform.d.mts", "default": "./fa/rawTransform.mjs" }, "require": { "types": "./fa/rawTransform.d.cts", "default": "./fa/rawTransform.cjs" } }, "./fa/regex": { "import": { "types": "./fa/regex.d.mts", "default": "./fa/regex.mjs" }, "require": { "types": "./fa/regex.d.cts", "default": "./fa/regex.cjs" } }, "./fa/rfcEmail": { "import": { "types": "./fa/rfcEmail.d.mts", "default": "./fa/rfcEmail.mjs" }, "require": { "types": "./fa/rfcEmail.d.cts", "default": "./fa/rfcEmail.cjs" } }, "./fa/safeInteger": { "import": { "types": "./fa/safeInteger.d.mts", "default": "./fa/safeInteger.mjs" }, "require": { "types": "./fa/safeInteger.d.cts", "default": "./fa/safeInteger.cjs" } }, "./fa/size": { "import": { "types": "./fa/size.d.mts", "default": "./fa/size.mjs" }, "require": { "types": "./fa/size.d.cts", "default": "./fa/size.cjs" } }, "./fa/slug": { "import": { "types": "./fa/slug.d.mts", "default": "./fa/slug.mjs" }, "require": { "types": "./fa/slug.d.cts", "default": "./fa/slug.cjs" } }, "./fa/someItem": { "import": { "types": "./fa/someItem.d.mts", "default": "./fa/someItem.mjs" }, "require": { "types": "./fa/someItem.d.cts", "default": "./fa/someItem.cjs" } }, "./fa/startsWith": { "import": { "types": "./fa/startsWith.d.mts", "default": "./fa/startsWith.mjs" }, "require": { "types": "./fa/startsWith.d.cts", "default": "./fa/startsWith.cjs" } }, "./fa/stringifyJson": { "import": { "types": "./fa/stringifyJson.d.mts", "default": "./fa/stringifyJson.mjs" }, "require": { "types": "./fa/stringifyJson.d.cts", "default": "./fa/stringifyJson.cjs" } }, "./fa/toBigint": { "import": { "types": "./fa/toBigint.d.mts", "default": "./fa/toBigint.mjs" }, "require": { "types": "./fa/toBigint.d.cts", "default": "./fa/toBigint.cjs" } }, "./fa/toDate": { "import": { "types": "./fa/toDate.d.mts", "default": "./fa/toDate.mjs" }, "require": { "types": "./fa/toDate.d.cts", "default": "./fa/toDate.cjs" } }, "./fa/toNumber": { "import": { "types": "./fa/toNumber.d.mts", "default": "./fa/toNumber.mjs" }, "require": { "types": "./fa/toNumber.d.cts", "default": "./fa/toNumber.cjs" } }, "./fa/toString": { "import": { "types": "./fa/toString.d.mts", "default": "./fa/toString.mjs" }, "require": { "types": "./fa/toString.d.cts", "default": "./fa/toString.cjs" } }, "./fa/ulid": { "import": { "types": "./fa/ulid.d.mts", "default": "./fa/ulid.mjs" }, "require": { "types": "./fa/ulid.d.cts", "default": "./fa/ulid.cjs" } }, "./fa/url": { "import": { "types": "./fa/url.d.mts", "default": "./fa/url.mjs" }, "require": { "types": "./fa/url.d.cts", "default": "./fa/url.cjs" } }, "./fa/uuid": { "import": { "types": "./fa/uuid.d.mts", "default": "./fa/uuid.mjs" }, "require": { "types": "./fa/uuid.d.cts", "default": "./fa/uuid.cjs" } }, "./fa/value": { "import": { "types": "./fa/value.d.mts", "default": "./fa/value.mjs" }, "require": { "types": "./fa/value.d.cts", "default": "./fa/value.cjs" } }, "./fa/values": { "import": { "types": "./fa/values.d.mts", "default": "./fa/values.mjs" }, "require": { "types": "./fa/values.d.cts", "default": "./fa/values.cjs" } }, "./fa/words": { "import": { "types": "./fa/words.d.mts", "default": "./fa/words.mjs" }, "require": { "types": "./fa/words.d.cts", "default": "./fa/words.cjs" } }, "./fi": { "import": { "types": "./fi/index.d.mts", "default": "./fi/index.mjs" }, "require": { "types": "./fi/index.d.cts", "default": "./fi/index.cjs" } }, "./fi/schema": { "import": { "types": "./fi/schema.d.mts", "default": "./fi/schema.mjs" }, "require": { "types": "./fi/schema.d.cts", "default": "./fi/schema.cjs" } }, "./fi/base64": { "import": { "types": "./fi/base64.d.mts", "default": "./fi/base64.mjs" }, "require": { "types": "./fi/base64.d.cts", "default": "./fi/base64.cjs" } }, "./fi/bic": { "import": { "types": "./fi/bic.d.mts", "default": "./fi/bic.mjs" }, "require": { "types": "./fi/bic.d.cts", "default": "./fi/bic.cjs" } }, "./fi/bytes": { "import": { "types": "./fi/bytes.d.mts", "default": "./fi/bytes.mjs" }, "require": { "types": "./fi/bytes.d.cts", "default": "./fi/bytes.cjs" } }, "./fi/check": { "import": { "types": "./fi/check.d.mts", "default": "./fi/check.mjs" }, "require": { "types": "./fi/check.d.cts", "default": "./fi/check.cjs" } }, "./fi/checkAsync": { "import": { "types": "./fi/checkAsync.d.mts", "default": "./fi/checkAsync.mjs" }, "require": { "types": "./fi/checkAsync.d.cts", "default": "./fi/checkAsync.cjs" } }, "./fi/checkItems": { "import": { "types": "./fi/checkItems.d.mts", "default": "./fi/checkItems.mjs" }, "require": { "types": "./fi/checkItems.d.cts", "default": "./fi/checkItems.cjs" } }, "./fi/checkItemsAsync": { "import": { "types": "./fi/checkItemsAsync.d.mts", "default": "./fi/checkItemsAsync.mjs" }, "require": { "types": "./fi/checkItemsAsync.d.cts", "default": "./fi/checkItemsAsync.cjs" } }, "./fi/creditCard": { "import": { "types": "./fi/creditCard.d.mts", "default": "./fi/creditCard.mjs" }, "require": { "types": "./fi/creditCard.d.cts", "default": "./fi/creditCard.cjs" } }, "./fi/cuid2": { "import": { "types": "./fi/cuid2.d.mts", "default": "./fi/cuid2.mjs" }, "require": { "types": "./fi/cuid2.d.cts", "default": "./fi/cuid2.cjs" } }, "./fi/decimal": { "import": { "types": "./fi/decimal.d.mts", "default": "./fi/decimal.mjs" }, "require": { "types": "./fi/decimal.d.cts", "default": "./fi/decimal.cjs" } }, "./fi/digits": { "import": { "types": "./fi/digits.d.mts", "default": "./fi/digits.mjs" }, "require": { "types": "./fi/digits.d.cts", "default": "./fi/digits.cjs" } }, "./fi/domain": { "import": { "types": "./fi/domain.d.mts", "default": "./fi/domain.mjs" }, "require": { "types": "./fi/domain.d.cts", "default": "./fi/domain.cjs" } }, "./fi/email": { "import": { "types": "./fi/email.d.mts", "default": "./fi/email.mjs" }, "require": { "types": "./fi/email.d.cts", "default": "./fi/email.cjs" } }, "./fi/emoji": { "import": { "types": "./fi/emoji.d.mts", "default": "./fi/emoji.mjs" }, "require": { "types": "./fi/emoji.d.cts", "default": "./fi/emoji.cjs" } }, "./fi/empty": { "import": { "types": "./fi/empty.d.mts", "default": "./fi/empty.mjs" }, "require": { "types": "./fi/empty.d.cts", "default": "./fi/empty.cjs" } }, "./fi/endsWith": { "import": { "types": "./fi/endsWith.d.mts", "default": "./fi/endsWith.mjs" }, "require": { "types": "./fi/endsWith.d.cts", "default": "./fi/endsWith.cjs" } }, "./fi/entries": { "import": { "types": "./fi/entries.d.mts", "default": "./fi/entries.mjs" }, "require": { "types": "./fi/entries.d.cts", "default": "./fi/entries.cjs" } }, "./fi/everyItem": { "import": { "types": "./fi/everyItem.d.mts", "default": "./fi/everyItem.mjs" }, "require": { "types": "./fi/everyItem.d.cts", "default": "./fi/everyItem.cjs" } }, "./fi/excludes": { "import": { "types": "./fi/excludes.d.mts", "default": "./fi/excludes.mjs" }, "require": { "types": "./fi/excludes.d.cts", "default": "./fi/excludes.cjs" } }, "./fi/finite": { "import": { "types": "./fi/finite.d.mts", "default": "./fi/finite.mjs" }, "require": { "types": "./fi/finite.d.cts", "default": "./fi/finite.cjs" } }, "./fi/graphemes": { "import": { "types": "./fi/graphemes.d.mts", "default": "./fi/graphemes.mjs" }, "require": { "types": "./fi/graphemes.d.cts", "default": "./fi/graphemes.cjs" } }, "./fi/gtValue": { "import": { "types": "./fi/gtValue.d.mts", "default": "./fi/gtValue.mjs" }, "require": { "types": "./fi/gtValue.d.cts", "default": "./fi/gtValue.cjs" } }, "./fi/guard": { "import": { "types": "./fi/guard.d.mts", "default": "./fi/guard.mjs" }, "require": { "types": "./fi/guard.d.cts", "default": "./fi/guard.cjs" } }, "./fi/hash": { "import": { "types": "./fi/hash.d.mts", "default": "./fi/hash.mjs" }, "require": { "types": "./fi/hash.d.cts", "default": "./fi/hash.cjs" } }, "./fi/hexColor": { "import": { "types": "./fi/hexColor.d.mts", "default": "./fi/hexColor.mjs" }, "require": { "types": "./fi/hexColor.d.cts", "default": "./fi/hexColor.cjs" } }, "./fi/hexadecimal": { "import": { "types": "./fi/hexadecimal.d.mts", "default": "./fi/hexadecimal.mjs" }, "require": { "types": "./fi/hexadecimal.d.cts", "default": "./fi/hexadecimal.cjs" } }, "./fi/imei": { "import": { "types": "./fi/imei.d.mts", "default": "./fi/imei.mjs" }, "require": { "types": "./fi/imei.d.cts", "default": "./fi/imei.cjs" } }, "./fi/includes": { "import": { "types": "./fi/includes.d.mts", "default": "./fi/includes.mjs" }, "require": { "types": "./fi/includes.d.cts", "default": "./fi/includes.cjs" } }, "./fi/integer": { "import": { "types": "./fi/integer.d.mts", "default": "./fi/integer.mjs" }, "require": { "types": "./fi/integer.d.cts", "default": "./fi/integer.cjs" } }, "./fi/ip": { "import": { "types": "./fi/ip.d.mts", "default": "./fi/ip.mjs" }, "require": { "types": "./fi/ip.d.cts", "default": "./fi/ip.cjs" } }, "./fi/ipv4": { "import": { "types": "./fi/ipv4.d.mts", "default": "./fi/ipv4.mjs" }, "require": { "types": "./fi/ipv4.d.cts", "default": "./fi/ipv4.cjs" } }, "./fi/ipv6": { "import": { "types": "./fi/ipv6.d.mts", "default": "./fi/ipv6.mjs" }, "require": { "types": "./fi/ipv6.d.cts", "default": "./fi/ipv6.cjs" } }, "./fi/isbn": { "import": { "types": "./fi/isbn.d.mts", "default": "./fi/isbn.mjs" }, "require": { "types": "./fi/isbn.d.cts", "default": "./fi/isbn.cjs" } }, "./fi/isoDate": { "import": { "types": "./fi/isoDate.d.mts", "default": "./fi/isoDate.mjs" }, "require": { "types": "./fi/isoDate.d.cts", "default": "./fi/isoDate.cjs" } }, "./fi/isoDateTime": { "import": { "types": "./fi/isoDateTime.d.mts", "default": "./fi/isoDateTime.mjs" }, "require": { "types": "./fi/isoDateTime.d.cts", "default": "./fi/isoDateTime.cjs" } }, "./fi/isoTime": { "import": { "types": "./fi/isoTime.d.mts", "default": "./fi/isoTime.mjs" }, "require": { "types": "./fi/isoTime.d.cts", "default": "./fi/isoTime.cjs" } }, "./fi/isoTimeSecond": { "import": { "types": "./fi/isoTimeSecond.d.mts", "default": "./fi/isoTimeSecond.mjs" }, "require": { "types": "./fi/isoTimeSecond.d.cts", "default": "./fi/isoTimeSecond.cjs" } }, "./fi/isoTimestamp": { "import": { "types": "./fi/isoTimestamp.d.mts", "default": "./fi/isoTimestamp.mjs" }, "require": { "types": "./fi/isoTimestamp.d.cts", "default": "./fi/isoTimestamp.cjs" } }, "./fi/isoWeek": { "import": { "types": "./fi/isoWeek.d.mts", "default": "./fi/isoWeek.mjs" }, "require": { "types": "./fi/isoWeek.d.cts", "default": "./fi/isoWeek.cjs" } }, "./fi/isrc": { "import": { "types": "./fi/isrc.d.mts", "default": "./fi/isrc.mjs" }, "require": { "types": "./fi/isrc.d.cts", "default": "./fi/isrc.cjs" } }, "./fi/jwsCompact": { "import": { "types": "./fi/jwsCompact.d.mts", "default": "./fi/jwsCompact.mjs" }, "require": { "types": "./fi/jwsCompact.d.cts", "default": "./fi/jwsCompact.cjs" } }, "./fi/length": { "import": { "types": "./fi/length.d.mts", "default": "./fi/length.mjs" }, "require": { "types": "./fi/length.d.cts", "default": "./fi/length.cjs" } }, "./fi/ltValue": { "import": { "types": "./fi/ltValue.d.mts", "default": "./fi/ltValue.mjs" }, "require": { "types": "./fi/ltValue.d.cts", "default": "./fi/ltValue.cjs" } }, "./fi/mac": { "import": { "types": "./fi/mac.d.mts", "default": "./fi/mac.mjs" }, "require": { "types": "./fi/mac.d.cts", "default": "./fi/mac.cjs" } }, "./fi/mac48": { "import": { "types": "./fi/mac48.d.mts", "default": "./fi/mac48.mjs" }, "require": { "types": "./fi/mac48.d.cts", "default": "./fi/mac48.cjs" } }, "./fi/mac64": { "import": { "types": "./fi/mac64.d.mts", "default": "./fi/mac64.mjs" }, "require": { "types": "./fi/mac64.d.cts", "default": "./fi/mac64.cjs" } }, "./fi/maxBytes": { "import": { "types": "./fi/maxBytes.d.mts", "default": "./fi/maxBytes.mjs" }, "require": { "types": "./fi/maxBytes.d.cts", "default": "./fi/maxBytes.cjs" } }, "./fi/maxEntries": { "import": { "types": "./fi/maxEntries.d.mts", "default": "./fi/maxEntries.mjs" }, "require": { "types": "./fi/maxEntries.d.cts", "default": "./fi/maxEntries.cjs" } }, "./fi/maxGraphemes": { "import": { "types": "./fi/maxGraphemes.d.mts", "default": "./fi/maxGraphemes.mjs" }, "require": { "types": "./fi/maxGraphemes.d.cts", "default": "./fi/maxGraphemes.cjs" } }, "./fi/maxLength": { "import": { "types": "./fi/maxLength.d.mts", "default": "./fi/maxLength.mjs" }, "require": { "types": "./fi/maxLength.d.cts", "default": "./fi/maxLength.cjs" } }, "./fi/maxSize": { "import": { "types": "./fi/maxSize.d.mts", "default": "./fi/maxSize.mjs" }, "require": { "types": "./fi/maxSize.d.cts", "default": "./fi/maxSize.cjs" } }, "./fi/maxValue": { "import": { "types": "./fi/maxValue.d.mts", "default": "./fi/maxValue.mjs" }, "require": { "types": "./fi/maxValue.d.cts", "default": "./fi/maxValue.cjs" } }, "./fi/maxWords": { "import": { "types": "./fi/maxWords.d.mts", "default": "./fi/maxWords.mjs" }, "require": { "types": "./fi/maxWords.d.cts", "default": "./fi/maxWords.cjs" } }, "./fi/mimeType": { "import": { "types": "./fi/mimeType.d.mts", "default": "./fi/mimeType.mjs" }, "require": { "types": "./fi/mimeType.d.cts", "default": "./fi/mimeType.cjs" } }, "./fi/minBytes": { "import": { "types": "./fi/minBytes.d.mts", "default": "./fi/minBytes.mjs" }, "require": { "types": "./fi/minBytes.d.cts", "default": "./fi/minBytes.cjs" } }, "./fi/minEntries": { "import": { "types": "./fi/minEntries.d.mts", "default": "./fi/minEntries.mjs" }, "require": { "types": "./fi/minEntries.d.cts", "default": "./fi/minEntries.cjs" } }, "./fi/minGraphemes": { "import": { "types": "./fi/minGraphemes.d.mts", "default": "./fi/minGraphemes.mjs" }, "require": { "types": "./fi/minGraphemes.d.cts", "default": "./fi/minGraphemes.cjs" } }, "./fi/minLength": { "import": { "types": "./fi/minLength.d.mts", "default": "./fi/minLength.mjs" }, "require": { "types": "./fi/minLength.d.cts", "default": "./fi/minLength.cjs" } }, "./fi/minSize": { "import": { "types": "./fi/minSize.d.mts", "default": "./fi/minSize.mjs" }, "require": { "types": "./fi/minSize.d.cts", "default": "./fi/minSize.cjs" } }, "./fi/minValue": { "import": { "types": "./fi/minValue.d.mts", "default": "./fi/minValue.mjs" }, "require": { "types": "./fi/minValue.d.cts", "default": "./fi/minValue.cjs" } }, "./fi/minWords": { "import": { "types": "./fi/minWords.d.mts", "default": "./fi/minWords.mjs" }, "require": { "types": "./fi/minWords.d.cts", "default": "./fi/minWords.cjs" } }, "./fi/multipleOf": { "import": { "types": "./fi/multipleOf.d.mts", "default": "./fi/multipleOf.mjs" }, "require": { "types": "./fi/multipleOf.d.cts", "default": "./fi/multipleOf.cjs" } }, "./fi/nanoid": { "import": { "types": "./fi/nanoid.d.mts", "default": "./fi/nanoid.mjs" }, "require": { "types": "./fi/nanoid.d.cts", "default": "./fi/nanoid.cjs" } }, "./fi/nonEmpty": { "import": { "types": "./fi/nonEmpty.d.mts", "default": "./fi/nonEmpty.mjs" }, "require": { "types": "./fi/nonEmpty.d.cts", "default": "./fi/nonEmpty.cjs" } }, "./fi/notBytes": { "import": { "types": "./fi/notBytes.d.mts", "default": "./fi/notBytes.mjs" }, "require": { "types": "./fi/notBytes.d.cts", "default": "./fi/notBytes.cjs" } }, "./fi/notEntries": { "import": { "types": "./fi/notEntries.d.mts", "default": "./fi/notEntries.mjs" }, "require": { "types": "./fi/notEntries.d.cts", "default": "./fi/notEntries.cjs" } }, "./fi/notGraphemes": { "import": { "types": "./fi/notGraphemes.d.mts", "default": "./fi/notGraphemes.mjs" }, "require": { "types": "./fi/notGraphemes.d.cts", "default": "./fi/notGraphemes.cjs" } }, "./fi/notLength": { "import": { "types": "./fi/notLength.d.mts", "default": "./fi/notLength.mjs" }, "require": { "types": "./fi/notLength.d.cts", "default": "./fi/notLength.cjs" } }, "./fi/notSize": { "import": { "types": "./fi/notSize.d.mts", "default": "./fi/notSize.mjs" }, "require": { "types": "./fi/notSize.d.cts", "default": "./fi/notSize.cjs" } }, "./fi/notValue": { "import": { "types": "./fi/notValue.d.mts", "default": "./fi/notValue.mjs" }, "require": { "types": "./fi/notValue.d.cts", "default": "./fi/notValue.cjs" } }, "./fi/notValues": { "import": { "types": "./fi/notValues.d.mts", "default": "./fi/notValues.mjs" }, "require": { "types": "./fi/notValues.d.cts", "default": "./fi/notValues.cjs" } }, "./fi/notWords": { "import": { "types": "./fi/notWords.d.mts", "default": "./fi/notWords.mjs" }, "require": { "types": "./fi/notWords.d.cts", "default": "./fi/notWords.cjs" } }, "./fi/octal": { "import": { "types": "./fi/octal.d.mts", "default": "./fi/octal.mjs" }, "require": { "types": "./fi/octal.d.cts", "default": "./fi/octal.cjs" } }, "./fi/parseBoolean": { "import": { "types": "./fi/parseBoolean.d.mts", "default": "./fi/parseBoolean.mjs" }, "require": { "types": "./fi/parseBoolean.d.cts", "default": "./fi/parseBoolean.cjs" } }, "./fi/parseJson": { "import": { "types": "./fi/parseJson.d.mts", "default": "./fi/parseJson.mjs" }, "require": { "types": "./fi/parseJson.d.cts", "default": "./fi/parseJson.cjs" } }, "./fi/partialCheck": { "import": { "types": "./fi/partialCheck.d.mts", "default": "./fi/partialCheck.mjs" }, "require": { "types": "./fi/partialCheck.d.cts", "default": "./fi/partialCheck.cjs" } }, "./fi/rawCheck": { "import": { "types": "./fi/rawCheck.d.mts", "default": "./fi/rawCheck.mjs" }, "require": { "types": "./fi/rawCheck.d.cts", "default": "./fi/rawCheck.cjs" } }, "./fi/rawTransform": { "import": { "types": "./fi/rawTransform.d.mts", "default": "./fi/rawTransform.mjs" }, "require": { "types": "./fi/rawTransform.d.cts", "default": "./fi/rawTransform.cjs" } }, "./fi/regex": { "import": { "types": "./fi/regex.d.mts", "default": "./fi/regex.mjs" }, "require": { "types": "./fi/regex.d.cts", "default": "./fi/regex.cjs" } }, "./fi/rfcEmail": { "import": { "types": "./fi/rfcEmail.d.mts", "default": "./fi/rfcEmail.mjs" }, "require": { "types": "./fi/rfcEmail.d.cts", "default": "./fi/rfcEmail.cjs" } }, "./fi/safeInteger": { "import": { "types": "./fi/safeInteger.d.mts", "default": "./fi/safeInteger.mjs" }, "require": { "types": "./fi/safeInteger.d.cts", "default": "./fi/safeInteger.cjs" } }, "./fi/size": { "import": { "types": "./fi/size.d.mts", "default": "./fi/size.mjs" }, "require": { "types": "./fi/size.d.cts", "default": "./fi/size.cjs" } }, "./fi/slug": { "import": { "types": "./fi/slug.d.mts", "default": "./fi/slug.mjs" }, "require": { "types": "./fi/slug.d.cts", "default": "./fi/slug.cjs" } }, "./fi/someItem": { "import": { "types": "./fi/someItem.d.mts", "default": "./fi/someItem.mjs" }, "require": { "types": "./fi/someItem.d.cts", "default": "./fi/someItem.cjs" } }, "./fi/startsWith": { "import": { "types": "./fi/startsWith.d.mts", "default": "./fi/startsWith.mjs" }, "require": { "types": "./fi/startsWith.d.cts", "default": "./fi/startsWith.cjs" } }, "./fi/stringifyJson": { "import": { "types": "./fi/stringifyJson.d.mts", "default": "./fi/stringifyJson.mjs" }, "require": { "types": "./fi/stringifyJson.d.cts", "default": "./fi/stringifyJson.cjs" } }, "./fi/toBigint": { "import": { "types": "./fi/toBigint.d.mts", "default": "./fi/toBigint.mjs" }, "require": { "types": "./fi/toBigint.d.cts", "default": "./fi/toBigint.cjs" } }, "./fi/toDate": { "import": { "types": "./fi/toDate.d.mts", "default": "./fi/toDate.mjs" }, "require": { "types": "./fi/toDate.d.cts", "default": "./fi/toDate.cjs" } }, "./fi/toNumber": { "import": { "types": "./fi/toNumber.d.mts", "default": "./fi/toNumber.mjs" }, "require": { "types": "./fi/toNumber.d.cts", "default": "./fi/toNumber.cjs" } }, "./fi/toString": { "import": { "types": "./fi/toString.d.mts", "default": "./fi/toString.mjs" }, "require": { "types": "./fi/toString.d.cts", "default": "./fi/toString.cjs" } }, "./fi/ulid": { "import": { "types": "./fi/ulid.d.mts", "default": "./fi/ulid.mjs" }, "require": { "types": "./fi/ulid.d.cts", "default": "./fi/ulid.cjs" } }, "./fi/url": { "import": { "types": "./fi/url.d.mts", "default": "./fi/url.mjs" }, "require": { "types": "./fi/url.d.cts", "default": "./fi/url.cjs" } }, "./fi/uuid": { "import": { "types": "./fi/uuid.d.mts", "default": "./fi/uuid.mjs" }, "require": { "types": "./fi/uuid.d.cts", "default": "./fi/uuid.cjs" } }, "./fi/value": { "import": { "types": "./fi/value.d.mts", "default": "./fi/value.mjs" }, "require": { "types": "./fi/value.d.cts", "default": "./fi/value.cjs" } }, "./fi/values": { "import": { "types": "./fi/values.d.mts", "default": "./fi/values.mjs" }, "require": { "types": "./fi/values.d.cts", "default": "./fi/values.cjs" } }, "./fi/words": { "import": { "types": "./fi/words.d.mts", "default": "./fi/words.mjs" }, "require": { "types": "./fi/words.d.cts", "default": "./fi/words.cjs" } }, "./fr": { "import": { "types": "./fr/index.d.mts", "default": "./fr/index.mjs" }, "require": { "types": "./fr/index.d.cts", "default": "./fr/index.cjs" } }, "./fr/schema": { "import": { "types": "./fr/schema.d.mts", "default": "./fr/schema.mjs" }, "require": { "types": "./fr/schema.d.cts", "default": "./fr/schema.cjs" } }, "./fr/base64": { "import": { "types": "./fr/base64.d.mts", "default": "./fr/base64.mjs" }, "require": { "types": "./fr/base64.d.cts", "default": "./fr/base64.cjs" } }, "./fr/bic": { "import": { "types": "./fr/bic.d.mts", "default": "./fr/bic.mjs" }, "require": { "types": "./fr/bic.d.cts", "default": "./fr/bic.cjs" } }, "./fr/bytes": { "import": { "types": "./fr/bytes.d.mts", "default": "./fr/bytes.mjs" }, "require": { "types": "./fr/bytes.d.cts", "default": "./fr/bytes.cjs" } }, "./fr/check": { "import": { "types": "./fr/check.d.mts", "default": "./fr/check.mjs" }, "require": { "types": "./fr/check.d.cts", "default": "./fr/check.cjs" } }, "./fr/checkAsync": { "import": { "types": "./fr/checkAsync.d.mts", "default": "./fr/checkAsync.mjs" }, "require": { "types": "./fr/checkAsync.d.cts", "default": "./fr/checkAsync.cjs" } }, "./fr/checkItems": { "import": { "types": "./fr/checkItems.d.mts", "default": "./fr/checkItems.mjs" }, "require": { "types": "./fr/checkItems.d.cts", "default": "./fr/checkItems.cjs" } }, "./fr/checkItemsAsync": { "import": { "types": "./fr/checkItemsAsync.d.mts", "default": "./fr/checkItemsAsync.mjs" }, "require": { "types": "./fr/checkItemsAsync.d.cts", "default": "./fr/checkItemsAsync.cjs" } }, "./fr/creditCard": { "import": { "types": "./fr/creditCard.d.mts", "default": "./fr/creditCard.mjs" }, "require": { "types": "./fr/creditCard.d.cts", "default": "./fr/creditCard.cjs" } }, "./fr/cuid2": { "import": { "types": "./fr/cuid2.d.mts", "default": "./fr/cuid2.mjs" }, "require": { "types": "./fr/cuid2.d.cts", "default": "./fr/cuid2.cjs" } }, "./fr/decimal": { "import": { "types": "./fr/decimal.d.mts", "default": "./fr/decimal.mjs" }, "require": { "types": "./fr/decimal.d.cts", "default": "./fr/decimal.cjs" } }, "./fr/digits": { "import": { "types": "./fr/digits.d.mts", "default": "./fr/digits.mjs" }, "require": { "types": "./fr/digits.d.cts", "default": "./fr/digits.cjs" } }, "./fr/domain": { "import": { "types": "./fr/domain.d.mts", "default": "./fr/domain.mjs" }, "require": { "types": "./fr/domain.d.cts", "default": "./fr/domain.cjs" } }, "./fr/email": { "import": { "types": "./fr/email.d.mts", "default": "./fr/email.mjs" }, "require": { "types": "./fr/email.d.cts", "default": "./fr/email.cjs" } }, "./fr/emoji": { "import": { "types": "./fr/emoji.d.mts", "default": "./fr/emoji.mjs" }, "require": { "types": "./fr/emoji.d.cts", "default": "./fr/emoji.cjs" } }, "./fr/empty": { "import": { "types": "./fr/empty.d.mts", "default": "./fr/empty.mjs" }, "require": { "types": "./fr/empty.d.cts", "default": "./fr/empty.cjs" } }, "./fr/endsWith": { "import": { "types": "./fr/endsWith.d.mts", "default": "./fr/endsWith.mjs" }, "require": { "types": "./fr/endsWith.d.cts", "default": "./fr/endsWith.cjs" } }, "./fr/entries": { "import": { "types": "./fr/entries.d.mts", "default": "./fr/entries.mjs" }, "require": { "types": "./fr/entries.d.cts", "default": "./fr/entries.cjs" } }, "./fr/everyItem": { "import": { "types": "./fr/everyItem.d.mts", "default": "./fr/everyItem.mjs" }, "require": { "types": "./fr/everyItem.d.cts", "default": "./fr/everyItem.cjs" } }, "./fr/excludes": { "import": { "types": "./fr/excludes.d.mts", "default": "./fr/excludes.mjs" }, "require": { "types": "./fr/excludes.d.cts", "default": "./fr/excludes.cjs" } }, "./fr/finite": { "import": { "types": "./fr/finite.d.mts", "default": "./fr/finite.mjs" }, "require": { "types": "./fr/finite.d.cts", "default": "./fr/finite.cjs" } }, "./fr/graphemes": { "import": { "types": "./fr/graphemes.d.mts", "default": "./fr/graphemes.mjs" }, "require": { "types": "./fr/graphemes.d.cts", "default": "./fr/graphemes.cjs" } }, "./fr/gtValue": { "import": { "types": "./fr/gtValue.d.mts", "default": "./fr/gtValue.mjs" }, "require": { "types": "./fr/gtValue.d.cts", "default": "./fr/gtValue.cjs" } }, "./fr/guard": { "import": { "types": "./fr/guard.d.mts", "default": "./fr/guard.mjs" }, "require": { "types": "./fr/guard.d.cts", "default": "./fr/guard.cjs" } }, "./fr/hash": { "import": { "types": "./fr/hash.d.mts", "default": "./fr/hash.mjs" }, "require": { "types": "./fr/hash.d.cts", "default": "./fr/hash.cjs" } }, "./fr/hexadecimal": { "import": { "types": "./fr/hexadecimal.d.mts", "default": "./fr/hexadecimal.mjs" }, "require": { "types": "./fr/hexadecimal.d.cts", "default": "./fr/hexadecimal.cjs" } }, "./fr/hexColor": { "import": { "types": "./fr/hexColor.d.mts", "default": "./fr/hexColor.mjs" }, "require": { "types": "./fr/hexColor.d.cts", "default": "./fr/hexColor.cjs" } }, "./fr/imei": { "import": { "types": "./fr/imei.d.mts", "default": "./fr/imei.mjs" }, "require": { "types": "./fr/imei.d.cts", "default": "./fr/imei.cjs" } }, "./fr/includes": { "import": { "types": "./fr/includes.d.mts", "default": "./fr/includes.mjs" }, "require": { "types": "./fr/includes.d.cts", "default": "./fr/includes.cjs" } }, "./fr/integer": { "import": { "types": "./fr/integer.d.mts", "default": "./fr/integer.mjs" }, "require": { "types": "./fr/integer.d.cts", "default": "./fr/integer.cjs" } }, "./fr/ip": { "import": { "types": "./fr/ip.d.mts", "default": "./fr/ip.mjs" }, "require": { "types": "./fr/ip.d.cts", "default": "./fr/ip.cjs" } }, "./fr/ipv4": { "import": { "types": "./fr/ipv4.d.mts", "default": "./fr/ipv4.mjs" }, "require": { "types": "./fr/ipv4.d.cts", "default": "./fr/ipv4.cjs" } }, "./fr/ipv6": { "import": { "types": "./fr/ipv6.d.mts", "default": "./fr/ipv6.mjs" }, "require": { "types": "./fr/ipv6.d.cts", "default": "./fr/ipv6.cjs" } }, "./fr/isbn": { "import": { "types": "./fr/isbn.d.mts", "default": "./fr/isbn.mjs" }, "require": { "types": "./fr/isbn.d.cts", "default": "./fr/isbn.cjs" } }, "./fr/isoDate": { "import": { "types": "./fr/isoDate.d.mts", "default": "./fr/isoDate.mjs" }, "require": { "types": "./fr/isoDate.d.cts", "default": "./fr/isoDate.cjs" } }, "./fr/isoDateTime": { "import": { "types": "./fr/isoDateTime.d.mts", "default": "./fr/isoDateTime.mjs" }, "require": { "types": "./fr/isoDateTime.d.cts", "default": "./fr/isoDateTime.cjs" } }, "./fr/isoTime": { "import": { "types": "./fr/isoTime.d.mts", "default": "./fr/isoTime.mjs" }, "require": { "types": "./fr/isoTime.d.cts", "default": "./fr/isoTime.cjs" } }, "./fr/isoTimeSecond": { "import": { "types": "./fr/isoTimeSecond.d.mts", "default": "./fr/isoTimeSecond.mjs" }, "require": { "types": "./fr/isoTimeSecond.d.cts", "default": "./fr/isoTimeSecond.cjs" } }, "./fr/isoTimestamp": { "import": { "types": "./fr/isoTimestamp.d.mts", "default": "./fr/isoTimestamp.mjs" }, "require": { "types": "./fr/isoTimestamp.d.cts", "default": "./fr/isoTimestamp.cjs" } }, "./fr/isoWeek": { "import": { "types": "./fr/isoWeek.d.mts", "default": "./fr/isoWeek.mjs" }, "require": { "types": "./fr/isoWeek.d.cts", "default": "./fr/isoWeek.cjs" } }, "./fr/isrc": { "import": { "types": "./fr/isrc.d.mts", "default": "./fr/isrc.mjs" }, "require": { "types": "./fr/isrc.d.cts", "default": "./fr/isrc.cjs" } }, "./fr/jwsCompact": { "import": { "types": "./fr/jwsCompact.d.mts", "default": "./fr/jwsCompact.mjs" }, "require": { "types": "./fr/jwsCompact.d.cts", "default": "./fr/jwsCompact.cjs" } }, "./fr/length": { "import": { "types": "./fr/length.d.mts", "default": "./fr/length.mjs" }, "require": { "types": "./fr/length.d.cts", "default": "./fr/length.cjs" } }, "./fr/ltValue": { "import": { "types": "./fr/ltValue.d.mts", "default": "./fr/ltValue.mjs" }, "require": { "types": "./fr/ltValue.d.cts", "default": "./fr/ltValue.cjs" } }, "./fr/mac": { "import": { "types": "./fr/mac.d.mts", "default": "./fr/mac.mjs" }, "require": { "types": "./fr/mac.d.cts", "default": "./fr/mac.cjs" } }, "./fr/mac48": { "import": { "types": "./fr/mac48.d.mts", "default": "./fr/mac48.mjs" }, "require": { "types": "./fr/mac48.d.cts", "default": "./fr/mac48.cjs" } }, "./fr/mac64": { "import": { "types": "./fr/mac64.d.mts", "default": "./fr/mac64.mjs" }, "require": { "types": "./fr/mac64.d.cts", "default": "./fr/mac64.cjs" } }, "./fr/maxBytes": { "import": { "types": "./fr/maxBytes.d.mts", "default": "./fr/maxBytes.mjs" }, "require": { "types": "./fr/maxBytes.d.cts", "default": "./fr/maxBytes.cjs" } }, "./fr/maxEntries": { "import": { "types": "./fr/maxEntries.d.mts", "default": "./fr/maxEntries.mjs" }, "require": { "types": "./fr/maxEntries.d.cts", "default": "./fr/maxEntries.cjs" } }, "./fr/maxGraphemes": { "import": { "types": "./fr/maxGraphemes.d.mts", "default": "./fr/maxGraphemes.mjs" }, "require": { "types": "./fr/maxGraphemes.d.cts", "default": "./fr/maxGraphemes.cjs" } }, "./fr/maxLength": { "import": { "types": "./fr/maxLength.d.mts", "default": "./fr/maxLength.mjs" }, "require": { "types": "./fr/maxLength.d.cts", "default": "./fr/maxLength.cjs" } }, "./fr/maxSize": { "import": { "types": "./fr/maxSize.d.mts", "default": "./fr/maxSize.mjs" }, "require": { "types": "./fr/maxSize.d.cts", "default": "./fr/maxSize.cjs" } }, "./fr/maxValue": { "import": { "types": "./fr/maxValue.d.mts", "default": "./fr/maxValue.mjs" }, "require": { "types": "./fr/maxValue.d.cts", "default": "./fr/maxValue.cjs" } }, "./fr/maxWords": { "import": { "types": "./fr/maxWords.d.mts", "default": "./fr/maxWords.mjs" }, "require": { "types": "./fr/maxWords.d.cts", "default": "./fr/maxWords.cjs" } }, "./fr/mimeType": { "import": { "types": "./fr/mimeType.d.mts", "default": "./fr/mimeType.mjs" }, "require": { "types": "./fr/mimeType.d.cts", "default": "./fr/mimeType.cjs" } }, "./fr/minBytes": { "import": { "types": "./fr/minBytes.d.mts", "default": "./fr/minBytes.mjs" }, "require": { "types": "./fr/minBytes.d.cts", "default": "./fr/minBytes.cjs" } }, "./fr/minEntries": { "import": { "types": "./fr/minEntries.d.mts", "default": "./fr/minEntries.mjs" }, "require": { "types": "./fr/minEntries.d.cts", "default": "./fr/minEntries.cjs" } }, "./fr/minGraphemes": { "import": { "types": "./fr/minGraphemes.d.mts", "default": "./fr/minGraphemes.mjs" }, "require": { "types": "./fr/minGraphemes.d.cts", "default": "./fr/minGraphemes.cjs" } }, "./fr/minLength": { "import": { "types": "./fr/minLength.d.mts", "default": "./fr/minLength.mjs" }, "require": { "types": "./fr/minLength.d.cts", "default": "./fr/minLength.cjs" } }, "./fr/minSize": { "import": { "types": "./fr/minSize.d.mts", "default": "./fr/minSize.mjs" }, "require": { "types": "./fr/minSize.d.cts", "default": "./fr/minSize.cjs" } }, "./fr/minValue": { "import": { "types": "./fr/minValue.d.mts", "default": "./fr/minValue.mjs" }, "require": { "types": "./fr/minValue.d.cts", "default": "./fr/minValue.cjs" } }, "./fr/minWords": { "import": { "types": "./fr/minWords.d.mts", "default": "./fr/minWords.mjs" }, "require": { "types": "./fr/minWords.d.cts", "default": "./fr/minWords.cjs" } }, "./fr/multipleOf": { "import": { "types": "./fr/multipleOf.d.mts", "default": "./fr/multipleOf.mjs" }, "require": { "types": "./fr/multipleOf.d.cts", "default": "./fr/multipleOf.cjs" } }, "./fr/nanoid": { "import": { "types": "./fr/nanoid.d.mts", "default": "./fr/nanoid.mjs" }, "require": { "types": "./fr/nanoid.d.cts", "default": "./fr/nanoid.cjs" } }, "./fr/nonEmpty": { "import": { "types": "./fr/nonEmpty.d.mts", "default": "./fr/nonEmpty.mjs" }, "require": { "types": "./fr/nonEmpty.d.cts", "default": "./fr/nonEmpty.cjs" } }, "./fr/notBytes": { "import": { "types": "./fr/notBytes.d.mts", "default": "./fr/notBytes.mjs" }, "require": { "types": "./fr/notBytes.d.cts", "default": "./fr/notBytes.cjs" } }, "./fr/notEntries": { "import": { "types": "./fr/notEntries.d.mts", "default": "./fr/notEntries.mjs" }, "require": { "types": "./fr/notEntries.d.cts", "default": "./fr/notEntries.cjs" } }, "./fr/notGraphemes": { "import": { "types": "./fr/notGraphemes.d.mts", "default": "./fr/notGraphemes.mjs" }, "require": { "types": "./fr/notGraphemes.d.cts", "default": "./fr/notGraphemes.cjs" } }, "./fr/notLength": { "import": { "types": "./fr/notLength.d.mts", "default": "./fr/notLength.mjs" }, "require": { "types": "./fr/notLength.d.cts", "default": "./fr/notLength.cjs" } }, "./fr/notSize": { "import": { "types": "./fr/notSize.d.mts", "default": "./fr/notSize.mjs" }, "require": { "types": "./fr/notSize.d.cts", "default": "./fr/notSize.cjs" } }, "./fr/notValue": { "import": { "types": "./fr/notValue.d.mts", "default": "./fr/notValue.mjs" }, "require": { "types": "./fr/notValue.d.cts", "default": "./fr/notValue.cjs" } }, "./fr/notValues": { "import": { "types": "./fr/notValues.d.mts", "default": "./fr/notValues.mjs" }, "require": { "types": "./fr/notValues.d.cts", "default": "./fr/notValues.cjs" } }, "./fr/notWords": { "import": { "types": "./fr/notWords.d.mts", "default": "./fr/notWords.mjs" }, "require": { "types": "./fr/notWords.d.cts", "default": "./fr/notWords.cjs" } }, "./fr/octal": { "import": { "types": "./fr/octal.d.mts", "default": "./fr/octal.mjs" }, "require": { "types": "./fr/octal.d.cts", "default": "./fr/octal.cjs" } }, "./fr/parseBoolean": { "import": { "types": "./fr/parseBoolean.d.mts", "default": "./fr/parseBoolean.mjs" }, "require": { "types": "./fr/parseBoolean.d.cts", "default": "./fr/parseBoolean.cjs" } }, "./fr/parseJson": { "import": { "types": "./fr/parseJson.d.mts", "default": "./fr/parseJson.mjs" }, "require": { "types": "./fr/parseJson.d.cts", "default": "./fr/parseJson.cjs" } }, "./fr/partialCheck": { "import": { "types": "./fr/partialCheck.d.mts", "default": "./fr/partialCheck.mjs" }, "require": { "types": "./fr/partialCheck.d.cts", "default": "./fr/partialCheck.cjs" } }, "./fr/rawCheck": { "import": { "types": "./fr/rawCheck.d.mts", "default": "./fr/rawCheck.mjs" }, "require": { "types": "./fr/rawCheck.d.cts", "default": "./fr/rawCheck.cjs" } }, "./fr/rawTransform": { "import": { "types": "./fr/rawTransform.d.mts", "default": "./fr/rawTransform.mjs" }, "require": { "types": "./fr/rawTransform.d.cts", "default": "./fr/rawTransform.cjs" } }, "./fr/regex": { "import": { "types": "./fr/regex.d.mts", "default": "./fr/regex.mjs" }, "require": { "types": "./fr/regex.d.cts", "default": "./fr/regex.cjs" } }, "./fr/rfcEmail": { "import": { "types": "./fr/rfcEmail.d.mts", "default": "./fr/rfcEmail.mjs" }, "require": { "types": "./fr/rfcEmail.d.cts", "default": "./fr/rfcEmail.cjs" } }, "./fr/safeInteger": { "import": { "types": "./fr/safeInteger.d.mts", "default": "./fr/safeInteger.mjs" }, "require": { "types": "./fr/safeInteger.d.cts", "default": "./fr/safeInteger.cjs" } }, "./fr/size": { "import": { "types": "./fr/size.d.mts", "default": "./fr/size.mjs" }, "require": { "types": "./fr/size.d.cts", "default": "./fr/size.cjs" } }, "./fr/slug": { "import": { "types": "./fr/slug.d.mts", "default": "./fr/slug.mjs" }, "require": { "types": "./fr/slug.d.cts", "default": "./fr/slug.cjs" } }, "./fr/someItem": { "import": { "types": "./fr/someItem.d.mts", "default": "./fr/someItem.mjs" }, "require": { "types": "./fr/someItem.d.cts", "default": "./fr/someItem.cjs" } }, "./fr/startsWith": { "import": { "types": "./fr/startsWith.d.mts", "default": "./fr/startsWith.mjs" }, "require": { "types": "./fr/startsWith.d.cts", "default": "./fr/startsWith.cjs" } }, "./fr/stringifyJson": { "import": { "types": "./fr/stringifyJson.d.mts", "default": "./fr/stringifyJson.mjs" }, "require": { "types": "./fr/stringifyJson.d.cts", "default": "./fr/stringifyJson.cjs" } }, "./fr/toBigint": { "import": { "types": "./fr/toBigint.d.mts", "default": "./fr/toBigint.mjs" }, "require": { "types": "./fr/toBigint.d.cts", "default": "./fr/toBigint.cjs" } }, "./fr/toDate": { "import": { "types": "./fr/toDate.d.mts", "default": "./fr/toDate.mjs" }, "require": { "types": "./fr/toDate.d.cts", "default": "./fr/toDate.cjs" } }, "./fr/toNumber": { "import": { "types": "./fr/toNumber.d.mts", "default": "./fr/toNumber.mjs" }, "require": { "types": "./fr/toNumber.d.cts", "default": "./fr/toNumber.cjs" } }, "./fr/toString": { "import": { "types": "./fr/toString.d.mts", "default": "./fr/toString.mjs" }, "require": { "types": "./fr/toString.d.cts", "default": "./fr/toString.cjs" } }, "./fr/ulid": { "import": { "types": "./fr/ulid.d.mts", "default": "./fr/ulid.mjs" }, "require": { "types": "./fr/ulid.d.cts", "default": "./fr/ulid.cjs" } }, "./fr/url": { "import": { "types": "./fr/url.d.mts", "default": "./fr/url.mjs" }, "require": { "types": "./fr/url.d.cts", "default": "./fr/url.cjs" } }, "./fr/uuid": { "import": { "types": "./fr/uuid.d.mts", "default": "./fr/uuid.mjs" }, "require": { "types": "./fr/uuid.d.cts", "default": "./fr/uuid.cjs" } }, "./fr/value": { "import": { "types": "./fr/value.d.mts", "default": "./fr/value.mjs" }, "require": { "types": "./fr/value.d.cts", "default": "./fr/value.cjs" } }, "./fr/values": { "import": { "types": "./fr/values.d.mts", "default": "./fr/values.mjs" }, "require": { "types": "./fr/values.d.cts", "default": "./fr/values.cjs" } }, "./fr/words": { "import": { "types": "./fr/words.d.mts", "default": "./fr/words.mjs" }, "require": { "types": "./fr/words.d.cts", "default": "./fr/words.cjs" } }, "./hu": { "import": { "types": "./hu/index.d.mts", "default": "./hu/index.mjs" }, "require": { "types": "./hu/index.d.cts", "default": "./hu/index.cjs" } }, "./hu/schema": { "import": { "types": "./hu/schema.d.mts", "default": "./hu/schema.mjs" }, "require": { "types": "./hu/schema.d.cts", "default": "./hu/schema.cjs" } }, "./hu/base64": { "import": { "types": "./hu/base64.d.mts", "default": "./hu/base64.mjs" }, "require": { "types": "./hu/base64.d.cts", "default": "./hu/base64.cjs" } }, "./hu/bic": { "import": { "types": "./hu/bic.d.mts", "default": "./hu/bic.mjs" }, "require": { "types": "./hu/bic.d.cts", "default": "./hu/bic.cjs" } }, "./hu/bytes": { "import": { "types": "./hu/bytes.d.mts", "default": "./hu/bytes.mjs" }, "require": { "types": "./hu/bytes.d.cts", "default": "./hu/bytes.cjs" } }, "./hu/check": { "import": { "types": "./hu/check.d.mts", "default": "./hu/check.mjs" }, "require": { "types": "./hu/check.d.cts", "default": "./hu/check.cjs" } }, "./hu/checkAsync": { "import": { "types": "./hu/checkAsync.d.mts", "default": "./hu/checkAsync.mjs" }, "require": { "types": "./hu/checkAsync.d.cts", "default": "./hu/checkAsync.cjs" } }, "./hu/checkItems": { "import": { "types": "./hu/checkItems.d.mts", "default": "./hu/checkItems.mjs" }, "require": { "types": "./hu/checkItems.d.cts", "default": "./hu/checkItems.cjs" } }, "./hu/checkItemsAsync": { "import": { "types": "./hu/checkItemsAsync.d.mts", "default": "./hu/checkItemsAsync.mjs" }, "require": { "types": "./hu/checkItemsAsync.d.cts", "default": "./hu/checkItemsAsync.cjs" } }, "./hu/creditCard": { "import": { "types": "./hu/creditCard.d.mts", "default": "./hu/creditCard.mjs" }, "require": { "types": "./hu/creditCard.d.cts", "default": "./hu/creditCard.cjs" } }, "./hu/cuid2": { "import": { "types": "./hu/cuid2.d.mts", "default": "./hu/cuid2.mjs" }, "require": { "types": "./hu/cuid2.d.cts", "default": "./hu/cuid2.cjs" } }, "./hu/decimal": { "import": { "types": "./hu/decimal.d.mts", "default": "./hu/decimal.mjs" }, "require": { "types": "./hu/decimal.d.cts", "default": "./hu/decimal.cjs" } }, "./hu/digits": { "import": { "types": "./hu/digits.d.mts", "default": "./hu/digits.mjs" }, "require": { "types": "./hu/digits.d.cts", "default": "./hu/digits.cjs" } }, "./hu/domain": { "import": { "types": "./hu/domain.d.mts", "default": "./hu/domain.mjs" }, "require": { "types": "./hu/domain.d.cts", "default": "./hu/domain.cjs" } }, "./hu/email": { "import": { "types": "./hu/email.d.mts", "default": "./hu/email.mjs" }, "require": { "types": "./hu/email.d.cts", "default": "./hu/email.cjs" } }, "./hu/emoji": { "import": { "types": "./hu/emoji.d.mts", "default": "./hu/emoji.mjs" }, "require": { "types": "./hu/emoji.d.cts", "default": "./hu/emoji.cjs" } }, "./hu/empty": { "import": { "types": "./hu/empty.d.mts", "default": "./hu/empty.mjs" }, "require": { "types": "./hu/empty.d.cts", "default": "./hu/empty.cjs" } }, "./hu/endsWith": { "import": { "types": "./hu/endsWith.d.mts", "default": "./hu/endsWith.mjs" }, "require": { "types": "./hu/endsWith.d.cts", "default": "./hu/endsWith.cjs" } }, "./hu/entries": { "import": { "types": "./hu/entries.d.mts", "default": "./hu/entries.mjs" }, "require": { "types": "./hu/entries.d.cts", "default": "./hu/entries.cjs" } }, "./hu/everyItem": { "import": { "types": "./hu/everyItem.d.mts", "default": "./hu/everyItem.mjs" }, "require": { "types": "./hu/everyItem.d.cts", "default": "./hu/everyItem.cjs" } }, "./hu/excludes": { "import": { "types": "./hu/excludes.d.mts", "default": "./hu/excludes.mjs" }, "require": { "types": "./hu/excludes.d.cts", "default": "./hu/excludes.cjs" } }, "./hu/finite": { "import": { "types": "./hu/finite.d.mts", "default": "./hu/finite.mjs" }, "require": { "types": "./hu/finite.d.cts", "default": "./hu/finite.cjs" } }, "./hu/graphemes": { "import": { "types": "./hu/graphemes.d.mts", "default": "./hu/graphemes.mjs" }, "require": { "types": "./hu/graphemes.d.cts", "default": "./hu/graphemes.cjs" } }, "./hu/gtValue": { "import": { "types": "./hu/gtValue.d.mts", "default": "./hu/gtValue.mjs" }, "require": { "types": "./hu/gtValue.d.cts", "default": "./hu/gtValue.cjs" } }, "./hu/guard": { "import": { "types": "./hu/guard.d.mts", "default": "./hu/guard.mjs" }, "require": { "types": "./hu/guard.d.cts", "default": "./hu/guard.cjs" } }, "./hu/hash": { "import": { "types": "./hu/hash.d.mts", "default": "./hu/hash.mjs" }, "require": { "types": "./hu/hash.d.cts", "default": "./hu/hash.cjs" } }, "./hu/hexadecimal": { "import": { "types": "./hu/hexadecimal.d.mts", "default": "./hu/hexadecimal.mjs" }, "require": { "types": "./hu/hexadecimal.d.cts", "default": "./hu/hexadecimal.cjs" } }, "./hu/hexColor": { "import": { "types": "./hu/hexColor.d.mts", "default": "./hu/hexColor.mjs" }, "require": { "types": "./hu/hexColor.d.cts", "default": "./hu/hexColor.cjs" } }, "./hu/imei": { "import": { "types": "./hu/imei.d.mts", "default": "./hu/imei.mjs" }, "require": { "types": "./hu/imei.d.cts", "default": "./hu/imei.cjs" } }, "./hu/includes": { "import": { "types": "./hu/includes.d.mts", "default": "./hu/includes.mjs" }, "require": { "types": "./hu/includes.d.cts", "default": "./hu/includes.cjs" } }, "./hu/integer": { "import": { "types": "./hu/integer.d.mts", "default": "./hu/integer.mjs" }, "require": { "types": "./hu/integer.d.cts", "default": "./hu/integer.cjs" } }, "./hu/ip": { "import": { "types": "./hu/ip.d.mts", "default": "./hu/ip.mjs" }, "require": { "types": "./hu/ip.d.cts", "default": "./hu/ip.cjs" } }, "./hu/ipv4": { "import": { "types": "./hu/ipv4.d.mts", "default": "./hu/ipv4.mjs" }, "require": { "types": "./hu/ipv4.d.cts", "default": "./hu/ipv4.cjs" } }, "./hu/ipv6": { "import": { "types": "./hu/ipv6.d.mts", "default": "./hu/ipv6.mjs" }, "require": { "types": "./hu/ipv6.d.cts", "default": "./hu/ipv6.cjs" } }, "./hu/isbn": { "import": { "types": "./hu/isbn.d.mts", "default": "./hu/isbn.mjs" }, "require": { "types": "./hu/isbn.d.cts", "default": "./hu/isbn.cjs" } }, "./hu/isoDate": { "import": { "types": "./hu/isoDate.d.mts", "default": "./hu/isoDate.mjs" }, "require": { "types": "./hu/isoDate.d.cts", "default": "./hu/isoDate.cjs" } }, "./hu/isoDateTime": { "import": { "types": "./hu/isoDateTime.d.mts", "default": "./hu/isoDateTime.mjs" }, "require": { "types": "./hu/isoDateTime.d.cts", "default": "./hu/isoDateTime.cjs" } }, "./hu/isoTime": { "import": { "types": "./hu/isoTime.d.mts", "default": "./hu/isoTime.mjs" }, "require": { "types": "./hu/isoTime.d.cts", "default": "./hu/isoTime.cjs" } }, "./hu/isoTimeSecond": { "import": { "types": "./hu/isoTimeSecond.d.mts", "default": "./hu/isoTimeSecond.mjs" }, "require": { "types": "./hu/isoTimeSecond.d.cts", "default": "./hu/isoTimeSecond.cjs" } }, "./hu/isoTimestamp": { "import": { "types": "./hu/isoTimestamp.d.mts", "default": "./hu/isoTimestamp.mjs" }, "require": { "types": "./hu/isoTimestamp.d.cts", "default": "./hu/isoTimestamp.cjs" } }, "./hu/isoWeek": { "import": { "types": "./hu/isoWeek.d.mts", "default": "./hu/isoWeek.mjs" }, "require": { "types": "./hu/isoWeek.d.cts", "default": "./hu/isoWeek.cjs" } }, "./hu/isrc": { "import": { "types": "./hu/isrc.d.mts", "default": "./hu/isrc.mjs" }, "require": { "types": "./hu/isrc.d.cts", "default": "./hu/isrc.cjs" } }, "./hu/jwsCompact": { "import": { "types": "./hu/jwsCompact.d.mts", "default": "./hu/jwsCompact.mjs" }, "require": { "types": "./hu/jwsCompact.d.cts", "default": "./hu/jwsCompact.cjs" } }, "./hu/length": { "import": { "types": "./hu/length.d.mts", "default": "./hu/length.mjs" }, "require": { "types": "./hu/length.d.cts", "default": "./hu/length.cjs" } }, "./hu/ltValue": { "import": { "types": "./hu/ltValue.d.mts", "default": "./hu/ltValue.mjs" }, "require": { "types": "./hu/ltValue.d.cts", "default": "./hu/ltValue.cjs" } }, "./hu/mac": { "import": { "types": "./hu/mac.d.mts", "default": "./hu/mac.mjs" }, "require": { "types": "./hu/mac.d.cts", "default": "./hu/mac.cjs" } }, "./hu/mac48": { "import": { "types": "./hu/mac48.d.mts", "default": "./hu/mac48.mjs" }, "require": { "types": "./hu/mac48.d.cts", "default": "./hu/mac48.cjs" } }, "./hu/mac64": { "import": { "types": "./hu/mac64.d.mts", "default": "./hu/mac64.mjs" }, "require": { "types": "./hu/mac64.d.cts", "default": "./hu/mac64.cjs" } }, "./hu/maxBytes": { "import": { "types": "./hu/maxBytes.d.mts", "default": "./hu/maxBytes.mjs" }, "require": { "types": "./hu/maxBytes.d.cts", "default": "./hu/maxBytes.cjs" } }, "./hu/maxEntries": { "import": { "types": "./hu/maxEntries.d.mts", "default": "./hu/maxEntries.mjs" }, "require": { "types": "./hu/maxEntries.d.cts", "default": "./hu/maxEntries.cjs" } }, "./hu/maxGraphemes": { "import": { "types": "./hu/maxGraphemes.d.mts", "default": "./hu/maxGraphemes.mjs" }, "require": { "types": "./hu/maxGraphemes.d.cts", "default": "./hu/maxGraphemes.cjs" } }, "./hu/maxLength": { "import": { "types": "./hu/maxLength.d.mts", "default": "./hu/maxLength.mjs" }, "require": { "types": "./hu/maxLength.d.cts", "default": "./hu/maxLength.cjs" } }, "./hu/maxSize": { "import": { "types": "./hu/maxSize.d.mts", "default": "./hu/maxSize.mjs" }, "require": { "types": "./hu/maxSize.d.cts", "default": "./hu/maxSize.cjs" } }, "./hu/maxValue": { "import": { "types": "./hu/maxValue.d.mts", "default": "./hu/maxValue.mjs" }, "require": { "types": "./hu/maxValue.d.cts", "default": "./hu/maxValue.cjs" } }, "./hu/maxWords": { "import": { "types": "./hu/maxWords.d.mts", "default": "./hu/maxWords.mjs" }, "require": { "types": "./hu/maxWords.d.cts", "default": "./hu/maxWords.cjs" } }, "./hu/mimeType": { "import": { "types": "./hu/mimeType.d.mts", "default": "./hu/mimeType.mjs" }, "require": { "types": "./hu/mimeType.d.cts", "default": "./hu/mimeType.cjs" } }, "./hu/minBytes": { "import": { "types": "./hu/minBytes.d.mts", "default": "./hu/minBytes.mjs" }, "require": { "types": "./hu/minBytes.d.cts", "default": "./hu/minBytes.cjs" } }, "./hu/minEntries": { "import": { "types": "./hu/minEntries.d.mts", "default": "./hu/minEntries.mjs" }, "require": { "types": "./hu/minEntries.d.cts", "default": "./hu/minEntries.cjs" } }, "./hu/minGraphemes": { "import": { "types": "./hu/minGraphemes.d.mts", "default": "./hu/minGraphemes.mjs" }, "require": { "types": "./hu/minGraphemes.d.cts", "default": "./hu/minGraphemes.cjs" } }, "./hu/minLength": { "import": { "types": "./hu/minLength.d.mts", "default": "./hu/minLength.mjs" }, "require": { "types": "./hu/minLength.d.cts", "default": "./hu/minLength.cjs" } }, "./hu/minSize": { "import": { "types": "./hu/minSize.d.mts", "default": "./hu/minSize.mjs" }, "require": { "types": "./hu/minSize.d.cts", "default": "./hu/minSize.cjs" } }, "./hu/minValue": { "import": { "types": "./hu/minValue.d.mts", "default": "./hu/minValue.mjs" }, "require": { "types": "./hu/minValue.d.cts", "default": "./hu/minValue.cjs" } }, "./hu/minWords": { "import": { "types": "./hu/minWords.d.mts", "default": "./hu/minWords.mjs" }, "require": { "types": "./hu/minWords.d.cts", "default": "./hu/minWords.cjs" } }, "./hu/multipleOf": { "import": { "types": "./hu/multipleOf.d.mts", "default": "./hu/multipleOf.mjs" }, "require": { "types": "./hu/multipleOf.d.cts", "default": "./hu/multipleOf.cjs" } }, "./hu/nanoid": { "import": { "types": "./hu/nanoid.d.mts", "default": "./hu/nanoid.mjs" }, "require": { "types": "./hu/nanoid.d.cts", "default": "./hu/nanoid.cjs" } }, "./hu/nonEmpty": { "import": { "types": "./hu/nonEmpty.d.mts", "default": "./hu/nonEmpty.mjs" }, "require": { "types": "./hu/nonEmpty.d.cts", "default": "./hu/nonEmpty.cjs" } }, "./hu/notBytes": { "import": { "types": "./hu/notBytes.d.mts", "default": "./hu/notBytes.mjs" }, "require": { "types": "./hu/notBytes.d.cts", "default": "./hu/notBytes.cjs" } }, "./hu/notEntries": { "import": { "types": "./hu/notEntries.d.mts", "default": "./hu/notEntries.mjs" }, "require": { "types": "./hu/notEntries.d.cts", "default": "./hu/notEntries.cjs" } }, "./hu/notGraphemes": { "import": { "types": "./hu/notGraphemes.d.mts", "default": "./hu/notGraphemes.mjs" }, "require": { "types": "./hu/notGraphemes.d.cts", "default": "./hu/notGraphemes.cjs" } }, "./hu/notLength": { "import": { "types": "./hu/notLength.d.mts", "default": "./hu/notLength.mjs" }, "require": { "types": "./hu/notLength.d.cts", "default": "./hu/notLength.cjs" } }, "./hu/notSize": { "import": { "types": "./hu/notSize.d.mts", "default": "./hu/notSize.mjs" }, "require": { "types": "./hu/notSize.d.cts", "default": "./hu/notSize.cjs" } }, "./hu/notValue": { "import": { "types": "./hu/notValue.d.mts", "default": "./hu/notValue.mjs" }, "require": { "types": "./hu/notValue.d.cts", "default": "./hu/notValue.cjs" } }, "./hu/notValues": { "import": { "types": "./hu/notValues.d.mts", "default": "./hu/notValues.mjs" }, "require": { "types": "./hu/notValues.d.cts", "default": "./hu/notValues.cjs" } }, "./hu/notWords": { "import": { "types": "./hu/notWords.d.mts", "default": "./hu/notWords.mjs" }, "require": { "types": "./hu/notWords.d.cts", "default": "./hu/notWords.cjs" } }, "./hu/octal": { "import": { "types": "./hu/octal.d.mts", "default": "./hu/octal.mjs" }, "require": { "types": "./hu/octal.d.cts", "default": "./hu/octal.cjs" } }, "./hu/parseBoolean": { "import": { "types": "./hu/parseBoolean.d.mts", "default": "./hu/parseBoolean.mjs" }, "require": { "types": "./hu/parseBoolean.d.cts", "default": "./hu/parseBoolean.cjs" } }, "./hu/parseJson": { "import": { "types": "./hu/parseJson.d.mts", "default": "./hu/parseJson.mjs" }, "require": { "types": "./hu/parseJson.d.cts", "default": "./hu/parseJson.cjs" } }, "./hu/partialCheck": { "import": { "types": "./hu/partialCheck.d.mts", "default": "./hu/partialCheck.mjs" }, "require": { "types": "./hu/partialCheck.d.cts", "default": "./hu/partialCheck.cjs" } }, "./hu/rawCheck": { "import": { "types": "./hu/rawCheck.d.mts", "default": "./hu/rawCheck.mjs" }, "require": { "types": "./hu/rawCheck.d.cts", "default": "./hu/rawCheck.cjs" } }, "./hu/rawTransform": { "import": { "types": "./hu/rawTransform.d.mts", "default": "./hu/rawTransform.mjs" }, "require": { "types": "./hu/rawTransform.d.cts", "default": "./hu/rawTransform.cjs" } }, "./hu/regex": { "import": { "types": "./hu/regex.d.mts", "default": "./hu/regex.mjs" }, "require": { "types": "./hu/regex.d.cts", "default": "./hu/regex.cjs" } }, "./hu/rfcEmail": { "import": { "types": "./hu/rfcEmail.d.mts", "default": "./hu/rfcEmail.mjs" }, "require": { "types": "./hu/rfcEmail.d.cts", "default": "./hu/rfcEmail.cjs" } }, "./hu/safeInteger": { "import": { "types": "./hu/safeInteger.d.mts", "default": "./hu/safeInteger.mjs" }, "require": { "types": "./hu/safeInteger.d.cts", "default": "./hu/safeInteger.cjs" } }, "./hu/size": { "import": { "types": "./hu/size.d.mts", "default": "./hu/size.mjs" }, "require": { "types": "./hu/size.d.cts", "default": "./hu/size.cjs" } }, "./hu/slug": { "import": { "types": "./hu/slug.d.mts", "default": "./hu/slug.mjs" }, "require": { "types": "./hu/slug.d.cts", "default": "./hu/slug.cjs" } }, "./hu/someItem": { "import": { "types": "./hu/someItem.d.mts", "default": "./hu/someItem.mjs" }, "require": { "types": "./hu/someItem.d.cts", "default": "./hu/someItem.cjs" } }, "./hu/startsWith": { "import": { "types": "./hu/startsWith.d.mts", "default": "./hu/startsWith.mjs" }, "require": { "types": "./hu/startsWith.d.cts", "default": "./hu/startsWith.cjs" } }, "./hu/stringifyJson": { "import": { "types": "./hu/stringifyJson.d.mts", "default": "./hu/stringifyJson.mjs" }, "require": { "types": "./hu/stringifyJson.d.cts", "default": "./hu/stringifyJson.cjs" } }, "./hu/toBigint": { "import": { "types": "./hu/toBigint.d.mts", "default": "./hu/toBigint.mjs" }, "require": { "types": "./hu/toBigint.d.cts", "default": "./hu/toBigint.cjs" } }, "./hu/toDate": { "import": { "types": "./hu/toDate.d.mts", "default": "./hu/toDate.mjs" }, "require": { "types": "./hu/toDate.d.cts", "default": "./hu/toDate.cjs" } }, "./hu/toNumber": { "import": { "types": "./hu/toNumber.d.mts", "default": "./hu/toNumber.mjs" }, "require": { "types": "./hu/toNumber.d.cts", "default": "./hu/toNumber.cjs" } }, "./hu/toString": { "import": { "types": "./hu/toString.d.mts", "default": "./hu/toString.mjs" }, "require": { "types": "./hu/toString.d.cts", "default": "./hu/toString.cjs" } }, "./hu/ulid": { "import": { "types": "./hu/ulid.d.mts", "default": "./hu/ulid.mjs" }, "require": { "types": "./hu/ulid.d.cts", "default": "./hu/ulid.cjs" } }, "./hu/url": { "import": { "types": "./hu/url.d.mts", "default": "./hu/url.mjs" }, "require": { "types": "./hu/url.d.cts", "default": "./hu/url.cjs" } }, "./hu/uuid": { "import": { "types": "./hu/uuid.d.mts", "default": "./hu/uuid.mjs" }, "require": { "types": "./hu/uuid.d.cts", "default": "./hu/uuid.cjs" } }, "./hu/value": { "import": { "types": "./hu/value.d.mts", "default": "./hu/value.mjs" }, "require": { "types": "./hu/value.d.cts", "default": "./hu/value.cjs" } }, "./hu/values": { "import": { "types": "./hu/values.d.mts", "default": "./hu/values.mjs" }, "require": { "types": "./hu/values.d.cts", "default": "./hu/values.cjs" } }, "./hu/words": { "import": { "types": "./hu/words.d.mts", "default": "./hu/words.mjs" }, "require": { "types": "./hu/words.d.cts", "default": "./hu/words.cjs" } }, "./id": { "import": { "types": "./id/index.d.mts", "default": "./id/index.mjs" }, "require": { "types": "./id/index.d.cts", "default": "./id/index.cjs" } }, "./id/schema": { "import": { "types": "./id/schema.d.mts", "default": "./id/schema.mjs" }, "require": { "types": "./id/schema.d.cts", "default": "./id/schema.cjs" } }, "./id/base64": { "import": { "types": "./id/base64.d.mts", "default": "./id/base64.mjs" }, "require": { "types": "./id/base64.d.cts", "default": "./id/base64.cjs" } }, "./id/bic": { "import": { "types": "./id/bic.d.mts", "default": "./id/bic.mjs" }, "require": { "types": "./id/bic.d.cts", "default": "./id/bic.cjs" } }, "./id/bytes": { "import": { "types": "./id/bytes.d.mts", "default": "./id/bytes.mjs" }, "require": { "types": "./id/bytes.d.cts", "default": "./id/bytes.cjs" } }, "./id/check": { "import": { "types": "./id/check.d.mts", "default": "./id/check.mjs" }, "require": { "types": "./id/check.d.cts", "default": "./id/check.cjs" } }, "./id/checkAsync": { "import": { "types": "./id/checkAsync.d.mts", "default": "./id/checkAsync.mjs" }, "require": { "types": "./id/checkAsync.d.cts", "default": "./id/checkAsync.cjs" } }, "./id/checkItems": { "import": { "types": "./id/checkItems.d.mts", "default": "./id/checkItems.mjs" }, "require": { "types": "./id/checkItems.d.cts", "default": "./id/checkItems.cjs" } }, "./id/checkItemsAsync": { "import": { "types": "./id/checkItemsAsync.d.mts", "default": "./id/checkItemsAsync.mjs" }, "require": { "types": "./id/checkItemsAsync.d.cts", "default": "./id/checkItemsAsync.cjs" } }, "./id/creditCard": { "import": { "types": "./id/creditCard.d.mts", "default": "./id/creditCard.mjs" }, "require": { "types": "./id/creditCard.d.cts", "default": "./id/creditCard.cjs" } }, "./id/cuid2": { "import": { "types": "./id/cuid2.d.mts", "default": "./id/cuid2.mjs" }, "require": { "types": "./id/cuid2.d.cts", "default": "./id/cuid2.cjs" } }, "./id/decimal": { "import": { "types": "./id/decimal.d.mts", "default": "./id/decimal.mjs" }, "require": { "types": "./id/decimal.d.cts", "default": "./id/decimal.cjs" } }, "./id/digits": { "import": { "types": "./id/digits.d.mts", "default": "./id/digits.mjs" }, "require": { "types": "./id/digits.d.cts", "default": "./id/digits.cjs" } }, "./id/domain": { "import": { "types": "./id/domain.d.mts", "default": "./id/domain.mjs" }, "require": { "types": "./id/domain.d.cts", "default": "./id/domain.cjs" } }, "./id/email": { "import": { "types": "./id/email.d.mts", "default": "./id/email.mjs" }, "require": { "types": "./id/email.d.cts", "default": "./id/email.cjs" } }, "./id/emoji": { "import": { "types": "./id/emoji.d.mts", "default": "./id/emoji.mjs" }, "require": { "types": "./id/emoji.d.cts", "default": "./id/emoji.cjs" } }, "./id/empty": { "import": { "types": "./id/empty.d.mts", "default": "./id/empty.mjs" }, "require": { "types": "./id/empty.d.cts", "default": "./id/empty.cjs" } }, "./id/endsWith": { "import": { "types": "./id/endsWith.d.mts", "default": "./id/endsWith.mjs" }, "require": { "types": "./id/endsWith.d.cts", "default": "./id/endsWith.cjs" } }, "./id/entries": { "import": { "types": "./id/entries.d.mts", "default": "./id/entries.mjs" }, "require": { "types": "./id/entries.d.cts", "default": "./id/entries.cjs" } }, "./id/everyItem": { "import": { "types": "./id/everyItem.d.mts", "default": "./id/everyItem.mjs" }, "require": { "types": "./id/everyItem.d.cts", "default": "./id/everyItem.cjs" } }, "./id/excludes": { "import": { "types": "./id/excludes.d.mts", "default": "./id/excludes.mjs" }, "require": { "types": "./id/excludes.d.cts", "default": "./id/excludes.cjs" } }, "./id/finite": { "import": { "types": "./id/finite.d.mts", "default": "./id/finite.mjs" }, "require": { "types": "./id/finite.d.cts", "default": "./id/finite.cjs" } }, "./id/graphemes": { "import": { "types": "./id/graphemes.d.mts", "default": "./id/graphemes.mjs" }, "require": { "types": "./id/graphemes.d.cts", "default": "./id/graphemes.cjs" } }, "./id/gtValue": { "import": { "types": "./id/gtValue.d.mts", "default": "./id/gtValue.mjs" }, "require": { "types": "./id/gtValue.d.cts", "default": "./id/gtValue.cjs" } }, "./id/guard": { "import": { "types": "./id/guard.d.mts", "default": "./id/guard.mjs" }, "require": { "types": "./id/guard.d.cts", "default": "./id/guard.cjs" } }, "./id/hash": { "import": { "types": "./id/hash.d.mts", "default": "./id/hash.mjs" }, "require": { "types": "./id/hash.d.cts", "default": "./id/hash.cjs" } }, "./id/hexadecimal": { "import": { "types": "./id/hexadecimal.d.mts", "default": "./id/hexadecimal.mjs" }, "require": { "types": "./id/hexadecimal.d.cts", "default": "./id/hexadecimal.cjs" } }, "./id/hexColor": { "import": { "types": "./id/hexColor.d.mts", "default": "./id/hexColor.mjs" }, "require": { "types": "./id/hexColor.d.cts", "default": "./id/hexColor.cjs" } }, "./id/imei": { "import": { "types": "./id/imei.d.mts", "default": "./id/imei.mjs" }, "require": { "types": "./id/imei.d.cts", "default": "./id/imei.cjs" } }, "./id/includes": { "import": { "types": "./id/includes.d.mts", "default": "./id/includes.mjs" }, "require": { "types": "./id/includes.d.cts", "default": "./id/includes.cjs" } }, "./id/integer": { "import": { "types": "./id/integer.d.mts", "default": "./id/integer.mjs" }, "require": { "types": "./id/integer.d.cts", "default": "./id/integer.cjs" } }, "./id/ip": { "import": { "types": "./id/ip.d.mts", "default": "./id/ip.mjs" }, "require": { "types": "./id/ip.d.cts", "default": "./id/ip.cjs" } }, "./id/ipv4": { "import": { "types": "./id/ipv4.d.mts", "default": "./id/ipv4.mjs" }, "require": { "types": "./id/ipv4.d.cts", "default": "./id/ipv4.cjs" } }, "./id/ipv6": { "import": { "types": "./id/ipv6.d.mts", "default": "./id/ipv6.mjs" }, "require": { "types": "./id/ipv6.d.cts", "default": "./id/ipv6.cjs" } }, "./id/isbn": { "import": { "types": "./id/isbn.d.mts", "default": "./id/isbn.mjs" }, "require": { "types": "./id/isbn.d.cts", "default": "./id/isbn.cjs" } }, "./id/isoDate": { "import": { "types": "./id/isoDate.d.mts", "default": "./id/isoDate.mjs" }, "require": { "types": "./id/isoDate.d.cts", "default": "./id/isoDate.cjs" } }, "./id/isoDateTime": { "import": { "types": "./id/isoDateTime.d.mts", "default": "./id/isoDateTime.mjs" }, "require": { "types": "./id/isoDateTime.d.cts", "default": "./id/isoDateTime.cjs" } }, "./id/isoTime": { "import": { "types": "./id/isoTime.d.mts", "default": "./id/isoTime.mjs" }, "require": { "types": "./id/isoTime.d.cts", "default": "./id/isoTime.cjs" } }, "./id/isoTimeSecond": { "import": { "types": "./id/isoTimeSecond.d.mts", "default": "./id/isoTimeSecond.mjs" }, "require": { "types": "./id/isoTimeSecond.d.cts", "default": "./id/isoTimeSecond.cjs" } }, "./id/isoTimestamp": { "import": { "types": "./id/isoTimestamp.d.mts", "default": "./id/isoTimestamp.mjs" }, "require": { "types": "./id/isoTimestamp.d.cts", "default": "./id/isoTimestamp.cjs" } }, "./id/isoWeek": { "import": { "types": "./id/isoWeek.d.mts", "default": "./id/isoWeek.mjs" }, "require": { "types": "./id/isoWeek.d.cts", "default": "./id/isoWeek.cjs" } }, "./id/isrc": { "import": { "types": "./id/isrc.d.mts", "default": "./id/isrc.mjs" }, "require": { "types": "./id/isrc.d.cts", "default": "./id/isrc.cjs" } }, "./id/jwsCompact": { "import": { "types": "./id/jwsCompact.d.mts", "default": "./id/jwsCompact.mjs" }, "require": { "types": "./id/jwsCompact.d.cts", "default": "./id/jwsCompact.cjs" } }, "./id/length": { "import": { "types": "./id/length.d.mts", "default": "./id/length.mjs" }, "require": { "types": "./id/length.d.cts", "default": "./id/length.cjs" } }, "./id/ltValue": { "import": { "types": "./id/ltValue.d.mts", "default": "./id/ltValue.mjs" }, "require": { "types": "./id/ltValue.d.cts", "default": "./id/ltValue.cjs" } }, "./id/mac": { "import": { "types": "./id/mac.d.mts", "default": "./id/mac.mjs" }, "require": { "types": "./id/mac.d.cts", "default": "./id/mac.cjs" } }, "./id/mac48": { "import": { "types": "./id/mac48.d.mts", "default": "./id/mac48.mjs" }, "require": { "types": "./id/mac48.d.cts", "default": "./id/mac48.cjs" } }, "./id/mac64": { "import": { "types": "./id/mac64.d.mts", "default": "./id/mac64.mjs" }, "require": { "types": "./id/mac64.d.cts", "default": "./id/mac64.cjs" } }, "./id/maxBytes": { "import": { "types": "./id/maxBytes.d.mts", "default": "./id/maxBytes.mjs" }, "require": { "types": "./id/maxBytes.d.cts", "default": "./id/maxBytes.cjs" } }, "./id/maxEntries": { "import": { "types": "./id/maxEntries.d.mts", "default": "./id/maxEntries.mjs" }, "require": { "types": "./id/maxEntries.d.cts", "default": "./id/maxEntries.cjs" } }, "./id/maxGraphemes": { "import": { "types": "./id/maxGraphemes.d.mts", "default": "./id/maxGraphemes.mjs" }, "require": { "types": "./id/maxGraphemes.d.cts", "default": "./id/maxGraphemes.cjs" } }, "./id/maxLength": { "import": { "types": "./id/maxLength.d.mts", "default": "./id/maxLength.mjs" }, "require": { "types": "./id/maxLength.d.cts", "default": "./id/maxLength.cjs" } }, "./id/maxSize": { "import": { "types": "./id/maxSize.d.mts", "default": "./id/maxSize.mjs" }, "require": { "types": "./id/maxSize.d.cts", "default": "./id/maxSize.cjs" } }, "./id/maxValue": { "import": { "types": "./id/maxValue.d.mts", "default": "./id/maxValue.mjs" }, "require": { "types": "./id/maxValue.d.cts", "default": "./id/maxValue.cjs" } }, "./id/maxWords": { "import": { "types": "./id/maxWords.d.mts", "default": "./id/maxWords.mjs" }, "require": { "types": "./id/maxWords.d.cts", "default": "./id/maxWords.cjs" } }, "./id/mimeType": { "import": { "types": "./id/mimeType.d.mts", "default": "./id/mimeType.mjs" }, "require": { "types": "./id/mimeType.d.cts", "default": "./id/mimeType.cjs" } }, "./id/minBytes": { "import": { "types": "./id/minBytes.d.mts", "default": "./id/minBytes.mjs" }, "require": { "types": "./id/minBytes.d.cts", "default": "./id/minBytes.cjs" } }, "./id/minEntries": { "import": { "types": "./id/minEntries.d.mts", "default": "./id/minEntries.mjs" }, "require": { "types": "./id/minEntries.d.cts", "default": "./id/minEntries.cjs" } }, "./id/minGraphemes": { "import": { "types": "./id/minGraphemes.d.mts", "default": "./id/minGraphemes.mjs" }, "require": { "types": "./id/minGraphemes.d.cts", "default": "./id/minGraphemes.cjs" } }, "./id/minLength": { "import": { "types": "./id/minLength.d.mts", "default": "./id/minLength.mjs" }, "require": { "types": "./id/minLength.d.cts", "default": "./id/minLength.cjs" } }, "./id/minSize": { "import": { "types": "./id/minSize.d.mts", "default": "./id/minSize.mjs" }, "require": { "types": "./id/minSize.d.cts", "default": "./id/minSize.cjs" } }, "./id/minValue": { "import": { "types": "./id/minValue.d.mts", "default": "./id/minValue.mjs" }, "require": { "types": "./id/minValue.d.cts", "default": "./id/minValue.cjs" } }, "./id/minWords": { "import": { "types": "./id/minWords.d.mts", "default": "./id/minWords.mjs" }, "require": { "types": "./id/minWords.d.cts", "default": "./id/minWords.cjs" } }, "./id/multipleOf": { "import": { "types": "./id/multipleOf.d.mts", "default": "./id/multipleOf.mjs" }, "require": { "types": "./id/multipleOf.d.cts", "default": "./id/multipleOf.cjs" } }, "./id/nanoid": { "import": { "types": "./id/nanoid.d.mts", "default": "./id/nanoid.mjs" }, "require": { "types": "./id/nanoid.d.cts", "default": "./id/nanoid.cjs" } }, "./id/nonEmpty": { "import": { "types": "./id/nonEmpty.d.mts", "default": "./id/nonEmpty.mjs" }, "require": { "types": "./id/nonEmpty.d.cts", "default": "./id/nonEmpty.cjs" } }, "./id/notBytes": { "import": { "types": "./id/notBytes.d.mts", "default": "./id/notBytes.mjs" }, "require": { "types": "./id/notBytes.d.cts", "default": "./id/notBytes.cjs" } }, "./id/notEntries": { "import": { "types": "./id/notEntries.d.mts", "default": "./id/notEntries.mjs" }, "require": { "types": "./id/notEntries.d.cts", "default": "./id/notEntries.cjs" } }, "./id/notGraphemes": { "import": { "types": "./id/notGraphemes.d.mts", "default": "./id/notGraphemes.mjs" }, "require": { "types": "./id/notGraphemes.d.cts", "default": "./id/notGraphemes.cjs" } }, "./id/notLength": { "import": { "types": "./id/notLength.d.mts", "default": "./id/notLength.mjs" }, "require": { "types": "./id/notLength.d.cts", "default": "./id/notLength.cjs" } }, "./id/notSize": { "import": { "types": "./id/notSize.d.mts", "default": "./id/notSize.mjs" }, "require": { "types": "./id/notSize.d.cts", "default": "./id/notSize.cjs" } }, "./id/notValue": { "import": { "types": "./id/notValue.d.mts", "default": "./id/notValue.mjs" }, "require": { "types": "./id/notValue.d.cts", "default": "./id/notValue.cjs" } }, "./id/notValues": { "import": { "types": "./id/notValues.d.mts", "default": "./id/notValues.mjs" }, "require": { "types": "./id/notValues.d.cts", "default": "./id/notValues.cjs" } }, "./id/notWords": { "import": { "types": "./id/notWords.d.mts", "default": "./id/notWords.mjs" }, "require": { "types": "./id/notWords.d.cts", "default": "./id/notWords.cjs" } }, "./id/octal": { "import": { "types": "./id/octal.d.mts", "default": "./id/octal.mjs" }, "require": { "types": "./id/octal.d.cts", "default": "./id/octal.cjs" } }, "./id/parseBoolean": { "import": { "types": "./id/parseBoolean.d.mts", "default": "./id/parseBoolean.mjs" }, "require": { "types": "./id/parseBoolean.d.cts", "default": "./id/parseBoolean.cjs" } }, "./id/parseJson": { "import": { "types": "./id/parseJson.d.mts", "default": "./id/parseJson.mjs" }, "require": { "types": "./id/parseJson.d.cts", "default": "./id/parseJson.cjs" } }, "./id/partialCheck": { "import": { "types": "./id/partialCheck.d.mts", "default": "./id/partialCheck.mjs" }, "require": { "types": "./id/partialCheck.d.cts", "default": "./id/partialCheck.cjs" } }, "./id/rawCheck": { "import": { "types": "./id/rawCheck.d.mts", "default": "./id/rawCheck.mjs" }, "require": { "types": "./id/rawCheck.d.cts", "default": "./id/rawCheck.cjs" } }, "./id/rawTransform": { "import": { "types": "./id/rawTransform.d.mts", "default": "./id/rawTransform.mjs" }, "require": { "types": "./id/rawTransform.d.cts", "default": "./id/rawTransform.cjs" } }, "./id/regex": { "import": { "types": "./id/regex.d.mts", "default": "./id/regex.mjs" }, "require": { "types": "./id/regex.d.cts", "default": "./id/regex.cjs" } }, "./id/rfcEmail": { "import": { "types": "./id/rfcEmail.d.mts", "default": "./id/rfcEmail.mjs" }, "require": { "types": "./id/rfcEmail.d.cts", "default": "./id/rfcEmail.cjs" } }, "./id/safeInteger": { "import": { "types": "./id/safeInteger.d.mts", "default": "./id/safeInteger.mjs" }, "require": { "types": "./id/safeInteger.d.cts", "default": "./id/safeInteger.cjs" } }, "./id/size": { "import": { "types": "./id/size.d.mts", "default": "./id/size.mjs" }, "require": { "types": "./id/size.d.cts", "default": "./id/size.cjs" } }, "./id/slug": { "import": { "types": "./id/slug.d.mts", "default": "./id/slug.mjs" }, "require": { "types": "./id/slug.d.cts", "default": "./id/slug.cjs" } }, "./id/someItem": { "import": { "types": "./id/someItem.d.mts", "default": "./id/someItem.mjs" }, "require": { "types": "./id/someItem.d.cts", "default": "./id/someItem.cjs" } }, "./id/startsWith": { "import": { "types": "./id/startsWith.d.mts", "default": "./id/startsWith.mjs" }, "require": { "types": "./id/startsWith.d.cts", "default": "./id/startsWith.cjs" } }, "./id/stringifyJson": { "import": { "types": "./id/stringifyJson.d.mts", "default": "./id/stringifyJson.mjs" }, "require": { "types": "./id/stringifyJson.d.cts", "default": "./id/stringifyJson.cjs" } }, "./id/toBigint": { "import": { "types": "./id/toBigint.d.mts", "default": "./id/toBigint.mjs" }, "require": { "types": "./id/toBigint.d.cts", "default": "./id/toBigint.cjs" } }, "./id/toDate": { "import": { "types": "./id/toDate.d.mts", "default": "./id/toDate.mjs" }, "require": { "types": "./id/toDate.d.cts", "default": "./id/toDate.cjs" } }, "./id/toNumber": { "import": { "types": "./id/toNumber.d.mts", "default": "./id/toNumber.mjs" }, "require": { "types": "./id/toNumber.d.cts", "default": "./id/toNumber.cjs" } }, "./id/toString": { "import": { "types": "./id/toString.d.mts", "default": "./id/toString.mjs" }, "require": { "types": "./id/toString.d.cts", "default": "./id/toString.cjs" } }, "./id/ulid": { "import": { "types": "./id/ulid.d.mts", "default": "./id/ulid.mjs" }, "require": { "types": "./id/ulid.d.cts", "default": "./id/ulid.cjs" } }, "./id/url": { "import": { "types": "./id/url.d.mts", "default": "./id/url.mjs" }, "require": { "types": "./id/url.d.cts", "default": "./id/url.cjs" } }, "./id/uuid": { "import": { "types": "./id/uuid.d.mts", "default": "./id/uuid.mjs" }, "require": { "types": "./id/uuid.d.cts", "default": "./id/uuid.cjs" } }, "./id/value": { "import": { "types": "./id/value.d.mts", "default": "./id/value.mjs" }, "require": { "types": "./id/value.d.cts", "default": "./id/value.cjs" } }, "./id/values": { "import": { "types": "./id/values.d.mts", "default": "./id/values.mjs" }, "require": { "types": "./id/values.d.cts", "default": "./id/values.cjs" } }, "./id/words": { "import": { "types": "./id/words.d.mts", "default": "./id/words.mjs" }, "require": { "types": "./id/words.d.cts", "default": "./id/words.cjs" } }, "./it": { "import": { "types": "./it/index.d.mts", "default": "./it/index.mjs" }, "require": { "types": "./it/index.d.cts", "default": "./it/index.cjs" } }, "./it/schema": { "import": { "types": "./it/schema.d.mts", "default": "./it/schema.mjs" }, "require": { "types": "./it/schema.d.cts", "default": "./it/schema.cjs" } }, "./it/base64": { "import": { "types": "./it/base64.d.mts", "default": "./it/base64.mjs" }, "require": { "types": "./it/base64.d.cts", "default": "./it/base64.cjs" } }, "./it/bic": { "import": { "types": "./it/bic.d.mts", "default": "./it/bic.mjs" }, "require": { "types": "./it/bic.d.cts", "default": "./it/bic.cjs" } }, "./it/bytes": { "import": { "types": "./it/bytes.d.mts", "default": "./it/bytes.mjs" }, "require": { "types": "./it/bytes.d.cts", "default": "./it/bytes.cjs" } }, "./it/check": { "import": { "types": "./it/check.d.mts", "default": "./it/check.mjs" }, "require": { "types": "./it/check.d.cts", "default": "./it/check.cjs" } }, "./it/checkAsync": { "import": { "types": "./it/checkAsync.d.mts", "default": "./it/checkAsync.mjs" }, "require": { "types": "./it/checkAsync.d.cts", "default": "./it/checkAsync.cjs" } }, "./it/checkItems": { "import": { "types": "./it/checkItems.d.mts", "default": "./it/checkItems.mjs" }, "require": { "types": "./it/checkItems.d.cts", "default": "./it/checkItems.cjs" } }, "./it/checkItemsAsync": { "import": { "types": "./it/checkItemsAsync.d.mts", "default": "./it/checkItemsAsync.mjs" }, "require": { "types": "./it/checkItemsAsync.d.cts", "default": "./it/checkItemsAsync.cjs" } }, "./it/creditCard": { "import": { "types": "./it/creditCard.d.mts", "default": "./it/creditCard.mjs" }, "require": { "types": "./it/creditCard.d.cts", "default": "./it/creditCard.cjs" } }, "./it/cuid2": { "import": { "types": "./it/cuid2.d.mts", "default": "./it/cuid2.mjs" }, "require": { "types": "./it/cuid2.d.cts", "default": "./it/cuid2.cjs" } }, "./it/decimal": { "import": { "types": "./it/decimal.d.mts", "default": "./it/decimal.mjs" }, "require": { "types": "./it/decimal.d.cts", "default": "./it/decimal.cjs" } }, "./it/digits": { "import": { "types": "./it/digits.d.mts", "default": "./it/digits.mjs" }, "require": { "types": "./it/digits.d.cts", "default": "./it/digits.cjs" } }, "./it/domain": { "import": { "types": "./it/domain.d.mts", "default": "./it/domain.mjs" }, "require": { "types": "./it/domain.d.cts", "default": "./it/domain.cjs" } }, "./it/email": { "import": { "types": "./it/email.d.mts", "default": "./it/email.mjs" }, "require": { "types": "./it/email.d.cts", "default": "./it/email.cjs" } }, "./it/emoji": { "import": { "types": "./it/emoji.d.mts", "default": "./it/emoji.mjs" }, "require": { "types": "./it/emoji.d.cts", "default": "./it/emoji.cjs" } }, "./it/empty": { "import": { "types": "./it/empty.d.mts", "default": "./it/empty.mjs" }, "require": { "types": "./it/empty.d.cts", "default": "./it/empty.cjs" } }, "./it/endsWith": { "import": { "types": "./it/endsWith.d.mts", "default": "./it/endsWith.mjs" }, "require": { "types": "./it/endsWith.d.cts", "default": "./it/endsWith.cjs" } }, "./it/entries": { "import": { "types": "./it/entries.d.mts", "default": "./it/entries.mjs" }, "require": { "types": "./it/entries.d.cts", "default": "./it/entries.cjs" } }, "./it/everyItem": { "import": { "types": "./it/everyItem.d.mts", "default": "./it/everyItem.mjs" }, "require": { "types": "./it/everyItem.d.cts", "default": "./it/everyItem.cjs" } }, "./it/excludes": { "import": { "types": "./it/excludes.d.mts", "default": "./it/excludes.mjs" }, "require": { "types": "./it/excludes.d.cts", "default": "./it/excludes.cjs" } }, "./it/finite": { "import": { "types": "./it/finite.d.mts", "default": "./it/finite.mjs" }, "require": { "types": "./it/finite.d.cts", "default": "./it/finite.cjs" } }, "./it/graphemes": { "import": { "types": "./it/graphemes.d.mts", "default": "./it/graphemes.mjs" }, "require": { "types": "./it/graphemes.d.cts", "default": "./it/graphemes.cjs" } }, "./it/gtValue": { "import": { "types": "./it/gtValue.d.mts", "default": "./it/gtValue.mjs" }, "require": { "types": "./it/gtValue.d.cts", "default": "./it/gtValue.cjs" } }, "./it/guard": { "import": { "types": "./it/guard.d.mts", "default": "./it/guard.mjs" }, "require": { "types": "./it/guard.d.cts", "default": "./it/guard.cjs" } }, "./it/hash": { "import": { "types": "./it/hash.d.mts", "default": "./it/hash.mjs" }, "require": { "types": "./it/hash.d.cts", "default": "./it/hash.cjs" } }, "./it/hexadecimal": { "import": { "types": "./it/hexadecimal.d.mts", "default": "./it/hexadecimal.mjs" }, "require": { "types": "./it/hexadecimal.d.cts", "default": "./it/hexadecimal.cjs" } }, "./it/hexColor": { "import": { "types": "./it/hexColor.d.mts", "default": "./it/hexColor.mjs" }, "require": { "types": "./it/hexColor.d.cts", "default": "./it/hexColor.cjs" } }, "./it/imei": { "import": { "types": "./it/imei.d.mts", "default": "./it/imei.mjs" }, "require": { "types": "./it/imei.d.cts", "default": "./it/imei.cjs" } }, "./it/includes": { "import": { "types": "./it/includes.d.mts", "default": "./it/includes.mjs" }, "require": { "types": "./it/includes.d.cts", "default": "./it/includes.cjs" } }, "./it/integer": { "import": { "types": "./it/integer.d.mts", "default": "./it/integer.mjs" }, "require": { "types": "./it/integer.d.cts", "default": "./it/integer.cjs" } }, "./it/ip": { "import": { "types": "./it/ip.d.mts", "default": "./it/ip.mjs" }, "require": { "types": "./it/ip.d.cts", "default": "./it/ip.cjs" } }, "./it/ipv4": { "import": { "types": "./it/ipv4.d.mts", "default": "./it/ipv4.mjs" }, "require": { "types": "./it/ipv4.d.cts", "default": "./it/ipv4.cjs" } }, "./it/ipv6": { "import": { "types": "./it/ipv6.d.mts", "default": "./it/ipv6.mjs" }, "require": { "types": "./it/ipv6.d.cts", "default": "./it/ipv6.cjs" } }, "./it/isbn": { "import": { "types": "./it/isbn.d.mts", "default": "./it/isbn.mjs" }, "require": { "types": "./it/isbn.d.cts", "default": "./it/isbn.cjs" } }, "./it/isoDate": { "import": { "types": "./it/isoDate.d.mts", "default": "./it/isoDate.mjs" }, "require": { "types": "./it/isoDate.d.cts", "default": "./it/isoDate.cjs" } }, "./it/isoDateTime": { "import": { "types": "./it/isoDateTime.d.mts", "default": "./it/isoDateTime.mjs" }, "require": { "types": "./it/isoDateTime.d.cts", "default": "./it/isoDateTime.cjs" } }, "./it/isoTime": { "import": { "types": "./it/isoTime.d.mts", "default": "./it/isoTime.mjs" }, "require": { "types": "./it/isoTime.d.cts", "default": "./it/isoTime.cjs" } }, "./it/isoTimeSecond": { "import": { "types": "./it/isoTimeSecond.d.mts", "default": "./it/isoTimeSecond.mjs" }, "require": { "types": "./it/isoTimeSecond.d.cts", "default": "./it/isoTimeSecond.cjs" } }, "./it/isoTimestamp": { "import": { "types": "./it/isoTimestamp.d.mts", "default": "./it/isoTimestamp.mjs" }, "require": { "types": "./it/isoTimestamp.d.cts", "default": "./it/isoTimestamp.cjs" } }, "./it/isoWeek": { "import": { "types": "./it/isoWeek.d.mts", "default": "./it/isoWeek.mjs" }, "require": { "types": "./it/isoWeek.d.cts", "default": "./it/isoWeek.cjs" } }, "./it/isrc": { "import": { "types": "./it/isrc.d.mts", "default": "./it/isrc.mjs" }, "require": { "types": "./it/isrc.d.cts", "default": "./it/isrc.cjs" } }, "./it/jwsCompact": { "import": { "types": "./it/jwsCompact.d.mts", "default": "./it/jwsCompact.mjs" }, "require": { "types": "./it/jwsCompact.d.cts", "default": "./it/jwsCompact.cjs" } }, "./it/length": { "import": { "types": "./it/length.d.mts", "default": "./it/length.mjs" }, "require": { "types": "./it/length.d.cts", "default": "./it/length.cjs" } }, "./it/ltValue": { "import": { "types": "./it/ltValue.d.mts", "default": "./it/ltValue.mjs" }, "require": { "types": "./it/ltValue.d.cts", "default": "./it/ltValue.cjs" } }, "./it/mac": { "import": { "types": "./it/mac.d.mts", "default": "./it/mac.mjs" }, "require": { "types": "./it/mac.d.cts", "default": "./it/mac.cjs" } }, "./it/mac48": { "import": { "types": "./it/mac48.d.mts", "default": "./it/mac48.mjs" }, "require": { "types": "./it/mac48.d.cts", "default": "./it/mac48.cjs" } }, "./it/mac64": { "import": { "types": "./it/mac64.d.mts", "default": "./it/mac64.mjs" }, "require": { "types": "./it/mac64.d.cts", "default": "./it/mac64.cjs" } }, "./it/maxBytes": { "import": { "types": "./it/maxBytes.d.mts", "default": "./it/maxBytes.mjs" }, "require": { "types": "./it/maxBytes.d.cts", "default": "./it/maxBytes.cjs" } }, "./it/maxEntries": { "import": { "types": "./it/maxEntries.d.mts", "default": "./it/maxEntries.mjs" }, "require": { "types": "./it/maxEntries.d.cts", "default": "./it/maxEntries.cjs" } }, "./it/maxGraphemes": { "import": { "types": "./it/maxGraphemes.d.mts", "default": "./it/maxGraphemes.mjs" }, "require": { "types": "./it/maxGraphemes.d.cts", "default": "./it/maxGraphemes.cjs" } }, "./it/maxLength": { "import": { "types": "./it/maxLength.d.mts", "default": "./it/maxLength.mjs" }, "require": { "types": "./it/maxLength.d.cts", "default": "./it/maxLength.cjs" } }, "./it/maxSize": { "import": { "types": "./it/maxSize.d.mts", "default": "./it/maxSize.mjs" }, "require": { "types": "./it/maxSize.d.cts", "default": "./it/maxSize.cjs" } }, "./it/maxValue": { "import": { "types": "./it/maxValue.d.mts", "default": "./it/maxValue.mjs" }, "require": { "types": "./it/maxValue.d.cts", "default": "./it/maxValue.cjs" } }, "./it/maxWords": { "import": { "types": "./it/maxWords.d.mts", "default": "./it/maxWords.mjs" }, "require": { "types": "./it/maxWords.d.cts", "default": "./it/maxWords.cjs" } }, "./it/mimeType": { "import": { "types": "./it/mimeType.d.mts", "default": "./it/mimeType.mjs" }, "require": { "types": "./it/mimeType.d.cts", "default": "./it/mimeType.cjs" } }, "./it/minBytes": { "import": { "types": "./it/minBytes.d.mts", "default": "./it/minBytes.mjs" }, "require": { "types": "./it/minBytes.d.cts", "default": "./it/minBytes.cjs" } }, "./it/minEntries": { "import": { "types": "./it/minEntries.d.mts", "default": "./it/minEntries.mjs" }, "require": { "types": "./it/minEntries.d.cts", "default": "./it/minEntries.cjs" } }, "./it/minGraphemes": { "import": { "types": "./it/minGraphemes.d.mts", "default": "./it/minGraphemes.mjs" }, "require": { "types": "./it/minGraphemes.d.cts", "default": "./it/minGraphemes.cjs" } }, "./it/minLength": { "import": { "types": "./it/minLength.d.mts", "default": "./it/minLength.mjs" }, "require": { "types": "./it/minLength.d.cts", "default": "./it/minLength.cjs" } }, "./it/minSize": { "import": { "types": "./it/minSize.d.mts", "default": "./it/minSize.mjs" }, "require": { "types": "./it/minSize.d.cts", "default": "./it/minSize.cjs" } }, "./it/minValue": { "import": { "types": "./it/minValue.d.mts", "default": "./it/minValue.mjs" }, "require": { "types": "./it/minValue.d.cts", "default": "./it/minValue.cjs" } }, "./it/minWords": { "import": { "types": "./it/minWords.d.mts", "default": "./it/minWords.mjs" }, "require": { "types": "./it/minWords.d.cts", "default": "./it/minWords.cjs" } }, "./it/multipleOf": { "import": { "types": "./it/multipleOf.d.mts", "default": "./it/multipleOf.mjs" }, "require": { "types": "./it/multipleOf.d.cts", "default": "./it/multipleOf.cjs" } }, "./it/nanoid": { "import": { "types": "./it/nanoid.d.mts", "default": "./it/nanoid.mjs" }, "require": { "types": "./it/nanoid.d.cts", "default": "./it/nanoid.cjs" } }, "./it/nonEmpty": { "import": { "types": "./it/nonEmpty.d.mts", "default": "./it/nonEmpty.mjs" }, "require": { "types": "./it/nonEmpty.d.cts", "default": "./it/nonEmpty.cjs" } }, "./it/notBytes": { "import": { "types": "./it/notBytes.d.mts", "default": "./it/notBytes.mjs" }, "require": { "types": "./it/notBytes.d.cts", "default": "./it/notBytes.cjs" } }, "./it/notEntries": { "import": { "types": "./it/notEntries.d.mts", "default": "./it/notEntries.mjs" }, "require": { "types": "./it/notEntries.d.cts", "default": "./it/notEntries.cjs" } }, "./it/notGraphemes": { "import": { "types": "./it/notGraphemes.d.mts", "default": "./it/notGraphemes.mjs" }, "require": { "types": "./it/notGraphemes.d.cts", "default": "./it/notGraphemes.cjs" } }, "./it/notLength": { "import": { "types": "./it/notLength.d.mts", "default": "./it/notLength.mjs" }, "require": { "types": "./it/notLength.d.cts", "default": "./it/notLength.cjs" } }, "./it/notSize": { "import": { "types": "./it/notSize.d.mts", "default": "./it/notSize.mjs" }, "require": { "types": "./it/notSize.d.cts", "default": "./it/notSize.cjs" } }, "./it/notValue": { "import": { "types": "./it/notValue.d.mts", "default": "./it/notValue.mjs" }, "require": { "types": "./it/notValue.d.cts", "default": "./it/notValue.cjs" } }, "./it/notValues": { "import": { "types": "./it/notValues.d.mts", "default": "./it/notValues.mjs" }, "require": { "types": "./it/notValues.d.cts", "default": "./it/notValues.cjs" } }, "./it/notWords": { "import": { "types": "./it/notWords.d.mts", "default": "./it/notWords.mjs" }, "require": { "types": "./it/notWords.d.cts", "default": "./it/notWords.cjs" } }, "./it/octal": { "import": { "types": "./it/octal.d.mts", "default": "./it/octal.mjs" }, "require": { "types": "./it/octal.d.cts", "default": "./it/octal.cjs" } }, "./it/parseBoolean": { "import": { "types": "./it/parseBoolean.d.mts", "default": "./it/parseBoolean.mjs" }, "require": { "types": "./it/parseBoolean.d.cts", "default": "./it/parseBoolean.cjs" } }, "./it/parseJson": { "import": { "types": "./it/parseJson.d.mts", "default": "./it/parseJson.mjs" }, "require": { "types": "./it/parseJson.d.cts", "default": "./it/parseJson.cjs" } }, "./it/partialCheck": { "import": { "types": "./it/partialCheck.d.mts", "default": "./it/partialCheck.mjs" }, "require": { "types": "./it/partialCheck.d.cts", "default": "./it/partialCheck.cjs" } }, "./it/rawCheck": { "import": { "types": "./it/rawCheck.d.mts", "default": "./it/rawCheck.mjs" }, "require": { "types": "./it/rawCheck.d.cts", "default": "./it/rawCheck.cjs" } }, "./it/rawTransform": { "import": { "types": "./it/rawTransform.d.mts", "default": "./it/rawTransform.mjs" }, "require": { "types": "./it/rawTransform.d.cts", "default": "./it/rawTransform.cjs" } }, "./it/regex": { "import": { "types": "./it/regex.d.mts", "default": "./it/regex.mjs" }, "require": { "types": "./it/regex.d.cts", "default": "./it/regex.cjs" } }, "./it/rfcEmail": { "import": { "types": "./it/rfcEmail.d.mts", "default": "./it/rfcEmail.mjs" }, "require": { "types": "./it/rfcEmail.d.cts", "default": "./it/rfcEmail.cjs" } }, "./it/safeInteger": { "import": { "types": "./it/safeInteger.d.mts", "default": "./it/safeInteger.mjs" }, "require": { "types": "./it/safeInteger.d.cts", "default": "./it/safeInteger.cjs" } }, "./it/size": { "import": { "types": "./it/size.d.mts", "default": "./it/size.mjs" }, "require": { "types": "./it/size.d.cts", "default": "./it/size.cjs" } }, "./it/slug": { "import": { "types": "./it/slug.d.mts", "default": "./it/slug.mjs" }, "require": { "types": "./it/slug.d.cts", "default": "./it/slug.cjs" } }, "./it/someItem": { "import": { "types": "./it/someItem.d.mts", "default": "./it/someItem.mjs" }, "require": { "types": "./it/someItem.d.cts", "default": "./it/someItem.cjs" } }, "./it/startsWith": { "import": { "types": "./it/startsWith.d.mts", "default": "./it/startsWith.mjs" }, "require": { "types": "./it/startsWith.d.cts", "default": "./it/startsWith.cjs" } }, "./it/stringifyJson": { "import": { "types": "./it/stringifyJson.d.mts", "default": "./it/stringifyJson.mjs" }, "require": { "types": "./it/stringifyJson.d.cts", "default": "./it/stringifyJson.cjs" } }, "./it/toBigint": { "import": { "types": "./it/toBigint.d.mts", "default": "./it/toBigint.mjs" }, "require": { "types": "./it/toBigint.d.cts", "default": "./it/toBigint.cjs" } }, "./it/toDate": { "import": { "types": "./it/toDate.d.mts", "default": "./it/toDate.mjs" }, "require": { "types": "./it/toDate.d.cts", "default": "./it/toDate.cjs" } }, "./it/toNumber": { "import": { "types": "./it/toNumber.d.mts", "default": "./it/toNumber.mjs" }, "require": { "types": "./it/toNumber.d.cts", "default": "./it/toNumber.cjs" } }, "./it/toString": { "import": { "types": "./it/toString.d.mts", "default": "./it/toString.mjs" }, "require": { "types": "./it/toString.d.cts", "default": "./it/toString.cjs" } }, "./it/ulid": { "import": { "types": "./it/ulid.d.mts", "default": "./it/ulid.mjs" }, "require": { "types": "./it/ulid.d.cts", "default": "./it/ulid.cjs" } }, "./it/url": { "import": { "types": "./it/url.d.mts", "default": "./it/url.mjs" }, "require": { "types": "./it/url.d.cts", "default": "./it/url.cjs" } }, "./it/uuid": { "import": { "types": "./it/uuid.d.mts", "default": "./it/uuid.mjs" }, "require": { "types": "./it/uuid.d.cts", "default": "./it/uuid.cjs" } }, "./it/value": { "import": { "types": "./it/value.d.mts", "default": "./it/value.mjs" }, "require": { "types": "./it/value.d.cts", "default": "./it/value.cjs" } }, "./it/values": { "import": { "types": "./it/values.d.mts", "default": "./it/values.mjs" }, "require": { "types": "./it/values.d.cts", "default": "./it/values.cjs" } }, "./it/words": { "import": { "types": "./it/words.d.mts", "default": "./it/words.mjs" }, "require": { "types": "./it/words.d.cts", "default": "./it/words.cjs" } }, "./ja": { "import": { "types": "./ja/index.d.mts", "default": "./ja/index.mjs" }, "require": { "types": "./ja/index.d.cts", "default": "./ja/index.cjs" } }, "./ja/schema": { "import": { "types": "./ja/schema.d.mts", "default": "./ja/schema.mjs" }, "require": { "types": "./ja/schema.d.cts", "default": "./ja/schema.cjs" } }, "./ja/base64": { "import": { "types": "./ja/base64.d.mts", "default": "./ja/base64.mjs" }, "require": { "types": "./ja/base64.d.cts", "default": "./ja/base64.cjs" } }, "./ja/bic": { "import": { "types": "./ja/bic.d.mts", "default": "./ja/bic.mjs" }, "require": { "types": "./ja/bic.d.cts", "default": "./ja/bic.cjs" } }, "./ja/bytes": { "import": { "types": "./ja/bytes.d.mts", "default": "./ja/bytes.mjs" }, "require": { "types": "./ja/bytes.d.cts", "default": "./ja/bytes.cjs" } }, "./ja/check": { "import": { "types": "./ja/check.d.mts", "default": "./ja/check.mjs" }, "require": { "types": "./ja/check.d.cts", "default": "./ja/check.cjs" } }, "./ja/checkAsync": { "import": { "types": "./ja/checkAsync.d.mts", "default": "./ja/checkAsync.mjs" }, "require": { "types": "./ja/checkAsync.d.cts", "default": "./ja/checkAsync.cjs" } }, "./ja/checkItems": { "import": { "types": "./ja/checkItems.d.mts", "default": "./ja/checkItems.mjs" }, "require": { "types": "./ja/checkItems.d.cts", "default": "./ja/checkItems.cjs" } }, "./ja/checkItemsAsync": { "import": { "types": "./ja/checkItemsAsync.d.mts", "default": "./ja/checkItemsAsync.mjs" }, "require": { "types": "./ja/checkItemsAsync.d.cts", "default": "./ja/checkItemsAsync.cjs" } }, "./ja/creditCard": { "import": { "types": "./ja/creditCard.d.mts", "default": "./ja/creditCard.mjs" }, "require": { "types": "./ja/creditCard.d.cts", "default": "./ja/creditCard.cjs" } }, "./ja/cuid2": { "import": { "types": "./ja/cuid2.d.mts", "default": "./ja/cuid2.mjs" }, "require": { "types": "./ja/cuid2.d.cts", "default": "./ja/cuid2.cjs" } }, "./ja/decimal": { "import": { "types": "./ja/decimal.d.mts", "default": "./ja/decimal.mjs" }, "require": { "types": "./ja/decimal.d.cts", "default": "./ja/decimal.cjs" } }, "./ja/digits": { "import": { "types": "./ja/digits.d.mts", "default": "./ja/digits.mjs" }, "require": { "types": "./ja/digits.d.cts", "default": "./ja/digits.cjs" } }, "./ja/domain": { "import": { "types": "./ja/domain.d.mts", "default": "./ja/domain.mjs" }, "require": { "types": "./ja/domain.d.cts", "default": "./ja/domain.cjs" } }, "./ja/email": { "import": { "types": "./ja/email.d.mts", "default": "./ja/email.mjs" }, "require": { "types": "./ja/email.d.cts", "default": "./ja/email.cjs" } }, "./ja/emoji": { "import": { "types": "./ja/emoji.d.mts", "default": "./ja/emoji.mjs" }, "require": { "types": "./ja/emoji.d.cts", "default": "./ja/emoji.cjs" } }, "./ja/empty": { "import": { "types": "./ja/empty.d.mts", "default": "./ja/empty.mjs" }, "require": { "types": "./ja/empty.d.cts", "default": "./ja/empty.cjs" } }, "./ja/endsWith": { "import": { "types": "./ja/endsWith.d.mts", "default": "./ja/endsWith.mjs" }, "require": { "types": "./ja/endsWith.d.cts", "default": "./ja/endsWith.cjs" } }, "./ja/entries": { "import": { "types": "./ja/entries.d.mts", "default": "./ja/entries.mjs" }, "require": { "types": "./ja/entries.d.cts", "default": "./ja/entries.cjs" } }, "./ja/everyItem": { "import": { "types": "./ja/everyItem.d.mts", "default": "./ja/everyItem.mjs" }, "require": { "types": "./ja/everyItem.d.cts", "default": "./ja/everyItem.cjs" } }, "./ja/excludes": { "import": { "types": "./ja/excludes.d.mts", "default": "./ja/excludes.mjs" }, "require": { "types": "./ja/excludes.d.cts", "default": "./ja/excludes.cjs" } }, "./ja/finite": { "import": { "types": "./ja/finite.d.mts", "default": "./ja/finite.mjs" }, "require": { "types": "./ja/finite.d.cts", "default": "./ja/finite.cjs" } }, "./ja/graphemes": { "import": { "types": "./ja/graphemes.d.mts", "default": "./ja/graphemes.mjs" }, "require": { "types": "./ja/graphemes.d.cts", "default": "./ja/graphemes.cjs" } }, "./ja/gtValue": { "import": { "types": "./ja/gtValue.d.mts", "default": "./ja/gtValue.mjs" }, "require": { "types": "./ja/gtValue.d.cts", "default": "./ja/gtValue.cjs" } }, "./ja/guard": { "import": { "types": "./ja/guard.d.mts", "default": "./ja/guard.mjs" }, "require": { "types": "./ja/guard.d.cts", "default": "./ja/guard.cjs" } }, "./ja/hash": { "import": { "types": "./ja/hash.d.mts", "default": "./ja/hash.mjs" }, "require": { "types": "./ja/hash.d.cts", "default": "./ja/hash.cjs" } }, "./ja/hexadecimal": { "import": { "types": "./ja/hexadecimal.d.mts", "default": "./ja/hexadecimal.mjs" }, "require": { "types": "./ja/hexadecimal.d.cts", "default": "./ja/hexadecimal.cjs" } }, "./ja/hexColor": { "import": { "types": "./ja/hexColor.d.mts", "default": "./ja/hexColor.mjs" }, "require": { "types": "./ja/hexColor.d.cts", "default": "./ja/hexColor.cjs" } }, "./ja/imei": { "import": { "types": "./ja/imei.d.mts", "default": "./ja/imei.mjs" }, "require": { "types": "./ja/imei.d.cts", "default": "./ja/imei.cjs" } }, "./ja/includes": { "import": { "types": "./ja/includes.d.mts", "default": "./ja/includes.mjs" }, "require": { "types": "./ja/includes.d.cts", "default": "./ja/includes.cjs" } }, "./ja/integer": { "import": { "types": "./ja/integer.d.mts", "default": "./ja/integer.mjs" }, "require": { "types": "./ja/integer.d.cts", "default": "./ja/integer.cjs" } }, "./ja/ip": { "import": { "types": "./ja/ip.d.mts", "default": "./ja/ip.mjs" }, "require": { "types": "./ja/ip.d.cts", "default": "./ja/ip.cjs" } }, "./ja/ipv4": { "import": { "types": "./ja/ipv4.d.mts", "default": "./ja/ipv4.mjs" }, "require": { "types": "./ja/ipv4.d.cts", "default": "./ja/ipv4.cjs" } }, "./ja/ipv6": { "import": { "types": "./ja/ipv6.d.mts", "default": "./ja/ipv6.mjs" }, "require": { "types": "./ja/ipv6.d.cts", "default": "./ja/ipv6.cjs" } }, "./ja/isbn": { "import": { "types": "./ja/isbn.d.mts", "default": "./ja/isbn.mjs" }, "require": { "types": "./ja/isbn.d.cts", "default": "./ja/isbn.cjs" } }, "./ja/isoDate": { "import": { "types": "./ja/isoDate.d.mts", "default": "./ja/isoDate.mjs" }, "require": { "types": "./ja/isoDate.d.cts", "default": "./ja/isoDate.cjs" } }, "./ja/isoDateTime": { "import": { "types": "./ja/isoDateTime.d.mts", "default": "./ja/isoDateTime.mjs" }, "require": { "types": "./ja/isoDateTime.d.cts", "default": "./ja/isoDateTime.cjs" } }, "./ja/isoTime": { "import": { "types": "./ja/isoTime.d.mts", "default": "./ja/isoTime.mjs" }, "require": { "types": "./ja/isoTime.d.cts", "default": "./ja/isoTime.cjs" } }, "./ja/isoTimeSecond": { "import": { "types": "./ja/isoTimeSecond.d.mts", "default": "./ja/isoTimeSecond.mjs" }, "require": { "types": "./ja/isoTimeSecond.d.cts", "default": "./ja/isoTimeSecond.cjs" } }, "./ja/isoTimestamp": { "import": { "types": "./ja/isoTimestamp.d.mts", "default": "./ja/isoTimestamp.mjs" }, "require": { "types": "./ja/isoTimestamp.d.cts", "default": "./ja/isoTimestamp.cjs" } }, "./ja/isoWeek": { "import": { "types": "./ja/isoWeek.d.mts", "default": "./ja/isoWeek.mjs" }, "require": { "types": "./ja/isoWeek.d.cts", "default": "./ja/isoWeek.cjs" } }, "./ja/isrc": { "import": { "types": "./ja/isrc.d.mts", "default": "./ja/isrc.mjs" }, "require": { "types": "./ja/isrc.d.cts", "default": "./ja/isrc.cjs" } }, "./ja/jwsCompact": { "import": { "types": "./ja/jwsCompact.d.mts", "default": "./ja/jwsCompact.mjs" }, "require": { "types": "./ja/jwsCompact.d.cts", "default": "./ja/jwsCompact.cjs" } }, "./ja/length": { "import": { "types": "./ja/length.d.mts", "default": "./ja/length.mjs" }, "require": { "types": "./ja/length.d.cts", "default": "./ja/length.cjs" } }, "./ja/ltValue": { "import": { "types": "./ja/ltValue.d.mts", "default": "./ja/ltValue.mjs" }, "require": { "types": "./ja/ltValue.d.cts", "default": "./ja/ltValue.cjs" } }, "./ja/mac": { "import": { "types": "./ja/mac.d.mts", "default": "./ja/mac.mjs" }, "require": { "types": "./ja/mac.d.cts", "default": "./ja/mac.cjs" } }, "./ja/mac48": { "import": { "types": "./ja/mac48.d.mts", "default": "./ja/mac48.mjs" }, "require": { "types": "./ja/mac48.d.cts", "default": "./ja/mac48.cjs" } }, "./ja/mac64": { "import": { "types": "./ja/mac64.d.mts", "default": "./ja/mac64.mjs" }, "require": { "types": "./ja/mac64.d.cts", "default": "./ja/mac64.cjs" } }, "./ja/maxBytes": { "import": { "types": "./ja/maxBytes.d.mts", "default": "./ja/maxBytes.mjs" }, "require": { "types": "./ja/maxBytes.d.cts", "default": "./ja/maxBytes.cjs" } }, "./ja/maxEntries": { "import": { "types": "./ja/maxEntries.d.mts", "default": "./ja/maxEntries.mjs" }, "require": { "types": "./ja/maxEntries.d.cts", "default": "./ja/maxEntries.cjs" } }, "./ja/maxGraphemes": { "import": { "types": "./ja/maxGraphemes.d.mts", "default": "./ja/maxGraphemes.mjs" }, "require": { "types": "./ja/maxGraphemes.d.cts", "default": "./ja/maxGraphemes.cjs" } }, "./ja/maxLength": { "import": { "types": "./ja/maxLength.d.mts", "default": "./ja/maxLength.mjs" }, "require": { "types": "./ja/maxLength.d.cts", "default": "./ja/maxLength.cjs" } }, "./ja/maxSize": { "import": { "types": "./ja/maxSize.d.mts", "default": "./ja/maxSize.mjs" }, "require": { "types": "./ja/maxSize.d.cts", "default": "./ja/maxSize.cjs" } }, "./ja/maxValue": { "import": { "types": "./ja/maxValue.d.mts", "default": "./ja/maxValue.mjs" }, "require": { "types": "./ja/maxValue.d.cts", "default": "./ja/maxValue.cjs" } }, "./ja/maxWords": { "import": { "types": "./ja/maxWords.d.mts", "default": "./ja/maxWords.mjs" }, "require": { "types": "./ja/maxWords.d.cts", "default": "./ja/maxWords.cjs" } }, "./ja/mimeType": { "import": { "types": "./ja/mimeType.d.mts", "default": "./ja/mimeType.mjs" }, "require": { "types": "./ja/mimeType.d.cts", "default": "./ja/mimeType.cjs" } }, "./ja/minBytes": { "import": { "types": "./ja/minBytes.d.mts", "default": "./ja/minBytes.mjs" }, "require": { "types": "./ja/minBytes.d.cts", "default": "./ja/minBytes.cjs" } }, "./ja/minEntries": { "import": { "types": "./ja/minEntries.d.mts", "default": "./ja/minEntries.mjs" }, "require": { "types": "./ja/minEntries.d.cts", "default": "./ja/minEntries.cjs" } }, "./ja/minGraphemes": { "import": { "types": "./ja/minGraphemes.d.mts", "default": "./ja/minGraphemes.mjs" }, "require": { "types": "./ja/minGraphemes.d.cts", "default": "./ja/minGraphemes.cjs" } }, "./ja/minLength": { "import": { "types": "./ja/minLength.d.mts", "default": "./ja/minLength.mjs" }, "require": { "types": "./ja/minLength.d.cts", "default": "./ja/minLength.cjs" } }, "./ja/minSize": { "import": { "types": "./ja/minSize.d.mts", "default": "./ja/minSize.mjs" }, "require": { "types": "./ja/minSize.d.cts", "default": "./ja/minSize.cjs" } }, "./ja/minValue": { "import": { "types": "./ja/minValue.d.mts", "default": "./ja/minValue.mjs" }, "require": { "types": "./ja/minValue.d.cts", "default": "./ja/minValue.cjs" } }, "./ja/minWords": { "import": { "types": "./ja/minWords.d.mts", "default": "./ja/minWords.mjs" }, "require": { "types": "./ja/minWords.d.cts", "default": "./ja/minWords.cjs" } }, "./ja/multipleOf": { "import": { "types": "./ja/multipleOf.d.mts", "default": "./ja/multipleOf.mjs" }, "require": { "types": "./ja/multipleOf.d.cts", "default": "./ja/multipleOf.cjs" } }, "./ja/nanoid": { "import": { "types": "./ja/nanoid.d.mts", "default": "./ja/nanoid.mjs" }, "require": { "types": "./ja/nanoid.d.cts", "default": "./ja/nanoid.cjs" } }, "./ja/nonEmpty": { "import": { "types": "./ja/nonEmpty.d.mts", "default": "./ja/nonEmpty.mjs" }, "require": { "types": "./ja/nonEmpty.d.cts", "default": "./ja/nonEmpty.cjs" } }, "./ja/notBytes": { "import": { "types": "./ja/notBytes.d.mts", "default": "./ja/notBytes.mjs" }, "require": { "types": "./ja/notBytes.d.cts", "default": "./ja/notBytes.cjs" } }, "./ja/notEntries": { "import": { "types": "./ja/notEntries.d.mts", "default": "./ja/notEntries.mjs" }, "require": { "types": "./ja/notEntries.d.cts", "default": "./ja/notEntries.cjs" } }, "./ja/notGraphemes": { "import": { "types": "./ja/notGraphemes.d.mts", "default": "./ja/notGraphemes.mjs" }, "require": { "types": "./ja/notGraphemes.d.cts", "default": "./ja/notGraphemes.cjs" } }, "./ja/notLength": { "import": { "types": "./ja/notLength.d.mts", "default": "./ja/notLength.mjs" }, "require": { "types": "./ja/notLength.d.cts", "default": "./ja/notLength.cjs" } }, "./ja/notSize": { "import": { "types": "./ja/notSize.d.mts", "default": "./ja/notSize.mjs" }, "require": { "types": "./ja/notSize.d.cts", "default": "./ja/notSize.cjs" } }, "./ja/notValue": { "import": { "types": "./ja/notValue.d.mts", "default": "./ja/notValue.mjs" }, "require": { "types": "./ja/notValue.d.cts", "default": "./ja/notValue.cjs" } }, "./ja/notValues": { "import": { "types": "./ja/notValues.d.mts", "default": "./ja/notValues.mjs" }, "require": { "types": "./ja/notValues.d.cts", "default": "./ja/notValues.cjs" } }, "./ja/notWords": { "import": { "types": "./ja/notWords.d.mts", "default": "./ja/notWords.mjs" }, "require": { "types": "./ja/notWords.d.cts", "default": "./ja/notWords.cjs" } }, "./ja/octal": { "import": { "types": "./ja/octal.d.mts", "default": "./ja/octal.mjs" }, "require": { "types": "./ja/octal.d.cts", "default": "./ja/octal.cjs" } }, "./ja/parseBoolean": { "import": { "types": "./ja/parseBoolean.d.mts", "default": "./ja/parseBoolean.mjs" }, "require": { "types": "./ja/parseBoolean.d.cts", "default": "./ja/parseBoolean.cjs" } }, "./ja/parseJson": { "import": { "types": "./ja/parseJson.d.mts", "default": "./ja/parseJson.mjs" }, "require": { "types": "./ja/parseJson.d.cts", "default": "./ja/parseJson.cjs" } }, "./ja/partialCheck": { "import": { "types": "./ja/partialCheck.d.mts", "default": "./ja/partialCheck.mjs" }, "require": { "types": "./ja/partialCheck.d.cts", "default": "./ja/partialCheck.cjs" } }, "./ja/rawCheck": { "import": { "types": "./ja/rawCheck.d.mts", "default": "./ja/rawCheck.mjs" }, "require": { "types": "./ja/rawCheck.d.cts", "default": "./ja/rawCheck.cjs" } }, "./ja/rawTransform": { "import": { "types": "./ja/rawTransform.d.mts", "default": "./ja/rawTransform.mjs" }, "require": { "types": "./ja/rawTransform.d.cts", "default": "./ja/rawTransform.cjs" } }, "./ja/regex": { "import": { "types": "./ja/regex.d.mts", "default": "./ja/regex.mjs" }, "require": { "types": "./ja/regex.d.cts", "default": "./ja/regex.cjs" } }, "./ja/rfcEmail": { "import": { "types": "./ja/rfcEmail.d.mts", "default": "./ja/rfcEmail.mjs" }, "require": { "types": "./ja/rfcEmail.d.cts", "default": "./ja/rfcEmail.cjs" } }, "./ja/safeInteger": { "import": { "types": "./ja/safeInteger.d.mts", "default": "./ja/safeInteger.mjs" }, "require": { "types": "./ja/safeInteger.d.cts", "default": "./ja/safeInteger.cjs" } }, "./ja/size": { "import": { "types": "./ja/size.d.mts", "default": "./ja/size.mjs" }, "require": { "types": "./ja/size.d.cts", "default": "./ja/size.cjs" } }, "./ja/slug": { "import": { "types": "./ja/slug.d.mts", "default": "./ja/slug.mjs" }, "require": { "types": "./ja/slug.d.cts", "default": "./ja/slug.cjs" } }, "./ja/someItem": { "import": { "types": "./ja/someItem.d.mts", "default": "./ja/someItem.mjs" }, "require": { "types": "./ja/someItem.d.cts", "default": "./ja/someItem.cjs" } }, "./ja/startsWith": { "import": { "types": "./ja/startsWith.d.mts", "default": "./ja/startsWith.mjs" }, "require": { "types": "./ja/startsWith.d.cts", "default": "./ja/startsWith.cjs" } }, "./ja/stringifyJson": { "import": { "types": "./ja/stringifyJson.d.mts", "default": "./ja/stringifyJson.mjs" }, "require": { "types": "./ja/stringifyJson.d.cts", "default": "./ja/stringifyJson.cjs" } }, "./ja/toBigint": { "import": { "types": "./ja/toBigint.d.mts", "default": "./ja/toBigint.mjs" }, "require": { "types": "./ja/toBigint.d.cts", "default": "./ja/toBigint.cjs" } }, "./ja/toDate": { "import": { "types": "./ja/toDate.d.mts", "default": "./ja/toDate.mjs" }, "require": { "types": "./ja/toDate.d.cts", "default": "./ja/toDate.cjs" } }, "./ja/toNumber": { "import": { "types": "./ja/toNumber.d.mts", "default": "./ja/toNumber.mjs" }, "require": { "types": "./ja/toNumber.d.cts", "default": "./ja/toNumber.cjs" } }, "./ja/toString": { "import": { "types": "./ja/toString.d.mts", "default": "./ja/toString.mjs" }, "require": { "types": "./ja/toString.d.cts", "default": "./ja/toString.cjs" } }, "./ja/ulid": { "import": { "types": "./ja/ulid.d.mts", "default": "./ja/ulid.mjs" }, "require": { "types": "./ja/ulid.d.cts", "default": "./ja/ulid.cjs" } }, "./ja/url": { "import": { "types": "./ja/url.d.mts", "default": "./ja/url.mjs" }, "require": { "types": "./ja/url.d.cts", "default": "./ja/url.cjs" } }, "./ja/uuid": { "import": { "types": "./ja/uuid.d.mts", "default": "./ja/uuid.mjs" }, "require": { "types": "./ja/uuid.d.cts", "default": "./ja/uuid.cjs" } }, "./ja/value": { "import": { "types": "./ja/value.d.mts", "default": "./ja/value.mjs" }, "require": { "types": "./ja/value.d.cts", "default": "./ja/value.cjs" } }, "./ja/values": { "import": { "types": "./ja/values.d.mts", "default": "./ja/values.mjs" }, "require": { "types": "./ja/values.d.cts", "default": "./ja/values.cjs" } }, "./ja/words": { "import": { "types": "./ja/words.d.mts", "default": "./ja/words.mjs" }, "require": { "types": "./ja/words.d.cts", "default": "./ja/words.cjs" } }, "./ko": { "import": { "types": "./ko/index.d.mts", "default": "./ko/index.mjs" }, "require": { "types": "./ko/index.d.cts", "default": "./ko/index.cjs" } }, "./ko/schema": { "import": { "types": "./ko/schema.d.mts", "default": "./ko/schema.mjs" }, "require": { "types": "./ko/schema.d.cts", "default": "./ko/schema.cjs" } }, "./ko/base64": { "import": { "types": "./ko/base64.d.mts", "default": "./ko/base64.mjs" }, "require": { "types": "./ko/base64.d.cts", "default": "./ko/base64.cjs" } }, "./ko/bic": { "import": { "types": "./ko/bic.d.mts", "default": "./ko/bic.mjs" }, "require": { "types": "./ko/bic.d.cts", "default": "./ko/bic.cjs" } }, "./ko/bytes": { "import": { "types": "./ko/bytes.d.mts", "default": "./ko/bytes.mjs" }, "require": { "types": "./ko/bytes.d.cts", "default": "./ko/bytes.cjs" } }, "./ko/check": { "import": { "types": "./ko/check.d.mts", "default": "./ko/check.mjs" }, "require": { "types": "./ko/check.d.cts", "default": "./ko/check.cjs" } }, "./ko/checkAsync": { "import": { "types": "./ko/checkAsync.d.mts", "default": "./ko/checkAsync.mjs" }, "require": { "types": "./ko/checkAsync.d.cts", "default": "./ko/checkAsync.cjs" } }, "./ko/checkItems": { "import": { "types": "./ko/checkItems.d.mts", "default": "./ko/checkItems.mjs" }, "require": { "types": "./ko/checkItems.d.cts", "default": "./ko/checkItems.cjs" } }, "./ko/checkItemsAsync": { "import": { "types": "./ko/checkItemsAsync.d.mts", "default": "./ko/checkItemsAsync.mjs" }, "require": { "types": "./ko/checkItemsAsync.d.cts", "default": "./ko/checkItemsAsync.cjs" } }, "./ko/creditCard": { "import": { "types": "./ko/creditCard.d.mts", "default": "./ko/creditCard.mjs" }, "require": { "types": "./ko/creditCard.d.cts", "default": "./ko/creditCard.cjs" } }, "./ko/cuid2": { "import": { "types": "./ko/cuid2.d.mts", "default": "./ko/cuid2.mjs" }, "require": { "types": "./ko/cuid2.d.cts", "default": "./ko/cuid2.cjs" } }, "./ko/decimal": { "import": { "types": "./ko/decimal.d.mts", "default": "./ko/decimal.mjs" }, "require": { "types": "./ko/decimal.d.cts", "default": "./ko/decimal.cjs" } }, "./ko/digits": { "import": { "types": "./ko/digits.d.mts", "default": "./ko/digits.mjs" }, "require": { "types": "./ko/digits.d.cts", "default": "./ko/digits.cjs" } }, "./ko/domain": { "import": { "types": "./ko/domain.d.mts", "default": "./ko/domain.mjs" }, "require": { "types": "./ko/domain.d.cts", "default": "./ko/domain.cjs" } }, "./ko/email": { "import": { "types": "./ko/email.d.mts", "default": "./ko/email.mjs" }, "require": { "types": "./ko/email.d.cts", "default": "./ko/email.cjs" } }, "./ko/emoji": { "import": { "types": "./ko/emoji.d.mts", "default": "./ko/emoji.mjs" }, "require": { "types": "./ko/emoji.d.cts", "default": "./ko/emoji.cjs" } }, "./ko/empty": { "import": { "types": "./ko/empty.d.mts", "default": "./ko/empty.mjs" }, "require": { "types": "./ko/empty.d.cts", "default": "./ko/empty.cjs" } }, "./ko/endsWith": { "import": { "types": "./ko/endsWith.d.mts", "default": "./ko/endsWith.mjs" }, "require": { "types": "./ko/endsWith.d.cts", "default": "./ko/endsWith.cjs" } }, "./ko/entries": { "import": { "types": "./ko/entries.d.mts", "default": "./ko/entries.mjs" }, "require": { "types": "./ko/entries.d.cts", "default": "./ko/entries.cjs" } }, "./ko/everyItem": { "import": { "types": "./ko/everyItem.d.mts", "default": "./ko/everyItem.mjs" }, "require": { "types": "./ko/everyItem.d.cts", "default": "./ko/everyItem.cjs" } }, "./ko/excludes": { "import": { "types": "./ko/excludes.d.mts", "default": "./ko/excludes.mjs" }, "require": { "types": "./ko/excludes.d.cts", "default": "./ko/excludes.cjs" } }, "./ko/finite": { "import": { "types": "./ko/finite.d.mts", "default": "./ko/finite.mjs" }, "require": { "types": "./ko/finite.d.cts", "default": "./ko/finite.cjs" } }, "./ko/graphemes": { "import": { "types": "./ko/graphemes.d.mts", "default": "./ko/graphemes.mjs" }, "require": { "types": "./ko/graphemes.d.cts", "default": "./ko/graphemes.cjs" } }, "./ko/gtValue": { "import": { "types": "./ko/gtValue.d.mts", "default": "./ko/gtValue.mjs" }, "require": { "types": "./ko/gtValue.d.cts", "default": "./ko/gtValue.cjs" } }, "./ko/guard": { "import": { "types": "./ko/guard.d.mts", "default": "./ko/guard.mjs" }, "require": { "types": "./ko/guard.d.cts", "default": "./ko/guard.cjs" } }, "./ko/hash": { "import": { "types": "./ko/hash.d.mts", "default": "./ko/hash.mjs" }, "require": { "types": "./ko/hash.d.cts", "default": "./ko/hash.cjs" } }, "./ko/hexadecimal": { "import": { "types": "./ko/hexadecimal.d.mts", "default": "./ko/hexadecimal.mjs" }, "require": { "types": "./ko/hexadecimal.d.cts", "default": "./ko/hexadecimal.cjs" } }, "./ko/hexColor": { "import": { "types": "./ko/hexColor.d.mts", "default": "./ko/hexColor.mjs" }, "require": { "types": "./ko/hexColor.d.cts", "default": "./ko/hexColor.cjs" } }, "./ko/imei": { "import": { "types": "./ko/imei.d.mts", "default": "./ko/imei.mjs" }, "require": { "types": "./ko/imei.d.cts", "default": "./ko/imei.cjs" } }, "./ko/includes": { "import": { "types": "./ko/includes.d.mts", "default": "./ko/includes.mjs" }, "require": { "types": "./ko/includes.d.cts", "default": "./ko/includes.cjs" } }, "./ko/integer": { "import": { "types": "./ko/integer.d.mts", "default": "./ko/integer.mjs" }, "require": { "types": "./ko/integer.d.cts", "default": "./ko/integer.cjs" } }, "./ko/ip": { "import": { "types": "./ko/ip.d.mts", "default": "./ko/ip.mjs" }, "require": { "types": "./ko/ip.d.cts", "default": "./ko/ip.cjs" } }, "./ko/ipv4": { "import": { "types": "./ko/ipv4.d.mts", "default": "./ko/ipv4.mjs" }, "require": { "types": "./ko/ipv4.d.cts", "default": "./ko/ipv4.cjs" } }, "./ko/ipv6": { "import": { "types": "./ko/ipv6.d.mts", "default": "./ko/ipv6.mjs" }, "require": { "types": "./ko/ipv6.d.cts", "default": "./ko/ipv6.cjs" } }, "./ko/isbn": { "import": { "types": "./ko/isbn.d.mts", "default": "./ko/isbn.mjs" }, "require": { "types": "./ko/isbn.d.cts", "default": "./ko/isbn.cjs" } }, "./ko/isoDate": { "import": { "types": "./ko/isoDate.d.mts", "default": "./ko/isoDate.mjs" }, "require": { "types": "./ko/isoDate.d.cts", "default": "./ko/isoDate.cjs" } }, "./ko/isoDateTime": { "import": { "types": "./ko/isoDateTime.d.mts", "default": "./ko/isoDateTime.mjs" }, "require": { "types": "./ko/isoDateTime.d.cts", "default": "./ko/isoDateTime.cjs" } }, "./ko/isoTime": { "import": { "types": "./ko/isoTime.d.mts", "default": "./ko/isoTime.mjs" }, "require": { "types": "./ko/isoTime.d.cts", "default": "./ko/isoTime.cjs" } }, "./ko/isoTimeSecond": { "import": { "types": "./ko/isoTimeSecond.d.mts", "default": "./ko/isoTimeSecond.mjs" }, "require": { "types": "./ko/isoTimeSecond.d.cts", "default": "./ko/isoTimeSecond.cjs" } }, "./ko/isoTimestamp": { "import": { "types": "./ko/isoTimestamp.d.mts", "default": "./ko/isoTimestamp.mjs" }, "require": { "types": "./ko/isoTimestamp.d.cts", "default": "./ko/isoTimestamp.cjs" } }, "./ko/isoWeek": { "import": { "types": "./ko/isoWeek.d.mts", "default": "./ko/isoWeek.mjs" }, "require": { "types": "./ko/isoWeek.d.cts", "default": "./ko/isoWeek.cjs" } }, "./ko/isrc": { "import": { "types": "./ko/isrc.d.mts", "default": "./ko/isrc.mjs" }, "require": { "types": "./ko/isrc.d.cts", "default": "./ko/isrc.cjs" } }, "./ko/jwsCompact": { "import": { "types": "./ko/jwsCompact.d.mts", "default": "./ko/jwsCompact.mjs" }, "require": { "types": "./ko/jwsCompact.d.cts", "default": "./ko/jwsCompact.cjs" } }, "./ko/length": { "import": { "types": "./ko/length.d.mts", "default": "./ko/length.mjs" }, "require": { "types": "./ko/length.d.cts", "default": "./ko/length.cjs" } }, "./ko/ltValue": { "import": { "types": "./ko/ltValue.d.mts", "default": "./ko/ltValue.mjs" }, "require": { "types": "./ko/ltValue.d.cts", "default": "./ko/ltValue.cjs" } }, "./ko/mac": { "import": { "types": "./ko/mac.d.mts", "default": "./ko/mac.mjs" }, "require": { "types": "./ko/mac.d.cts", "default": "./ko/mac.cjs" } }, "./ko/mac48": { "import": { "types": "./ko/mac48.d.mts", "default": "./ko/mac48.mjs" }, "require": { "types": "./ko/mac48.d.cts", "default": "./ko/mac48.cjs" } }, "./ko/mac64": { "import": { "types": "./ko/mac64.d.mts", "default": "./ko/mac64.mjs" }, "require": { "types": "./ko/mac64.d.cts", "default": "./ko/mac64.cjs" } }, "./ko/maxBytes": { "import": { "types": "./ko/maxBytes.d.mts", "default": "./ko/maxBytes.mjs" }, "require": { "types": "./ko/maxBytes.d.cts", "default": "./ko/maxBytes.cjs" } }, "./ko/maxEntries": { "import": { "types": "./ko/maxEntries.d.mts", "default": "./ko/maxEntries.mjs" }, "require": { "types": "./ko/maxEntries.d.cts", "default": "./ko/maxEntries.cjs" } }, "./ko/maxGraphemes": { "import": { "types": "./ko/maxGraphemes.d.mts", "default": "./ko/maxGraphemes.mjs" }, "require": { "types": "./ko/maxGraphemes.d.cts", "default": "./ko/maxGraphemes.cjs" } }, "./ko/maxLength": { "import": { "types": "./ko/maxLength.d.mts", "default": "./ko/maxLength.mjs" }, "require": { "types": "./ko/maxLength.d.cts", "default": "./ko/maxLength.cjs" } }, "./ko/maxSize": { "import": { "types": "./ko/maxSize.d.mts", "default": "./ko/maxSize.mjs" }, "require": { "types": "./ko/maxSize.d.cts", "default": "./ko/maxSize.cjs" } }, "./ko/maxValue": { "import": { "types": "./ko/maxValue.d.mts", "default": "./ko/maxValue.mjs" }, "require": { "types": "./ko/maxValue.d.cts", "default": "./ko/maxValue.cjs" } }, "./ko/maxWords": { "import": { "types": "./ko/maxWords.d.mts", "default": "./ko/maxWords.mjs" }, "require": { "types": "./ko/maxWords.d.cts", "default": "./ko/maxWords.cjs" } }, "./ko/mimeType": { "import": { "types": "./ko/mimeType.d.mts", "default": "./ko/mimeType.mjs" }, "require": { "types": "./ko/mimeType.d.cts", "default": "./ko/mimeType.cjs" } }, "./ko/minBytes": { "import": { "types": "./ko/minBytes.d.mts", "default": "./ko/minBytes.mjs" }, "require": { "types": "./ko/minBytes.d.cts", "default": "./ko/minBytes.cjs" } }, "./ko/minEntries": { "import": { "types": "./ko/minEntries.d.mts", "default": "./ko/minEntries.mjs" }, "require": { "types": "./ko/minEntries.d.cts", "default": "./ko/minEntries.cjs" } }, "./ko/minGraphemes": { "import": { "types": "./ko/minGraphemes.d.mts", "default": "./ko/minGraphemes.mjs" }, "require": { "types": "./ko/minGraphemes.d.cts", "default": "./ko/minGraphemes.cjs" } }, "./ko/minLength": { "import": { "types": "./ko/minLength.d.mts", "default": "./ko/minLength.mjs" }, "require": { "types": "./ko/minLength.d.cts", "default": "./ko/minLength.cjs" } }, "./ko/minSize": { "import": { "types": "./ko/minSize.d.mts", "default": "./ko/minSize.mjs" }, "require": { "types": "./ko/minSize.d.cts", "default": "./ko/minSize.cjs" } }, "./ko/minValue": { "import": { "types": "./ko/minValue.d.mts", "default": "./ko/minValue.mjs" }, "require": { "types": "./ko/minValue.d.cts", "default": "./ko/minValue.cjs" } }, "./ko/minWords": { "import": { "types": "./ko/minWords.d.mts", "default": "./ko/minWords.mjs" }, "require": { "types": "./ko/minWords.d.cts", "default": "./ko/minWords.cjs" } }, "./ko/multipleOf": { "import": { "types": "./ko/multipleOf.d.mts", "default": "./ko/multipleOf.mjs" }, "require": { "types": "./ko/multipleOf.d.cts", "default": "./ko/multipleOf.cjs" } }, "./ko/nanoid": { "import": { "types": "./ko/nanoid.d.mts", "default": "./ko/nanoid.mjs" }, "require": { "types": "./ko/nanoid.d.cts", "default": "./ko/nanoid.cjs" } }, "./ko/nonEmpty": { "import": { "types": "./ko/nonEmpty.d.mts", "default": "./ko/nonEmpty.mjs" }, "require": { "types": "./ko/nonEmpty.d.cts", "default": "./ko/nonEmpty.cjs" } }, "./ko/notBytes": { "import": { "types": "./ko/notBytes.d.mts", "default": "./ko/notBytes.mjs" }, "require": { "types": "./ko/notBytes.d.cts", "default": "./ko/notBytes.cjs" } }, "./ko/notEntries": { "import": { "types": "./ko/notEntries.d.mts", "default": "./ko/notEntries.mjs" }, "require": { "types": "./ko/notEntries.d.cts", "default": "./ko/notEntries.cjs" } }, "./ko/notGraphemes": { "import": { "types": "./ko/notGraphemes.d.mts", "default": "./ko/notGraphemes.mjs" }, "require": { "types": "./ko/notGraphemes.d.cts", "default": "./ko/notGraphemes.cjs" } }, "./ko/notLength": { "import": { "types": "./ko/notLength.d.mts", "default": "./ko/notLength.mjs" }, "require": { "types": "./ko/notLength.d.cts", "default": "./ko/notLength.cjs" } }, "./ko/notSize": { "import": { "types": "./ko/notSize.d.mts", "default": "./ko/notSize.mjs" }, "require": { "types": "./ko/notSize.d.cts", "default": "./ko/notSize.cjs" } }, "./ko/notValue": { "import": { "types": "./ko/notValue.d.mts", "default": "./ko/notValue.mjs" }, "require": { "types": "./ko/notValue.d.cts", "default": "./ko/notValue.cjs" } }, "./ko/notValues": { "import": { "types": "./ko/notValues.d.mts", "default": "./ko/notValues.mjs" }, "require": { "types": "./ko/notValues.d.cts", "default": "./ko/notValues.cjs" } }, "./ko/notWords": { "import": { "types": "./ko/notWords.d.mts", "default": "./ko/notWords.mjs" }, "require": { "types": "./ko/notWords.d.cts", "default": "./ko/notWords.cjs" } }, "./ko/octal": { "import": { "types": "./ko/octal.d.mts", "default": "./ko/octal.mjs" }, "require": { "types": "./ko/octal.d.cts", "default": "./ko/octal.cjs" } }, "./ko/parseBoolean": { "import": { "types": "./ko/parseBoolean.d.mts", "default": "./ko/parseBoolean.mjs" }, "require": { "types": "./ko/parseBoolean.d.cts", "default": "./ko/parseBoolean.cjs" } }, "./ko/parseJson": { "import": { "types": "./ko/parseJson.d.mts", "default": "./ko/parseJson.mjs" }, "require": { "types": "./ko/parseJson.d.cts", "default": "./ko/parseJson.cjs" } }, "./ko/partialCheck": { "import": { "types": "./ko/partialCheck.d.mts", "default": "./ko/partialCheck.mjs" }, "require": { "types": "./ko/partialCheck.d.cts", "default": "./ko/partialCheck.cjs" } }, "./ko/rawCheck": { "import": { "types": "./ko/rawCheck.d.mts", "default": "./ko/rawCheck.mjs" }, "require": { "types": "./ko/rawCheck.d.cts", "default": "./ko/rawCheck.cjs" } }, "./ko/rawTransform": { "import": { "types": "./ko/rawTransform.d.mts", "default": "./ko/rawTransform.mjs" }, "require": { "types": "./ko/rawTransform.d.cts", "default": "./ko/rawTransform.cjs" } }, "./ko/regex": { "import": { "types": "./ko/regex.d.mts", "default": "./ko/regex.mjs" }, "require": { "types": "./ko/regex.d.cts", "default": "./ko/regex.cjs" } }, "./ko/rfcEmail": { "import": { "types": "./ko/rfcEmail.d.mts", "default": "./ko/rfcEmail.mjs" }, "require": { "types": "./ko/rfcEmail.d.cts", "default": "./ko/rfcEmail.cjs" } }, "./ko/safeInteger": { "import": { "types": "./ko/safeInteger.d.mts", "default": "./ko/safeInteger.mjs" }, "require": { "types": "./ko/safeInteger.d.cts", "default": "./ko/safeInteger.cjs" } }, "./ko/size": { "import": { "types": "./ko/size.d.mts", "default": "./ko/size.mjs" }, "require": { "types": "./ko/size.d.cts", "default": "./ko/size.cjs" } }, "./ko/slug": { "import": { "types": "./ko/slug.d.mts", "default": "./ko/slug.mjs" }, "require": { "types": "./ko/slug.d.cts", "default": "./ko/slug.cjs" } }, "./ko/someItem": { "import": { "types": "./ko/someItem.d.mts", "default": "./ko/someItem.mjs" }, "require": { "types": "./ko/someItem.d.cts", "default": "./ko/someItem.cjs" } }, "./ko/startsWith": { "import": { "types": "./ko/startsWith.d.mts", "default": "./ko/startsWith.mjs" }, "require": { "types": "./ko/startsWith.d.cts", "default": "./ko/startsWith.cjs" } }, "./ko/stringifyJson": { "import": { "types": "./ko/stringifyJson.d.mts", "default": "./ko/stringifyJson.mjs" }, "require": { "types": "./ko/stringifyJson.d.cts", "default": "./ko/stringifyJson.cjs" } }, "./ko/toBigint": { "import": { "types": "./ko/toBigint.d.mts", "default": "./ko/toBigint.mjs" }, "require": { "types": "./ko/toBigint.d.cts", "default": "./ko/toBigint.cjs" } }, "./ko/toDate": { "import": { "types": "./ko/toDate.d.mts", "default": "./ko/toDate.mjs" }, "require": { "types": "./ko/toDate.d.cts", "default": "./ko/toDate.cjs" } }, "./ko/toNumber": { "import": { "types": "./ko/toNumber.d.mts", "default": "./ko/toNumber.mjs" }, "require": { "types": "./ko/toNumber.d.cts", "default": "./ko/toNumber.cjs" } }, "./ko/toString": { "import": { "types": "./ko/toString.d.mts", "default": "./ko/toString.mjs" }, "require": { "types": "./ko/toString.d.cts", "default": "./ko/toString.cjs" } }, "./ko/ulid": { "import": { "types": "./ko/ulid.d.mts", "default": "./ko/ulid.mjs" }, "require": { "types": "./ko/ulid.d.cts", "default": "./ko/ulid.cjs" } }, "./ko/url": { "import": { "types": "./ko/url.d.mts", "default": "./ko/url.mjs" }, "require": { "types": "./ko/url.d.cts", "default": "./ko/url.cjs" } }, "./ko/uuid": { "import": { "types": "./ko/uuid.d.mts", "default": "./ko/uuid.mjs" }, "require": { "types": "./ko/uuid.d.cts", "default": "./ko/uuid.cjs" } }, "./ko/value": { "import": { "types": "./ko/value.d.mts", "default": "./ko/value.mjs" }, "require": { "types": "./ko/value.d.cts", "default": "./ko/value.cjs" } }, "./ko/values": { "import": { "types": "./ko/values.d.mts", "default": "./ko/values.mjs" }, "require": { "types": "./ko/values.d.cts", "default": "./ko/values.cjs" } }, "./ko/words": { "import": { "types": "./ko/words.d.mts", "default": "./ko/words.mjs" }, "require": { "types": "./ko/words.d.cts", "default": "./ko/words.cjs" } }, "./kr": { "import": { "types": "./kr/index.d.mts", "default": "./kr/index.mjs" }, "require": { "types": "./kr/index.d.cts", "default": "./kr/index.cjs" } }, "./kr/schema": { "import": { "types": "./kr/schema.d.mts", "default": "./kr/schema.mjs" }, "require": { "types": "./kr/schema.d.cts", "default": "./kr/schema.cjs" } }, "./kr/base64": { "import": { "types": "./kr/base64.d.mts", "default": "./kr/base64.mjs" }, "require": { "types": "./kr/base64.d.cts", "default": "./kr/base64.cjs" } }, "./kr/bic": { "import": { "types": "./kr/bic.d.mts", "default": "./kr/bic.mjs" }, "require": { "types": "./kr/bic.d.cts", "default": "./kr/bic.cjs" } }, "./kr/bytes": { "import": { "types": "./kr/bytes.d.mts", "default": "./kr/bytes.mjs" }, "require": { "types": "./kr/bytes.d.cts", "default": "./kr/bytes.cjs" } }, "./kr/check": { "import": { "types": "./kr/check.d.mts", "default": "./kr/check.mjs" }, "require": { "types": "./kr/check.d.cts", "default": "./kr/check.cjs" } }, "./kr/checkAsync": { "import": { "types": "./kr/checkAsync.d.mts", "default": "./kr/checkAsync.mjs" }, "require": { "types": "./kr/checkAsync.d.cts", "default": "./kr/checkAsync.cjs" } }, "./kr/checkItems": { "import": { "types": "./kr/checkItems.d.mts", "default": "./kr/checkItems.mjs" }, "require": { "types": "./kr/checkItems.d.cts", "default": "./kr/checkItems.cjs" } }, "./kr/checkItemsAsync": { "import": { "types": "./kr/checkItemsAsync.d.mts", "default": "./kr/checkItemsAsync.mjs" }, "require": { "types": "./kr/checkItemsAsync.d.cts", "default": "./kr/checkItemsAsync.cjs" } }, "./kr/creditCard": { "import": { "types": "./kr/creditCard.d.mts", "default": "./kr/creditCard.mjs" }, "require": { "types": "./kr/creditCard.d.cts", "default": "./kr/creditCard.cjs" } }, "./kr/cuid2": { "import": { "types": "./kr/cuid2.d.mts", "default": "./kr/cuid2.mjs" }, "require": { "types": "./kr/cuid2.d.cts", "default": "./kr/cuid2.cjs" } }, "./kr/decimal": { "import": { "types": "./kr/decimal.d.mts", "default": "./kr/decimal.mjs" }, "require": { "types": "./kr/decimal.d.cts", "default": "./kr/decimal.cjs" } }, "./kr/digits": { "import": { "types": "./kr/digits.d.mts", "default": "./kr/digits.mjs" }, "require": { "types": "./kr/digits.d.cts", "default": "./kr/digits.cjs" } }, "./kr/domain": { "import": { "types": "./kr/domain.d.mts", "default": "./kr/domain.mjs" }, "require": { "types": "./kr/domain.d.cts", "default": "./kr/domain.cjs" } }, "./kr/email": { "import": { "types": "./kr/email.d.mts", "default": "./kr/email.mjs" }, "require": { "types": "./kr/email.d.cts", "default": "./kr/email.cjs" } }, "./kr/emoji": { "import": { "types": "./kr/emoji.d.mts", "default": "./kr/emoji.mjs" }, "require": { "types": "./kr/emoji.d.cts", "default": "./kr/emoji.cjs" } }, "./kr/empty": { "import": { "types": "./kr/empty.d.mts", "default": "./kr/empty.mjs" }, "require": { "types": "./kr/empty.d.cts", "default": "./kr/empty.cjs" } }, "./kr/endsWith": { "import": { "types": "./kr/endsWith.d.mts", "default": "./kr/endsWith.mjs" }, "require": { "types": "./kr/endsWith.d.cts", "default": "./kr/endsWith.cjs" } }, "./kr/entries": { "import": { "types": "./kr/entries.d.mts", "default": "./kr/entries.mjs" }, "require": { "types": "./kr/entries.d.cts", "default": "./kr/entries.cjs" } }, "./kr/everyItem": { "import": { "types": "./kr/everyItem.d.mts", "default": "./kr/everyItem.mjs" }, "require": { "types": "./kr/everyItem.d.cts", "default": "./kr/everyItem.cjs" } }, "./kr/excludes": { "import": { "types": "./kr/excludes.d.mts", "default": "./kr/excludes.mjs" }, "require": { "types": "./kr/excludes.d.cts", "default": "./kr/excludes.cjs" } }, "./kr/finite": { "import": { "types": "./kr/finite.d.mts", "default": "./kr/finite.mjs" }, "require": { "types": "./kr/finite.d.cts", "default": "./kr/finite.cjs" } }, "./kr/graphemes": { "import": { "types": "./kr/graphemes.d.mts", "default": "./kr/graphemes.mjs" }, "require": { "types": "./kr/graphemes.d.cts", "default": "./kr/graphemes.cjs" } }, "./kr/gtValue": { "import": { "types": "./kr/gtValue.d.mts", "default": "./kr/gtValue.mjs" }, "require": { "types": "./kr/gtValue.d.cts", "default": "./kr/gtValue.cjs" } }, "./kr/guard": { "import": { "types": "./kr/guard.d.mts", "default": "./kr/guard.mjs" }, "require": { "types": "./kr/guard.d.cts", "default": "./kr/guard.cjs" } }, "./kr/hash": { "import": { "types": "./kr/hash.d.mts", "default": "./kr/hash.mjs" }, "require": { "types": "./kr/hash.d.cts", "default": "./kr/hash.cjs" } }, "./kr/hexadecimal": { "import": { "types": "./kr/hexadecimal.d.mts", "default": "./kr/hexadecimal.mjs" }, "require": { "types": "./kr/hexadecimal.d.cts", "default": "./kr/hexadecimal.cjs" } }, "./kr/hexColor": { "import": { "types": "./kr/hexColor.d.mts", "default": "./kr/hexColor.mjs" }, "require": { "types": "./kr/hexColor.d.cts", "default": "./kr/hexColor.cjs" } }, "./kr/imei": { "import": { "types": "./kr/imei.d.mts", "default": "./kr/imei.mjs" }, "require": { "types": "./kr/imei.d.cts", "default": "./kr/imei.cjs" } }, "./kr/includes": { "import": { "types": "./kr/includes.d.mts", "default": "./kr/includes.mjs" }, "require": { "types": "./kr/includes.d.cts", "default": "./kr/includes.cjs" } }, "./kr/integer": { "import": { "types": "./kr/integer.d.mts", "default": "./kr/integer.mjs" }, "require": { "types": "./kr/integer.d.cts", "default": "./kr/integer.cjs" } }, "./kr/ip": { "import": { "types": "./kr/ip.d.mts", "default": "./kr/ip.mjs" }, "require": { "types": "./kr/ip.d.cts", "default": "./kr/ip.cjs" } }, "./kr/ipv4": { "import": { "types": "./kr/ipv4.d.mts", "default": "./kr/ipv4.mjs" }, "require": { "types": "./kr/ipv4.d.cts", "default": "./kr/ipv4.cjs" } }, "./kr/ipv6": { "import": { "types": "./kr/ipv6.d.mts", "default": "./kr/ipv6.mjs" }, "require": { "types": "./kr/ipv6.d.cts", "default": "./kr/ipv6.cjs" } }, "./kr/isbn": { "import": { "types": "./kr/isbn.d.mts", "default": "./kr/isbn.mjs" }, "require": { "types": "./kr/isbn.d.cts", "default": "./kr/isbn.cjs" } }, "./kr/isoDate": { "import": { "types": "./kr/isoDate.d.mts", "default": "./kr/isoDate.mjs" }, "require": { "types": "./kr/isoDate.d.cts", "default": "./kr/isoDate.cjs" } }, "./kr/isoDateTime": { "import": { "types": "./kr/isoDateTime.d.mts", "default": "./kr/isoDateTime.mjs" }, "require": { "types": "./kr/isoDateTime.d.cts", "default": "./kr/isoDateTime.cjs" } }, "./kr/isoTime": { "import": { "types": "./kr/isoTime.d.mts", "default": "./kr/isoTime.mjs" }, "require": { "types": "./kr/isoTime.d.cts", "default": "./kr/isoTime.cjs" } }, "./kr/isoTimeSecond": { "import": { "types": "./kr/isoTimeSecond.d.mts", "default": "./kr/isoTimeSecond.mjs" }, "require": { "types": "./kr/isoTimeSecond.d.cts", "default": "./kr/isoTimeSecond.cjs" } }, "./kr/isoTimestamp": { "import": { "types": "./kr/isoTimestamp.d.mts", "default": "./kr/isoTimestamp.mjs" }, "require": { "types": "./kr/isoTimestamp.d.cts", "default": "./kr/isoTimestamp.cjs" } }, "./kr/isoWeek": { "import": { "types": "./kr/isoWeek.d.mts", "default": "./kr/isoWeek.mjs" }, "require": { "types": "./kr/isoWeek.d.cts", "default": "./kr/isoWeek.cjs" } }, "./kr/isrc": { "import": { "types": "./kr/isrc.d.mts", "default": "./kr/isrc.mjs" }, "require": { "types": "./kr/isrc.d.cts", "default": "./kr/isrc.cjs" } }, "./kr/jwsCompact": { "import": { "types": "./kr/jwsCompact.d.mts", "default": "./kr/jwsCompact.mjs" }, "require": { "types": "./kr/jwsCompact.d.cts", "default": "./kr/jwsCompact.cjs" } }, "./kr/length": { "import": { "types": "./kr/length.d.mts", "default": "./kr/length.mjs" }, "require": { "types": "./kr/length.d.cts", "default": "./kr/length.cjs" } }, "./kr/ltValue": { "import": { "types": "./kr/ltValue.d.mts", "default": "./kr/ltValue.mjs" }, "require": { "types": "./kr/ltValue.d.cts", "default": "./kr/ltValue.cjs" } }, "./kr/mac": { "import": { "types": "./kr/mac.d.mts", "default": "./kr/mac.mjs" }, "require": { "types": "./kr/mac.d.cts", "default": "./kr/mac.cjs" } }, "./kr/mac48": { "import": { "types": "./kr/mac48.d.mts", "default": "./kr/mac48.mjs" }, "require": { "types": "./kr/mac48.d.cts", "default": "./kr/mac48.cjs" } }, "./kr/mac64": { "import": { "types": "./kr/mac64.d.mts", "default": "./kr/mac64.mjs" }, "require": { "types": "./kr/mac64.d.cts", "default": "./kr/mac64.cjs" } }, "./kr/maxBytes": { "import": { "types": "./kr/maxBytes.d.mts", "default": "./kr/maxBytes.mjs" }, "require": { "types": "./kr/maxBytes.d.cts", "default": "./kr/maxBytes.cjs" } }, "./kr/maxEntries": { "import": { "types": "./kr/maxEntries.d.mts", "default": "./kr/maxEntries.mjs" }, "require": { "types": "./kr/maxEntries.d.cts", "default": "./kr/maxEntries.cjs" } }, "./kr/maxGraphemes": { "import": { "types": "./kr/maxGraphemes.d.mts", "default": "./kr/maxGraphemes.mjs" }, "require": { "types": "./kr/maxGraphemes.d.cts", "default": "./kr/maxGraphemes.cjs" } }, "./kr/maxLength": { "import": { "types": "./kr/maxLength.d.mts", "default": "./kr/maxLength.mjs" }, "require": { "types": "./kr/maxLength.d.cts", "default": "./kr/maxLength.cjs" } }, "./kr/maxSize": { "import": { "types": "./kr/maxSize.d.mts", "default": "./kr/maxSize.mjs" }, "require": { "types": "./kr/maxSize.d.cts", "default": "./kr/maxSize.cjs" } }, "./kr/maxValue": { "import": { "types": "./kr/maxValue.d.mts", "default": "./kr/maxValue.mjs" }, "require": { "types": "./kr/maxValue.d.cts", "default": "./kr/maxValue.cjs" } }, "./kr/maxWords": { "import": { "types": "./kr/maxWords.d.mts", "default": "./kr/maxWords.mjs" }, "require": { "types": "./kr/maxWords.d.cts", "default": "./kr/maxWords.cjs" } }, "./kr/mimeType": { "import": { "types": "./kr/mimeType.d.mts", "default": "./kr/mimeType.mjs" }, "require": { "types": "./kr/mimeType.d.cts", "default": "./kr/mimeType.cjs" } }, "./kr/minBytes": { "import": { "types": "./kr/minBytes.d.mts", "default": "./kr/minBytes.mjs" }, "require": { "types": "./kr/minBytes.d.cts", "default": "./kr/minBytes.cjs" } }, "./kr/minEntries": { "import": { "types": "./kr/minEntries.d.mts", "default": "./kr/minEntries.mjs" }, "require": { "types": "./kr/minEntries.d.cts", "default": "./kr/minEntries.cjs" } }, "./kr/minGraphemes": { "import": { "types": "./kr/minGraphemes.d.mts", "default": "./kr/minGraphemes.mjs" }, "require": { "types": "./kr/minGraphemes.d.cts", "default": "./kr/minGraphemes.cjs" } }, "./kr/minLength": { "import": { "types": "./kr/minLength.d.mts", "default": "./kr/minLength.mjs" }, "require": { "types": "./kr/minLength.d.cts", "default": "./kr/minLength.cjs" } }, "./kr/minSize": { "import": { "types": "./kr/minSize.d.mts", "default": "./kr/minSize.mjs" }, "require": { "types": "./kr/minSize.d.cts", "default": "./kr/minSize.cjs" } }, "./kr/minValue": { "import": { "types": "./kr/minValue.d.mts", "default": "./kr/minValue.mjs" }, "require": { "types": "./kr/minValue.d.cts", "default": "./kr/minValue.cjs" } }, "./kr/minWords": { "import": { "types": "./kr/minWords.d.mts", "default": "./kr/minWords.mjs" }, "require": { "types": "./kr/minWords.d.cts", "default": "./kr/minWords.cjs" } }, "./kr/multipleOf": { "import": { "types": "./kr/multipleOf.d.mts", "default": "./kr/multipleOf.mjs" }, "require": { "types": "./kr/multipleOf.d.cts", "default": "./kr/multipleOf.cjs" } }, "./kr/nanoid": { "import": { "types": "./kr/nanoid.d.mts", "default": "./kr/nanoid.mjs" }, "require": { "types": "./kr/nanoid.d.cts", "default": "./kr/nanoid.cjs" } }, "./kr/nonEmpty": { "import": { "types": "./kr/nonEmpty.d.mts", "default": "./kr/nonEmpty.mjs" }, "require": { "types": "./kr/nonEmpty.d.cts", "default": "./kr/nonEmpty.cjs" } }, "./kr/notBytes": { "import": { "types": "./kr/notBytes.d.mts", "default": "./kr/notBytes.mjs" }, "require": { "types": "./kr/notBytes.d.cts", "default": "./kr/notBytes.cjs" } }, "./kr/notEntries": { "import": { "types": "./kr/notEntries.d.mts", "default": "./kr/notEntries.mjs" }, "require": { "types": "./kr/notEntries.d.cts", "default": "./kr/notEntries.cjs" } }, "./kr/notGraphemes": { "import": { "types": "./kr/notGraphemes.d.mts", "default": "./kr/notGraphemes.mjs" }, "require": { "types": "./kr/notGraphemes.d.cts", "default": "./kr/notGraphemes.cjs" } }, "./kr/notLength": { "import": { "types": "./kr/notLength.d.mts", "default": "./kr/notLength.mjs" }, "require": { "types": "./kr/notLength.d.cts", "default": "./kr/notLength.cjs" } }, "./kr/notSize": { "import": { "types": "./kr/notSize.d.mts", "default": "./kr/notSize.mjs" }, "require": { "types": "./kr/notSize.d.cts", "default": "./kr/notSize.cjs" } }, "./kr/notValue": { "import": { "types": "./kr/notValue.d.mts", "default": "./kr/notValue.mjs" }, "require": { "types": "./kr/notValue.d.cts", "default": "./kr/notValue.cjs" } }, "./kr/notValues": { "import": { "types": "./kr/notValues.d.mts", "default": "./kr/notValues.mjs" }, "require": { "types": "./kr/notValues.d.cts", "default": "./kr/notValues.cjs" } }, "./kr/notWords": { "import": { "types": "./kr/notWords.d.mts", "default": "./kr/notWords.mjs" }, "require": { "types": "./kr/notWords.d.cts", "default": "./kr/notWords.cjs" } }, "./kr/octal": { "import": { "types": "./kr/octal.d.mts", "default": "./kr/octal.mjs" }, "require": { "types": "./kr/octal.d.cts", "default": "./kr/octal.cjs" } }, "./kr/parseBoolean": { "import": { "types": "./kr/parseBoolean.d.mts", "default": "./kr/parseBoolean.mjs" }, "require": { "types": "./kr/parseBoolean.d.cts", "default": "./kr/parseBoolean.cjs" } }, "./kr/parseJson": { "import": { "types": "./kr/parseJson.d.mts", "default": "./kr/parseJson.mjs" }, "require": { "types": "./kr/parseJson.d.cts", "default": "./kr/parseJson.cjs" } }, "./kr/partialCheck": { "import": { "types": "./kr/partialCheck.d.mts", "default": "./kr/partialCheck.mjs" }, "require": { "types": "./kr/partialCheck.d.cts", "default": "./kr/partialCheck.cjs" } }, "./kr/rawCheck": { "import": { "types": "./kr/rawCheck.d.mts", "default": "./kr/rawCheck.mjs" }, "require": { "types": "./kr/rawCheck.d.cts", "default": "./kr/rawCheck.cjs" } }, "./kr/rawTransform": { "import": { "types": "./kr/rawTransform.d.mts", "default": "./kr/rawTransform.mjs" }, "require": { "types": "./kr/rawTransform.d.cts", "default": "./kr/rawTransform.cjs" } }, "./kr/regex": { "import": { "types": "./kr/regex.d.mts", "default": "./kr/regex.mjs" }, "require": { "types": "./kr/regex.d.cts", "default": "./kr/regex.cjs" } }, "./kr/rfcEmail": { "import": { "types": "./kr/rfcEmail.d.mts", "default": "./kr/rfcEmail.mjs" }, "require": { "types": "./kr/rfcEmail.d.cts", "default": "./kr/rfcEmail.cjs" } }, "./kr/safeInteger": { "import": { "types": "./kr/safeInteger.d.mts", "default": "./kr/safeInteger.mjs" }, "require": { "types": "./kr/safeInteger.d.cts", "default": "./kr/safeInteger.cjs" } }, "./kr/size": { "import": { "types": "./kr/size.d.mts", "default": "./kr/size.mjs" }, "require": { "types": "./kr/size.d.cts", "default": "./kr/size.cjs" } }, "./kr/slug": { "import": { "types": "./kr/slug.d.mts", "default": "./kr/slug.mjs" }, "require": { "types": "./kr/slug.d.cts", "default": "./kr/slug.cjs" } }, "./kr/someItem": { "import": { "types": "./kr/someItem.d.mts", "default": "./kr/someItem.mjs" }, "require": { "types": "./kr/someItem.d.cts", "default": "./kr/someItem.cjs" } }, "./kr/startsWith": { "import": { "types": "./kr/startsWith.d.mts", "default": "./kr/startsWith.mjs" }, "require": { "types": "./kr/startsWith.d.cts", "default": "./kr/startsWith.cjs" } }, "./kr/stringifyJson": { "import": { "types": "./kr/stringifyJson.d.mts", "default": "./kr/stringifyJson.mjs" }, "require": { "types": "./kr/stringifyJson.d.cts", "default": "./kr/stringifyJson.cjs" } }, "./kr/toBigint": { "import": { "types": "./kr/toBigint.d.mts", "default": "./kr/toBigint.mjs" }, "require": { "types": "./kr/toBigint.d.cts", "default": "./kr/toBigint.cjs" } }, "./kr/toDate": { "import": { "types": "./kr/toDate.d.mts", "default": "./kr/toDate.mjs" }, "require": { "types": "./kr/toDate.d.cts", "default": "./kr/toDate.cjs" } }, "./kr/toNumber": { "import": { "types": "./kr/toNumber.d.mts", "default": "./kr/toNumber.mjs" }, "require": { "types": "./kr/toNumber.d.cts", "default": "./kr/toNumber.cjs" } }, "./kr/toString": { "import": { "types": "./kr/toString.d.mts", "default": "./kr/toString.mjs" }, "require": { "types": "./kr/toString.d.cts", "default": "./kr/toString.cjs" } }, "./kr/ulid": { "import": { "types": "./kr/ulid.d.mts", "default": "./kr/ulid.mjs" }, "require": { "types": "./kr/ulid.d.cts", "default": "./kr/ulid.cjs" } }, "./kr/url": { "import": { "types": "./kr/url.d.mts", "default": "./kr/url.mjs" }, "require": { "types": "./kr/url.d.cts", "default": "./kr/url.cjs" } }, "./kr/uuid": { "import": { "types": "./kr/uuid.d.mts", "default": "./kr/uuid.mjs" }, "require": { "types": "./kr/uuid.d.cts", "default": "./kr/uuid.cjs" } }, "./kr/value": { "import": { "types": "./kr/value.d.mts", "default": "./kr/value.mjs" }, "require": { "types": "./kr/value.d.cts", "default": "./kr/value.cjs" } }, "./kr/values": { "import": { "types": "./kr/values.d.mts", "default": "./kr/values.mjs" }, "require": { "types": "./kr/values.d.cts", "default": "./kr/values.cjs" } }, "./kr/words": { "import": { "types": "./kr/words.d.mts", "default": "./kr/words.mjs" }, "require": { "types": "./kr/words.d.cts", "default": "./kr/words.cjs" } }, "./mn": { "import": { "types": "./mn/index.d.mts", "default": "./mn/index.mjs" }, "require": { "types": "./mn/index.d.cts", "default": "./mn/index.cjs" } }, "./mn/schema": { "import": { "types": "./mn/schema.d.mts", "default": "./mn/schema.mjs" }, "require": { "types": "./mn/schema.d.cts", "default": "./mn/schema.cjs" } }, "./mn/base64": { "import": { "types": "./mn/base64.d.mts", "default": "./mn/base64.mjs" }, "require": { "types": "./mn/base64.d.cts", "default": "./mn/base64.cjs" } }, "./mn/bic": { "import": { "types": "./mn/bic.d.mts", "default": "./mn/bic.mjs" }, "require": { "types": "./mn/bic.d.cts", "default": "./mn/bic.cjs" } }, "./mn/bytes": { "import": { "types": "./mn/bytes.d.mts", "default": "./mn/bytes.mjs" }, "require": { "types": "./mn/bytes.d.cts", "default": "./mn/bytes.cjs" } }, "./mn/check": { "import": { "types": "./mn/check.d.mts", "default": "./mn/check.mjs" }, "require": { "types": "./mn/check.d.cts", "default": "./mn/check.cjs" } }, "./mn/checkAsync": { "import": { "types": "./mn/checkAsync.d.mts", "default": "./mn/checkAsync.mjs" }, "require": { "types": "./mn/checkAsync.d.cts", "default": "./mn/checkAsync.cjs" } }, "./mn/checkItems": { "import": { "types": "./mn/checkItems.d.mts", "default": "./mn/checkItems.mjs" }, "require": { "types": "./mn/checkItems.d.cts", "default": "./mn/checkItems.cjs" } }, "./mn/checkItemsAsync": { "import": { "types": "./mn/checkItemsAsync.d.mts", "default": "./mn/checkItemsAsync.mjs" }, "require": { "types": "./mn/checkItemsAsync.d.cts", "default": "./mn/checkItemsAsync.cjs" } }, "./mn/creditCard": { "import": { "types": "./mn/creditCard.d.mts", "default": "./mn/creditCard.mjs" }, "require": { "types": "./mn/creditCard.d.cts", "default": "./mn/creditCard.cjs" } }, "./mn/cuid2": { "import": { "types": "./mn/cuid2.d.mts", "default": "./mn/cuid2.mjs" }, "require": { "types": "./mn/cuid2.d.cts", "default": "./mn/cuid2.cjs" } }, "./mn/decimal": { "import": { "types": "./mn/decimal.d.mts", "default": "./mn/decimal.mjs" }, "require": { "types": "./mn/decimal.d.cts", "default": "./mn/decimal.cjs" } }, "./mn/digits": { "import": { "types": "./mn/digits.d.mts", "default": "./mn/digits.mjs" }, "require": { "types": "./mn/digits.d.cts", "default": "./mn/digits.cjs" } }, "./mn/domain": { "import": { "types": "./mn/domain.d.mts", "default": "./mn/domain.mjs" }, "require": { "types": "./mn/domain.d.cts", "default": "./mn/domain.cjs" } }, "./mn/email": { "import": { "types": "./mn/email.d.mts", "default": "./mn/email.mjs" }, "require": { "types": "./mn/email.d.cts", "default": "./mn/email.cjs" } }, "./mn/emoji": { "import": { "types": "./mn/emoji.d.mts", "default": "./mn/emoji.mjs" }, "require": { "types": "./mn/emoji.d.cts", "default": "./mn/emoji.cjs" } }, "./mn/empty": { "import": { "types": "./mn/empty.d.mts", "default": "./mn/empty.mjs" }, "require": { "types": "./mn/empty.d.cts", "default": "./mn/empty.cjs" } }, "./mn/endsWith": { "import": { "types": "./mn/endsWith.d.mts", "default": "./mn/endsWith.mjs" }, "require": { "types": "./mn/endsWith.d.cts", "default": "./mn/endsWith.cjs" } }, "./mn/entries": { "import": { "types": "./mn/entries.d.mts", "default": "./mn/entries.mjs" }, "require": { "types": "./mn/entries.d.cts", "default": "./mn/entries.cjs" } }, "./mn/everyItem": { "import": { "types": "./mn/everyItem.d.mts", "default": "./mn/everyItem.mjs" }, "require": { "types": "./mn/everyItem.d.cts", "default": "./mn/everyItem.cjs" } }, "./mn/excludes": { "import": { "types": "./mn/excludes.d.mts", "default": "./mn/excludes.mjs" }, "require": { "types": "./mn/excludes.d.cts", "default": "./mn/excludes.cjs" } }, "./mn/finite": { "import": { "types": "./mn/finite.d.mts", "default": "./mn/finite.mjs" }, "require": { "types": "./mn/finite.d.cts", "default": "./mn/finite.cjs" } }, "./mn/graphemes": { "import": { "types": "./mn/graphemes.d.mts", "default": "./mn/graphemes.mjs" }, "require": { "types": "./mn/graphemes.d.cts", "default": "./mn/graphemes.cjs" } }, "./mn/gtValue": { "import": { "types": "./mn/gtValue.d.mts", "default": "./mn/gtValue.mjs" }, "require": { "types": "./mn/gtValue.d.cts", "default": "./mn/gtValue.cjs" } }, "./mn/guard": { "import": { "types": "./mn/guard.d.mts", "default": "./mn/guard.mjs" }, "require": { "types": "./mn/guard.d.cts", "default": "./mn/guard.cjs" } }, "./mn/hash": { "import": { "types": "./mn/hash.d.mts", "default": "./mn/hash.mjs" }, "require": { "types": "./mn/hash.d.cts", "default": "./mn/hash.cjs" } }, "./mn/hexColor": { "import": { "types": "./mn/hexColor.d.mts", "default": "./mn/hexColor.mjs" }, "require": { "types": "./mn/hexColor.d.cts", "default": "./mn/hexColor.cjs" } }, "./mn/hexadecimal": { "import": { "types": "./mn/hexadecimal.d.mts", "default": "./mn/hexadecimal.mjs" }, "require": { "types": "./mn/hexadecimal.d.cts", "default": "./mn/hexadecimal.cjs" } }, "./mn/imei": { "import": { "types": "./mn/imei.d.mts", "default": "./mn/imei.mjs" }, "require": { "types": "./mn/imei.d.cts", "default": "./mn/imei.cjs" } }, "./mn/includes": { "import": { "types": "./mn/includes.d.mts", "default": "./mn/includes.mjs" }, "require": { "types": "./mn/includes.d.cts", "default": "./mn/includes.cjs" } }, "./mn/integer": { "import": { "types": "./mn/integer.d.mts", "default": "./mn/integer.mjs" }, "require": { "types": "./mn/integer.d.cts", "default": "./mn/integer.cjs" } }, "./mn/ip": { "import": { "types": "./mn/ip.d.mts", "default": "./mn/ip.mjs" }, "require": { "types": "./mn/ip.d.cts", "default": "./mn/ip.cjs" } }, "./mn/ipv4": { "import": { "types": "./mn/ipv4.d.mts", "default": "./mn/ipv4.mjs" }, "require": { "types": "./mn/ipv4.d.cts", "default": "./mn/ipv4.cjs" } }, "./mn/ipv6": { "import": { "types": "./mn/ipv6.d.mts", "default": "./mn/ipv6.mjs" }, "require": { "types": "./mn/ipv6.d.cts", "default": "./mn/ipv6.cjs" } }, "./mn/isbn": { "import": { "types": "./mn/isbn.d.mts", "default": "./mn/isbn.mjs" }, "require": { "types": "./mn/isbn.d.cts", "default": "./mn/isbn.cjs" } }, "./mn/isoDate": { "import": { "types": "./mn/isoDate.d.mts", "default": "./mn/isoDate.mjs" }, "require": { "types": "./mn/isoDate.d.cts", "default": "./mn/isoDate.cjs" } }, "./mn/isoDateTime": { "import": { "types": "./mn/isoDateTime.d.mts", "default": "./mn/isoDateTime.mjs" }, "require": { "types": "./mn/isoDateTime.d.cts", "default": "./mn/isoDateTime.cjs" } }, "./mn/isoTime": { "import": { "types": "./mn/isoTime.d.mts", "default": "./mn/isoTime.mjs" }, "require": { "types": "./mn/isoTime.d.cts", "default": "./mn/isoTime.cjs" } }, "./mn/isoTimeSecond": { "import": { "types": "./mn/isoTimeSecond.d.mts", "default": "./mn/isoTimeSecond.mjs" }, "require": { "types": "./mn/isoTimeSecond.d.cts", "default": "./mn/isoTimeSecond.cjs" } }, "./mn/isoTimestamp": { "import": { "types": "./mn/isoTimestamp.d.mts", "default": "./mn/isoTimestamp.mjs" }, "require": { "types": "./mn/isoTimestamp.d.cts", "default": "./mn/isoTimestamp.cjs" } }, "./mn/isoWeek": { "import": { "types": "./mn/isoWeek.d.mts", "default": "./mn/isoWeek.mjs" }, "require": { "types": "./mn/isoWeek.d.cts", "default": "./mn/isoWeek.cjs" } }, "./mn/isrc": { "import": { "types": "./mn/isrc.d.mts", "default": "./mn/isrc.mjs" }, "require": { "types": "./mn/isrc.d.cts", "default": "./mn/isrc.cjs" } }, "./mn/jwsCompact": { "import": { "types": "./mn/jwsCompact.d.mts", "default": "./mn/jwsCompact.mjs" }, "require": { "types": "./mn/jwsCompact.d.cts", "default": "./mn/jwsCompact.cjs" } }, "./mn/length": { "import": { "types": "./mn/length.d.mts", "default": "./mn/length.mjs" }, "require": { "types": "./mn/length.d.cts", "default": "./mn/length.cjs" } }, "./mn/ltValue": { "import": { "types": "./mn/ltValue.d.mts", "default": "./mn/ltValue.mjs" }, "require": { "types": "./mn/ltValue.d.cts", "default": "./mn/ltValue.cjs" } }, "./mn/mac": { "import": { "types": "./mn/mac.d.mts", "default": "./mn/mac.mjs" }, "require": { "types": "./mn/mac.d.cts", "default": "./mn/mac.cjs" } }, "./mn/mac48": { "import": { "types": "./mn/mac48.d.mts", "default": "./mn/mac48.mjs" }, "require": { "types": "./mn/mac48.d.cts", "default": "./mn/mac48.cjs" } }, "./mn/mac64": { "import": { "types": "./mn/mac64.d.mts", "default": "./mn/mac64.mjs" }, "require": { "types": "./mn/mac64.d.cts", "default": "./mn/mac64.cjs" } }, "./mn/maxBytes": { "import": { "types": "./mn/maxBytes.d.mts", "default": "./mn/maxBytes.mjs" }, "require": { "types": "./mn/maxBytes.d.cts", "default": "./mn/maxBytes.cjs" } }, "./mn/maxEntries": { "import": { "types": "./mn/maxEntries.d.mts", "default": "./mn/maxEntries.mjs" }, "require": { "types": "./mn/maxEntries.d.cts", "default": "./mn/maxEntries.cjs" } }, "./mn/maxGraphemes": { "import": { "types": "./mn/maxGraphemes.d.mts", "default": "./mn/maxGraphemes.mjs" }, "require": { "types": "./mn/maxGraphemes.d.cts", "default": "./mn/maxGraphemes.cjs" } }, "./mn/maxLength": { "import": { "types": "./mn/maxLength.d.mts", "default": "./mn/maxLength.mjs" }, "require": { "types": "./mn/maxLength.d.cts", "default": "./mn/maxLength.cjs" } }, "./mn/maxSize": { "import": { "types": "./mn/maxSize.d.mts", "default": "./mn/maxSize.mjs" }, "require": { "types": "./mn/maxSize.d.cts", "default": "./mn/maxSize.cjs" } }, "./mn/maxValue": { "import": { "types": "./mn/maxValue.d.mts", "default": "./mn/maxValue.mjs" }, "require": { "types": "./mn/maxValue.d.cts", "default": "./mn/maxValue.cjs" } }, "./mn/maxWords": { "import": { "types": "./mn/maxWords.d.mts", "default": "./mn/maxWords.mjs" }, "require": { "types": "./mn/maxWords.d.cts", "default": "./mn/maxWords.cjs" } }, "./mn/mimeType": { "import": { "types": "./mn/mimeType.d.mts", "default": "./mn/mimeType.mjs" }, "require": { "types": "./mn/mimeType.d.cts", "default": "./mn/mimeType.cjs" } }, "./mn/minBytes": { "import": { "types": "./mn/minBytes.d.mts", "default": "./mn/minBytes.mjs" }, "require": { "types": "./mn/minBytes.d.cts", "default": "./mn/minBytes.cjs" } }, "./mn/minEntries": { "import": { "types": "./mn/minEntries.d.mts", "default": "./mn/minEntries.mjs" }, "require": { "types": "./mn/minEntries.d.cts", "default": "./mn/minEntries.cjs" } }, "./mn/minGraphemes": { "import": { "types": "./mn/minGraphemes.d.mts", "default": "./mn/minGraphemes.mjs" }, "require": { "types": "./mn/minGraphemes.d.cts", "default": "./mn/minGraphemes.cjs" } }, "./mn/minLength": { "import": { "types": "./mn/minLength.d.mts", "default": "./mn/minLength.mjs" }, "require": { "types": "./mn/minLength.d.cts", "default": "./mn/minLength.cjs" } }, "./mn/minSize": { "import": { "types": "./mn/minSize.d.mts", "default": "./mn/minSize.mjs" }, "require": { "types": "./mn/minSize.d.cts", "default": "./mn/minSize.cjs" } }, "./mn/minValue": { "import": { "types": "./mn/minValue.d.mts", "default": "./mn/minValue.mjs" }, "require": { "types": "./mn/minValue.d.cts", "default": "./mn/minValue.cjs" } }, "./mn/minWords": { "import": { "types": "./mn/minWords.d.mts", "default": "./mn/minWords.mjs" }, "require": { "types": "./mn/minWords.d.cts", "default": "./mn/minWords.cjs" } }, "./mn/multipleOf": { "import": { "types": "./mn/multipleOf.d.mts", "default": "./mn/multipleOf.mjs" }, "require": { "types": "./mn/multipleOf.d.cts", "default": "./mn/multipleOf.cjs" } }, "./mn/nanoid": { "import": { "types": "./mn/nanoid.d.mts", "default": "./mn/nanoid.mjs" }, "require": { "types": "./mn/nanoid.d.cts", "default": "./mn/nanoid.cjs" } }, "./mn/nonEmpty": { "import": { "types": "./mn/nonEmpty.d.mts", "default": "./mn/nonEmpty.mjs" }, "require": { "types": "./mn/nonEmpty.d.cts", "default": "./mn/nonEmpty.cjs" } }, "./mn/notBytes": { "import": { "types": "./mn/notBytes.d.mts", "default": "./mn/notBytes.mjs" }, "require": { "types": "./mn/notBytes.d.cts", "default": "./mn/notBytes.cjs" } }, "./mn/notEntries": { "import": { "types": "./mn/notEntries.d.mts", "default": "./mn/notEntries.mjs" }, "require": { "types": "./mn/notEntries.d.cts", "default": "./mn/notEntries.cjs" } }, "./mn/notGraphemes": { "import": { "types": "./mn/notGraphemes.d.mts", "default": "./mn/notGraphemes.mjs" }, "require": { "types": "./mn/notGraphemes.d.cts", "default": "./mn/notGraphemes.cjs" } }, "./mn/notLength": { "import": { "types": "./mn/notLength.d.mts", "default": "./mn/notLength.mjs" }, "require": { "types": "./mn/notLength.d.cts", "default": "./mn/notLength.cjs" } }, "./mn/notSize": { "import": { "types": "./mn/notSize.d.mts", "default": "./mn/notSize.mjs" }, "require": { "types": "./mn/notSize.d.cts", "default": "./mn/notSize.cjs" } }, "./mn/notValue": { "import": { "types": "./mn/notValue.d.mts", "default": "./mn/notValue.mjs" }, "require": { "types": "./mn/notValue.d.cts", "default": "./mn/notValue.cjs" } }, "./mn/notValues": { "import": { "types": "./mn/notValues.d.mts", "default": "./mn/notValues.mjs" }, "require": { "types": "./mn/notValues.d.cts", "default": "./mn/notValues.cjs" } }, "./mn/notWords": { "import": { "types": "./mn/notWords.d.mts", "default": "./mn/notWords.mjs" }, "require": { "types": "./mn/notWords.d.cts", "default": "./mn/notWords.cjs" } }, "./mn/octal": { "import": { "types": "./mn/octal.d.mts", "default": "./mn/octal.mjs" }, "require": { "types": "./mn/octal.d.cts", "default": "./mn/octal.cjs" } }, "./mn/parseBoolean": { "import": { "types": "./mn/parseBoolean.d.mts", "default": "./mn/parseBoolean.mjs" }, "require": { "types": "./mn/parseBoolean.d.cts", "default": "./mn/parseBoolean.cjs" } }, "./mn/parseJson": { "import": { "types": "./mn/parseJson.d.mts", "default": "./mn/parseJson.mjs" }, "require": { "types": "./mn/parseJson.d.cts", "default": "./mn/parseJson.cjs" } }, "./mn/partialCheck": { "import": { "types": "./mn/partialCheck.d.mts", "default": "./mn/partialCheck.mjs" }, "require": { "types": "./mn/partialCheck.d.cts", "default": "./mn/partialCheck.cjs" } }, "./mn/rawCheck": { "import": { "types": "./mn/rawCheck.d.mts", "default": "./mn/rawCheck.mjs" }, "require": { "types": "./mn/rawCheck.d.cts", "default": "./mn/rawCheck.cjs" } }, "./mn/rawTransform": { "import": { "types": "./mn/rawTransform.d.mts", "default": "./mn/rawTransform.mjs" }, "require": { "types": "./mn/rawTransform.d.cts", "default": "./mn/rawTransform.cjs" } }, "./mn/regex": { "import": { "types": "./mn/regex.d.mts", "default": "./mn/regex.mjs" }, "require": { "types": "./mn/regex.d.cts", "default": "./mn/regex.cjs" } }, "./mn/rfcEmail": { "import": { "types": "./mn/rfcEmail.d.mts", "default": "./mn/rfcEmail.mjs" }, "require": { "types": "./mn/rfcEmail.d.cts", "default": "./mn/rfcEmail.cjs" } }, "./mn/safeInteger": { "import": { "types": "./mn/safeInteger.d.mts", "default": "./mn/safeInteger.mjs" }, "require": { "types": "./mn/safeInteger.d.cts", "default": "./mn/safeInteger.cjs" } }, "./mn/size": { "import": { "types": "./mn/size.d.mts", "default": "./mn/size.mjs" }, "require": { "types": "./mn/size.d.cts", "default": "./mn/size.cjs" } }, "./mn/slug": { "import": { "types": "./mn/slug.d.mts", "default": "./mn/slug.mjs" }, "require": { "types": "./mn/slug.d.cts", "default": "./mn/slug.cjs" } }, "./mn/someItem": { "import": { "types": "./mn/someItem.d.mts", "default": "./mn/someItem.mjs" }, "require": { "types": "./mn/someItem.d.cts", "default": "./mn/someItem.cjs" } }, "./mn/startsWith": { "import": { "types": "./mn/startsWith.d.mts", "default": "./mn/startsWith.mjs" }, "require": { "types": "./mn/startsWith.d.cts", "default": "./mn/startsWith.cjs" } }, "./mn/stringifyJson": { "import": { "types": "./mn/stringifyJson.d.mts", "default": "./mn/stringifyJson.mjs" }, "require": { "types": "./mn/stringifyJson.d.cts", "default": "./mn/stringifyJson.cjs" } }, "./mn/toBigint": { "import": { "types": "./mn/toBigint.d.mts", "default": "./mn/toBigint.mjs" }, "require": { "types": "./mn/toBigint.d.cts", "default": "./mn/toBigint.cjs" } }, "./mn/toDate": { "import": { "types": "./mn/toDate.d.mts", "default": "./mn/toDate.mjs" }, "require": { "types": "./mn/toDate.d.cts", "default": "./mn/toDate.cjs" } }, "./mn/toNumber": { "import": { "types": "./mn/toNumber.d.mts", "default": "./mn/toNumber.mjs" }, "require": { "types": "./mn/toNumber.d.cts", "default": "./mn/toNumber.cjs" } }, "./mn/toString": { "import": { "types": "./mn/toString.d.mts", "default": "./mn/toString.mjs" }, "require": { "types": "./mn/toString.d.cts", "default": "./mn/toString.cjs" } }, "./mn/ulid": { "import": { "types": "./mn/ulid.d.mts", "default": "./mn/ulid.mjs" }, "require": { "types": "./mn/ulid.d.cts", "default": "./mn/ulid.cjs" } }, "./mn/url": { "import": { "types": "./mn/url.d.mts", "default": "./mn/url.mjs" }, "require": { "types": "./mn/url.d.cts", "default": "./mn/url.cjs" } }, "./mn/uuid": { "import": { "types": "./mn/uuid.d.mts", "default": "./mn/uuid.mjs" }, "require": { "types": "./mn/uuid.d.cts", "default": "./mn/uuid.cjs" } }, "./mn/value": { "import": { "types": "./mn/value.d.mts", "default": "./mn/value.mjs" }, "require": { "types": "./mn/value.d.cts", "default": "./mn/value.cjs" } }, "./mn/values": { "import": { "types": "./mn/values.d.mts", "default": "./mn/values.mjs" }, "require": { "types": "./mn/values.d.cts", "default": "./mn/values.cjs" } }, "./mn/words": { "import": { "types": "./mn/words.d.mts", "default": "./mn/words.mjs" }, "require": { "types": "./mn/words.d.cts", "default": "./mn/words.cjs" } }, "./nb": { "import": { "types": "./nb/index.d.mts", "default": "./nb/index.mjs" }, "require": { "types": "./nb/index.d.cts", "default": "./nb/index.cjs" } }, "./nb/schema": { "import": { "types": "./nb/schema.d.mts", "default": "./nb/schema.mjs" }, "require": { "types": "./nb/schema.d.cts", "default": "./nb/schema.cjs" } }, "./nb/base64": { "import": { "types": "./nb/base64.d.mts", "default": "./nb/base64.mjs" }, "require": { "types": "./nb/base64.d.cts", "default": "./nb/base64.cjs" } }, "./nb/bic": { "import": { "types": "./nb/bic.d.mts", "default": "./nb/bic.mjs" }, "require": { "types": "./nb/bic.d.cts", "default": "./nb/bic.cjs" } }, "./nb/bytes": { "import": { "types": "./nb/bytes.d.mts", "default": "./nb/bytes.mjs" }, "require": { "types": "./nb/bytes.d.cts", "default": "./nb/bytes.cjs" } }, "./nb/check": { "import": { "types": "./nb/check.d.mts", "default": "./nb/check.mjs" }, "require": { "types": "./nb/check.d.cts", "default": "./nb/check.cjs" } }, "./nb/checkAsync": { "import": { "types": "./nb/checkAsync.d.mts", "default": "./nb/checkAsync.mjs" }, "require": { "types": "./nb/checkAsync.d.cts", "default": "./nb/checkAsync.cjs" } }, "./nb/checkItems": { "import": { "types": "./nb/checkItems.d.mts", "default": "./nb/checkItems.mjs" }, "require": { "types": "./nb/checkItems.d.cts", "default": "./nb/checkItems.cjs" } }, "./nb/checkItemsAsync": { "import": { "types": "./nb/checkItemsAsync.d.mts", "default": "./nb/checkItemsAsync.mjs" }, "require": { "types": "./nb/checkItemsAsync.d.cts", "default": "./nb/checkItemsAsync.cjs" } }, "./nb/creditCard": { "import": { "types": "./nb/creditCard.d.mts", "default": "./nb/creditCard.mjs" }, "require": { "types": "./nb/creditCard.d.cts", "default": "./nb/creditCard.cjs" } }, "./nb/cuid2": { "import": { "types": "./nb/cuid2.d.mts", "default": "./nb/cuid2.mjs" }, "require": { "types": "./nb/cuid2.d.cts", "default": "./nb/cuid2.cjs" } }, "./nb/decimal": { "import": { "types": "./nb/decimal.d.mts", "default": "./nb/decimal.mjs" }, "require": { "types": "./nb/decimal.d.cts", "default": "./nb/decimal.cjs" } }, "./nb/digits": { "import": { "types": "./nb/digits.d.mts", "default": "./nb/digits.mjs" }, "require": { "types": "./nb/digits.d.cts", "default": "./nb/digits.cjs" } }, "./nb/domain": { "import": { "types": "./nb/domain.d.mts", "default": "./nb/domain.mjs" }, "require": { "types": "./nb/domain.d.cts", "default": "./nb/domain.cjs" } }, "./nb/email": { "import": { "types": "./nb/email.d.mts", "default": "./nb/email.mjs" }, "require": { "types": "./nb/email.d.cts", "default": "./nb/email.cjs" } }, "./nb/emoji": { "import": { "types": "./nb/emoji.d.mts", "default": "./nb/emoji.mjs" }, "require": { "types": "./nb/emoji.d.cts", "default": "./nb/emoji.cjs" } }, "./nb/empty": { "import": { "types": "./nb/empty.d.mts", "default": "./nb/empty.mjs" }, "require": { "types": "./nb/empty.d.cts", "default": "./nb/empty.cjs" } }, "./nb/endsWith": { "import": { "types": "./nb/endsWith.d.mts", "default": "./nb/endsWith.mjs" }, "require": { "types": "./nb/endsWith.d.cts", "default": "./nb/endsWith.cjs" } }, "./nb/entries": { "import": { "types": "./nb/entries.d.mts", "default": "./nb/entries.mjs" }, "require": { "types": "./nb/entries.d.cts", "default": "./nb/entries.cjs" } }, "./nb/everyItem": { "import": { "types": "./nb/everyItem.d.mts", "default": "./nb/everyItem.mjs" }, "require": { "types": "./nb/everyItem.d.cts", "default": "./nb/everyItem.cjs" } }, "./nb/excludes": { "import": { "types": "./nb/excludes.d.mts", "default": "./nb/excludes.mjs" }, "require": { "types": "./nb/excludes.d.cts", "default": "./nb/excludes.cjs" } }, "./nb/finite": { "import": { "types": "./nb/finite.d.mts", "default": "./nb/finite.mjs" }, "require": { "types": "./nb/finite.d.cts", "default": "./nb/finite.cjs" } }, "./nb/graphemes": { "import": { "types": "./nb/graphemes.d.mts", "default": "./nb/graphemes.mjs" }, "require": { "types": "./nb/graphemes.d.cts", "default": "./nb/graphemes.cjs" } }, "./nb/gtValue": { "import": { "types": "./nb/gtValue.d.mts", "default": "./nb/gtValue.mjs" }, "require": { "types": "./nb/gtValue.d.cts", "default": "./nb/gtValue.cjs" } }, "./nb/guard": { "import": { "types": "./nb/guard.d.mts", "default": "./nb/guard.mjs" }, "require": { "types": "./nb/guard.d.cts", "default": "./nb/guard.cjs" } }, "./nb/hash": { "import": { "types": "./nb/hash.d.mts", "default": "./nb/hash.mjs" }, "require": { "types": "./nb/hash.d.cts", "default": "./nb/hash.cjs" } }, "./nb/hexadecimal": { "import": { "types": "./nb/hexadecimal.d.mts", "default": "./nb/hexadecimal.mjs" }, "require": { "types": "./nb/hexadecimal.d.cts", "default": "./nb/hexadecimal.cjs" } }, "./nb/hexColor": { "import": { "types": "./nb/hexColor.d.mts", "default": "./nb/hexColor.mjs" }, "require": { "types": "./nb/hexColor.d.cts", "default": "./nb/hexColor.cjs" } }, "./nb/imei": { "import": { "types": "./nb/imei.d.mts", "default": "./nb/imei.mjs" }, "require": { "types": "./nb/imei.d.cts", "default": "./nb/imei.cjs" } }, "./nb/includes": { "import": { "types": "./nb/includes.d.mts", "default": "./nb/includes.mjs" }, "require": { "types": "./nb/includes.d.cts", "default": "./nb/includes.cjs" } }, "./nb/integer": { "import": { "types": "./nb/integer.d.mts", "default": "./nb/integer.mjs" }, "require": { "types": "./nb/integer.d.cts", "default": "./nb/integer.cjs" } }, "./nb/ip": { "import": { "types": "./nb/ip.d.mts", "default": "./nb/ip.mjs" }, "require": { "types": "./nb/ip.d.cts", "default": "./nb/ip.cjs" } }, "./nb/ipv4": { "import": { "types": "./nb/ipv4.d.mts", "default": "./nb/ipv4.mjs" }, "require": { "types": "./nb/ipv4.d.cts", "default": "./nb/ipv4.cjs" } }, "./nb/ipv6": { "import": { "types": "./nb/ipv6.d.mts", "default": "./nb/ipv6.mjs" }, "require": { "types": "./nb/ipv6.d.cts", "default": "./nb/ipv6.cjs" } }, "./nb/isbn": { "import": { "types": "./nb/isbn.d.mts", "default": "./nb/isbn.mjs" }, "require": { "types": "./nb/isbn.d.cts", "default": "./nb/isbn.cjs" } }, "./nb/isoDate": { "import": { "types": "./nb/isoDate.d.mts", "default": "./nb/isoDate.mjs" }, "require": { "types": "./nb/isoDate.d.cts", "default": "./nb/isoDate.cjs" } }, "./nb/isoDateTime": { "import": { "types": "./nb/isoDateTime.d.mts", "default": "./nb/isoDateTime.mjs" }, "require": { "types": "./nb/isoDateTime.d.cts", "default": "./nb/isoDateTime.cjs" } }, "./nb/isoTime": { "import": { "types": "./nb/isoTime.d.mts", "default": "./nb/isoTime.mjs" }, "require": { "types": "./nb/isoTime.d.cts", "default": "./nb/isoTime.cjs" } }, "./nb/isoTimeSecond": { "import": { "types": "./nb/isoTimeSecond.d.mts", "default": "./nb/isoTimeSecond.mjs" }, "require": { "types": "./nb/isoTimeSecond.d.cts", "default": "./nb/isoTimeSecond.cjs" } }, "./nb/isoTimestamp": { "import": { "types": "./nb/isoTimestamp.d.mts", "default": "./nb/isoTimestamp.mjs" }, "require": { "types": "./nb/isoTimestamp.d.cts", "default": "./nb/isoTimestamp.cjs" } }, "./nb/isoWeek": { "import": { "types": "./nb/isoWeek.d.mts", "default": "./nb/isoWeek.mjs" }, "require": { "types": "./nb/isoWeek.d.cts", "default": "./nb/isoWeek.cjs" } }, "./nb/isrc": { "import": { "types": "./nb/isrc.d.mts", "default": "./nb/isrc.mjs" }, "require": { "types": "./nb/isrc.d.cts", "default": "./nb/isrc.cjs" } }, "./nb/jwsCompact": { "import": { "types": "./nb/jwsCompact.d.mts", "default": "./nb/jwsCompact.mjs" }, "require": { "types": "./nb/jwsCompact.d.cts", "default": "./nb/jwsCompact.cjs" } }, "./nb/length": { "import": { "types": "./nb/length.d.mts", "default": "./nb/length.mjs" }, "require": { "types": "./nb/length.d.cts", "default": "./nb/length.cjs" } }, "./nb/ltValue": { "import": { "types": "./nb/ltValue.d.mts", "default": "./nb/ltValue.mjs" }, "require": { "types": "./nb/ltValue.d.cts", "default": "./nb/ltValue.cjs" } }, "./nb/mac": { "import": { "types": "./nb/mac.d.mts", "default": "./nb/mac.mjs" }, "require": { "types": "./nb/mac.d.cts", "default": "./nb/mac.cjs" } }, "./nb/mac48": { "import": { "types": "./nb/mac48.d.mts", "default": "./nb/mac48.mjs" }, "require": { "types": "./nb/mac48.d.cts", "default": "./nb/mac48.cjs" } }, "./nb/mac64": { "import": { "types": "./nb/mac64.d.mts", "default": "./nb/mac64.mjs" }, "require": { "types": "./nb/mac64.d.cts", "default": "./nb/mac64.cjs" } }, "./nb/maxBytes": { "import": { "types": "./nb/maxBytes.d.mts", "default": "./nb/maxBytes.mjs" }, "require": { "types": "./nb/maxBytes.d.cts", "default": "./nb/maxBytes.cjs" } }, "./nb/maxEntries": { "import": { "types": "./nb/maxEntries.d.mts", "default": "./nb/maxEntries.mjs" }, "require": { "types": "./nb/maxEntries.d.cts", "default": "./nb/maxEntries.cjs" } }, "./nb/maxGraphemes": { "import": { "types": "./nb/maxGraphemes.d.mts", "default": "./nb/maxGraphemes.mjs" }, "require": { "types": "./nb/maxGraphemes.d.cts", "default": "./nb/maxGraphemes.cjs" } }, "./nb/maxLength": { "import": { "types": "./nb/maxLength.d.mts", "default": "./nb/maxLength.mjs" }, "require": { "types": "./nb/maxLength.d.cts", "default": "./nb/maxLength.cjs" } }, "./nb/maxSize": { "import": { "types": "./nb/maxSize.d.mts", "default": "./nb/maxSize.mjs" }, "require": { "types": "./nb/maxSize.d.cts", "default": "./nb/maxSize.cjs" } }, "./nb/maxValue": { "import": { "types": "./nb/maxValue.d.mts", "default": "./nb/maxValue.mjs" }, "require": { "types": "./nb/maxValue.d.cts", "default": "./nb/maxValue.cjs" } }, "./nb/maxWords": { "import": { "types": "./nb/maxWords.d.mts", "default": "./nb/maxWords.mjs" }, "require": { "types": "./nb/maxWords.d.cts", "default": "./nb/maxWords.cjs" } }, "./nb/mimeType": { "import": { "types": "./nb/mimeType.d.mts", "default": "./nb/mimeType.mjs" }, "require": { "types": "./nb/mimeType.d.cts", "default": "./nb/mimeType.cjs" } }, "./nb/minBytes": { "import": { "types": "./nb/minBytes.d.mts", "default": "./nb/minBytes.mjs" }, "require": { "types": "./nb/minBytes.d.cts", "default": "./nb/minBytes.cjs" } }, "./nb/minEntries": { "import": { "types": "./nb/minEntries.d.mts", "default": "./nb/minEntries.mjs" }, "require": { "types": "./nb/minEntries.d.cts", "default": "./nb/minEntries.cjs" } }, "./nb/minGraphemes": { "import": { "types": "./nb/minGraphemes.d.mts", "default": "./nb/minGraphemes.mjs" }, "require": { "types": "./nb/minGraphemes.d.cts", "default": "./nb/minGraphemes.cjs" } }, "./nb/minLength": { "import": { "types": "./nb/minLength.d.mts", "default": "./nb/minLength.mjs" }, "require": { "types": "./nb/minLength.d.cts", "default": "./nb/minLength.cjs" } }, "./nb/minSize": { "import": { "types": "./nb/minSize.d.mts", "default": "./nb/minSize.mjs" }, "require": { "types": "./nb/minSize.d.cts", "default": "./nb/minSize.cjs" } }, "./nb/minValue": { "import": { "types": "./nb/minValue.d.mts", "default": "./nb/minValue.mjs" }, "require": { "types": "./nb/minValue.d.cts", "default": "./nb/minValue.cjs" } }, "./nb/minWords": { "import": { "types": "./nb/minWords.d.mts", "default": "./nb/minWords.mjs" }, "require": { "types": "./nb/minWords.d.cts", "default": "./nb/minWords.cjs" } }, "./nb/multipleOf": { "import": { "types": "./nb/multipleOf.d.mts", "default": "./nb/multipleOf.mjs" }, "require": { "types": "./nb/multipleOf.d.cts", "default": "./nb/multipleOf.cjs" } }, "./nb/nanoid": { "import": { "types": "./nb/nanoid.d.mts", "default": "./nb/nanoid.mjs" }, "require": { "types": "./nb/nanoid.d.cts", "default": "./nb/nanoid.cjs" } }, "./nb/nonEmpty": { "import": { "types": "./nb/nonEmpty.d.mts", "default": "./nb/nonEmpty.mjs" }, "require": { "types": "./nb/nonEmpty.d.cts", "default": "./nb/nonEmpty.cjs" } }, "./nb/notBytes": { "import": { "types": "./nb/notBytes.d.mts", "default": "./nb/notBytes.mjs" }, "require": { "types": "./nb/notBytes.d.cts", "default": "./nb/notBytes.cjs" } }, "./nb/notEntries": { "import": { "types": "./nb/notEntries.d.mts", "default": "./nb/notEntries.mjs" }, "require": { "types": "./nb/notEntries.d.cts", "default": "./nb/notEntries.cjs" } }, "./nb/notGraphemes": { "import": { "types": "./nb/notGraphemes.d.mts", "default": "./nb/notGraphemes.mjs" }, "require": { "types": "./nb/notGraphemes.d.cts", "default": "./nb/notGraphemes.cjs" } }, "./nb/notLength": { "import": { "types": "./nb/notLength.d.mts", "default": "./nb/notLength.mjs" }, "require": { "types": "./nb/notLength.d.cts", "default": "./nb/notLength.cjs" } }, "./nb/notSize": { "import": { "types": "./nb/notSize.d.mts", "default": "./nb/notSize.mjs" }, "require": { "types": "./nb/notSize.d.cts", "default": "./nb/notSize.cjs" } }, "./nb/notValue": { "import": { "types": "./nb/notValue.d.mts", "default": "./nb/notValue.mjs" }, "require": { "types": "./nb/notValue.d.cts", "default": "./nb/notValue.cjs" } }, "./nb/notValues": { "import": { "types": "./nb/notValues.d.mts", "default": "./nb/notValues.mjs" }, "require": { "types": "./nb/notValues.d.cts", "default": "./nb/notValues.cjs" } }, "./nb/notWords": { "import": { "types": "./nb/notWords.d.mts", "default": "./nb/notWords.mjs" }, "require": { "types": "./nb/notWords.d.cts", "default": "./nb/notWords.cjs" } }, "./nb/octal": { "import": { "types": "./nb/octal.d.mts", "default": "./nb/octal.mjs" }, "require": { "types": "./nb/octal.d.cts", "default": "./nb/octal.cjs" } }, "./nb/parseBoolean": { "import": { "types": "./nb/parseBoolean.d.mts", "default": "./nb/parseBoolean.mjs" }, "require": { "types": "./nb/parseBoolean.d.cts", "default": "./nb/parseBoolean.cjs" } }, "./nb/parseJson": { "import": { "types": "./nb/parseJson.d.mts", "default": "./nb/parseJson.mjs" }, "require": { "types": "./nb/parseJson.d.cts", "default": "./nb/parseJson.cjs" } }, "./nb/partialCheck": { "import": { "types": "./nb/partialCheck.d.mts", "default": "./nb/partialCheck.mjs" }, "require": { "types": "./nb/partialCheck.d.cts", "default": "./nb/partialCheck.cjs" } }, "./nb/rawCheck": { "import": { "types": "./nb/rawCheck.d.mts", "default": "./nb/rawCheck.mjs" }, "require": { "types": "./nb/rawCheck.d.cts", "default": "./nb/rawCheck.cjs" } }, "./nb/rawTransform": { "import": { "types": "./nb/rawTransform.d.mts", "default": "./nb/rawTransform.mjs" }, "require": { "types": "./nb/rawTransform.d.cts", "default": "./nb/rawTransform.cjs" } }, "./nb/regex": { "import": { "types": "./nb/regex.d.mts", "default": "./nb/regex.mjs" }, "require": { "types": "./nb/regex.d.cts", "default": "./nb/regex.cjs" } }, "./nb/rfcEmail": { "import": { "types": "./nb/rfcEmail.d.mts", "default": "./nb/rfcEmail.mjs" }, "require": { "types": "./nb/rfcEmail.d.cts", "default": "./nb/rfcEmail.cjs" } }, "./nb/safeInteger": { "import": { "types": "./nb/safeInteger.d.mts", "default": "./nb/safeInteger.mjs" }, "require": { "types": "./nb/safeInteger.d.cts", "default": "./nb/safeInteger.cjs" } }, "./nb/size": { "import": { "types": "./nb/size.d.mts", "default": "./nb/size.mjs" }, "require": { "types": "./nb/size.d.cts", "default": "./nb/size.cjs" } }, "./nb/slug": { "import": { "types": "./nb/slug.d.mts", "default": "./nb/slug.mjs" }, "require": { "types": "./nb/slug.d.cts", "default": "./nb/slug.cjs" } }, "./nb/someItem": { "import": { "types": "./nb/someItem.d.mts", "default": "./nb/someItem.mjs" }, "require": { "types": "./nb/someItem.d.cts", "default": "./nb/someItem.cjs" } }, "./nb/startsWith": { "import": { "types": "./nb/startsWith.d.mts", "default": "./nb/startsWith.mjs" }, "require": { "types": "./nb/startsWith.d.cts", "default": "./nb/startsWith.cjs" } }, "./nb/stringifyJson": { "import": { "types": "./nb/stringifyJson.d.mts", "default": "./nb/stringifyJson.mjs" }, "require": { "types": "./nb/stringifyJson.d.cts", "default": "./nb/stringifyJson.cjs" } }, "./nb/toBigint": { "import": { "types": "./nb/toBigint.d.mts", "default": "./nb/toBigint.mjs" }, "require": { "types": "./nb/toBigint.d.cts", "default": "./nb/toBigint.cjs" } }, "./nb/toDate": { "import": { "types": "./nb/toDate.d.mts", "default": "./nb/toDate.mjs" }, "require": { "types": "./nb/toDate.d.cts", "default": "./nb/toDate.cjs" } }, "./nb/toNumber": { "import": { "types": "./nb/toNumber.d.mts", "default": "./nb/toNumber.mjs" }, "require": { "types": "./nb/toNumber.d.cts", "default": "./nb/toNumber.cjs" } }, "./nb/toString": { "import": { "types": "./nb/toString.d.mts", "default": "./nb/toString.mjs" }, "require": { "types": "./nb/toString.d.cts", "default": "./nb/toString.cjs" } }, "./nb/ulid": { "import": { "types": "./nb/ulid.d.mts", "default": "./nb/ulid.mjs" }, "require": { "types": "./nb/ulid.d.cts", "default": "./nb/ulid.cjs" } }, "./nb/url": { "import": { "types": "./nb/url.d.mts", "default": "./nb/url.mjs" }, "require": { "types": "./nb/url.d.cts", "default": "./nb/url.cjs" } }, "./nb/uuid": { "import": { "types": "./nb/uuid.d.mts", "default": "./nb/uuid.mjs" }, "require": { "types": "./nb/uuid.d.cts", "default": "./nb/uuid.cjs" } }, "./nb/value": { "import": { "types": "./nb/value.d.mts", "default": "./nb/value.mjs" }, "require": { "types": "./nb/value.d.cts", "default": "./nb/value.cjs" } }, "./nb/values": { "import": { "types": "./nb/values.d.mts", "default": "./nb/values.mjs" }, "require": { "types": "./nb/values.d.cts", "default": "./nb/values.cjs" } }, "./nb/words": { "import": { "types": "./nb/words.d.mts", "default": "./nb/words.mjs" }, "require": { "types": "./nb/words.d.cts", "default": "./nb/words.cjs" } }, "./nl": { "import": { "types": "./nl/index.d.mts", "default": "./nl/index.mjs" }, "require": { "types": "./nl/index.d.cts", "default": "./nl/index.cjs" } }, "./nl/schema": { "import": { "types": "./nl/schema.d.mts", "default": "./nl/schema.mjs" }, "require": { "types": "./nl/schema.d.cts", "default": "./nl/schema.cjs" } }, "./nl/base64": { "import": { "types": "./nl/base64.d.mts", "default": "./nl/base64.mjs" }, "require": { "types": "./nl/base64.d.cts", "default": "./nl/base64.cjs" } }, "./nl/bic": { "import": { "types": "./nl/bic.d.mts", "default": "./nl/bic.mjs" }, "require": { "types": "./nl/bic.d.cts", "default": "./nl/bic.cjs" } }, "./nl/bytes": { "import": { "types": "./nl/bytes.d.mts", "default": "./nl/bytes.mjs" }, "require": { "types": "./nl/bytes.d.cts", "default": "./nl/bytes.cjs" } }, "./nl/check": { "import": { "types": "./nl/check.d.mts", "default": "./nl/check.mjs" }, "require": { "types": "./nl/check.d.cts", "default": "./nl/check.cjs" } }, "./nl/checkAsync": { "import": { "types": "./nl/checkAsync.d.mts", "default": "./nl/checkAsync.mjs" }, "require": { "types": "./nl/checkAsync.d.cts", "default": "./nl/checkAsync.cjs" } }, "./nl/checkItems": { "import": { "types": "./nl/checkItems.d.mts", "default": "./nl/checkItems.mjs" }, "require": { "types": "./nl/checkItems.d.cts", "default": "./nl/checkItems.cjs" } }, "./nl/checkItemsAsync": { "import": { "types": "./nl/checkItemsAsync.d.mts", "default": "./nl/checkItemsAsync.mjs" }, "require": { "types": "./nl/checkItemsAsync.d.cts", "default": "./nl/checkItemsAsync.cjs" } }, "./nl/creditCard": { "import": { "types": "./nl/creditCard.d.mts", "default": "./nl/creditCard.mjs" }, "require": { "types": "./nl/creditCard.d.cts", "default": "./nl/creditCard.cjs" } }, "./nl/cuid2": { "import": { "types": "./nl/cuid2.d.mts", "default": "./nl/cuid2.mjs" }, "require": { "types": "./nl/cuid2.d.cts", "default": "./nl/cuid2.cjs" } }, "./nl/decimal": { "import": { "types": "./nl/decimal.d.mts", "default": "./nl/decimal.mjs" }, "require": { "types": "./nl/decimal.d.cts", "default": "./nl/decimal.cjs" } }, "./nl/digits": { "import": { "types": "./nl/digits.d.mts", "default": "./nl/digits.mjs" }, "require": { "types": "./nl/digits.d.cts", "default": "./nl/digits.cjs" } }, "./nl/domain": { "import": { "types": "./nl/domain.d.mts", "default": "./nl/domain.mjs" }, "require": { "types": "./nl/domain.d.cts", "default": "./nl/domain.cjs" } }, "./nl/email": { "import": { "types": "./nl/email.d.mts", "default": "./nl/email.mjs" }, "require": { "types": "./nl/email.d.cts", "default": "./nl/email.cjs" } }, "./nl/emoji": { "import": { "types": "./nl/emoji.d.mts", "default": "./nl/emoji.mjs" }, "require": { "types": "./nl/emoji.d.cts", "default": "./nl/emoji.cjs" } }, "./nl/empty": { "import": { "types": "./nl/empty.d.mts", "default": "./nl/empty.mjs" }, "require": { "types": "./nl/empty.d.cts", "default": "./nl/empty.cjs" } }, "./nl/endsWith": { "import": { "types": "./nl/endsWith.d.mts", "default": "./nl/endsWith.mjs" }, "require": { "types": "./nl/endsWith.d.cts", "default": "./nl/endsWith.cjs" } }, "./nl/entries": { "import": { "types": "./nl/entries.d.mts", "default": "./nl/entries.mjs" }, "require": { "types": "./nl/entries.d.cts", "default": "./nl/entries.cjs" } }, "./nl/everyItem": { "import": { "types": "./nl/everyItem.d.mts", "default": "./nl/everyItem.mjs" }, "require": { "types": "./nl/everyItem.d.cts", "default": "./nl/everyItem.cjs" } }, "./nl/excludes": { "import": { "types": "./nl/excludes.d.mts", "default": "./nl/excludes.mjs" }, "require": { "types": "./nl/excludes.d.cts", "default": "./nl/excludes.cjs" } }, "./nl/finite": { "import": { "types": "./nl/finite.d.mts", "default": "./nl/finite.mjs" }, "require": { "types": "./nl/finite.d.cts", "default": "./nl/finite.cjs" } }, "./nl/graphemes": { "import": { "types": "./nl/graphemes.d.mts", "default": "./nl/graphemes.mjs" }, "require": { "types": "./nl/graphemes.d.cts", "default": "./nl/graphemes.cjs" } }, "./nl/gtValue": { "import": { "types": "./nl/gtValue.d.mts", "default": "./nl/gtValue.mjs" }, "require": { "types": "./nl/gtValue.d.cts", "default": "./nl/gtValue.cjs" } }, "./nl/guard": { "import": { "types": "./nl/guard.d.mts", "default": "./nl/guard.mjs" }, "require": { "types": "./nl/guard.d.cts", "default": "./nl/guard.cjs" } }, "./nl/hash": { "import": { "types": "./nl/hash.d.mts", "default": "./nl/hash.mjs" }, "require": { "types": "./nl/hash.d.cts", "default": "./nl/hash.cjs" } }, "./nl/hexadecimal": { "import": { "types": "./nl/hexadecimal.d.mts", "default": "./nl/hexadecimal.mjs" }, "require": { "types": "./nl/hexadecimal.d.cts", "default": "./nl/hexadecimal.cjs" } }, "./nl/hexColor": { "import": { "types": "./nl/hexColor.d.mts", "default": "./nl/hexColor.mjs" }, "require": { "types": "./nl/hexColor.d.cts", "default": "./nl/hexColor.cjs" } }, "./nl/imei": { "import": { "types": "./nl/imei.d.mts", "default": "./nl/imei.mjs" }, "require": { "types": "./nl/imei.d.cts", "default": "./nl/imei.cjs" } }, "./nl/includes": { "import": { "types": "./nl/includes.d.mts", "default": "./nl/includes.mjs" }, "require": { "types": "./nl/includes.d.cts", "default": "./nl/includes.cjs" } }, "./nl/integer": { "import": { "types": "./nl/integer.d.mts", "default": "./nl/integer.mjs" }, "require": { "types": "./nl/integer.d.cts", "default": "./nl/integer.cjs" } }, "./nl/ip": { "import": { "types": "./nl/ip.d.mts", "default": "./nl/ip.mjs" }, "require": { "types": "./nl/ip.d.cts", "default": "./nl/ip.cjs" } }, "./nl/ipv4": { "import": { "types": "./nl/ipv4.d.mts", "default": "./nl/ipv4.mjs" }, "require": { "types": "./nl/ipv4.d.cts", "default": "./nl/ipv4.cjs" } }, "./nl/ipv6": { "import": { "types": "./nl/ipv6.d.mts", "default": "./nl/ipv6.mjs" }, "require": { "types": "./nl/ipv6.d.cts", "default": "./nl/ipv6.cjs" } }, "./nl/isbn": { "import": { "types": "./nl/isbn.d.mts", "default": "./nl/isbn.mjs" }, "require": { "types": "./nl/isbn.d.cts", "default": "./nl/isbn.cjs" } }, "./nl/isoDate": { "import": { "types": "./nl/isoDate.d.mts", "default": "./nl/isoDate.mjs" }, "require": { "types": "./nl/isoDate.d.cts", "default": "./nl/isoDate.cjs" } }, "./nl/isoDateTime": { "import": { "types": "./nl/isoDateTime.d.mts", "default": "./nl/isoDateTime.mjs" }, "require": { "types": "./nl/isoDateTime.d.cts", "default": "./nl/isoDateTime.cjs" } }, "./nl/isoTime": { "import": { "types": "./nl/isoTime.d.mts", "default": "./nl/isoTime.mjs" }, "require": { "types": "./nl/isoTime.d.cts", "default": "./nl/isoTime.cjs" } }, "./nl/isoTimeSecond": { "import": { "types": "./nl/isoTimeSecond.d.mts", "default": "./nl/isoTimeSecond.mjs" }, "require": { "types": "./nl/isoTimeSecond.d.cts", "default": "./nl/isoTimeSecond.cjs" } }, "./nl/isoTimestamp": { "import": { "types": "./nl/isoTimestamp.d.mts", "default": "./nl/isoTimestamp.mjs" }, "require": { "types": "./nl/isoTimestamp.d.cts", "default": "./nl/isoTimestamp.cjs" } }, "./nl/isoWeek": { "import": { "types": "./nl/isoWeek.d.mts", "default": "./nl/isoWeek.mjs" }, "require": { "types": "./nl/isoWeek.d.cts", "default": "./nl/isoWeek.cjs" } }, "./nl/isrc": { "import": { "types": "./nl/isrc.d.mts", "default": "./nl/isrc.mjs" }, "require": { "types": "./nl/isrc.d.cts", "default": "./nl/isrc.cjs" } }, "./nl/jwsCompact": { "import": { "types": "./nl/jwsCompact.d.mts", "default": "./nl/jwsCompact.mjs" }, "require": { "types": "./nl/jwsCompact.d.cts", "default": "./nl/jwsCompact.cjs" } }, "./nl/length": { "import": { "types": "./nl/length.d.mts", "default": "./nl/length.mjs" }, "require": { "types": "./nl/length.d.cts", "default": "./nl/length.cjs" } }, "./nl/ltValue": { "import": { "types": "./nl/ltValue.d.mts", "default": "./nl/ltValue.mjs" }, "require": { "types": "./nl/ltValue.d.cts", "default": "./nl/ltValue.cjs" } }, "./nl/mac": { "import": { "types": "./nl/mac.d.mts", "default": "./nl/mac.mjs" }, "require": { "types": "./nl/mac.d.cts", "default": "./nl/mac.cjs" } }, "./nl/mac48": { "import": { "types": "./nl/mac48.d.mts", "default": "./nl/mac48.mjs" }, "require": { "types": "./nl/mac48.d.cts", "default": "./nl/mac48.cjs" } }, "./nl/mac64": { "import": { "types": "./nl/mac64.d.mts", "default": "./nl/mac64.mjs" }, "require": { "types": "./nl/mac64.d.cts", "default": "./nl/mac64.cjs" } }, "./nl/maxBytes": { "import": { "types": "./nl/maxBytes.d.mts", "default": "./nl/maxBytes.mjs" }, "require": { "types": "./nl/maxBytes.d.cts", "default": "./nl/maxBytes.cjs" } }, "./nl/maxEntries": { "import": { "types": "./nl/maxEntries.d.mts", "default": "./nl/maxEntries.mjs" }, "require": { "types": "./nl/maxEntries.d.cts", "default": "./nl/maxEntries.cjs" } }, "./nl/maxGraphemes": { "import": { "types": "./nl/maxGraphemes.d.mts", "default": "./nl/maxGraphemes.mjs" }, "require": { "types": "./nl/maxGraphemes.d.cts", "default": "./nl/maxGraphemes.cjs" } }, "./nl/maxLength": { "import": { "types": "./nl/maxLength.d.mts", "default": "./nl/maxLength.mjs" }, "require": { "types": "./nl/maxLength.d.cts", "default": "./nl/maxLength.cjs" } }, "./nl/maxSize": { "import": { "types": "./nl/maxSize.d.mts", "default": "./nl/maxSize.mjs" }, "require": { "types": "./nl/maxSize.d.cts", "default": "./nl/maxSize.cjs" } }, "./nl/maxValue": { "import": { "types": "./nl/maxValue.d.mts", "default": "./nl/maxValue.mjs" }, "require": { "types": "./nl/maxValue.d.cts", "default": "./nl/maxValue.cjs" } }, "./nl/maxWords": { "import": { "types": "./nl/maxWords.d.mts", "default": "./nl/maxWords.mjs" }, "require": { "types": "./nl/maxWords.d.cts", "default": "./nl/maxWords.cjs" } }, "./nl/mimeType": { "import": { "types": "./nl/mimeType.d.mts", "default": "./nl/mimeType.mjs" }, "require": { "types": "./nl/mimeType.d.cts", "default": "./nl/mimeType.cjs" } }, "./nl/minBytes": { "import": { "types": "./nl/minBytes.d.mts", "default": "./nl/minBytes.mjs" }, "require": { "types": "./nl/minBytes.d.cts", "default": "./nl/minBytes.cjs" } }, "./nl/minEntries": { "import": { "types": "./nl/minEntries.d.mts", "default": "./nl/minEntries.mjs" }, "require": { "types": "./nl/minEntries.d.cts", "default": "./nl/minEntries.cjs" } }, "./nl/minGraphemes": { "import": { "types": "./nl/minGraphemes.d.mts", "default": "./nl/minGraphemes.mjs" }, "require": { "types": "./nl/minGraphemes.d.cts", "default": "./nl/minGraphemes.cjs" } }, "./nl/minLength": { "import": { "types": "./nl/minLength.d.mts", "default": "./nl/minLength.mjs" }, "require": { "types": "./nl/minLength.d.cts", "default": "./nl/minLength.cjs" } }, "./nl/minSize": { "import": { "types": "./nl/minSize.d.mts", "default": "./nl/minSize.mjs" }, "require": { "types": "./nl/minSize.d.cts", "default": "./nl/minSize.cjs" } }, "./nl/minValue": { "import": { "types": "./nl/minValue.d.mts", "default": "./nl/minValue.mjs" }, "require": { "types": "./nl/minValue.d.cts", "default": "./nl/minValue.cjs" } }, "./nl/minWords": { "import": { "types": "./nl/minWords.d.mts", "default": "./nl/minWords.mjs" }, "require": { "types": "./nl/minWords.d.cts", "default": "./nl/minWords.cjs" } }, "./nl/multipleOf": { "import": { "types": "./nl/multipleOf.d.mts", "default": "./nl/multipleOf.mjs" }, "require": { "types": "./nl/multipleOf.d.cts", "default": "./nl/multipleOf.cjs" } }, "./nl/nanoid": { "import": { "types": "./nl/nanoid.d.mts", "default": "./nl/nanoid.mjs" }, "require": { "types": "./nl/nanoid.d.cts", "default": "./nl/nanoid.cjs" } }, "./nl/nonEmpty": { "import": { "types": "./nl/nonEmpty.d.mts", "default": "./nl/nonEmpty.mjs" }, "require": { "types": "./nl/nonEmpty.d.cts", "default": "./nl/nonEmpty.cjs" } }, "./nl/notBytes": { "import": { "types": "./nl/notBytes.d.mts", "default": "./nl/notBytes.mjs" }, "require": { "types": "./nl/notBytes.d.cts", "default": "./nl/notBytes.cjs" } }, "./nl/notEntries": { "import": { "types": "./nl/notEntries.d.mts", "default": "./nl/notEntries.mjs" }, "require": { "types": "./nl/notEntries.d.cts", "default": "./nl/notEntries.cjs" } }, "./nl/notGraphemes": { "import": { "types": "./nl/notGraphemes.d.mts", "default": "./nl/notGraphemes.mjs" }, "require": { "types": "./nl/notGraphemes.d.cts", "default": "./nl/notGraphemes.cjs" } }, "./nl/notLength": { "import": { "types": "./nl/notLength.d.mts", "default": "./nl/notLength.mjs" }, "require": { "types": "./nl/notLength.d.cts", "default": "./nl/notLength.cjs" } }, "./nl/notSize": { "import": { "types": "./nl/notSize.d.mts", "default": "./nl/notSize.mjs" }, "require": { "types": "./nl/notSize.d.cts", "default": "./nl/notSize.cjs" } }, "./nl/notValue": { "import": { "types": "./nl/notValue.d.mts", "default": "./nl/notValue.mjs" }, "require": { "types": "./nl/notValue.d.cts", "default": "./nl/notValue.cjs" } }, "./nl/notValues": { "import": { "types": "./nl/notValues.d.mts", "default": "./nl/notValues.mjs" }, "require": { "types": "./nl/notValues.d.cts", "default": "./nl/notValues.cjs" } }, "./nl/notWords": { "import": { "types": "./nl/notWords.d.mts", "default": "./nl/notWords.mjs" }, "require": { "types": "./nl/notWords.d.cts", "default": "./nl/notWords.cjs" } }, "./nl/octal": { "import": { "types": "./nl/octal.d.mts", "default": "./nl/octal.mjs" }, "require": { "types": "./nl/octal.d.cts", "default": "./nl/octal.cjs" } }, "./nl/parseBoolean": { "import": { "types": "./nl/parseBoolean.d.mts", "default": "./nl/parseBoolean.mjs" }, "require": { "types": "./nl/parseBoolean.d.cts", "default": "./nl/parseBoolean.cjs" } }, "./nl/parseJson": { "import": { "types": "./nl/parseJson.d.mts", "default": "./nl/parseJson.mjs" }, "require": { "types": "./nl/parseJson.d.cts", "default": "./nl/parseJson.cjs" } }, "./nl/partialCheck": { "import": { "types": "./nl/partialCheck.d.mts", "default": "./nl/partialCheck.mjs" }, "require": { "types": "./nl/partialCheck.d.cts", "default": "./nl/partialCheck.cjs" } }, "./nl/rawCheck": { "import": { "types": "./nl/rawCheck.d.mts", "default": "./nl/rawCheck.mjs" }, "require": { "types": "./nl/rawCheck.d.cts", "default": "./nl/rawCheck.cjs" } }, "./nl/rawTransform": { "import": { "types": "./nl/rawTransform.d.mts", "default": "./nl/rawTransform.mjs" }, "require": { "types": "./nl/rawTransform.d.cts", "default": "./nl/rawTransform.cjs" } }, "./nl/regex": { "import": { "types": "./nl/regex.d.mts", "default": "./nl/regex.mjs" }, "require": { "types": "./nl/regex.d.cts", "default": "./nl/regex.cjs" } }, "./nl/rfcEmail": { "import": { "types": "./nl/rfcEmail.d.mts", "default": "./nl/rfcEmail.mjs" }, "require": { "types": "./nl/rfcEmail.d.cts", "default": "./nl/rfcEmail.cjs" } }, "./nl/safeInteger": { "import": { "types": "./nl/safeInteger.d.mts", "default": "./nl/safeInteger.mjs" }, "require": { "types": "./nl/safeInteger.d.cts", "default": "./nl/safeInteger.cjs" } }, "./nl/size": { "import": { "types": "./nl/size.d.mts", "default": "./nl/size.mjs" }, "require": { "types": "./nl/size.d.cts", "default": "./nl/size.cjs" } }, "./nl/slug": { "import": { "types": "./nl/slug.d.mts", "default": "./nl/slug.mjs" }, "require": { "types": "./nl/slug.d.cts", "default": "./nl/slug.cjs" } }, "./nl/someItem": { "import": { "types": "./nl/someItem.d.mts", "default": "./nl/someItem.mjs" }, "require": { "types": "./nl/someItem.d.cts", "default": "./nl/someItem.cjs" } }, "./nl/startsWith": { "import": { "types": "./nl/startsWith.d.mts", "default": "./nl/startsWith.mjs" }, "require": { "types": "./nl/startsWith.d.cts", "default": "./nl/startsWith.cjs" } }, "./nl/stringifyJson": { "import": { "types": "./nl/stringifyJson.d.mts", "default": "./nl/stringifyJson.mjs" }, "require": { "types": "./nl/stringifyJson.d.cts", "default": "./nl/stringifyJson.cjs" } }, "./nl/toBigint": { "import": { "types": "./nl/toBigint.d.mts", "default": "./nl/toBigint.mjs" }, "require": { "types": "./nl/toBigint.d.cts", "default": "./nl/toBigint.cjs" } }, "./nl/toDate": { "import": { "types": "./nl/toDate.d.mts", "default": "./nl/toDate.mjs" }, "require": { "types": "./nl/toDate.d.cts", "default": "./nl/toDate.cjs" } }, "./nl/toNumber": { "import": { "types": "./nl/toNumber.d.mts", "default": "./nl/toNumber.mjs" }, "require": { "types": "./nl/toNumber.d.cts", "default": "./nl/toNumber.cjs" } }, "./nl/toString": { "import": { "types": "./nl/toString.d.mts", "default": "./nl/toString.mjs" }, "require": { "types": "./nl/toString.d.cts", "default": "./nl/toString.cjs" } }, "./nl/ulid": { "import": { "types": "./nl/ulid.d.mts", "default": "./nl/ulid.mjs" }, "require": { "types": "./nl/ulid.d.cts", "default": "./nl/ulid.cjs" } }, "./nl/url": { "import": { "types": "./nl/url.d.mts", "default": "./nl/url.mjs" }, "require": { "types": "./nl/url.d.cts", "default": "./nl/url.cjs" } }, "./nl/uuid": { "import": { "types": "./nl/uuid.d.mts", "default": "./nl/uuid.mjs" }, "require": { "types": "./nl/uuid.d.cts", "default": "./nl/uuid.cjs" } }, "./nl/value": { "import": { "types": "./nl/value.d.mts", "default": "./nl/value.mjs" }, "require": { "types": "./nl/value.d.cts", "default": "./nl/value.cjs" } }, "./nl/values": { "import": { "types": "./nl/values.d.mts", "default": "./nl/values.mjs" }, "require": { "types": "./nl/values.d.cts", "default": "./nl/values.cjs" } }, "./nl/words": { "import": { "types": "./nl/words.d.mts", "default": "./nl/words.mjs" }, "require": { "types": "./nl/words.d.cts", "default": "./nl/words.cjs" } }, "./pl": { "import": { "types": "./pl/index.d.mts", "default": "./pl/index.mjs" }, "require": { "types": "./pl/index.d.cts", "default": "./pl/index.cjs" } }, "./pl/schema": { "import": { "types": "./pl/schema.d.mts", "default": "./pl/schema.mjs" }, "require": { "types": "./pl/schema.d.cts", "default": "./pl/schema.cjs" } }, "./pl/base64": { "import": { "types": "./pl/base64.d.mts", "default": "./pl/base64.mjs" }, "require": { "types": "./pl/base64.d.cts", "default": "./pl/base64.cjs" } }, "./pl/bic": { "import": { "types": "./pl/bic.d.mts", "default": "./pl/bic.mjs" }, "require": { "types": "./pl/bic.d.cts", "default": "./pl/bic.cjs" } }, "./pl/bytes": { "import": { "types": "./pl/bytes.d.mts", "default": "./pl/bytes.mjs" }, "require": { "types": "./pl/bytes.d.cts", "default": "./pl/bytes.cjs" } }, "./pl/check": { "import": { "types": "./pl/check.d.mts", "default": "./pl/check.mjs" }, "require": { "types": "./pl/check.d.cts", "default": "./pl/check.cjs" } }, "./pl/checkAsync": { "import": { "types": "./pl/checkAsync.d.mts", "default": "./pl/checkAsync.mjs" }, "require": { "types": "./pl/checkAsync.d.cts", "default": "./pl/checkAsync.cjs" } }, "./pl/checkItems": { "import": { "types": "./pl/checkItems.d.mts", "default": "./pl/checkItems.mjs" }, "require": { "types": "./pl/checkItems.d.cts", "default": "./pl/checkItems.cjs" } }, "./pl/checkItemsAsync": { "import": { "types": "./pl/checkItemsAsync.d.mts", "default": "./pl/checkItemsAsync.mjs" }, "require": { "types": "./pl/checkItemsAsync.d.cts", "default": "./pl/checkItemsAsync.cjs" } }, "./pl/creditCard": { "import": { "types": "./pl/creditCard.d.mts", "default": "./pl/creditCard.mjs" }, "require": { "types": "./pl/creditCard.d.cts", "default": "./pl/creditCard.cjs" } }, "./pl/cuid2": { "import": { "types": "./pl/cuid2.d.mts", "default": "./pl/cuid2.mjs" }, "require": { "types": "./pl/cuid2.d.cts", "default": "./pl/cuid2.cjs" } }, "./pl/decimal": { "import": { "types": "./pl/decimal.d.mts", "default": "./pl/decimal.mjs" }, "require": { "types": "./pl/decimal.d.cts", "default": "./pl/decimal.cjs" } }, "./pl/digits": { "import": { "types": "./pl/digits.d.mts", "default": "./pl/digits.mjs" }, "require": { "types": "./pl/digits.d.cts", "default": "./pl/digits.cjs" } }, "./pl/domain": { "import": { "types": "./pl/domain.d.mts", "default": "./pl/domain.mjs" }, "require": { "types": "./pl/domain.d.cts", "default": "./pl/domain.cjs" } }, "./pl/email": { "import": { "types": "./pl/email.d.mts", "default": "./pl/email.mjs" }, "require": { "types": "./pl/email.d.cts", "default": "./pl/email.cjs" } }, "./pl/emoji": { "import": { "types": "./pl/emoji.d.mts", "default": "./pl/emoji.mjs" }, "require": { "types": "./pl/emoji.d.cts", "default": "./pl/emoji.cjs" } }, "./pl/empty": { "import": { "types": "./pl/empty.d.mts", "default": "./pl/empty.mjs" }, "require": { "types": "./pl/empty.d.cts", "default": "./pl/empty.cjs" } }, "./pl/endsWith": { "import": { "types": "./pl/endsWith.d.mts", "default": "./pl/endsWith.mjs" }, "require": { "types": "./pl/endsWith.d.cts", "default": "./pl/endsWith.cjs" } }, "./pl/entries": { "import": { "types": "./pl/entries.d.mts", "default": "./pl/entries.mjs" }, "require": { "types": "./pl/entries.d.cts", "default": "./pl/entries.cjs" } }, "./pl/everyItem": { "import": { "types": "./pl/everyItem.d.mts", "default": "./pl/everyItem.mjs" }, "require": { "types": "./pl/everyItem.d.cts", "default": "./pl/everyItem.cjs" } }, "./pl/excludes": { "import": { "types": "./pl/excludes.d.mts", "default": "./pl/excludes.mjs" }, "require": { "types": "./pl/excludes.d.cts", "default": "./pl/excludes.cjs" } }, "./pl/finite": { "import": { "types": "./pl/finite.d.mts", "default": "./pl/finite.mjs" }, "require": { "types": "./pl/finite.d.cts", "default": "./pl/finite.cjs" } }, "./pl/graphemes": { "import": { "types": "./pl/graphemes.d.mts", "default": "./pl/graphemes.mjs" }, "require": { "types": "./pl/graphemes.d.cts", "default": "./pl/graphemes.cjs" } }, "./pl/gtValue": { "import": { "types": "./pl/gtValue.d.mts", "default": "./pl/gtValue.mjs" }, "require": { "types": "./pl/gtValue.d.cts", "default": "./pl/gtValue.cjs" } }, "./pl/guard": { "import": { "types": "./pl/guard.d.mts", "default": "./pl/guard.mjs" }, "require": { "types": "./pl/guard.d.cts", "default": "./pl/guard.cjs" } }, "./pl/hash": { "import": { "types": "./pl/hash.d.mts", "default": "./pl/hash.mjs" }, "require": { "types": "./pl/hash.d.cts", "default": "./pl/hash.cjs" } }, "./pl/hexadecimal": { "import": { "types": "./pl/hexadecimal.d.mts", "default": "./pl/hexadecimal.mjs" }, "require": { "types": "./pl/hexadecimal.d.cts", "default": "./pl/hexadecimal.cjs" } }, "./pl/hexColor": { "import": { "types": "./pl/hexColor.d.mts", "default": "./pl/hexColor.mjs" }, "require": { "types": "./pl/hexColor.d.cts", "default": "./pl/hexColor.cjs" } }, "./pl/imei": { "import": { "types": "./pl/imei.d.mts", "default": "./pl/imei.mjs" }, "require": { "types": "./pl/imei.d.cts", "default": "./pl/imei.cjs" } }, "./pl/includes": { "import": { "types": "./pl/includes.d.mts", "default": "./pl/includes.mjs" }, "require": { "types": "./pl/includes.d.cts", "default": "./pl/includes.cjs" } }, "./pl/integer": { "import": { "types": "./pl/integer.d.mts", "default": "./pl/integer.mjs" }, "require": { "types": "./pl/integer.d.cts", "default": "./pl/integer.cjs" } }, "./pl/ip": { "import": { "types": "./pl/ip.d.mts", "default": "./pl/ip.mjs" }, "require": { "types": "./pl/ip.d.cts", "default": "./pl/ip.cjs" } }, "./pl/ipv4": { "import": { "types": "./pl/ipv4.d.mts", "default": "./pl/ipv4.mjs" }, "require": { "types": "./pl/ipv4.d.cts", "default": "./pl/ipv4.cjs" } }, "./pl/ipv6": { "import": { "types": "./pl/ipv6.d.mts", "default": "./pl/ipv6.mjs" }, "require": { "types": "./pl/ipv6.d.cts", "default": "./pl/ipv6.cjs" } }, "./pl/isbn": { "import": { "types": "./pl/isbn.d.mts", "default": "./pl/isbn.mjs" }, "require": { "types": "./pl/isbn.d.cts", "default": "./pl/isbn.cjs" } }, "./pl/isoDate": { "import": { "types": "./pl/isoDate.d.mts", "default": "./pl/isoDate.mjs" }, "require": { "types": "./pl/isoDate.d.cts", "default": "./pl/isoDate.cjs" } }, "./pl/isoDateTime": { "import": { "types": "./pl/isoDateTime.d.mts", "default": "./pl/isoDateTime.mjs" }, "require": { "types": "./pl/isoDateTime.d.cts", "default": "./pl/isoDateTime.cjs" } }, "./pl/isoTime": { "import": { "types": "./pl/isoTime.d.mts", "default": "./pl/isoTime.mjs" }, "require": { "types": "./pl/isoTime.d.cts", "default": "./pl/isoTime.cjs" } }, "./pl/isoTimeSecond": { "import": { "types": "./pl/isoTimeSecond.d.mts", "default": "./pl/isoTimeSecond.mjs" }, "require": { "types": "./pl/isoTimeSecond.d.cts", "default": "./pl/isoTimeSecond.cjs" } }, "./pl/isoTimestamp": { "import": { "types": "./pl/isoTimestamp.d.mts", "default": "./pl/isoTimestamp.mjs" }, "require": { "types": "./pl/isoTimestamp.d.cts", "default": "./pl/isoTimestamp.cjs" } }, "./pl/isoWeek": { "import": { "types": "./pl/isoWeek.d.mts", "default": "./pl/isoWeek.mjs" }, "require": { "types": "./pl/isoWeek.d.cts", "default": "./pl/isoWeek.cjs" } }, "./pl/isrc": { "import": { "types": "./pl/isrc.d.mts", "default": "./pl/isrc.mjs" }, "require": { "types": "./pl/isrc.d.cts", "default": "./pl/isrc.cjs" } }, "./pl/jwsCompact": { "import": { "types": "./pl/jwsCompact.d.mts", "default": "./pl/jwsCompact.mjs" }, "require": { "types": "./pl/jwsCompact.d.cts", "default": "./pl/jwsCompact.cjs" } }, "./pl/length": { "import": { "types": "./pl/length.d.mts", "default": "./pl/length.mjs" }, "require": { "types": "./pl/length.d.cts", "default": "./pl/length.cjs" } }, "./pl/ltValue": { "import": { "types": "./pl/ltValue.d.mts", "default": "./pl/ltValue.mjs" }, "require": { "types": "./pl/ltValue.d.cts", "default": "./pl/ltValue.cjs" } }, "./pl/mac": { "import": { "types": "./pl/mac.d.mts", "default": "./pl/mac.mjs" }, "require": { "types": "./pl/mac.d.cts", "default": "./pl/mac.cjs" } }, "./pl/mac48": { "import": { "types": "./pl/mac48.d.mts", "default": "./pl/mac48.mjs" }, "require": { "types": "./pl/mac48.d.cts", "default": "./pl/mac48.cjs" } }, "./pl/mac64": { "import": { "types": "./pl/mac64.d.mts", "default": "./pl/mac64.mjs" }, "require": { "types": "./pl/mac64.d.cts", "default": "./pl/mac64.cjs" } }, "./pl/maxBytes": { "import": { "types": "./pl/maxBytes.d.mts", "default": "./pl/maxBytes.mjs" }, "require": { "types": "./pl/maxBytes.d.cts", "default": "./pl/maxBytes.cjs" } }, "./pl/maxEntries": { "import": { "types": "./pl/maxEntries.d.mts", "default": "./pl/maxEntries.mjs" }, "require": { "types": "./pl/maxEntries.d.cts", "default": "./pl/maxEntries.cjs" } }, "./pl/maxGraphemes": { "import": { "types": "./pl/maxGraphemes.d.mts", "default": "./pl/maxGraphemes.mjs" }, "require": { "types": "./pl/maxGraphemes.d.cts", "default": "./pl/maxGraphemes.cjs" } }, "./pl/maxLength": { "import": { "types": "./pl/maxLength.d.mts", "default": "./pl/maxLength.mjs" }, "require": { "types": "./pl/maxLength.d.cts", "default": "./pl/maxLength.cjs" } }, "./pl/maxSize": { "import": { "types": "./pl/maxSize.d.mts", "default": "./pl/maxSize.mjs" }, "require": { "types": "./pl/maxSize.d.cts", "default": "./pl/maxSize.cjs" } }, "./pl/maxValue": { "import": { "types": "./pl/maxValue.d.mts", "default": "./pl/maxValue.mjs" }, "require": { "types": "./pl/maxValue.d.cts", "default": "./pl/maxValue.cjs" } }, "./pl/maxWords": { "import": { "types": "./pl/maxWords.d.mts", "default": "./pl/maxWords.mjs" }, "require": { "types": "./pl/maxWords.d.cts", "default": "./pl/maxWords.cjs" } }, "./pl/mimeType": { "import": { "types": "./pl/mimeType.d.mts", "default": "./pl/mimeType.mjs" }, "require": { "types": "./pl/mimeType.d.cts", "default": "./pl/mimeType.cjs" } }, "./pl/minBytes": { "import": { "types": "./pl/minBytes.d.mts", "default": "./pl/minBytes.mjs" }, "require": { "types": "./pl/minBytes.d.cts", "default": "./pl/minBytes.cjs" } }, "./pl/minEntries": { "import": { "types": "./pl/minEntries.d.mts", "default": "./pl/minEntries.mjs" }, "require": { "types": "./pl/minEntries.d.cts", "default": "./pl/minEntries.cjs" } }, "./pl/minGraphemes": { "import": { "types": "./pl/minGraphemes.d.mts", "default": "./pl/minGraphemes.mjs" }, "require": { "types": "./pl/minGraphemes.d.cts", "default": "./pl/minGraphemes.cjs" } }, "./pl/minLength": { "import": { "types": "./pl/minLength.d.mts", "default": "./pl/minLength.mjs" }, "require": { "types": "./pl/minLength.d.cts", "default": "./pl/minLength.cjs" } }, "./pl/minSize": { "import": { "types": "./pl/minSize.d.mts", "default": "./pl/minSize.mjs" }, "require": { "types": "./pl/minSize.d.cts", "default": "./pl/minSize.cjs" } }, "./pl/minValue": { "import": { "types": "./pl/minValue.d.mts", "default": "./pl/minValue.mjs" }, "require": { "types": "./pl/minValue.d.cts", "default": "./pl/minValue.cjs" } }, "./pl/minWords": { "import": { "types": "./pl/minWords.d.mts", "default": "./pl/minWords.mjs" }, "require": { "types": "./pl/minWords.d.cts", "default": "./pl/minWords.cjs" } }, "./pl/multipleOf": { "import": { "types": "./pl/multipleOf.d.mts", "default": "./pl/multipleOf.mjs" }, "require": { "types": "./pl/multipleOf.d.cts", "default": "./pl/multipleOf.cjs" } }, "./pl/nanoid": { "import": { "types": "./pl/nanoid.d.mts", "default": "./pl/nanoid.mjs" }, "require": { "types": "./pl/nanoid.d.cts", "default": "./pl/nanoid.cjs" } }, "./pl/nonEmpty": { "import": { "types": "./pl/nonEmpty.d.mts", "default": "./pl/nonEmpty.mjs" }, "require": { "types": "./pl/nonEmpty.d.cts", "default": "./pl/nonEmpty.cjs" } }, "./pl/notBytes": { "import": { "types": "./pl/notBytes.d.mts", "default": "./pl/notBytes.mjs" }, "require": { "types": "./pl/notBytes.d.cts", "default": "./pl/notBytes.cjs" } }, "./pl/notEntries": { "import": { "types": "./pl/notEntries.d.mts", "default": "./pl/notEntries.mjs" }, "require": { "types": "./pl/notEntries.d.cts", "default": "./pl/notEntries.cjs" } }, "./pl/notGraphemes": { "import": { "types": "./pl/notGraphemes.d.mts", "default": "./pl/notGraphemes.mjs" }, "require": { "types": "./pl/notGraphemes.d.cts", "default": "./pl/notGraphemes.cjs" } }, "./pl/notLength": { "import": { "types": "./pl/notLength.d.mts", "default": "./pl/notLength.mjs" }, "require": { "types": "./pl/notLength.d.cts", "default": "./pl/notLength.cjs" } }, "./pl/notSize": { "import": { "types": "./pl/notSize.d.mts", "default": "./pl/notSize.mjs" }, "require": { "types": "./pl/notSize.d.cts", "default": "./pl/notSize.cjs" } }, "./pl/notValue": { "import": { "types": "./pl/notValue.d.mts", "default": "./pl/notValue.mjs" }, "require": { "types": "./pl/notValue.d.cts", "default": "./pl/notValue.cjs" } }, "./pl/notValues": { "import": { "types": "./pl/notValues.d.mts", "default": "./pl/notValues.mjs" }, "require": { "types": "./pl/notValues.d.cts", "default": "./pl/notValues.cjs" } }, "./pl/notWords": { "import": { "types": "./pl/notWords.d.mts", "default": "./pl/notWords.mjs" }, "require": { "types": "./pl/notWords.d.cts", "default": "./pl/notWords.cjs" } }, "./pl/octal": { "import": { "types": "./pl/octal.d.mts", "default": "./pl/octal.mjs" }, "require": { "types": "./pl/octal.d.cts", "default": "./pl/octal.cjs" } }, "./pl/parseBoolean": { "import": { "types": "./pl/parseBoolean.d.mts", "default": "./pl/parseBoolean.mjs" }, "require": { "types": "./pl/parseBoolean.d.cts", "default": "./pl/parseBoolean.cjs" } }, "./pl/parseJson": { "import": { "types": "./pl/parseJson.d.mts", "default": "./pl/parseJson.mjs" }, "require": { "types": "./pl/parseJson.d.cts", "default": "./pl/parseJson.cjs" } }, "./pl/partialCheck": { "import": { "types": "./pl/partialCheck.d.mts", "default": "./pl/partialCheck.mjs" }, "require": { "types": "./pl/partialCheck.d.cts", "default": "./pl/partialCheck.cjs" } }, "./pl/rawCheck": { "import": { "types": "./pl/rawCheck.d.mts", "default": "./pl/rawCheck.mjs" }, "require": { "types": "./pl/rawCheck.d.cts", "default": "./pl/rawCheck.cjs" } }, "./pl/rawTransform": { "import": { "types": "./pl/rawTransform.d.mts", "default": "./pl/rawTransform.mjs" }, "require": { "types": "./pl/rawTransform.d.cts", "default": "./pl/rawTransform.cjs" } }, "./pl/regex": { "import": { "types": "./pl/regex.d.mts", "default": "./pl/regex.mjs" }, "require": { "types": "./pl/regex.d.cts", "default": "./pl/regex.cjs" } }, "./pl/rfcEmail": { "import": { "types": "./pl/rfcEmail.d.mts", "default": "./pl/rfcEmail.mjs" }, "require": { "types": "./pl/rfcEmail.d.cts", "default": "./pl/rfcEmail.cjs" } }, "./pl/safeInteger": { "import": { "types": "./pl/safeInteger.d.mts", "default": "./pl/safeInteger.mjs" }, "require": { "types": "./pl/safeInteger.d.cts", "default": "./pl/safeInteger.cjs" } }, "./pl/size": { "import": { "types": "./pl/size.d.mts", "default": "./pl/size.mjs" }, "require": { "types": "./pl/size.d.cts", "default": "./pl/size.cjs" } }, "./pl/slug": { "import": { "types": "./pl/slug.d.mts", "default": "./pl/slug.mjs" }, "require": { "types": "./pl/slug.d.cts", "default": "./pl/slug.cjs" } }, "./pl/someItem": { "import": { "types": "./pl/someItem.d.mts", "default": "./pl/someItem.mjs" }, "require": { "types": "./pl/someItem.d.cts", "default": "./pl/someItem.cjs" } }, "./pl/startsWith": { "import": { "types": "./pl/startsWith.d.mts", "default": "./pl/startsWith.mjs" }, "require": { "types": "./pl/startsWith.d.cts", "default": "./pl/startsWith.cjs" } }, "./pl/stringifyJson": { "import": { "types": "./pl/stringifyJson.d.mts", "default": "./pl/stringifyJson.mjs" }, "require": { "types": "./pl/stringifyJson.d.cts", "default": "./pl/stringifyJson.cjs" } }, "./pl/toBigint": { "import": { "types": "./pl/toBigint.d.mts", "default": "./pl/toBigint.mjs" }, "require": { "types": "./pl/toBigint.d.cts", "default": "./pl/toBigint.cjs" } }, "./pl/toDate": { "import": { "types": "./pl/toDate.d.mts", "default": "./pl/toDate.mjs" }, "require": { "types": "./pl/toDate.d.cts", "default": "./pl/toDate.cjs" } }, "./pl/toNumber": { "import": { "types": "./pl/toNumber.d.mts", "default": "./pl/toNumber.mjs" }, "require": { "types": "./pl/toNumber.d.cts", "default": "./pl/toNumber.cjs" } }, "./pl/toString": { "import": { "types": "./pl/toString.d.mts", "default": "./pl/toString.mjs" }, "require": { "types": "./pl/toString.d.cts", "default": "./pl/toString.cjs" } }, "./pl/ulid": { "import": { "types": "./pl/ulid.d.mts", "default": "./pl/ulid.mjs" }, "require": { "types": "./pl/ulid.d.cts", "default": "./pl/ulid.cjs" } }, "./pl/url": { "import": { "types": "./pl/url.d.mts", "default": "./pl/url.mjs" }, "require": { "types": "./pl/url.d.cts", "default": "./pl/url.cjs" } }, "./pl/uuid": { "import": { "types": "./pl/uuid.d.mts", "default": "./pl/uuid.mjs" }, "require": { "types": "./pl/uuid.d.cts", "default": "./pl/uuid.cjs" } }, "./pl/value": { "import": { "types": "./pl/value.d.mts", "default": "./pl/value.mjs" }, "require": { "types": "./pl/value.d.cts", "default": "./pl/value.cjs" } }, "./pl/values": { "import": { "types": "./pl/values.d.mts", "default": "./pl/values.mjs" }, "require": { "types": "./pl/values.d.cts", "default": "./pl/values.cjs" } }, "./pl/words": { "import": { "types": "./pl/words.d.mts", "default": "./pl/words.mjs" }, "require": { "types": "./pl/words.d.cts", "default": "./pl/words.cjs" } }, "./pt": { "import": { "types": "./pt/index.d.mts", "default": "./pt/index.mjs" }, "require": { "types": "./pt/index.d.cts", "default": "./pt/index.cjs" } }, "./pt/schema": { "import": { "types": "./pt/schema.d.mts", "default": "./pt/schema.mjs" }, "require": { "types": "./pt/schema.d.cts", "default": "./pt/schema.cjs" } }, "./pt/base64": { "import": { "types": "./pt/base64.d.mts", "default": "./pt/base64.mjs" }, "require": { "types": "./pt/base64.d.cts", "default": "./pt/base64.cjs" } }, "./pt/bic": { "import": { "types": "./pt/bic.d.mts", "default": "./pt/bic.mjs" }, "require": { "types": "./pt/bic.d.cts", "default": "./pt/bic.cjs" } }, "./pt/bytes": { "import": { "types": "./pt/bytes.d.mts", "default": "./pt/bytes.mjs" }, "require": { "types": "./pt/bytes.d.cts", "default": "./pt/bytes.cjs" } }, "./pt/check": { "import": { "types": "./pt/check.d.mts", "default": "./pt/check.mjs" }, "require": { "types": "./pt/check.d.cts", "default": "./pt/check.cjs" } }, "./pt/checkAsync": { "import": { "types": "./pt/checkAsync.d.mts", "default": "./pt/checkAsync.mjs" }, "require": { "types": "./pt/checkAsync.d.cts", "default": "./pt/checkAsync.cjs" } }, "./pt/checkItems": { "import": { "types": "./pt/checkItems.d.mts", "default": "./pt/checkItems.mjs" }, "require": { "types": "./pt/checkItems.d.cts", "default": "./pt/checkItems.cjs" } }, "./pt/checkItemsAsync": { "import": { "types": "./pt/checkItemsAsync.d.mts", "default": "./pt/checkItemsAsync.mjs" }, "require": { "types": "./pt/checkItemsAsync.d.cts", "default": "./pt/checkItemsAsync.cjs" } }, "./pt/creditCard": { "import": { "types": "./pt/creditCard.d.mts", "default": "./pt/creditCard.mjs" }, "require": { "types": "./pt/creditCard.d.cts", "default": "./pt/creditCard.cjs" } }, "./pt/cuid2": { "import": { "types": "./pt/cuid2.d.mts", "default": "./pt/cuid2.mjs" }, "require": { "types": "./pt/cuid2.d.cts", "default": "./pt/cuid2.cjs" } }, "./pt/decimal": { "import": { "types": "./pt/decimal.d.mts", "default": "./pt/decimal.mjs" }, "require": { "types": "./pt/decimal.d.cts", "default": "./pt/decimal.cjs" } }, "./pt/digits": { "import": { "types": "./pt/digits.d.mts", "default": "./pt/digits.mjs" }, "require": { "types": "./pt/digits.d.cts", "default": "./pt/digits.cjs" } }, "./pt/domain": { "import": { "types": "./pt/domain.d.mts", "default": "./pt/domain.mjs" }, "require": { "types": "./pt/domain.d.cts", "default": "./pt/domain.cjs" } }, "./pt/email": { "import": { "types": "./pt/email.d.mts", "default": "./pt/email.mjs" }, "require": { "types": "./pt/email.d.cts", "default": "./pt/email.cjs" } }, "./pt/emoji": { "import": { "types": "./pt/emoji.d.mts", "default": "./pt/emoji.mjs" }, "require": { "types": "./pt/emoji.d.cts", "default": "./pt/emoji.cjs" } }, "./pt/empty": { "import": { "types": "./pt/empty.d.mts", "default": "./pt/empty.mjs" }, "require": { "types": "./pt/empty.d.cts", "default": "./pt/empty.cjs" } }, "./pt/endsWith": { "import": { "types": "./pt/endsWith.d.mts", "default": "./pt/endsWith.mjs" }, "require": { "types": "./pt/endsWith.d.cts", "default": "./pt/endsWith.cjs" } }, "./pt/entries": { "import": { "types": "./pt/entries.d.mts", "default": "./pt/entries.mjs" }, "require": { "types": "./pt/entries.d.cts", "default": "./pt/entries.cjs" } }, "./pt/everyItem": { "import": { "types": "./pt/everyItem.d.mts", "default": "./pt/everyItem.mjs" }, "require": { "types": "./pt/everyItem.d.cts", "default": "./pt/everyItem.cjs" } }, "./pt/excludes": { "import": { "types": "./pt/excludes.d.mts", "default": "./pt/excludes.mjs" }, "require": { "types": "./pt/excludes.d.cts", "default": "./pt/excludes.cjs" } }, "./pt/finite": { "import": { "types": "./pt/finite.d.mts", "default": "./pt/finite.mjs" }, "require": { "types": "./pt/finite.d.cts", "default": "./pt/finite.cjs" } }, "./pt/graphemes": { "import": { "types": "./pt/graphemes.d.mts", "default": "./pt/graphemes.mjs" }, "require": { "types": "./pt/graphemes.d.cts", "default": "./pt/graphemes.cjs" } }, "./pt/gtValue": { "import": { "types": "./pt/gtValue.d.mts", "default": "./pt/gtValue.mjs" }, "require": { "types": "./pt/gtValue.d.cts", "default": "./pt/gtValue.cjs" } }, "./pt/guard": { "import": { "types": "./pt/guard.d.mts", "default": "./pt/guard.mjs" }, "require": { "types": "./pt/guard.d.cts", "default": "./pt/guard.cjs" } }, "./pt/hash": { "import": { "types": "./pt/hash.d.mts", "default": "./pt/hash.mjs" }, "require": { "types": "./pt/hash.d.cts", "default": "./pt/hash.cjs" } }, "./pt/hexadecimal": { "import": { "types": "./pt/hexadecimal.d.mts", "default": "./pt/hexadecimal.mjs" }, "require": { "types": "./pt/hexadecimal.d.cts", "default": "./pt/hexadecimal.cjs" } }, "./pt/hexColor": { "import": { "types": "./pt/hexColor.d.mts", "default": "./pt/hexColor.mjs" }, "require": { "types": "./pt/hexColor.d.cts", "default": "./pt/hexColor.cjs" } }, "./pt/imei": { "import": { "types": "./pt/imei.d.mts", "default": "./pt/imei.mjs" }, "require": { "types": "./pt/imei.d.cts", "default": "./pt/imei.cjs" } }, "./pt/includes": { "import": { "types": "./pt/includes.d.mts", "default": "./pt/includes.mjs" }, "require": { "types": "./pt/includes.d.cts", "default": "./pt/includes.cjs" } }, "./pt/integer": { "import": { "types": "./pt/integer.d.mts", "default": "./pt/integer.mjs" }, "require": { "types": "./pt/integer.d.cts", "default": "./pt/integer.cjs" } }, "./pt/ip": { "import": { "types": "./pt/ip.d.mts", "default": "./pt/ip.mjs" }, "require": { "types": "./pt/ip.d.cts", "default": "./pt/ip.cjs" } }, "./pt/ipv4": { "import": { "types": "./pt/ipv4.d.mts", "default": "./pt/ipv4.mjs" }, "require": { "types": "./pt/ipv4.d.cts", "default": "./pt/ipv4.cjs" } }, "./pt/ipv6": { "import": { "types": "./pt/ipv6.d.mts", "default": "./pt/ipv6.mjs" }, "require": { "types": "./pt/ipv6.d.cts", "default": "./pt/ipv6.cjs" } }, "./pt/isbn": { "import": { "types": "./pt/isbn.d.mts", "default": "./pt/isbn.mjs" }, "require": { "types": "./pt/isbn.d.cts", "default": "./pt/isbn.cjs" } }, "./pt/isoDate": { "import": { "types": "./pt/isoDate.d.mts", "default": "./pt/isoDate.mjs" }, "require": { "types": "./pt/isoDate.d.cts", "default": "./pt/isoDate.cjs" } }, "./pt/isoDateTime": { "import": { "types": "./pt/isoDateTime.d.mts", "default": "./pt/isoDateTime.mjs" }, "require": { "types": "./pt/isoDateTime.d.cts", "default": "./pt/isoDateTime.cjs" } }, "./pt/isoTime": { "import": { "types": "./pt/isoTime.d.mts", "default": "./pt/isoTime.mjs" }, "require": { "types": "./pt/isoTime.d.cts", "default": "./pt/isoTime.cjs" } }, "./pt/isoTimeSecond": { "import": { "types": "./pt/isoTimeSecond.d.mts", "default": "./pt/isoTimeSecond.mjs" }, "require": { "types": "./pt/isoTimeSecond.d.cts", "default": "./pt/isoTimeSecond.cjs" } }, "./pt/isoTimestamp": { "import": { "types": "./pt/isoTimestamp.d.mts", "default": "./pt/isoTimestamp.mjs" }, "require": { "types": "./pt/isoTimestamp.d.cts", "default": "./pt/isoTimestamp.cjs" } }, "./pt/isoWeek": { "import": { "types": "./pt/isoWeek.d.mts", "default": "./pt/isoWeek.mjs" }, "require": { "types": "./pt/isoWeek.d.cts", "default": "./pt/isoWeek.cjs" } }, "./pt/isrc": { "import": { "types": "./pt/isrc.d.mts", "default": "./pt/isrc.mjs" }, "require": { "types": "./pt/isrc.d.cts", "default": "./pt/isrc.cjs" } }, "./pt/jwsCompact": { "import": { "types": "./pt/jwsCompact.d.mts", "default": "./pt/jwsCompact.mjs" }, "require": { "types": "./pt/jwsCompact.d.cts", "default": "./pt/jwsCompact.cjs" } }, "./pt/length": { "import": { "types": "./pt/length.d.mts", "default": "./pt/length.mjs" }, "require": { "types": "./pt/length.d.cts", "default": "./pt/length.cjs" } }, "./pt/ltValue": { "import": { "types": "./pt/ltValue.d.mts", "default": "./pt/ltValue.mjs" }, "require": { "types": "./pt/ltValue.d.cts", "default": "./pt/ltValue.cjs" } }, "./pt/mac": { "import": { "types": "./pt/mac.d.mts", "default": "./pt/mac.mjs" }, "require": { "types": "./pt/mac.d.cts", "default": "./pt/mac.cjs" } }, "./pt/mac48": { "import": { "types": "./pt/mac48.d.mts", "default": "./pt/mac48.mjs" }, "require": { "types": "./pt/mac48.d.cts", "default": "./pt/mac48.cjs" } }, "./pt/mac64": { "import": { "types": "./pt/mac64.d.mts", "default": "./pt/mac64.mjs" }, "require": { "types": "./pt/mac64.d.cts", "default": "./pt/mac64.cjs" } }, "./pt/maxBytes": { "import": { "types": "./pt/maxBytes.d.mts", "default": "./pt/maxBytes.mjs" }, "require": { "types": "./pt/maxBytes.d.cts", "default": "./pt/maxBytes.cjs" } }, "./pt/maxEntries": { "import": { "types": "./pt/maxEntries.d.mts", "default": "./pt/maxEntries.mjs" }, "require": { "types": "./pt/maxEntries.d.cts", "default": "./pt/maxEntries.cjs" } }, "./pt/maxGraphemes": { "import": { "types": "./pt/maxGraphemes.d.mts", "default": "./pt/maxGraphemes.mjs" }, "require": { "types": "./pt/maxGraphemes.d.cts", "default": "./pt/maxGraphemes.cjs" } }, "./pt/maxLength": { "import": { "types": "./pt/maxLength.d.mts", "default": "./pt/maxLength.mjs" }, "require": { "types": "./pt/maxLength.d.cts", "default": "./pt/maxLength.cjs" } }, "./pt/maxSize": { "import": { "types": "./pt/maxSize.d.mts", "default": "./pt/maxSize.mjs" }, "require": { "types": "./pt/maxSize.d.cts", "default": "./pt/maxSize.cjs" } }, "./pt/maxValue": { "import": { "types": "./pt/maxValue.d.mts", "default": "./pt/maxValue.mjs" }, "require": { "types": "./pt/maxValue.d.cts", "default": "./pt/maxValue.cjs" } }, "./pt/maxWords": { "import": { "types": "./pt/maxWords.d.mts", "default": "./pt/maxWords.mjs" }, "require": { "types": "./pt/maxWords.d.cts", "default": "./pt/maxWords.cjs" } }, "./pt/mimeType": { "import": { "types": "./pt/mimeType.d.mts", "default": "./pt/mimeType.mjs" }, "require": { "types": "./pt/mimeType.d.cts", "default": "./pt/mimeType.cjs" } }, "./pt/minBytes": { "import": { "types": "./pt/minBytes.d.mts", "default": "./pt/minBytes.mjs" }, "require": { "types": "./pt/minBytes.d.cts", "default": "./pt/minBytes.cjs" } }, "./pt/minEntries": { "import": { "types": "./pt/minEntries.d.mts", "default": "./pt/minEntries.mjs" }, "require": { "types": "./pt/minEntries.d.cts", "default": "./pt/minEntries.cjs" } }, "./pt/minGraphemes": { "import": { "types": "./pt/minGraphemes.d.mts", "default": "./pt/minGraphemes.mjs" }, "require": { "types": "./pt/minGraphemes.d.cts", "default": "./pt/minGraphemes.cjs" } }, "./pt/minLength": { "import": { "types": "./pt/minLength.d.mts", "default": "./pt/minLength.mjs" }, "require": { "types": "./pt/minLength.d.cts", "default": "./pt/minLength.cjs" } }, "./pt/minSize": { "import": { "types": "./pt/minSize.d.mts", "default": "./pt/minSize.mjs" }, "require": { "types": "./pt/minSize.d.cts", "default": "./pt/minSize.cjs" } }, "./pt/minValue": { "import": { "types": "./pt/minValue.d.mts", "default": "./pt/minValue.mjs" }, "require": { "types": "./pt/minValue.d.cts", "default": "./pt/minValue.cjs" } }, "./pt/minWords": { "import": { "types": "./pt/minWords.d.mts", "default": "./pt/minWords.mjs" }, "require": { "types": "./pt/minWords.d.cts", "default": "./pt/minWords.cjs" } }, "./pt/multipleOf": { "import": { "types": "./pt/multipleOf.d.mts", "default": "./pt/multipleOf.mjs" }, "require": { "types": "./pt/multipleOf.d.cts", "default": "./pt/multipleOf.cjs" } }, "./pt/nanoid": { "import": { "types": "./pt/nanoid.d.mts", "default": "./pt/nanoid.mjs" }, "require": { "types": "./pt/nanoid.d.cts", "default": "./pt/nanoid.cjs" } }, "./pt/nonEmpty": { "import": { "types": "./pt/nonEmpty.d.mts", "default": "./pt/nonEmpty.mjs" }, "require": { "types": "./pt/nonEmpty.d.cts", "default": "./pt/nonEmpty.cjs" } }, "./pt/notBytes": { "import": { "types": "./pt/notBytes.d.mts", "default": "./pt/notBytes.mjs" }, "require": { "types": "./pt/notBytes.d.cts", "default": "./pt/notBytes.cjs" } }, "./pt/notEntries": { "import": { "types": "./pt/notEntries.d.mts", "default": "./pt/notEntries.mjs" }, "require": { "types": "./pt/notEntries.d.cts", "default": "./pt/notEntries.cjs" } }, "./pt/notGraphemes": { "import": { "types": "./pt/notGraphemes.d.mts", "default": "./pt/notGraphemes.mjs" }, "require": { "types": "./pt/notGraphemes.d.cts", "default": "./pt/notGraphemes.cjs" } }, "./pt/notLength": { "import": { "types": "./pt/notLength.d.mts", "default": "./pt/notLength.mjs" }, "require": { "types": "./pt/notLength.d.cts", "default": "./pt/notLength.cjs" } }, "./pt/notSize": { "import": { "types": "./pt/notSize.d.mts", "default": "./pt/notSize.mjs" }, "require": { "types": "./pt/notSize.d.cts", "default": "./pt/notSize.cjs" } }, "./pt/notValue": { "import": { "types": "./pt/notValue.d.mts", "default": "./pt/notValue.mjs" }, "require": { "types": "./pt/notValue.d.cts", "default": "./pt/notValue.cjs" } }, "./pt/notValues": { "import": { "types": "./pt/notValues.d.mts", "default": "./pt/notValues.mjs" }, "require": { "types": "./pt/notValues.d.cts", "default": "./pt/notValues.cjs" } }, "./pt/notWords": { "import": { "types": "./pt/notWords.d.mts", "default": "./pt/notWords.mjs" }, "require": { "types": "./pt/notWords.d.cts", "default": "./pt/notWords.cjs" } }, "./pt/octal": { "import": { "types": "./pt/octal.d.mts", "default": "./pt/octal.mjs" }, "require": { "types": "./pt/octal.d.cts", "default": "./pt/octal.cjs" } }, "./pt/parseBoolean": { "import": { "types": "./pt/parseBoolean.d.mts", "default": "./pt/parseBoolean.mjs" }, "require": { "types": "./pt/parseBoolean.d.cts", "default": "./pt/parseBoolean.cjs" } }, "./pt/parseJson": { "import": { "types": "./pt/parseJson.d.mts", "default": "./pt/parseJson.mjs" }, "require": { "types": "./pt/parseJson.d.cts", "default": "./pt/parseJson.cjs" } }, "./pt/partialCheck": { "import": { "types": "./pt/partialCheck.d.mts", "default": "./pt/partialCheck.mjs" }, "require": { "types": "./pt/partialCheck.d.cts", "default": "./pt/partialCheck.cjs" } }, "./pt/rawCheck": { "import": { "types": "./pt/rawCheck.d.mts", "default": "./pt/rawCheck.mjs" }, "require": { "types": "./pt/rawCheck.d.cts", "default": "./pt/rawCheck.cjs" } }, "./pt/rawTransform": { "import": { "types": "./pt/rawTransform.d.mts", "default": "./pt/rawTransform.mjs" }, "require": { "types": "./pt/rawTransform.d.cts", "default": "./pt/rawTransform.cjs" } }, "./pt/regex": { "import": { "types": "./pt/regex.d.mts", "default": "./pt/regex.mjs" }, "require": { "types": "./pt/regex.d.cts", "default": "./pt/regex.cjs" } }, "./pt/rfcEmail": { "import": { "types": "./pt/rfcEmail.d.mts", "default": "./pt/rfcEmail.mjs" }, "require": { "types": "./pt/rfcEmail.d.cts", "default": "./pt/rfcEmail.cjs" } }, "./pt/safeInteger": { "import": { "types": "./pt/safeInteger.d.mts", "default": "./pt/safeInteger.mjs" }, "require": { "types": "./pt/safeInteger.d.cts", "default": "./pt/safeInteger.cjs" } }, "./pt/size": { "import": { "types": "./pt/size.d.mts", "default": "./pt/size.mjs" }, "require": { "types": "./pt/size.d.cts", "default": "./pt/size.cjs" } }, "./pt/slug": { "import": { "types": "./pt/slug.d.mts", "default": "./pt/slug.mjs" }, "require": { "types": "./pt/slug.d.cts", "default": "./pt/slug.cjs" } }, "./pt/someItem": { "import": { "types": "./pt/someItem.d.mts", "default": "./pt/someItem.mjs" }, "require": { "types": "./pt/someItem.d.cts", "default": "./pt/someItem.cjs" } }, "./pt/startsWith": { "import": { "types": "./pt/startsWith.d.mts", "default": "./pt/startsWith.mjs" }, "require": { "types": "./pt/startsWith.d.cts", "default": "./pt/startsWith.cjs" } }, "./pt/stringifyJson": { "import": { "types": "./pt/stringifyJson.d.mts", "default": "./pt/stringifyJson.mjs" }, "require": { "types": "./pt/stringifyJson.d.cts", "default": "./pt/stringifyJson.cjs" } }, "./pt/toBigint": { "import": { "types": "./pt/toBigint.d.mts", "default": "./pt/toBigint.mjs" }, "require": { "types": "./pt/toBigint.d.cts", "default": "./pt/toBigint.cjs" } }, "./pt/toDate": { "import": { "types": "./pt/toDate.d.mts", "default": "./pt/toDate.mjs" }, "require": { "types": "./pt/toDate.d.cts", "default": "./pt/toDate.cjs" } }, "./pt/toNumber": { "import": { "types": "./pt/toNumber.d.mts", "default": "./pt/toNumber.mjs" }, "require": { "types": "./pt/toNumber.d.cts", "default": "./pt/toNumber.cjs" } }, "./pt/toString": { "import": { "types": "./pt/toString.d.mts", "default": "./pt/toString.mjs" }, "require": { "types": "./pt/toString.d.cts", "default": "./pt/toString.cjs" } }, "./pt/ulid": { "import": { "types": "./pt/ulid.d.mts", "default": "./pt/ulid.mjs" }, "require": { "types": "./pt/ulid.d.cts", "default": "./pt/ulid.cjs" } }, "./pt/url": { "import": { "types": "./pt/url.d.mts", "default": "./pt/url.mjs" }, "require": { "types": "./pt/url.d.cts", "default": "./pt/url.cjs" } }, "./pt/uuid": { "import": { "types": "./pt/uuid.d.mts", "default": "./pt/uuid.mjs" }, "require": { "types": "./pt/uuid.d.cts", "default": "./pt/uuid.cjs" } }, "./pt/value": { "import": { "types": "./pt/value.d.mts", "default": "./pt/value.mjs" }, "require": { "types": "./pt/value.d.cts", "default": "./pt/value.cjs" } }, "./pt/values": { "import": { "types": "./pt/values.d.mts", "default": "./pt/values.mjs" }, "require": { "types": "./pt/values.d.cts", "default": "./pt/values.cjs" } }, "./pt/words": { "import": { "types": "./pt/words.d.mts", "default": "./pt/words.mjs" }, "require": { "types": "./pt/words.d.cts", "default": "./pt/words.cjs" } }, "./ro": { "import": { "types": "./ro/index.d.mts", "default": "./ro/index.mjs" }, "require": { "types": "./ro/index.d.cts", "default": "./ro/index.cjs" } }, "./ro/schema": { "import": { "types": "./ro/schema.d.mts", "default": "./ro/schema.mjs" }, "require": { "types": "./ro/schema.d.cts", "default": "./ro/schema.cjs" } }, "./ro/base64": { "import": { "types": "./ro/base64.d.mts", "default": "./ro/base64.mjs" }, "require": { "types": "./ro/base64.d.cts", "default": "./ro/base64.cjs" } }, "./ro/bic": { "import": { "types": "./ro/bic.d.mts", "default": "./ro/bic.mjs" }, "require": { "types": "./ro/bic.d.cts", "default": "./ro/bic.cjs" } }, "./ro/bytes": { "import": { "types": "./ro/bytes.d.mts", "default": "./ro/bytes.mjs" }, "require": { "types": "./ro/bytes.d.cts", "default": "./ro/bytes.cjs" } }, "./ro/check": { "import": { "types": "./ro/check.d.mts", "default": "./ro/check.mjs" }, "require": { "types": "./ro/check.d.cts", "default": "./ro/check.cjs" } }, "./ro/checkAsync": { "import": { "types": "./ro/checkAsync.d.mts", "default": "./ro/checkAsync.mjs" }, "require": { "types": "./ro/checkAsync.d.cts", "default": "./ro/checkAsync.cjs" } }, "./ro/checkItems": { "import": { "types": "./ro/checkItems.d.mts", "default": "./ro/checkItems.mjs" }, "require": { "types": "./ro/checkItems.d.cts", "default": "./ro/checkItems.cjs" } }, "./ro/checkItemsAsync": { "import": { "types": "./ro/checkItemsAsync.d.mts", "default": "./ro/checkItemsAsync.mjs" }, "require": { "types": "./ro/checkItemsAsync.d.cts", "default": "./ro/checkItemsAsync.cjs" } }, "./ro/creditCard": { "import": { "types": "./ro/creditCard.d.mts", "default": "./ro/creditCard.mjs" }, "require": { "types": "./ro/creditCard.d.cts", "default": "./ro/creditCard.cjs" } }, "./ro/cuid2": { "import": { "types": "./ro/cuid2.d.mts", "default": "./ro/cuid2.mjs" }, "require": { "types": "./ro/cuid2.d.cts", "default": "./ro/cuid2.cjs" } }, "./ro/decimal": { "import": { "types": "./ro/decimal.d.mts", "default": "./ro/decimal.mjs" }, "require": { "types": "./ro/decimal.d.cts", "default": "./ro/decimal.cjs" } }, "./ro/digits": { "import": { "types": "./ro/digits.d.mts", "default": "./ro/digits.mjs" }, "require": { "types": "./ro/digits.d.cts", "default": "./ro/digits.cjs" } }, "./ro/domain": { "import": { "types": "./ro/domain.d.mts", "default": "./ro/domain.mjs" }, "require": { "types": "./ro/domain.d.cts", "default": "./ro/domain.cjs" } }, "./ro/email": { "import": { "types": "./ro/email.d.mts", "default": "./ro/email.mjs" }, "require": { "types": "./ro/email.d.cts", "default": "./ro/email.cjs" } }, "./ro/emoji": { "import": { "types": "./ro/emoji.d.mts", "default": "./ro/emoji.mjs" }, "require": { "types": "./ro/emoji.d.cts", "default": "./ro/emoji.cjs" } }, "./ro/empty": { "import": { "types": "./ro/empty.d.mts", "default": "./ro/empty.mjs" }, "require": { "types": "./ro/empty.d.cts", "default": "./ro/empty.cjs" } }, "./ro/endsWith": { "import": { "types": "./ro/endsWith.d.mts", "default": "./ro/endsWith.mjs" }, "require": { "types": "./ro/endsWith.d.cts", "default": "./ro/endsWith.cjs" } }, "./ro/entries": { "import": { "types": "./ro/entries.d.mts", "default": "./ro/entries.mjs" }, "require": { "types": "./ro/entries.d.cts", "default": "./ro/entries.cjs" } }, "./ro/everyItem": { "import": { "types": "./ro/everyItem.d.mts", "default": "./ro/everyItem.mjs" }, "require": { "types": "./ro/everyItem.d.cts", "default": "./ro/everyItem.cjs" } }, "./ro/excludes": { "import": { "types": "./ro/excludes.d.mts", "default": "./ro/excludes.mjs" }, "require": { "types": "./ro/excludes.d.cts", "default": "./ro/excludes.cjs" } }, "./ro/finite": { "import": { "types": "./ro/finite.d.mts", "default": "./ro/finite.mjs" }, "require": { "types": "./ro/finite.d.cts", "default": "./ro/finite.cjs" } }, "./ro/graphemes": { "import": { "types": "./ro/graphemes.d.mts", "default": "./ro/graphemes.mjs" }, "require": { "types": "./ro/graphemes.d.cts", "default": "./ro/graphemes.cjs" } }, "./ro/gtValue": { "import": { "types": "./ro/gtValue.d.mts", "default": "./ro/gtValue.mjs" }, "require": { "types": "./ro/gtValue.d.cts", "default": "./ro/gtValue.cjs" } }, "./ro/guard": { "import": { "types": "./ro/guard.d.mts", "default": "./ro/guard.mjs" }, "require": { "types": "./ro/guard.d.cts", "default": "./ro/guard.cjs" } }, "./ro/hash": { "import": { "types": "./ro/hash.d.mts", "default": "./ro/hash.mjs" }, "require": { "types": "./ro/hash.d.cts", "default": "./ro/hash.cjs" } }, "./ro/hexadecimal": { "import": { "types": "./ro/hexadecimal.d.mts", "default": "./ro/hexadecimal.mjs" }, "require": { "types": "./ro/hexadecimal.d.cts", "default": "./ro/hexadecimal.cjs" } }, "./ro/hexColor": { "import": { "types": "./ro/hexColor.d.mts", "default": "./ro/hexColor.mjs" }, "require": { "types": "./ro/hexColor.d.cts", "default": "./ro/hexColor.cjs" } }, "./ro/imei": { "import": { "types": "./ro/imei.d.mts", "default": "./ro/imei.mjs" }, "require": { "types": "./ro/imei.d.cts", "default": "./ro/imei.cjs" } }, "./ro/includes": { "import": { "types": "./ro/includes.d.mts", "default": "./ro/includes.mjs" }, "require": { "types": "./ro/includes.d.cts", "default": "./ro/includes.cjs" } }, "./ro/integer": { "import": { "types": "./ro/integer.d.mts", "default": "./ro/integer.mjs" }, "require": { "types": "./ro/integer.d.cts", "default": "./ro/integer.cjs" } }, "./ro/ip": { "import": { "types": "./ro/ip.d.mts", "default": "./ro/ip.mjs" }, "require": { "types": "./ro/ip.d.cts", "default": "./ro/ip.cjs" } }, "./ro/ipv4": { "import": { "types": "./ro/ipv4.d.mts", "default": "./ro/ipv4.mjs" }, "require": { "types": "./ro/ipv4.d.cts", "default": "./ro/ipv4.cjs" } }, "./ro/ipv6": { "import": { "types": "./ro/ipv6.d.mts", "default": "./ro/ipv6.mjs" }, "require": { "types": "./ro/ipv6.d.cts", "default": "./ro/ipv6.cjs" } }, "./ro/isbn": { "import": { "types": "./ro/isbn.d.mts", "default": "./ro/isbn.mjs" }, "require": { "types": "./ro/isbn.d.cts", "default": "./ro/isbn.cjs" } }, "./ro/isoDate": { "import": { "types": "./ro/isoDate.d.mts", "default": "./ro/isoDate.mjs" }, "require": { "types": "./ro/isoDate.d.cts", "default": "./ro/isoDate.cjs" } }, "./ro/isoDateTime": { "import": { "types": "./ro/isoDateTime.d.mts", "default": "./ro/isoDateTime.mjs" }, "require": { "types": "./ro/isoDateTime.d.cts", "default": "./ro/isoDateTime.cjs" } }, "./ro/isoTime": { "import": { "types": "./ro/isoTime.d.mts", "default": "./ro/isoTime.mjs" }, "require": { "types": "./ro/isoTime.d.cts", "default": "./ro/isoTime.cjs" } }, "./ro/isoTimeSecond": { "import": { "types": "./ro/isoTimeSecond.d.mts", "default": "./ro/isoTimeSecond.mjs" }, "require": { "types": "./ro/isoTimeSecond.d.cts", "default": "./ro/isoTimeSecond.cjs" } }, "./ro/isoTimestamp": { "import": { "types": "./ro/isoTimestamp.d.mts", "default": "./ro/isoTimestamp.mjs" }, "require": { "types": "./ro/isoTimestamp.d.cts", "default": "./ro/isoTimestamp.cjs" } }, "./ro/isoWeek": { "import": { "types": "./ro/isoWeek.d.mts", "default": "./ro/isoWeek.mjs" }, "require": { "types": "./ro/isoWeek.d.cts", "default": "./ro/isoWeek.cjs" } }, "./ro/isrc": { "import": { "types": "./ro/isrc.d.mts", "default": "./ro/isrc.mjs" }, "require": { "types": "./ro/isrc.d.cts", "default": "./ro/isrc.cjs" } }, "./ro/jwsCompact": { "import": { "types": "./ro/jwsCompact.d.mts", "default": "./ro/jwsCompact.mjs" }, "require": { "types": "./ro/jwsCompact.d.cts", "default": "./ro/jwsCompact.cjs" } }, "./ro/length": { "import": { "types": "./ro/length.d.mts", "default": "./ro/length.mjs" }, "require": { "types": "./ro/length.d.cts", "default": "./ro/length.cjs" } }, "./ro/ltValue": { "import": { "types": "./ro/ltValue.d.mts", "default": "./ro/ltValue.mjs" }, "require": { "types": "./ro/ltValue.d.cts", "default": "./ro/ltValue.cjs" } }, "./ro/mac": { "import": { "types": "./ro/mac.d.mts", "default": "./ro/mac.mjs" }, "require": { "types": "./ro/mac.d.cts", "default": "./ro/mac.cjs" } }, "./ro/mac48": { "import": { "types": "./ro/mac48.d.mts", "default": "./ro/mac48.mjs" }, "require": { "types": "./ro/mac48.d.cts", "default": "./ro/mac48.cjs" } }, "./ro/mac64": { "import": { "types": "./ro/mac64.d.mts", "default": "./ro/mac64.mjs" }, "require": { "types": "./ro/mac64.d.cts", "default": "./ro/mac64.cjs" } }, "./ro/maxBytes": { "import": { "types": "./ro/maxBytes.d.mts", "default": "./ro/maxBytes.mjs" }, "require": { "types": "./ro/maxBytes.d.cts", "default": "./ro/maxBytes.cjs" } }, "./ro/maxEntries": { "import": { "types": "./ro/maxEntries.d.mts", "default": "./ro/maxEntries.mjs" }, "require": { "types": "./ro/maxEntries.d.cts", "default": "./ro/maxEntries.cjs" } }, "./ro/maxGraphemes": { "import": { "types": "./ro/maxGraphemes.d.mts", "default": "./ro/maxGraphemes.mjs" }, "require": { "types": "./ro/maxGraphemes.d.cts", "default": "./ro/maxGraphemes.cjs" } }, "./ro/maxLength": { "import": { "types": "./ro/maxLength.d.mts", "default": "./ro/maxLength.mjs" }, "require": { "types": "./ro/maxLength.d.cts", "default": "./ro/maxLength.cjs" } }, "./ro/maxSize": { "import": { "types": "./ro/maxSize.d.mts", "default": "./ro/maxSize.mjs" }, "require": { "types": "./ro/maxSize.d.cts", "default": "./ro/maxSize.cjs" } }, "./ro/maxValue": { "import": { "types": "./ro/maxValue.d.mts", "default": "./ro/maxValue.mjs" }, "require": { "types": "./ro/maxValue.d.cts", "default": "./ro/maxValue.cjs" } }, "./ro/maxWords": { "import": { "types": "./ro/maxWords.d.mts", "default": "./ro/maxWords.mjs" }, "require": { "types": "./ro/maxWords.d.cts", "default": "./ro/maxWords.cjs" } }, "./ro/mimeType": { "import": { "types": "./ro/mimeType.d.mts", "default": "./ro/mimeType.mjs" }, "require": { "types": "./ro/mimeType.d.cts", "default": "./ro/mimeType.cjs" } }, "./ro/minBytes": { "import": { "types": "./ro/minBytes.d.mts", "default": "./ro/minBytes.mjs" }, "require": { "types": "./ro/minBytes.d.cts", "default": "./ro/minBytes.cjs" } }, "./ro/minEntries": { "import": { "types": "./ro/minEntries.d.mts", "default": "./ro/minEntries.mjs" }, "require": { "types": "./ro/minEntries.d.cts", "default": "./ro/minEntries.cjs" } }, "./ro/minGraphemes": { "import": { "types": "./ro/minGraphemes.d.mts", "default": "./ro/minGraphemes.mjs" }, "require": { "types": "./ro/minGraphemes.d.cts", "default": "./ro/minGraphemes.cjs" } }, "./ro/minLength": { "import": { "types": "./ro/minLength.d.mts", "default": "./ro/minLength.mjs" }, "require": { "types": "./ro/minLength.d.cts", "default": "./ro/minLength.cjs" } }, "./ro/minSize": { "import": { "types": "./ro/minSize.d.mts", "default": "./ro/minSize.mjs" }, "require": { "types": "./ro/minSize.d.cts", "default": "./ro/minSize.cjs" } }, "./ro/minValue": { "import": { "types": "./ro/minValue.d.mts", "default": "./ro/minValue.mjs" }, "require": { "types": "./ro/minValue.d.cts", "default": "./ro/minValue.cjs" } }, "./ro/minWords": { "import": { "types": "./ro/minWords.d.mts", "default": "./ro/minWords.mjs" }, "require": { "types": "./ro/minWords.d.cts", "default": "./ro/minWords.cjs" } }, "./ro/multipleOf": { "import": { "types": "./ro/multipleOf.d.mts", "default": "./ro/multipleOf.mjs" }, "require": { "types": "./ro/multipleOf.d.cts", "default": "./ro/multipleOf.cjs" } }, "./ro/nanoid": { "import": { "types": "./ro/nanoid.d.mts", "default": "./ro/nanoid.mjs" }, "require": { "types": "./ro/nanoid.d.cts", "default": "./ro/nanoid.cjs" } }, "./ro/nonEmpty": { "import": { "types": "./ro/nonEmpty.d.mts", "default": "./ro/nonEmpty.mjs" }, "require": { "types": "./ro/nonEmpty.d.cts", "default": "./ro/nonEmpty.cjs" } }, "./ro/notBytes": { "import": { "types": "./ro/notBytes.d.mts", "default": "./ro/notBytes.mjs" }, "require": { "types": "./ro/notBytes.d.cts", "default": "./ro/notBytes.cjs" } }, "./ro/notEntries": { "import": { "types": "./ro/notEntries.d.mts", "default": "./ro/notEntries.mjs" }, "require": { "types": "./ro/notEntries.d.cts", "default": "./ro/notEntries.cjs" } }, "./ro/notGraphemes": { "import": { "types": "./ro/notGraphemes.d.mts", "default": "./ro/notGraphemes.mjs" }, "require": { "types": "./ro/notGraphemes.d.cts", "default": "./ro/notGraphemes.cjs" } }, "./ro/notLength": { "import": { "types": "./ro/notLength.d.mts", "default": "./ro/notLength.mjs" }, "require": { "types": "./ro/notLength.d.cts", "default": "./ro/notLength.cjs" } }, "./ro/notSize": { "import": { "types": "./ro/notSize.d.mts", "default": "./ro/notSize.mjs" }, "require": { "types": "./ro/notSize.d.cts", "default": "./ro/notSize.cjs" } }, "./ro/notValue": { "import": { "types": "./ro/notValue.d.mts", "default": "./ro/notValue.mjs" }, "require": { "types": "./ro/notValue.d.cts", "default": "./ro/notValue.cjs" } }, "./ro/notValues": { "import": { "types": "./ro/notValues.d.mts", "default": "./ro/notValues.mjs" }, "require": { "types": "./ro/notValues.d.cts", "default": "./ro/notValues.cjs" } }, "./ro/notWords": { "import": { "types": "./ro/notWords.d.mts", "default": "./ro/notWords.mjs" }, "require": { "types": "./ro/notWords.d.cts", "default": "./ro/notWords.cjs" } }, "./ro/octal": { "import": { "types": "./ro/octal.d.mts", "default": "./ro/octal.mjs" }, "require": { "types": "./ro/octal.d.cts", "default": "./ro/octal.cjs" } }, "./ro/parseBoolean": { "import": { "types": "./ro/parseBoolean.d.mts", "default": "./ro/parseBoolean.mjs" }, "require": { "types": "./ro/parseBoolean.d.cts", "default": "./ro/parseBoolean.cjs" } }, "./ro/parseJson": { "import": { "types": "./ro/parseJson.d.mts", "default": "./ro/parseJson.mjs" }, "require": { "types": "./ro/parseJson.d.cts", "default": "./ro/parseJson.cjs" } }, "./ro/partialCheck": { "import": { "types": "./ro/partialCheck.d.mts", "default": "./ro/partialCheck.mjs" }, "require": { "types": "./ro/partialCheck.d.cts", "default": "./ro/partialCheck.cjs" } }, "./ro/rawCheck": { "import": { "types": "./ro/rawCheck.d.mts", "default": "./ro/rawCheck.mjs" }, "require": { "types": "./ro/rawCheck.d.cts", "default": "./ro/rawCheck.cjs" } }, "./ro/rawTransform": { "import": { "types": "./ro/rawTransform.d.mts", "default": "./ro/rawTransform.mjs" }, "require": { "types": "./ro/rawTransform.d.cts", "default": "./ro/rawTransform.cjs" } }, "./ro/regex": { "import": { "types": "./ro/regex.d.mts", "default": "./ro/regex.mjs" }, "require": { "types": "./ro/regex.d.cts", "default": "./ro/regex.cjs" } }, "./ro/rfcEmail": { "import": { "types": "./ro/rfcEmail.d.mts", "default": "./ro/rfcEmail.mjs" }, "require": { "types": "./ro/rfcEmail.d.cts", "default": "./ro/rfcEmail.cjs" } }, "./ro/safeInteger": { "import": { "types": "./ro/safeInteger.d.mts", "default": "./ro/safeInteger.mjs" }, "require": { "types": "./ro/safeInteger.d.cts", "default": "./ro/safeInteger.cjs" } }, "./ro/size": { "import": { "types": "./ro/size.d.mts", "default": "./ro/size.mjs" }, "require": { "types": "./ro/size.d.cts", "default": "./ro/size.cjs" } }, "./ro/slug": { "import": { "types": "./ro/slug.d.mts", "default": "./ro/slug.mjs" }, "require": { "types": "./ro/slug.d.cts", "default": "./ro/slug.cjs" } }, "./ro/someItem": { "import": { "types": "./ro/someItem.d.mts", "default": "./ro/someItem.mjs" }, "require": { "types": "./ro/someItem.d.cts", "default": "./ro/someItem.cjs" } }, "./ro/startsWith": { "import": { "types": "./ro/startsWith.d.mts", "default": "./ro/startsWith.mjs" }, "require": { "types": "./ro/startsWith.d.cts", "default": "./ro/startsWith.cjs" } }, "./ro/stringifyJson": { "import": { "types": "./ro/stringifyJson.d.mts", "default": "./ro/stringifyJson.mjs" }, "require": { "types": "./ro/stringifyJson.d.cts", "default": "./ro/stringifyJson.cjs" } }, "./ro/toBigint": { "import": { "types": "./ro/toBigint.d.mts", "default": "./ro/toBigint.mjs" }, "require": { "types": "./ro/toBigint.d.cts", "default": "./ro/toBigint.cjs" } }, "./ro/toDate": { "import": { "types": "./ro/toDate.d.mts", "default": "./ro/toDate.mjs" }, "require": { "types": "./ro/toDate.d.cts", "default": "./ro/toDate.cjs" } }, "./ro/toNumber": { "import": { "types": "./ro/toNumber.d.mts", "default": "./ro/toNumber.mjs" }, "require": { "types": "./ro/toNumber.d.cts", "default": "./ro/toNumber.cjs" } }, "./ro/toString": { "import": { "types": "./ro/toString.d.mts", "default": "./ro/toString.mjs" }, "require": { "types": "./ro/toString.d.cts", "default": "./ro/toString.cjs" } }, "./ro/ulid": { "import": { "types": "./ro/ulid.d.mts", "default": "./ro/ulid.mjs" }, "require": { "types": "./ro/ulid.d.cts", "default": "./ro/ulid.cjs" } }, "./ro/url": { "import": { "types": "./ro/url.d.mts", "default": "./ro/url.mjs" }, "require": { "types": "./ro/url.d.cts", "default": "./ro/url.cjs" } }, "./ro/uuid": { "import": { "types": "./ro/uuid.d.mts", "default": "./ro/uuid.mjs" }, "require": { "types": "./ro/uuid.d.cts", "default": "./ro/uuid.cjs" } }, "./ro/value": { "import": { "types": "./ro/value.d.mts", "default": "./ro/value.mjs" }, "require": { "types": "./ro/value.d.cts", "default": "./ro/value.cjs" } }, "./ro/values": { "import": { "types": "./ro/values.d.mts", "default": "./ro/values.mjs" }, "require": { "types": "./ro/values.d.cts", "default": "./ro/values.cjs" } }, "./ro/words": { "import": { "types": "./ro/words.d.mts", "default": "./ro/words.mjs" }, "require": { "types": "./ro/words.d.cts", "default": "./ro/words.cjs" } }, "./ru": { "import": { "types": "./ru/index.d.mts", "default": "./ru/index.mjs" }, "require": { "types": "./ru/index.d.cts", "default": "./ru/index.cjs" } }, "./ru/schema": { "import": { "types": "./ru/schema.d.mts", "default": "./ru/schema.mjs" }, "require": { "types": "./ru/schema.d.cts", "default": "./ru/schema.cjs" } }, "./ru/base64": { "import": { "types": "./ru/base64.d.mts", "default": "./ru/base64.mjs" }, "require": { "types": "./ru/base64.d.cts", "default": "./ru/base64.cjs" } }, "./ru/bic": { "import": { "types": "./ru/bic.d.mts", "default": "./ru/bic.mjs" }, "require": { "types": "./ru/bic.d.cts", "default": "./ru/bic.cjs" } }, "./ru/bytes": { "import": { "types": "./ru/bytes.d.mts", "default": "./ru/bytes.mjs" }, "require": { "types": "./ru/bytes.d.cts", "default": "./ru/bytes.cjs" } }, "./ru/check": { "import": { "types": "./ru/check.d.mts", "default": "./ru/check.mjs" }, "require": { "types": "./ru/check.d.cts", "default": "./ru/check.cjs" } }, "./ru/checkAsync": { "import": { "types": "./ru/checkAsync.d.mts", "default": "./ru/checkAsync.mjs" }, "require": { "types": "./ru/checkAsync.d.cts", "default": "./ru/checkAsync.cjs" } }, "./ru/checkItems": { "import": { "types": "./ru/checkItems.d.mts", "default": "./ru/checkItems.mjs" }, "require": { "types": "./ru/checkItems.d.cts", "default": "./ru/checkItems.cjs" } }, "./ru/checkItemsAsync": { "import": { "types": "./ru/checkItemsAsync.d.mts", "default": "./ru/checkItemsAsync.mjs" }, "require": { "types": "./ru/checkItemsAsync.d.cts", "default": "./ru/checkItemsAsync.cjs" } }, "./ru/creditCard": { "import": { "types": "./ru/creditCard.d.mts", "default": "./ru/creditCard.mjs" }, "require": { "types": "./ru/creditCard.d.cts", "default": "./ru/creditCard.cjs" } }, "./ru/cuid2": { "import": { "types": "./ru/cuid2.d.mts", "default": "./ru/cuid2.mjs" }, "require": { "types": "./ru/cuid2.d.cts", "default": "./ru/cuid2.cjs" } }, "./ru/decimal": { "import": { "types": "./ru/decimal.d.mts", "default": "./ru/decimal.mjs" }, "require": { "types": "./ru/decimal.d.cts", "default": "./ru/decimal.cjs" } }, "./ru/digits": { "import": { "types": "./ru/digits.d.mts", "default": "./ru/digits.mjs" }, "require": { "types": "./ru/digits.d.cts", "default": "./ru/digits.cjs" } }, "./ru/domain": { "import": { "types": "./ru/domain.d.mts", "default": "./ru/domain.mjs" }, "require": { "types": "./ru/domain.d.cts", "default": "./ru/domain.cjs" } }, "./ru/email": { "import": { "types": "./ru/email.d.mts", "default": "./ru/email.mjs" }, "require": { "types": "./ru/email.d.cts", "default": "./ru/email.cjs" } }, "./ru/emoji": { "import": { "types": "./ru/emoji.d.mts", "default": "./ru/emoji.mjs" }, "require": { "types": "./ru/emoji.d.cts", "default": "./ru/emoji.cjs" } }, "./ru/empty": { "import": { "types": "./ru/empty.d.mts", "default": "./ru/empty.mjs" }, "require": { "types": "./ru/empty.d.cts", "default": "./ru/empty.cjs" } }, "./ru/endsWith": { "import": { "types": "./ru/endsWith.d.mts", "default": "./ru/endsWith.mjs" }, "require": { "types": "./ru/endsWith.d.cts", "default": "./ru/endsWith.cjs" } }, "./ru/entries": { "import": { "types": "./ru/entries.d.mts", "default": "./ru/entries.mjs" }, "require": { "types": "./ru/entries.d.cts", "default": "./ru/entries.cjs" } }, "./ru/everyItem": { "import": { "types": "./ru/everyItem.d.mts", "default": "./ru/everyItem.mjs" }, "require": { "types": "./ru/everyItem.d.cts", "default": "./ru/everyItem.cjs" } }, "./ru/excludes": { "import": { "types": "./ru/excludes.d.mts", "default": "./ru/excludes.mjs" }, "require": { "types": "./ru/excludes.d.cts", "default": "./ru/excludes.cjs" } }, "./ru/finite": { "import": { "types": "./ru/finite.d.mts", "default": "./ru/finite.mjs" }, "require": { "types": "./ru/finite.d.cts", "default": "./ru/finite.cjs" } }, "./ru/graphemes": { "import": { "types": "./ru/graphemes.d.mts", "default": "./ru/graphemes.mjs" }, "require": { "types": "./ru/graphemes.d.cts", "default": "./ru/graphemes.cjs" } }, "./ru/gtValue": { "import": { "types": "./ru/gtValue.d.mts", "default": "./ru/gtValue.mjs" }, "require": { "types": "./ru/gtValue.d.cts", "default": "./ru/gtValue.cjs" } }, "./ru/guard": { "import": { "types": "./ru/guard.d.mts", "default": "./ru/guard.mjs" }, "require": { "types": "./ru/guard.d.cts", "default": "./ru/guard.cjs" } }, "./ru/hash": { "import": { "types": "./ru/hash.d.mts", "default": "./ru/hash.mjs" }, "require": { "types": "./ru/hash.d.cts", "default": "./ru/hash.cjs" } }, "./ru/hexadecimal": { "import": { "types": "./ru/hexadecimal.d.mts", "default": "./ru/hexadecimal.mjs" }, "require": { "types": "./ru/hexadecimal.d.cts", "default": "./ru/hexadecimal.cjs" } }, "./ru/hexColor": { "import": { "types": "./ru/hexColor.d.mts", "default": "./ru/hexColor.mjs" }, "require": { "types": "./ru/hexColor.d.cts", "default": "./ru/hexColor.cjs" } }, "./ru/imei": { "import": { "types": "./ru/imei.d.mts", "default": "./ru/imei.mjs" }, "require": { "types": "./ru/imei.d.cts", "default": "./ru/imei.cjs" } }, "./ru/includes": { "import": { "types": "./ru/includes.d.mts", "default": "./ru/includes.mjs" }, "require": { "types": "./ru/includes.d.cts", "default": "./ru/includes.cjs" } }, "./ru/integer": { "import": { "types": "./ru/integer.d.mts", "default": "./ru/integer.mjs" }, "require": { "types": "./ru/integer.d.cts", "default": "./ru/integer.cjs" } }, "./ru/ip": { "import": { "types": "./ru/ip.d.mts", "default": "./ru/ip.mjs" }, "require": { "types": "./ru/ip.d.cts", "default": "./ru/ip.cjs" } }, "./ru/ipv4": { "import": { "types": "./ru/ipv4.d.mts", "default": "./ru/ipv4.mjs" }, "require": { "types": "./ru/ipv4.d.cts", "default": "./ru/ipv4.cjs" } }, "./ru/ipv6": { "import": { "types": "./ru/ipv6.d.mts", "default": "./ru/ipv6.mjs" }, "require": { "types": "./ru/ipv6.d.cts", "default": "./ru/ipv6.cjs" } }, "./ru/isbn": { "import": { "types": "./ru/isbn.d.mts", "default": "./ru/isbn.mjs" }, "require": { "types": "./ru/isbn.d.cts", "default": "./ru/isbn.cjs" } }, "./ru/isoDate": { "import": { "types": "./ru/isoDate.d.mts", "default": "./ru/isoDate.mjs" }, "require": { "types": "./ru/isoDate.d.cts", "default": "./ru/isoDate.cjs" } }, "./ru/isoDateTime": { "import": { "types": "./ru/isoDateTime.d.mts", "default": "./ru/isoDateTime.mjs" }, "require": { "types": "./ru/isoDateTime.d.cts", "default": "./ru/isoDateTime.cjs" } }, "./ru/isoTime": { "import": { "types": "./ru/isoTime.d.mts", "default": "./ru/isoTime.mjs" }, "require": { "types": "./ru/isoTime.d.cts", "default": "./ru/isoTime.cjs" } }, "./ru/isoTimeSecond": { "import": { "types": "./ru/isoTimeSecond.d.mts", "default": "./ru/isoTimeSecond.mjs" }, "require": { "types": "./ru/isoTimeSecond.d.cts", "default": "./ru/isoTimeSecond.cjs" } }, "./ru/isoTimestamp": { "import": { "types": "./ru/isoTimestamp.d.mts", "default": "./ru/isoTimestamp.mjs" }, "require": { "types": "./ru/isoTimestamp.d.cts", "default": "./ru/isoTimestamp.cjs" } }, "./ru/isoWeek": { "import": { "types": "./ru/isoWeek.d.mts", "default": "./ru/isoWeek.mjs" }, "require": { "types": "./ru/isoWeek.d.cts", "default": "./ru/isoWeek.cjs" } }, "./ru/isrc": { "import": { "types": "./ru/isrc.d.mts", "default": "./ru/isrc.mjs" }, "require": { "types": "./ru/isrc.d.cts", "default": "./ru/isrc.cjs" } }, "./ru/jwsCompact": { "import": { "types": "./ru/jwsCompact.d.mts", "default": "./ru/jwsCompact.mjs" }, "require": { "types": "./ru/jwsCompact.d.cts", "default": "./ru/jwsCompact.cjs" } }, "./ru/length": { "import": { "types": "./ru/length.d.mts", "default": "./ru/length.mjs" }, "require": { "types": "./ru/length.d.cts", "default": "./ru/length.cjs" } }, "./ru/ltValue": { "import": { "types": "./ru/ltValue.d.mts", "default": "./ru/ltValue.mjs" }, "require": { "types": "./ru/ltValue.d.cts", "default": "./ru/ltValue.cjs" } }, "./ru/mac": { "import": { "types": "./ru/mac.d.mts", "default": "./ru/mac.mjs" }, "require": { "types": "./ru/mac.d.cts", "default": "./ru/mac.cjs" } }, "./ru/mac48": { "import": { "types": "./ru/mac48.d.mts", "default": "./ru/mac48.mjs" }, "require": { "types": "./ru/mac48.d.cts", "default": "./ru/mac48.cjs" } }, "./ru/mac64": { "import": { "types": "./ru/mac64.d.mts", "default": "./ru/mac64.mjs" }, "require": { "types": "./ru/mac64.d.cts", "default": "./ru/mac64.cjs" } }, "./ru/maxBytes": { "import": { "types": "./ru/maxBytes.d.mts", "default": "./ru/maxBytes.mjs" }, "require": { "types": "./ru/maxBytes.d.cts", "default": "./ru/maxBytes.cjs" } }, "./ru/maxEntries": { "import": { "types": "./ru/maxEntries.d.mts", "default": "./ru/maxEntries.mjs" }, "require": { "types": "./ru/maxEntries.d.cts", "default": "./ru/maxEntries.cjs" } }, "./ru/maxGraphemes": { "import": { "types": "./ru/maxGraphemes.d.mts", "default": "./ru/maxGraphemes.mjs" }, "require": { "types": "./ru/maxGraphemes.d.cts", "default": "./ru/maxGraphemes.cjs" } }, "./ru/maxLength": { "import": { "types": "./ru/maxLength.d.mts", "default": "./ru/maxLength.mjs" }, "require": { "types": "./ru/maxLength.d.cts", "default": "./ru/maxLength.cjs" } }, "./ru/maxSize": { "import": { "types": "./ru/maxSize.d.mts", "default": "./ru/maxSize.mjs" }, "require": { "types": "./ru/maxSize.d.cts", "default": "./ru/maxSize.cjs" } }, "./ru/maxValue": { "import": { "types": "./ru/maxValue.d.mts", "default": "./ru/maxValue.mjs" }, "require": { "types": "./ru/maxValue.d.cts", "default": "./ru/maxValue.cjs" } }, "./ru/maxWords": { "import": { "types": "./ru/maxWords.d.mts", "default": "./ru/maxWords.mjs" }, "require": { "types": "./ru/maxWords.d.cts", "default": "./ru/maxWords.cjs" } }, "./ru/mimeType": { "import": { "types": "./ru/mimeType.d.mts", "default": "./ru/mimeType.mjs" }, "require": { "types": "./ru/mimeType.d.cts", "default": "./ru/mimeType.cjs" } }, "./ru/minBytes": { "import": { "types": "./ru/minBytes.d.mts", "default": "./ru/minBytes.mjs" }, "require": { "types": "./ru/minBytes.d.cts", "default": "./ru/minBytes.cjs" } }, "./ru/minEntries": { "import": { "types": "./ru/minEntries.d.mts", "default": "./ru/minEntries.mjs" }, "require": { "types": "./ru/minEntries.d.cts", "default": "./ru/minEntries.cjs" } }, "./ru/minGraphemes": { "import": { "types": "./ru/minGraphemes.d.mts", "default": "./ru/minGraphemes.mjs" }, "require": { "types": "./ru/minGraphemes.d.cts", "default": "./ru/minGraphemes.cjs" } }, "./ru/minLength": { "import": { "types": "./ru/minLength.d.mts", "default": "./ru/minLength.mjs" }, "require": { "types": "./ru/minLength.d.cts", "default": "./ru/minLength.cjs" } }, "./ru/minSize": { "import": { "types": "./ru/minSize.d.mts", "default": "./ru/minSize.mjs" }, "require": { "types": "./ru/minSize.d.cts", "default": "./ru/minSize.cjs" } }, "./ru/minValue": { "import": { "types": "./ru/minValue.d.mts", "default": "./ru/minValue.mjs" }, "require": { "types": "./ru/minValue.d.cts", "default": "./ru/minValue.cjs" } }, "./ru/minWords": { "import": { "types": "./ru/minWords.d.mts", "default": "./ru/minWords.mjs" }, "require": { "types": "./ru/minWords.d.cts", "default": "./ru/minWords.cjs" } }, "./ru/multipleOf": { "import": { "types": "./ru/multipleOf.d.mts", "default": "./ru/multipleOf.mjs" }, "require": { "types": "./ru/multipleOf.d.cts", "default": "./ru/multipleOf.cjs" } }, "./ru/nanoid": { "import": { "types": "./ru/nanoid.d.mts", "default": "./ru/nanoid.mjs" }, "require": { "types": "./ru/nanoid.d.cts", "default": "./ru/nanoid.cjs" } }, "./ru/nonEmpty": { "import": { "types": "./ru/nonEmpty.d.mts", "default": "./ru/nonEmpty.mjs" }, "require": { "types": "./ru/nonEmpty.d.cts", "default": "./ru/nonEmpty.cjs" } }, "./ru/notBytes": { "import": { "types": "./ru/notBytes.d.mts", "default": "./ru/notBytes.mjs" }, "require": { "types": "./ru/notBytes.d.cts", "default": "./ru/notBytes.cjs" } }, "./ru/notEntries": { "import": { "types": "./ru/notEntries.d.mts", "default": "./ru/notEntries.mjs" }, "require": { "types": "./ru/notEntries.d.cts", "default": "./ru/notEntries.cjs" } }, "./ru/notGraphemes": { "import": { "types": "./ru/notGraphemes.d.mts", "default": "./ru/notGraphemes.mjs" }, "require": { "types": "./ru/notGraphemes.d.cts", "default": "./ru/notGraphemes.cjs" } }, "./ru/notLength": { "import": { "types": "./ru/notLength.d.mts", "default": "./ru/notLength.mjs" }, "require": { "types": "./ru/notLength.d.cts", "default": "./ru/notLength.cjs" } }, "./ru/notSize": { "import": { "types": "./ru/notSize.d.mts", "default": "./ru/notSize.mjs" }, "require": { "types": "./ru/notSize.d.cts", "default": "./ru/notSize.cjs" } }, "./ru/notValue": { "import": { "types": "./ru/notValue.d.mts", "default": "./ru/notValue.mjs" }, "require": { "types": "./ru/notValue.d.cts", "default": "./ru/notValue.cjs" } }, "./ru/notValues": { "import": { "types": "./ru/notValues.d.mts", "default": "./ru/notValues.mjs" }, "require": { "types": "./ru/notValues.d.cts", "default": "./ru/notValues.cjs" } }, "./ru/notWords": { "import": { "types": "./ru/notWords.d.mts", "default": "./ru/notWords.mjs" }, "require": { "types": "./ru/notWords.d.cts", "default": "./ru/notWords.cjs" } }, "./ru/octal": { "import": { "types": "./ru/octal.d.mts", "default": "./ru/octal.mjs" }, "require": { "types": "./ru/octal.d.cts", "default": "./ru/octal.cjs" } }, "./ru/parseBoolean": { "import": { "types": "./ru/parseBoolean.d.mts", "default": "./ru/parseBoolean.mjs" }, "require": { "types": "./ru/parseBoolean.d.cts", "default": "./ru/parseBoolean.cjs" } }, "./ru/parseJson": { "import": { "types": "./ru/parseJson.d.mts", "default": "./ru/parseJson.mjs" }, "require": { "types": "./ru/parseJson.d.cts", "default": "./ru/parseJson.cjs" } }, "./ru/partialCheck": { "import": { "types": "./ru/partialCheck.d.mts", "default": "./ru/partialCheck.mjs" }, "require": { "types": "./ru/partialCheck.d.cts", "default": "./ru/partialCheck.cjs" } }, "./ru/rawCheck": { "import": { "types": "./ru/rawCheck.d.mts", "default": "./ru/rawCheck.mjs" }, "require": { "types": "./ru/rawCheck.d.cts", "default": "./ru/rawCheck.cjs" } }, "./ru/rawTransform": { "import": { "types": "./ru/rawTransform.d.mts", "default": "./ru/rawTransform.mjs" }, "require": { "types": "./ru/rawTransform.d.cts", "default": "./ru/rawTransform.cjs" } }, "./ru/regex": { "import": { "types": "./ru/regex.d.mts", "default": "./ru/regex.mjs" }, "require": { "types": "./ru/regex.d.cts", "default": "./ru/regex.cjs" } }, "./ru/rfcEmail": { "import": { "types": "./ru/rfcEmail.d.mts", "default": "./ru/rfcEmail.mjs" }, "require": { "types": "./ru/rfcEmail.d.cts", "default": "./ru/rfcEmail.cjs" } }, "./ru/safeInteger": { "import": { "types": "./ru/safeInteger.d.mts", "default": "./ru/safeInteger.mjs" }, "require": { "types": "./ru/safeInteger.d.cts", "default": "./ru/safeInteger.cjs" } }, "./ru/size": { "import": { "types": "./ru/size.d.mts", "default": "./ru/size.mjs" }, "require": { "types": "./ru/size.d.cts", "default": "./ru/size.cjs" } }, "./ru/slug": { "import": { "types": "./ru/slug.d.mts", "default": "./ru/slug.mjs" }, "require": { "types": "./ru/slug.d.cts", "default": "./ru/slug.cjs" } }, "./ru/someItem": { "import": { "types": "./ru/someItem.d.mts", "default": "./ru/someItem.mjs" }, "require": { "types": "./ru/someItem.d.cts", "default": "./ru/someItem.cjs" } }, "./ru/startsWith": { "import": { "types": "./ru/startsWith.d.mts", "default": "./ru/startsWith.mjs" }, "require": { "types": "./ru/startsWith.d.cts", "default": "./ru/startsWith.cjs" } }, "./ru/stringifyJson": { "import": { "types": "./ru/stringifyJson.d.mts", "default": "./ru/stringifyJson.mjs" }, "require": { "types": "./ru/stringifyJson.d.cts", "default": "./ru/stringifyJson.cjs" } }, "./ru/toBigint": { "import": { "types": "./ru/toBigint.d.mts", "default": "./ru/toBigint.mjs" }, "require": { "types": "./ru/toBigint.d.cts", "default": "./ru/toBigint.cjs" } }, "./ru/toDate": { "import": { "types": "./ru/toDate.d.mts", "default": "./ru/toDate.mjs" }, "require": { "types": "./ru/toDate.d.cts", "default": "./ru/toDate.cjs" } }, "./ru/toNumber": { "import": { "types": "./ru/toNumber.d.mts", "default": "./ru/toNumber.mjs" }, "require": { "types": "./ru/toNumber.d.cts", "default": "./ru/toNumber.cjs" } }, "./ru/toString": { "import": { "types": "./ru/toString.d.mts", "default": "./ru/toString.mjs" }, "require": { "types": "./ru/toString.d.cts", "default": "./ru/toString.cjs" } }, "./ru/ulid": { "import": { "types": "./ru/ulid.d.mts", "default": "./ru/ulid.mjs" }, "require": { "types": "./ru/ulid.d.cts", "default": "./ru/ulid.cjs" } }, "./ru/url": { "import": { "types": "./ru/url.d.mts", "default": "./ru/url.mjs" }, "require": { "types": "./ru/url.d.cts", "default": "./ru/url.cjs" } }, "./ru/uuid": { "import": { "types": "./ru/uuid.d.mts", "default": "./ru/uuid.mjs" }, "require": { "types": "./ru/uuid.d.cts", "default": "./ru/uuid.cjs" } }, "./ru/value": { "import": { "types": "./ru/value.d.mts", "default": "./ru/value.mjs" }, "require": { "types": "./ru/value.d.cts", "default": "./ru/value.cjs" } }, "./ru/values": { "import": { "types": "./ru/values.d.mts", "default": "./ru/values.mjs" }, "require": { "types": "./ru/values.d.cts", "default": "./ru/values.cjs" } }, "./ru/words": { "import": { "types": "./ru/words.d.mts", "default": "./ru/words.mjs" }, "require": { "types": "./ru/words.d.cts", "default": "./ru/words.cjs" } }, "./sk": { "import": { "types": "./sk/index.d.mts", "default": "./sk/index.mjs" }, "require": { "types": "./sk/index.d.cts", "default": "./sk/index.cjs" } }, "./sk/schema": { "import": { "types": "./sk/schema.d.mts", "default": "./sk/schema.mjs" }, "require": { "types": "./sk/schema.d.cts", "default": "./sk/schema.cjs" } }, "./sk/base64": { "import": { "types": "./sk/base64.d.mts", "default": "./sk/base64.mjs" }, "require": { "types": "./sk/base64.d.cts", "default": "./sk/base64.cjs" } }, "./sk/bic": { "import": { "types": "./sk/bic.d.mts", "default": "./sk/bic.mjs" }, "require": { "types": "./sk/bic.d.cts", "default": "./sk/bic.cjs" } }, "./sk/bytes": { "import": { "types": "./sk/bytes.d.mts", "default": "./sk/bytes.mjs" }, "require": { "types": "./sk/bytes.d.cts", "default": "./sk/bytes.cjs" } }, "./sk/check": { "import": { "types": "./sk/check.d.mts", "default": "./sk/check.mjs" }, "require": { "types": "./sk/check.d.cts", "default": "./sk/check.cjs" } }, "./sk/checkAsync": { "import": { "types": "./sk/checkAsync.d.mts", "default": "./sk/checkAsync.mjs" }, "require": { "types": "./sk/checkAsync.d.cts", "default": "./sk/checkAsync.cjs" } }, "./sk/checkItems": { "import": { "types": "./sk/checkItems.d.mts", "default": "./sk/checkItems.mjs" }, "require": { "types": "./sk/checkItems.d.cts", "default": "./sk/checkItems.cjs" } }, "./sk/checkItemsAsync": { "import": { "types": "./sk/checkItemsAsync.d.mts", "default": "./sk/checkItemsAsync.mjs" }, "require": { "types": "./sk/checkItemsAsync.d.cts", "default": "./sk/checkItemsAsync.cjs" } }, "./sk/creditCard": { "import": { "types": "./sk/creditCard.d.mts", "default": "./sk/creditCard.mjs" }, "require": { "types": "./sk/creditCard.d.cts", "default": "./sk/creditCard.cjs" } }, "./sk/cuid2": { "import": { "types": "./sk/cuid2.d.mts", "default": "./sk/cuid2.mjs" }, "require": { "types": "./sk/cuid2.d.cts", "default": "./sk/cuid2.cjs" } }, "./sk/decimal": { "import": { "types": "./sk/decimal.d.mts", "default": "./sk/decimal.mjs" }, "require": { "types": "./sk/decimal.d.cts", "default": "./sk/decimal.cjs" } }, "./sk/digits": { "import": { "types": "./sk/digits.d.mts", "default": "./sk/digits.mjs" }, "require": { "types": "./sk/digits.d.cts", "default": "./sk/digits.cjs" } }, "./sk/domain": { "import": { "types": "./sk/domain.d.mts", "default": "./sk/domain.mjs" }, "require": { "types": "./sk/domain.d.cts", "default": "./sk/domain.cjs" } }, "./sk/email": { "import": { "types": "./sk/email.d.mts", "default": "./sk/email.mjs" }, "require": { "types": "./sk/email.d.cts", "default": "./sk/email.cjs" } }, "./sk/emoji": { "import": { "types": "./sk/emoji.d.mts", "default": "./sk/emoji.mjs" }, "require": { "types": "./sk/emoji.d.cts", "default": "./sk/emoji.cjs" } }, "./sk/empty": { "import": { "types": "./sk/empty.d.mts", "default": "./sk/empty.mjs" }, "require": { "types": "./sk/empty.d.cts", "default": "./sk/empty.cjs" } }, "./sk/endsWith": { "import": { "types": "./sk/endsWith.d.mts", "default": "./sk/endsWith.mjs" }, "require": { "types": "./sk/endsWith.d.cts", "default": "./sk/endsWith.cjs" } }, "./sk/entries": { "import": { "types": "./sk/entries.d.mts", "default": "./sk/entries.mjs" }, "require": { "types": "./sk/entries.d.cts", "default": "./sk/entries.cjs" } }, "./sk/everyItem": { "import": { "types": "./sk/everyItem.d.mts", "default": "./sk/everyItem.mjs" }, "require": { "types": "./sk/everyItem.d.cts", "default": "./sk/everyItem.cjs" } }, "./sk/excludes": { "import": { "types": "./sk/excludes.d.mts", "default": "./sk/excludes.mjs" }, "require": { "types": "./sk/excludes.d.cts", "default": "./sk/excludes.cjs" } }, "./sk/finite": { "import": { "types": "./sk/finite.d.mts", "default": "./sk/finite.mjs" }, "require": { "types": "./sk/finite.d.cts", "default": "./sk/finite.cjs" } }, "./sk/graphemes": { "import": { "types": "./sk/graphemes.d.mts", "default": "./sk/graphemes.mjs" }, "require": { "types": "./sk/graphemes.d.cts", "default": "./sk/graphemes.cjs" } }, "./sk/gtValue": { "import": { "types": "./sk/gtValue.d.mts", "default": "./sk/gtValue.mjs" }, "require": { "types": "./sk/gtValue.d.cts", "default": "./sk/gtValue.cjs" } }, "./sk/guard": { "import": { "types": "./sk/guard.d.mts", "default": "./sk/guard.mjs" }, "require": { "types": "./sk/guard.d.cts", "default": "./sk/guard.cjs" } }, "./sk/hash": { "import": { "types": "./sk/hash.d.mts", "default": "./sk/hash.mjs" }, "require": { "types": "./sk/hash.d.cts", "default": "./sk/hash.cjs" } }, "./sk/hexColor": { "import": { "types": "./sk/hexColor.d.mts", "default": "./sk/hexColor.mjs" }, "require": { "types": "./sk/hexColor.d.cts", "default": "./sk/hexColor.cjs" } }, "./sk/hexadecimal": { "import": { "types": "./sk/hexadecimal.d.mts", "default": "./sk/hexadecimal.mjs" }, "require": { "types": "./sk/hexadecimal.d.cts", "default": "./sk/hexadecimal.cjs" } }, "./sk/imei": { "import": { "types": "./sk/imei.d.mts", "default": "./sk/imei.mjs" }, "require": { "types": "./sk/imei.d.cts", "default": "./sk/imei.cjs" } }, "./sk/includes": { "import": { "types": "./sk/includes.d.mts", "default": "./sk/includes.mjs" }, "require": { "types": "./sk/includes.d.cts", "default": "./sk/includes.cjs" } }, "./sk/integer": { "import": { "types": "./sk/integer.d.mts", "default": "./sk/integer.mjs" }, "require": { "types": "./sk/integer.d.cts", "default": "./sk/integer.cjs" } }, "./sk/ip": { "import": { "types": "./sk/ip.d.mts", "default": "./sk/ip.mjs" }, "require": { "types": "./sk/ip.d.cts", "default": "./sk/ip.cjs" } }, "./sk/ipv4": { "import": { "types": "./sk/ipv4.d.mts", "default": "./sk/ipv4.mjs" }, "require": { "types": "./sk/ipv4.d.cts", "default": "./sk/ipv4.cjs" } }, "./sk/ipv6": { "import": { "types": "./sk/ipv6.d.mts", "default": "./sk/ipv6.mjs" }, "require": { "types": "./sk/ipv6.d.cts", "default": "./sk/ipv6.cjs" } }, "./sk/isbn": { "import": { "types": "./sk/isbn.d.mts", "default": "./sk/isbn.mjs" }, "require": { "types": "./sk/isbn.d.cts", "default": "./sk/isbn.cjs" } }, "./sk/isoDate": { "import": { "types": "./sk/isoDate.d.mts", "default": "./sk/isoDate.mjs" }, "require": { "types": "./sk/isoDate.d.cts", "default": "./sk/isoDate.cjs" } }, "./sk/isoDateTime": { "import": { "types": "./sk/isoDateTime.d.mts", "default": "./sk/isoDateTime.mjs" }, "require": { "types": "./sk/isoDateTime.d.cts", "default": "./sk/isoDateTime.cjs" } }, "./sk/isoTime": { "import": { "types": "./sk/isoTime.d.mts", "default": "./sk/isoTime.mjs" }, "require": { "types": "./sk/isoTime.d.cts", "default": "./sk/isoTime.cjs" } }, "./sk/isoTimeSecond": { "import": { "types": "./sk/isoTimeSecond.d.mts", "default": "./sk/isoTimeSecond.mjs" }, "require": { "types": "./sk/isoTimeSecond.d.cts", "default": "./sk/isoTimeSecond.cjs" } }, "./sk/isoTimestamp": { "import": { "types": "./sk/isoTimestamp.d.mts", "default": "./sk/isoTimestamp.mjs" }, "require": { "types": "./sk/isoTimestamp.d.cts", "default": "./sk/isoTimestamp.cjs" } }, "./sk/isoWeek": { "import": { "types": "./sk/isoWeek.d.mts", "default": "./sk/isoWeek.mjs" }, "require": { "types": "./sk/isoWeek.d.cts", "default": "./sk/isoWeek.cjs" } }, "./sk/isrc": { "import": { "types": "./sk/isrc.d.mts", "default": "./sk/isrc.mjs" }, "require": { "types": "./sk/isrc.d.cts", "default": "./sk/isrc.cjs" } }, "./sk/jwsCompact": { "import": { "types": "./sk/jwsCompact.d.mts", "default": "./sk/jwsCompact.mjs" }, "require": { "types": "./sk/jwsCompact.d.cts", "default": "./sk/jwsCompact.cjs" } }, "./sk/length": { "import": { "types": "./sk/length.d.mts", "default": "./sk/length.mjs" }, "require": { "types": "./sk/length.d.cts", "default": "./sk/length.cjs" } }, "./sk/ltValue": { "import": { "types": "./sk/ltValue.d.mts", "default": "./sk/ltValue.mjs" }, "require": { "types": "./sk/ltValue.d.cts", "default": "./sk/ltValue.cjs" } }, "./sk/mac": { "import": { "types": "./sk/mac.d.mts", "default": "./sk/mac.mjs" }, "require": { "types": "./sk/mac.d.cts", "default": "./sk/mac.cjs" } }, "./sk/mac48": { "import": { "types": "./sk/mac48.d.mts", "default": "./sk/mac48.mjs" }, "require": { "types": "./sk/mac48.d.cts", "default": "./sk/mac48.cjs" } }, "./sk/mac64": { "import": { "types": "./sk/mac64.d.mts", "default": "./sk/mac64.mjs" }, "require": { "types": "./sk/mac64.d.cts", "default": "./sk/mac64.cjs" } }, "./sk/maxBytes": { "import": { "types": "./sk/maxBytes.d.mts", "default": "./sk/maxBytes.mjs" }, "require": { "types": "./sk/maxBytes.d.cts", "default": "./sk/maxBytes.cjs" } }, "./sk/maxEntries": { "import": { "types": "./sk/maxEntries.d.mts", "default": "./sk/maxEntries.mjs" }, "require": { "types": "./sk/maxEntries.d.cts", "default": "./sk/maxEntries.cjs" } }, "./sk/maxGraphemes": { "import": { "types": "./sk/maxGraphemes.d.mts", "default": "./sk/maxGraphemes.mjs" }, "require": { "types": "./sk/maxGraphemes.d.cts", "default": "./sk/maxGraphemes.cjs" } }, "./sk/maxLength": { "import": { "types": "./sk/maxLength.d.mts", "default": "./sk/maxLength.mjs" }, "require": { "types": "./sk/maxLength.d.cts", "default": "./sk/maxLength.cjs" } }, "./sk/maxSize": { "import": { "types": "./sk/maxSize.d.mts", "default": "./sk/maxSize.mjs" }, "require": { "types": "./sk/maxSize.d.cts", "default": "./sk/maxSize.cjs" } }, "./sk/maxValue": { "import": { "types": "./sk/maxValue.d.mts", "default": "./sk/maxValue.mjs" }, "require": { "types": "./sk/maxValue.d.cts", "default": "./sk/maxValue.cjs" } }, "./sk/maxWords": { "import": { "types": "./sk/maxWords.d.mts", "default": "./sk/maxWords.mjs" }, "require": { "types": "./sk/maxWords.d.cts", "default": "./sk/maxWords.cjs" } }, "./sk/mimeType": { "import": { "types": "./sk/mimeType.d.mts", "default": "./sk/mimeType.mjs" }, "require": { "types": "./sk/mimeType.d.cts", "default": "./sk/mimeType.cjs" } }, "./sk/minBytes": { "import": { "types": "./sk/minBytes.d.mts", "default": "./sk/minBytes.mjs" }, "require": { "types": "./sk/minBytes.d.cts", "default": "./sk/minBytes.cjs" } }, "./sk/minEntries": { "import": { "types": "./sk/minEntries.d.mts", "default": "./sk/minEntries.mjs" }, "require": { "types": "./sk/minEntries.d.cts", "default": "./sk/minEntries.cjs" } }, "./sk/minGraphemes": { "import": { "types": "./sk/minGraphemes.d.mts", "default": "./sk/minGraphemes.mjs" }, "require": { "types": "./sk/minGraphemes.d.cts", "default": "./sk/minGraphemes.cjs" } }, "./sk/minLength": { "import": { "types": "./sk/minLength.d.mts", "default": "./sk/minLength.mjs" }, "require": { "types": "./sk/minLength.d.cts", "default": "./sk/minLength.cjs" } }, "./sk/minSize": { "import": { "types": "./sk/minSize.d.mts", "default": "./sk/minSize.mjs" }, "require": { "types": "./sk/minSize.d.cts", "default": "./sk/minSize.cjs" } }, "./sk/minValue": { "import": { "types": "./sk/minValue.d.mts", "default": "./sk/minValue.mjs" }, "require": { "types": "./sk/minValue.d.cts", "default": "./sk/minValue.cjs" } }, "./sk/minWords": { "import": { "types": "./sk/minWords.d.mts", "default": "./sk/minWords.mjs" }, "require": { "types": "./sk/minWords.d.cts", "default": "./sk/minWords.cjs" } }, "./sk/multipleOf": { "import": { "types": "./sk/multipleOf.d.mts", "default": "./sk/multipleOf.mjs" }, "require": { "types": "./sk/multipleOf.d.cts", "default": "./sk/multipleOf.cjs" } }, "./sk/nanoid": { "import": { "types": "./sk/nanoid.d.mts", "default": "./sk/nanoid.mjs" }, "require": { "types": "./sk/nanoid.d.cts", "default": "./sk/nanoid.cjs" } }, "./sk/nonEmpty": { "import": { "types": "./sk/nonEmpty.d.mts", "default": "./sk/nonEmpty.mjs" }, "require": { "types": "./sk/nonEmpty.d.cts", "default": "./sk/nonEmpty.cjs" } }, "./sk/notBytes": { "import": { "types": "./sk/notBytes.d.mts", "default": "./sk/notBytes.mjs" }, "require": { "types": "./sk/notBytes.d.cts", "default": "./sk/notBytes.cjs" } }, "./sk/notEntries": { "import": { "types": "./sk/notEntries.d.mts", "default": "./sk/notEntries.mjs" }, "require": { "types": "./sk/notEntries.d.cts", "default": "./sk/notEntries.cjs" } }, "./sk/notGraphemes": { "import": { "types": "./sk/notGraphemes.d.mts", "default": "./sk/notGraphemes.mjs" }, "require": { "types": "./sk/notGraphemes.d.cts", "default": "./sk/notGraphemes.cjs" } }, "./sk/notLength": { "import": { "types": "./sk/notLength.d.mts", "default": "./sk/notLength.mjs" }, "require": { "types": "./sk/notLength.d.cts", "default": "./sk/notLength.cjs" } }, "./sk/notSize": { "import": { "types": "./sk/notSize.d.mts", "default": "./sk/notSize.mjs" }, "require": { "types": "./sk/notSize.d.cts", "default": "./sk/notSize.cjs" } }, "./sk/notValue": { "import": { "types": "./sk/notValue.d.mts", "default": "./sk/notValue.mjs" }, "require": { "types": "./sk/notValue.d.cts", "default": "./sk/notValue.cjs" } }, "./sk/notValues": { "import": { "types": "./sk/notValues.d.mts", "default": "./sk/notValues.mjs" }, "require": { "types": "./sk/notValues.d.cts", "default": "./sk/notValues.cjs" } }, "./sk/notWords": { "import": { "types": "./sk/notWords.d.mts", "default": "./sk/notWords.mjs" }, "require": { "types": "./sk/notWords.d.cts", "default": "./sk/notWords.cjs" } }, "./sk/octal": { "import": { "types": "./sk/octal.d.mts", "default": "./sk/octal.mjs" }, "require": { "types": "./sk/octal.d.cts", "default": "./sk/octal.cjs" } }, "./sk/parseBoolean": { "import": { "types": "./sk/parseBoolean.d.mts", "default": "./sk/parseBoolean.mjs" }, "require": { "types": "./sk/parseBoolean.d.cts", "default": "./sk/parseBoolean.cjs" } }, "./sk/parseJson": { "import": { "types": "./sk/parseJson.d.mts", "default": "./sk/parseJson.mjs" }, "require": { "types": "./sk/parseJson.d.cts", "default": "./sk/parseJson.cjs" } }, "./sk/partialCheck": { "import": { "types": "./sk/partialCheck.d.mts", "default": "./sk/partialCheck.mjs" }, "require": { "types": "./sk/partialCheck.d.cts", "default": "./sk/partialCheck.cjs" } }, "./sk/rawCheck": { "import": { "types": "./sk/rawCheck.d.mts", "default": "./sk/rawCheck.mjs" }, "require": { "types": "./sk/rawCheck.d.cts", "default": "./sk/rawCheck.cjs" } }, "./sk/rawTransform": { "import": { "types": "./sk/rawTransform.d.mts", "default": "./sk/rawTransform.mjs" }, "require": { "types": "./sk/rawTransform.d.cts", "default": "./sk/rawTransform.cjs" } }, "./sk/regex": { "import": { "types": "./sk/regex.d.mts", "default": "./sk/regex.mjs" }, "require": { "types": "./sk/regex.d.cts", "default": "./sk/regex.cjs" } }, "./sk/rfcEmail": { "import": { "types": "./sk/rfcEmail.d.mts", "default": "./sk/rfcEmail.mjs" }, "require": { "types": "./sk/rfcEmail.d.cts", "default": "./sk/rfcEmail.cjs" } }, "./sk/safeInteger": { "import": { "types": "./sk/safeInteger.d.mts", "default": "./sk/safeInteger.mjs" }, "require": { "types": "./sk/safeInteger.d.cts", "default": "./sk/safeInteger.cjs" } }, "./sk/size": { "import": { "types": "./sk/size.d.mts", "default": "./sk/size.mjs" }, "require": { "types": "./sk/size.d.cts", "default": "./sk/size.cjs" } }, "./sk/slug": { "import": { "types": "./sk/slug.d.mts", "default": "./sk/slug.mjs" }, "require": { "types": "./sk/slug.d.cts", "default": "./sk/slug.cjs" } }, "./sk/someItem": { "import": { "types": "./sk/someItem.d.mts", "default": "./sk/someItem.mjs" }, "require": { "types": "./sk/someItem.d.cts", "default": "./sk/someItem.cjs" } }, "./sk/startsWith": { "import": { "types": "./sk/startsWith.d.mts", "default": "./sk/startsWith.mjs" }, "require": { "types": "./sk/startsWith.d.cts", "default": "./sk/startsWith.cjs" } }, "./sk/stringifyJson": { "import": { "types": "./sk/stringifyJson.d.mts", "default": "./sk/stringifyJson.mjs" }, "require": { "types": "./sk/stringifyJson.d.cts", "default": "./sk/stringifyJson.cjs" } }, "./sk/toBigint": { "import": { "types": "./sk/toBigint.d.mts", "default": "./sk/toBigint.mjs" }, "require": { "types": "./sk/toBigint.d.cts", "default": "./sk/toBigint.cjs" } }, "./sk/toDate": { "import": { "types": "./sk/toDate.d.mts", "default": "./sk/toDate.mjs" }, "require": { "types": "./sk/toDate.d.cts", "default": "./sk/toDate.cjs" } }, "./sk/toNumber": { "import": { "types": "./sk/toNumber.d.mts", "default": "./sk/toNumber.mjs" }, "require": { "types": "./sk/toNumber.d.cts", "default": "./sk/toNumber.cjs" } }, "./sk/toString": { "import": { "types": "./sk/toString.d.mts", "default": "./sk/toString.mjs" }, "require": { "types": "./sk/toString.d.cts", "default": "./sk/toString.cjs" } }, "./sk/ulid": { "import": { "types": "./sk/ulid.d.mts", "default": "./sk/ulid.mjs" }, "require": { "types": "./sk/ulid.d.cts", "default": "./sk/ulid.cjs" } }, "./sk/url": { "import": { "types": "./sk/url.d.mts", "default": "./sk/url.mjs" }, "require": { "types": "./sk/url.d.cts", "default": "./sk/url.cjs" } }, "./sk/uuid": { "import": { "types": "./sk/uuid.d.mts", "default": "./sk/uuid.mjs" }, "require": { "types": "./sk/uuid.d.cts", "default": "./sk/uuid.cjs" } }, "./sk/value": { "import": { "types": "./sk/value.d.mts", "default": "./sk/value.mjs" }, "require": { "types": "./sk/value.d.cts", "default": "./sk/value.cjs" } }, "./sk/values": { "import": { "types": "./sk/values.d.mts", "default": "./sk/values.mjs" }, "require": { "types": "./sk/values.d.cts", "default": "./sk/values.cjs" } }, "./sk/words": { "import": { "types": "./sk/words.d.mts", "default": "./sk/words.mjs" }, "require": { "types": "./sk/words.d.cts", "default": "./sk/words.cjs" } }, "./sl": { "import": { "types": "./sl/index.d.mts", "default": "./sl/index.mjs" }, "require": { "types": "./sl/index.d.cts", "default": "./sl/index.cjs" } }, "./sl/schema": { "import": { "types": "./sl/schema.d.mts", "default": "./sl/schema.mjs" }, "require": { "types": "./sl/schema.d.cts", "default": "./sl/schema.cjs" } }, "./sl/base64": { "import": { "types": "./sl/base64.d.mts", "default": "./sl/base64.mjs" }, "require": { "types": "./sl/base64.d.cts", "default": "./sl/base64.cjs" } }, "./sl/bic": { "import": { "types": "./sl/bic.d.mts", "default": "./sl/bic.mjs" }, "require": { "types": "./sl/bic.d.cts", "default": "./sl/bic.cjs" } }, "./sl/bytes": { "import": { "types": "./sl/bytes.d.mts", "default": "./sl/bytes.mjs" }, "require": { "types": "./sl/bytes.d.cts", "default": "./sl/bytes.cjs" } }, "./sl/check": { "import": { "types": "./sl/check.d.mts", "default": "./sl/check.mjs" }, "require": { "types": "./sl/check.d.cts", "default": "./sl/check.cjs" } }, "./sl/checkAsync": { "import": { "types": "./sl/checkAsync.d.mts", "default": "./sl/checkAsync.mjs" }, "require": { "types": "./sl/checkAsync.d.cts", "default": "./sl/checkAsync.cjs" } }, "./sl/checkItems": { "import": { "types": "./sl/checkItems.d.mts", "default": "./sl/checkItems.mjs" }, "require": { "types": "./sl/checkItems.d.cts", "default": "./sl/checkItems.cjs" } }, "./sl/checkItemsAsync": { "import": { "types": "./sl/checkItemsAsync.d.mts", "default": "./sl/checkItemsAsync.mjs" }, "require": { "types": "./sl/checkItemsAsync.d.cts", "default": "./sl/checkItemsAsync.cjs" } }, "./sl/creditCard": { "import": { "types": "./sl/creditCard.d.mts", "default": "./sl/creditCard.mjs" }, "require": { "types": "./sl/creditCard.d.cts", "default": "./sl/creditCard.cjs" } }, "./sl/cuid2": { "import": { "types": "./sl/cuid2.d.mts", "default": "./sl/cuid2.mjs" }, "require": { "types": "./sl/cuid2.d.cts", "default": "./sl/cuid2.cjs" } }, "./sl/decimal": { "import": { "types": "./sl/decimal.d.mts", "default": "./sl/decimal.mjs" }, "require": { "types": "./sl/decimal.d.cts", "default": "./sl/decimal.cjs" } }, "./sl/digits": { "import": { "types": "./sl/digits.d.mts", "default": "./sl/digits.mjs" }, "require": { "types": "./sl/digits.d.cts", "default": "./sl/digits.cjs" } }, "./sl/domain": { "import": { "types": "./sl/domain.d.mts", "default": "./sl/domain.mjs" }, "require": { "types": "./sl/domain.d.cts", "default": "./sl/domain.cjs" } }, "./sl/email": { "import": { "types": "./sl/email.d.mts", "default": "./sl/email.mjs" }, "require": { "types": "./sl/email.d.cts", "default": "./sl/email.cjs" } }, "./sl/emoji": { "import": { "types": "./sl/emoji.d.mts", "default": "./sl/emoji.mjs" }, "require": { "types": "./sl/emoji.d.cts", "default": "./sl/emoji.cjs" } }, "./sl/empty": { "import": { "types": "./sl/empty.d.mts", "default": "./sl/empty.mjs" }, "require": { "types": "./sl/empty.d.cts", "default": "./sl/empty.cjs" } }, "./sl/endsWith": { "import": { "types": "./sl/endsWith.d.mts", "default": "./sl/endsWith.mjs" }, "require": { "types": "./sl/endsWith.d.cts", "default": "./sl/endsWith.cjs" } }, "./sl/entries": { "import": { "types": "./sl/entries.d.mts", "default": "./sl/entries.mjs" }, "require": { "types": "./sl/entries.d.cts", "default": "./sl/entries.cjs" } }, "./sl/everyItem": { "import": { "types": "./sl/everyItem.d.mts", "default": "./sl/everyItem.mjs" }, "require": { "types": "./sl/everyItem.d.cts", "default": "./sl/everyItem.cjs" } }, "./sl/excludes": { "import": { "types": "./sl/excludes.d.mts", "default": "./sl/excludes.mjs" }, "require": { "types": "./sl/excludes.d.cts", "default": "./sl/excludes.cjs" } }, "./sl/finite": { "import": { "types": "./sl/finite.d.mts", "default": "./sl/finite.mjs" }, "require": { "types": "./sl/finite.d.cts", "default": "./sl/finite.cjs" } }, "./sl/graphemes": { "import": { "types": "./sl/graphemes.d.mts", "default": "./sl/graphemes.mjs" }, "require": { "types": "./sl/graphemes.d.cts", "default": "./sl/graphemes.cjs" } }, "./sl/gtValue": { "import": { "types": "./sl/gtValue.d.mts", "default": "./sl/gtValue.mjs" }, "require": { "types": "./sl/gtValue.d.cts", "default": "./sl/gtValue.cjs" } }, "./sl/guard": { "import": { "types": "./sl/guard.d.mts", "default": "./sl/guard.mjs" }, "require": { "types": "./sl/guard.d.cts", "default": "./sl/guard.cjs" } }, "./sl/hash": { "import": { "types": "./sl/hash.d.mts", "default": "./sl/hash.mjs" }, "require": { "types": "./sl/hash.d.cts", "default": "./sl/hash.cjs" } }, "./sl/hexadecimal": { "import": { "types": "./sl/hexadecimal.d.mts", "default": "./sl/hexadecimal.mjs" }, "require": { "types": "./sl/hexadecimal.d.cts", "default": "./sl/hexadecimal.cjs" } }, "./sl/hexColor": { "import": { "types": "./sl/hexColor.d.mts", "default": "./sl/hexColor.mjs" }, "require": { "types": "./sl/hexColor.d.cts", "default": "./sl/hexColor.cjs" } }, "./sl/imei": { "import": { "types": "./sl/imei.d.mts", "default": "./sl/imei.mjs" }, "require": { "types": "./sl/imei.d.cts", "default": "./sl/imei.cjs" } }, "./sl/includes": { "import": { "types": "./sl/includes.d.mts", "default": "./sl/includes.mjs" }, "require": { "types": "./sl/includes.d.cts", "default": "./sl/includes.cjs" } }, "./sl/integer": { "import": { "types": "./sl/integer.d.mts", "default": "./sl/integer.mjs" }, "require": { "types": "./sl/integer.d.cts", "default": "./sl/integer.cjs" } }, "./sl/ip": { "import": { "types": "./sl/ip.d.mts", "default": "./sl/ip.mjs" }, "require": { "types": "./sl/ip.d.cts", "default": "./sl/ip.cjs" } }, "./sl/ipv4": { "import": { "types": "./sl/ipv4.d.mts", "default": "./sl/ipv4.mjs" }, "require": { "types": "./sl/ipv4.d.cts", "default": "./sl/ipv4.cjs" } }, "./sl/ipv6": { "import": { "types": "./sl/ipv6.d.mts", "default": "./sl/ipv6.mjs" }, "require": { "types": "./sl/ipv6.d.cts", "default": "./sl/ipv6.cjs" } }, "./sl/isbn": { "import": { "types": "./sl/isbn.d.mts", "default": "./sl/isbn.mjs" }, "require": { "types": "./sl/isbn.d.cts", "default": "./sl/isbn.cjs" } }, "./sl/isoDate": { "import": { "types": "./sl/isoDate.d.mts", "default": "./sl/isoDate.mjs" }, "require": { "types": "./sl/isoDate.d.cts", "default": "./sl/isoDate.cjs" } }, "./sl/isoDateTime": { "import": { "types": "./sl/isoDateTime.d.mts", "default": "./sl/isoDateTime.mjs" }, "require": { "types": "./sl/isoDateTime.d.cts", "default": "./sl/isoDateTime.cjs" } }, "./sl/isoTime": { "import": { "types": "./sl/isoTime.d.mts", "default": "./sl/isoTime.mjs" }, "require": { "types": "./sl/isoTime.d.cts", "default": "./sl/isoTime.cjs" } }, "./sl/isoTimeSecond": { "import": { "types": "./sl/isoTimeSecond.d.mts", "default": "./sl/isoTimeSecond.mjs" }, "require": { "types": "./sl/isoTimeSecond.d.cts", "default": "./sl/isoTimeSecond.cjs" } }, "./sl/isoTimestamp": { "import": { "types": "./sl/isoTimestamp.d.mts", "default": "./sl/isoTimestamp.mjs" }, "require": { "types": "./sl/isoTimestamp.d.cts", "default": "./sl/isoTimestamp.cjs" } }, "./sl/isoWeek": { "import": { "types": "./sl/isoWeek.d.mts", "default": "./sl/isoWeek.mjs" }, "require": { "types": "./sl/isoWeek.d.cts", "default": "./sl/isoWeek.cjs" } }, "./sl/isrc": { "import": { "types": "./sl/isrc.d.mts", "default": "./sl/isrc.mjs" }, "require": { "types": "./sl/isrc.d.cts", "default": "./sl/isrc.cjs" } }, "./sl/jwsCompact": { "import": { "types": "./sl/jwsCompact.d.mts", "default": "./sl/jwsCompact.mjs" }, "require": { "types": "./sl/jwsCompact.d.cts", "default": "./sl/jwsCompact.cjs" } }, "./sl/length": { "import": { "types": "./sl/length.d.mts", "default": "./sl/length.mjs" }, "require": { "types": "./sl/length.d.cts", "default": "./sl/length.cjs" } }, "./sl/ltValue": { "import": { "types": "./sl/ltValue.d.mts", "default": "./sl/ltValue.mjs" }, "require": { "types": "./sl/ltValue.d.cts", "default": "./sl/ltValue.cjs" } }, "./sl/mac": { "import": { "types": "./sl/mac.d.mts", "default": "./sl/mac.mjs" }, "require": { "types": "./sl/mac.d.cts", "default": "./sl/mac.cjs" } }, "./sl/mac48": { "import": { "types": "./sl/mac48.d.mts", "default": "./sl/mac48.mjs" }, "require": { "types": "./sl/mac48.d.cts", "default": "./sl/mac48.cjs" } }, "./sl/mac64": { "import": { "types": "./sl/mac64.d.mts", "default": "./sl/mac64.mjs" }, "require": { "types": "./sl/mac64.d.cts", "default": "./sl/mac64.cjs" } }, "./sl/maxBytes": { "import": { "types": "./sl/maxBytes.d.mts", "default": "./sl/maxBytes.mjs" }, "require": { "types": "./sl/maxBytes.d.cts", "default": "./sl/maxBytes.cjs" } }, "./sl/maxEntries": { "import": { "types": "./sl/maxEntries.d.mts", "default": "./sl/maxEntries.mjs" }, "require": { "types": "./sl/maxEntries.d.cts", "default": "./sl/maxEntries.cjs" } }, "./sl/maxGraphemes": { "import": { "types": "./sl/maxGraphemes.d.mts", "default": "./sl/maxGraphemes.mjs" }, "require": { "types": "./sl/maxGraphemes.d.cts", "default": "./sl/maxGraphemes.cjs" } }, "./sl/maxLength": { "import": { "types": "./sl/maxLength.d.mts", "default": "./sl/maxLength.mjs" }, "require": { "types": "./sl/maxLength.d.cts", "default": "./sl/maxLength.cjs" } }, "./sl/maxSize": { "import": { "types": "./sl/maxSize.d.mts", "default": "./sl/maxSize.mjs" }, "require": { "types": "./sl/maxSize.d.cts", "default": "./sl/maxSize.cjs" } }, "./sl/maxValue": { "import": { "types": "./sl/maxValue.d.mts", "default": "./sl/maxValue.mjs" }, "require": { "types": "./sl/maxValue.d.cts", "default": "./sl/maxValue.cjs" } }, "./sl/maxWords": { "import": { "types": "./sl/maxWords.d.mts", "default": "./sl/maxWords.mjs" }, "require": { "types": "./sl/maxWords.d.cts", "default": "./sl/maxWords.cjs" } }, "./sl/mimeType": { "import": { "types": "./sl/mimeType.d.mts", "default": "./sl/mimeType.mjs" }, "require": { "types": "./sl/mimeType.d.cts", "default": "./sl/mimeType.cjs" } }, "./sl/minBytes": { "import": { "types": "./sl/minBytes.d.mts", "default": "./sl/minBytes.mjs" }, "require": { "types": "./sl/minBytes.d.cts", "default": "./sl/minBytes.cjs" } }, "./sl/minEntries": { "import": { "types": "./sl/minEntries.d.mts", "default": "./sl/minEntries.mjs" }, "require": { "types": "./sl/minEntries.d.cts", "default": "./sl/minEntries.cjs" } }, "./sl/minGraphemes": { "import": { "types": "./sl/minGraphemes.d.mts", "default": "./sl/minGraphemes.mjs" }, "require": { "types": "./sl/minGraphemes.d.cts", "default": "./sl/minGraphemes.cjs" } }, "./sl/minLength": { "import": { "types": "./sl/minLength.d.mts", "default": "./sl/minLength.mjs" }, "require": { "types": "./sl/minLength.d.cts", "default": "./sl/minLength.cjs" } }, "./sl/minSize": { "import": { "types": "./sl/minSize.d.mts", "default": "./sl/minSize.mjs" }, "require": { "types": "./sl/minSize.d.cts", "default": "./sl/minSize.cjs" } }, "./sl/minValue": { "import": { "types": "./sl/minValue.d.mts", "default": "./sl/minValue.mjs" }, "require": { "types": "./sl/minValue.d.cts", "default": "./sl/minValue.cjs" } }, "./sl/minWords": { "import": { "types": "./sl/minWords.d.mts", "default": "./sl/minWords.mjs" }, "require": { "types": "./sl/minWords.d.cts", "default": "./sl/minWords.cjs" } }, "./sl/multipleOf": { "import": { "types": "./sl/multipleOf.d.mts", "default": "./sl/multipleOf.mjs" }, "require": { "types": "./sl/multipleOf.d.cts", "default": "./sl/multipleOf.cjs" } }, "./sl/nanoid": { "import": { "types": "./sl/nanoid.d.mts", "default": "./sl/nanoid.mjs" }, "require": { "types": "./sl/nanoid.d.cts", "default": "./sl/nanoid.cjs" } }, "./sl/nonEmpty": { "import": { "types": "./sl/nonEmpty.d.mts", "default": "./sl/nonEmpty.mjs" }, "require": { "types": "./sl/nonEmpty.d.cts", "default": "./sl/nonEmpty.cjs" } }, "./sl/notBytes": { "import": { "types": "./sl/notBytes.d.mts", "default": "./sl/notBytes.mjs" }, "require": { "types": "./sl/notBytes.d.cts", "default": "./sl/notBytes.cjs" } }, "./sl/notEntries": { "import": { "types": "./sl/notEntries.d.mts", "default": "./sl/notEntries.mjs" }, "require": { "types": "./sl/notEntries.d.cts", "default": "./sl/notEntries.cjs" } }, "./sl/notGraphemes": { "import": { "types": "./sl/notGraphemes.d.mts", "default": "./sl/notGraphemes.mjs" }, "require": { "types": "./sl/notGraphemes.d.cts", "default": "./sl/notGraphemes.cjs" } }, "./sl/notLength": { "import": { "types": "./sl/notLength.d.mts", "default": "./sl/notLength.mjs" }, "require": { "types": "./sl/notLength.d.cts", "default": "./sl/notLength.cjs" } }, "./sl/notSize": { "import": { "types": "./sl/notSize.d.mts", "default": "./sl/notSize.mjs" }, "require": { "types": "./sl/notSize.d.cts", "default": "./sl/notSize.cjs" } }, "./sl/notValue": { "import": { "types": "./sl/notValue.d.mts", "default": "./sl/notValue.mjs" }, "require": { "types": "./sl/notValue.d.cts", "default": "./sl/notValue.cjs" } }, "./sl/notValues": { "import": { "types": "./sl/notValues.d.mts", "default": "./sl/notValues.mjs" }, "require": { "types": "./sl/notValues.d.cts", "default": "./sl/notValues.cjs" } }, "./sl/notWords": { "import": { "types": "./sl/notWords.d.mts", "default": "./sl/notWords.mjs" }, "require": { "types": "./sl/notWords.d.cts", "default": "./sl/notWords.cjs" } }, "./sl/octal": { "import": { "types": "./sl/octal.d.mts", "default": "./sl/octal.mjs" }, "require": { "types": "./sl/octal.d.cts", "default": "./sl/octal.cjs" } }, "./sl/parseBoolean": { "import": { "types": "./sl/parseBoolean.d.mts", "default": "./sl/parseBoolean.mjs" }, "require": { "types": "./sl/parseBoolean.d.cts", "default": "./sl/parseBoolean.cjs" } }, "./sl/parseJson": { "import": { "types": "./sl/parseJson.d.mts", "default": "./sl/parseJson.mjs" }, "require": { "types": "./sl/parseJson.d.cts", "default": "./sl/parseJson.cjs" } }, "./sl/partialCheck": { "import": { "types": "./sl/partialCheck.d.mts", "default": "./sl/partialCheck.mjs" }, "require": { "types": "./sl/partialCheck.d.cts", "default": "./sl/partialCheck.cjs" } }, "./sl/rawCheck": { "import": { "types": "./sl/rawCheck.d.mts", "default": "./sl/rawCheck.mjs" }, "require": { "types": "./sl/rawCheck.d.cts", "default": "./sl/rawCheck.cjs" } }, "./sl/rawTransform": { "import": { "types": "./sl/rawTransform.d.mts", "default": "./sl/rawTransform.mjs" }, "require": { "types": "./sl/rawTransform.d.cts", "default": "./sl/rawTransform.cjs" } }, "./sl/regex": { "import": { "types": "./sl/regex.d.mts", "default": "./sl/regex.mjs" }, "require": { "types": "./sl/regex.d.cts", "default": "./sl/regex.cjs" } }, "./sl/rfcEmail": { "import": { "types": "./sl/rfcEmail.d.mts", "default": "./sl/rfcEmail.mjs" }, "require": { "types": "./sl/rfcEmail.d.cts", "default": "./sl/rfcEmail.cjs" } }, "./sl/safeInteger": { "import": { "types": "./sl/safeInteger.d.mts", "default": "./sl/safeInteger.mjs" }, "require": { "types": "./sl/safeInteger.d.cts", "default": "./sl/safeInteger.cjs" } }, "./sl/size": { "import": { "types": "./sl/size.d.mts", "default": "./sl/size.mjs" }, "require": { "types": "./sl/size.d.cts", "default": "./sl/size.cjs" } }, "./sl/slug": { "import": { "types": "./sl/slug.d.mts", "default": "./sl/slug.mjs" }, "require": { "types": "./sl/slug.d.cts", "default": "./sl/slug.cjs" } }, "./sl/someItem": { "import": { "types": "./sl/someItem.d.mts", "default": "./sl/someItem.mjs" }, "require": { "types": "./sl/someItem.d.cts", "default": "./sl/someItem.cjs" } }, "./sl/startsWith": { "import": { "types": "./sl/startsWith.d.mts", "default": "./sl/startsWith.mjs" }, "require": { "types": "./sl/startsWith.d.cts", "default": "./sl/startsWith.cjs" } }, "./sl/stringifyJson": { "import": { "types": "./sl/stringifyJson.d.mts", "default": "./sl/stringifyJson.mjs" }, "require": { "types": "./sl/stringifyJson.d.cts", "default": "./sl/stringifyJson.cjs" } }, "./sl/toBigint": { "import": { "types": "./sl/toBigint.d.mts", "default": "./sl/toBigint.mjs" }, "require": { "types": "./sl/toBigint.d.cts", "default": "./sl/toBigint.cjs" } }, "./sl/toDate": { "import": { "types": "./sl/toDate.d.mts", "default": "./sl/toDate.mjs" }, "require": { "types": "./sl/toDate.d.cts", "default": "./sl/toDate.cjs" } }, "./sl/toNumber": { "import": { "types": "./sl/toNumber.d.mts", "default": "./sl/toNumber.mjs" }, "require": { "types": "./sl/toNumber.d.cts", "default": "./sl/toNumber.cjs" } }, "./sl/toString": { "import": { "types": "./sl/toString.d.mts", "default": "./sl/toString.mjs" }, "require": { "types": "./sl/toString.d.cts", "default": "./sl/toString.cjs" } }, "./sl/ulid": { "import": { "types": "./sl/ulid.d.mts", "default": "./sl/ulid.mjs" }, "require": { "types": "./sl/ulid.d.cts", "default": "./sl/ulid.cjs" } }, "./sl/url": { "import": { "types": "./sl/url.d.mts", "default": "./sl/url.mjs" }, "require": { "types": "./sl/url.d.cts", "default": "./sl/url.cjs" } }, "./sl/uuid": { "import": { "types": "./sl/uuid.d.mts", "default": "./sl/uuid.mjs" }, "require": { "types": "./sl/uuid.d.cts", "default": "./sl/uuid.cjs" } }, "./sl/value": { "import": { "types": "./sl/value.d.mts", "default": "./sl/value.mjs" }, "require": { "types": "./sl/value.d.cts", "default": "./sl/value.cjs" } }, "./sl/values": { "import": { "types": "./sl/values.d.mts", "default": "./sl/values.mjs" }, "require": { "types": "./sl/values.d.cts", "default": "./sl/values.cjs" } }, "./sl/words": { "import": { "types": "./sl/words.d.mts", "default": "./sl/words.mjs" }, "require": { "types": "./sl/words.d.cts", "default": "./sl/words.cjs" } }, "./sv": { "import": { "types": "./sv/index.d.mts", "default": "./sv/index.mjs" }, "require": { "types": "./sv/index.d.cts", "default": "./sv/index.cjs" } }, "./sv/schema": { "import": { "types": "./sv/schema.d.mts", "default": "./sv/schema.mjs" }, "require": { "types": "./sv/schema.d.cts", "default": "./sv/schema.cjs" } }, "./sv/base64": { "import": { "types": "./sv/base64.d.mts", "default": "./sv/base64.mjs" }, "require": { "types": "./sv/base64.d.cts", "default": "./sv/base64.cjs" } }, "./sv/bic": { "import": { "types": "./sv/bic.d.mts", "default": "./sv/bic.mjs" }, "require": { "types": "./sv/bic.d.cts", "default": "./sv/bic.cjs" } }, "./sv/bytes": { "import": { "types": "./sv/bytes.d.mts", "default": "./sv/bytes.mjs" }, "require": { "types": "./sv/bytes.d.cts", "default": "./sv/bytes.cjs" } }, "./sv/check": { "import": { "types": "./sv/check.d.mts", "default": "./sv/check.mjs" }, "require": { "types": "./sv/check.d.cts", "default": "./sv/check.cjs" } }, "./sv/checkAsync": { "import": { "types": "./sv/checkAsync.d.mts", "default": "./sv/checkAsync.mjs" }, "require": { "types": "./sv/checkAsync.d.cts", "default": "./sv/checkAsync.cjs" } }, "./sv/checkItems": { "import": { "types": "./sv/checkItems.d.mts", "default": "./sv/checkItems.mjs" }, "require": { "types": "./sv/checkItems.d.cts", "default": "./sv/checkItems.cjs" } }, "./sv/checkItemsAsync": { "import": { "types": "./sv/checkItemsAsync.d.mts", "default": "./sv/checkItemsAsync.mjs" }, "require": { "types": "./sv/checkItemsAsync.d.cts", "default": "./sv/checkItemsAsync.cjs" } }, "./sv/creditCard": { "import": { "types": "./sv/creditCard.d.mts", "default": "./sv/creditCard.mjs" }, "require": { "types": "./sv/creditCard.d.cts", "default": "./sv/creditCard.cjs" } }, "./sv/cuid2": { "import": { "types": "./sv/cuid2.d.mts", "default": "./sv/cuid2.mjs" }, "require": { "types": "./sv/cuid2.d.cts", "default": "./sv/cuid2.cjs" } }, "./sv/decimal": { "import": { "types": "./sv/decimal.d.mts", "default": "./sv/decimal.mjs" }, "require": { "types": "./sv/decimal.d.cts", "default": "./sv/decimal.cjs" } }, "./sv/digits": { "import": { "types": "./sv/digits.d.mts", "default": "./sv/digits.mjs" }, "require": { "types": "./sv/digits.d.cts", "default": "./sv/digits.cjs" } }, "./sv/domain": { "import": { "types": "./sv/domain.d.mts", "default": "./sv/domain.mjs" }, "require": { "types": "./sv/domain.d.cts", "default": "./sv/domain.cjs" } }, "./sv/email": { "import": { "types": "./sv/email.d.mts", "default": "./sv/email.mjs" }, "require": { "types": "./sv/email.d.cts", "default": "./sv/email.cjs" } }, "./sv/emoji": { "import": { "types": "./sv/emoji.d.mts", "default": "./sv/emoji.mjs" }, "require": { "types": "./sv/emoji.d.cts", "default": "./sv/emoji.cjs" } }, "./sv/empty": { "import": { "types": "./sv/empty.d.mts", "default": "./sv/empty.mjs" }, "require": { "types": "./sv/empty.d.cts", "default": "./sv/empty.cjs" } }, "./sv/endsWith": { "import": { "types": "./sv/endsWith.d.mts", "default": "./sv/endsWith.mjs" }, "require": { "types": "./sv/endsWith.d.cts", "default": "./sv/endsWith.cjs" } }, "./sv/entries": { "import": { "types": "./sv/entries.d.mts", "default": "./sv/entries.mjs" }, "require": { "types": "./sv/entries.d.cts", "default": "./sv/entries.cjs" } }, "./sv/everyItem": { "import": { "types": "./sv/everyItem.d.mts", "default": "./sv/everyItem.mjs" }, "require": { "types": "./sv/everyItem.d.cts", "default": "./sv/everyItem.cjs" } }, "./sv/excludes": { "import": { "types": "./sv/excludes.d.mts", "default": "./sv/excludes.mjs" }, "require": { "types": "./sv/excludes.d.cts", "default": "./sv/excludes.cjs" } }, "./sv/finite": { "import": { "types": "./sv/finite.d.mts", "default": "./sv/finite.mjs" }, "require": { "types": "./sv/finite.d.cts", "default": "./sv/finite.cjs" } }, "./sv/graphemes": { "import": { "types": "./sv/graphemes.d.mts", "default": "./sv/graphemes.mjs" }, "require": { "types": "./sv/graphemes.d.cts", "default": "./sv/graphemes.cjs" } }, "./sv/gtValue": { "import": { "types": "./sv/gtValue.d.mts", "default": "./sv/gtValue.mjs" }, "require": { "types": "./sv/gtValue.d.cts", "default": "./sv/gtValue.cjs" } }, "./sv/guard": { "import": { "types": "./sv/guard.d.mts", "default": "./sv/guard.mjs" }, "require": { "types": "./sv/guard.d.cts", "default": "./sv/guard.cjs" } }, "./sv/hash": { "import": { "types": "./sv/hash.d.mts", "default": "./sv/hash.mjs" }, "require": { "types": "./sv/hash.d.cts", "default": "./sv/hash.cjs" } }, "./sv/hexadecimal": { "import": { "types": "./sv/hexadecimal.d.mts", "default": "./sv/hexadecimal.mjs" }, "require": { "types": "./sv/hexadecimal.d.cts", "default": "./sv/hexadecimal.cjs" } }, "./sv/hexColor": { "import": { "types": "./sv/hexColor.d.mts", "default": "./sv/hexColor.mjs" }, "require": { "types": "./sv/hexColor.d.cts", "default": "./sv/hexColor.cjs" } }, "./sv/imei": { "import": { "types": "./sv/imei.d.mts", "default": "./sv/imei.mjs" }, "require": { "types": "./sv/imei.d.cts", "default": "./sv/imei.cjs" } }, "./sv/includes": { "import": { "types": "./sv/includes.d.mts", "default": "./sv/includes.mjs" }, "require": { "types": "./sv/includes.d.cts", "default": "./sv/includes.cjs" } }, "./sv/integer": { "import": { "types": "./sv/integer.d.mts", "default": "./sv/integer.mjs" }, "require": { "types": "./sv/integer.d.cts", "default": "./sv/integer.cjs" } }, "./sv/ip": { "import": { "types": "./sv/ip.d.mts", "default": "./sv/ip.mjs" }, "require": { "types": "./sv/ip.d.cts", "default": "./sv/ip.cjs" } }, "./sv/ipv4": { "import": { "types": "./sv/ipv4.d.mts", "default": "./sv/ipv4.mjs" }, "require": { "types": "./sv/ipv4.d.cts", "default": "./sv/ipv4.cjs" } }, "./sv/ipv6": { "import": { "types": "./sv/ipv6.d.mts", "default": "./sv/ipv6.mjs" }, "require": { "types": "./sv/ipv6.d.cts", "default": "./sv/ipv6.cjs" } }, "./sv/isbn": { "import": { "types": "./sv/isbn.d.mts", "default": "./sv/isbn.mjs" }, "require": { "types": "./sv/isbn.d.cts", "default": "./sv/isbn.cjs" } }, "./sv/isoDate": { "import": { "types": "./sv/isoDate.d.mts", "default": "./sv/isoDate.mjs" }, "require": { "types": "./sv/isoDate.d.cts", "default": "./sv/isoDate.cjs" } }, "./sv/isoDateTime": { "import": { "types": "./sv/isoDateTime.d.mts", "default": "./sv/isoDateTime.mjs" }, "require": { "types": "./sv/isoDateTime.d.cts", "default": "./sv/isoDateTime.cjs" } }, "./sv/isoTime": { "import": { "types": "./sv/isoTime.d.mts", "default": "./sv/isoTime.mjs" }, "require": { "types": "./sv/isoTime.d.cts", "default": "./sv/isoTime.cjs" } }, "./sv/isoTimeSecond": { "import": { "types": "./sv/isoTimeSecond.d.mts", "default": "./sv/isoTimeSecond.mjs" }, "require": { "types": "./sv/isoTimeSecond.d.cts", "default": "./sv/isoTimeSecond.cjs" } }, "./sv/isoTimestamp": { "import": { "types": "./sv/isoTimestamp.d.mts", "default": "./sv/isoTimestamp.mjs" }, "require": { "types": "./sv/isoTimestamp.d.cts", "default": "./sv/isoTimestamp.cjs" } }, "./sv/isoWeek": { "import": { "types": "./sv/isoWeek.d.mts", "default": "./sv/isoWeek.mjs" }, "require": { "types": "./sv/isoWeek.d.cts", "default": "./sv/isoWeek.cjs" } }, "./sv/isrc": { "import": { "types": "./sv/isrc.d.mts", "default": "./sv/isrc.mjs" }, "require": { "types": "./sv/isrc.d.cts", "default": "./sv/isrc.cjs" } }, "./sv/jwsCompact": { "import": { "types": "./sv/jwsCompact.d.mts", "default": "./sv/jwsCompact.mjs" }, "require": { "types": "./sv/jwsCompact.d.cts", "default": "./sv/jwsCompact.cjs" } }, "./sv/length": { "import": { "types": "./sv/length.d.mts", "default": "./sv/length.mjs" }, "require": { "types": "./sv/length.d.cts", "default": "./sv/length.cjs" } }, "./sv/ltValue": { "import": { "types": "./sv/ltValue.d.mts", "default": "./sv/ltValue.mjs" }, "require": { "types": "./sv/ltValue.d.cts", "default": "./sv/ltValue.cjs" } }, "./sv/mac": { "import": { "types": "./sv/mac.d.mts", "default": "./sv/mac.mjs" }, "require": { "types": "./sv/mac.d.cts", "default": "./sv/mac.cjs" } }, "./sv/mac48": { "import": { "types": "./sv/mac48.d.mts", "default": "./sv/mac48.mjs" }, "require": { "types": "./sv/mac48.d.cts", "default": "./sv/mac48.cjs" } }, "./sv/mac64": { "import": { "types": "./sv/mac64.d.mts", "default": "./sv/mac64.mjs" }, "require": { "types": "./sv/mac64.d.cts", "default": "./sv/mac64.cjs" } }, "./sv/maxBytes": { "import": { "types": "./sv/maxBytes.d.mts", "default": "./sv/maxBytes.mjs" }, "require": { "types": "./sv/maxBytes.d.cts", "default": "./sv/maxBytes.cjs" } }, "./sv/maxEntries": { "import": { "types": "./sv/maxEntries.d.mts", "default": "./sv/maxEntries.mjs" }, "require": { "types": "./sv/maxEntries.d.cts", "default": "./sv/maxEntries.cjs" } }, "./sv/maxGraphemes": { "import": { "types": "./sv/maxGraphemes.d.mts", "default": "./sv/maxGraphemes.mjs" }, "require": { "types": "./sv/maxGraphemes.d.cts", "default": "./sv/maxGraphemes.cjs" } }, "./sv/maxLength": { "import": { "types": "./sv/maxLength.d.mts", "default": "./sv/maxLength.mjs" }, "require": { "types": "./sv/maxLength.d.cts", "default": "./sv/maxLength.cjs" } }, "./sv/maxSize": { "import": { "types": "./sv/maxSize.d.mts", "default": "./sv/maxSize.mjs" }, "require": { "types": "./sv/maxSize.d.cts", "default": "./sv/maxSize.cjs" } }, "./sv/maxValue": { "import": { "types": "./sv/maxValue.d.mts", "default": "./sv/maxValue.mjs" }, "require": { "types": "./sv/maxValue.d.cts", "default": "./sv/maxValue.cjs" } }, "./sv/maxWords": { "import": { "types": "./sv/maxWords.d.mts", "default": "./sv/maxWords.mjs" }, "require": { "types": "./sv/maxWords.d.cts", "default": "./sv/maxWords.cjs" } }, "./sv/mimeType": { "import": { "types": "./sv/mimeType.d.mts", "default": "./sv/mimeType.mjs" }, "require": { "types": "./sv/mimeType.d.cts", "default": "./sv/mimeType.cjs" } }, "./sv/minBytes": { "import": { "types": "./sv/minBytes.d.mts", "default": "./sv/minBytes.mjs" }, "require": { "types": "./sv/minBytes.d.cts", "default": "./sv/minBytes.cjs" } }, "./sv/minEntries": { "import": { "types": "./sv/minEntries.d.mts", "default": "./sv/minEntries.mjs" }, "require": { "types": "./sv/minEntries.d.cts", "default": "./sv/minEntries.cjs" } }, "./sv/minGraphemes": { "import": { "types": "./sv/minGraphemes.d.mts", "default": "./sv/minGraphemes.mjs" }, "require": { "types": "./sv/minGraphemes.d.cts", "default": "./sv/minGraphemes.cjs" } }, "./sv/minLength": { "import": { "types": "./sv/minLength.d.mts", "default": "./sv/minLength.mjs" }, "require": { "types": "./sv/minLength.d.cts", "default": "./sv/minLength.cjs" } }, "./sv/minSize": { "import": { "types": "./sv/minSize.d.mts", "default": "./sv/minSize.mjs" }, "require": { "types": "./sv/minSize.d.cts", "default": "./sv/minSize.cjs" } }, "./sv/minValue": { "import": { "types": "./sv/minValue.d.mts", "default": "./sv/minValue.mjs" }, "require": { "types": "./sv/minValue.d.cts", "default": "./sv/minValue.cjs" } }, "./sv/minWords": { "import": { "types": "./sv/minWords.d.mts", "default": "./sv/minWords.mjs" }, "require": { "types": "./sv/minWords.d.cts", "default": "./sv/minWords.cjs" } }, "./sv/multipleOf": { "import": { "types": "./sv/multipleOf.d.mts", "default": "./sv/multipleOf.mjs" }, "require": { "types": "./sv/multipleOf.d.cts", "default": "./sv/multipleOf.cjs" } }, "./sv/nanoid": { "import": { "types": "./sv/nanoid.d.mts", "default": "./sv/nanoid.mjs" }, "require": { "types": "./sv/nanoid.d.cts", "default": "./sv/nanoid.cjs" } }, "./sv/nonEmpty": { "import": { "types": "./sv/nonEmpty.d.mts", "default": "./sv/nonEmpty.mjs" }, "require": { "types": "./sv/nonEmpty.d.cts", "default": "./sv/nonEmpty.cjs" } }, "./sv/notBytes": { "import": { "types": "./sv/notBytes.d.mts", "default": "./sv/notBytes.mjs" }, "require": { "types": "./sv/notBytes.d.cts", "default": "./sv/notBytes.cjs" } }, "./sv/notEntries": { "import": { "types": "./sv/notEntries.d.mts", "default": "./sv/notEntries.mjs" }, "require": { "types": "./sv/notEntries.d.cts", "default": "./sv/notEntries.cjs" } }, "./sv/notGraphemes": { "import": { "types": "./sv/notGraphemes.d.mts", "default": "./sv/notGraphemes.mjs" }, "require": { "types": "./sv/notGraphemes.d.cts", "default": "./sv/notGraphemes.cjs" } }, "./sv/notLength": { "import": { "types": "./sv/notLength.d.mts", "default": "./sv/notLength.mjs" }, "require": { "types": "./sv/notLength.d.cts", "default": "./sv/notLength.cjs" } }, "./sv/notSize": { "import": { "types": "./sv/notSize.d.mts", "default": "./sv/notSize.mjs" }, "require": { "types": "./sv/notSize.d.cts", "default": "./sv/notSize.cjs" } }, "./sv/notValue": { "import": { "types": "./sv/notValue.d.mts", "default": "./sv/notValue.mjs" }, "require": { "types": "./sv/notValue.d.cts", "default": "./sv/notValue.cjs" } }, "./sv/notValues": { "import": { "types": "./sv/notValues.d.mts", "default": "./sv/notValues.mjs" }, "require": { "types": "./sv/notValues.d.cts", "default": "./sv/notValues.cjs" } }, "./sv/notWords": { "import": { "types": "./sv/notWords.d.mts", "default": "./sv/notWords.mjs" }, "require": { "types": "./sv/notWords.d.cts", "default": "./sv/notWords.cjs" } }, "./sv/octal": { "import": { "types": "./sv/octal.d.mts", "default": "./sv/octal.mjs" }, "require": { "types": "./sv/octal.d.cts", "default": "./sv/octal.cjs" } }, "./sv/parseBoolean": { "import": { "types": "./sv/parseBoolean.d.mts", "default": "./sv/parseBoolean.mjs" }, "require": { "types": "./sv/parseBoolean.d.cts", "default": "./sv/parseBoolean.cjs" } }, "./sv/parseJson": { "import": { "types": "./sv/parseJson.d.mts", "default": "./sv/parseJson.mjs" }, "require": { "types": "./sv/parseJson.d.cts", "default": "./sv/parseJson.cjs" } }, "./sv/partialCheck": { "import": { "types": "./sv/partialCheck.d.mts", "default": "./sv/partialCheck.mjs" }, "require": { "types": "./sv/partialCheck.d.cts", "default": "./sv/partialCheck.cjs" } }, "./sv/rawCheck": { "import": { "types": "./sv/rawCheck.d.mts", "default": "./sv/rawCheck.mjs" }, "require": { "types": "./sv/rawCheck.d.cts", "default": "./sv/rawCheck.cjs" } }, "./sv/rawTransform": { "import": { "types": "./sv/rawTransform.d.mts", "default": "./sv/rawTransform.mjs" }, "require": { "types": "./sv/rawTransform.d.cts", "default": "./sv/rawTransform.cjs" } }, "./sv/regex": { "import": { "types": "./sv/regex.d.mts", "default": "./sv/regex.mjs" }, "require": { "types": "./sv/regex.d.cts", "default": "./sv/regex.cjs" } }, "./sv/rfcEmail": { "import": { "types": "./sv/rfcEmail.d.mts", "default": "./sv/rfcEmail.mjs" }, "require": { "types": "./sv/rfcEmail.d.cts", "default": "./sv/rfcEmail.cjs" } }, "./sv/safeInteger": { "import": { "types": "./sv/safeInteger.d.mts", "default": "./sv/safeInteger.mjs" }, "require": { "types": "./sv/safeInteger.d.cts", "default": "./sv/safeInteger.cjs" } }, "./sv/size": { "import": { "types": "./sv/size.d.mts", "default": "./sv/size.mjs" }, "require": { "types": "./sv/size.d.cts", "default": "./sv/size.cjs" } }, "./sv/slug": { "import": { "types": "./sv/slug.d.mts", "default": "./sv/slug.mjs" }, "require": { "types": "./sv/slug.d.cts", "default": "./sv/slug.cjs" } }, "./sv/someItem": { "import": { "types": "./sv/someItem.d.mts", "default": "./sv/someItem.mjs" }, "require": { "types": "./sv/someItem.d.cts", "default": "./sv/someItem.cjs" } }, "./sv/startsWith": { "import": { "types": "./sv/startsWith.d.mts", "default": "./sv/startsWith.mjs" }, "require": { "types": "./sv/startsWith.d.cts", "default": "./sv/startsWith.cjs" } }, "./sv/stringifyJson": { "import": { "types": "./sv/stringifyJson.d.mts", "default": "./sv/stringifyJson.mjs" }, "require": { "types": "./sv/stringifyJson.d.cts", "default": "./sv/stringifyJson.cjs" } }, "./sv/toBigint": { "import": { "types": "./sv/toBigint.d.mts", "default": "./sv/toBigint.mjs" }, "require": { "types": "./sv/toBigint.d.cts", "default": "./sv/toBigint.cjs" } }, "./sv/toDate": { "import": { "types": "./sv/toDate.d.mts", "default": "./sv/toDate.mjs" }, "require": { "types": "./sv/toDate.d.cts", "default": "./sv/toDate.cjs" } }, "./sv/toNumber": { "import": { "types": "./sv/toNumber.d.mts", "default": "./sv/toNumber.mjs" }, "require": { "types": "./sv/toNumber.d.cts", "default": "./sv/toNumber.cjs" } }, "./sv/toString": { "import": { "types": "./sv/toString.d.mts", "default": "./sv/toString.mjs" }, "require": { "types": "./sv/toString.d.cts", "default": "./sv/toString.cjs" } }, "./sv/ulid": { "import": { "types": "./sv/ulid.d.mts", "default": "./sv/ulid.mjs" }, "require": { "types": "./sv/ulid.d.cts", "default": "./sv/ulid.cjs" } }, "./sv/url": { "import": { "types": "./sv/url.d.mts", "default": "./sv/url.mjs" }, "require": { "types": "./sv/url.d.cts", "default": "./sv/url.cjs" } }, "./sv/uuid": { "import": { "types": "./sv/uuid.d.mts", "default": "./sv/uuid.mjs" }, "require": { "types": "./sv/uuid.d.cts", "default": "./sv/uuid.cjs" } }, "./sv/value": { "import": { "types": "./sv/value.d.mts", "default": "./sv/value.mjs" }, "require": { "types": "./sv/value.d.cts", "default": "./sv/value.cjs" } }, "./sv/values": { "import": { "types": "./sv/values.d.mts", "default": "./sv/values.mjs" }, "require": { "types": "./sv/values.d.cts", "default": "./sv/values.cjs" } }, "./sv/words": { "import": { "types": "./sv/words.d.mts", "default": "./sv/words.mjs" }, "require": { "types": "./sv/words.d.cts", "default": "./sv/words.cjs" } }, "./tr": { "import": { "types": "./tr/index.d.mts", "default": "./tr/index.mjs" }, "require": { "types": "./tr/index.d.cts", "default": "./tr/index.cjs" } }, "./tr/schema": { "import": { "types": "./tr/schema.d.mts", "default": "./tr/schema.mjs" }, "require": { "types": "./tr/schema.d.cts", "default": "./tr/schema.cjs" } }, "./tr/base64": { "import": { "types": "./tr/base64.d.mts", "default": "./tr/base64.mjs" }, "require": { "types": "./tr/base64.d.cts", "default": "./tr/base64.cjs" } }, "./tr/bic": { "import": { "types": "./tr/bic.d.mts", "default": "./tr/bic.mjs" }, "require": { "types": "./tr/bic.d.cts", "default": "./tr/bic.cjs" } }, "./tr/bytes": { "import": { "types": "./tr/bytes.d.mts", "default": "./tr/bytes.mjs" }, "require": { "types": "./tr/bytes.d.cts", "default": "./tr/bytes.cjs" } }, "./tr/check": { "import": { "types": "./tr/check.d.mts", "default": "./tr/check.mjs" }, "require": { "types": "./tr/check.d.cts", "default": "./tr/check.cjs" } }, "./tr/checkAsync": { "import": { "types": "./tr/checkAsync.d.mts", "default": "./tr/checkAsync.mjs" }, "require": { "types": "./tr/checkAsync.d.cts", "default": "./tr/checkAsync.cjs" } }, "./tr/checkItems": { "import": { "types": "./tr/checkItems.d.mts", "default": "./tr/checkItems.mjs" }, "require": { "types": "./tr/checkItems.d.cts", "default": "./tr/checkItems.cjs" } }, "./tr/checkItemsAsync": { "import": { "types": "./tr/checkItemsAsync.d.mts", "default": "./tr/checkItemsAsync.mjs" }, "require": { "types": "./tr/checkItemsAsync.d.cts", "default": "./tr/checkItemsAsync.cjs" } }, "./tr/creditCard": { "import": { "types": "./tr/creditCard.d.mts", "default": "./tr/creditCard.mjs" }, "require": { "types": "./tr/creditCard.d.cts", "default": "./tr/creditCard.cjs" } }, "./tr/cuid2": { "import": { "types": "./tr/cuid2.d.mts", "default": "./tr/cuid2.mjs" }, "require": { "types": "./tr/cuid2.d.cts", "default": "./tr/cuid2.cjs" } }, "./tr/decimal": { "import": { "types": "./tr/decimal.d.mts", "default": "./tr/decimal.mjs" }, "require": { "types": "./tr/decimal.d.cts", "default": "./tr/decimal.cjs" } }, "./tr/digits": { "import": { "types": "./tr/digits.d.mts", "default": "./tr/digits.mjs" }, "require": { "types": "./tr/digits.d.cts", "default": "./tr/digits.cjs" } }, "./tr/domain": { "import": { "types": "./tr/domain.d.mts", "default": "./tr/domain.mjs" }, "require": { "types": "./tr/domain.d.cts", "default": "./tr/domain.cjs" } }, "./tr/email": { "import": { "types": "./tr/email.d.mts", "default": "./tr/email.mjs" }, "require": { "types": "./tr/email.d.cts", "default": "./tr/email.cjs" } }, "./tr/emoji": { "import": { "types": "./tr/emoji.d.mts", "default": "./tr/emoji.mjs" }, "require": { "types": "./tr/emoji.d.cts", "default": "./tr/emoji.cjs" } }, "./tr/empty": { "import": { "types": "./tr/empty.d.mts", "default": "./tr/empty.mjs" }, "require": { "types": "./tr/empty.d.cts", "default": "./tr/empty.cjs" } }, "./tr/endsWith": { "import": { "types": "./tr/endsWith.d.mts", "default": "./tr/endsWith.mjs" }, "require": { "types": "./tr/endsWith.d.cts", "default": "./tr/endsWith.cjs" } }, "./tr/entries": { "import": { "types": "./tr/entries.d.mts", "default": "./tr/entries.mjs" }, "require": { "types": "./tr/entries.d.cts", "default": "./tr/entries.cjs" } }, "./tr/everyItem": { "import": { "types": "./tr/everyItem.d.mts", "default": "./tr/everyItem.mjs" }, "require": { "types": "./tr/everyItem.d.cts", "default": "./tr/everyItem.cjs" } }, "./tr/excludes": { "import": { "types": "./tr/excludes.d.mts", "default": "./tr/excludes.mjs" }, "require": { "types": "./tr/excludes.d.cts", "default": "./tr/excludes.cjs" } }, "./tr/finite": { "import": { "types": "./tr/finite.d.mts", "default": "./tr/finite.mjs" }, "require": { "types": "./tr/finite.d.cts", "default": "./tr/finite.cjs" } }, "./tr/graphemes": { "import": { "types": "./tr/graphemes.d.mts", "default": "./tr/graphemes.mjs" }, "require": { "types": "./tr/graphemes.d.cts", "default": "./tr/graphemes.cjs" } }, "./tr/gtValue": { "import": { "types": "./tr/gtValue.d.mts", "default": "./tr/gtValue.mjs" }, "require": { "types": "./tr/gtValue.d.cts", "default": "./tr/gtValue.cjs" } }, "./tr/guard": { "import": { "types": "./tr/guard.d.mts", "default": "./tr/guard.mjs" }, "require": { "types": "./tr/guard.d.cts", "default": "./tr/guard.cjs" } }, "./tr/hash": { "import": { "types": "./tr/hash.d.mts", "default": "./tr/hash.mjs" }, "require": { "types": "./tr/hash.d.cts", "default": "./tr/hash.cjs" } }, "./tr/hexadecimal": { "import": { "types": "./tr/hexadecimal.d.mts", "default": "./tr/hexadecimal.mjs" }, "require": { "types": "./tr/hexadecimal.d.cts", "default": "./tr/hexadecimal.cjs" } }, "./tr/hexColor": { "import": { "types": "./tr/hexColor.d.mts", "default": "./tr/hexColor.mjs" }, "require": { "types": "./tr/hexColor.d.cts", "default": "./tr/hexColor.cjs" } }, "./tr/imei": { "import": { "types": "./tr/imei.d.mts", "default": "./tr/imei.mjs" }, "require": { "types": "./tr/imei.d.cts", "default": "./tr/imei.cjs" } }, "./tr/includes": { "import": { "types": "./tr/includes.d.mts", "default": "./tr/includes.mjs" }, "require": { "types": "./tr/includes.d.cts", "default": "./tr/includes.cjs" } }, "./tr/integer": { "import": { "types": "./tr/integer.d.mts", "default": "./tr/integer.mjs" }, "require": { "types": "./tr/integer.d.cts", "default": "./tr/integer.cjs" } }, "./tr/ip": { "import": { "types": "./tr/ip.d.mts", "default": "./tr/ip.mjs" }, "require": { "types": "./tr/ip.d.cts", "default": "./tr/ip.cjs" } }, "./tr/ipv4": { "import": { "types": "./tr/ipv4.d.mts", "default": "./tr/ipv4.mjs" }, "require": { "types": "./tr/ipv4.d.cts", "default": "./tr/ipv4.cjs" } }, "./tr/ipv6": { "import": { "types": "./tr/ipv6.d.mts", "default": "./tr/ipv6.mjs" }, "require": { "types": "./tr/ipv6.d.cts", "default": "./tr/ipv6.cjs" } }, "./tr/isbn": { "import": { "types": "./tr/isbn.d.mts", "default": "./tr/isbn.mjs" }, "require": { "types": "./tr/isbn.d.cts", "default": "./tr/isbn.cjs" } }, "./tr/isoDate": { "import": { "types": "./tr/isoDate.d.mts", "default": "./tr/isoDate.mjs" }, "require": { "types": "./tr/isoDate.d.cts", "default": "./tr/isoDate.cjs" } }, "./tr/isoDateTime": { "import": { "types": "./tr/isoDateTime.d.mts", "default": "./tr/isoDateTime.mjs" }, "require": { "types": "./tr/isoDateTime.d.cts", "default": "./tr/isoDateTime.cjs" } }, "./tr/isoTime": { "import": { "types": "./tr/isoTime.d.mts", "default": "./tr/isoTime.mjs" }, "require": { "types": "./tr/isoTime.d.cts", "default": "./tr/isoTime.cjs" } }, "./tr/isoTimeSecond": { "import": { "types": "./tr/isoTimeSecond.d.mts", "default": "./tr/isoTimeSecond.mjs" }, "require": { "types": "./tr/isoTimeSecond.d.cts", "default": "./tr/isoTimeSecond.cjs" } }, "./tr/isoTimestamp": { "import": { "types": "./tr/isoTimestamp.d.mts", "default": "./tr/isoTimestamp.mjs" }, "require": { "types": "./tr/isoTimestamp.d.cts", "default": "./tr/isoTimestamp.cjs" } }, "./tr/isoWeek": { "import": { "types": "./tr/isoWeek.d.mts", "default": "./tr/isoWeek.mjs" }, "require": { "types": "./tr/isoWeek.d.cts", "default": "./tr/isoWeek.cjs" } }, "./tr/isrc": { "import": { "types": "./tr/isrc.d.mts", "default": "./tr/isrc.mjs" }, "require": { "types": "./tr/isrc.d.cts", "default": "./tr/isrc.cjs" } }, "./tr/jwsCompact": { "import": { "types": "./tr/jwsCompact.d.mts", "default": "./tr/jwsCompact.mjs" }, "require": { "types": "./tr/jwsCompact.d.cts", "default": "./tr/jwsCompact.cjs" } }, "./tr/length": { "import": { "types": "./tr/length.d.mts", "default": "./tr/length.mjs" }, "require": { "types": "./tr/length.d.cts", "default": "./tr/length.cjs" } }, "./tr/ltValue": { "import": { "types": "./tr/ltValue.d.mts", "default": "./tr/ltValue.mjs" }, "require": { "types": "./tr/ltValue.d.cts", "default": "./tr/ltValue.cjs" } }, "./tr/mac": { "import": { "types": "./tr/mac.d.mts", "default": "./tr/mac.mjs" }, "require": { "types": "./tr/mac.d.cts", "default": "./tr/mac.cjs" } }, "./tr/mac48": { "import": { "types": "./tr/mac48.d.mts", "default": "./tr/mac48.mjs" }, "require": { "types": "./tr/mac48.d.cts", "default": "./tr/mac48.cjs" } }, "./tr/mac64": { "import": { "types": "./tr/mac64.d.mts", "default": "./tr/mac64.mjs" }, "require": { "types": "./tr/mac64.d.cts", "default": "./tr/mac64.cjs" } }, "./tr/maxBytes": { "import": { "types": "./tr/maxBytes.d.mts", "default": "./tr/maxBytes.mjs" }, "require": { "types": "./tr/maxBytes.d.cts", "default": "./tr/maxBytes.cjs" } }, "./tr/maxEntries": { "import": { "types": "./tr/maxEntries.d.mts", "default": "./tr/maxEntries.mjs" }, "require": { "types": "./tr/maxEntries.d.cts", "default": "./tr/maxEntries.cjs" } }, "./tr/maxGraphemes": { "import": { "types": "./tr/maxGraphemes.d.mts", "default": "./tr/maxGraphemes.mjs" }, "require": { "types": "./tr/maxGraphemes.d.cts", "default": "./tr/maxGraphemes.cjs" } }, "./tr/maxLength": { "import": { "types": "./tr/maxLength.d.mts", "default": "./tr/maxLength.mjs" }, "require": { "types": "./tr/maxLength.d.cts", "default": "./tr/maxLength.cjs" } }, "./tr/maxSize": { "import": { "types": "./tr/maxSize.d.mts", "default": "./tr/maxSize.mjs" }, "require": { "types": "./tr/maxSize.d.cts", "default": "./tr/maxSize.cjs" } }, "./tr/maxValue": { "import": { "types": "./tr/maxValue.d.mts", "default": "./tr/maxValue.mjs" }, "require": { "types": "./tr/maxValue.d.cts", "default": "./tr/maxValue.cjs" } }, "./tr/maxWords": { "import": { "types": "./tr/maxWords.d.mts", "default": "./tr/maxWords.mjs" }, "require": { "types": "./tr/maxWords.d.cts", "default": "./tr/maxWords.cjs" } }, "./tr/mimeType": { "import": { "types": "./tr/mimeType.d.mts", "default": "./tr/mimeType.mjs" }, "require": { "types": "./tr/mimeType.d.cts", "default": "./tr/mimeType.cjs" } }, "./tr/minBytes": { "import": { "types": "./tr/minBytes.d.mts", "default": "./tr/minBytes.mjs" }, "require": { "types": "./tr/minBytes.d.cts", "default": "./tr/minBytes.cjs" } }, "./tr/minEntries": { "import": { "types": "./tr/minEntries.d.mts", "default": "./tr/minEntries.mjs" }, "require": { "types": "./tr/minEntries.d.cts", "default": "./tr/minEntries.cjs" } }, "./tr/minGraphemes": { "import": { "types": "./tr/minGraphemes.d.mts", "default": "./tr/minGraphemes.mjs" }, "require": { "types": "./tr/minGraphemes.d.cts", "default": "./tr/minGraphemes.cjs" } }, "./tr/minLength": { "import": { "types": "./tr/minLength.d.mts", "default": "./tr/minLength.mjs" }, "require": { "types": "./tr/minLength.d.cts", "default": "./tr/minLength.cjs" } }, "./tr/minSize": { "import": { "types": "./tr/minSize.d.mts", "default": "./tr/minSize.mjs" }, "require": { "types": "./tr/minSize.d.cts", "default": "./tr/minSize.cjs" } }, "./tr/minValue": { "import": { "types": "./tr/minValue.d.mts", "default": "./tr/minValue.mjs" }, "require": { "types": "./tr/minValue.d.cts", "default": "./tr/minValue.cjs" } }, "./tr/minWords": { "import": { "types": "./tr/minWords.d.mts", "default": "./tr/minWords.mjs" }, "require": { "types": "./tr/minWords.d.cts", "default": "./tr/minWords.cjs" } }, "./tr/multipleOf": { "import": { "types": "./tr/multipleOf.d.mts", "default": "./tr/multipleOf.mjs" }, "require": { "types": "./tr/multipleOf.d.cts", "default": "./tr/multipleOf.cjs" } }, "./tr/nanoid": { "import": { "types": "./tr/nanoid.d.mts", "default": "./tr/nanoid.mjs" }, "require": { "types": "./tr/nanoid.d.cts", "default": "./tr/nanoid.cjs" } }, "./tr/nonEmpty": { "import": { "types": "./tr/nonEmpty.d.mts", "default": "./tr/nonEmpty.mjs" }, "require": { "types": "./tr/nonEmpty.d.cts", "default": "./tr/nonEmpty.cjs" } }, "./tr/notBytes": { "import": { "types": "./tr/notBytes.d.mts", "default": "./tr/notBytes.mjs" }, "require": { "types": "./tr/notBytes.d.cts", "default": "./tr/notBytes.cjs" } }, "./tr/notEntries": { "import": { "types": "./tr/notEntries.d.mts", "default": "./tr/notEntries.mjs" }, "require": { "types": "./tr/notEntries.d.cts", "default": "./tr/notEntries.cjs" } }, "./tr/notGraphemes": { "import": { "types": "./tr/notGraphemes.d.mts", "default": "./tr/notGraphemes.mjs" }, "require": { "types": "./tr/notGraphemes.d.cts", "default": "./tr/notGraphemes.cjs" } }, "./tr/notLength": { "import": { "types": "./tr/notLength.d.mts", "default": "./tr/notLength.mjs" }, "require": { "types": "./tr/notLength.d.cts", "default": "./tr/notLength.cjs" } }, "./tr/notSize": { "import": { "types": "./tr/notSize.d.mts", "default": "./tr/notSize.mjs" }, "require": { "types": "./tr/notSize.d.cts", "default": "./tr/notSize.cjs" } }, "./tr/notValue": { "import": { "types": "./tr/notValue.d.mts", "default": "./tr/notValue.mjs" }, "require": { "types": "./tr/notValue.d.cts", "default": "./tr/notValue.cjs" } }, "./tr/notValues": { "import": { "types": "./tr/notValues.d.mts", "default": "./tr/notValues.mjs" }, "require": { "types": "./tr/notValues.d.cts", "default": "./tr/notValues.cjs" } }, "./tr/notWords": { "import": { "types": "./tr/notWords.d.mts", "default": "./tr/notWords.mjs" }, "require": { "types": "./tr/notWords.d.cts", "default": "./tr/notWords.cjs" } }, "./tr/octal": { "import": { "types": "./tr/octal.d.mts", "default": "./tr/octal.mjs" }, "require": { "types": "./tr/octal.d.cts", "default": "./tr/octal.cjs" } }, "./tr/parseBoolean": { "import": { "types": "./tr/parseBoolean.d.mts", "default": "./tr/parseBoolean.mjs" }, "require": { "types": "./tr/parseBoolean.d.cts", "default": "./tr/parseBoolean.cjs" } }, "./tr/parseJson": { "import": { "types": "./tr/parseJson.d.mts", "default": "./tr/parseJson.mjs" }, "require": { "types": "./tr/parseJson.d.cts", "default": "./tr/parseJson.cjs" } }, "./tr/partialCheck": { "import": { "types": "./tr/partialCheck.d.mts", "default": "./tr/partialCheck.mjs" }, "require": { "types": "./tr/partialCheck.d.cts", "default": "./tr/partialCheck.cjs" } }, "./tr/rawCheck": { "import": { "types": "./tr/rawCheck.d.mts", "default": "./tr/rawCheck.mjs" }, "require": { "types": "./tr/rawCheck.d.cts", "default": "./tr/rawCheck.cjs" } }, "./tr/rawTransform": { "import": { "types": "./tr/rawTransform.d.mts", "default": "./tr/rawTransform.mjs" }, "require": { "types": "./tr/rawTransform.d.cts", "default": "./tr/rawTransform.cjs" } }, "./tr/regex": { "import": { "types": "./tr/regex.d.mts", "default": "./tr/regex.mjs" }, "require": { "types": "./tr/regex.d.cts", "default": "./tr/regex.cjs" } }, "./tr/rfcEmail": { "import": { "types": "./tr/rfcEmail.d.mts", "default": "./tr/rfcEmail.mjs" }, "require": { "types": "./tr/rfcEmail.d.cts", "default": "./tr/rfcEmail.cjs" } }, "./tr/safeInteger": { "import": { "types": "./tr/safeInteger.d.mts", "default": "./tr/safeInteger.mjs" }, "require": { "types": "./tr/safeInteger.d.cts", "default": "./tr/safeInteger.cjs" } }, "./tr/size": { "import": { "types": "./tr/size.d.mts", "default": "./tr/size.mjs" }, "require": { "types": "./tr/size.d.cts", "default": "./tr/size.cjs" } }, "./tr/slug": { "import": { "types": "./tr/slug.d.mts", "default": "./tr/slug.mjs" }, "require": { "types": "./tr/slug.d.cts", "default": "./tr/slug.cjs" } }, "./tr/someItem": { "import": { "types": "./tr/someItem.d.mts", "default": "./tr/someItem.mjs" }, "require": { "types": "./tr/someItem.d.cts", "default": "./tr/someItem.cjs" } }, "./tr/startsWith": { "import": { "types": "./tr/startsWith.d.mts", "default": "./tr/startsWith.mjs" }, "require": { "types": "./tr/startsWith.d.cts", "default": "./tr/startsWith.cjs" } }, "./tr/stringifyJson": { "import": { "types": "./tr/stringifyJson.d.mts", "default": "./tr/stringifyJson.mjs" }, "require": { "types": "./tr/stringifyJson.d.cts", "default": "./tr/stringifyJson.cjs" } }, "./tr/toBigint": { "import": { "types": "./tr/toBigint.d.mts", "default": "./tr/toBigint.mjs" }, "require": { "types": "./tr/toBigint.d.cts", "default": "./tr/toBigint.cjs" } }, "./tr/toDate": { "import": { "types": "./tr/toDate.d.mts", "default": "./tr/toDate.mjs" }, "require": { "types": "./tr/toDate.d.cts", "default": "./tr/toDate.cjs" } }, "./tr/toNumber": { "import": { "types": "./tr/toNumber.d.mts", "default": "./tr/toNumber.mjs" }, "require": { "types": "./tr/toNumber.d.cts", "default": "./tr/toNumber.cjs" } }, "./tr/toString": { "import": { "types": "./tr/toString.d.mts", "default": "./tr/toString.mjs" }, "require": { "types": "./tr/toString.d.cts", "default": "./tr/toString.cjs" } }, "./tr/ulid": { "import": { "types": "./tr/ulid.d.mts", "default": "./tr/ulid.mjs" }, "require": { "types": "./tr/ulid.d.cts", "default": "./tr/ulid.cjs" } }, "./tr/url": { "import": { "types": "./tr/url.d.mts", "default": "./tr/url.mjs" }, "require": { "types": "./tr/url.d.cts", "default": "./tr/url.cjs" } }, "./tr/uuid": { "import": { "types": "./tr/uuid.d.mts", "default": "./tr/uuid.mjs" }, "require": { "types": "./tr/uuid.d.cts", "default": "./tr/uuid.cjs" } }, "./tr/value": { "import": { "types": "./tr/value.d.mts", "default": "./tr/value.mjs" }, "require": { "types": "./tr/value.d.cts", "default": "./tr/value.cjs" } }, "./tr/values": { "import": { "types": "./tr/values.d.mts", "default": "./tr/values.mjs" }, "require": { "types": "./tr/values.d.cts", "default": "./tr/values.cjs" } }, "./tr/words": { "import": { "types": "./tr/words.d.mts", "default": "./tr/words.mjs" }, "require": { "types": "./tr/words.d.cts", "default": "./tr/words.cjs" } }, "./uk": { "import": { "types": "./uk/index.d.mts", "default": "./uk/index.mjs" }, "require": { "types": "./uk/index.d.cts", "default": "./uk/index.cjs" } }, "./uk/schema": { "import": { "types": "./uk/schema.d.mts", "default": "./uk/schema.mjs" }, "require": { "types": "./uk/schema.d.cts", "default": "./uk/schema.cjs" } }, "./uk/base64": { "import": { "types": "./uk/base64.d.mts", "default": "./uk/base64.mjs" }, "require": { "types": "./uk/base64.d.cts", "default": "./uk/base64.cjs" } }, "./uk/bic": { "import": { "types": "./uk/bic.d.mts", "default": "./uk/bic.mjs" }, "require": { "types": "./uk/bic.d.cts", "default": "./uk/bic.cjs" } }, "./uk/bytes": { "import": { "types": "./uk/bytes.d.mts", "default": "./uk/bytes.mjs" }, "require": { "types": "./uk/bytes.d.cts", "default": "./uk/bytes.cjs" } }, "./uk/check": { "import": { "types": "./uk/check.d.mts", "default": "./uk/check.mjs" }, "require": { "types": "./uk/check.d.cts", "default": "./uk/check.cjs" } }, "./uk/checkAsync": { "import": { "types": "./uk/checkAsync.d.mts", "default": "./uk/checkAsync.mjs" }, "require": { "types": "./uk/checkAsync.d.cts", "default": "./uk/checkAsync.cjs" } }, "./uk/checkItems": { "import": { "types": "./uk/checkItems.d.mts", "default": "./uk/checkItems.mjs" }, "require": { "types": "./uk/checkItems.d.cts", "default": "./uk/checkItems.cjs" } }, "./uk/checkItemsAsync": { "import": { "types": "./uk/checkItemsAsync.d.mts", "default": "./uk/checkItemsAsync.mjs" }, "require": { "types": "./uk/checkItemsAsync.d.cts", "default": "./uk/checkItemsAsync.cjs" } }, "./uk/creditCard": { "import": { "types": "./uk/creditCard.d.mts", "default": "./uk/creditCard.mjs" }, "require": { "types": "./uk/creditCard.d.cts", "default": "./uk/creditCard.cjs" } }, "./uk/cuid2": { "import": { "types": "./uk/cuid2.d.mts", "default": "./uk/cuid2.mjs" }, "require": { "types": "./uk/cuid2.d.cts", "default": "./uk/cuid2.cjs" } }, "./uk/decimal": { "import": { "types": "./uk/decimal.d.mts", "default": "./uk/decimal.mjs" }, "require": { "types": "./uk/decimal.d.cts", "default": "./uk/decimal.cjs" } }, "./uk/digits": { "import": { "types": "./uk/digits.d.mts", "default": "./uk/digits.mjs" }, "require": { "types": "./uk/digits.d.cts", "default": "./uk/digits.cjs" } }, "./uk/domain": { "import": { "types": "./uk/domain.d.mts", "default": "./uk/domain.mjs" }, "require": { "types": "./uk/domain.d.cts", "default": "./uk/domain.cjs" } }, "./uk/email": { "import": { "types": "./uk/email.d.mts", "default": "./uk/email.mjs" }, "require": { "types": "./uk/email.d.cts", "default": "./uk/email.cjs" } }, "./uk/emoji": { "import": { "types": "./uk/emoji.d.mts", "default": "./uk/emoji.mjs" }, "require": { "types": "./uk/emoji.d.cts", "default": "./uk/emoji.cjs" } }, "./uk/empty": { "import": { "types": "./uk/empty.d.mts", "default": "./uk/empty.mjs" }, "require": { "types": "./uk/empty.d.cts", "default": "./uk/empty.cjs" } }, "./uk/endsWith": { "import": { "types": "./uk/endsWith.d.mts", "default": "./uk/endsWith.mjs" }, "require": { "types": "./uk/endsWith.d.cts", "default": "./uk/endsWith.cjs" } }, "./uk/entries": { "import": { "types": "./uk/entries.d.mts", "default": "./uk/entries.mjs" }, "require": { "types": "./uk/entries.d.cts", "default": "./uk/entries.cjs" } }, "./uk/everyItem": { "import": { "types": "./uk/everyItem.d.mts", "default": "./uk/everyItem.mjs" }, "require": { "types": "./uk/everyItem.d.cts", "default": "./uk/everyItem.cjs" } }, "./uk/excludes": { "import": { "types": "./uk/excludes.d.mts", "default": "./uk/excludes.mjs" }, "require": { "types": "./uk/excludes.d.cts", "default": "./uk/excludes.cjs" } }, "./uk/finite": { "import": { "types": "./uk/finite.d.mts", "default": "./uk/finite.mjs" }, "require": { "types": "./uk/finite.d.cts", "default": "./uk/finite.cjs" } }, "./uk/graphemes": { "import": { "types": "./uk/graphemes.d.mts", "default": "./uk/graphemes.mjs" }, "require": { "types": "./uk/graphemes.d.cts", "default": "./uk/graphemes.cjs" } }, "./uk/gtValue": { "import": { "types": "./uk/gtValue.d.mts", "default": "./uk/gtValue.mjs" }, "require": { "types": "./uk/gtValue.d.cts", "default": "./uk/gtValue.cjs" } }, "./uk/guard": { "import": { "types": "./uk/guard.d.mts", "default": "./uk/guard.mjs" }, "require": { "types": "./uk/guard.d.cts", "default": "./uk/guard.cjs" } }, "./uk/hash": { "import": { "types": "./uk/hash.d.mts", "default": "./uk/hash.mjs" }, "require": { "types": "./uk/hash.d.cts", "default": "./uk/hash.cjs" } }, "./uk/hexadecimal": { "import": { "types": "./uk/hexadecimal.d.mts", "default": "./uk/hexadecimal.mjs" }, "require": { "types": "./uk/hexadecimal.d.cts", "default": "./uk/hexadecimal.cjs" } }, "./uk/hexColor": { "import": { "types": "./uk/hexColor.d.mts", "default": "./uk/hexColor.mjs" }, "require": { "types": "./uk/hexColor.d.cts", "default": "./uk/hexColor.cjs" } }, "./uk/imei": { "import": { "types": "./uk/imei.d.mts", "default": "./uk/imei.mjs" }, "require": { "types": "./uk/imei.d.cts", "default": "./uk/imei.cjs" } }, "./uk/includes": { "import": { "types": "./uk/includes.d.mts", "default": "./uk/includes.mjs" }, "require": { "types": "./uk/includes.d.cts", "default": "./uk/includes.cjs" } }, "./uk/integer": { "import": { "types": "./uk/integer.d.mts", "default": "./uk/integer.mjs" }, "require": { "types": "./uk/integer.d.cts", "default": "./uk/integer.cjs" } }, "./uk/ip": { "import": { "types": "./uk/ip.d.mts", "default": "./uk/ip.mjs" }, "require": { "types": "./uk/ip.d.cts", "default": "./uk/ip.cjs" } }, "./uk/ipv4": { "import": { "types": "./uk/ipv4.d.mts", "default": "./uk/ipv4.mjs" }, "require": { "types": "./uk/ipv4.d.cts", "default": "./uk/ipv4.cjs" } }, "./uk/ipv6": { "import": { "types": "./uk/ipv6.d.mts", "default": "./uk/ipv6.mjs" }, "require": { "types": "./uk/ipv6.d.cts", "default": "./uk/ipv6.cjs" } }, "./uk/isbn": { "import": { "types": "./uk/isbn.d.mts", "default": "./uk/isbn.mjs" }, "require": { "types": "./uk/isbn.d.cts", "default": "./uk/isbn.cjs" } }, "./uk/isoDate": { "import": { "types": "./uk/isoDate.d.mts", "default": "./uk/isoDate.mjs" }, "require": { "types": "./uk/isoDate.d.cts", "default": "./uk/isoDate.cjs" } }, "./uk/isoDateTime": { "import": { "types": "./uk/isoDateTime.d.mts", "default": "./uk/isoDateTime.mjs" }, "require": { "types": "./uk/isoDateTime.d.cts", "default": "./uk/isoDateTime.cjs" } }, "./uk/isoTime": { "import": { "types": "./uk/isoTime.d.mts", "default": "./uk/isoTime.mjs" }, "require": { "types": "./uk/isoTime.d.cts", "default": "./uk/isoTime.cjs" } }, "./uk/isoTimeSecond": { "import": { "types": "./uk/isoTimeSecond.d.mts", "default": "./uk/isoTimeSecond.mjs" }, "require": { "types": "./uk/isoTimeSecond.d.cts", "default": "./uk/isoTimeSecond.cjs" } }, "./uk/isoTimestamp": { "import": { "types": "./uk/isoTimestamp.d.mts", "default": "./uk/isoTimestamp.mjs" }, "require": { "types": "./uk/isoTimestamp.d.cts", "default": "./uk/isoTimestamp.cjs" } }, "./uk/isoWeek": { "import": { "types": "./uk/isoWeek.d.mts", "default": "./uk/isoWeek.mjs" }, "require": { "types": "./uk/isoWeek.d.cts", "default": "./uk/isoWeek.cjs" } }, "./uk/isrc": { "import": { "types": "./uk/isrc.d.mts", "default": "./uk/isrc.mjs" }, "require": { "types": "./uk/isrc.d.cts", "default": "./uk/isrc.cjs" } }, "./uk/jwsCompact": { "import": { "types": "./uk/jwsCompact.d.mts", "default": "./uk/jwsCompact.mjs" }, "require": { "types": "./uk/jwsCompact.d.cts", "default": "./uk/jwsCompact.cjs" } }, "./uk/length": { "import": { "types": "./uk/length.d.mts", "default": "./uk/length.mjs" }, "require": { "types": "./uk/length.d.cts", "default": "./uk/length.cjs" } }, "./uk/ltValue": { "import": { "types": "./uk/ltValue.d.mts", "default": "./uk/ltValue.mjs" }, "require": { "types": "./uk/ltValue.d.cts", "default": "./uk/ltValue.cjs" } }, "./uk/mac": { "import": { "types": "./uk/mac.d.mts", "default": "./uk/mac.mjs" }, "require": { "types": "./uk/mac.d.cts", "default": "./uk/mac.cjs" } }, "./uk/mac48": { "import": { "types": "./uk/mac48.d.mts", "default": "./uk/mac48.mjs" }, "require": { "types": "./uk/mac48.d.cts", "default": "./uk/mac48.cjs" } }, "./uk/mac64": { "import": { "types": "./uk/mac64.d.mts", "default": "./uk/mac64.mjs" }, "require": { "types": "./uk/mac64.d.cts", "default": "./uk/mac64.cjs" } }, "./uk/maxBytes": { "import": { "types": "./uk/maxBytes.d.mts", "default": "./uk/maxBytes.mjs" }, "require": { "types": "./uk/maxBytes.d.cts", "default": "./uk/maxBytes.cjs" } }, "./uk/maxEntries": { "import": { "types": "./uk/maxEntries.d.mts", "default": "./uk/maxEntries.mjs" }, "require": { "types": "./uk/maxEntries.d.cts", "default": "./uk/maxEntries.cjs" } }, "./uk/maxGraphemes": { "import": { "types": "./uk/maxGraphemes.d.mts", "default": "./uk/maxGraphemes.mjs" }, "require": { "types": "./uk/maxGraphemes.d.cts", "default": "./uk/maxGraphemes.cjs" } }, "./uk/maxLength": { "import": { "types": "./uk/maxLength.d.mts", "default": "./uk/maxLength.mjs" }, "require": { "types": "./uk/maxLength.d.cts", "default": "./uk/maxLength.cjs" } }, "./uk/maxSize": { "import": { "types": "./uk/maxSize.d.mts", "default": "./uk/maxSize.mjs" }, "require": { "types": "./uk/maxSize.d.cts", "default": "./uk/maxSize.cjs" } }, "./uk/maxValue": { "import": { "types": "./uk/maxValue.d.mts", "default": "./uk/maxValue.mjs" }, "require": { "types": "./uk/maxValue.d.cts", "default": "./uk/maxValue.cjs" } }, "./uk/maxWords": { "import": { "types": "./uk/maxWords.d.mts", "default": "./uk/maxWords.mjs" }, "require": { "types": "./uk/maxWords.d.cts", "default": "./uk/maxWords.cjs" } }, "./uk/mimeType": { "import": { "types": "./uk/mimeType.d.mts", "default": "./uk/mimeType.mjs" }, "require": { "types": "./uk/mimeType.d.cts", "default": "./uk/mimeType.cjs" } }, "./uk/minBytes": { "import": { "types": "./uk/minBytes.d.mts", "default": "./uk/minBytes.mjs" }, "require": { "types": "./uk/minBytes.d.cts", "default": "./uk/minBytes.cjs" } }, "./uk/minEntries": { "import": { "types": "./uk/minEntries.d.mts", "default": "./uk/minEntries.mjs" }, "require": { "types": "./uk/minEntries.d.cts", "default": "./uk/minEntries.cjs" } }, "./uk/minGraphemes": { "import": { "types": "./uk/minGraphemes.d.mts", "default": "./uk/minGraphemes.mjs" }, "require": { "types": "./uk/minGraphemes.d.cts", "default": "./uk/minGraphemes.cjs" } }, "./uk/minLength": { "import": { "types": "./uk/minLength.d.mts", "default": "./uk/minLength.mjs" }, "require": { "types": "./uk/minLength.d.cts", "default": "./uk/minLength.cjs" } }, "./uk/minSize": { "import": { "types": "./uk/minSize.d.mts", "default": "./uk/minSize.mjs" }, "require": { "types": "./uk/minSize.d.cts", "default": "./uk/minSize.cjs" } }, "./uk/minValue": { "import": { "types": "./uk/minValue.d.mts", "default": "./uk/minValue.mjs" }, "require": { "types": "./uk/minValue.d.cts", "default": "./uk/minValue.cjs" } }, "./uk/minWords": { "import": { "types": "./uk/minWords.d.mts", "default": "./uk/minWords.mjs" }, "require": { "types": "./uk/minWords.d.cts", "default": "./uk/minWords.cjs" } }, "./uk/multipleOf": { "import": { "types": "./uk/multipleOf.d.mts", "default": "./uk/multipleOf.mjs" }, "require": { "types": "./uk/multipleOf.d.cts", "default": "./uk/multipleOf.cjs" } }, "./uk/nanoid": { "import": { "types": "./uk/nanoid.d.mts", "default": "./uk/nanoid.mjs" }, "require": { "types": "./uk/nanoid.d.cts", "default": "./uk/nanoid.cjs" } }, "./uk/nonEmpty": { "import": { "types": "./uk/nonEmpty.d.mts", "default": "./uk/nonEmpty.mjs" }, "require": { "types": "./uk/nonEmpty.d.cts", "default": "./uk/nonEmpty.cjs" } }, "./uk/notBytes": { "import": { "types": "./uk/notBytes.d.mts", "default": "./uk/notBytes.mjs" }, "require": { "types": "./uk/notBytes.d.cts", "default": "./uk/notBytes.cjs" } }, "./uk/notEntries": { "import": { "types": "./uk/notEntries.d.mts", "default": "./uk/notEntries.mjs" }, "require": { "types": "./uk/notEntries.d.cts", "default": "./uk/notEntries.cjs" } }, "./uk/notGraphemes": { "import": { "types": "./uk/notGraphemes.d.mts", "default": "./uk/notGraphemes.mjs" }, "require": { "types": "./uk/notGraphemes.d.cts", "default": "./uk/notGraphemes.cjs" } }, "./uk/notLength": { "import": { "types": "./uk/notLength.d.mts", "default": "./uk/notLength.mjs" }, "require": { "types": "./uk/notLength.d.cts", "default": "./uk/notLength.cjs" } }, "./uk/notSize": { "import": { "types": "./uk/notSize.d.mts", "default": "./uk/notSize.mjs" }, "require": { "types": "./uk/notSize.d.cts", "default": "./uk/notSize.cjs" } }, "./uk/notValue": { "import": { "types": "./uk/notValue.d.mts", "default": "./uk/notValue.mjs" }, "require": { "types": "./uk/notValue.d.cts", "default": "./uk/notValue.cjs" } }, "./uk/notValues": { "import": { "types": "./uk/notValues.d.mts", "default": "./uk/notValues.mjs" }, "require": { "types": "./uk/notValues.d.cts", "default": "./uk/notValues.cjs" } }, "./uk/notWords": { "import": { "types": "./uk/notWords.d.mts", "default": "./uk/notWords.mjs" }, "require": { "types": "./uk/notWords.d.cts", "default": "./uk/notWords.cjs" } }, "./uk/octal": { "import": { "types": "./uk/octal.d.mts", "default": "./uk/octal.mjs" }, "require": { "types": "./uk/octal.d.cts", "default": "./uk/octal.cjs" } }, "./uk/parseBoolean": { "import": { "types": "./uk/parseBoolean.d.mts", "default": "./uk/parseBoolean.mjs" }, "require": { "types": "./uk/parseBoolean.d.cts", "default": "./uk/parseBoolean.cjs" } }, "./uk/parseJson": { "import": { "types": "./uk/parseJson.d.mts", "default": "./uk/parseJson.mjs" }, "require": { "types": "./uk/parseJson.d.cts", "default": "./uk/parseJson.cjs" } }, "./uk/partialCheck": { "import": { "types": "./uk/partialCheck.d.mts", "default": "./uk/partialCheck.mjs" }, "require": { "types": "./uk/partialCheck.d.cts", "default": "./uk/partialCheck.cjs" } }, "./uk/rawCheck": { "import": { "types": "./uk/rawCheck.d.mts", "default": "./uk/rawCheck.mjs" }, "require": { "types": "./uk/rawCheck.d.cts", "default": "./uk/rawCheck.cjs" } }, "./uk/rawTransform": { "import": { "types": "./uk/rawTransform.d.mts", "default": "./uk/rawTransform.mjs" }, "require": { "types": "./uk/rawTransform.d.cts", "default": "./uk/rawTransform.cjs" } }, "./uk/regex": { "import": { "types": "./uk/regex.d.mts", "default": "./uk/regex.mjs" }, "require": { "types": "./uk/regex.d.cts", "default": "./uk/regex.cjs" } }, "./uk/rfcEmail": { "import": { "types": "./uk/rfcEmail.d.mts", "default": "./uk/rfcEmail.mjs" }, "require": { "types": "./uk/rfcEmail.d.cts", "default": "./uk/rfcEmail.cjs" } }, "./uk/safeInteger": { "import": { "types": "./uk/safeInteger.d.mts", "default": "./uk/safeInteger.mjs" }, "require": { "types": "./uk/safeInteger.d.cts", "default": "./uk/safeInteger.cjs" } }, "./uk/size": { "import": { "types": "./uk/size.d.mts", "default": "./uk/size.mjs" }, "require": { "types": "./uk/size.d.cts", "default": "./uk/size.cjs" } }, "./uk/slug": { "import": { "types": "./uk/slug.d.mts", "default": "./uk/slug.mjs" }, "require": { "types": "./uk/slug.d.cts", "default": "./uk/slug.cjs" } }, "./uk/someItem": { "import": { "types": "./uk/someItem.d.mts", "default": "./uk/someItem.mjs" }, "require": { "types": "./uk/someItem.d.cts", "default": "./uk/someItem.cjs" } }, "./uk/startsWith": { "import": { "types": "./uk/startsWith.d.mts", "default": "./uk/startsWith.mjs" }, "require": { "types": "./uk/startsWith.d.cts", "default": "./uk/startsWith.cjs" } }, "./uk/stringifyJson": { "import": { "types": "./uk/stringifyJson.d.mts", "default": "./uk/stringifyJson.mjs" }, "require": { "types": "./uk/stringifyJson.d.cts", "default": "./uk/stringifyJson.cjs" } }, "./uk/toBigint": { "import": { "types": "./uk/toBigint.d.mts", "default": "./uk/toBigint.mjs" }, "require": { "types": "./uk/toBigint.d.cts", "default": "./uk/toBigint.cjs" } }, "./uk/toDate": { "import": { "types": "./uk/toDate.d.mts", "default": "./uk/toDate.mjs" }, "require": { "types": "./uk/toDate.d.cts", "default": "./uk/toDate.cjs" } }, "./uk/toNumber": { "import": { "types": "./uk/toNumber.d.mts", "default": "./uk/toNumber.mjs" }, "require": { "types": "./uk/toNumber.d.cts", "default": "./uk/toNumber.cjs" } }, "./uk/toString": { "import": { "types": "./uk/toString.d.mts", "default": "./uk/toString.mjs" }, "require": { "types": "./uk/toString.d.cts", "default": "./uk/toString.cjs" } }, "./uk/ulid": { "import": { "types": "./uk/ulid.d.mts", "default": "./uk/ulid.mjs" }, "require": { "types": "./uk/ulid.d.cts", "default": "./uk/ulid.cjs" } }, "./uk/url": { "import": { "types": "./uk/url.d.mts", "default": "./uk/url.mjs" }, "require": { "types": "./uk/url.d.cts", "default": "./uk/url.cjs" } }, "./uk/uuid": { "import": { "types": "./uk/uuid.d.mts", "default": "./uk/uuid.mjs" }, "require": { "types": "./uk/uuid.d.cts", "default": "./uk/uuid.cjs" } }, "./uk/value": { "import": { "types": "./uk/value.d.mts", "default": "./uk/value.mjs" }, "require": { "types": "./uk/value.d.cts", "default": "./uk/value.cjs" } }, "./uk/values": { "import": { "types": "./uk/values.d.mts", "default": "./uk/values.mjs" }, "require": { "types": "./uk/values.d.cts", "default": "./uk/values.cjs" } }, "./uk/words": { "import": { "types": "./uk/words.d.mts", "default": "./uk/words.mjs" }, "require": { "types": "./uk/words.d.cts", "default": "./uk/words.cjs" } }, "./vi": { "import": { "types": "./vi/index.d.mts", "default": "./vi/index.mjs" }, "require": { "types": "./vi/index.d.cts", "default": "./vi/index.cjs" } }, "./vi/schema": { "import": { "types": "./vi/schema.d.mts", "default": "./vi/schema.mjs" }, "require": { "types": "./vi/schema.d.cts", "default": "./vi/schema.cjs" } }, "./vi/base64": { "import": { "types": "./vi/base64.d.mts", "default": "./vi/base64.mjs" }, "require": { "types": "./vi/base64.d.cts", "default": "./vi/base64.cjs" } }, "./vi/bic": { "import": { "types": "./vi/bic.d.mts", "default": "./vi/bic.mjs" }, "require": { "types": "./vi/bic.d.cts", "default": "./vi/bic.cjs" } }, "./vi/bytes": { "import": { "types": "./vi/bytes.d.mts", "default": "./vi/bytes.mjs" }, "require": { "types": "./vi/bytes.d.cts", "default": "./vi/bytes.cjs" } }, "./vi/check": { "import": { "types": "./vi/check.d.mts", "default": "./vi/check.mjs" }, "require": { "types": "./vi/check.d.cts", "default": "./vi/check.cjs" } }, "./vi/checkAsync": { "import": { "types": "./vi/checkAsync.d.mts", "default": "./vi/checkAsync.mjs" }, "require": { "types": "./vi/checkAsync.d.cts", "default": "./vi/checkAsync.cjs" } }, "./vi/checkItems": { "import": { "types": "./vi/checkItems.d.mts", "default": "./vi/checkItems.mjs" }, "require": { "types": "./vi/checkItems.d.cts", "default": "./vi/checkItems.cjs" } }, "./vi/checkItemsAsync": { "import": { "types": "./vi/checkItemsAsync.d.mts", "default": "./vi/checkItemsAsync.mjs" }, "require": { "types": "./vi/checkItemsAsync.d.cts", "default": "./vi/checkItemsAsync.cjs" } }, "./vi/creditCard": { "import": { "types": "./vi/creditCard.d.mts", "default": "./vi/creditCard.mjs" }, "require": { "types": "./vi/creditCard.d.cts", "default": "./vi/creditCard.cjs" } }, "./vi/cuid2": { "import": { "types": "./vi/cuid2.d.mts", "default": "./vi/cuid2.mjs" }, "require": { "types": "./vi/cuid2.d.cts", "default": "./vi/cuid2.cjs" } }, "./vi/decimal": { "import": { "types": "./vi/decimal.d.mts", "default": "./vi/decimal.mjs" }, "require": { "types": "./vi/decimal.d.cts", "default": "./vi/decimal.cjs" } }, "./vi/digits": { "import": { "types": "./vi/digits.d.mts", "default": "./vi/digits.mjs" }, "require": { "types": "./vi/digits.d.cts", "default": "./vi/digits.cjs" } }, "./vi/domain": { "import": { "types": "./vi/domain.d.mts", "default": "./vi/domain.mjs" }, "require": { "types": "./vi/domain.d.cts", "default": "./vi/domain.cjs" } }, "./vi/email": { "import": { "types": "./vi/email.d.mts", "default": "./vi/email.mjs" }, "require": { "types": "./vi/email.d.cts", "default": "./vi/email.cjs" } }, "./vi/emoji": { "import": { "types": "./vi/emoji.d.mts", "default": "./vi/emoji.mjs" }, "require": { "types": "./vi/emoji.d.cts", "default": "./vi/emoji.cjs" } }, "./vi/empty": { "import": { "types": "./vi/empty.d.mts", "default": "./vi/empty.mjs" }, "require": { "types": "./vi/empty.d.cts", "default": "./vi/empty.cjs" } }, "./vi/endsWith": { "import": { "types": "./vi/endsWith.d.mts", "default": "./vi/endsWith.mjs" }, "require": { "types": "./vi/endsWith.d.cts", "default": "./vi/endsWith.cjs" } }, "./vi/entries": { "import": { "types": "./vi/entries.d.mts", "default": "./vi/entries.mjs" }, "require": { "types": "./vi/entries.d.cts", "default": "./vi/entries.cjs" } }, "./vi/everyItem": { "import": { "types": "./vi/everyItem.d.mts", "default": "./vi/everyItem.mjs" }, "require": { "types": "./vi/everyItem.d.cts", "default": "./vi/everyItem.cjs" } }, "./vi/excludes": { "import": { "types": "./vi/excludes.d.mts", "default": "./vi/excludes.mjs" }, "require": { "types": "./vi/excludes.d.cts", "default": "./vi/excludes.cjs" } }, "./vi/finite": { "import": { "types": "./vi/finite.d.mts", "default": "./vi/finite.mjs" }, "require": { "types": "./vi/finite.d.cts", "default": "./vi/finite.cjs" } }, "./vi/graphemes": { "import": { "types": "./vi/graphemes.d.mts", "default": "./vi/graphemes.mjs" }, "require": { "types": "./vi/graphemes.d.cts", "default": "./vi/graphemes.cjs" } }, "./vi/gtValue": { "import": { "types": "./vi/gtValue.d.mts", "default": "./vi/gtValue.mjs" }, "require": { "types": "./vi/gtValue.d.cts", "default": "./vi/gtValue.cjs" } }, "./vi/guard": { "import": { "types": "./vi/guard.d.mts", "default": "./vi/guard.mjs" }, "require": { "types": "./vi/guard.d.cts", "default": "./vi/guard.cjs" } }, "./vi/hash": { "import": { "types": "./vi/hash.d.mts", "default": "./vi/hash.mjs" }, "require": { "types": "./vi/hash.d.cts", "default": "./vi/hash.cjs" } }, "./vi/hexadecimal": { "import": { "types": "./vi/hexadecimal.d.mts", "default": "./vi/hexadecimal.mjs" }, "require": { "types": "./vi/hexadecimal.d.cts", "default": "./vi/hexadecimal.cjs" } }, "./vi/hexColor": { "import": { "types": "./vi/hexColor.d.mts", "default": "./vi/hexColor.mjs" }, "require": { "types": "./vi/hexColor.d.cts", "default": "./vi/hexColor.cjs" } }, "./vi/imei": { "import": { "types": "./vi/imei.d.mts", "default": "./vi/imei.mjs" }, "require": { "types": "./vi/imei.d.cts", "default": "./vi/imei.cjs" } }, "./vi/includes": { "import": { "types": "./vi/includes.d.mts", "default": "./vi/includes.mjs" }, "require": { "types": "./vi/includes.d.cts", "default": "./vi/includes.cjs" } }, "./vi/integer": { "import": { "types": "./vi/integer.d.mts", "default": "./vi/integer.mjs" }, "require": { "types": "./vi/integer.d.cts", "default": "./vi/integer.cjs" } }, "./vi/ip": { "import": { "types": "./vi/ip.d.mts", "default": "./vi/ip.mjs" }, "require": { "types": "./vi/ip.d.cts", "default": "./vi/ip.cjs" } }, "./vi/ipv4": { "import": { "types": "./vi/ipv4.d.mts", "default": "./vi/ipv4.mjs" }, "require": { "types": "./vi/ipv4.d.cts", "default": "./vi/ipv4.cjs" } }, "./vi/ipv6": { "import": { "types": "./vi/ipv6.d.mts", "default": "./vi/ipv6.mjs" }, "require": { "types": "./vi/ipv6.d.cts", "default": "./vi/ipv6.cjs" } }, "./vi/isbn": { "import": { "types": "./vi/isbn.d.mts", "default": "./vi/isbn.mjs" }, "require": { "types": "./vi/isbn.d.cts", "default": "./vi/isbn.cjs" } }, "./vi/isoDate": { "import": { "types": "./vi/isoDate.d.mts", "default": "./vi/isoDate.mjs" }, "require": { "types": "./vi/isoDate.d.cts", "default": "./vi/isoDate.cjs" } }, "./vi/isoDateTime": { "import": { "types": "./vi/isoDateTime.d.mts", "default": "./vi/isoDateTime.mjs" }, "require": { "types": "./vi/isoDateTime.d.cts", "default": "./vi/isoDateTime.cjs" } }, "./vi/isoTime": { "import": { "types": "./vi/isoTime.d.mts", "default": "./vi/isoTime.mjs" }, "require": { "types": "./vi/isoTime.d.cts", "default": "./vi/isoTime.cjs" } }, "./vi/isoTimeSecond": { "import": { "types": "./vi/isoTimeSecond.d.mts", "default": "./vi/isoTimeSecond.mjs" }, "require": { "types": "./vi/isoTimeSecond.d.cts", "default": "./vi/isoTimeSecond.cjs" } }, "./vi/isoTimestamp": { "import": { "types": "./vi/isoTimestamp.d.mts", "default": "./vi/isoTimestamp.mjs" }, "require": { "types": "./vi/isoTimestamp.d.cts", "default": "./vi/isoTimestamp.cjs" } }, "./vi/isoWeek": { "import": { "types": "./vi/isoWeek.d.mts", "default": "./vi/isoWeek.mjs" }, "require": { "types": "./vi/isoWeek.d.cts", "default": "./vi/isoWeek.cjs" } }, "./vi/isrc": { "import": { "types": "./vi/isrc.d.mts", "default": "./vi/isrc.mjs" }, "require": { "types": "./vi/isrc.d.cts", "default": "./vi/isrc.cjs" } }, "./vi/jwsCompact": { "import": { "types": "./vi/jwsCompact.d.mts", "default": "./vi/jwsCompact.mjs" }, "require": { "types": "./vi/jwsCompact.d.cts", "default": "./vi/jwsCompact.cjs" } }, "./vi/length": { "import": { "types": "./vi/length.d.mts", "default": "./vi/length.mjs" }, "require": { "types": "./vi/length.d.cts", "default": "./vi/length.cjs" } }, "./vi/ltValue": { "import": { "types": "./vi/ltValue.d.mts", "default": "./vi/ltValue.mjs" }, "require": { "types": "./vi/ltValue.d.cts", "default": "./vi/ltValue.cjs" } }, "./vi/mac": { "import": { "types": "./vi/mac.d.mts", "default": "./vi/mac.mjs" }, "require": { "types": "./vi/mac.d.cts", "default": "./vi/mac.cjs" } }, "./vi/mac48": { "import": { "types": "./vi/mac48.d.mts", "default": "./vi/mac48.mjs" }, "require": { "types": "./vi/mac48.d.cts", "default": "./vi/mac48.cjs" } }, "./vi/mac64": { "import": { "types": "./vi/mac64.d.mts", "default": "./vi/mac64.mjs" }, "require": { "types": "./vi/mac64.d.cts", "default": "./vi/mac64.cjs" } }, "./vi/maxBytes": { "import": { "types": "./vi/maxBytes.d.mts", "default": "./vi/maxBytes.mjs" }, "require": { "types": "./vi/maxBytes.d.cts", "default": "./vi/maxBytes.cjs" } }, "./vi/maxEntries": { "import": { "types": "./vi/maxEntries.d.mts", "default": "./vi/maxEntries.mjs" }, "require": { "types": "./vi/maxEntries.d.cts", "default": "./vi/maxEntries.cjs" } }, "./vi/maxGraphemes": { "import": { "types": "./vi/maxGraphemes.d.mts", "default": "./vi/maxGraphemes.mjs" }, "require": { "types": "./vi/maxGraphemes.d.cts", "default": "./vi/maxGraphemes.cjs" } }, "./vi/maxLength": { "import": { "types": "./vi/maxLength.d.mts", "default": "./vi/maxLength.mjs" }, "require": { "types": "./vi/maxLength.d.cts", "default": "./vi/maxLength.cjs" } }, "./vi/maxSize": { "import": { "types": "./vi/maxSize.d.mts", "default": "./vi/maxSize.mjs" }, "require": { "types": "./vi/maxSize.d.cts", "default": "./vi/maxSize.cjs" } }, "./vi/maxValue": { "import": { "types": "./vi/maxValue.d.mts", "default": "./vi/maxValue.mjs" }, "require": { "types": "./vi/maxValue.d.cts", "default": "./vi/maxValue.cjs" } }, "./vi/maxWords": { "import": { "types": "./vi/maxWords.d.mts", "default": "./vi/maxWords.mjs" }, "require": { "types": "./vi/maxWords.d.cts", "default": "./vi/maxWords.cjs" } }, "./vi/mimeType": { "import": { "types": "./vi/mimeType.d.mts", "default": "./vi/mimeType.mjs" }, "require": { "types": "./vi/mimeType.d.cts", "default": "./vi/mimeType.cjs" } }, "./vi/minBytes": { "import": { "types": "./vi/minBytes.d.mts", "default": "./vi/minBytes.mjs" }, "require": { "types": "./vi/minBytes.d.cts", "default": "./vi/minBytes.cjs" } }, "./vi/minEntries": { "import": { "types": "./vi/minEntries.d.mts", "default": "./vi/minEntries.mjs" }, "require": { "types": "./vi/minEntries.d.cts", "default": "./vi/minEntries.cjs" } }, "./vi/minGraphemes": { "import": { "types": "./vi/minGraphemes.d.mts", "default": "./vi/minGraphemes.mjs" }, "require": { "types": "./vi/minGraphemes.d.cts", "default": "./vi/minGraphemes.cjs" } }, "./vi/minLength": { "import": { "types": "./vi/minLength.d.mts", "default": "./vi/minLength.mjs" }, "require": { "types": "./vi/minLength.d.cts", "default": "./vi/minLength.cjs" } }, "./vi/minSize": { "import": { "types": "./vi/minSize.d.mts", "default": "./vi/minSize.mjs" }, "require": { "types": "./vi/minSize.d.cts", "default": "./vi/minSize.cjs" } }, "./vi/minValue": { "import": { "types": "./vi/minValue.d.mts", "default": "./vi/minValue.mjs" }, "require": { "types": "./vi/minValue.d.cts", "default": "./vi/minValue.cjs" } }, "./vi/minWords": { "import": { "types": "./vi/minWords.d.mts", "default": "./vi/minWords.mjs" }, "require": { "types": "./vi/minWords.d.cts", "default": "./vi/minWords.cjs" } }, "./vi/multipleOf": { "import": { "types": "./vi/multipleOf.d.mts", "default": "./vi/multipleOf.mjs" }, "require": { "types": "./vi/multipleOf.d.cts", "default": "./vi/multipleOf.cjs" } }, "./vi/nanoid": { "import": { "types": "./vi/nanoid.d.mts", "default": "./vi/nanoid.mjs" }, "require": { "types": "./vi/nanoid.d.cts", "default": "./vi/nanoid.cjs" } }, "./vi/nonEmpty": { "import": { "types": "./vi/nonEmpty.d.mts", "default": "./vi/nonEmpty.mjs" }, "require": { "types": "./vi/nonEmpty.d.cts", "default": "./vi/nonEmpty.cjs" } }, "./vi/notBytes": { "import": { "types": "./vi/notBytes.d.mts", "default": "./vi/notBytes.mjs" }, "require": { "types": "./vi/notBytes.d.cts", "default": "./vi/notBytes.cjs" } }, "./vi/notEntries": { "import": { "types": "./vi/notEntries.d.mts", "default": "./vi/notEntries.mjs" }, "require": { "types": "./vi/notEntries.d.cts", "default": "./vi/notEntries.cjs" } }, "./vi/notGraphemes": { "import": { "types": "./vi/notGraphemes.d.mts", "default": "./vi/notGraphemes.mjs" }, "require": { "types": "./vi/notGraphemes.d.cts", "default": "./vi/notGraphemes.cjs" } }, "./vi/notLength": { "import": { "types": "./vi/notLength.d.mts", "default": "./vi/notLength.mjs" }, "require": { "types": "./vi/notLength.d.cts", "default": "./vi/notLength.cjs" } }, "./vi/notSize": { "import": { "types": "./vi/notSize.d.mts", "default": "./vi/notSize.mjs" }, "require": { "types": "./vi/notSize.d.cts", "default": "./vi/notSize.cjs" } }, "./vi/notValue": { "import": { "types": "./vi/notValue.d.mts", "default": "./vi/notValue.mjs" }, "require": { "types": "./vi/notValue.d.cts", "default": "./vi/notValue.cjs" } }, "./vi/notValues": { "import": { "types": "./vi/notValues.d.mts", "default": "./vi/notValues.mjs" }, "require": { "types": "./vi/notValues.d.cts", "default": "./vi/notValues.cjs" } }, "./vi/notWords": { "import": { "types": "./vi/notWords.d.mts", "default": "./vi/notWords.mjs" }, "require": { "types": "./vi/notWords.d.cts", "default": "./vi/notWords.cjs" } }, "./vi/octal": { "import": { "types": "./vi/octal.d.mts", "default": "./vi/octal.mjs" }, "require": { "types": "./vi/octal.d.cts", "default": "./vi/octal.cjs" } }, "./vi/parseBoolean": { "import": { "types": "./vi/parseBoolean.d.mts", "default": "./vi/parseBoolean.mjs" }, "require": { "types": "./vi/parseBoolean.d.cts", "default": "./vi/parseBoolean.cjs" } }, "./vi/parseJson": { "import": { "types": "./vi/parseJson.d.mts", "default": "./vi/parseJson.mjs" }, "require": { "types": "./vi/parseJson.d.cts", "default": "./vi/parseJson.cjs" } }, "./vi/partialCheck": { "import": { "types": "./vi/partialCheck.d.mts", "default": "./vi/partialCheck.mjs" }, "require": { "types": "./vi/partialCheck.d.cts", "default": "./vi/partialCheck.cjs" } }, "./vi/rawCheck": { "import": { "types": "./vi/rawCheck.d.mts", "default": "./vi/rawCheck.mjs" }, "require": { "types": "./vi/rawCheck.d.cts", "default": "./vi/rawCheck.cjs" } }, "./vi/rawTransform": { "import": { "types": "./vi/rawTransform.d.mts", "default": "./vi/rawTransform.mjs" }, "require": { "types": "./vi/rawTransform.d.cts", "default": "./vi/rawTransform.cjs" } }, "./vi/regex": { "import": { "types": "./vi/regex.d.mts", "default": "./vi/regex.mjs" }, "require": { "types": "./vi/regex.d.cts", "default": "./vi/regex.cjs" } }, "./vi/rfcEmail": { "import": { "types": "./vi/rfcEmail.d.mts", "default": "./vi/rfcEmail.mjs" }, "require": { "types": "./vi/rfcEmail.d.cts", "default": "./vi/rfcEmail.cjs" } }, "./vi/safeInteger": { "import": { "types": "./vi/safeInteger.d.mts", "default": "./vi/safeInteger.mjs" }, "require": { "types": "./vi/safeInteger.d.cts", "default": "./vi/safeInteger.cjs" } }, "./vi/size": { "import": { "types": "./vi/size.d.mts", "default": "./vi/size.mjs" }, "require": { "types": "./vi/size.d.cts", "default": "./vi/size.cjs" } }, "./vi/slug": { "import": { "types": "./vi/slug.d.mts", "default": "./vi/slug.mjs" }, "require": { "types": "./vi/slug.d.cts", "default": "./vi/slug.cjs" } }, "./vi/someItem": { "import": { "types": "./vi/someItem.d.mts", "default": "./vi/someItem.mjs" }, "require": { "types": "./vi/someItem.d.cts", "default": "./vi/someItem.cjs" } }, "./vi/startsWith": { "import": { "types": "./vi/startsWith.d.mts", "default": "./vi/startsWith.mjs" }, "require": { "types": "./vi/startsWith.d.cts", "default": "./vi/startsWith.cjs" } }, "./vi/stringifyJson": { "import": { "types": "./vi/stringifyJson.d.mts", "default": "./vi/stringifyJson.mjs" }, "require": { "types": "./vi/stringifyJson.d.cts", "default": "./vi/stringifyJson.cjs" } }, "./vi/toBigint": { "import": { "types": "./vi/toBigint.d.mts", "default": "./vi/toBigint.mjs" }, "require": { "types": "./vi/toBigint.d.cts", "default": "./vi/toBigint.cjs" } }, "./vi/toDate": { "import": { "types": "./vi/toDate.d.mts", "default": "./vi/toDate.mjs" }, "require": { "types": "./vi/toDate.d.cts", "default": "./vi/toDate.cjs" } }, "./vi/toNumber": { "import": { "types": "./vi/toNumber.d.mts", "default": "./vi/toNumber.mjs" }, "require": { "types": "./vi/toNumber.d.cts", "default": "./vi/toNumber.cjs" } }, "./vi/toString": { "import": { "types": "./vi/toString.d.mts", "default": "./vi/toString.mjs" }, "require": { "types": "./vi/toString.d.cts", "default": "./vi/toString.cjs" } }, "./vi/ulid": { "import": { "types": "./vi/ulid.d.mts", "default": "./vi/ulid.mjs" }, "require": { "types": "./vi/ulid.d.cts", "default": "./vi/ulid.cjs" } }, "./vi/url": { "import": { "types": "./vi/url.d.mts", "default": "./vi/url.mjs" }, "require": { "types": "./vi/url.d.cts", "default": "./vi/url.cjs" } }, "./vi/uuid": { "import": { "types": "./vi/uuid.d.mts", "default": "./vi/uuid.mjs" }, "require": { "types": "./vi/uuid.d.cts", "default": "./vi/uuid.cjs" } }, "./vi/value": { "import": { "types": "./vi/value.d.mts", "default": "./vi/value.mjs" }, "require": { "types": "./vi/value.d.cts", "default": "./vi/value.cjs" } }, "./vi/values": { "import": { "types": "./vi/values.d.mts", "default": "./vi/values.mjs" }, "require": { "types": "./vi/values.d.cts", "default": "./vi/values.cjs" } }, "./vi/words": { "import": { "types": "./vi/words.d.mts", "default": "./vi/words.mjs" }, "require": { "types": "./vi/words.d.cts", "default": "./vi/words.cjs" } }, "./zh-CN": { "import": { "types": "./zh-CN/index.d.mts", "default": "./zh-CN/index.mjs" }, "require": { "types": "./zh-CN/index.d.cts", "default": "./zh-CN/index.cjs" } }, "./zh-CN/schema": { "import": { "types": "./zh-CN/schema.d.mts", "default": "./zh-CN/schema.mjs" }, "require": { "types": "./zh-CN/schema.d.cts", "default": "./zh-CN/schema.cjs" } }, "./zh-CN/base64": { "import": { "types": "./zh-CN/base64.d.mts", "default": "./zh-CN/base64.mjs" }, "require": { "types": "./zh-CN/base64.d.cts", "default": "./zh-CN/base64.cjs" } }, "./zh-CN/bic": { "import": { "types": "./zh-CN/bic.d.mts", "default": "./zh-CN/bic.mjs" }, "require": { "types": "./zh-CN/bic.d.cts", "default": "./zh-CN/bic.cjs" } }, "./zh-CN/bytes": { "import": { "types": "./zh-CN/bytes.d.mts", "default": "./zh-CN/bytes.mjs" }, "require": { "types": "./zh-CN/bytes.d.cts", "default": "./zh-CN/bytes.cjs" } }, "./zh-CN/check": { "import": { "types": "./zh-CN/check.d.mts", "default": "./zh-CN/check.mjs" }, "require": { "types": "./zh-CN/check.d.cts", "default": "./zh-CN/check.cjs" } }, "./zh-CN/checkAsync": { "import": { "types": "./zh-CN/checkAsync.d.mts", "default": "./zh-CN/checkAsync.mjs" }, "require": { "types": "./zh-CN/checkAsync.d.cts", "default": "./zh-CN/checkAsync.cjs" } }, "./zh-CN/checkItems": { "import": { "types": "./zh-CN/checkItems.d.mts", "default": "./zh-CN/checkItems.mjs" }, "require": { "types": "./zh-CN/checkItems.d.cts", "default": "./zh-CN/checkItems.cjs" } }, "./zh-CN/checkItemsAsync": { "import": { "types": "./zh-CN/checkItemsAsync.d.mts", "default": "./zh-CN/checkItemsAsync.mjs" }, "require": { "types": "./zh-CN/checkItemsAsync.d.cts", "default": "./zh-CN/checkItemsAsync.cjs" } }, "./zh-CN/creditCard": { "import": { "types": "./zh-CN/creditCard.d.mts", "default": "./zh-CN/creditCard.mjs" }, "require": { "types": "./zh-CN/creditCard.d.cts", "default": "./zh-CN/creditCard.cjs" } }, "./zh-CN/cuid2": { "import": { "types": "./zh-CN/cuid2.d.mts", "default": "./zh-CN/cuid2.mjs" }, "require": { "types": "./zh-CN/cuid2.d.cts", "default": "./zh-CN/cuid2.cjs" } }, "./zh-CN/decimal": { "import": { "types": "./zh-CN/decimal.d.mts", "default": "./zh-CN/decimal.mjs" }, "require": { "types": "./zh-CN/decimal.d.cts", "default": "./zh-CN/decimal.cjs" } }, "./zh-CN/digits": { "import": { "types": "./zh-CN/digits.d.mts", "default": "./zh-CN/digits.mjs" }, "require": { "types": "./zh-CN/digits.d.cts", "default": "./zh-CN/digits.cjs" } }, "./zh-CN/domain": { "import": { "types": "./zh-CN/domain.d.mts", "default": "./zh-CN/domain.mjs" }, "require": { "types": "./zh-CN/domain.d.cts", "default": "./zh-CN/domain.cjs" } }, "./zh-CN/email": { "import": { "types": "./zh-CN/email.d.mts", "default": "./zh-CN/email.mjs" }, "require": { "types": "./zh-CN/email.d.cts", "default": "./zh-CN/email.cjs" } }, "./zh-CN/emoji": { "import": { "types": "./zh-CN/emoji.d.mts", "default": "./zh-CN/emoji.mjs" }, "require": { "types": "./zh-CN/emoji.d.cts", "default": "./zh-CN/emoji.cjs" } }, "./zh-CN/empty": { "import": { "types": "./zh-CN/empty.d.mts", "default": "./zh-CN/empty.mjs" }, "require": { "types": "./zh-CN/empty.d.cts", "default": "./zh-CN/empty.cjs" } }, "./zh-CN/endsWith": { "import": { "types": "./zh-CN/endsWith.d.mts", "default": "./zh-CN/endsWith.mjs" }, "require": { "types": "./zh-CN/endsWith.d.cts", "default": "./zh-CN/endsWith.cjs" } }, "./zh-CN/entries": { "import": { "types": "./zh-CN/entries.d.mts", "default": "./zh-CN/entries.mjs" }, "require": { "types": "./zh-CN/entries.d.cts", "default": "./zh-CN/entries.cjs" } }, "./zh-CN/everyItem": { "import": { "types": "./zh-CN/everyItem.d.mts", "default": "./zh-CN/everyItem.mjs" }, "require": { "types": "./zh-CN/everyItem.d.cts", "default": "./zh-CN/everyItem.cjs" } }, "./zh-CN/excludes": { "import": { "types": "./zh-CN/excludes.d.mts", "default": "./zh-CN/excludes.mjs" }, "require": { "types": "./zh-CN/excludes.d.cts", "default": "./zh-CN/excludes.cjs" } }, "./zh-CN/finite": { "import": { "types": "./zh-CN/finite.d.mts", "default": "./zh-CN/finite.mjs" }, "require": { "types": "./zh-CN/finite.d.cts", "default": "./zh-CN/finite.cjs" } }, "./zh-CN/graphemes": { "import": { "types": "./zh-CN/graphemes.d.mts", "default": "./zh-CN/graphemes.mjs" }, "require": { "types": "./zh-CN/graphemes.d.cts", "default": "./zh-CN/graphemes.cjs" } }, "./zh-CN/gtValue": { "import": { "types": "./zh-CN/gtValue.d.mts", "default": "./zh-CN/gtValue.mjs" }, "require": { "types": "./zh-CN/gtValue.d.cts", "default": "./zh-CN/gtValue.cjs" } }, "./zh-CN/guard": { "import": { "types": "./zh-CN/guard.d.mts", "default": "./zh-CN/guard.mjs" }, "require": { "types": "./zh-CN/guard.d.cts", "default": "./zh-CN/guard.cjs" } }, "./zh-CN/hash": { "import": { "types": "./zh-CN/hash.d.mts", "default": "./zh-CN/hash.mjs" }, "require": { "types": "./zh-CN/hash.d.cts", "default": "./zh-CN/hash.cjs" } }, "./zh-CN/hexadecimal": { "import": { "types": "./zh-CN/hexadecimal.d.mts", "default": "./zh-CN/hexadecimal.mjs" }, "require": { "types": "./zh-CN/hexadecimal.d.cts", "default": "./zh-CN/hexadecimal.cjs" } }, "./zh-CN/hexColor": { "import": { "types": "./zh-CN/hexColor.d.mts", "default": "./zh-CN/hexColor.mjs" }, "require": { "types": "./zh-CN/hexColor.d.cts", "default": "./zh-CN/hexColor.cjs" } }, "./zh-CN/imei": { "import": { "types": "./zh-CN/imei.d.mts", "default": "./zh-CN/imei.mjs" }, "require": { "types": "./zh-CN/imei.d.cts", "default": "./zh-CN/imei.cjs" } }, "./zh-CN/includes": { "import": { "types": "./zh-CN/includes.d.mts", "default": "./zh-CN/includes.mjs" }, "require": { "types": "./zh-CN/includes.d.cts", "default": "./zh-CN/includes.cjs" } }, "./zh-CN/integer": { "import": { "types": "./zh-CN/integer.d.mts", "default": "./zh-CN/integer.mjs" }, "require": { "types": "./zh-CN/integer.d.cts", "default": "./zh-CN/integer.cjs" } }, "./zh-CN/ip": { "import": { "types": "./zh-CN/ip.d.mts", "default": "./zh-CN/ip.mjs" }, "require": { "types": "./zh-CN/ip.d.cts", "default": "./zh-CN/ip.cjs" } }, "./zh-CN/ipv4": { "import": { "types": "./zh-CN/ipv4.d.mts", "default": "./zh-CN/ipv4.mjs" }, "require": { "types": "./zh-CN/ipv4.d.cts", "default": "./zh-CN/ipv4.cjs" } }, "./zh-CN/ipv6": { "import": { "types": "./zh-CN/ipv6.d.mts", "default": "./zh-CN/ipv6.mjs" }, "require": { "types": "./zh-CN/ipv6.d.cts", "default": "./zh-CN/ipv6.cjs" } }, "./zh-CN/isbn": { "import": { "types": "./zh-CN/isbn.d.mts", "default": "./zh-CN/isbn.mjs" }, "require": { "types": "./zh-CN/isbn.d.cts", "default": "./zh-CN/isbn.cjs" } }, "./zh-CN/isoDate": { "import": { "types": "./zh-CN/isoDate.d.mts", "default": "./zh-CN/isoDate.mjs" }, "require": { "types": "./zh-CN/isoDate.d.cts", "default": "./zh-CN/isoDate.cjs" } }, "./zh-CN/isoDateTime": { "import": { "types": "./zh-CN/isoDateTime.d.mts", "default": "./zh-CN/isoDateTime.mjs" }, "require": { "types": "./zh-CN/isoDateTime.d.cts", "default": "./zh-CN/isoDateTime.cjs" } }, "./zh-CN/isoTime": { "import": { "types": "./zh-CN/isoTime.d.mts", "default": "./zh-CN/isoTime.mjs" }, "require": { "types": "./zh-CN/isoTime.d.cts", "default": "./zh-CN/isoTime.cjs" } }, "./zh-CN/isoTimeSecond": { "import": { "types": "./zh-CN/isoTimeSecond.d.mts", "default": "./zh-CN/isoTimeSecond.mjs" }, "require": { "types": "./zh-CN/isoTimeSecond.d.cts", "default": "./zh-CN/isoTimeSecond.cjs" } }, "./zh-CN/isoTimestamp": { "import": { "types": "./zh-CN/isoTimestamp.d.mts", "default": "./zh-CN/isoTimestamp.mjs" }, "require": { "types": "./zh-CN/isoTimestamp.d.cts", "default": "./zh-CN/isoTimestamp.cjs" } }, "./zh-CN/isoWeek": { "import": { "types": "./zh-CN/isoWeek.d.mts", "default": "./zh-CN/isoWeek.mjs" }, "require": { "types": "./zh-CN/isoWeek.d.cts", "default": "./zh-CN/isoWeek.cjs" } }, "./zh-CN/isrc": { "import": { "types": "./zh-CN/isrc.d.mts", "default": "./zh-CN/isrc.mjs" }, "require": { "types": "./zh-CN/isrc.d.cts", "default": "./zh-CN/isrc.cjs" } }, "./zh-CN/jwsCompact": { "import": { "types": "./zh-CN/jwsCompact.d.mts", "default": "./zh-CN/jwsCompact.mjs" }, "require": { "types": "./zh-CN/jwsCompact.d.cts", "default": "./zh-CN/jwsCompact.cjs" } }, "./zh-CN/length": { "import": { "types": "./zh-CN/length.d.mts", "default": "./zh-CN/length.mjs" }, "require": { "types": "./zh-CN/length.d.cts", "default": "./zh-CN/length.cjs" } }, "./zh-CN/ltValue": { "import": { "types": "./zh-CN/ltValue.d.mts", "default": "./zh-CN/ltValue.mjs" }, "require": { "types": "./zh-CN/ltValue.d.cts", "default": "./zh-CN/ltValue.cjs" } }, "./zh-CN/mac": { "import": { "types": "./zh-CN/mac.d.mts", "default": "./zh-CN/mac.mjs" }, "require": { "types": "./zh-CN/mac.d.cts", "default": "./zh-CN/mac.cjs" } }, "./zh-CN/mac48": { "import": { "types": "./zh-CN/mac48.d.mts", "default": "./zh-CN/mac48.mjs" }, "require": { "types": "./zh-CN/mac48.d.cts", "default": "./zh-CN/mac48.cjs" } }, "./zh-CN/mac64": { "import": { "types": "./zh-CN/mac64.d.mts", "default": "./zh-CN/mac64.mjs" }, "require": { "types": "./zh-CN/mac64.d.cts", "default": "./zh-CN/mac64.cjs" } }, "./zh-CN/maxBytes": { "import": { "types": "./zh-CN/maxBytes.d.mts", "default": "./zh-CN/maxBytes.mjs" }, "require": { "types": "./zh-CN/maxBytes.d.cts", "default": "./zh-CN/maxBytes.cjs" } }, "./zh-CN/maxEntries": { "import": { "types": "./zh-CN/maxEntries.d.mts", "default": "./zh-CN/maxEntries.mjs" }, "require": { "types": "./zh-CN/maxEntries.d.cts", "default": "./zh-CN/maxEntries.cjs" } }, "./zh-CN/maxGraphemes": { "import": { "types": "./zh-CN/maxGraphemes.d.mts", "default": "./zh-CN/maxGraphemes.mjs" }, "require": { "types": "./zh-CN/maxGraphemes.d.cts", "default": "./zh-CN/maxGraphemes.cjs" } }, "./zh-CN/maxLength": { "import": { "types": "./zh-CN/maxLength.d.mts", "default": "./zh-CN/maxLength.mjs" }, "require": { "types": "./zh-CN/maxLength.d.cts", "default": "./zh-CN/maxLength.cjs" } }, "./zh-CN/maxSize": { "import": { "types": "./zh-CN/maxSize.d.mts", "default": "./zh-CN/maxSize.mjs" }, "require": { "types": "./zh-CN/maxSize.d.cts", "default": "./zh-CN/maxSize.cjs" } }, "./zh-CN/maxValue": { "import": { "types": "./zh-CN/maxValue.d.mts", "default": "./zh-CN/maxValue.mjs" }, "require": { "types": "./zh-CN/maxValue.d.cts", "default": "./zh-CN/maxValue.cjs" } }, "./zh-CN/maxWords": { "import": { "types": "./zh-CN/maxWords.d.mts", "default": "./zh-CN/maxWords.mjs" }, "require": { "types": "./zh-CN/maxWords.d.cts", "default": "./zh-CN/maxWords.cjs" } }, "./zh-CN/mimeType": { "import": { "types": "./zh-CN/mimeType.d.mts", "default": "./zh-CN/mimeType.mjs" }, "require": { "types": "./zh-CN/mimeType.d.cts", "default": "./zh-CN/mimeType.cjs" } }, "./zh-CN/minBytes": { "import": { "types": "./zh-CN/minBytes.d.mts", "default": "./zh-CN/minBytes.mjs" }, "require": { "types": "./zh-CN/minBytes.d.cts", "default": "./zh-CN/minBytes.cjs" } }, "./zh-CN/minEntries": { "import": { "types": "./zh-CN/minEntries.d.mts", "default": "./zh-CN/minEntries.mjs" }, "require": { "types": "./zh-CN/minEntries.d.cts", "default": "./zh-CN/minEntries.cjs" } }, "./zh-CN/minGraphemes": { "import": { "types": "./zh-CN/minGraphemes.d.mts", "default": "./zh-CN/minGraphemes.mjs" }, "require": { "types": "./zh-CN/minGraphemes.d.cts", "default": "./zh-CN/minGraphemes.cjs" } }, "./zh-CN/minLength": { "import": { "types": "./zh-CN/minLength.d.mts", "default": "./zh-CN/minLength.mjs" }, "require": { "types": "./zh-CN/minLength.d.cts", "default": "./zh-CN/minLength.cjs" } }, "./zh-CN/minSize": { "import": { "types": "./zh-CN/minSize.d.mts", "default": "./zh-CN/minSize.mjs" }, "require": { "types": "./zh-CN/minSize.d.cts", "default": "./zh-CN/minSize.cjs" } }, "./zh-CN/minValue": { "import": { "types": "./zh-CN/minValue.d.mts", "default": "./zh-CN/minValue.mjs" }, "require": { "types": "./zh-CN/minValue.d.cts", "default": "./zh-CN/minValue.cjs" } }, "./zh-CN/minWords": { "import": { "types": "./zh-CN/minWords.d.mts", "default": "./zh-CN/minWords.mjs" }, "require": { "types": "./zh-CN/minWords.d.cts", "default": "./zh-CN/minWords.cjs" } }, "./zh-CN/multipleOf": { "import": { "types": "./zh-CN/multipleOf.d.mts", "default": "./zh-CN/multipleOf.mjs" }, "require": { "types": "./zh-CN/multipleOf.d.cts", "default": "./zh-CN/multipleOf.cjs" } }, "./zh-CN/nanoid": { "import": { "types": "./zh-CN/nanoid.d.mts", "default": "./zh-CN/nanoid.mjs" }, "require": { "types": "./zh-CN/nanoid.d.cts", "default": "./zh-CN/nanoid.cjs" } }, "./zh-CN/nonEmpty": { "import": { "types": "./zh-CN/nonEmpty.d.mts", "default": "./zh-CN/nonEmpty.mjs" }, "require": { "types": "./zh-CN/nonEmpty.d.cts", "default": "./zh-CN/nonEmpty.cjs" } }, "./zh-CN/notBytes": { "import": { "types": "./zh-CN/notBytes.d.mts", "default": "./zh-CN/notBytes.mjs" }, "require": { "types": "./zh-CN/notBytes.d.cts", "default": "./zh-CN/notBytes.cjs" } }, "./zh-CN/notEntries": { "import": { "types": "./zh-CN/notEntries.d.mts", "default": "./zh-CN/notEntries.mjs" }, "require": { "types": "./zh-CN/notEntries.d.cts", "default": "./zh-CN/notEntries.cjs" } }, "./zh-CN/notGraphemes": { "import": { "types": "./zh-CN/notGraphemes.d.mts", "default": "./zh-CN/notGraphemes.mjs" }, "require": { "types": "./zh-CN/notGraphemes.d.cts", "default": "./zh-CN/notGraphemes.cjs" } }, "./zh-CN/notLength": { "import": { "types": "./zh-CN/notLength.d.mts", "default": "./zh-CN/notLength.mjs" }, "require": { "types": "./zh-CN/notLength.d.cts", "default": "./zh-CN/notLength.cjs" } }, "./zh-CN/notSize": { "import": { "types": "./zh-CN/notSize.d.mts", "default": "./zh-CN/notSize.mjs" }, "require": { "types": "./zh-CN/notSize.d.cts", "default": "./zh-CN/notSize.cjs" } }, "./zh-CN/notValue": { "import": { "types": "./zh-CN/notValue.d.mts", "default": "./zh-CN/notValue.mjs" }, "require": { "types": "./zh-CN/notValue.d.cts", "default": "./zh-CN/notValue.cjs" } }, "./zh-CN/notValues": { "import": { "types": "./zh-CN/notValues.d.mts", "default": "./zh-CN/notValues.mjs" }, "require": { "types": "./zh-CN/notValues.d.cts", "default": "./zh-CN/notValues.cjs" } }, "./zh-CN/notWords": { "import": { "types": "./zh-CN/notWords.d.mts", "default": "./zh-CN/notWords.mjs" }, "require": { "types": "./zh-CN/notWords.d.cts", "default": "./zh-CN/notWords.cjs" } }, "./zh-CN/octal": { "import": { "types": "./zh-CN/octal.d.mts", "default": "./zh-CN/octal.mjs" }, "require": { "types": "./zh-CN/octal.d.cts", "default": "./zh-CN/octal.cjs" } }, "./zh-CN/parseBoolean": { "import": { "types": "./zh-CN/parseBoolean.d.mts", "default": "./zh-CN/parseBoolean.mjs" }, "require": { "types": "./zh-CN/parseBoolean.d.cts", "default": "./zh-CN/parseBoolean.cjs" } }, "./zh-CN/parseJson": { "import": { "types": "./zh-CN/parseJson.d.mts", "default": "./zh-CN/parseJson.mjs" }, "require": { "types": "./zh-CN/parseJson.d.cts", "default": "./zh-CN/parseJson.cjs" } }, "./zh-CN/partialCheck": { "import": { "types": "./zh-CN/partialCheck.d.mts", "default": "./zh-CN/partialCheck.mjs" }, "require": { "types": "./zh-CN/partialCheck.d.cts", "default": "./zh-CN/partialCheck.cjs" } }, "./zh-CN/rawCheck": { "import": { "types": "./zh-CN/rawCheck.d.mts", "default": "./zh-CN/rawCheck.mjs" }, "require": { "types": "./zh-CN/rawCheck.d.cts", "default": "./zh-CN/rawCheck.cjs" } }, "./zh-CN/rawTransform": { "import": { "types": "./zh-CN/rawTransform.d.mts", "default": "./zh-CN/rawTransform.mjs" }, "require": { "types": "./zh-CN/rawTransform.d.cts", "default": "./zh-CN/rawTransform.cjs" } }, "./zh-CN/regex": { "import": { "types": "./zh-CN/regex.d.mts", "default": "./zh-CN/regex.mjs" }, "require": { "types": "./zh-CN/regex.d.cts", "default": "./zh-CN/regex.cjs" } }, "./zh-CN/rfcEmail": { "import": { "types": "./zh-CN/rfcEmail.d.mts", "default": "./zh-CN/rfcEmail.mjs" }, "require": { "types": "./zh-CN/rfcEmail.d.cts", "default": "./zh-CN/rfcEmail.cjs" } }, "./zh-CN/safeInteger": { "import": { "types": "./zh-CN/safeInteger.d.mts", "default": "./zh-CN/safeInteger.mjs" }, "require": { "types": "./zh-CN/safeInteger.d.cts", "default": "./zh-CN/safeInteger.cjs" } }, "./zh-CN/size": { "import": { "types": "./zh-CN/size.d.mts", "default": "./zh-CN/size.mjs" }, "require": { "types": "./zh-CN/size.d.cts", "default": "./zh-CN/size.cjs" } }, "./zh-CN/slug": { "import": { "types": "./zh-CN/slug.d.mts", "default": "./zh-CN/slug.mjs" }, "require": { "types": "./zh-CN/slug.d.cts", "default": "./zh-CN/slug.cjs" } }, "./zh-CN/someItem": { "import": { "types": "./zh-CN/someItem.d.mts", "default": "./zh-CN/someItem.mjs" }, "require": { "types": "./zh-CN/someItem.d.cts", "default": "./zh-CN/someItem.cjs" } }, "./zh-CN/startsWith": { "import": { "types": "./zh-CN/startsWith.d.mts", "default": "./zh-CN/startsWith.mjs" }, "require": { "types": "./zh-CN/startsWith.d.cts", "default": "./zh-CN/startsWith.cjs" } }, "./zh-CN/stringifyJson": { "import": { "types": "./zh-CN/stringifyJson.d.mts", "default": "./zh-CN/stringifyJson.mjs" }, "require": { "types": "./zh-CN/stringifyJson.d.cts", "default": "./zh-CN/stringifyJson.cjs" } }, "./zh-CN/toBigint": { "import": { "types": "./zh-CN/toBigint.d.mts", "default": "./zh-CN/toBigint.mjs" }, "require": { "types": "./zh-CN/toBigint.d.cts", "default": "./zh-CN/toBigint.cjs" } }, "./zh-CN/toDate": { "import": { "types": "./zh-CN/toDate.d.mts", "default": "./zh-CN/toDate.mjs" }, "require": { "types": "./zh-CN/toDate.d.cts", "default": "./zh-CN/toDate.cjs" } }, "./zh-CN/toNumber": { "import": { "types": "./zh-CN/toNumber.d.mts", "default": "./zh-CN/toNumber.mjs" }, "require": { "types": "./zh-CN/toNumber.d.cts", "default": "./zh-CN/toNumber.cjs" } }, "./zh-CN/toString": { "import": { "types": "./zh-CN/toString.d.mts", "default": "./zh-CN/toString.mjs" }, "require": { "types": "./zh-CN/toString.d.cts", "default": "./zh-CN/toString.cjs" } }, "./zh-CN/ulid": { "import": { "types": "./zh-CN/ulid.d.mts", "default": "./zh-CN/ulid.mjs" }, "require": { "types": "./zh-CN/ulid.d.cts", "default": "./zh-CN/ulid.cjs" } }, "./zh-CN/url": { "import": { "types": "./zh-CN/url.d.mts", "default": "./zh-CN/url.mjs" }, "require": { "types": "./zh-CN/url.d.cts", "default": "./zh-CN/url.cjs" } }, "./zh-CN/uuid": { "import": { "types": "./zh-CN/uuid.d.mts", "default": "./zh-CN/uuid.mjs" }, "require": { "types": "./zh-CN/uuid.d.cts", "default": "./zh-CN/uuid.cjs" } }, "./zh-CN/value": { "import": { "types": "./zh-CN/value.d.mts", "default": "./zh-CN/value.mjs" }, "require": { "types": "./zh-CN/value.d.cts", "default": "./zh-CN/value.cjs" } }, "./zh-CN/values": { "import": { "types": "./zh-CN/values.d.mts", "default": "./zh-CN/values.mjs" }, "require": { "types": "./zh-CN/values.d.cts", "default": "./zh-CN/values.cjs" } }, "./zh-CN/words": { "import": { "types": "./zh-CN/words.d.mts", "default": "./zh-CN/words.mjs" }, "require": { "types": "./zh-CN/words.d.cts", "default": "./zh-CN/words.cjs" } }, "./zh-TW": { "import": { "types": "./zh-TW/index.d.mts", "default": "./zh-TW/index.mjs" }, "require": { "types": "./zh-TW/index.d.cts", "default": "./zh-TW/index.cjs" } }, "./zh-TW/schema": { "import": { "types": "./zh-TW/schema.d.mts", "default": "./zh-TW/schema.mjs" }, "require": { "types": "./zh-TW/schema.d.cts", "default": "./zh-TW/schema.cjs" } }, "./zh-TW/base64": { "import": { "types": "./zh-TW/base64.d.mts", "default": "./zh-TW/base64.mjs" }, "require": { "types": "./zh-TW/base64.d.cts", "default": "./zh-TW/base64.cjs" } }, "./zh-TW/bic": { "import": { "types": "./zh-TW/bic.d.mts", "default": "./zh-TW/bic.mjs" }, "require": { "types": "./zh-TW/bic.d.cts", "default": "./zh-TW/bic.cjs" } }, "./zh-TW/bytes": { "import": { "types": "./zh-TW/bytes.d.mts", "default": "./zh-TW/bytes.mjs" }, "require": { "types": "./zh-TW/bytes.d.cts", "default": "./zh-TW/bytes.cjs" } }, "./zh-TW/check": { "import": { "types": "./zh-TW/check.d.mts", "default": "./zh-TW/check.mjs" }, "require": { "types": "./zh-TW/check.d.cts", "default": "./zh-TW/check.cjs" } }, "./zh-TW/checkAsync": { "import": { "types": "./zh-TW/checkAsync.d.mts", "default": "./zh-TW/checkAsync.mjs" }, "require": { "types": "./zh-TW/checkAsync.d.cts", "default": "./zh-TW/checkAsync.cjs" } }, "./zh-TW/checkItems": { "import": { "types": "./zh-TW/checkItems.d.mts", "default": "./zh-TW/checkItems.mjs" }, "require": { "types": "./zh-TW/checkItems.d.cts", "default": "./zh-TW/checkItems.cjs" } }, "./zh-TW/checkItemsAsync": { "import": { "types": "./zh-TW/checkItemsAsync.d.mts", "default": "./zh-TW/checkItemsAsync.mjs" }, "require": { "types": "./zh-TW/checkItemsAsync.d.cts", "default": "./zh-TW/checkItemsAsync.cjs" } }, "./zh-TW/creditCard": { "import": { "types": "./zh-TW/creditCard.d.mts", "default": "./zh-TW/creditCard.mjs" }, "require": { "types": "./zh-TW/creditCard.d.cts", "default": "./zh-TW/creditCard.cjs" } }, "./zh-TW/cuid2": { "import": { "types": "./zh-TW/cuid2.d.mts", "default": "./zh-TW/cuid2.mjs" }, "require": { "types": "./zh-TW/cuid2.d.cts", "default": "./zh-TW/cuid2.cjs" } }, "./zh-TW/decimal": { "import": { "types": "./zh-TW/decimal.d.mts", "default": "./zh-TW/decimal.mjs" }, "require": { "types": "./zh-TW/decimal.d.cts", "default": "./zh-TW/decimal.cjs" } }, "./zh-TW/digits": { "import": { "types": "./zh-TW/digits.d.mts", "default": "./zh-TW/digits.mjs" }, "require": { "types": "./zh-TW/digits.d.cts", "default": "./zh-TW/digits.cjs" } }, "./zh-TW/domain": { "import": { "types": "./zh-TW/domain.d.mts", "default": "./zh-TW/domain.mjs" }, "require": { "types": "./zh-TW/domain.d.cts", "default": "./zh-TW/domain.cjs" } }, "./zh-TW/email": { "import": { "types": "./zh-TW/email.d.mts", "default": "./zh-TW/email.mjs" }, "require": { "types": "./zh-TW/email.d.cts", "default": "./zh-TW/email.cjs" } }, "./zh-TW/emoji": { "import": { "types": "./zh-TW/emoji.d.mts", "default": "./zh-TW/emoji.mjs" }, "require": { "types": "./zh-TW/emoji.d.cts", "default": "./zh-TW/emoji.cjs" } }, "./zh-TW/empty": { "import": { "types": "./zh-TW/empty.d.mts", "default": "./zh-TW/empty.mjs" }, "require": { "types": "./zh-TW/empty.d.cts", "default": "./zh-TW/empty.cjs" } }, "./zh-TW/endsWith": { "import": { "types": "./zh-TW/endsWith.d.mts", "default": "./zh-TW/endsWith.mjs" }, "require": { "types": "./zh-TW/endsWith.d.cts", "default": "./zh-TW/endsWith.cjs" } }, "./zh-TW/entries": { "import": { "types": "./zh-TW/entries.d.mts", "default": "./zh-TW/entries.mjs" }, "require": { "types": "./zh-TW/entries.d.cts", "default": "./zh-TW/entries.cjs" } }, "./zh-TW/everyItem": { "import": { "types": "./zh-TW/everyItem.d.mts", "default": "./zh-TW/everyItem.mjs" }, "require": { "types": "./zh-TW/everyItem.d.cts", "default": "./zh-TW/everyItem.cjs" } }, "./zh-TW/excludes": { "import": { "types": "./zh-TW/excludes.d.mts", "default": "./zh-TW/excludes.mjs" }, "require": { "types": "./zh-TW/excludes.d.cts", "default": "./zh-TW/excludes.cjs" } }, "./zh-TW/finite": { "import": { "types": "./zh-TW/finite.d.mts", "default": "./zh-TW/finite.mjs" }, "require": { "types": "./zh-TW/finite.d.cts", "default": "./zh-TW/finite.cjs" } }, "./zh-TW/graphemes": { "import": { "types": "./zh-TW/graphemes.d.mts", "default": "./zh-TW/graphemes.mjs" }, "require": { "types": "./zh-TW/graphemes.d.cts", "default": "./zh-TW/graphemes.cjs" } }, "./zh-TW/gtValue": { "import": { "types": "./zh-TW/gtValue.d.mts", "default": "./zh-TW/gtValue.mjs" }, "require": { "types": "./zh-TW/gtValue.d.cts", "default": "./zh-TW/gtValue.cjs" } }, "./zh-TW/guard": { "import": { "types": "./zh-TW/guard.d.mts", "default": "./zh-TW/guard.mjs" }, "require": { "types": "./zh-TW/guard.d.cts", "default": "./zh-TW/guard.cjs" } }, "./zh-TW/hash": { "import": { "types": "./zh-TW/hash.d.mts", "default": "./zh-TW/hash.mjs" }, "require": { "types": "./zh-TW/hash.d.cts", "default": "./zh-TW/hash.cjs" } }, "./zh-TW/hexadecimal": { "import": { "types": "./zh-TW/hexadecimal.d.mts", "default": "./zh-TW/hexadecimal.mjs" }, "require": { "types": "./zh-TW/hexadecimal.d.cts", "default": "./zh-TW/hexadecimal.cjs" } }, "./zh-TW/hexColor": { "import": { "types": "./zh-TW/hexColor.d.mts", "default": "./zh-TW/hexColor.mjs" }, "require": { "types": "./zh-TW/hexColor.d.cts", "default": "./zh-TW/hexColor.cjs" } }, "./zh-TW/imei": { "import": { "types": "./zh-TW/imei.d.mts", "default": "./zh-TW/imei.mjs" }, "require": { "types": "./zh-TW/imei.d.cts", "default": "./zh-TW/imei.cjs" } }, "./zh-TW/includes": { "import": { "types": "./zh-TW/includes.d.mts", "default": "./zh-TW/includes.mjs" }, "require": { "types": "./zh-TW/includes.d.cts", "default": "./zh-TW/includes.cjs" } }, "./zh-TW/integer": { "import": { "types": "./zh-TW/integer.d.mts", "default": "./zh-TW/integer.mjs" }, "require": { "types": "./zh-TW/integer.d.cts", "default": "./zh-TW/integer.cjs" } }, "./zh-TW/ip": { "import": { "types": "./zh-TW/ip.d.mts", "default": "./zh-TW/ip.mjs" }, "require": { "types": "./zh-TW/ip.d.cts", "default": "./zh-TW/ip.cjs" } }, "./zh-TW/ipv4": { "import": { "types": "./zh-TW/ipv4.d.mts", "default": "./zh-TW/ipv4.mjs" }, "require": { "types": "./zh-TW/ipv4.d.cts", "default": "./zh-TW/ipv4.cjs" } }, "./zh-TW/ipv6": { "import": { "types": "./zh-TW/ipv6.d.mts", "default": "./zh-TW/ipv6.mjs" }, "require": { "types": "./zh-TW/ipv6.d.cts", "default": "./zh-TW/ipv6.cjs" } }, "./zh-TW/isbn": { "import": { "types": "./zh-TW/isbn.d.mts", "default": "./zh-TW/isbn.mjs" }, "require": { "types": "./zh-TW/isbn.d.cts", "default": "./zh-TW/isbn.cjs" } }, "./zh-TW/isoDate": { "import": { "types": "./zh-TW/isoDate.d.mts", "default": "./zh-TW/isoDate.mjs" }, "require": { "types": "./zh-TW/isoDate.d.cts", "default": "./zh-TW/isoDate.cjs" } }, "./zh-TW/isoDateTime": { "import": { "types": "./zh-TW/isoDateTime.d.mts", "default": "./zh-TW/isoDateTime.mjs" }, "require": { "types": "./zh-TW/isoDateTime.d.cts", "default": "./zh-TW/isoDateTime.cjs" } }, "./zh-TW/isoTime": { "import": { "types": "./zh-TW/isoTime.d.mts", "default": "./zh-TW/isoTime.mjs" }, "require": { "types": "./zh-TW/isoTime.d.cts", "default": "./zh-TW/isoTime.cjs" } }, "./zh-TW/isoTimeSecond": { "import": { "types": "./zh-TW/isoTimeSecond.d.mts", "default": "./zh-TW/isoTimeSecond.mjs" }, "require": { "types": "./zh-TW/isoTimeSecond.d.cts", "default": "./zh-TW/isoTimeSecond.cjs" } }, "./zh-TW/isoTimestamp": { "import": { "types": "./zh-TW/isoTimestamp.d.mts", "default": "./zh-TW/isoTimestamp.mjs" }, "require": { "types": "./zh-TW/isoTimestamp.d.cts", "default": "./zh-TW/isoTimestamp.cjs" } }, "./zh-TW/isoWeek": { "import": { "types": "./zh-TW/isoWeek.d.mts", "default": "./zh-TW/isoWeek.mjs" }, "require": { "types": "./zh-TW/isoWeek.d.cts", "default": "./zh-TW/isoWeek.cjs" } }, "./zh-TW/isrc": { "import": { "types": "./zh-TW/isrc.d.mts", "default": "./zh-TW/isrc.mjs" }, "require": { "types": "./zh-TW/isrc.d.cts", "default": "./zh-TW/isrc.cjs" } }, "./zh-TW/jwsCompact": { "import": { "types": "./zh-TW/jwsCompact.d.mts", "default": "./zh-TW/jwsCompact.mjs" }, "require": { "types": "./zh-TW/jwsCompact.d.cts", "default": "./zh-TW/jwsCompact.cjs" } }, "./zh-TW/length": { "import": { "types": "./zh-TW/length.d.mts", "default": "./zh-TW/length.mjs" }, "require": { "types": "./zh-TW/length.d.cts", "default": "./zh-TW/length.cjs" } }, "./zh-TW/ltValue": { "import": { "types": "./zh-TW/ltValue.d.mts", "default": "./zh-TW/ltValue.mjs" }, "require": { "types": "./zh-TW/ltValue.d.cts", "default": "./zh-TW/ltValue.cjs" } }, "./zh-TW/mac": { "import": { "types": "./zh-TW/mac.d.mts", "default": "./zh-TW/mac.mjs" }, "require": { "types": "./zh-TW/mac.d.cts", "default": "./zh-TW/mac.cjs" } }, "./zh-TW/mac48": { "import": { "types": "./zh-TW/mac48.d.mts", "default": "./zh-TW/mac48.mjs" }, "require": { "types": "./zh-TW/mac48.d.cts", "default": "./zh-TW/mac48.cjs" } }, "./zh-TW/mac64": { "import": { "types": "./zh-TW/mac64.d.mts", "default": "./zh-TW/mac64.mjs" }, "require": { "types": "./zh-TW/mac64.d.cts", "default": "./zh-TW/mac64.cjs" } }, "./zh-TW/maxBytes": { "import": { "types": "./zh-TW/maxBytes.d.mts", "default": "./zh-TW/maxBytes.mjs" }, "require": { "types": "./zh-TW/maxBytes.d.cts", "default": "./zh-TW/maxBytes.cjs" } }, "./zh-TW/maxEntries": { "import": { "types": "./zh-TW/maxEntries.d.mts", "default": "./zh-TW/maxEntries.mjs" }, "require": { "types": "./zh-TW/maxEntries.d.cts", "default": "./zh-TW/maxEntries.cjs" } }, "./zh-TW/maxGraphemes": { "import": { "types": "./zh-TW/maxGraphemes.d.mts", "default": "./zh-TW/maxGraphemes.mjs" }, "require": { "types": "./zh-TW/maxGraphemes.d.cts", "default": "./zh-TW/maxGraphemes.cjs" } }, "./zh-TW/maxLength": { "import": { "types": "./zh-TW/maxLength.d.mts", "default": "./zh-TW/maxLength.mjs" }, "require": { "types": "./zh-TW/maxLength.d.cts", "default": "./zh-TW/maxLength.cjs" } }, "./zh-TW/maxSize": { "import": { "types": "./zh-TW/maxSize.d.mts", "default": "./zh-TW/maxSize.mjs" }, "require": { "types": "./zh-TW/maxSize.d.cts", "default": "./zh-TW/maxSize.cjs" } }, "./zh-TW/maxValue": { "import": { "types": "./zh-TW/maxValue.d.mts", "default": "./zh-TW/maxValue.mjs" }, "require": { "types": "./zh-TW/maxValue.d.cts", "default": "./zh-TW/maxValue.cjs" } }, "./zh-TW/maxWords": { "import": { "types": "./zh-TW/maxWords.d.mts", "default": "./zh-TW/maxWords.mjs" }, "require": { "types": "./zh-TW/maxWords.d.cts", "default": "./zh-TW/maxWords.cjs" } }, "./zh-TW/mimeType": { "import": { "types": "./zh-TW/mimeType.d.mts", "default": "./zh-TW/mimeType.mjs" }, "require": { "types": "./zh-TW/mimeType.d.cts", "default": "./zh-TW/mimeType.cjs" } }, "./zh-TW/minBytes": { "import": { "types": "./zh-TW/minBytes.d.mts", "default": "./zh-TW/minBytes.mjs" }, "require": { "types": "./zh-TW/minBytes.d.cts", "default": "./zh-TW/minBytes.cjs" } }, "./zh-TW/minEntries": { "import": { "types": "./zh-TW/minEntries.d.mts", "default": "./zh-TW/minEntries.mjs" }, "require": { "types": "./zh-TW/minEntries.d.cts", "default": "./zh-TW/minEntries.cjs" } }, "./zh-TW/minGraphemes": { "import": { "types": "./zh-TW/minGraphemes.d.mts", "default": "./zh-TW/minGraphemes.mjs" }, "require": { "types": "./zh-TW/minGraphemes.d.cts", "default": "./zh-TW/minGraphemes.cjs" } }, "./zh-TW/minLength": { "import": { "types": "./zh-TW/minLength.d.mts", "default": "./zh-TW/minLength.mjs" }, "require": { "types": "./zh-TW/minLength.d.cts", "default": "./zh-TW/minLength.cjs" } }, "./zh-TW/minSize": { "import": { "types": "./zh-TW/minSize.d.mts", "default": "./zh-TW/minSize.mjs" }, "require": { "types": "./zh-TW/minSize.d.cts", "default": "./zh-TW/minSize.cjs" } }, "./zh-TW/minValue": { "import": { "types": "./zh-TW/minValue.d.mts", "default": "./zh-TW/minValue.mjs" }, "require": { "types": "./zh-TW/minValue.d.cts", "default": "./zh-TW/minValue.cjs" } }, "./zh-TW/minWords": { "import": { "types": "./zh-TW/minWords.d.mts", "default": "./zh-TW/minWords.mjs" }, "require": { "types": "./zh-TW/minWords.d.cts", "default": "./zh-TW/minWords.cjs" } }, "./zh-TW/multipleOf": { "import": { "types": "./zh-TW/multipleOf.d.mts", "default": "./zh-TW/multipleOf.mjs" }, "require": { "types": "./zh-TW/multipleOf.d.cts", "default": "./zh-TW/multipleOf.cjs" } }, "./zh-TW/nanoid": { "import": { "types": "./zh-TW/nanoid.d.mts", "default": "./zh-TW/nanoid.mjs" }, "require": { "types": "./zh-TW/nanoid.d.cts", "default": "./zh-TW/nanoid.cjs" } }, "./zh-TW/nonEmpty": { "import": { "types": "./zh-TW/nonEmpty.d.mts", "default": "./zh-TW/nonEmpty.mjs" }, "require": { "types": "./zh-TW/nonEmpty.d.cts", "default": "./zh-TW/nonEmpty.cjs" } }, "./zh-TW/notBytes": { "import": { "types": "./zh-TW/notBytes.d.mts", "default": "./zh-TW/notBytes.mjs" }, "require": { "types": "./zh-TW/notBytes.d.cts", "default": "./zh-TW/notBytes.cjs" } }, "./zh-TW/notEntries": { "import": { "types": "./zh-TW/notEntries.d.mts", "default": "./zh-TW/notEntries.mjs" }, "require": { "types": "./zh-TW/notEntries.d.cts", "default": "./zh-TW/notEntries.cjs" } }, "./zh-TW/notGraphemes": { "import": { "types": "./zh-TW/notGraphemes.d.mts", "default": "./zh-TW/notGraphemes.mjs" }, "require": { "types": "./zh-TW/notGraphemes.d.cts", "default": "./zh-TW/notGraphemes.cjs" } }, "./zh-TW/notLength": { "import": { "types": "./zh-TW/notLength.d.mts", "default": "./zh-TW/notLength.mjs" }, "require": { "types": "./zh-TW/notLength.d.cts", "default": "./zh-TW/notLength.cjs" } }, "./zh-TW/notSize": { "import": { "types": "./zh-TW/notSize.d.mts", "default": "./zh-TW/notSize.mjs" }, "require": { "types": "./zh-TW/notSize.d.cts", "default": "./zh-TW/notSize.cjs" } }, "./zh-TW/notValue": { "import": { "types": "./zh-TW/notValue.d.mts", "default": "./zh-TW/notValue.mjs" }, "require": { "types": "./zh-TW/notValue.d.cts", "default": "./zh-TW/notValue.cjs" } }, "./zh-TW/notValues": { "import": { "types": "./zh-TW/notValues.d.mts", "default": "./zh-TW/notValues.mjs" }, "require": { "types": "./zh-TW/notValues.d.cts", "default": "./zh-TW/notValues.cjs" } }, "./zh-TW/notWords": { "import": { "types": "./zh-TW/notWords.d.mts", "default": "./zh-TW/notWords.mjs" }, "require": { "types": "./zh-TW/notWords.d.cts", "default": "./zh-TW/notWords.cjs" } }, "./zh-TW/octal": { "import": { "types": "./zh-TW/octal.d.mts", "default": "./zh-TW/octal.mjs" }, "require": { "types": "./zh-TW/octal.d.cts", "default": "./zh-TW/octal.cjs" } }, "./zh-TW/parseBoolean": { "import": { "types": "./zh-TW/parseBoolean.d.mts", "default": "./zh-TW/parseBoolean.mjs" }, "require": { "types": "./zh-TW/parseBoolean.d.cts", "default": "./zh-TW/parseBoolean.cjs" } }, "./zh-TW/parseJson": { "import": { "types": "./zh-TW/parseJson.d.mts", "default": "./zh-TW/parseJson.mjs" }, "require": { "types": "./zh-TW/parseJson.d.cts", "default": "./zh-TW/parseJson.cjs" } }, "./zh-TW/partialCheck": { "import": { "types": "./zh-TW/partialCheck.d.mts", "default": "./zh-TW/partialCheck.mjs" }, "require": { "types": "./zh-TW/partialCheck.d.cts", "default": "./zh-TW/partialCheck.cjs" } }, "./zh-TW/rawCheck": { "import": { "types": "./zh-TW/rawCheck.d.mts", "default": "./zh-TW/rawCheck.mjs" }, "require": { "types": "./zh-TW/rawCheck.d.cts", "default": "./zh-TW/rawCheck.cjs" } }, "./zh-TW/rawTransform": { "import": { "types": "./zh-TW/rawTransform.d.mts", "default": "./zh-TW/rawTransform.mjs" }, "require": { "types": "./zh-TW/rawTransform.d.cts", "default": "./zh-TW/rawTransform.cjs" } }, "./zh-TW/regex": { "import": { "types": "./zh-TW/regex.d.mts", "default": "./zh-TW/regex.mjs" }, "require": { "types": "./zh-TW/regex.d.cts", "default": "./zh-TW/regex.cjs" } }, "./zh-TW/rfcEmail": { "import": { "types": "./zh-TW/rfcEmail.d.mts", "default": "./zh-TW/rfcEmail.mjs" }, "require": { "types": "./zh-TW/rfcEmail.d.cts", "default": "./zh-TW/rfcEmail.cjs" } }, "./zh-TW/safeInteger": { "import": { "types": "./zh-TW/safeInteger.d.mts", "default": "./zh-TW/safeInteger.mjs" }, "require": { "types": "./zh-TW/safeInteger.d.cts", "default": "./zh-TW/safeInteger.cjs" } }, "./zh-TW/size": { "import": { "types": "./zh-TW/size.d.mts", "default": "./zh-TW/size.mjs" }, "require": { "types": "./zh-TW/size.d.cts", "default": "./zh-TW/size.cjs" } }, "./zh-TW/slug": { "import": { "types": "./zh-TW/slug.d.mts", "default": "./zh-TW/slug.mjs" }, "require": { "types": "./zh-TW/slug.d.cts", "default": "./zh-TW/slug.cjs" } }, "./zh-TW/someItem": { "import": { "types": "./zh-TW/someItem.d.mts", "default": "./zh-TW/someItem.mjs" }, "require": { "types": "./zh-TW/someItem.d.cts", "default": "./zh-TW/someItem.cjs" } }, "./zh-TW/startsWith": { "import": { "types": "./zh-TW/startsWith.d.mts", "default": "./zh-TW/startsWith.mjs" }, "require": { "types": "./zh-TW/startsWith.d.cts", "default": "./zh-TW/startsWith.cjs" } }, "./zh-TW/stringifyJson": { "import": { "types": "./zh-TW/stringifyJson.d.mts", "default": "./zh-TW/stringifyJson.mjs" }, "require": { "types": "./zh-TW/stringifyJson.d.cts", "default": "./zh-TW/stringifyJson.cjs" } }, "./zh-TW/toBigint": { "import": { "types": "./zh-TW/toBigint.d.mts", "default": "./zh-TW/toBigint.mjs" }, "require": { "types": "./zh-TW/toBigint.d.cts", "default": "./zh-TW/toBigint.cjs" } }, "./zh-TW/toDate": { "import": { "types": "./zh-TW/toDate.d.mts", "default": "./zh-TW/toDate.mjs" }, "require": { "types": "./zh-TW/toDate.d.cts", "default": "./zh-TW/toDate.cjs" } }, "./zh-TW/toNumber": { "import": { "types": "./zh-TW/toNumber.d.mts", "default": "./zh-TW/toNumber.mjs" }, "require": { "types": "./zh-TW/toNumber.d.cts", "default": "./zh-TW/toNumber.cjs" } }, "./zh-TW/toString": { "import": { "types": "./zh-TW/toString.d.mts", "default": "./zh-TW/toString.mjs" }, "require": { "types": "./zh-TW/toString.d.cts", "default": "./zh-TW/toString.cjs" } }, "./zh-TW/ulid": { "import": { "types": "./zh-TW/ulid.d.mts", "default": "./zh-TW/ulid.mjs" }, "require": { "types": "./zh-TW/ulid.d.cts", "default": "./zh-TW/ulid.cjs" } }, "./zh-TW/url": { "import": { "types": "./zh-TW/url.d.mts", "default": "./zh-TW/url.mjs" }, "require": { "types": "./zh-TW/url.d.cts", "default": "./zh-TW/url.cjs" } }, "./zh-TW/uuid": { "import": { "types": "./zh-TW/uuid.d.mts", "default": "./zh-TW/uuid.mjs" }, "require": { "types": "./zh-TW/uuid.d.cts", "default": "./zh-TW/uuid.cjs" } }, "./zh-TW/value": { "import": { "types": "./zh-TW/value.d.mts", "default": "./zh-TW/value.mjs" }, "require": { "types": "./zh-TW/value.d.cts", "default": "./zh-TW/value.cjs" } }, "./zh-TW/values": { "import": { "types": "./zh-TW/values.d.mts", "default": "./zh-TW/values.mjs" }, "require": { "types": "./zh-TW/values.d.cts", "default": "./zh-TW/values.cjs" } }, "./zh-TW/words": { "import": { "types": "./zh-TW/words.d.mts", "default": "./zh-TW/words.mjs" }, "require": { "types": "./zh-TW/words.d.cts", "default": "./zh-TW/words.cjs" } } } } ================================================ FILE: packages/i18n/scripts/build-jsr.ts ================================================ import fs from 'node:fs'; import path from 'node:path'; import jsr from '../jsr.json'; import package_ from '../package.json'; import ar from '../src/ar'; import az from '../src/az'; import ca from '../src/ca'; import cs from '../src/cs'; import de from '../src/de'; import el from '../src/el'; import es from '../src/es'; import fa from '../src/fa'; import fi from '../src/fi'; import fr from '../src/fr'; import hu from '../src/hu'; import id from '../src/id'; import it from '../src/it'; import ja from '../src/ja'; import ko from '../src/ko'; import kr from '../src/kr'; import mn from '../src/mn'; import nb from '../src/nb'; import nl from '../src/nl'; import pl from '../src/pl'; import pt from '../src/pt'; import ro from '../src/ro'; import ru from '../src/ru'; import sk from '../src/sk'; import sl from '../src/sl'; import sv from '../src/sv'; import tr from '../src/tr'; import uk from '../src/uk'; import vi from '../src/vi'; import zhCN from '../src/zh-CN'; import zhTW from '../src/zh-TW'; // Create languages array // Note: The language file `en` does not need to be added as the default // messages of Valibot are already in English const languages = [ ar, az, ca, cs, de, el, es, fa, fi, fr, hu, id, it, ja, ko, kr, mn, nb, nl, pl, pt, ro, ru, sk, sl, sv, tr, uk, vi, zhCN, zhTW, ]; // Create root imports variable const rootImports: string[] = []; // Create exclude array const exclude: string[] = [ 'scripts', 'src', 'CHANGELOG.md', 'package.json', 'tsconfig.json', '!index.ts', ]; // Create exports object with index file const exports: Record = { '.': './index.ts', }; // Clean root directory for (const file of package_.files) { fs.rmSync(file, { recursive: true, force: true }); } // Create language specific submodules for (const language of languages) { // Create language directory fs.mkdirSync(language.code); // Add language to exclude exclude.push(`!${language.code}`); // Add index file to exports exports[`./${language.code}`] = `./${language.code}/index.ts`; // Add index imports to root index files rootImports.push(`import "./${language.code}/index.ts";`); // Create language imports variable const languageImports: string[] = []; // Add schema file to exports exports[`./${language.code}/schema`] = `./${language.code}/schema.ts`; // Add schema import to language index file languageImports.push(`import "./schema.ts";`); // Write schema.ts file fs.writeFileSync( path.join(language.code, 'schema.ts'), ` import { setSchemaMessage } from "jsr:@valibot/valibot@1.3.0"; setSchemaMessage( ${language.schema.toString()}, "${language.code}" ); `.trim() ); // Create submodules for specific messages for (const [reference, message] of Object.entries(language.specific)) { // Add file to exports exports[`./${language.code}/${reference}`] = `./${language.code}/${reference}.ts`; // Add import to language index file languageImports.push(`import "./${reference}.ts";`); // Write ${reference}.ts file fs.writeFileSync( path.join(language.code, `${reference}.ts`), ` import { setSpecificMessage, ${reference} } from "jsr:@valibot/valibot@1.3.0"; setSpecificMessage( ${reference}, ${message.toString()}, "${language.code}" ); `.trim() ); } // Write language index.ts file fs.writeFileSync( path.join(language.code, 'index.ts'), languageImports.join('\n') ); } // Write root index.ts file fs.writeFileSync('index.ts', rootImports.join('\n')); // Write root jsr.json file fs.writeFileSync( 'jsr.json', JSON.stringify({ ...jsr, exclude, exports }, null, 2) ); ================================================ FILE: packages/i18n/scripts/build-npm.ts ================================================ import fs from 'node:fs'; import path from 'node:path'; import package_ from '../package.json'; import ar from '../src/ar'; import az from '../src/az'; import ca from '../src/ca'; import cs from '../src/cs'; import de from '../src/de'; import el from '../src/el'; import es from '../src/es'; import fa from '../src/fa'; import fi from '../src/fi'; import fr from '../src/fr'; import hu from '../src/hu'; import id from '../src/id'; import it from '../src/it'; import ja from '../src/ja'; import ko from '../src/ko'; import kr from '../src/kr'; import mn from '../src/mn'; import nb from '../src/nb'; import nl from '../src/nl'; import pl from '../src/pl'; import pt from '../src/pt'; import ro from '../src/ro'; import ru from '../src/ru'; import sk from '../src/sk'; import sl from '../src/sl'; import sv from '../src/sv'; import tr from '../src/tr'; import uk from '../src/uk'; import vi from '../src/vi'; import zhCN from '../src/zh-CN'; import zhTW from '../src/zh-TW'; // Create languages array // Note: The language file `en` does not need to be added as the default // messages of Valibot are already in English const languages = [ ar, az, ca, cs, de, el, es, fa, fi, fr, hu, id, it, ja, ko, kr, mn, nb, nl, pl, pt, ro, ru, sk, sl, sv, tr, uk, vi, zhCN, zhTW, ]; // Create root import variables const rootModuleImports: string[] = []; const rootCommonImports: string[] = ['"use strict";']; // Create files array const files: string[] = [ 'index.ts', 'index.mjs', 'index.cjs', 'index.d.mts', 'index.d.cts', ]; /** * Exports type. */ type Exports = Record< string, { import: { types: string; default: string; }; require: { types: string; default: string; }; } >; // Create exports object with index files const exports: Exports = { '.': { import: { types: './index.d.mts', default: './index.mjs', }, require: { types: './index.d.cts', default: './index.cjs', }, }, }; // Clean root directory for (const file of package_.files) { fs.rmSync(file, { recursive: true, force: true }); } // Create language specific submodules for (const language of languages) { // Create language directory fs.mkdirSync(language.code); // Add language to files files.push(language.code); // Add index files to exports exports[`./${language.code}`] = { import: { types: `./${language.code}/index.d.mts`, default: `./${language.code}/index.mjs`, }, require: { types: `./${language.code}/index.d.cts`, default: `./${language.code}/index.cjs`, }, }; // Add index imports to root index files rootModuleImports.push(`import "@valibot/i18n/${language.code}";`); rootCommonImports.push( `var import_${language.code} = require("@valibot/i18n/${language.code}");` ); // Create language import variables const languageModuleImports: string[] = []; const languageCommonImports: string[] = ['"use strict";']; // Add schema files to exports exports[`./${language.code}/schema`] = { import: { types: `./${language.code}/schema.d.mts`, default: `./${language.code}/schema.mjs`, }, require: { types: `./${language.code}/schema.d.cts`, default: `./${language.code}/schema.cjs`, }, }; // Add schema import to language index file languageModuleImports.push(`import "@valibot/i18n/${language.code}/schema";`); languageCommonImports.push( `var import_schema = require("@valibot/i18n/${language.code}/schema");` ); // Write schema.mjs file fs.writeFileSync( path.join(language.code, 'schema.mjs'), ` import { setSchemaMessage } from "valibot"; setSchemaMessage( ${language.schema.toString()}, "${language.code}" ); `.trim() ); // Write schema.cjs file fs.writeFileSync( path.join(language.code, 'schema.cjs'), ` "use strict"; var import_valibot = require("valibot"); (0, import_valibot.setSchemaMessage)( ${language.schema.toString()}, "${language.code}" ); `.trim() ); // Write schema.d.mts file fs.writeFileSync(path.join(language.code, 'schema.d.mts'), 'export { }'); // Write schema.d.cts file fs.writeFileSync(path.join(language.code, 'schema.d.cts'), 'export { }'); // Create submodules for specific messages for (const [reference, message] of Object.entries(language.specific)) { // Add files to exports exports[`./${language.code}/${reference}`] = { import: { types: `./${language.code}/${reference}.d.mts`, default: `./${language.code}/${reference}.mjs`, }, require: { types: `./${language.code}/${reference}.d.cts`, default: `./${language.code}/${reference}.cjs`, }, }; // Add import to language index file languageModuleImports.push( `import "@valibot/i18n/${language.code}/${reference}";` ); languageCommonImports.push( `var import_${reference} = require("@valibot/i18n/${language.code}/${reference}");` ); // Write ${reference}.mjs file fs.writeFileSync( path.join(language.code, `${reference}.mjs`), ` import { setSpecificMessage, ${reference} } from "valibot"; setSpecificMessage( ${reference}, ${message.toString()}, "${language.code}" ); `.trim() ); // Write ${reference}.cjs file fs.writeFileSync( path.join(language.code, `${reference}.cjs`), ` "use strict"; var import_valibot = require("valibot"); (0, import_valibot.setSpecificMessage)( import_valibot.${reference}, ${message.toString()}, "${language.code}" ); `.trim() ); // Write ${reference}.d.mts file fs.writeFileSync( path.join(language.code, `${reference}.d.mts`), 'export { }' ); // Write ${reference}.d.cts file fs.writeFileSync( path.join(language.code, `${reference}.d.cts`), 'export { }' ); } // Write language index.mjs file fs.writeFileSync( path.join(language.code, 'index.mjs'), languageModuleImports.join('\n') ); // Write language index.cjs file fs.writeFileSync( path.join(language.code, 'index.cjs'), languageCommonImports.join('\n') ); // Write language index.d.mts file fs.writeFileSync(path.join(language.code, 'index.d.mts'), 'export { }'); // Write language index.d.cts file fs.writeFileSync(path.join(language.code, 'index.d.cts'), 'export { }'); } // Write root index.mjs file fs.writeFileSync('index.mjs', rootModuleImports.join('\n')); // Write root index.cjs file fs.writeFileSync('index.cjs', rootCommonImports.join('\n')); // Write root index.d.mts file fs.writeFileSync('index.d.mts', 'export { }'); // Write root index.d.cts file fs.writeFileSync('index.d.cts', 'export { }'); // Write root package.json file fs.writeFileSync( 'package.json', JSON.stringify({ ...package_, files, exports }, null, 2) ); // Write root .gitignore file fs.writeFileSync('.gitignore', files.join('\n')); ================================================ FILE: packages/i18n/src/ar.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'ar', schema: (issue) => `نوع غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, specific: { base64: (issue) => `معرّف Base64 غير صالح: القيمة المُدخلة ${issue.received}`, bic: (issue) => `BIC غير صالح: القيمة المُدخلة ${issue.received}`, bytes: (issue) => `حجم بايت غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, check: (issue) => `مُدخل غير صالح: القيمة المُدخلة ${issue.received}`, checkAsync: (issue) => `مُدخل غير صالح: القيمة المُدخلة ${issue.received}`, checkItems: (issue) => `عناصر غير صالحة: قيمة الإدخال ${issue.received}`, checkItemsAsync: (issue) => `عناصر غير صالحة: قيمة الإدخال ${issue.received}`, creditCard: (issue) => `بطاقة إئتمان غير صالحة: القيمة المُدخلة ${issue.received}`, cuid2: (issue) => `قيمة Cuid2 غير صالحة: القيمة المُدخلة ${issue.received}`, decimal: (issue) => `رقم عُشَري غير صالح: القيمة المُدخلة ${issue.received}`, digits: (issue) => `أرقام غير صالحة: القيمة المُدخلة ${issue.received}`, domain: (issue) => `نطاق غير صالح: القيمة المُدخلة ${issue.received}`, email: (issue) => `بريد الكتروني غير صالح: القيمة المُدخلة ${issue.received}`, emoji: (issue) => `رمز تعبيري غير صالح: القيمة المُدخلة ${issue.received}`, empty: (issue) => `الطول غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, endsWith: (issue) => `نهاية غير صالحة: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, entries: (issue) => `عدد الإدخالات غير صالح: القيمة المتوقعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, everyItem: (issue) => `عنصر غير صالح: القيمة المُدخلة ${issue.received}`, excludes: (issue) => `محتوى غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, finite: (issue) => `عدد محدود غير صالح: القيمة المُدخلة ${issue.received}`, graphemes: (issue) => `عدد الرموز غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, gtValue: (issue) => `قيمة غير صالحة: القيمة المتوقعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, guard: (issue) => `إدخال غير صالح: القيمة المُدخلة ${issue.received}`, hash: (issue) => `رقم تجزئة غير صحيح: القيمة المُدخلة ${issue.received}`, hexadecimal: (issue) => `رقم سداسي عشري غير صالح: القيمة المُدخلة ${issue.received}`, hexColor: (issue) => `رمز لون غير صالح: القيمة المُدخلة ${issue.received}`, imei: (issue) => `رقم IMEI غير صالح: القيمة المُدخلة ${issue.received}`, includes: (issue) => `محتوى غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, integer: (issue) => `رقم غير صالح: القيمة المُدخلة ${issue.received}`, ip: (issue) => `عنوان IP غير صالح: القيمة المُدخلة ${issue.received}`, ipv4: (issue) => `عنوان IPv4 غير صالح: القيمة المُدخلة ${issue.received}`, ipv6: (issue) => `عنوان IPv6 غير صالح: القيمة المُدخلة ${issue.received}`, isbn: (issue) => `ISBN غير صالح: القيمة المُدخلة ${issue.received}`, isoDate: (issue) => `تاريخ غير صالح: القيمة المُدخلة ${issue.received}`, isoDateTime: (issue) => `التاريخ والوقت غير صالحان: القيمة المُدخلة ${issue.received}`, isoTime: (issue) => `صيغة وقت غير صالحة: القيمة المُدخلة ${issue.received}`, isoTimeSecond: (issue) => `قيمة وقت بالثواني غير صالحة: القيمة المُدخلة ${issue.received}`, isoTimestamp: (issue) => `الطابع الزمني غير صالح: القيمة المُدخلة ${issue.received}`, isoWeek: (issue) => `أسبوع غير صالح: القيمة المُدخلة ${issue.received}`, isrc: (issue) => `ISRC غير صالح: القيمة المُدخلة ${issue.received}`, jwsCompact: (issue) => `ترميز JWS المضغوط غير صالح: القيمة المُدخلة ${issue.received}`, length: (issue) => `الطول غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, ltValue: (issue) => `قيمة غير صالحة: القيمة المتوقعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, mac: (issue) => `عنوان MAC غير صالح: القيمة المُدخلة ${issue.received}`, mac48: (issue) => `عنوان 48-بت MAC غير صالح: القيمة المُدخلة ${issue.received}`, mac64: (issue) => `عنوان 64-بت MAC غير صالح: القيمة المُدخلة ${issue.received}`, maxBytes: (issue) => `حجم بايت غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, maxEntries: (issue) => `عدد الإدخالات غير صالح: القيمة المتوقعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, maxGraphemes: (issue) => `عدد الرموز غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, maxLength: (issue) => `الطول غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, maxSize: (issue) => `حجم غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, maxValue: (issue) => `قيمة غير صالحة: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, maxWords: (issue) => `عدد الكلمات غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, mimeType: (issue) => `نوع MIME غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, minBytes: (issue) => `حجم بايت غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, minEntries: (issue) => `عدد الإدخالات غير صالح: القيمة المتوقعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, minGraphemes: (issue) => `عدد الرموز غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, minLength: (issue) => `طول غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, minSize: (issue) => `حجم غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, minValue: (issue) => `قيمة غير صالحة: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, minWords: (issue) => `عدد الكلمات غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, multipleOf: (issue) => `متعدد غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, nanoid: (issue) => `معرّف Nano ID غير صالح: القيمة المُدخلة ${issue.received}`, nonEmpty: (issue) => `الطول غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, notBytes: (issue) => `حجم بايت غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, notEntries: (issue) => `عدد الإدخالات غير صالح: القيمة المتوقعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, notGraphemes: (issue) => `عدد الرموز غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, notLength: (issue) => `طول غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, notSize: (issue) => `حجم غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, notValue: (issue) => `قيمة غير صالحة: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, notValues: (issue) => `قيمة غير صالحة: القيمة المتوقعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, notWords: (issue) => `عدد الكلمات غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, octal: (issue) => `رقم ثماني غير صالح: القيمة المُدخلة ${issue.received}`, parseBoolean: (issue) => `قيمة منطقية غير صالحة: القيمة المُدخلة ${issue.received}`, parseJson: (issue) => `JSON غير صالح: القيمة المُدخلة ${issue.received}`, partialCheck: (issue) => `مُدخل غير صالح: القيمة المُدخلة ${issue.received}`, rawCheck: (issue) => `إدخال غير صالح: القيمة المُدخلة ${issue.received}`, rawTransform: (issue) => `إدخال غير صالح: القيمة المُدخلة ${issue.received}`, regex: (issue) => `صيغة غير صالحة: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, rfcEmail: (issue) => `بريد إلكتروني غير صالح: القيمة المُدخلة ${issue.received}`, safeInteger: (issue) => `رقم كامل آمن غير صالح: القيمة المُدخلة ${issue.received}`, size: (issue) => `حجم غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, slug: (issue) => `معرّف slug غير صالح: القيمة المُدخلة ${issue.received}`, someItem: (issue) => `عنصر غير صالح: القيمة المُدخلة ${issue.received}`, startsWith: (issue) => `بداية غير صالحة: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, stringifyJson: (issue) => `JSON غير صالح: القيمة المُدخلة ${issue.received}`, toBigint: (issue) => `BigInt غير صالح: القيمة المُدخلة ${issue.received}`, toDate: (issue) => `تاريخ غير صالح: القيمة المُدخلة ${issue.received}`, toNumber: (issue) => `رقم غير صالح: القيمة المُدخلة ${issue.received}`, toString: (issue) => `نص غير صالح: القيمة المُدخلة ${issue.received}`, ulid: (issue) => `معرّف ULID غير صالح: القيمة المُدخلة ${issue.received}`, url: (issue) => `رابط غير صالح: القيمة المُدخلة ${issue.received}`, uuid: (issue) => `معرّف UUID غير صالح: القيمة المُدخلة ${issue.received}`, value: (issue) => `قيمة غير صالحة: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, values: (issue) => `قيمة غير صالحة: القيمة المتوقعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, words: (issue) => `عدد الكلمات غير صالح: القيمة المتوقّعة ${issue.expected} لكن القيمة المُدخلة ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/az.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'az', schema: (issue) => `Yanlış tip: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, specific: { base64: (issue) => `Yanlış Base64: Alınan ${issue.received}`, bic: (issue) => `Yanlış BIC: Alınan ${issue.received}`, bytes: (issue) => `Yanlış bayt: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, check: (issue) => `Yanlış giriş: Alınan ${issue.received}`, checkAsync: (issue) => `Yanlış giriş: Alınan ${issue.received}`, checkItems: (issue) => `Yanlış element: Alınan ${issue.received}`, checkItemsAsync: (issue) => `Yanlış element: Alınan ${issue.received}`, creditCard: (issue) => `Yanlış kredit kartı: Alınan ${issue.received}`, cuid2: (issue) => `Yanlış Cuid2: Alınan ${issue.received}`, decimal: (issue) => `Yanlış onluq ədəd: Alınan ${issue.received}`, digits: (issue) => `Yanlış rəqəmlər: Alınan ${issue.received}`, domain: (issue) => `Yanlış domen: Alınan ${issue.received}`, email: (issue) => `Yanlış e-poçt: Alınan ${issue.received}`, emoji: (issue) => `Yanlış emoji: Alınan ${issue.received}`, empty: (issue) => `Yanlış uzunluq: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, endsWith: (issue) => `Yanlış sonluq: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, entries: (issue) => `Yanlış giriş sayı: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, everyItem: (issue) => `Yanlış element: Alınan ${issue.received}`, excludes: (issue) => `Yanlış məzmun: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, finite: (issue) => `Yanlış sonlu ədəd: Alınan ${issue.received}`, graphemes: (issue) => `Yanlış qrafem: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, gtValue: (issue) => `Yanlış dəyər: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, guard: (issue) => `Yanlış giriş: Alınan ${issue.received}`, hash: (issue) => `Yanlış hash: Alınan ${issue.received}`, hexadecimal: (issue) => `Yanlış onaltılıq: Alınan ${issue.received}`, hexColor: (issue) => `Yanlış hex rəng: Alınan ${issue.received}`, imei: (issue) => `Yanlış IMEI: Alınan ${issue.received}`, includes: (issue) => `Yanlış məzmun: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, integer: (issue) => `Yanlış tam ədəd: Alınan ${issue.received}`, ip: (issue) => `Yanlış IP: Alınan ${issue.received}`, ipv4: (issue) => `Yanlış IPv4: Alınan ${issue.received}`, ipv6: (issue) => `Yanlış IPv6: Alınan ${issue.received}`, isbn: (issue) => `Yanlış ISBN: Alınan ${issue.received}`, isoDate: (issue) => `Yanlış tarix: Alınan ${issue.received}`, isoDateTime: (issue) => `Yanlış tarix-vaxt: Alınan ${issue.received}`, isoTime: (issue) => `Yanlış vaxt: Alınan ${issue.received}`, isoTimeSecond: (issue) => `Yanlış saniyəli vaxt: Alınan ${issue.received}`, isoTimestamp: (issue) => `Yanlış zaman möhürü: Alınan ${issue.received}`, isoWeek: (issue) => `Yanlış həftə: Alınan ${issue.received}`, isrc: (issue) => `Yanlış ISRC: Alınan ${issue.received}`, jwsCompact: (issue) => `Yanlış kompakt JWS: Alınan ${issue.received}`, length: (issue) => `Yanlış uzunluq: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, ltValue: (issue) => `Yanlış dəyər: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, mac: (issue) => `Yanlış MAC: Alınan ${issue.received}`, mac48: (issue) => `Yanlış 48-bit MAC: Alınan ${issue.received}`, mac64: (issue) => `Yanlış 64-bit MAC: Alınan ${issue.received}`, maxBytes: (issue) => `Yanlış bayt: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, maxEntries: (issue) => `Yanlış giriş sayı: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, maxGraphemes: (issue) => `Yanlış qrafem: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, maxLength: (issue) => `Yanlış uzunluq: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, maxSize: (issue) => `Yanlış ölçü: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, maxValue: (issue) => `Yanlış dəyər: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, maxWords: (issue) => `Yanlış söz sayı: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, mimeType: (issue) => `Yanlış MIME tipi: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, minBytes: (issue) => `Yanlış bayt: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, minEntries: (issue) => `Yanlış giriş sayı: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, minGraphemes: (issue) => `Yanlış qrafem: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, minLength: (issue) => `Yanlış uzunluq: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, minSize: (issue) => `Yanlış ölçü: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, minValue: (issue) => `Yanlış dəyər: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, minWords: (issue) => `Yanlış söz sayı: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, multipleOf: (issue) => `Yanlış qat: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, nanoid: (issue) => `Yanlış Nano ID: Alınan ${issue.received}`, nonEmpty: (issue) => `Yanlış uzunluq: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, notBytes: (issue) => `Yanlış bayt: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, notEntries: (issue) => `Yanlış giriş sayı: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, notGraphemes: (issue) => `Yanlış qrafem: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, notLength: (issue) => `Yanlış uzunluq: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, notSize: (issue) => `Yanlış ölçü: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, notValue: (issue) => `Yanlış dəyər: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, notValues: (issue) => `Yanlış dəyər: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, notWords: (issue) => `Yanlış söz sayı: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, octal: (issue) => `Yanlış səkkizlik: Alınan ${issue.received}`, parseBoolean: (issue) => `Yanlış boolean: Alınan ${issue.received}`, parseJson: (issue) => `Yanlış JSON: Alınan ${issue.received}`, partialCheck: (issue) => `Yanlış giriş: Alınan ${issue.received}`, rawCheck: (issue) => `Yanlış giriş: Alınan ${issue.received}`, rawTransform: (issue) => `Yanlış giriş: Alınan ${issue.received}`, regex: (issue) => `Yanlış format: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, rfcEmail: (issue) => `Yanlış e-poçt: Alınan ${issue.received}`, safeInteger: (issue) => `Yanlış təhlükəsiz tam ədəd: Alınan ${issue.received}`, size: (issue) => `Yanlış ölçü: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, slug: (issue) => `Yanlış slug: Alınan ${issue.received}`, someItem: (issue) => `Yanlış element: Alınan ${issue.received}`, startsWith: (issue) => `Yanlış başlanğıc: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, stringifyJson: (issue) => `Yanlış JSON: Alınan ${issue.received}`, toBigint: (issue) => `Yanlış bigint: Alınan ${issue.received}`, toDate: (issue) => `Yanlış tarix: Alınan ${issue.received}`, toNumber: (issue) => `Yanlış ədəd: Alınan ${issue.received}`, toString: (issue) => `Yanlış sətir: Alınan ${issue.received}`, ulid: (issue) => `Yanlış ULID: Alınan ${issue.received}`, url: (issue) => `Yanlış URL: Alınan ${issue.received}`, uuid: (issue) => `Yanlış UUID: Alınan ${issue.received}`, value: (issue) => `Yanlış dəyər: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, values: (issue) => `Yanlış dəyər: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, words: (issue) => `Yanlış söz sayı: Gözlənilən ${issue.expected} lakin alınan ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/ca.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'ca', schema: (issue) => `Tipus invàlid: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, specific: { base64: (issue) => `Base64 invàlid: S'ha rebut ${issue.received}`, bic: (issue) => `BIC invàlid: S'ha rebut ${issue.received}`, bytes: (issue) => `Bytes invàlids: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, check: (issue) => `Valor invàlid: S'ha rebut ${issue.received}`, checkAsync: (issue) => `Valor invàlid: S'ha rebut ${issue.received}`, checkItems: (issue) => `Element invàlids: S'ha rebut ${issue.received}`, checkItemsAsync: (issue) => `Element invàlids: S'ha rebut ${issue.received}`, creditCard: (issue) => `Targeta de crèdit invàlida: S'ha rebut ${issue.received}`, cuid2: (issue) => `Cuid2 invàlid: S'ha rebut ${issue.received}`, decimal: (issue) => `Decimal invàlid: S'ha rebut ${issue.received}`, digits: (issue) => `Dígits invàlids: S'ha rebut ${issue.received}`, domain: (issue) => `Domini invàlid: S'ha rebut ${issue.received}`, email: (issue) => `Correu electrònic invàlid: S'ha rebut ${issue.received}`, emoji: (issue) => `Emoji invàlid: S'ha rebut ${issue.received}`, empty: (issue) => `Llargada invàlida: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, endsWith: (issue) => `Final invàlid: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, entries: (issue) => `Entrades invàlides: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, everyItem: (issue) => `Element invàlid: S'ha rebut ${issue.received}`, excludes: (issue) => `Contingut invàlid: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, finite: (issue) => `Finit invàlid: S'ha rebut ${issue.received}`, graphemes: (issue) => `Gràfems invàlids: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, gtValue: (issue) => `Valor invàlid: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, guard: (issue) => `Entrada invàlida: S'ha rebut ${issue.received}`, hash: (issue) => `Hash invàlid: S'ha rebut ${issue.received}`, hexadecimal: (issue) => `Hexadecimal invàlid: S'ha rebut ${issue.received}`, hexColor: (issue) => `Color hexadecimal invàlid: S'ha rebut ${issue.received}`, imei: (issue) => `IMEI invàlid: S'ha rebut ${issue.received}`, includes: (issue) => `Contingut invàlid: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, integer: (issue) => `Enter invàlid: S'ha rebut ${issue.received}`, ip: (issue) => `IP invàlida: S'ha rebut ${issue.received}`, ipv4: (issue) => `IPv4 invàlid: S'ha rebut ${issue.received}`, ipv6: (issue) => `IPv6 invàlid: S'ha rebut ${issue.received}`, isbn: (issue) => `ISBN invàlid: S'ha rebut ${issue.received}`, isoDate: (issue) => `Data invàlida: S'ha rebut ${issue.received}`, isoDateTime: (issue) => `Data-hora invàlida: S'ha rebut ${issue.received}`, isoTime: (issue) => `Hora invàlida: S'ha rebut ${issue.received}`, isoTimeSecond: (issue) => `Segon de temps invàlid: S'ha rebut ${issue.received}`, isoTimestamp: (issue) => `Timestamp invàlid: S'ha rebut ${issue.received}`, isoWeek: (issue) => `Setmana invàlida: S'ha rebut ${issue.received}`, isrc: (issue) => `ISRC invàlid: S'ha rebut ${issue.received}`, jwsCompact: (issue) => `JWS compacte invàlid: S'ha rebut ${issue.received}`, length: (issue) => `Llargada invàlida: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, ltValue: (issue) => `Valor invàlid: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, mac: (issue) => `MAC invàlida: S'ha rebut ${issue.received}`, mac48: (issue) => `MAC de 48 bits invàlida: S'ha rebut ${issue.received}`, mac64: (issue) => `MAC de 64 bits invàlida: S'ha rebut ${issue.received}`, maxBytes: (issue) => `Quantitat de bytes invàlida: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, maxEntries: (issue) => `Entrades invàlides: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, maxGraphemes: (issue) => `Gràfems invàlids: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, maxLength: (issue) => `Llargada invàlida: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, maxSize: (issue) => `Mida invàlida: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, maxValue: (issue) => `Valor invàlid: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, maxWords: (issue) => `Paraules invàlides: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, mimeType: (issue) => `Tipus de MIME invàlid: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, minBytes: (issue) => `Quantitat de bytes invàlida: S'esperava mínim ${issue.expected} però s'ha rebut ${issue.received}`, minEntries: (issue) => `Entrades invàlides: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, minGraphemes: (issue) => `Gràfems invàlids: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, minLength: (issue) => `Llargada invàlida: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, minSize: (issue) => `Mida invàlida: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, minValue: (issue) => `Valor invàlid: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, minWords: (issue) => `Paraules invàlides: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, multipleOf: (issue) => `Múltiple invàlid: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, nanoid: (issue) => `Nano ID invàlid: S'ha rebut ${issue.received}`, nonEmpty: (issue) => `Llargada invàlida: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, notBytes: (issue) => `Bytes invàlids: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, notEntries: (issue) => `Entrades invàlides: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, notGraphemes: (issue) => `Gràfems invàlids: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, notLength: (issue) => `Llargada invàlida: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, notSize: (issue) => `Mida invàlida: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, notValue: (issue) => `Valor invàlid: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, notValues: (issue) => `Valor invàlid: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, notWords: (issue) => `Paraules invàlides: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, octal: (issue) => `Octal invàlid: S'ha rebut ${issue.received}`, parseBoolean: (issue) => `Booleà invàlid: S'ha rebut ${issue.received}`, parseJson: (issue) => `JSON invàlid: S'ha rebut ${issue.received}`, partialCheck: (issue) => `Valor invàlid: S'ha rebut ${issue.received}`, rawCheck: (issue) => `Entrada invàlida: S'ha rebut ${issue.received}`, rawTransform: (issue) => `Entrada invàlida: S'ha rebut ${issue.received}`, regex: (issue) => `Format invàlid: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, rfcEmail: (issue) => `Correu electrònic invàlid: S'ha rebut ${issue.received}`, safeInteger: (issue) => `Enter segur invàlid: S'ha rebut ${issue.received}`, size: (issue) => `Mida invàlida: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, slug: (issue) => `Slug invàlid: S'ha rebut ${issue.received}`, someItem: (issue) => `Element invàlid: S'ha rebut ${issue.received}`, startsWith: (issue) => `Inici invàlid: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, stringifyJson: (issue) => `JSON invàlid: S'ha rebut ${issue.received}`, toBigint: (issue) => `BigInt invàlid: S'ha rebut ${issue.received}`, toDate: (issue) => `Data invàlida: S'ha rebut ${issue.received}`, toNumber: (issue) => `Número invàlid: S'ha rebut ${issue.received}`, toString: (issue) => `Cadena invàlida: S'ha rebut ${issue.received}`, ulid: (issue) => `ULID invàlid: S'ha rebut ${issue.received}`, url: (issue) => `URL invàlida: S'ha rebut ${issue.received}`, uuid: (issue) => `UUID invàlid: S'ha rebut ${issue.received}`, value: (issue) => `Valor invàlid: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, values: (issue) => `Valor invàlid: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, words: (issue) => `Paraules invàlides: S'esperava ${issue.expected} però s'ha rebut ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/cs.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'cs', schema: (issue) => `Neplatný typ: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, specific: { base64: (issue) => `Neplatný Base64: Obdrženo ${issue.received}`, bic: (issue) => `Neplatný BIC: Obdrženo ${issue.received}`, bytes: (issue) => `Neplatné bajty: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, check: (issue) => `Neplatný vstup: Obdrženo ${issue.received}`, checkAsync: (issue) => `Neplatný vstup: Obdrženo ${issue.received}`, checkItems: (issue) => `Neplatná položka: Obdrženo ${issue.received}`, checkItemsAsync: (issue) => `Neplatná položka: Obdrženo ${issue.received}`, creditCard: (issue) => `Neplatná hodnota kreditní karty: Obdrženo ${issue.received}`, cuid2: (issue) => `Neplatné Cuid2: Obdrženo ${issue.received}`, decimal: (issue) => `Neplatné desetinné číslo: Obdrženo ${issue.received}`, digits: (issue) => `Neplatné číslice: Obdrženo ${issue.received}`, domain: (issue) => `Neplatná doména: Obdrženo ${issue.received}`, email: (issue) => `Neplatný email: Obdrženo ${issue.received}`, emoji: (issue) => `Neplatné emoji: Obdrženo ${issue.received}`, empty: (issue) => `Neplatná délka: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, endsWith: (issue) => `Neplatný konec: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, entries: (issue) => `Neplatný počet položek: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, everyItem: (issue) => `Neplatná položka: Obdrženo ${issue.received}`, excludes: (issue) => `Neplatný obsah: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, finite: (issue) => `Neplatné konečné číslo: Obdrženo ${issue.received}`, graphemes: (issue) => `Překročena maximální délka grafémů: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, gtValue: (issue) => `Neplatná hodnota: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, guard: (issue) => `Neplatný vstup: Obdrženo ${issue.received}`, hash: (issue) => `Neplatný hash: Obdrženo ${issue.received}`, hexadecimal: (issue) => `Neplatné hexadecimální číslo: Obdrženo ${issue.received}`, hexColor: (issue) => `Neplatná hexadecimální barva: Obdrženo ${issue.received}`, imei: (issue) => `Neplatné IMEI: Obdrženo ${issue.received}`, includes: (issue) => `Neplatný obsah: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, integer: (issue) => `Neplatné celé číslo: Obdrženo ${issue.received}`, ip: (issue) => `Neplatná IP adresa: Obdrženo ${issue.received}`, ipv4: (issue) => `Neplatná IPv4 adresa: Obdrženo ${issue.received}`, ipv6: (issue) => `Neplatná IPv6 adresa: Obdrženo ${issue.received}`, isbn: (issue) => `Neplatné ISBN: Obdrženo ${issue.received}`, isoDate: (issue) => `Neplatné datum: Obdrženo ${issue.received}`, isoDateTime: (issue) => `Neplatné datum a čas: Obdrženo ${issue.received}`, isoTime: (issue) => `Neplatný čas: Očekáváno "hh:mm", ale obdrženo ${issue.received}`, isoTimeSecond: (issue) => `Neplatný čas: Očekáváno "hh:mm:ss", ale obdrženo ${issue.received}`, isoTimestamp: (issue) => `Neplatný časový údaj: Očekáván ISO 8601 formát, ale obdrženo ${issue.received}`, isoWeek: (issue) => `Neplatný týden: Obdrženo ${issue.received}`, isrc: (issue) => `Neplatné ISRC: Obdrženo ${issue.received}`, jwsCompact: (issue) => `Neplatné kompaktní JWS: Obdrženo ${issue.received}`, length: (issue) => `Neplatná délka: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, ltValue: (issue) => `Neplatná hodnota: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, mac: (issue) => `Neplatná MAC adresa: Obdrženo ${issue.received}`, mac48: (issue) => `Neplatná 48-bitová MAC adresa: Obdrženo ${issue.received}`, mac64: (issue) => `Neplatná 64-bitová MAC adresa: Obdrženo ${issue.received}`, maxBytes: (issue) => `Překročena maximální hodnota v bajtech (bytes): Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, maxEntries: (issue) => `Neplatný počet položek: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, maxGraphemes: (issue) => `Překročena maximální délka grafémů: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, maxLength: (issue) => `Překročena maximální délka: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, maxSize: (issue) => `Překročena maximální velikost: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, maxValue: (issue) => `Překročena maximální hodnota: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, maxWords: (issue) => `Překročena maximální délka slov: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, mimeType: (issue) => `Neplatný MIME typ: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, minBytes: (issue) => `Nedostatečná minimální délka bajtů (bytes): Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, minEntries: (issue) => `Neplatný počet položek: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, minGraphemes: (issue) => `Nedostatečná minimální délka grafémů: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, minLength: (issue) => `Nedostatečná minimální délka: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, minSize: (issue) => `Nedostatečná minimální velikost: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, minValue: (issue) => `Nedostatečná minimální hodnota: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, minWords: (issue) => `Nedostatečná minimální délka slov: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, multipleOf: (issue) => `Neplatný násobek: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, nanoid: (issue) => `Neplatné Nano ID: Obdrženo ${issue.received}`, nonEmpty: (issue) => `Nedostatečná délka: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, notBytes: (issue) => `Nedostatečná minimální délka bajtů (bytes): Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, notEntries: (issue) => `Neplatný počet položek: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, notGraphemes: (issue) => `Nedostatečná minimální délka grafémů: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, notLength: (issue) => `Nedostatečná délka: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, notSize: (issue) => `Nedostatečná minimální velikost: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, notValue: (issue) => `Nedostatečná minimální hodnota: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, notValues: (issue) => `Neplatná hodnota: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, notWords: (issue) => `Nedostatečná minimální délka slov: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, octal: (issue) => `Neplatné osmičkové číslo: Obdrženo ${issue.received}`, parseBoolean: (issue) => `Neplatná logická hodnota: Obdrženo ${issue.received}`, parseJson: (issue) => `Neplatný JSON: Obdrženo ${issue.received}`, partialCheck: (issue) => `Neplatný vstup: Obdrženo ${issue.received}`, rawCheck: (issue) => `Neplatný vstup: Obdrženo ${issue.received}`, rawTransform: (issue) => `Neplatný vstup: Obdrženo ${issue.received}`, regex: (issue) => `Neplatný formát: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, rfcEmail: (issue) => `Neplatný email: Obdrženo ${issue.received}`, safeInteger: (issue) => `Neplatné bezpečné celé číslo: Obdrženo ${issue.received}`, size: (issue) => `Neplatná velikost: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, slug: (issue) => `Neplatný slug: Obdrženo ${issue.received}`, someItem: (issue) => `Neplatná položka: Obdrženo ${issue.received}`, startsWith: (issue) => `Neplatný začátek: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, stringifyJson: (issue) => `Neplatný JSON: Obdrženo ${issue.received}`, toBigint: (issue) => `Neplatný bigint: Obdrženo ${issue.received}`, toDate: (issue) => `Neplatné datum: Obdrženo ${issue.received}`, toNumber: (issue) => `Neplatné číslo: Obdrženo ${issue.received}`, toString: (issue) => `Neplatný řetězec: Obdrženo ${issue.received}`, ulid: (issue) => `Neplatné ULID: Obdrženo ${issue.received}`, url: (issue) => `Neplatná URL: Obdrženo ${issue.received}`, uuid: (issue) => `Neplatné UUID: Obdrženo ${issue.received}`, value: (issue) => `Neplatná hodnota: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, values: (issue) => `Neplatná hodnota: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, words: (issue) => `Překročena maximální délka slov: Očekáváno ${issue.expected}, ale obdrženo ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/de.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'de', schema: (issue) => `Ungültiger Typ: ${issue.expected} erwartet aber ${issue.received} erhalten`, specific: { base64: (issue) => `Ungültiges Base64: ${issue.received} erhalten`, bic: (issue) => `Ungültiger BIC: ${issue.received} erhalten`, bytes: (issue) => `Ungültige Bytes: ${issue.expected} erwartet aber ${issue.received} erhalten`, check: (issue) => `Ungültige Eingabe: ${issue.received} erhalten`, checkAsync: (issue) => `Ungültige Eingabe: ${issue.received} erhalten`, checkItems: (issue) => `Ungültiges Element: ${issue.received} erhalten`, checkItemsAsync: (issue) => `Ungültiges Element: ${issue.received} erhalten`, creditCard: (issue) => `Ungültige Kreditkarte: ${issue.received} erhalten`, cuid2: (issue) => `Ungültige Cuid2: ${issue.received} erhalten`, decimal: (issue) => `Ungültige Dezimale: ${issue.received} erhalten`, digits: (issue) => `Ungültige Ziffern: ${issue.received} erhalten`, domain: (issue) => `Ungültige Domain: ${issue.received} erhalten`, email: (issue) => `Ungültige E-Mail: ${issue.received} erhalten`, emoji: (issue) => `Ungültiges Emoji: ${issue.received} erhalten`, empty: (issue) => `Ungültige Länge: ${issue.expected} erwartet aber ${issue.received} erhalten`, endsWith: (issue) => `Ungültiges Ende: ${issue.expected} erwartet aber ${issue.received} erhalten`, entries: (issue) => `Ungültige Einträge: ${issue.expected} erwartet aber ${issue.received} erhalten`, everyItem: (issue) => `Ungültiges Element: ${issue.received} erhalten`, excludes: (issue) => `Ungültiger Inhalt: ${issue.expected} erwartet aber ${issue.received} erhalten`, finite: (issue) => `Ungültiges Endliche: ${issue.received} erhalten`, graphemes: (issue) => `Ungültige Grapheme: ${issue.expected} erwartet aber ${issue.received} erhalten`, gtValue: (issue) => `Ungültiger Wert: ${issue.expected} erwartet aber ${issue.received} erhalten`, guard: (issue) => `Ungültige Eingabe: ${issue.received} erhalten`, hash: (issue) => `Ungültiger Hash: ${issue.received} erhalten`, hexadecimal: (issue) => `Ungültige Hexadezimale: ${issue.received} erhalten`, hexColor: (issue) => `Ungültige Hex-Farbe: ${issue.received} erhalten`, imei: (issue) => `Ungültige IMEI: ${issue.received} erhalten`, includes: (issue) => `Ungültiger Inhalt: ${issue.expected} erwartet aber ${issue.received} erhalten`, integer: (issue) => `Ungültige Ganzzahl: ${issue.received} erhalten`, ip: (issue) => `Ungültige IP: ${issue.received} erhalten`, ipv4: (issue) => `Ungültige IPv4: ${issue.received} erhalten`, ipv6: (issue) => `Ungültige IPv6: ${issue.received} erhalten`, isbn: (issue) => `Ungültige ISBN: ${issue.received} erhalten`, isoDate: (issue) => `Ungültiges Datum: ${issue.received} erhalten`, isoDateTime: (issue) => `Ungültige Datums-Zeit: ${issue.received} erhalten`, isoTime: (issue) => `Ungültige Zeit: ${issue.received} erhalten`, isoTimeSecond: (issue) => `Ungültige Zeitsekunde: ${issue.received} erhalten`, isoTimestamp: (issue) => `Ungültiger Zeitstempel: ${issue.received} erhalten`, isoWeek: (issue) => `Ungültige Woche: ${issue.received} erhalten`, isrc: (issue) => `Ungültige ISRC: ${issue.received} erhalten`, jwsCompact: (issue) => `Ungültiges kompaktes JWS: ${issue.received} erhalten`, length: (issue) => `Ungültige Länge: ${issue.expected} erwartet aber ${issue.received} erhalten`, ltValue: (issue) => `Ungültiger Wert: ${issue.expected} erwartet aber ${issue.received} erhalten`, mac: (issue) => `Ungültige MAC: ${issue.received} erhalten`, mac48: (issue) => `Ungültige 48-bit MAC: ${issue.received} erhalten`, mac64: (issue) => `Ungültige 64-bit MAC: ${issue.received} erhalten`, maxBytes: (issue) => `Ungültige Bytes: ${issue.expected} erwartet aber ${issue.received} erhalten`, maxEntries: (issue) => `Ungültige Einträge: ${issue.expected} erwartet aber ${issue.received} erhalten`, maxGraphemes: (issue) => `Ungültige Grapheme: ${issue.expected} erwartet aber ${issue.received} erhalten`, maxLength: (issue) => `Ungültige Länge: ${issue.expected} erwartet aber ${issue.received} erhalten`, maxSize: (issue) => `Ungültige Größe: ${issue.expected} erwartet aber ${issue.received} erhalten`, maxValue: (issue) => `Ungültiger Wert: ${issue.expected} erwartet aber ${issue.received} erhalten`, maxWords: (issue) => `Ungültige Wörter: ${issue.expected} erwartet aber ${issue.received} erhalten`, mimeType: (issue) => `Ungültiger MIME-Typ: ${issue.expected} erwartet aber ${issue.received} erhalten`, minBytes: (issue) => `Ungültige Bytes: ${issue.expected} erwartet aber ${issue.received} erhalten`, minEntries: (issue) => `Ungültige Einträge: ${issue.expected} erwartet aber ${issue.received} erhalten`, minGraphemes: (issue) => `Ungültige Grapheme: ${issue.expected} erwartet aber ${issue.received} erhalten`, minLength: (issue) => `Ungültige Länge: ${issue.expected} erwartet aber ${issue.received} erhalten`, minSize: (issue) => `Ungültige Größe: ${issue.expected} erwartet aber ${issue.received} erhalten`, minValue: (issue) => `Ungültiger Wert: ${issue.expected} erwartet aber ${issue.received} erhalten`, minWords: (issue) => `Ungültige Wörter: ${issue.expected} erwartet aber ${issue.received} erhalten`, multipleOf: (issue) => `Ungültiges Vielfaches: ${issue.expected} erwartet aber ${issue.received} erhalten`, nanoid: (issue) => `Ungültige Nano-ID: ${issue.received} erhalten`, nonEmpty: (issue) => `Ungültige Länge: ${issue.expected} erwartet aber ${issue.received} erhalten`, notBytes: (issue) => `Ungültige Bytes: ${issue.expected} erwartet aber ${issue.received} erhalten`, notEntries: (issue) => `Ungültige Einträge: ${issue.expected} erwartet aber ${issue.received} erhalten`, notGraphemes: (issue) => `Ungültige Grapheme: ${issue.expected} erwartet aber ${issue.received} erhalten`, notLength: (issue) => `Ungültige Länge: ${issue.expected} erwartet aber ${issue.received} erhalten`, notSize: (issue) => `Ungültige Größe: ${issue.expected} erwartet aber ${issue.received} erhalten`, notValue: (issue) => `Ungültiger Wert: ${issue.expected} erwartet aber ${issue.received} erhalten`, notValues: (issue) => `Ungültiger Wert: ${issue.expected} erwartet aber ${issue.received} erhalten`, notWords: (issue) => `Ungültige Wörter: ${issue.expected} erwartet aber ${issue.received} erhalten`, octal: (issue) => `Ungültiges Octal: ${issue.received} erhalten`, parseBoolean: (issue) => `Ungültiger boolescher Wert: ${issue.received} erhalten`, parseJson: (issue) => `Ungültiges JSON: ${issue.received} erhalten`, partialCheck: (issue) => `Ungültige Eingabe: ${issue.received} erhalten`, rawCheck: (issue) => `Ungültige Eingabe: ${issue.received} erhalten`, rawTransform: (issue) => `Ungültige Eingabe: ${issue.received} erhalten`, regex: (issue) => `Ungültiges Format: ${issue.expected} erwartet aber ${issue.received} erhalten`, rfcEmail: (issue) => `Ungültige E-Mail: ${issue.received} erhalten`, safeInteger: (issue) => `Ungültige sichere Ganzzahl: ${issue.received} erhalten`, size: (issue) => `Ungültige Größe: ${issue.expected} erwartet aber ${issue.received} erhalten`, slug: (issue) => `Ungültiger Slug: ${issue.received} erhalten`, someItem: (issue) => `Ungültiges Element: ${issue.received} erhalten`, startsWith: (issue) => `Ungültiger Start: ${issue.expected} erwartet aber ${issue.received} erhalten`, stringifyJson: (issue) => `Ungültiges JSON: ${issue.received} erhalten`, toBigint: (issue) => `Ungültiger BigInt: ${issue.received} erhalten`, toDate: (issue) => `Ungültiges Datum: ${issue.received} erhalten`, toNumber: (issue) => `Ungültige Zahl: ${issue.received} erhalten`, toString: (issue) => `Ungültige Zeichenkette: ${issue.received} erhalten`, ulid: (issue) => `Ungültige ULID: ${issue.received} erhalten`, url: (issue) => `Ungültige URL: ${issue.received} erhalten`, uuid: (issue) => `Ungültige UUID: ${issue.received} erhalten`, value: (issue) => `Ungültiger Wert: ${issue.expected} erwartet aber ${issue.received} erhalten`, values: (issue) => `Ungültiger Wert: ${issue.expected} erwartet aber ${issue.received} erhalten`, words: (issue) => `Ungültige Wörter: ${issue.expected} erwartet aber ${issue.received} erhalten`, }, }; export default language; ================================================ FILE: packages/i18n/src/el.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'el', schema: (issue) => `Λάθος τύπος: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, specific: { base64: (issue) => `Λάθος Base64: Ήρθε ${issue.received}`, bic: (issue) => `Λάθος BIC: Ήρθε ${issue.received}`, bytes: (issue) => `Λάθος bytes: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, check: (issue) => `Λάθος είσοδος: Ήρθε ${issue.received}`, checkAsync: (issue) => `Λάθος είσοδος: Ήρθε ${issue.received}`, checkItems: (issue) => `Λάθος στοιχείο: Ήρθε ${issue.received}`, checkItemsAsync: (issue) => `Λάθος στοιχείο: Ήρθε ${issue.received}`, creditCard: (issue) => `Λάθος πιστωτική κάρτα: Ήρθε ${issue.received}`, cuid2: (issue) => `Λάθος Cuid2: Ήρθε ${issue.received}`, decimal: (issue) => `Λάθος δεκαδικός: Ήρθε ${issue.received}`, digits: (issue) => `Λάθος ψηφία: Ήρθε ${issue.received}`, domain: (issue) => `Λάθος τομέας: Ήρθε ${issue.received}`, email: (issue) => `Λάθος email: Ήρθε ${issue.received}`, emoji: (issue) => `Λάθος emoji: Ήρθε ${issue.received}`, empty: (issue) => `Λάθος μέγεθος: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, endsWith: (issue) => `Λάθος τέλος: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, entries: (issue) => `Λάθος καταχωρήσεις: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, everyItem: (issue) => `Λάθος στοιχείο: Ήρθε ${issue.received}`, excludes: (issue) => `Λάθος περιεχόμενο: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, finite: (issue) => `Μη πεπερασμένη τιμή: Ήρθε ${issue.received}`, graphemes: (issue) => `Λάθος γραφήματα: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, gtValue: (issue) => `Λάθος τιμή: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, guard: (issue) => `Λάθος είσοδος: Ήρθε ${issue.received}`, hash: (issue) => `Λάθος σύνοψη: Ήρθε ${issue.received}`, hexadecimal: (issue) => `Λάθος δεκαεξαδικός: Ήρθε ${issue.received}`, hexColor: (issue) => `Λάθος hex χρώμα: Ήρθε ${issue.received}`, imei: (issue) => `Λάθος IMEI: Ήρθε ${issue.received}`, includes: (issue) => `Λάθος περιεχόμενο: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, integer: (issue) => `Λάθος ακέραιος: Ήρθε ${issue.received}`, ip: (issue) => `Λάθος IP: Ήρθε ${issue.received}`, ipv4: (issue) => `Λάθος IPv4: Ήρθε ${issue.received}`, ipv6: (issue) => `Λάθος IPv6: Ήρθε ${issue.received}`, isbn: (issue) => `Λάθος ISBN: Ήρθε ${issue.received}`, isoDate: (issue) => `Λάθος ημερομηνία: Ήρθε ${issue.received}`, isoDateTime: (issue) => `Λάθος ημερομηνία-ώρα: Ήρθε ${issue.received}`, isoTime: (issue) => `Λάθος ώρα: Ήρθε ${issue.received}`, isoTimeSecond: (issue) => `Λάθος ώρα με δευτερόλεπτα: Ήρθε ${issue.received}`, isoTimestamp: (issue) => `Λάθος χρονοσήμανση: Ήρθε ${issue.received}`, isoWeek: (issue) => `Λάθος εβδομάδα: Ήρθε ${issue.received}`, isrc: (issue) => `Λάθος ISRC: Ήρθε ${issue.received}`, jwsCompact: (issue) => `Λάθος συμπαγές JWS: Ήρθε ${issue.received}`, length: (issue) => `Λάθος μήκος: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, ltValue: (issue) => `Λάθος τιμή: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, mac: (issue) => `Λάθος MAC: Ήρθε ${issue.received}`, mac48: (issue) => `Λάθος 48-bit MAC: Ήρθε ${issue.received}`, mac64: (issue) => `Λάθος 64-bit MAC: Ήρθε ${issue.received}`, maxBytes: (issue) => `Λάθος bytes: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, maxEntries: (issue) => `Λάθος καταχωρήσεις: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, maxGraphemes: (issue) => `Λάθος γραφήματα: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, maxLength: (issue) => `Λάθος μήκος: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, maxSize: (issue) => `Λάθος μέγεθος: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, maxValue: (issue) => `Λάθος τιμή: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, maxWords: (issue) => `Λάθος λέξεις: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, mimeType: (issue) => `Λάθος τύπος MIME: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, minBytes: (issue) => `Λάθος bytes: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, minEntries: (issue) => `Λάθος καταχωρήσεις: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, minGraphemes: (issue) => `Λάθος γραφήματα: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, minLength: (issue) => `Λάθος μήκος: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, minSize: (issue) => `Λάθος μέγεθος: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, minValue: (issue) => `Λάθος τιμή: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, minWords: (issue) => `Λάθος λέξεις: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, multipleOf: (issue) => `Λάθος πολλαπλάσιο: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, nanoid: (issue) => `Λάθος Nano ID: Ήρθε ${issue.received}`, nonEmpty: (issue) => `Λάθος μήκος: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, notBytes: (issue) => `Λάθος bytes: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, notEntries: (issue) => `Λάθος καταχωρήσεις: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, notGraphemes: (issue) => `Λάθος γραφήματα: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, notLength: (issue) => `Λάθος μήκος: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, notSize: (issue) => `Λάθος μέγεθος: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, notValue: (issue) => `Λάθος τιμή: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, notValues: (issue) => `Λάθος τιμές: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, notWords: (issue) => `Λάθος λέξεις: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, octal: (issue) => `Λάθος οκταδικός: Ήρθε ${issue.received}`, parseBoolean: (issue) => `Λάθος λογική τιμή: Ήρθε ${issue.received}`, parseJson: (issue) => `Λάθος JSON: Ήρθε ${issue.received}`, partialCheck: (issue) => `Λάθος είσοδος: Ήρθε ${issue.received}`, rawCheck: (issue) => `Λάθος είσοδος: Ήρθε ${issue.received}`, rawTransform: (issue) => `Λάθος είσοδος: Ήρθε ${issue.received}`, regex: (issue) => `Λάθος μορφή: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, rfcEmail: (issue) => `Λάθος email: Ήρθε ${issue.received}`, safeInteger: (issue) => `Λάθος ασφαλής ακέραιος: Ήρθε ${issue.received}`, size: (issue) => `Λάθος μέγεθος: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, slug: (issue) => `Λάθος αναγνωριστικό: Ήρθε ${issue.received}`, someItem: (issue) => `Λάθος στοιχείο: Ήρθε ${issue.received}`, startsWith: (issue) => `Λάθος αρχή: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, stringifyJson: (issue) => `Λάθος JSON: Ήρθε ${issue.received}`, toBigint: (issue) => `Λάθος BigInt: Ήρθε ${issue.received}`, toDate: (issue) => `Λάθος ημερομηνία: Ήρθε ${issue.received}`, toNumber: (issue) => `Λάθος αριθμός: Ήρθε ${issue.received}`, toString: (issue) => `Λάθος συμβολοσειρά: Ήρθε ${issue.received}`, ulid: (issue) => `Λάθος ULID: Ήρθε ${issue.received}`, url: (issue) => `Λάθος URL: Ήρθε ${issue.received}`, uuid: (issue) => `Λάθος UUID: Ήρθε ${issue.received}`, value: (issue) => `Λάθος τιμή: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, values: (issue) => `Λάθος τιμή: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, words: (issue) => `Λάθος λέξεις: Αναμενόταν ${issue.expected} αλλά ήρθε ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/en.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'en', schema: (issue) => `Invalid type: Expected ${issue.expected} but received ${issue.received}`, specific: { base64: (issue) => `Invalid Base64: Received ${issue.received}`, bic: (issue) => `Invalid BIC: Received ${issue.received}`, bytes: (issue) => `Invalid bytes: Expected ${issue.expected} but received ${issue.received}`, check: (issue) => `Invalid input: Received ${issue.received}`, checkAsync: (issue) => `Invalid input: Received ${issue.received}`, checkItems: (issue) => `Invalid item: Received ${issue.received}`, checkItemsAsync: (issue) => `Invalid item: Received ${issue.received}`, creditCard: (issue) => `Invalid credit card: Received ${issue.received}`, cuid2: (issue) => `Invalid Cuid2: Received ${issue.received}`, decimal: (issue) => `Invalid decimal: Received ${issue.received}`, digits: (issue) => `Invalid digits: Received ${issue.received}`, domain: (issue) => `Invalid domain: Received ${issue.received}`, email: (issue) => `Invalid email: Received ${issue.received}`, emoji: (issue) => `Invalid emoji: Received ${issue.received}`, empty: (issue) => `Invalid length: Expected ${issue.expected} but received ${issue.received}`, endsWith: (issue) => `Invalid end: Expected ${issue.expected} but received ${issue.received}`, entries: (issue) => `Invalid entries: Expected ${issue.expected} but received ${issue.received}`, everyItem: (issue) => `Invalid item: Received ${issue.received}`, excludes: (issue) => `Invalid content: Expected ${issue.expected} but received ${issue.received}`, finite: (issue) => `Invalid finite: Received ${issue.received}`, graphemes: (issue) => `Invalid graphemes: Expected ${issue.expected} but received ${issue.received}`, gtValue: (issue) => `Invalid value: Expected ${issue.expected} but received ${issue.received}`, guard: (issue) => `Invalid input: Received ${issue.received}`, hash: (issue) => `Invalid hash: Received ${issue.received}`, hexadecimal: (issue) => `Invalid hexadecimal: Received ${issue.received}`, hexColor: (issue) => `Invalid hex color: Received ${issue.received}`, imei: (issue) => `Invalid IMEI: Received ${issue.received}`, includes: (issue) => `Invalid content: Expected ${issue.expected} but received ${issue.received}`, integer: (issue) => `Invalid integer: Received ${issue.received}`, ip: (issue) => `Invalid IP: Received ${issue.received}`, ipv4: (issue) => `Invalid IPv4: Received ${issue.received}`, ipv6: (issue) => `Invalid IPv6: Received ${issue.received}`, isbn: (issue) => `Invalid ISBN: Received ${issue.received}`, isoDate: (issue) => `Invalid date: Received ${issue.received}`, isoDateTime: (issue) => `Invalid date-time: Received ${issue.received}`, isoTime: (issue) => `Invalid time: Received ${issue.received}`, isoTimeSecond: (issue) => `Invalid time second: Received ${issue.received}`, isoTimestamp: (issue) => `Invalid timestamp: Received ${issue.received}`, isoWeek: (issue) => `Invalid week: Received ${issue.received}`, isrc: (issue) => `Invalid ISRC: Received ${issue.received}`, jwsCompact: (issue) => `Invalid JWS compact: Received ${issue.received}`, length: (issue) => `Invalid length: Expected ${issue.expected} but received ${issue.received}`, ltValue: (issue) => `Invalid value: Expected ${issue.expected} but received ${issue.received}`, mac: (issue) => `Invalid MAC: Received ${issue.received}`, mac48: (issue) => `Invalid 48-bit MAC: Received ${issue.received}`, mac64: (issue) => `Invalid 64-bit MAC: Received ${issue.received}`, maxBytes: (issue) => `Invalid bytes: Expected ${issue.expected} but received ${issue.received}`, maxEntries: (issue) => `Invalid entries: Expected ${issue.expected} but received ${issue.received}`, maxGraphemes: (issue) => `Invalid graphemes: Expected ${issue.expected} but received ${issue.received}`, maxLength: (issue) => `Invalid length: Expected ${issue.expected} but received ${issue.received}`, maxSize: (issue) => `Invalid size: Expected ${issue.expected} but received ${issue.received}`, maxValue: (issue) => `Invalid value: Expected ${issue.expected} but received ${issue.received}`, maxWords: (issue) => `Invalid words: Expected ${issue.expected} but received ${issue.received}`, mimeType: (issue) => `Invalid MIME type: Expected ${issue.expected} but received ${issue.received}`, minBytes: (issue) => `Invalid bytes: Expected ${issue.expected} but received ${issue.received}`, minEntries: (issue) => `Invalid entries: Expected ${issue.expected} but received ${issue.received}`, minGraphemes: (issue) => `Invalid graphemes: Expected ${issue.expected} but received ${issue.received}`, minLength: (issue) => `Invalid length: Expected ${issue.expected} but received ${issue.received}`, minSize: (issue) => `Invalid size: Expected ${issue.expected} but received ${issue.received}`, minValue: (issue) => `Invalid value: Expected ${issue.expected} but received ${issue.received}`, minWords: (issue) => `Invalid words: Expected ${issue.expected} but received ${issue.received}`, multipleOf: (issue) => `Invalid multiple: Expected ${issue.expected} but received ${issue.received}`, nanoid: (issue) => `Invalid Nano ID: Received ${issue.received}`, nonEmpty: (issue) => `Invalid length: Expected ${issue.expected} but received ${issue.received}`, notBytes: (issue) => `Invalid bytes: Expected ${issue.expected} but received ${issue.received}`, notEntries: (issue) => `Invalid entries: Expected ${issue.expected} but received ${issue.received}`, notGraphemes: (issue) => `Invalid graphemes: Expected ${issue.expected} but received ${issue.received}`, notLength: (issue) => `Invalid length: Expected ${issue.expected} but received ${issue.received}`, notSize: (issue) => `Invalid size: Expected ${issue.expected} but received ${issue.received}`, notValue: (issue) => `Invalid value: Expected ${issue.expected} but received ${issue.received}`, notValues: (issue) => `Invalid value: Expected ${issue.expected} but received ${issue.received}`, notWords: (issue) => `Invalid words: Expected ${issue.expected} but received ${issue.received}`, octal: (issue) => `Invalid octal: Received ${issue.received}`, parseBoolean: (issue) => `Invalid boolean: Received ${issue.received}`, parseJson: (issue) => `Invalid JSON: Received ${issue.received}`, partialCheck: (issue) => `Invalid input: Received ${issue.received}`, rawCheck: (issue) => `Invalid input: Received ${issue.received}`, rawTransform: (issue) => `Invalid input: Received ${issue.received}`, regex: (issue) => `Invalid format: Expected ${issue.expected} but received ${issue.received}`, rfcEmail: (issue) => `Invalid email: Received ${issue.received}`, safeInteger: (issue) => `Invalid safe integer: Received ${issue.received}`, size: (issue) => `Invalid size: Expected ${issue.expected} but received ${issue.received}`, slug: (issue) => `Invalid slug: Received ${issue.received}`, someItem: (issue) => `Invalid item: Received ${issue.received}`, startsWith: (issue) => `Invalid start: Expected ${issue.expected} but received ${issue.received}`, stringifyJson: (issue) => `Invalid JSON: Received ${issue.received}`, toBigint: (issue) => `Invalid bigint: Received ${issue.received}`, toDate: (issue) => `Invalid date: Received ${issue.received}`, toNumber: (issue) => `Invalid number: Received ${issue.received}`, toString: (issue) => `Invalid string: Received ${issue.received}`, ulid: (issue) => `Invalid ULID: Received ${issue.received}`, url: (issue) => `Invalid URL: Received ${issue.received}`, uuid: (issue) => `Invalid UUID: Received ${issue.received}`, value: (issue) => `Invalid value: Expected ${issue.expected} but received ${issue.received}`, values: (issue) => `Invalid value: Expected ${issue.expected} but received ${issue.received}`, words: (issue) => `Invalid words: Expected ${issue.expected} but received ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/es.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'es', schema: (issue) => `Tipo inválido: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, specific: { base64: (issue) => `Base64 inválido: Se recibió ${issue.received}`, bic: (issue) => `BIC inválido: Se recibió ${issue.received}`, bytes: (issue) => `Bytes inválidos: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, check: (issue) => `Valor inválido: Se recibió ${issue.received}`, checkAsync: (issue) => `Valor inválido: Se recibió ${issue.received}`, checkItems: (issue) => `Artículo inválidos: Se recibió ${issue.received}`, checkItemsAsync: (issue) => `Artículo inválidos: Se recibió ${issue.received}`, creditCard: (issue) => `Tarjeta de crédito inválida: Se recibió ${issue.received}`, cuid2: (issue) => `Cuid2 inválido: Se recibió ${issue.received}`, decimal: (issue) => `Decimal inválido: Se recibió ${issue.received}`, digits: (issue) => `Dígitos inválidos: Se recibió ${issue.received}`, domain: (issue) => `Dominio inválido: Se recibió ${issue.received}`, email: (issue) => `Correo electrónico inválido: Se recibió ${issue.received}`, emoji: (issue) => `Emoji inválido: Se recibió ${issue.received}`, empty: (issue) => `Longitud inválida: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, endsWith: (issue) => `Final inválido: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, entries: (issue) => `Entradas inválidas: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, everyItem: (issue) => `Artículo inválido: Se recibió ${issue.received}`, excludes: (issue) => `Contenido inválido: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, finite: (issue) => `Finito inválido: Se recibió ${issue.received}`, graphemes: (issue) => `Grafemas inválidos: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, gtValue: (issue) => `Valor inválido: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, guard: (issue) => `Entrada inválida: Se recibió ${issue.received}`, hash: (issue) => `Hash inválido: Se recibió ${issue.received}`, hexadecimal: (issue) => `Hexadecimal inválido: Se recibió ${issue.received}`, hexColor: (issue) => `Color hexadecimal inválido: Se recibió ${issue.received}`, imei: (issue) => `IMEI inválido: Se recibió ${issue.received}`, includes: (issue) => `Contenido inválido: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, integer: (issue) => `Entero inválido: Se recibió ${issue.received}`, ip: (issue) => `IP inválida: Se recibió ${issue.received}`, ipv4: (issue) => `IPv4 inválido: Se recibió ${issue.received}`, ipv6: (issue) => `IPv6 inválido: Se recibió ${issue.received}`, isbn: (issue) => `ISBN inválido: Se recibió ${issue.received}`, isoDate: (issue) => `Fecha inválida: Se recibió ${issue.received}`, isoDateTime: (issue) => `Fecha-hora inválida: Se recibió ${issue.received}`, isoTime: (issue) => `Hora inválida: Se recibió ${issue.received}`, isoTimeSecond: (issue) => `Segundo de tiempo inválido: Se recibió ${issue.received}`, isoTimestamp: (issue) => `Marca de tiempo inválida: Se recibió ${issue.received}`, isoWeek: (issue) => `Semana inválida: Se recibió ${issue.received}`, isrc: (issue) => `ISRC inválido: Se recibió ${issue.received}`, jwsCompact: (issue) => `JWS compacto inválido: Se recibió ${issue.received}`, length: (issue) => `Longitud inválida: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, ltValue: (issue) => `Valor inválido: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, mac: (issue) => `MAC inválida: Se recibió ${issue.received}`, mac48: (issue) => `MAC de 48 bits inválida: Se recibió ${issue.received}`, mac64: (issue) => `MAC de 64 bits inválida: Se recibió ${issue.received}`, maxBytes: (issue) => `Cantidad de bytes inválidos: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, maxEntries: (issue) => `Entradas inválidas: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, maxGraphemes: (issue) => `Grafemas inválidos: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, maxLength: (issue) => `Longitud inválida: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, maxSize: (issue) => `Tamaño inválido: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, maxValue: (issue) => `Valor inválido: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, maxWords: (issue) => `Palabras inválidas: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, mimeType: (issue) => `Tipo de MIME inválido: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, minBytes: (issue) => `Cantidad de bytes inválidos: Se esperaba mínimo ${issue.expected} pero se recibió ${issue.received}`, minEntries: (issue) => `Entradas inválidas: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, minGraphemes: (issue) => `Grafemas inválidos: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, minLength: (issue) => `Longitud inválida: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, minSize: (issue) => `Tamaño inválido: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, minValue: (issue) => `Valor inválido: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, minWords: (issue) => `Palabras inválidas: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, multipleOf: (issue) => `Múltiplo inválido: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, nanoid: (issue) => `ID Nano inválido: Se recibió ${issue.received}`, nonEmpty: (issue) => `Longitud inválida: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, notBytes: (issue) => `Bytes inválidos: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, notEntries: (issue) => `Entradas inválidas: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, notGraphemes: (issue) => `Grafemas inválidos: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, notLength: (issue) => `Longitud inválida: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, notSize: (issue) => `Tamaño inválido: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, notValue: (issue) => `Valor inválido: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, notValues: (issue) => `Valor inválido: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, notWords: (issue) => `Palabras inválidas: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, octal: (issue) => `Octal inválido: Se recibió ${issue.received}`, parseBoolean: (issue) => `Booleano inválido: Se recibió ${issue.received}`, parseJson: (issue) => `JSON inválido: Se recibió ${issue.received}`, partialCheck: (issue) => `Valor inválido: Se recibió ${issue.received}`, rawCheck: (issue) => `Entrada inválida: Se recibió ${issue.received}`, rawTransform: (issue) => `Entrada inválida: Se recibió ${issue.received}`, regex: (issue) => `Formato inválido: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, rfcEmail: (issue) => `Correo electrónico inválido: Se recibió ${issue.received}`, safeInteger: (issue) => `Entero seguro inválido: Se recibió ${issue.received}`, size: (issue) => `Tamaño inválido: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, slug: (issue) => `Slug inválido: Se recibió ${issue.received}`, someItem: (issue) => `Artículo inválido: Se recibió ${issue.received}`, startsWith: (issue) => `Inicio inválido: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, stringifyJson: (issue) => `JSON inválido: Se recibió ${issue.received}`, toBigint: (issue) => `BigInt inválido: Se recibió ${issue.received}`, toDate: (issue) => `Fecha inválida: Se recibió ${issue.received}`, toNumber: (issue) => `Número inválido: Se recibió ${issue.received}`, toString: (issue) => `Cadena inválida: Se recibió ${issue.received}`, ulid: (issue) => `ULID inválido: Se recibió ${issue.received}`, url: (issue) => `URL inválida: Se recibió ${issue.received}`, uuid: (issue) => `UUID inválido: Se recibió ${issue.received}`, value: (issue) => `Valor inválido: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, values: (issue) => `Valor inválido: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, words: (issue) => `Palabras inválidas: Se esperaba ${issue.expected} pero se recibió ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/fa.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'fa', schema: (issue) => `نوع نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, specific: { base64: (issue) => `Base64 نامعتبر: ${issue.received} دریافت شد`, bic: (issue) => `BIC نامعتبر: ${issue.received} دریافت شد`, bytes: (issue) => `بایت‌های نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, check: (issue) => `ورودی نامعتبر: ${issue.received} دریافت شد`, checkAsync: (issue) => `ورودی نامعتبر: ${issue.received} دریافت شد`, checkItems: (issue) => `آیتم نامعتبر: ${issue.received} دریافت شد`, checkItemsAsync: (issue) => `آیتم نامعتبر: ${issue.received} دریافت شد`, creditCard: (issue) => `کارت اعتباری نامعتبر: ${issue.received} دریافت شد`, cuid2: (issue) => `Cuid2 نامعتبر: ${issue.received} دریافت شد`, decimal: (issue) => `اعشار نامعتبر: ${issue.received} دریافت شد`, digits: (issue) => `ارقام نامعتبر: ${issue.received} دریافت شد`, domain: (issue) => `دامنه نامعتبر: ${issue.received} دریافت شد`, email: (issue) => `ایمیل نامعتبر: ${issue.received} دریافت شد`, emoji: (issue) => `ایموجی نامعتبر: ${issue.received} دریافت شد`, empty: (issue) => `طول نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, endsWith: (issue) => `پایان نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, entries: (issue) => `تعداد ورودی نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, everyItem: (issue) => `آیتم نامعتبر: ${issue.received} دریافت شد`, excludes: (issue) => `محتوای نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, finite: (issue) => `عدد متناهی نامعتبر: ${issue.received} دریافت شد`, graphemes: (issue) => `گرافم‌های نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, gtValue: (issue) => `مقدار نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, guard: (issue) => `ورودی نامعتبر: ${issue.received} دریافت شد`, hash: (issue) => `هش نامعتبر: ${issue.received} دریافت شد`, hexadecimal: (issue) => `هگزادسیمال نامعتبر: ${issue.received} دریافت شد`, hexColor: (issue) => `رنگ هگزادسیمال نامعتبر: ${issue.received} دریافت شد`, imei: (issue) => `IMEI نامعتبر: ${issue.received} دریافت شد`, includes: (issue) => `محتوای نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, integer: (issue) => `عدد صحیح نامعتبر: ${issue.received} دریافت شد`, ip: (issue) => `ip نامعتبر: ${issue.received} دریافت شد`, ipv4: (issue) => `IPv4 نامعتبر: ${issue.received} دریافت شد`, ipv6: (issue) => `IPv6 نامعتبر: ${issue.received} دریافت شد`, isbn: (issue) => `ISBN نامعتبر: ${issue.received} دریافت شد`, isoDate: (issue) => `تاریخ ISO نامعتبر: ${issue.received} دریافت شد`, isoDateTime: (issue) => `تاریخ‌ و زمان ISO نامعتبر: ${issue.received} دریافت شد`, isoTime: (issue) => `زمان ISO نامعتبر: ${issue.received} دریافت شد`, isoTimeSecond: (issue) => `ثانیه ISO نامعتبر: ${issue.received} دریافت شد`, isoTimestamp: (issue) => `تایم‌استمپ ISO نامعتبر: ${issue.received} دریافت شد`, isoWeek: (issue) => `هفته ISO نامعتبر: ${issue.received} دریافت شد`, isrc: (issue) => `ISRC نامعتبر: ${issue.received} دریافت شد`, jwsCompact: (issue) => `JWS فشرده نامعتبر: ${issue.received} دریافت شد`, length: (issue) => `طول نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, ltValue: (issue) => `مقدار نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, mac: (issue) => `MAC نامعتبر: ${issue.received} دریافت شد`, mac48: (issue) => `MAC 48 بیتی نامعتبر: ${issue.received} دریافت شد`, mac64: (issue) => `MAC 64 بیتی نامعتبر: ${issue.received} دریافت شد`, maxBytes: (issue) => `بایت‌های نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, maxEntries: (issue) => `تعداد ورودی نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, maxGraphemes: (issue) => `گرافم‌های نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, maxLength: (issue) => `طول نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, maxSize: (issue) => `اندازه نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, maxValue: (issue) => `مقدار نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, maxWords: (issue) => `کلمات نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, mimeType: (issue) => `MIME type نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, minBytes: (issue) => `بایت‌های نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, minEntries: (issue) => `تعداد ورودی نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, minGraphemes: (issue) => `گرافم‌های نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, minLength: (issue) => `طول نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, minSize: (issue) => `اندازه نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, minValue: (issue) => `مقدار نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, minWords: (issue) => `کلمات نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, multipleOf: (issue) => `ضریب نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, nanoid: (issue) => `Nano ID نامعتبر: ${issue.received} دریافت شد`, nonEmpty: (issue) => `طول نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, notBytes: (issue) => `بایت‌های نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, notEntries: (issue) => `تعداد ورودی نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, notGraphemes: (issue) => `گرافم‌های نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, notLength: (issue) => `طول نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, notSize: (issue) => `اندازه نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, notValue: (issue) => `مقدار نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, notValues: (issue) => `مقدار نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, notWords: (issue) => `کلمات نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, octal: (issue) => `هشت‌دویی نامعتبر: ${issue.received} دریافت شد`, parseBoolean: (issue) => `مقدار بولی نامعتبر: ${issue.received} دریافت شد`, parseJson: (issue) => `JSON نامعتبر: ${issue.received} دریافت شد`, partialCheck: (issue) => `ورودی نامعتبر: ${issue.received} دریافت شد`, rawCheck: (issue) => `ورودی نامعتبر: ${issue.received} دریافت شد`, rawTransform: (issue) => `ورودی نامعتبر: ${issue.received} دریافت شد`, regex: (issue) => `قالب نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, rfcEmail: (issue) => `ایمیل نامعتبر: ${issue.received} دریافت شد`, safeInteger: (issue) => `عدد صحیح امن نامعتبر: ${issue.received} دریافت شد`, size: (issue) => `اندازه نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, slug: (issue) => `اسلاگ نامعتبر: ${issue.received} دریافت شد`, someItem: (issue) => `آیتم نامعتبر: ${issue.received} دریافت شد`, startsWith: (issue) => `شروع نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, stringifyJson: (issue) => `JSON نامعتبر: ${issue.received} دریافت شد`, toBigint: (issue) => `BigInt نامعتبر: ${issue.received} دریافت شد`, toDate: (issue) => `تاریخ نامعتبر: ${issue.received} دریافت شد`, toNumber: (issue) => `عدد نامعتبر: ${issue.received} دریافت شد`, toString: (issue) => `رشته نامعتبر: ${issue.received} دریافت شد`, ulid: (issue) => `ULID نامعتبر: ${issue.received} دریافت شد`, url: (issue) => `URL نامعتبر: ${issue.received} دریافت شد`, uuid: (issue) => `UUID نامعتبر: ${issue.received} دریافت شد`, value: (issue) => `مقدار نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, values: (issue) => `مقدار نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, words: (issue) => `کلمات نامعتبر: ${issue.expected} انتظار می‌رفت اما ${issue.received} دریافت شد`, }, }; export default language; ================================================ FILE: packages/i18n/src/fi.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'fi', schema: (issue) => `Virheellinen tyyppi: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, specific: { base64: (issue) => `Virheellinen Base64: saatiin ${issue.received}`, bic: (issue) => `Virheellinen BIC: saatiin ${issue.received}`, bytes: (issue) => `Virheelliset tavut: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, check: (issue) => `Virheellinen syöte: saatiin ${issue.received}`, checkAsync: (issue) => `Virheellinen syöte: saatiin ${issue.received}`, checkItems: (issue) => `Virheellinen alkio: saatiin ${issue.received}`, checkItemsAsync: (issue) => `Virheellinen alkio: saatiin ${issue.received}`, creditCard: (issue) => `Virheellinen luottokortti: saatiin ${issue.received}`, cuid2: (issue) => `Virheellinen Cuid2: saatiin ${issue.received}`, decimal: (issue) => `Virheellinen desimaaliluku: saatiin ${issue.received}`, digits: (issue) => `Virheellinen numero: saatiin ${issue.received}`, domain: (issue) => `Virheellinen verkkotunnus: saatiin ${issue.received}`, email: (issue) => `Virheellinen sähköposti: saatiin ${issue.received}`, emoji: (issue) => `Virheellinen emoji: saatiin ${issue.received}`, empty: (issue) => `Virheellinen pituus: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, endsWith: (issue) => `Virheellinen loppu: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, entries: (issue) => `Virheelliset merkinnät: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, everyItem: (issue) => `Virheellinen alkio: saatiin ${issue.received}`, excludes: (issue) => `Virheellinen sisältö: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, finite: (issue) => `Virheellinen äärellinen luku: saatiin ${issue.received}`, graphemes: (issue) => `Virheellinen määrä grafeemeja: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, gtValue: (issue) => `Virheellinen arvo: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, guard: (issue) => `Virheellinen syöte: saatiin ${issue.received}`, hash: (issue) => `Virheellinen hash: saatiin ${issue.received}`, hexColor: (issue) => `Virheellinen heksaväri: saatiin ${issue.received}`, hexadecimal: (issue) => `Virheellinen heksadesimaali: saatiin ${issue.received}`, imei: (issue) => `Virheellinen IMEI: saatiin ${issue.received}`, includes: (issue) => `Virheellinen sisältö: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, integer: (issue) => `Virheellinen kokonaisluku: saatiin ${issue.received}`, ip: (issue) => `Virheellinen IP-osoite: saatiin ${issue.received}`, ipv4: (issue) => `Virheellinen IPv4: saatiin ${issue.received}`, ipv6: (issue) => `Virheellinen IPv6: saatiin ${issue.received}`, isbn: (issue) => `Virheellinen ISBN: saatiin ${issue.received}`, isoDate: (issue) => `Virheellinen päivämäärä: saatiin ${issue.received}`, isoDateTime: (issue) => `Virheellinen ISO-päivämäärä ja -aika: saatiin ${issue.received}`, isoTime: (issue) => `Virheellinen aika: saatiin ${issue.received}`, isoTimeSecond: (issue) => `Virheellinen aika sekunneissa: saatiin ${issue.received}`, isoTimestamp: (issue) => `Virheellinen aikaleima: saatiin ${issue.received}`, isoWeek: (issue) => `Virheellinen viikko: saatiin ${issue.received}`, isrc: (issue) => `Virheellinen ISRC: saatiin ${issue.received}`, jwsCompact: (issue) => `Virheellinen JWS Compact: saatiin ${issue.received}`, length: (issue) => `Virheellinen pituus: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, ltValue: (issue) => `Virheellinen arvo: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, mac: (issue) => `Virheellinen MAC: saatiin ${issue.received}`, mac48: (issue) => `Virheellinen 48-bit MAC: saatiin ${issue.received}`, mac64: (issue) => `Virheellinen 64-bit MAC: saatiin ${issue.received}`, maxBytes: (issue) => `Virheellinen määrä tavuja: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, maxEntries: (issue) => `Virheelliset merkinnät: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, maxGraphemes: (issue) => `Virheellinen määrä grafeemeja: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, maxLength: (issue) => `Virheellinen pituus: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, maxSize: (issue) => `Virheellinen koko: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, maxValue: (issue) => `Virheellinen arvo: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, maxWords: (issue) => `Virheellinen sanamäärä: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, mimeType: (issue) => `Virheellinen MIME-tyyppi: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, minBytes: (issue) => `Virheellinen määrä tavuja: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, minEntries: (issue) => `Virheelliset merkinnät: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, minGraphemes: (issue) => `Virheellinen määrä grafeemeja: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, minLength: (issue) => `Virheellinen pituus: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, minSize: (issue) => `Virheellinen koko: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, minValue: (issue) => `Virheellinen arvo: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, minWords: (issue) => `Virheellinen sanamäärä: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, multipleOf: (issue) => `Virheellinen monikerta: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, nanoid: (issue) => `Virheellinen Nano ID: saatiin ${issue.received}`, nonEmpty: (issue) => `Virheellinen pituus: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, notBytes: (issue) => `Virheellinen määrä tavuja: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, notEntries: (issue) => `Virheelliset merkinnät: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, notGraphemes: (issue) => `Virheellinen määrä grafeemeja: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, notLength: (issue) => `Virheellinen pituus: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, notSize: (issue) => `Virheellinen koko: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, notValue: (issue) => `Virheellinen arvo: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, notValues: (issue) => `Virheellinen arvo: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, notWords: (issue) => `Virheelliset sanat: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, octal: (issue) => `Virheellinen oktaaliluku: saatiin ${issue.received}`, parseBoolean: (issue) => `Virheellinen totuusarvo: saatiin ${issue.received}`, parseJson: (issue) => `Virheellinen JSON: saatiin ${issue.received}`, partialCheck: (issue) => `Virheellinen syöte: saatiin ${issue.received}`, rawCheck: (issue) => `Virheellinen syöte: saatiin ${issue.received}`, rawTransform: (issue) => `Virheellinen syöte: saatiin ${issue.received}`, regex: (issue) => `Virheellinen muoto: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, rfcEmail: (issue) => `Virheellinen sähköposti: saatiin ${issue.received}`, safeInteger: (issue) => `Virheellinen turvallinen kokonaisluku: saatiin ${issue.received}`, size: (issue) => `Virheellinen koko: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, slug: (issue) => `Virheellinen slug: saatiin ${issue.received}`, someItem: (issue) => `Virheellinen alkio: saatiin ${issue.received}`, startsWith: (issue) => `Virheellinen alku: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, stringifyJson: (issue) => `Virheellinen JSON: saatiin ${issue.received}`, toBigint: (issue) => `Virheellinen BigInt: saatiin ${issue.received}`, toDate: (issue) => `Virheellinen päivämäärä: saatiin ${issue.received}`, toNumber: (issue) => `Virheellinen luku: saatiin ${issue.received}`, toString: (issue) => `Virheellinen merkkijono: saatiin ${issue.received}`, ulid: (issue) => `Virheellinen ULID: saatiin ${issue.received}`, url: (issue) => `Virheellinen URL: saatiin ${issue.received}`, uuid: (issue) => `Virheellinen UUID: saatiin ${issue.received}`, value: (issue) => `Virheellinen arvo: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, values: (issue) => `Virheellinen arvo: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, words: (issue) => `Virheelliset sanat: odotettiin ${issue.expected}, mutta saatiin ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/fr.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'fr', schema: (issue) => `Typage invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, specific: { base64: (issue) => `Base64 invalide: reçu ${issue.received}`, bic: (issue) => `BIC invalide: reçu ${issue.received}`, bytes: (issue) => `Octet invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, check: (issue) => `Valeur invalide: reçu ${issue.received}`, checkAsync: (issue) => `Valeur invalide: reçu ${issue.received}`, checkItems: (issue) => `Élément invalide: reçu ${issue.received}`, checkItemsAsync: (issue) => `Élément invalide: reçu ${issue.received}`, creditCard: (issue) => `Carte de crédit invalide: reçu ${issue.received}`, cuid2: (issue) => `Cuid2 invalide: reçu ${issue.received}`, decimal: (issue) => `Décimale invalide: reçu ${issue.received}`, digits: (issue) => `Chiffres invalide: reçu ${issue.received}`, domain: (issue) => `Domaine invalide: reçu ${issue.received}`, email: (issue) => `Email invalide: reçu ${issue.received}`, emoji: (issue) => `Émoji invalide: reçu ${issue.received}`, empty: (issue) => `Longueur invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, endsWith: (issue) => `Fin invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, entries: (issue) => `Entrées invalides: attendu ${issue.expected}, mais reçu ${issue.received}`, everyItem: (issue) => `Élément invalide: reçu ${issue.received}`, excludes: (issue) => `Contenu invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, finite: (issue) => `Entier invalide: reçu ${issue.received}`, graphemes: (issue) => `Graphèmes invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, gtValue: (issue) => `Valeur invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, guard: (issue) => `Entrée invalide: reçu ${issue.received}`, hash: (issue) => `Hash invalide: reçu ${issue.received}`, hexadecimal: (issue) => `Hexadécimal invalide: reçu ${issue.received}`, hexColor: (issue) => `Couleur hexa invalide: reçu ${issue.received}`, imei: (issue) => `IMEI invalide: reçu ${issue.received}`, includes: (issue) => `Contenu invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, integer: (issue) => `Entier invalide: reçu ${issue.received}`, ip: (issue) => `IP invalide: reçu ${issue.received}`, ipv4: (issue) => `IPv4 invalide: reçu ${issue.received}`, ipv6: (issue) => `IPv6 invalide: reçu ${issue.received}`, isbn: (issue) => `ISBN invalide: reçu ${issue.received}`, isoDate: (issue) => `Date invalide: reçu ${issue.received}`, isoDateTime: (issue) => `Date et heure invalide: reçu ${issue.received}`, isoTime: (issue) => `Temps invalide: reçu ${issue.received}`, isoTimeSecond: (issue) => `Temps invalide (secondes): reçu ${issue.received}`, isoTimestamp: (issue) => `Timestamp invalide: reçu ${issue.received}`, isoWeek: (issue) => `Semaine invalide: reçu ${issue.received}`, isrc: (issue) => `ISRC invalide: reçu ${issue.received}`, jwsCompact: (issue) => `JWS compact invalide: reçu ${issue.received}`, length: (issue) => `Longueur invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, ltValue: (issue) => `Valeur invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, mac: (issue) => `MAC invalide: reçu ${issue.received}`, mac48: (issue) => `MAC 48-bit invalide: reçu ${issue.received}`, mac64: (issue) => `MAC 64-bit invalide: reçu ${issue.received}`, maxBytes: (issue) => `Octet invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, maxEntries: (issue) => `Entrées invalides: attendu ${issue.expected}, mais reçu ${issue.received}`, maxGraphemes: (issue) => `Graphèmes invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, maxLength: (issue) => `Longueur invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, maxSize: (issue) => `Taille invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, maxValue: (issue) => `Valeur invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, maxWords: (issue) => `Mots invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, mimeType: (issue) => `Type MIME invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, minBytes: (issue) => `Octet invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, minEntries: (issue) => `Entrées invalides: attendu ${issue.expected}, mais reçu ${issue.received}`, minGraphemes: (issue) => `Graphèmes invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, minLength: (issue) => `Longueur invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, minSize: (issue) => `Taille invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, minValue: (issue) => `Valeur invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, minWords: (issue) => `Mots invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, multipleOf: (issue) => `Multiple invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, nanoid: (issue) => `Nano ID invalide: reçu ${issue.received}`, nonEmpty: (issue) => `Longueur invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, notBytes: (issue) => `Octet invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, notEntries: (issue) => `Entrées invalides: attendu ${issue.expected}, mais reçu ${issue.received}`, notGraphemes: (issue) => `Graphèmes invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, notLength: (issue) => `Longueur invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, notSize: (issue) => `Taille invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, notValue: (issue) => `Valeur invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, notValues: (issue) => `Valeur invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, notWords: (issue) => `Mots invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, octal: (issue) => `Octet invalide: reçu ${issue.received}`, parseBoolean: (issue) => `Booléen invalide: reçu ${issue.received}`, parseJson: (issue) => `JSON invalide: reçu ${issue.received}`, partialCheck: (issue) => `Valeur invalide: reçu ${issue.received}`, rawCheck: (issue) => `Entrée invalide: reçu ${issue.received}`, rawTransform: (issue) => `Entrée invalide: reçu ${issue.received}`, regex: (issue) => `Format invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, rfcEmail: (issue) => `Email invalide: reçu ${issue.received}`, safeInteger: (issue) => `Entier sûr invalide: reçu ${issue.received}`, size: (issue) => `Taille invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, slug: (issue) => `Slug invalide: reçu ${issue.received}`, someItem: (issue) => `Élément invalide: reçu ${issue.received}`, startsWith: (issue) => `Début invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, stringifyJson: (issue) => `JSON invalide: reçu ${issue.received}`, toBigint: (issue) => `BigInt invalide: reçu ${issue.received}`, toDate: (issue) => `Date invalide: reçu ${issue.received}`, toNumber: (issue) => `Nombre invalide: reçu ${issue.received}`, toString: (issue) => `Chaîne invalide: reçu ${issue.received}`, ulid: (issue) => `ULID invalide: reçu ${issue.received}`, url: (issue) => `URL invalide: reçu ${issue.received}`, uuid: (issue) => `UUID invalide: reçu ${issue.received}`, value: (issue) => `Valeur invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, values: (issue) => `Valeur invalide: attendu ${issue.expected}, mais reçu ${issue.received}`, words: (issue) => `Mots invalide: reçu ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/hu.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'hu', schema: (issue) => `Érvénytelen típus: ${issue.expected} várt, de ${issue.received} kapott`, specific: { base64: (issue) => `Érvénytelen Base64: ${issue.received} kapott`, bic: (issue) => `Érvénytelen BIC: ${issue.received} kapott`, bytes: (issue) => `Érvénytelen bájtok: ${issue.expected} várt, de ${issue.received} kapott`, check: (issue) => `Érvénytelen bemenet: ${issue.received} kapott`, checkAsync: (issue) => `Érvénytelen bemenet: ${issue.received} kapott`, checkItems: (issue) => `Érvénytelen elem: ${issue.received} kapott`, checkItemsAsync: (issue) => `Érvénytelen elem: ${issue.received} kapott`, creditCard: (issue) => `Érvénytelen kártya szám: ${issue.received} kapott`, cuid2: (issue) => `Érvénytelen Cuid2: ${issue.received} kapott`, decimal: (issue) => `Érvénytelen decimális: ${issue.received} kapott`, digits: (issue) => `Érvénytelen számjegyek: ${issue.received} kapott`, domain: (issue) => `Érvénytelen tartománynév: ${issue.received} kapott`, email: (issue) => `Érvénytelen email: ${issue.received} kapott`, emoji: (issue) => `Érvénytelen emoji: ${issue.received} kapott`, empty: (issue) => `Érvénytelen hosszúság: ${issue.expected} várt, de ${issue.received} kapott`, endsWith: (issue) => `Érvénytelen vég: ${issue.expected} várt, de ${issue.received} kapott`, entries: (issue) => `Érvénytelen bejegyzésszám: ${issue.expected} várt, de ${issue.received} kapott`, everyItem: (issue) => `Érvénytelen elem: ${issue.received} kapott`, excludes: (issue) => `Érvénytelen tartalom: ${issue.expected} várt, de ${issue.received} kapott`, finite: (issue) => `Érvénytelen véges: ${issue.received} kapott`, graphemes: (issue) => `Érvénytelen gráfémák: ${issue.expected} várt, de ${issue.received} kapott`, gtValue: (issue) => `Érvénytelen érték: ${issue.expected} várt, de ${issue.received} kapott`, guard: (issue) => `Érvénytelen bemenet: ${issue.received} kapott`, hash: (issue) => `Érvénytelen hash: ${issue.received} kapott`, hexadecimal: (issue) => `Érvénytelen hexadecimális: ${issue.received} kapott`, hexColor: (issue) => `Érvénytelen hex szín: ${issue.received} kapott`, imei: (issue) => `Érvénytelen IMEI: ${issue.received} kapott`, includes: (issue) => `Érvénytelen tartalom: ${issue.expected} várt, de ${issue.received} kapott`, integer: (issue) => `Érvénytelen egész szám: ${issue.received} kapott`, ip: (issue) => `Érvénytelen IP: ${issue.received} kapott`, ipv4: (issue) => `Érvénytelen IPv4: ${issue.received} kapott`, ipv6: (issue) => `Érvénytelen IPv6: ${issue.received} kapott`, isbn: (issue) => `Érvénytelen ISBN: ${issue.received} kapott`, isoDate: (issue) => `Érvénytelen dátum: ${issue.received} kapott`, isoDateTime: (issue) => `Érvénytelen dátum idő: ${issue.received} kapott`, isoTime: (issue) => `Érvénytelen idő: ${issue.received} kapott`, isoTimeSecond: (issue) => `Érvénytelen idő másodperc: ${issue.received} kapott`, isoTimestamp: (issue) => `Érvénytelen időbélyeg: ${issue.received} kapott`, isoWeek: (issue) => `Érvénytelen hét: ${issue.received} kapott`, isrc: (issue) => `Érvénytelen ISRC: ${issue.received} kapott`, jwsCompact: (issue) => `Érvénytelen tömör JWS: ${issue.received} kapott`, length: (issue) => `Érvénytelen hosszúság: ${issue.expected} várt, de ${issue.received} kapott`, ltValue: (issue) => `Érvénytelen érték: ${issue.expected} várt, de ${issue.received} kapott`, mac: (issue) => `Érvénytelen MAC: ${issue.received} kapott`, mac48: (issue) => `Érvénytelen 48 bites MAC: ${issue.received} kapott`, mac64: (issue) => `Érvénytelen 64 bites MAC: ${issue.received} kapott`, maxBytes: (issue) => `Érvénytelen bájtok: ${issue.expected} várt, de ${issue.received} kapott`, maxEntries: (issue) => `Érvénytelen bejegyzésszám: ${issue.expected} várt, de ${issue.received} kapott`, maxGraphemes: (issue) => `Érvénytelen gráfémák: ${issue.expected} várt, de ${issue.received} kapott`, maxLength: (issue) => `Érvénytelen hosszúság: ${issue.expected} várt, de ${issue.received} kapott`, maxSize: (issue) => `Érvénytelen méret: ${issue.expected} várt, de ${issue.received} kapott`, maxValue: (issue) => `Érvénytelen érték: ${issue.expected} várt, de ${issue.received} kapott`, maxWords: (issue) => `Érvénytelen szavak: ${issue.expected} várt, de ${issue.received} kapott`, mimeType: (issue) => `Érvénytelen MIME típus: ${issue.expected} várt, de ${issue.received} kapott`, minBytes: (issue) => `Érvénytelen bájtok: ${issue.expected} várt, de ${issue.received} kapott`, minEntries: (issue) => `Érvénytelen bejegyzésszám: ${issue.expected} várt, de ${issue.received} kapott`, minGraphemes: (issue) => `Érvénytelen gráfémák: ${issue.expected} várt, de ${issue.received} kapott`, minLength: (issue) => `Érvénytelen hosszúság: ${issue.expected} várt, de ${issue.received} kapott`, minSize: (issue) => `Érvénytelen méret: ${issue.expected} várt, de ${issue.received} kapott`, minValue: (issue) => `Érvénytelen érték: ${issue.expected} várt, de ${issue.received} kapott`, minWords: (issue) => `Érvénytelen szavak: ${issue.expected} várt, de ${issue.received} kapott`, multipleOf: (issue) => `Érvénytelen többszörös: ${issue.expected} várt, de ${issue.received} kapott`, nanoid: (issue) => `Érvénytelen Nano ID: ${issue.received} kapott`, nonEmpty: (issue) => `Érvénytelen hosszúság: ${issue.expected} várt, de ${issue.received} kapott`, notBytes: (issue) => `Érvénytelen bájtok: ${issue.expected} várt, de ${issue.received} kapott`, notEntries: (issue) => `Érvénytelen bejegyzésszám: ${issue.expected} várt, de ${issue.received} kapott`, notGraphemes: (issue) => `Érvénytelen gráfémák: ${issue.expected} várt, de ${issue.received} kapott`, notLength: (issue) => `Érvénytelen hosszúság: ${issue.expected} várt, de ${issue.received} kapott`, notSize: (issue) => `Érvénytelen méret: ${issue.expected} várt, de ${issue.received} kapott`, notValue: (issue) => `Érvénytelen érték: ${issue.expected} várt, de ${issue.received} kapott`, notValues: (issue) => `Érvénytelen érték: ${issue.expected} várt, de ${issue.received} kapott`, notWords: (issue) => `Érvénytelen szavak: ${issue.expected} várt, de ${issue.received} kapott`, octal: (issue) => `Érvénytelen nyolcas: ${issue.received} kapott`, parseBoolean: (issue) => `Érvénytelen logikai érték: ${issue.received} kapott`, parseJson: (issue) => `Érvénytelen JSON: ${issue.received} kapott`, partialCheck: (issue) => `Érvénytelen bemenet: ${issue.received} kapott`, rawCheck: (issue) => `Érvénytelen bemenet: ${issue.received} kapott`, rawTransform: (issue) => `Érvénytelen bemenet: ${issue.received} kapott`, regex: (issue) => `Érvénytelen formátum: ${issue.expected} várt, de ${issue.received} kapott`, rfcEmail: (issue) => `Érvénytelen email: ${issue.received} kapott`, safeInteger: (issue) => `Érvénytelen biztonságos egész szám: ${issue.received} kapott`, size: (issue) => `Érvénytelen méret: ${issue.expected} várt, de ${issue.received} kapott`, slug: (issue) => `Érvénytelen slug: ${issue.received} kapott`, someItem: (issue) => `Érvénytelen elem: ${issue.received} kapott`, startsWith: (issue) => `Érvénytelen kezdet: ${issue.expected} várt, de ${issue.received} kapott`, stringifyJson: (issue) => `Érvénytelen JSON: ${issue.received} kapott`, toBigint: (issue) => `Érvénytelen BigInt: ${issue.received} kapott`, toDate: (issue) => `Érvénytelen dátum: ${issue.received} kapott`, toNumber: (issue) => `Érvénytelen szám: ${issue.received} kapott`, toString: (issue) => `Érvénytelen karakterlánc: ${issue.received} kapott`, ulid: (issue) => `Érvénytelen ULID: ${issue.received} kapott`, url: (issue) => `Érvénytelen URL: ${issue.received} kapott`, uuid: (issue) => `Érvénytelen UUID: ${issue.received} kapott`, value: (issue) => `Érvénytelen érték: ${issue.expected} várt, de ${issue.received} kapott`, values: (issue) => `Érvénytelen érték: ${issue.expected} várt, de ${issue.received} kapott`, words: (issue) => `Érvénytelen szavak: ${issue.expected} várt, de ${issue.received} kapott`, }, }; export default language; ================================================ FILE: packages/i18n/src/id.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'id', schema: (issue) => `Tipe tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, specific: { base64: (issue) => `Base64 tidak valid: Menerima ${issue.received}`, bic: (issue) => `BIC tidak valid: Menerima ${issue.received}`, bytes: (issue) => `Byte tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, check: (issue) => `Input tidak valid: Menerima ${issue.received}`, checkAsync: (issue) => `Input tidak valid: Menerima ${issue.received}`, checkItems: (issue) => `Item tidak valid: Menerima ${issue.received}`, checkItemsAsync: (issue) => `Item tidak valid: Menerima ${issue.received}`, creditCard: (issue) => `Kartu kredit tidak valid: Menerima ${issue.received}`, cuid2: (issue) => `Cuid2 tidak valid: Menerima ${issue.received}`, decimal: (issue) => `Desimal tidak valid: Menerima ${issue.received}`, digits: (issue) => `Digit tidak valid: Menerima ${issue.received}`, domain: (issue) => `Domain tidak valid: Menerima ${issue.received}`, email: (issue) => `Email tidak valid: Menerima ${issue.received}`, emoji: (issue) => `Emoji tidak valid: Menerima ${issue.received}`, empty: (issue) => `Panjang tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, endsWith: (issue) => `Akhiran tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, entries: (issue) => `Entri tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, everyItem: (issue) => `Item tidak valid: Menerima ${issue.received}`, excludes: (issue) => `Konten tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, finite: (issue) => `Finite tidak valid: Menerima ${issue.received}`, graphemes: (issue) => `Grafem tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, gtValue: (issue) => `Nilai tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, guard: (issue) => `Input tidak valid: Menerima ${issue.received}`, hash: (issue) => `Hash tidak valid: Menerima ${issue.received}`, hexadecimal: (issue) => `Heksadesimal tidak valid: Menerima ${issue.received}`, hexColor: (issue) => `Warna hex tidak valid: Menerima ${issue.received}`, imei: (issue) => `IMEI tidak valid: Menerima ${issue.received}`, includes: (issue) => `Konten tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, integer: (issue) => `Bukan integer: Menerima ${issue.received}`, ip: (issue) => `IP tidak valid: Menerima ${issue.received}`, ipv4: (issue) => `IPv4 tidak valid: Menerima ${issue.received}`, ipv6: (issue) => `IPv6 tidak valid: Menerima ${issue.received}`, isbn: (issue) => `ISBN tidak valid: Menerima ${issue.received}`, isoDate: (issue) => `Tanggal tidak valid: Menerima ${issue.received}`, isoDateTime: (issue) => `Tanggal-waktu tidak valid: Menerima ${issue.received}`, isoTime: (issue) => `Waktu tidak valid: Menerima ${issue.received}`, isoTimeSecond: (issue) => `Detik waktu tidak valid: Menerima ${issue.received}`, isoTimestamp: (issue) => `Timestamp tidak valid: Menerima ${issue.received}`, isoWeek: (issue) => `Minggu tidak valid: Menerima ${issue.received}`, isrc: (issue) => `ISRC tidak valid: Menerima ${issue.received}`, jwsCompact: (issue) => `JWS ringkas tidak valid: Menerima ${issue.received}`, length: (issue) => `Panjang tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, ltValue: (issue) => `Nilai tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, mac: (issue) => `MAC tidak valid: Menerima ${issue.received}`, mac48: (issue) => `MAC 48-bit tidak valid: Menerima ${issue.received}`, mac64: (issue) => `MAC 64-bit tidak valid: Menerima ${issue.received}`, maxBytes: (issue) => `Byte maksimum tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, maxEntries: (issue) => `Entri tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, maxGraphemes: (issue) => `Grafem maksimum tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, maxLength: (issue) => `Panjang maksimum tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, maxSize: (issue) => `Ukuran maksimum tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, maxValue: (issue) => `Nilai maksimum tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, maxWords: (issue) => `Kata maksimum tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, mimeType: (issue) => `Tipe MIME tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, minBytes: (issue) => `Byte minimum tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, minEntries: (issue) => `Entri tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, minGraphemes: (issue) => `Grafem minimum tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, minLength: (issue) => `Panjang minimum tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, minSize: (issue) => `Ukuran minimum tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, minValue: (issue) => `Nilai minimum tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, minWords: (issue) => `Kata minimum tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, multipleOf: (issue) => `Kelipatan tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, nanoid: (issue) => `Nano ID tidak valid: Menerima ${issue.received}`, nonEmpty: (issue) => `Panjang tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, notBytes: (issue) => `Byte tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, notEntries: (issue) => `Entri tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, notGraphemes: (issue) => `Grafem tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, notLength: (issue) => `Panjang tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, notSize: (issue) => `Ukuran tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, notValue: (issue) => `Nilai tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, notValues: (issue) => `Nilai tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, notWords: (issue) => `Kata tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, octal: (issue) => `Oktal tidak valid: Menerima ${issue.received}`, parseBoolean: (issue) => `Boolean tidak valid: Menerima ${issue.received}`, parseJson: (issue) => `JSON tidak valid: Menerima ${issue.received}`, partialCheck: (issue) => `Input tidak valid: Menerima ${issue.received}`, rawCheck: (issue) => `Input tidak valid: Menerima ${issue.received}`, rawTransform: (issue) => `Input tidak valid: Menerima ${issue.received}`, regex: (issue) => `Format tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, rfcEmail: (issue) => `Email tidak valid: Menerima ${issue.received}`, safeInteger: (issue) => `Safe integer tidak valid: Menerima ${issue.received}`, size: (issue) => `Ukuran tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, slug: (issue) => `Slug tidak valid: Menerima ${issue.received}`, someItem: (issue) => `Item tidak valid: Menerima ${issue.received}`, startsWith: (issue) => `Awalan tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, stringifyJson: (issue) => `JSON tidak valid: Menerima ${issue.received}`, toBigint: (issue) => `BigInt tidak valid: Menerima ${issue.received}`, toDate: (issue) => `Tanggal tidak valid: Menerima ${issue.received}`, toNumber: (issue) => `Angka tidak valid: Menerima ${issue.received}`, toString: (issue) => `String tidak valid: Menerima ${issue.received}`, ulid: (issue) => `ULID tidak valid: Menerima ${issue.received}`, url: (issue) => `URL tidak valid: Menerima ${issue.received}`, uuid: (issue) => `UUID tidak valid: Menerima ${issue.received}`, value: (issue) => `Nilai tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, values: (issue) => `Nilai tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, words: (issue) => `Kata tidak valid: Seharusnya ${issue.expected} tetapi menerima ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/it.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'it', schema: (issue) => `Tipo non valido: Previsto ${issue.expected} ma ricevuto ${issue.received}`, specific: { base64: (issue) => `Base64 non valido: Ricevuto ${issue.received}`, bic: (issue) => `BIC non valido: Ricevuto ${issue.received}`, bytes: (issue) => `Byte non validi: Previsto ${issue.expected} ma ricevuto ${issue.received}`, check: (issue) => `Input non valido: Ricevuto ${issue.received}`, checkAsync: (issue) => `Input non valido: Ricevuto ${issue.received}`, checkItems: (issue) => `Elemento non valido: Input ${issue.received}`, checkItemsAsync: (issue) => `Elemento non valido: Input ${issue.received}`, creditCard: (issue) => `Carta di credito non valida: Ricevuto ${issue.received}`, cuid2: (issue) => `Cuid2 non valido: Ricevuto ${issue.received}`, decimal: (issue) => `Decimale non valido: Ricevuto ${issue.received}`, digits: (issue) => `Cifre non valide: Ricevuto ${issue.received}`, domain: (issue) => `Dominio non valido: Ricevuto ${issue.received}`, email: (issue) => `Email non valida: Ricevuto ${issue.received}`, emoji: (issue) => `Emoji non valido: Ricevuto ${issue.received}`, empty: (issue) => `Lunghezza non valida: Previsto ${issue.expected} ma ricevuto ${issue.received}`, endsWith: (issue) => `Finale non valido: Previsto ${issue.expected} ma ricevuto ${issue.received}`, entries: (issue) => `Voci non valide: Previsto ${issue.expected} ma ricevuto ${issue.received}`, everyItem: (issue) => `Elemento non valido: Ricevuto ${issue.received}`, excludes: (issue) => `Contenuto non valido: Previsto ${issue.expected} ma ricevuto ${issue.received}`, finite: (issue) => `Finito non valido: Ricevuto ${issue.received}`, graphemes: (issue) => `Grafi non validi: Previsto ${issue.expected} ma ricevuto ${issue.received}`, gtValue: (issue) => `Valore non valido: Previsto ${issue.expected} ma ricevuto ${issue.received}`, guard: (issue) => `Input non valido: Ricevuto ${issue.received}`, hash: (issue) => `Hash non valido: Ricevuto ${issue.received}`, hexadecimal: (issue) => `Esadecimale non valido: Ricevuto ${issue.received}`, hexColor: (issue) => `Colore esadecimale non valido: Ricevuto ${issue.received}`, imei: (issue) => `IMEI non valido: Ricevuto ${issue.received}`, includes: (issue) => `Contenuto non valido: Previsto ${issue.expected} ma ricevuto ${issue.received}`, integer: (issue) => `Intero non valido: Ricevuto ${issue.received}`, ip: (issue) => `IP non valido: Ricevuto ${issue.received}`, ipv4: (issue) => `IPv4 non valido: Ricevuto ${issue.received}`, ipv6: (issue) => `IPv6 non valido: Ricevuto ${issue.received}`, isbn: (issue) => `ISBN non valido: Ricevuto ${issue.received}`, isoDate: (issue) => `Data non valida: Ricevuto ${issue.received}`, isoDateTime: (issue) => `Data e ora non validi: Ricevuto ${issue.received}`, isoTime: (issue) => `Ora non valida: Ricevuto ${issue.received}`, isoTimeSecond: (issue) => `Secondo dell'ora non valido: Ricevuto ${issue.received}`, isoTimestamp: (issue) => `Timestamp non valido: Ricevuto ${issue.received}`, isoWeek: (issue) => `Settimana non valida: Ricevuto ${issue.received}`, isrc: (issue) => `ISRC non valido: Ricevuto ${issue.received}`, jwsCompact: (issue) => `JWS compatto non valido: Ricevuto ${issue.received}`, length: (issue) => `Lunghezza non valida: Previsto ${issue.expected} ma ricevuto ${issue.received}`, ltValue: (issue) => `Valore non valido: Previsto ${issue.expected} ma ricevuto ${issue.received}`, mac: (issue) => `MAC non valido: Ricevuto ${issue.received}`, mac48: (issue) => `MAC a 48 bit non valido: Ricevuto ${issue.received}`, mac64: (issue) => `MAC a 64 bit non valido: Ricevuto ${issue.received}`, maxBytes: (issue) => `Byte non validi: Previsto ${issue.expected} ma ricevuto ${issue.received}`, maxEntries: (issue) => `Voci non valide: Previsto ${issue.expected} ma ricevuto ${issue.received}`, maxGraphemes: (issue) => `Grafi non validi: Previsto ${issue.expected} ma ricevuto ${issue.received}`, maxLength: (issue) => `Lunghezza non valida: Previsto ${issue.expected} ma ricevuto ${issue.received}`, maxSize: (issue) => `Dimensione non valida: Previsto ${issue.expected} ma ricevuto ${issue.received}`, maxValue: (issue) => `Valore non valido: Previsto ${issue.expected} ma ricevuto ${issue.received}`, maxWords: (issue) => `Parole non valide: Previsto ${issue.expected} ma ricevuto ${issue.received}`, mimeType: (issue) => `Tipo MIME non valido: Previsto ${issue.expected} ma ricevuto ${issue.received}`, minBytes: (issue) => `Byte non validi: Previsto ${issue.expected} ma ricevuto ${issue.received}`, minEntries: (issue) => `Voci non valide: Previsto ${issue.expected} ma ricevuto ${issue.received}`, minGraphemes: (issue) => `Grafi non validi: Previsto ${issue.expected} ma ricevuto ${issue.received}`, minLength: (issue) => `Lunghezza non valida: Previsto ${issue.expected} ma ricevuto ${issue.received}`, minSize: (issue) => `Dimensione non valida: Previsto ${issue.expected} ma ricevuto ${issue.received}`, minValue: (issue) => `Valore non valido: Previsto ${issue.expected} ma ricevuto ${issue.received}`, minWords: (issue) => `Parole non valide: Previsto ${issue.expected} ma ricevuto ${issue.received}`, multipleOf: (issue) => `Multiplo non valido: Previsto ${issue.expected} ma ricevuto ${issue.received}`, nanoid: (issue) => `Nano ID non valido: Ricevuto ${issue.received}`, nonEmpty: (issue) => `Lunghezza non valida: Previsto ${issue.expected} ma ricevuto ${issue.received}`, notBytes: (issue) => `Byte non validi: Previsto ${issue.expected} ma ricevuto ${issue.received}`, notEntries: (issue) => `Voci non valide: Previsto ${issue.expected} ma ricevuto ${issue.received}`, notGraphemes: (issue) => `Grafi non validi: Previsto ${issue.expected} ma ricevuto ${issue.received}`, notLength: (issue) => `Lunghezza non valida: Previsto ${issue.expected} ma ricevuto ${issue.received}`, notSize: (issue) => `Dimensione non valida: previsto ${issue.expected} ma ricevuto ${issue.received}`, notValue: (issue) => `Valore non valido: Previsto ${issue.expected} ma ricevuto ${issue.received}`, notValues: (issue) => `Valore non valido: Previsto ${issue.expected} ma ricevuto ${issue.received}`, notWords: (issue) => `Parole non valide: Previsto ${issue.expected} ma ricevuto ${issue.received}`, octal: (issue) => `Ottale non valido: Ricevuto ${issue.received}`, parseBoolean: (issue) => `Booleano non valido: Ricevuto ${issue.received}`, parseJson: (issue) => `JSON non valido: Ricevuto ${issue.received}`, partialCheck: (issue) => `Input non valido: Ricevuto ${issue.received}`, rawCheck: (issue) => `Input non valido: Ricevuto ${issue.received}`, rawTransform: (issue) => `Input non valido: Ricevuto ${issue.received}`, regex: (issue) => `Formato non valido: Previsto ${issue.expected} ma ricevuto ${issue.received}`, rfcEmail: (issue) => `Email non valida: Ricevuto ${issue.received}`, safeInteger: (issue) => `Intero sicuro non valido: Ricevuto ${issue.received}`, size: (issue) => `Dimensione non valida: Previsto ${issue.expected} ma ricevuto ${issue.received}`, slug: (issue) => `Slug non valido: Ricevuto ${issue.received}`, someItem: (issue) => `Elemento non valido: Ricevuto ${issue.received}`, startsWith: (issue) => `Inizio non valido: Previsto ${issue.expected} ma ricevuto ${issue.received}`, stringifyJson: (issue) => `JSON non valido: Ricevuto ${issue.received}`, toBigint: (issue) => `BigInt non valido: Ricevuto ${issue.received}`, toDate: (issue) => `Data non valida: Ricevuto ${issue.received}`, toNumber: (issue) => `Numero non valido: Ricevuto ${issue.received}`, toString: (issue) => `Stringa non valida: Ricevuto ${issue.received}`, ulid: (issue) => `ULID non valido: Ricevuto ${issue.received}`, url: (issue) => `URL non valido: Ricevuto ${issue.received}`, uuid: (issue) => `UUID non valido: Ricevuto ${issue.received}`, value: (issue) => `Valore non valido: Previsto ${issue.expected} ma ricevuto ${issue.received}`, values: (issue) => `Valore non valido: Previsto ${issue.expected} ma ricevuto ${issue.received}`, words: (issue) => `Parole non valide: Previsto ${issue.expected} ma ricevuto ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/ja.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'ja', schema: (issue) => `無効な型: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, specific: { base64: (issue) => `無効なBase64: ${issue.received} を受け取りました`, bic: (issue) => `無効なBIC: ${issue.received} を受け取りました`, bytes: (issue) => `無効なバイト数: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, check: (issue) => `無効な入力: ${issue.received} を受け取りました`, checkAsync: (issue) => `無効な入力: ${issue.received} を受け取りました`, checkItems: (issue) => `無効な項目: ${issue.received} を受け取りました`, checkItemsAsync: (issue) => `無効な項目: ${issue.received} を受け取りました`, creditCard: (issue) => `無効なクレジットカード: ${issue.received} を受け取りました`, cuid2: (issue) => `無効なCuid2: ${issue.received} を受け取りました`, decimal: (issue) => `無効な10進数: ${issue.received} を受け取りました`, digits: (issue) => `無効な数字: ${issue.received} を受け取りました`, domain: (issue) => `無効なドメイン: ${issue.received} を受け取りました`, email: (issue) => `無効なメールアドレス: ${issue.received} を受け取りました`, emoji: (issue) => `無効な絵文字: ${issue.received} を受け取りました`, empty: (issue) => `無効な長さ: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, endsWith: (issue) => `無効な末尾: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, entries: (issue) => `無効な項目数: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, everyItem: (issue) => `無効な項目: ${issue.received} を受け取りました`, excludes: (issue) => `無効な内容: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, finite: (issue) => `無効な有限数: ${issue.received} を受け取りました`, graphemes: (issue) => `無効な書記素数: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, gtValue: (issue) => `無効な値: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, guard: (issue) => `無効な入力: ${issue.received} を受け取りました`, hash: (issue) => `無効なハッシュ値: ${issue.received} を受け取りました`, hexadecimal: (issue) => `無効な16進数: ${issue.received} を受け取りました`, hexColor: (issue) => `無効な16進数カラーコード: ${issue.received} を受け取りました`, imei: (issue) => `無効なIMEI: ${issue.received} を受け取りました`, includes: (issue) => `無効な内容: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, integer: (issue) => `無効な整数: ${issue.received} を受け取りました`, ip: (issue) => `無効なIP: ${issue.received} を受け取りました`, ipv4: (issue) => `無効なIPv4: ${issue.received} を受け取りました`, ipv6: (issue) => `無効なIPv6: ${issue.received} を受け取りました`, isbn: (issue) => `無効なISBN: ${issue.received} を受け取りました`, isoDate: (issue) => `無効な日付: ${issue.received} を受け取りました`, isoDateTime: (issue) => `無効な日時: ${issue.received} を受け取りました`, isoTime: (issue) => `無効な時刻: ${issue.received} を受け取りました`, isoTimeSecond: (issue) => `無効な時刻: ${issue.received} を受け取りました`, isoTimestamp: (issue) => `無効なタイムスタンプ: ${issue.received} を受け取りました`, isoWeek: (issue) => `無効な週番号: ${issue.received} を受け取りました`, isrc: (issue) => `無効なISRC: ${issue.received} を受け取りました`, jwsCompact: (issue) => `無効なコンパクトJWS: ${issue.received} を受け取りました`, length: (issue) => `無効な長さ: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, ltValue: (issue) => `無効な値: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, mac: (issue) => `無効なMACアドレス: ${issue.received} を受け取りました`, mac48: (issue) => `無効な48-bit MACアドレス: ${issue.received} を受け取りました`, mac64: (issue) => `無効な64-bit MACアドレス: ${issue.received} を受け取りました`, maxBytes: (issue) => `無効なバイト数: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, maxEntries: (issue) => `無効な項目数: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, maxGraphemes: (issue) => `無効な書記素数: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, maxLength: (issue) => `無効な長さ: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, maxSize: (issue) => `無効なサイズ: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, maxValue: (issue) => `無効な値: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, maxWords: (issue) => `無効な単語数: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, mimeType: (issue) => `無効なMIME type: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, minBytes: (issue) => `無効なバイト数: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, minEntries: (issue) => `無効な項目数: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, minGraphemes: (issue) => `無効な書記素数: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, minLength: (issue) => `無効な長さ: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, minSize: (issue) => `無効なサイズ: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, minValue: (issue) => `無効な値: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, minWords: (issue) => `無効な単語数: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, multipleOf: (issue) => `無効な倍数: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, nanoid: (issue) => `無効なNano ID: ${issue.received} を受け取りました`, nonEmpty: (issue) => `無効な長さ: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, notBytes: (issue) => `無効なバイト数: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, notEntries: (issue) => `無効な項目数: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, notGraphemes: (issue) => `無効な書記素数: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, notLength: (issue) => `無効な長さ: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, notSize: (issue) => `無効なサイズ: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, notValue: (issue) => `無効な値: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, notValues: (issue) => `無効な値: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, notWords: (issue) => `無効な単語数: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, octal: (issue) => `無効な8進数: ${issue.received} を受け取りました`, parseBoolean: (issue) => `無効な真偽値: ${issue.received} を受け取りました`, parseJson: (issue) => `無効なJSON: ${issue.received} を受け取りました`, partialCheck: (issue) => `無効な入力: ${issue.received} を受け取りました`, rawCheck: (issue) => `無効な入力: ${issue.received} を受け取りました`, rawTransform: (issue) => `無効な入力: ${issue.received} を受け取りました`, regex: (issue) => `無効なフォーマット: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, rfcEmail: (issue) => `無効なメールアドレス: ${issue.received} を受け取りました`, safeInteger: (issue) => `無効な安全な整数: ${issue.received} を受け取りました`, size: (issue) => `無効なサイズ: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, slug: (issue) => `無効なスラッグ: ${issue.received} を受け取りました`, someItem: (issue) => `無効な項目: ${issue.received} を受け取りました`, startsWith: (issue) => `無効な先頭: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, stringifyJson: (issue) => `無効なJSON: ${issue.received} を受け取りました`, toBigint: (issue) => `無効なBigInt: ${issue.received} を受け取りました`, toDate: (issue) => `無効な日付: ${issue.received} を受け取りました`, toNumber: (issue) => `無効な数値: ${issue.received} を受け取りました`, toString: (issue) => `無効な文字列: ${issue.received} を受け取りました`, ulid: (issue) => `無効なULID: ${issue.received} を受け取りました`, url: (issue) => `無効なURL: ${issue.received} を受け取りました`, uuid: (issue) => `無効なUUID: ${issue.received} を受け取りました`, value: (issue) => `無効な値: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, values: (issue) => `無効な値: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, words: (issue) => `無効な単語数: ${issue.expected} を期待しましたが、 ${issue.received} を受け取りました`, }, }; export default language; ================================================ FILE: packages/i18n/src/ko.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'ko', schema: (issue) => `유효하지 않은 타입: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, specific: { base64: (issue) => `유효하지 않은 Base64: ${issue.received} 을(를) 받았습니다`, bic: (issue) => `유효하지 않은 사업자 식별코드(BIC): ${issue.received} 을(를) 받았습니다`, bytes: (issue) => `유효하지 않은 바이트: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, check: (issue) => `유효하지 않은 입력: ${issue.received} 을(를) 받았습니다`, checkAsync: (issue) => `유효하지 않은 입력: ${issue.received} 을(를) 받았습니다`, checkItems: (issue) => `유효하지 않은 항목: ${issue.received} 을(를) 받았습니다`, checkItemsAsync: (issue) => `유효하지 않은 항목: ${issue.received} 을(를) 받았습니다`, creditCard: (issue) => `유효하지 않은 신용카드: ${issue.received} 을(를) 받았습니다`, cuid2: (issue) => `유효하지 않은 Cuid2: ${issue.received} 을(를) 받았습니다`, decimal: (issue) => `유효하지 않은 소수: ${issue.received} 을(를) 받았습니다`, digits: (issue) => `유효하지 않은 숫자: ${issue.received} 을(를) 받았습니다`, domain: (issue) => `유효하지 않은 도메인: ${issue.received} 을(를) 받았습니다`, email: (issue) => `유효하지 않은 이메일: ${issue.received} 을(를) 받았습니다`, emoji: (issue) => `유효하지 않은 이모지: ${issue.received} 을(를) 받았습니다`, empty: (issue) => `유효하지 않은 비어있음: ${issue.received} 을(를) 받았습니다`, endsWith: (issue) => `유효하지 않은 끝: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, entries: (issue) => `유효하지 않은 항목 수: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, everyItem: (issue) => `유효하지 않은 항목: ${issue.received} 을(를) 받았습니다`, excludes: (issue) => `유효하지 않은 제외: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, finite: (issue) => `유한하지 않은 값: ${issue.received} 을(를) 받았습니다`, graphemes: (issue) => `유효하지 않은 문자 그래프: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, gtValue: (issue) => `유효하지 않은 값: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, guard: (issue) => `유효하지 않은 입력: ${issue.received} 을(를) 받았습니다`, hash: (issue) => `유효하지 않은 해시: ${issue.received} 을(를) 받았습니다`, hexadecimal: (issue) => `유효하지 않은 16진수: ${issue.received} 을(를) 받았습니다`, hexColor: (issue) => `유효하지 않은 16진수 색상: ${issue.received} 을(를) 받았습니다`, imei: (issue) => `유효하지 않은 IMEI: ${issue.received} 을(를) 받았습니다`, includes: (issue) => `유효하지 않은 포함: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, integer: (issue) => `유효하지 않은 정수: ${issue.received} 을(를) 받았습니다`, ip: (issue) => `유효하지 않은 IP: ${issue.received} 을(를) 받았습니다`, ipv4: (issue) => `유효하지 않은 IPv4: ${issue.received} 을(를) 받았습니다`, ipv6: (issue) => `유효하지 않은 IPv6: ${issue.received} 을(를) 받았습니다`, isbn: (issue) => `유효하지 않은 ISBN: ${issue.received} 을(를) 받았습니다`, isoDate: (issue) => `유효하지 않은 ISO 날짜: ${issue.received} 을(를) 받았습니다`, isoDateTime: (issue) => `유효하지 않은 ISO 날짜-시간: ${issue.received} 을(를) 받았습니다`, isoTime: (issue) => `유효하지 않은 ISO 시간: ${issue.received} 을(를) 받았습니다`, isoTimeSecond: (issue) => `유효하지 않은 ISO 초: ${issue.received} 을(를) 받았습니다`, isoTimestamp: (issue) => `유효하지 않은 ISO 타임스탬프: ${issue.received} 을(를) 받았습니다`, isoWeek: (issue) => `유효하지 않은 ISO 주: ${issue.received} 을(를) 받았습니다`, isrc: (issue) => `유효하지 않은 ISRC: ${issue.received} 을(를) 받았습니다`, jwsCompact: (issue) => `유효하지 않은 JWS 압축 직렬화: ${issue.received} 을(를) 받았습니다`, length: (issue) => `유효하지 않은 길이: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, ltValue: (issue) => `유효하지 않은 값: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, mac: (issue) => `유효하지 않은 MAC: ${issue.received} 을(를) 받았습니다`, mac48: (issue) => `유효하지 않은 MAC-48: ${issue.received} 을(를) 받았습니다`, mac64: (issue) => `유효하지 않은 MAC-64: ${issue.received} 을(를) 받았습니다`, maxBytes: (issue) => `바이트가 너무 큽니다: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, maxEntries: (issue) => `유효하지 않은 항목 수: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, maxGraphemes: (issue) => `문자 그래프가 너무 큽니다: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, maxLength: (issue) => `길이가 너무 깁니다: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, maxSize: (issue) => `크기가 너무 큽니다: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, maxValue: (issue) => `값이 너무 큽니다: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, maxWords: (issue) => `단어가 너무 많습니다: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, mimeType: (issue) => `유효하지 않은 MIME 타입: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, minBytes: (issue) => `바이트가 너무 작습니다: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, minEntries: (issue) => `유효하지 않은 항목 수: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, minGraphemes: (issue) => `문자 그래프가 너무 작습니다: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, minLength: (issue) => `길이가 너무 짧습니다: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, minSize: (issue) => `크기가 너무 작습니다: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, minValue: (issue) => `값이 너무 작습니다: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, minWords: (issue) => `단어가 너무 적습니다: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, multipleOf: (issue) => `유효하지 않은 배수: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, nanoid: (issue) => `유효하지 않은 Nano ID: ${issue.received} 을(를) 받았습니다`, nonEmpty: (issue) => `값이 비어 있습니다: ${issue.received} 을(를) 받았습니다`, notBytes: (issue) => `허용되지 않는 바이트 길이: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, notEntries: (issue) => `유효하지 않은 항목 수: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, notGraphemes: (issue) => `허용되지 않는 문자 그래프 수: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, notLength: (issue) => `허용되지 않는 길이: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, notSize: (issue) => `허용되지 않는 크기: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, notValue: (issue) => `허용되지 않는 값: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, notValues: (issue) => `유효하지 않은 값: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, notWords: (issue) => `허용되지 않는 단어 수: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, octal: (issue) => `유효하지 않은 8진수: ${issue.received} 을(를) 받았습니다`, parseBoolean: (issue) => `유효하지 않은 불리언 값: ${issue.received} 을(를) 받았습니다`, parseJson: (issue) => `유효하지 않은 JSON: ${issue.received} 을(를) 받았습니다`, partialCheck: (issue) => `부분적으로 유효하지 않은 입력: ${issue.received} 을(를) 받았습니다`, rawCheck: (issue) => `유효하지 않은 입력: ${issue.received} 을(를) 받았습니다`, rawTransform: (issue) => `유효하지 않은 입력: ${issue.received} 을(를) 받았습니다`, regex: (issue) => `정규식에 맞지 않습니다: ${issue.received} 을(를) 받았습니다`, rfcEmail: (issue) => `유효하지 않은 이메일: ${issue.received} 을(를) 받았습니다`, safeInteger: (issue) => `유효하지 않은 안전한 정수: ${issue.received} 을(를) 받았습니다`, size: (issue) => `유효하지 않은 크기: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, slug: (issue) => `유효하지 않은 슬러그: ${issue.received} 을(를) 받았습니다`, someItem: (issue) => `유효하지 않은 항목: ${issue.received} 을(를) 받았습니다`, startsWith: (issue) => `유효하지 않은 시작: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, stringifyJson: (issue) => `유효하지 않은 JSON: ${issue.received} 을(를) 받았습니다`, toBigint: (issue) => `유효하지 않은 BigInt: ${issue.received} 을(를) 받았습니다`, toDate: (issue) => `유효하지 않은 날짜: ${issue.received} 을(를) 받았습니다`, toNumber: (issue) => `유효하지 않은 숫자: ${issue.received} 을(를) 받았습니다`, toString: (issue) => `유효하지 않은 문자열: ${issue.received} 을(를) 받았습니다`, ulid: (issue) => `유효하지 않은 ULID: ${issue.received} 을(를) 받았습니다`, url: (issue) => `유효하지 않은 URL: ${issue.received} 을(를) 받았습니다`, uuid: (issue) => `유효하지 않은 UUID: ${issue.received} 을(를) 받았습니다`, value: (issue) => `유효하지 않은 값: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, values: (issue) => `유효하지 않은 값: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, words: (issue) => `유효하지 않은 단어: ${issue.expected} 을(를) 예상했으나 ${issue.received} 을(를) 받았습니다`, }, }; export default language; ================================================ FILE: packages/i18n/src/kr.ts ================================================ import ko from './ko'; import type { Language } from './types'; /** * @deprecated Use 'ko.ts' instead. The correct ISO 639-1 code for Korean is 'ko'. * This alias will be removed in a future major release. */ const language: Language = { ...ko, code: 'kr' }; export default language; ================================================ FILE: packages/i18n/src/mn.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'mn', schema: (issue) => `Буруу төрөл: ${issue.expected} төрлийг хүлээсэн ч ${issue.received} төрлийн утга ирсэн байна`, specific: { base64: (issue) => `Буруу Base64: ${issue.received} ирлээ`, bic: (issue) => `Буруу BIC: ${issue.received} ирлээ`, bytes: (issue) => `Буруу байт: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, check: (issue) => `Буруу утга: ${issue.received} ирлээ`, checkAsync: (issue) => `Буруу утга: ${issue.received} ирлээ`, checkItems: (issue) => `Буруу элемент: ${issue.received} ирлээ`, checkItemsAsync: (issue) => `Буруу элемент: ${issue.received} ирлээ`, creditCard: (issue) => `Буруу картын дугаар: ${issue.received} ирлээ`, cuid2: (issue) => `Буруу Cuid2: ${issue.received} ирлээ`, decimal: (issue) => `Буруу аравтын тоо: ${issue.received} ирлээ`, digits: (issue) => `Буруу цифр: ${issue.received} ирлээ`, domain: (issue) => `Буруу домэйн: ${issue.received} ирлээ`, email: (issue) => `Буруу имэйл: ${issue.received} ирлээ`, emoji: (issue) => `Буруу эможи: ${issue.received} ирлээ`, empty: (issue) => `Буруу урт: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, endsWith: (issue) => `Буруу төгсгөл: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, entries: (issue) => `Буруу элементийн тоо: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, everyItem: (issue) => `Буруу элемент: ${issue.received} ирлээ`, excludes: (issue) => `Буруу агуулга: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, finite: (issue) => `Буруу хязгаарлагдмал тоо: ${issue.received} ирлээ`, graphemes: (issue) => `Буруу тэмдэгт: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, gtValue: (issue) => `Буруу утга: ${issue.expected}-ээс их байх ёстой ч ${issue.received} ирлээ`, guard: (issue) => `Буруу утга: ${issue.received} ирлээ`, hash: (issue) => `Буруу хэш: ${issue.received} ирлээ`, hexColor: (issue) => `Буруу hex өнгө: ${issue.received} ирлээ`, hexadecimal: (issue) => `Буруу 16-тын тоо: ${issue.received} ирлээ`, imei: (issue) => `Буруу IMEI: ${issue.received} ирлээ`, includes: (issue) => `Буруу агуулга: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, integer: (issue) => `Буруу бүхэл тоо: ${issue.received} ирлээ`, ip: (issue) => `Буруу IP: ${issue.received} ирлээ`, ipv4: (issue) => `Буруу IPv4: ${issue.received} ирлээ`, ipv6: (issue) => `Буруу IPv6: ${issue.received} ирлээ`, isbn: (issue) => `Буруу ISBN: ${issue.received} ирлээ`, isoDate: (issue) => `Буруу огноо: ${issue.received} ирлээ`, isoDateTime: (issue) => `Буруу огноо-цаг: ${issue.received} ирлээ`, isoTime: (issue) => `Буруу цаг: ${issue.received} ирлээ`, isoTimeSecond: (issue) => `Буруу цаг: ${issue.received} ирлээ`, isoTimestamp: (issue) => `Буруу ISO timestamp: ${issue.received} ирлээ`, isoWeek: (issue) => `Буруу долоо хоног: ${issue.received} ирлээ`, isrc: (issue) => `Буруу ISRC: ${issue.received} ирлээ`, jwsCompact: (issue) => `Буруу JWS compact: ${issue.received} ирлээ`, length: (issue) => `Буруу урт: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, ltValue: (issue) => `Буруу утга: ${issue.expected}-ээс бага байх ёстой ч ${issue.received} ирлээ`, mac: (issue) => `Буруу MAC: ${issue.received} ирлээ`, mac48: (issue) => `Буруу 48-bit MAC: ${issue.received} ирлээ`, mac64: (issue) => `Буруу 64-bit MAC: ${issue.received} ирлээ`, maxBytes: (issue) => `Буруу байт хэмжээ: ${issue.expected} хэтрэхгүй байх ёстой ч ${issue.received} ирлээ`, maxEntries: (issue) => `Буруу элементийн тоо: ${issue.expected} хэтрэхгүй байх ёстой ч ${issue.received} ирлээ`, maxGraphemes: (issue) => `Буруу тэмдэгтийн тоо: ${issue.expected} хэтрэхгүй байх ёстой ч ${issue.received} ирлээ`, maxLength: (issue) => `Буруу урт: ${issue.expected} хэтрэхгүй байх ёстой ч ${issue.received} ирлээ`, maxSize: (issue) => `Буруу хэмжээ: ${issue.expected} хэтрэхгүй байх ёстой ч ${issue.received} ирлээ`, maxValue: (issue) => `Буруу утга: ${issue.expected} хэтрэхгүй байх ёстой ч ${issue.received} ирлээ`, maxWords: (issue) => `Буруу үгийн тоо: ${issue.expected} хэтрэхгүй байх ёстой ч ${issue.received} ирлээ`, mimeType: (issue) => `Буруу MIME төрөл: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, minBytes: (issue) => `Буруу байт хэмжээ: ${issue.expected}-с багагүй байх ёстой ч ${issue.received} ирлээ`, minEntries: (issue) => `Буруу элементийн тоо: ${issue.expected}-с багагүй байх ёстой ч ${issue.received} ирлээ`, minGraphemes: (issue) => `Буруу тэмдэгтийн тоо: ${issue.expected}-с багагүй байх ёстой ч ${issue.received} ирлээ`, minLength: (issue) => `Буруу урт: ${issue.expected}-с багагүй байх ёстой ч ${issue.received} ирлээ`, minSize: (issue) => `Буруу хэмжээ: ${issue.expected}-с багагүй байх ёстой ч ${issue.received} ирлээ`, minValue: (issue) => `Буруу утга: ${issue.expected}-с багагүй байх ёстой ч ${issue.received} ирлээ`, minWords: (issue) => `Буруу үгийн тоо: ${issue.expected}-с багагүй байх ёстой ч ${issue.received} ирлээ`, multipleOf: (issue) => `Буруу үржвэр: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, nanoid: (issue) => `Буруу Nano ID: ${issue.received} ирлээ`, nonEmpty: (issue) => `Буруу урт: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, notBytes: (issue) => `Буруу байт хэмжээ: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, notEntries: (issue) => `Буруу элементийн тоо: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, notGraphemes: (issue) => `Буруу тэмдэгтийн тоо: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, notLength: (issue) => `Буруу урт: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, notSize: (issue) => `Буруу хэмжээ: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, notValue: (issue) => `Буруу утга: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, notValues: (issue) => `Буруу утга: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, notWords: (issue) => `Буруу үгс: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, octal: (issue) => `Буруу наймтын тоо: ${issue.received} ирлээ`, parseBoolean: (issue) => `Буруу boolean: ${issue.received} ирлээ`, parseJson: (issue) => `Буруу JSON: ${issue.received} ирлээ`, partialCheck: (issue) => `Буруу утга: ${issue.received} ирлээ`, rawCheck: (issue) => `Буруу утга: ${issue.received} ирлээ`, rawTransform: (issue) => `Буруу утга: ${issue.received} ирлээ`, regex: (issue) => `Буруу формат: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, rfcEmail: (issue) => `Буруу имэйл: ${issue.received} ирлээ`, safeInteger: (issue) => `Буруу аюулгүй бүхэл тоо: ${issue.received} ирлээ`, size: (issue) => `Буруу хэмжээ: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, slug: (issue) => `Буруу slug: ${issue.received} ирлээ`, someItem: (issue) => `Буруу элемент: ${issue.received} ирлээ`, startsWith: (issue) => `Буруу эхлэл: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, stringifyJson: (issue) => `Буруу JSON: ${issue.received} ирлээ`, toBigint: (issue) => `Буруу bigint: ${issue.received} ирлээ`, toDate: (issue) => `Буруу огноо: ${issue.received} ирлээ`, toNumber: (issue) => `Буруу тоо: ${issue.received} ирлээ`, toString: (issue) => `Буруу тэмдэгт мөр: ${issue.received} ирлээ`, ulid: (issue) => `Буруу ULID: ${issue.received} ирлээ`, url: (issue) => `Буруу URL: ${issue.received} ирлээ`, uuid: (issue) => `Буруу UUID: ${issue.received} ирлээ`, value: (issue) => `Буруу утга: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, values: (issue) => `Буруу утга: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, words: (issue) => `Буруу үгс: ${issue.expected} хүлээсэн ч ${issue.received} ирлээ`, }, }; export default language; ================================================ FILE: packages/i18n/src/nb.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'nb', schema: (issue) => `Ugyldig type: Forventet ${issue.expected}, men mottok ${issue.received}`, specific: { base64: (issue) => `Ugyldig Base64: Mottok ${issue.received}`, bic: (issue) => `Ugyldig BIC: Mottok ${issue.received}`, bytes: (issue) => `Ugyldige bytes: Forventet ${issue.expected}, men mottok ${issue.received}`, check: (issue) => `Ugyldig inndata: Mottok ${issue.received}`, checkAsync: (issue) => `Ugyldig inndata: Mottok ${issue.received}`, checkItems: (issue) => `Ugyldig element: Mottok ${issue.received}`, checkItemsAsync: (issue) => `Ugyldig element: Mottok ${issue.received}`, creditCard: (issue) => `Ugyldig kredittkort: Mottok ${issue.received}`, cuid2: (issue) => `Ugyldig Cuid2: Mottok ${issue.received}`, decimal: (issue) => `Ugyldig desimal: Mottok ${issue.received}`, digits: (issue) => `Ugyldig siffer: Mottok ${issue.received}`, domain: (issue) => `Ugyldig domene: Mottok ${issue.received}`, email: (issue) => `Ugyldig e-post: Mottok ${issue.received}`, emoji: (issue) => `Ugyldig emoji: Mottok ${issue.received}`, empty: (issue) => `Ugyldig lengde: Forventet ${issue.expected}, men mottok ${issue.received}`, endsWith: (issue) => `Ugyldig slutt: Forventet ${issue.expected}, men mottok ${issue.received}`, entries: (issue) => `Ugyldige oppføringer: Forventet ${issue.expected}, men mottok ${issue.received}`, everyItem: (issue) => `Ugyldig element: Mottok ${issue.received}`, excludes: (issue) => `Ugyldig innhold: Forventet ${issue.expected}, men mottok ${issue.received}`, finite: (issue) => `Ugyldig endelig: Mottok ${issue.received}`, graphemes: (issue) => `Ugyldig grafem: Forventet ${issue.expected}, men mottok ${issue.received}`, gtValue: (issue) => `Ugyldig verdi: Forventet ${issue.expected}, men mottok ${issue.received}`, guard: (issue) => `Ugyldig inndata: Mottok ${issue.received}`, hash: (issue) => `Ugyldig hash: Mottok ${issue.received}`, hexadecimal: (issue) => `Ugyldig heksadesimal: Mottok ${issue.received}`, hexColor: (issue) => `Ugyldig heksadesimal farge: Mottok ${issue.received}`, imei: (issue) => `Ugyldig IMEI: Mottok ${issue.received}`, includes: (issue) => `Ugyldig innhold: Forventet ${issue.expected}, men mottok ${issue.received}`, integer: (issue) => `Ugyldig heltall: Mottok ${issue.received}`, ip: (issue) => `Ugyldig IP: Mottok ${issue.received}`, ipv4: (issue) => `Ugyldig IPv4: Mottok ${issue.received}`, ipv6: (issue) => `Ugyldig IPv6: Mottok ${issue.received}`, isbn: (issue) => `Ugyldig ISBN: Mottok ${issue.received}`, isoDate: (issue) => `Ugyldig dato: Mottok ${issue.received}`, isoDateTime: (issue) => `Ugyldig dato-klokkeslett: Mottok ${issue.received}`, isoTime: (issue) => `Ugyldig tid: Mottok ${issue.received}`, isoTimeSecond: (issue) => `Ugyldig tidssekund: Mottok ${issue.received}`, isoTimestamp: (issue) => `Ugyldig tidsstempel: Mottok ${issue.received}`, isoWeek: (issue) => `Ugyldig uke: Mottok ${issue.received}`, isrc: (issue) => `Ugyldig ISRC: Mottok ${issue.received}`, jwsCompact: (issue) => `Ugyldig kompakt JWS: Mottok ${issue.received}`, length: (issue) => `Ugyldig lengde: Forventet ${issue.expected}, men mottok ${issue.received}`, ltValue: (issue) => `Ugyldig verdi: Forventet ${issue.expected}, men mottok ${issue.received}`, mac: (issue) => `Ugyldig MAC: Mottok ${issue.received}`, mac48: (issue) => `Ugyldig 48-bit MAC: Mottok ${issue.received}`, mac64: (issue) => `Ugyldig 64-bit MAC: Mottok ${issue.received}`, maxBytes: (issue) => `Ugyldige bytes: Forventet ${issue.expected}, men mottok ${issue.received}`, maxEntries: (issue) => `Ugyldige oppføringer: Forventet ${issue.expected}, men mottok ${issue.received}`, maxGraphemes: (issue) => `Ugyldig grafem: Forventet ${issue.expected}, men mottok ${issue.received}`, maxLength: (issue) => `Ugyldig lengde: Forventet ${issue.expected}, men mottok ${issue.received}`, maxSize: (issue) => `Ugyldig størrelse: Forventet ${issue.expected}, men mottok ${issue.received}`, maxValue: (issue) => `Ugyldig verdi: Forventet ${issue.expected}, men mottok ${issue.received}`, maxWords: (issue) => `Ugyldig ord: Forventet ${issue.expected}, men mottok ${issue.received}`, mimeType: (issue) => `Ugyldig MIME-type: Forventet ${issue.expected}, men mottok ${issue.received}`, minBytes: (issue) => `Ugyldige bytes: Forventet ${issue.expected}, men mottok ${issue.received}`, minEntries: (issue) => `Ugyldige oppføringer: Forventet ${issue.expected}, men mottok ${issue.received}`, minGraphemes: (issue) => `Ugyldig grafem: Forventet ${issue.expected}, men mottok ${issue.received}`, minLength: (issue) => `Ugyldig lengde: Forventet ${issue.expected}, men mottok ${issue.received}`, minSize: (issue) => `Ugyldig størrelse: Forventet ${issue.expected}, men mottok ${issue.received}`, minValue: (issue) => `Ugyldig verdi: Forventet ${issue.expected}, men mottok ${issue.received}`, minWords: (issue) => `Ugyldig ord: Forventet ${issue.expected}, men mottok ${issue.received}`, multipleOf: (issue) => `Ugyldig multiplum: Forventet ${issue.expected}, men mottok ${issue.received}`, nanoid: (issue) => `Ugyldig Nano ID: Mottok ${issue.received}`, nonEmpty: (issue) => `Ugyldig lengde: Forventet ${issue.expected}, men mottok ${issue.received}`, notBytes: (issue) => `Ugyldige bytes: Forventet ${issue.expected}, men mottok ${issue.received}`, notEntries: (issue) => `Ugyldige oppføringer: Forventet ${issue.expected}, men mottok ${issue.received}`, notGraphemes: (issue) => `Ugyldig grafem: Forventet ${issue.expected}, men mottok ${issue.received}`, notLength: (issue) => `Ugyldig lengde: Forventet ${issue.expected}, men mottok ${issue.received}`, notSize: (issue) => `Ugyldig størrelse: Forventet ${issue.expected}, men mottok ${issue.received}`, notValue: (issue) => `Ugyldig verdi: Forventet ${issue.expected}, men mottok ${issue.received}`, notValues: (issue) => `Ugyldig verdi: Forventet ${issue.expected}, men mottok ${issue.received}`, notWords: (issue) => `Ugyldig ord: Forventet ${issue.expected}, men mottok ${issue.received}`, octal: (issue) => `Ugyldig oktal: Mottok ${issue.received}`, parseBoolean: (issue) => `Ugyldig boolsk verdi: Mottok ${issue.received}`, parseJson: (issue) => `Ugyldig JSON: Mottok ${issue.received}`, partialCheck: (issue) => `Ugyldig inndata: Mottok ${issue.received}`, rawCheck: (issue) => `Ugyldig inndata: Mottok ${issue.received}`, rawTransform: (issue) => `Ugyldig inndata: Mottok ${issue.received}`, regex: (issue) => `Ugyldig format: Forventet ${issue.expected}, men mottok ${issue.received}`, rfcEmail: (issue) => `Ugyldig e-post: Mottok ${issue.received}`, safeInteger: (issue) => `Ugyldig sikkert heltall: Mottok ${issue.received}`, size: (issue) => `Ugyldig størrelse: Forventet ${issue.expected}, men mottok ${issue.received}`, slug: (issue) => `Ugyldig slug: Mottok ${issue.received}`, someItem: (issue) => `Ugyldig element: Mottok ${issue.received}`, startsWith: (issue) => `Ugyldig start: Forventet ${issue.expected}, men mottok ${issue.received}`, stringifyJson: (issue) => `Ugyldig JSON: Mottok ${issue.received}`, toBigint: (issue) => `Ugyldig BigInt: Mottok ${issue.received}`, toDate: (issue) => `Ugyldig dato: Mottok ${issue.received}`, toNumber: (issue) => `Ugyldig tall: Mottok ${issue.received}`, toString: (issue) => `Ugyldig streng: Mottok ${issue.received}`, ulid: (issue) => `Ugyldig ULID: Mottok ${issue.received}`, url: (issue) => `Ugyldig URL: Mottok ${issue.received}`, uuid: (issue) => `Ugyldig UUID: Mottok ${issue.received}`, value: (issue) => `Ugyldig verdi: Forventet ${issue.expected}, men mottok ${issue.received}`, values: (issue) => `Ugyldig verdi: Forventet ${issue.expected}, men mottok ${issue.received}`, words: (issue) => `Ugyldig ord: Forventet ${issue.expected}, men mottok ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/nl.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'nl', schema: (issue) => `Ongeldig type: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, specific: { base64: (issue) => `Ongeldige Base64: ${issue.received} ontvangen`, bic: (issue) => `Ongeldige BIC: ${issue.received} ontvangen`, bytes: (issue) => `Ongeldige bytes: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, check: (issue) => `Ongeldige invoer: ${issue.received} ontvangen`, checkAsync: (issue) => `Ongeldige invoer: ${issue.received} ontvangen`, checkItems: (issue) => `Ongeldige item: ${issue.received} ontvangen`, checkItemsAsync: (issue) => `Ongeldige item: ${issue.received} ontvangen`, creditCard: (issue) => `Ongeldige creditcard: ${issue.received} ontvangen`, cuid2: (issue) => `Ongeldige Cuid2: ${issue.received} ontvangen`, decimal: (issue) => `Ongeldige decimaal: ${issue.received} ontvangen`, digits: (issue) => `Ongeldige cijfers: ${issue.received} ontvangen`, domain: (issue) => `Ongeldig domein: ${issue.received} ontvangen`, email: (issue) => `Ongeldige e-mail: ${issue.received} ontvangen`, emoji: (issue) => `Ongeldige emoji: ${issue.received} ontvangen`, empty: (issue) => `Ongeldige lengte: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, endsWith: (issue) => `Ongeldig einde: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, entries: (issue) => `Ongeldig aantal items: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, everyItem: (issue) => `Ongeldig item: ${issue.received} ontvangen`, excludes: (issue) => `Ongeldige inhoud: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, finite: (issue) => `Ongeldige eindige: ${issue.received} ontvangen`, graphemes: (issue) => `Ongeldige grafemen: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, gtValue: (issue) => `Ongeldige waarde: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, guard: (issue) => `Ongeldige invoer: ${issue.received} ontvangen`, hash: (issue) => `Ongeldige hash: ${issue.received} ontvangen`, hexadecimal: (issue) => `Ongeldige hexadecimaal: ${issue.received} ontvangen`, hexColor: (issue) => `Ongeldige hex kleur: ${issue.received} ontvangen`, imei: (issue) => `Ongeldige IMEI: ${issue.received} ontvangen`, includes: (issue) => `Ongeldige inhoud: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, integer: (issue) => `Ongeldig geheel getal: ${issue.received} ontvangen`, ip: (issue) => `Ongeldige IP: ${issue.received} ontvangen`, ipv4: (issue) => `Ongeldig IPv4: ${issue.received} ontvangen`, ipv6: (issue) => `Ongeldig IPv6: ${issue.received} ontvangen`, isbn: (issue) => `Ongeldige ISBN: ${issue.received} ontvangen`, isoDate: (issue) => `Ongeldige datum: ${issue.received} ontvangen`, isoDateTime: (issue) => `Ongeldige datum-tijd: ${issue.received} ontvangen`, isoTime: (issue) => `Ongeldige tijd: ${issue.received} ontvangen`, isoTimeSecond: (issue) => `Ongeldige tijd in seconden: ${issue.received} ontvangen`, isoTimestamp: (issue) => `Ongeldige tijdstempel: ${issue.received} ontvangen`, isoWeek: (issue) => `Ongeldige week: ${issue.received} ontvangen`, isrc: (issue) => `Ongeldige ISRC: ${issue.received} ontvangen`, jwsCompact: (issue) => `Ongeldige compacte JWS: ${issue.received} ontvangen`, length: (issue) => `Ongeldige lengte: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, ltValue: (issue) => `Ongeldige waarde: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, mac: (issue) => `Ongeldige MAC: ${issue.received} ontvangen`, mac48: (issue) => `Ongeldige 48-bit MAC: ${issue.received} ontvangen`, mac64: (issue) => `Ongeldige 64-bit MAC: ${issue.received} ontvangen`, maxBytes: (issue) => `Ongeldige bytes: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, maxEntries: (issue) => `Ongeldig aantal items: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, maxGraphemes: (issue) => `Ongeldige grafemen: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, maxLength: (issue) => `Ongeldige lengte: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, maxSize: (issue) => `Ongeldige grootte: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, maxValue: (issue) => `Ongeldige waarde: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, maxWords: (issue) => `Ongeldige woorden: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, mimeType: (issue) => `Ongeldig MIME-type: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, minBytes: (issue) => `Ongeldige bytes: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, minEntries: (issue) => `Ongeldig aantal items: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, minGraphemes: (issue) => `Ongeldige grafemen: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, minLength: (issue) => `Ongeldige lengte: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, minSize: (issue) => `Ongeldige grootte: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, minValue: (issue) => `Ongeldige waarde: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, minWords: (issue) => `Ongeldige woorden: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, multipleOf: (issue) => `Ongeldige meervoudige: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, nanoid: (issue) => `Ongeldige Nano ID: ${issue.received} ontvangen`, nonEmpty: (issue) => `Ongeldige lengte: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, notBytes: (issue) => `Ongeldige bytes: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, notEntries: (issue) => `Ongeldig aantal items: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, notGraphemes: (issue) => `Ongeldige grafemen: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, notLength: (issue) => `Ongeldige lengte: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, notSize: (issue) => `Ongeldige grootte: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, notValue: (issue) => `Ongeldige waarde: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, notValues: (issue) => `Ongeldige waarde: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, notWords: (issue) => `Ongeldige woorden: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, octal: (issue) => `Ongeldige octaal: ${issue.received} ontvangen`, parseBoolean: (issue) => `Ongeldige booleaanse waarde: ${issue.received} ontvangen`, parseJson: (issue) => `Ongeldige JSON: ${issue.received} ontvangen`, partialCheck: (issue) => `Ongeldige invoer: ${issue.received} ontvangen`, rawCheck: (issue) => `Ongeldige invoer: ${issue.received} ontvangen`, rawTransform: (issue) => `Ongeldige invoer: ${issue.received} ontvangen`, regex: (issue) => `Ongeldig formaat: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, rfcEmail: (issue) => `Ongeldige e-mail: ${issue.received} ontvangen`, safeInteger: (issue) => `Ongeldig veilig geheel getal: ${issue.received} ontvangen`, size: (issue) => `Ongeldige grootte: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, slug: (issue) => `Ongeldige slug: ${issue.received} ontvangen`, someItem: (issue) => `Ongeldig item: ${issue.received} ontvangen`, startsWith: (issue) => `Ongeldig begin: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, stringifyJson: (issue) => `Ongeldige JSON: ${issue.received} ontvangen`, toBigint: (issue) => `Ongeldige BigInt: ${issue.received} ontvangen`, toDate: (issue) => `Ongeldige datum: ${issue.received} ontvangen`, toNumber: (issue) => `Ongeldig getal: ${issue.received} ontvangen`, toString: (issue) => `Ongeldige tekenreeks: ${issue.received} ontvangen`, ulid: (issue) => `Ongeldige ULID: ${issue.received} ontvangen`, url: (issue) => `Ongeldige URL: ${issue.received} ontvangen`, uuid: (issue) => `Ongeldige UUID: ${issue.received} ontvangen`, value: (issue) => `Ongeldige waarde: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, values: (issue) => `Ongeldige waarde: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, words: (issue) => `Ongeldige woorden: ${issue.expected} verwacht, maar ${issue.received} ontvangen`, }, }; export default language; ================================================ FILE: packages/i18n/src/pl.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'pl', schema: (issue) => `Nieprawidłowy typ: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, specific: { base64: (issue) => `Nieprawidłowe Base64: Otrzymano ${issue.received}`, bic: (issue) => `Nieprawidłowy BIC: Otrzymano ${issue.received}`, bytes: (issue) => `Nieprawidłowe bajty: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, check: (issue) => `Nieprawidłowe dane: Otrzymano ${issue.received}`, checkAsync: (issue) => `Nieprawidłowe dane: Otrzymano ${issue.received}`, checkItems: (issue) => `Nieprawidłowy element: Otrzymano ${issue.received}`, checkItemsAsync: (issue) => `Nieprawidłowy element: Otrzymano ${issue.received}`, creditCard: (issue) => `Nieprawidłowy numer karty kredytowej: Otrzymano ${issue.received}`, cuid2: (issue) => `Nieprawidłowy Cuid2: Otrzymano ${issue.received}`, decimal: (issue) => `Nieprawidłowa wartość dziesiętna: Otrzymano ${issue.received}`, digits: (issue) => `Nieprawidłowa liczba: Otrzymano ${issue.received}`, domain: (issue) => `Nieprawidłowa domena: Otrzymano ${issue.received}`, email: (issue) => `Nieprawidłowy email: Otrzymano ${issue.received}`, emoji: (issue) => `Nieprawidłowa emoji: Otrzymano ${issue.received}`, empty: (issue) => `Nieprawidłowa długość: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, endsWith: (issue) => `Nieprawidłowa końcówka: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, entries: (issue) => `Nieprawidłowa liczba wpisów: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, everyItem: (issue) => `Nieprawidłowy element: Otrzymano ${issue.received}`, excludes: (issue) => `Nieprawidłowa zawartość: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, finite: (issue) => `Nieprawidłowa wartość skończona: Otrzymano ${issue.received}`, graphemes: (issue) => `Nieprawidłowe grafemy: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, gtValue: (issue) => `Nieprawidłowa wartość: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, guard: (issue) => `Nieprawidłowe dane: Otrzymano ${issue.received}`, hash: (issue) => `Nieprawidłowy hash: Otrzymano ${issue.received}`, hexadecimal: (issue) => `Nieprawidłowa wartość szesnastkowa: Otrzymano ${issue.received}`, hexColor: (issue) => `Nieprawidłowy kolor hex: Otrzymano ${issue.received}`, imei: (issue) => `Nieprawidłowy IMEI: Otrzymano ${issue.received}`, includes: (issue) => `Nieprawidłowa zawartość: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, integer: (issue) => `Nieprawidłowa liczba całkowita: Otrzymano ${issue.received}`, ip: (issue) => `Nieprawidłowy adres IP: Otrzymano ${issue.received}`, ipv4: (issue) => `Nieprawidłowy adres IPv4: Otrzymano ${issue.received}`, ipv6: (issue) => `Nieprawidłowy adres IPv6: Otrzymano ${issue.received}`, isbn: (issue) => `Nieprawidłowy ISBN: Otrzymano ${issue.received}`, isoDate: (issue) => `Nieprawidłowa data: Otrzymano ${issue.received}`, isoDateTime: (issue) => `Nieprawidłowa data i czas: Otrzymano ${issue.received}`, isoTime: (issue) => `Nieprawidłowy czas: Otrzymano ${issue.received}`, isoTimeSecond: (issue) => `Nieprawidłowa wartość sekundy czasu: Otrzymano ${issue.received}`, isoTimestamp: (issue) => `Nieprawidłowy znacznik czasu: Otrzymano ${issue.received}`, isoWeek: (issue) => `Nieprawidłowy tydzień: Otrzymano ${issue.received}`, isrc: (issue) => `Nieprawidłowy ISRC: Otrzymano ${issue.received}`, jwsCompact: (issue) => `Nieprawidłowy kompaktowy JWS: Otrzymano ${issue.received}`, length: (issue) => `Nieprawidłowa długość: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, ltValue: (issue) => `Nieprawidłowa wartość: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, mac: (issue) => `Nieprawidłowy adres MAC: Otrzymano ${issue.received}`, mac48: (issue) => `Nieprawidłowy 48-bitowy adres MAC: Otrzymano ${issue.received}`, mac64: (issue) => `Nieprawidłowy 64-bitowy adres MAC: Otrzymano ${issue.received}`, maxBytes: (issue) => `Nieprawidłowe bajty: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, maxEntries: (issue) => `Nieprawidłowa liczba wpisów: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, maxGraphemes: (issue) => `Nieprawidłowe grafemy: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, maxLength: (issue) => `Nieprawidłowa długość: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, maxSize: (issue) => `Nieprawidłowy rozmiar: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, maxValue: (issue) => `Nieprawidłowa wartość: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, maxWords: (issue) => `Nieprawidłowe słowa: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, mimeType: (issue) => `Nieprawidłowy typ MIME: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, minBytes: (issue) => `Nieprawidłowe bajty: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, minEntries: (issue) => `Nieprawidłowa liczba wpisów: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, minGraphemes: (issue) => `Nieprawidłowe grafemy: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, minLength: (issue) => `Nieprawidłowa długość: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, minSize: (issue) => `Nieprawidłowy rozmiar: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, minValue: (issue) => `Nieprawidłowa wartość: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, minWords: (issue) => `Nieprawidłowe słowa: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, multipleOf: (issue) => `Nieprawidłowa wielokrotność: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, nanoid: (issue) => `Nieprawidłowy identyfikator Nano ID: Otrzymano ${issue.received}`, nonEmpty: (issue) => `Nieprawidłowa długość: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, notBytes: (issue) => `Nieprawidłowe bajty: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, notEntries: (issue) => `Nieprawidłowa liczba wpisów: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, notGraphemes: (issue) => `Nieprawidłowe grafemy: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, notLength: (issue) => `Nieprawidłowa długość: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, notSize: (issue) => `Nieprawidłowy rozmiar: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, notValue: (issue) => `Nieprawidłowa wartość: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, notValues: (issue) => `Nieprawidłowa wartość: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, notWords: (issue) => `Nieprawidłowe słowa: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, octal: (issue) => `Nieprawidłowa wartość ósemkowa: Otrzymano ${issue.received}`, parseBoolean: (issue) => `Nieprawidłowa wartość logiczna: Otrzymano ${issue.received}`, parseJson: (issue) => `Nieprawidłowy JSON: Otrzymano ${issue.received}`, partialCheck: (issue) => `Nieprawidłowe dane: Otrzymano ${issue.received}`, rawCheck: (issue) => `Nieprawidłowe dane: Otrzymano ${issue.received}`, rawTransform: (issue) => `Nieprawidłowe dane: Otrzymano ${issue.received}`, regex: (issue) => `Nieprawidłowy format: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, rfcEmail: (issue) => `Nieprawidłowy email: Otrzymano ${issue.received}`, safeInteger: (issue) => `Nieprawidłowa bezpieczna liczba całkowita: Otrzymano ${issue.received}`, size: (issue) => `Nieprawidłowy rozmiar: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, slug: (issue) => `Nieprawidłowy slug: Otrzymano ${issue.received}`, someItem: (issue) => `Nieprawidłowy element: Otrzymano ${issue.received}`, startsWith: (issue) => `Nieprawidłowy początek: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, stringifyJson: (issue) => `Nieprawidłowy JSON: Otrzymano ${issue.received}`, toBigint: (issue) => `Nieprawidłowy BigInt: Otrzymano ${issue.received}`, toDate: (issue) => `Nieprawidłowa data: Otrzymano ${issue.received}`, toNumber: (issue) => `Nieprawidłowa liczba: Otrzymano ${issue.received}`, toString: (issue) => `Nieprawidłowy ciąg znaków: Otrzymano ${issue.received}`, ulid: (issue) => `Nieprawidłowy ULID: Otrzymano ${issue.received}`, url: (issue) => `Nieprawidłowy URL: Otrzymano ${issue.received}`, uuid: (issue) => `Nieprawidłowy UUID: Otrzymano ${issue.received}`, value: (issue) => `Nieprawidłowa wartość: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, values: (issue) => `Nieprawidłowa wartość: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, words: (issue) => `Nieprawidłowe słowa: Oczekiwano ${issue.expected}, ale otrzymano ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/pt.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'pt', schema: (issue) => `Tipo inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, specific: { base64: (issue) => `Base64 inválido: Recebido ${issue.received}`, bic: (issue) => `BIC inválido: Recebido ${issue.received}`, bytes: (issue) => `Bytes inválidos: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, check: (issue) => `Entrada inválida: Recebido ${issue.received}`, checkAsync: (issue) => `Entrada inválida: Recebido ${issue.received}`, checkItems: (issue) => `Item inválido: Recebido ${issue.received}`, checkItemsAsync: (issue) => `Item inválido: Recebido ${issue.received}`, creditCard: (issue) => `Cartão de crédito inválido: Recebido ${issue.received}`, cuid2: (issue) => `Cuid2 inválido: Recebido ${issue.received}`, decimal: (issue) => `Decimal inválido: Recebido ${issue.received}`, digits: (issue) => `Dígitos inválidos: Recebido ${issue.received}`, domain: (issue) => `Domínio inválido: Recebido ${issue.received}`, email: (issue) => `Email inválido: Recebido ${issue.received}`, emoji: (issue) => `Emoji inválido: Recebido ${issue.received}`, empty: (issue) => `Tamanho inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, endsWith: (issue) => `Fim inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, entries: (issue) => `Entradas inválidas: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, everyItem: (issue) => `Item inválido: Recebido ${issue.received}`, excludes: (issue) => `Conteúdo inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, finite: (issue) => `Finito inválido: Recebido ${issue.received}`, graphemes: (issue) => `Grafemas inválidos: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, gtValue: (issue) => `Valor inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, guard: (issue) => `Entrada inválida: Recebido ${issue.received}`, hash: (issue) => `Hash inválido: Recebido ${issue.received}`, hexadecimal: (issue) => `Hexadecimal inválido: Recebido ${issue.received}`, hexColor: (issue) => `Cor hexadecimal inválida: Recebido ${issue.received}`, imei: (issue) => `IMEI inválido: Recebido ${issue.received}`, includes: (issue) => `Conteúdo inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, integer: (issue) => `Inteiro inválido: Recebido ${issue.received}`, ip: (issue) => `IP inválido: Recebido ${issue.received}`, ipv4: (issue) => `IPv4 inválido: Recebido ${issue.received}`, ipv6: (issue) => `IPv6 inválido: Recebido ${issue.received}`, isbn: (issue) => `ISBN inválido: Recebido ${issue.received}`, isoDate: (issue) => `Data inválida: Recebido ${issue.received}`, isoDateTime: (issue) => `Data e hora inválidas: Recebido ${issue.received}`, isoTime: (issue) => `Hora inválida: Recebido ${issue.received}`, isoTimeSecond: (issue) => `Segundo inválido: Recebido ${issue.received}`, isoTimestamp: (issue) => `Timestamp inválido: Recebido ${issue.received}`, isoWeek: (issue) => `Semana inválida: Recebido ${issue.received}`, isrc: (issue) => `ISRC inválido: Recebido ${issue.received}`, jwsCompact: (issue) => `JWS compacto inválido: Recebido ${issue.received}`, length: (issue) => `Tamanho inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, ltValue: (issue) => `Valor inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, mac: (issue) => `MAC inválido: Recebido ${issue.received}`, mac48: (issue) => `MAC de 48-bits inválido: Recebido ${issue.received}`, mac64: (issue) => `MAC de 64-bits inválido: Recebido ${issue.received}`, maxBytes: (issue) => `Bytes inválidos: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, maxEntries: (issue) => `Entradas inválidas: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, maxGraphemes: (issue) => `Grafemas inválidos: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, maxLength: (issue) => `Tamanho inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, maxSize: (issue) => `Tamanho inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, maxValue: (issue) => `Valor máximo inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, maxWords: (issue) => `Palavras inválidas: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, mimeType: (issue) => `Tipo MIME inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, minBytes: (issue) => `Bytes mínimos inválidos: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, minEntries: (issue) => `Entradas inválidas: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, minGraphemes: (issue) => `Grafemas inválidos: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, minLength: (issue) => `Tamanho inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, minSize: (issue) => `Tamanho inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, minValue: (issue) => `Valor inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, minWords: (issue) => `Palavras inválidas: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, multipleOf: (issue) => `Múltiplo inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, nanoid: (issue) => `ID Nano inválido: Recebido ${issue.received}`, nonEmpty: (issue) => `Tamanho inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, notBytes: (issue) => `Bytes inválidos: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, notEntries: (issue) => `Entradas inválidas: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, notGraphemes: (issue) => `Grafemas inválidos: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, notLength: (issue) => `Tamanho inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, notSize: (issue) => `Tamanho inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, notValue: (issue) => `Valor inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, notValues: (issue) => `Valor inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, notWords: (issue) => `Palavras inválidas: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, octal: (issue) => `Octal inválido: Recebido ${issue.received}`, parseBoolean: (issue) => `Booleano inválido: Recebido ${issue.received}`, parseJson: (issue) => `JSON inválido: Recebido ${issue.received}`, partialCheck: (issue) => `Valor inválido: Recebido ${issue.received}`, rawCheck: (issue) => `Entrada inválida: Recebido ${issue.received}`, rawTransform: (issue) => `Entrada inválida: Recebido ${issue.received}`, regex: (issue) => `Formato inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, rfcEmail: (issue) => `Email inválido: Recebido ${issue.received}`, safeInteger: (issue) => `Inteiro seguro inválido: Recebido ${issue.received}`, size: (issue) => `Tamanho inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, slug: (issue) => `Slug inválido: Recebido ${issue.received}`, someItem: (issue) => `Item inválido: Recebido ${issue.received}`, startsWith: (issue) => `Início inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, stringifyJson: (issue) => `JSON inválido: Recebido ${issue.received}`, toBigint: (issue) => `BigInt inválido: Recebido ${issue.received}`, toDate: (issue) => `Data inválida: Recebido ${issue.received}`, toNumber: (issue) => `Número inválido: Recebido ${issue.received}`, toString: (issue) => `String inválida: Recebido ${issue.received}`, ulid: (issue) => `ULID inválido: Recebido ${issue.received}`, url: (issue) => `URL inválido: Recebido ${issue.received}`, uuid: (issue) => `UUID inválido: Recebido ${issue.received}`, value: (issue) => `Valor inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, values: (issue) => `Valor inválido: Esperado ${issue.expected}, porém foi recebido ${issue.received}`, words: (issue) => `Palavras inválidas: Recebido ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/ro.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'ro', schema: (issue) => `Tip incorect: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, specific: { base64: (issue) => `Base64 incorect: S-a introdus ${issue.received}`, bic: (issue) => `BIC incorect: S-a introdus ${issue.received}`, bytes: (issue) => `Bytes incorect: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, check: (issue) => `Intrare incorectă: S-a introdus ${issue.received}`, checkAsync: (issue) => `Intrare incorectă: S-a introdus ${issue.received}`, checkItems: (issue) => `Element incorect: S-a introdus ${issue.received}`, checkItemsAsync: (issue) => `Element incorect: S-a introdus ${issue.received}`, creditCard: (issue) => `Card de credit incorect: S-a introdus ${issue.received}`, cuid2: (issue) => `Cuid2 incorect: S-a introdus ${issue.received}`, decimal: (issue) => `Zecimal incorect: S-a introdus ${issue.received}`, digits: (issue) => `Cifre incorecte: S-a introdus ${issue.received}`, domain: (issue) => `Domeniu incorect: S-a introdus ${issue.received}`, email: (issue) => `Email incorect: S-a introdus ${issue.received}`, emoji: (issue) => `Emoji incorect: S-a introdus ${issue.received}`, empty: (issue) => `Lungime incorectă: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, endsWith: (issue) => `Sfârșit incorect: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, entries: (issue) => `Număr de intrări incorect: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, everyItem: (issue) => `Element incorect: S-a introdus ${issue.received}`, excludes: (issue) => `Conținut incorect: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, finite: (issue) => `Finit incorect: S-a introdus ${issue.received}`, graphemes: (issue) => `Grafeme incorecte: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, gtValue: (issue) => `Valoare incorectă: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, guard: (issue) => `Intrare incorectă: S-a introdus ${issue.received}`, hash: (issue) => `Hash incorect: S-a introdus ${issue.received}`, hexadecimal: (issue) => `Hexazecimal incorect: S-a introdus ${issue.received}`, hexColor: (issue) => `Culoare hex incorectă: S-a introdus ${issue.received}`, imei: (issue) => `IMEI incorect: S-a introdus ${issue.received}`, includes: (issue) => `Conținut incorect: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, integer: (issue) => `Număr întreg incorect: S-a introdus ${issue.received}`, ip: (issue) => `IP incorect: S-a introdus ${issue.received}`, ipv4: (issue) => `IPv4 incorect: S-a introdus ${issue.received}`, ipv6: (issue) => `IPv6 incorect: S-a introdus ${issue.received}`, isbn: (issue) => `ISBN incorect: S-a introdus ${issue.received}`, isoDate: (issue) => `Dată incorectă: S-a introdus ${issue.received}`, isoDateTime: (issue) => `Dată-timp incorect: S-a introdus ${issue.received}`, isoTime: (issue) => `Timp incorect: S-a introdus ${issue.received}`, isoTimeSecond: (issue) => `Secundă-timp incorect: S-a introdus ${issue.received}`, isoTimestamp: (issue) => `Timestamp incorect: S-a introdus ${issue.received}`, isoWeek: (issue) => `Săptămână incorectă: S-a introdus ${issue.received}`, isrc: (issue) => `ISRC incorect: S-a introdus ${issue.received}`, jwsCompact: (issue) => `JWS compact incorect: S-a introdus ${issue.received}`, length: (issue) => `Lungime incorectă: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, ltValue: (issue) => `Valoare incorectă: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, mac: (issue) => `MAC incorect: S-a introdus ${issue.received}`, mac48: (issue) => `48-bit MAC incorect: S-a introdus ${issue.received}`, mac64: (issue) => `64-bit MAC incorect: S-a introdus ${issue.received}`, maxBytes: (issue) => `Număr de bytes incorect: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, maxEntries: (issue) => `Număr de intrări incorect: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, maxGraphemes: (issue) => `Număr de grafeme incorect: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, maxLength: (issue) => `Lungime incorectă: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, maxSize: (issue) => `Dimensiune incorectă: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, maxValue: (issue) => `Valoare incorectă: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, maxWords: (issue) => `Număr maxim de cuvinte incorect: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, mimeType: (issue) => `Tip MIME incorect: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, minBytes: (issue) => `Număr minim de bytes incorect: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, minEntries: (issue) => `Număr de intrări incorect: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, minGraphemes: (issue) => `Număr minim de grafeme incorect: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, minLength: (issue) => `Lungime minimă incorectă: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, minSize: (issue) => `Dimensiune minimă incorectă: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, minValue: (issue) => `Valoare minimă incorectă: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, minWords: (issue) => `Număr minim de cuvinte incorect: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, multipleOf: (issue) => `Multiplu incorect: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, nanoid: (issue) => `Nano ID incorect: S-a introdus ${issue.received}`, nonEmpty: (issue) => `Lungime incorectă: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, notBytes: (issue) => `Bytes incorect: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, notEntries: (issue) => `Număr de intrări incorect: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, notGraphemes: (issue) => `Grafeme incorecte: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, notLength: (issue) => `Lungime incorectă: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, notSize: (issue) => `Dimensiune incorectă: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, notValue: (issue) => `Valoare incorectă: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, notValues: (issue) => `Valoare incorectă: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, notWords: (issue) => `Cuvinte incorecte: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, octal: (issue) => `Octal incorect: S-a introdus ${issue.received}`, parseBoolean: (issue) => `Boolean incorect: S-a introdus ${issue.received}`, parseJson: (issue) => `JSON incorect: S-a introdus ${issue.received}`, partialCheck: (issue) => `Intrare incorectă: S-a introdus ${issue.received}`, rawCheck: (issue) => `Intrare incorectă: S-a introdus ${issue.received}`, rawTransform: (issue) => `Intrare incorectă: S-a introdus ${issue.received}`, regex: (issue) => `Format incorect: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, rfcEmail: (issue) => `Email incorect: S-a introdus ${issue.received}`, safeInteger: (issue) => `Întreg sigur incorect: S-a introdus ${issue.received}`, size: (issue) => `Dimensiune incorectă: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, slug: (issue) => `Slug incorect: S-a introdus ${issue.received}`, someItem: (issue) => `Element incorect: S-a introdus ${issue.received}`, startsWith: (issue) => `Început incorect: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, stringifyJson: (issue) => `JSON incorect: S-a introdus ${issue.received}`, toBigint: (issue) => `BigInt incorect: S-a introdus ${issue.received}`, toDate: (issue) => `Dată incorectă: S-a introdus ${issue.received}`, toNumber: (issue) => `Număr incorect: S-a introdus ${issue.received}`, toString: (issue) => `Șir incorect: S-a introdus ${issue.received}`, ulid: (issue) => `ULID incorect: S-a introdus ${issue.received}`, url: (issue) => `URL incorect: S-a introdus ${issue.received}`, uuid: (issue) => `UUID incorect: S-a introdus ${issue.received}`, value: (issue) => `Valoare incorectă: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, values: (issue) => `Valoare incorectă: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, words: (issue) => `Cuvinte incorecte: Specificat era ${issue.expected} dar s-a introdus ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/ru.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'ru', schema: (issue) => `Неправильный тип: ожидалось ${issue.expected}, получено ${issue.received}`, specific: { base64: (issue) => `Неправильный Base64: получено ${issue.received}`, bic: (issue) => `Неправильный BIC: получено ${issue.received}`, bytes: (issue) => `Неправильное количество байтов: ожидалось ${issue.expected}, получено ${issue.received}`, check: (issue) => `Неправильные данные: получено ${issue.received}`, checkAsync: (issue) => `Неправильные данные: получено ${issue.received}`, checkItems: (issue) => `Неправильный элемент: получено ${issue.received}`, checkItemsAsync: (issue) => `Неправильный элемент: получено ${issue.received}`, creditCard: (issue) => `Неправильный номер кредитной карты: получено ${issue.received}`, cuid2: (issue) => `Неправильный Cuid2: получено ${issue.received}`, decimal: (issue) => `Неправильное десятичное значение: получено ${issue.received}`, digits: (issue) => `Неправильное число: получено ${issue.received}`, domain: (issue) => `Неправильный домен: получено ${issue.received}`, email: (issue) => `Неправильный email: получено ${issue.received}`, emoji: (issue) => `Неправильный эмодзи: получено ${issue.received}`, empty: (issue) => `Неправильная длина: ожидалось ${issue.expected}, получено ${issue.received}`, endsWith: (issue) => `Неправильный конец: ожидалось ${issue.expected}, получено ${issue.received}`, entries: (issue) => `Неправильное количество записей: ожидалось ${issue.expected}, получено ${issue.received}`, everyItem: (issue) => `Неправильный элемент: получено ${issue.received}`, excludes: (issue) => `Неправильное вхождение: ожидалось ${issue.expected}, получено ${issue.received}`, finite: (issue) => `Неправильное конечное число: получено ${issue.received}`, graphemes: (issue) => `Неправильное количество графем: ожидалось ${issue.expected}, получено ${issue.received}`, gtValue: (issue) => `Неправильное значение: ожидалось ${issue.expected}, получено ${issue.received}`, guard: (issue) => `Неправильные данные: получено ${issue.received}`, hash: (issue) => `Неправильный хеш: получено ${issue.received}`, hexadecimal: (issue) => `Неправильное шестнадцатеричное значение: получено ${issue.received}`, hexColor: (issue) => `Неправильный шестнадцатеричный цвет: получено ${issue.received}`, imei: (issue) => `Неправильный IMEI: получено ${issue.received}`, includes: (issue) => `Неправильное вхождение: ожидалось ${issue.expected}, получено ${issue.received}`, integer: (issue) => `Неправильное целое число: получено ${issue.received}`, ip: (issue) => `Неправильный IP: получено ${issue.received}`, ipv4: (issue) => `Неправильный IPv4: получено ${issue.received}`, ipv6: (issue) => `Неправильный IPv6: получено ${issue.received}`, isbn: (issue) => `Неправильный ISBN: получено ${issue.received}`, isoDate: (issue) => `Неправильная дата: получено ${issue.received}`, isoDateTime: (issue) => `Неправильные дата и время: получено ${issue.received}`, isoTime: (issue) => `Неправильное время: получено ${issue.received}`, isoTimeSecond: (issue) => `Неправильное время с секундами: получено ${issue.received}`, isoTimestamp: (issue) => `Неправильная метка времени: получено ${issue.received}`, isoWeek: (issue) => `Неправильная неделя: получено ${issue.received}`, isrc: (issue) => `Неправильный ISRC: получено ${issue.received}`, jwsCompact: (issue) => `Неправильный компактный JWS: получено ${issue.received}`, length: (issue) => `Неправильная длина: ожидалось ${issue.expected}, получено ${issue.received}`, ltValue: (issue) => `Неправильное значение: ожидалось ${issue.expected}, получено ${issue.received}`, mac: (issue) => `Неправильный MAC: получено ${issue.received}`, mac48: (issue) => `Неправильный 48-битный MAC: получено ${issue.received}`, mac64: (issue) => `Неправильный 64-битный MAC: получено ${issue.received}`, maxBytes: (issue) => `Неправильное количество байтов: ожидалось ${issue.expected}, получено ${issue.received}`, maxEntries: (issue) => `Неправильное количество записей: ожидалось ${issue.expected}, получено ${issue.received}`, maxGraphemes: (issue) => `Неправильное количество графем: ожидалось ${issue.expected}, получено ${issue.received}`, maxLength: (issue) => `Неправильная длина: ожидалось ${issue.expected}, получено ${issue.received}`, maxSize: (issue) => `Неправильный размер: ожидалось ${issue.expected}, получено ${issue.received}`, maxValue: (issue) => `Неправильное значение: ожидалось ${issue.expected}, получено ${issue.received}`, maxWords: (issue) => `Неправильное количество слов: ожидалось ${issue.expected}, получено ${issue.received}`, mimeType: (issue) => `Неправильный MIME тип: ожидалось ${issue.expected}, получено ${issue.received}`, minBytes: (issue) => `Неправильное количество байтов: ожидалось ${issue.expected}, получено ${issue.received}`, minEntries: (issue) => `Неправильное количество записей: ожидалось ${issue.expected}, получено ${issue.received}`, minGraphemes: (issue) => `Неправильное количество графем: ожидалось ${issue.expected}, получено ${issue.received}`, minLength: (issue) => `Неправильная длина: ожидалось ${issue.expected}, получено ${issue.received}`, minSize: (issue) => `Неправильный размер: ожидалось ${issue.expected}, получено ${issue.received}`, minValue: (issue) => `Неправильное значение: ожидалось ${issue.expected}, получено ${issue.received}`, minWords: (issue) => `Неправильное количество слов: ожидалось ${issue.expected}, получено ${issue.received}`, multipleOf: (issue) => `Неправильное кратное число: ожидалось ${issue.expected}, получено ${issue.received}`, nanoid: (issue) => `Неправильный Nano ID: получено ${issue.received}`, nonEmpty: (issue) => `Неправильная длина: ожидалось ${issue.expected}, получено ${issue.received}`, notBytes: (issue) => `Неправильное количество байтов: ожидалось ${issue.expected}, получено ${issue.received}`, notEntries: (issue) => `Неправильное количество записей: ожидалось ${issue.expected}, получено ${issue.received}`, notGraphemes: (issue) => `Неправильное количество графем: ожидалось ${issue.expected}, получено ${issue.received}`, notLength: (issue) => `Неправильная длина: ожидалось ${issue.expected}, получено ${issue.received}`, notSize: (issue) => `Неправильный размер: ожидалось ${issue.expected}, получено ${issue.received}`, notValue: (issue) => `Неправильное значение: ожидалось ${issue.expected}, получено ${issue.received}`, notValues: (issue) => `Неправильное значение: ожидалось ${issue.expected}, получено ${issue.received}`, notWords: (issue) => `Неправильное количество слов: ожидалось ${issue.expected}, получено ${issue.received}`, octal: (issue) => `Неправильный восьмеричное значение: получено ${issue.received}`, parseBoolean: (issue) => `Неправильное логическое значение: получено ${issue.received}`, parseJson: (issue) => `Неправильный JSON: получено ${issue.received}`, partialCheck: (issue) => `Неправильные данные: получено ${issue.received}`, rawCheck: (issue) => `Неправильные данные: получено ${issue.received}`, rawTransform: (issue) => `Неправильные данные: получено ${issue.received}`, regex: (issue) => `Неправильный формат: ожидалось ${issue.expected}, получено ${issue.received}`, rfcEmail: (issue) => `Неправильный email: получено ${issue.received}`, safeInteger: (issue) => `Неправильное безопасное целое число: получено ${issue.received}`, size: (issue) => `Неправильный размер: ожидалось ${issue.expected}, получено ${issue.received}`, slug: (issue) => `Неправильный slug: получено ${issue.received}`, someItem: (issue) => `Неправильный элемент: получено ${issue.received}`, startsWith: (issue) => `Неправильное начало: ожидалось ${issue.expected}, получено ${issue.received}`, stringifyJson: (issue) => `Неправильный JSON: получено ${issue.received}`, toBigint: (issue) => `Неправильный BigInt: получено ${issue.received}`, toDate: (issue) => `Неправильная дата: получено ${issue.received}`, toNumber: (issue) => `Неправильное число: получено ${issue.received}`, toString: (issue) => `Неправильная строка: получено ${issue.received}`, ulid: (issue) => `Неправильный ULID: получено ${issue.received}`, url: (issue) => `Неправильный URL: получено ${issue.received}`, uuid: (issue) => `Неправильный UUID: получено ${issue.received}`, value: (issue) => `Неправильное значение: ожидалось ${issue.expected}, получено ${issue.received}`, values: (issue) => `Неправильное значение: ожидалось ${issue.expected}, получено ${issue.received}`, words: (issue) => `Неправильное количество слов: ожидалось ${issue.expected}, получено ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/sk.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'sk', schema: (issue) => `Neplatný typ: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, specific: { base64: (issue) => `Neplatný Base64: Prijaté ${issue.received}`, bic: (issue) => `Neplatný BIC: Prijaté ${issue.received}`, bytes: (issue) => `Neplatné bajty: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, check: (issue) => `Neplatný vstup: Prijaté ${issue.received}`, checkAsync: (issue) => `Neplatný vstup: Prijaté ${issue.received}`, checkItems: (issue) => `Neplatná položka: Prijaté ${issue.received}`, checkItemsAsync: (issue) => `Neplatná položka: Prijaté ${issue.received}`, creditCard: (issue) => `Neplatná kreditná karta: Prijaté ${issue.received}`, cuid2: (issue) => `Neplatné Cuid2: Prijaté ${issue.received}`, decimal: (issue) => `Neplatné desatinné číslo: Prijaté ${issue.received}`, digits: (issue) => `Neplatné číslice: Prijaté ${issue.received}`, domain: (issue) => `Neplatná doména: Prijaté ${issue.received}`, email: (issue) => `Neplatný email: Prijaté ${issue.received}`, emoji: (issue) => `Neplatné emoji: Prijaté ${issue.received}`, empty: (issue) => `Neplatná dĺžka: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, endsWith: (issue) => `Neplatný koniec: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, entries: (issue) => `Neplatný počet položiek: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, everyItem: (issue) => `Neplatná položka: Prijaté ${issue.received}`, excludes: (issue) => `Neplatný obsah: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, finite: (issue) => `Neplatná konečná hodnota: Prijaté ${issue.received}`, graphemes: (issue) => `Neplatné grafémy: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, gtValue: (issue) => `Neplatná hodnota: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, guard: (issue) => `Neplatný vstup: Prijaté ${issue.received}`, hash: (issue) => `Neplatný hash: Prijaté ${issue.received}`, hexColor: (issue) => `Neplatná hexadecimálna farba: Prijaté ${issue.received}`, hexadecimal: (issue) => `Neplatné hexadecimálne číslo: Prijaté ${issue.received}`, imei: (issue) => `Neplatné IMEI: Prijaté ${issue.received}`, includes: (issue) => `Neplatný obsah: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, integer: (issue) => `Neplatné celé číslo: Prijaté ${issue.received}`, ip: (issue) => `Neplatná IP adresa: Prijaté ${issue.received}`, ipv4: (issue) => `Neplatná IPv4 adresa: Prijaté ${issue.received}`, ipv6: (issue) => `Neplatná IPv6 adresa: Prijaté ${issue.received}`, isbn: (issue) => `Neplatné ISBN: Prijaté ${issue.received}`, isoDate: (issue) => `Neplatný dátum: Prijaté ${issue.received}`, isoDateTime: (issue) => `Neplatný dátum a čas: Prijaté ${issue.received}`, isoTime: (issue) => `Neplatný čas: Prijaté ${issue.received}`, isoTimeSecond: (issue) => `Neplatný čas: Prijaté ${issue.received}`, isoTimestamp: (issue) => `Neplatná časová značka: Prijaté ${issue.received}`, isoWeek: (issue) => `Neplatný týždeň: Prijaté ${issue.received}`, isrc: (issue) => `Neplatné ISRC: Prijaté ${issue.received}`, jwsCompact: (issue) => `Neplatné kompaktné JWS: Prijaté ${issue.received}`, length: (issue) => `Neplatná dĺžka: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, ltValue: (issue) => `Neplatná hodnota: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, mac: (issue) => `Neplatná MAC adresa: Prijaté ${issue.received}`, mac48: (issue) => `Neplatná 48-bitová MAC adresa: Prijaté ${issue.received}`, mac64: (issue) => `Neplatná 64-bitová MAC adresa: Prijaté ${issue.received}`, maxBytes: (issue) => `Prekročený maximálny počet bajtov: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, maxEntries: (issue) => `Prekročený maximálny počet položiek: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, maxGraphemes: (issue) => `Prekročená maximálna dĺžka znakov: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, maxLength: (issue) => `Prekročená maximálna dĺžka: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, maxSize: (issue) => `Prekročená maximálna veľkosť: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, maxValue: (issue) => `Prekročená maximálna hodnota: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, maxWords: (issue) => `Prekročený maximálny počet slov: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, mimeType: (issue) => `Neplatný MIME typ: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, minBytes: (issue) => `Nedostatočný počet bajtov: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, minEntries: (issue) => `Nedostatočný počet položiek: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, minGraphemes: (issue) => `Nedostatočná minimálna dĺžka grafémov: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, minLength: (issue) => `Nedostatočná minimálna dĺžka: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, minSize: (issue) => `Nedostatočná minimálna veľkosť: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, minValue: (issue) => `Nedostatočná minimálna hodnota: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, minWords: (issue) => `Nedostatočný počet slov: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, multipleOf: (issue) => `Neplatný násobok: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, nanoid: (issue) => `Neplatné Nano ID: Prijaté ${issue.received}`, nonEmpty: (issue) => `Nedostatočná dĺžka: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, notBytes: (issue) => `Neplatný počet bajtov: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, notEntries: (issue) => `Neplatný počet položiek: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, notGraphemes: (issue) => `Neplatná dĺžka grafémov: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, notLength: (issue) => `Neplatná dĺžka: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, notSize: (issue) => `Neplatná veľkosť: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, notValue: (issue) => `Neplatná hodnota: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, notValues: (issue) => `Neplatná hodnota: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, notWords: (issue) => `Neplatný počet slov: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, octal: (issue) => `Neplatné osmičkové číslo: Prijaté ${issue.received}`, parseBoolean: (issue) => `Neplatná logická hodnota: Prijaté ${issue.received}`, parseJson: (issue) => `Neplatný JSON: Prijaté ${issue.received}`, partialCheck: (issue) => `Neplatný vstup: Prijaté ${issue.received}`, rawCheck: (issue) => `Neplatný vstup: Prijaté ${issue.received}`, rawTransform: (issue) => `Neplatný vstup: Prijaté ${issue.received}`, regex: (issue) => `Neplatný formát: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, rfcEmail: (issue) => `Neplatný email: Prijaté ${issue.received}`, safeInteger: (issue) => `Neplatné bezpečné celé číslo: Prijaté ${issue.received}`, size: (issue) => `Neplatná veľkosť: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, slug: (issue) => `Neplatný slug: Prijaté ${issue.received}`, someItem: (issue) => `Neplatná položka: Prijaté ${issue.received}`, startsWith: (issue) => `Neplatný začiatok: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, stringifyJson: (issue) => `Neplatný JSON: Prijaté ${issue.received}`, toBigint: (issue) => `Neplatný bigint: Prijaté ${issue.received}`, toDate: (issue) => `Neplatný dátum: Prijaté ${issue.received}`, toNumber: (issue) => `Neplatné číslo: Prijaté ${issue.received}`, toString: (issue) => `Neplatný reťazec: Prijaté ${issue.received}`, ulid: (issue) => `Neplatné ULID: Prijaté ${issue.received}`, url: (issue) => `Neplatná URL: Prijaté ${issue.received}`, uuid: (issue) => `Neplatné UUID: Prijaté ${issue.received}`, value: (issue) => `Neplatná hodnota: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, values: (issue) => `Neplatná hodnota: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, words: (issue) => `Neplatný počet slov: Očakávané ${issue.expected}, ale prijaté ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/sl.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'sl', schema: (issue) => `Neveljaven tip: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, specific: { base64: (issue) => `Neveljaven Base64: Prejet ${issue.received}`, bic: (issue) => `Neveljavna BIC koda: Prejeta ${issue.received}`, bytes: (issue) => `Neveljavni bajti: Pričakovani ${issue.expected}, vendar prejeti ${issue.received}`, check: (issue) => `Neveljaven input: Prejet ${issue.received}`, checkAsync: (issue) => `Neveljaven input: Prejet ${issue.received}`, checkItems: (issue) => `Neveljaven element: Prejet ${issue.received}`, checkItemsAsync: (issue) => `Neveljaven element: Prejet ${issue.received}`, creditCard: (issue) => `Neveljavna kreditna kartica: Prejeta ${issue.received}`, cuid2: (issue) => `Neveljaven Cuid2: Prejet ${issue.received}`, decimal: (issue) => `Neveljaven decimal: Prejet ${issue.received}`, digits: (issue) => `Neveljavna številka: Prejeta ${issue.received}`, domain: (issue) => `Neveljavna domena: Prejet ${issue.received}`, email: (issue) => `Neveljaven e-poštni naslov: Prejet ${issue.received}`, emoji: (issue) => `Neveljaven emoji: Prejet ${issue.received}`, empty: (issue) => `Neveljaven dolžina: Pričakovana ${issue.expected}, vendar prejeta ${issue.received}`, endsWith: (issue) => `Neveljaven konec: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, entries: (issue) => `Neveljavno število vnosov: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, everyItem: (issue) => `Neveljaven element: Prejet ${issue.received}`, excludes: (issue) => `Neveljavna vsebina: Pričakovana ${issue.expected}, vendar prejeta ${issue.received}`, finite: (issue) => `Neveljavno končno število: Prejeto ${issue.received}`, graphemes: (issue) => `Neveljavni grafemi: Pričakovani ${issue.expected}, vendar prejeti ${issue.received}`, gtValue: (issue) => `Neveljavna vrednost: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, guard: (issue) => `Neveljaven vnos: Prejet ${issue.received}`, hash: (issue) => `Neveljaven hash: Prejet ${issue.received}`, hexadecimal: (issue) => `Neveljavna šestnajstiška številka: Prejeta ${issue.received}`, hexColor: (issue) => `Neveljavna šestnajstiška barva: Prejeta ${issue.received}`, imei: (issue) => `Neveljaven IMEI: Prejet ${issue.received}`, includes: (issue) => `Neveljaven content: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, integer: (issue) => `Neveljavno celo število: Prejeto ${issue.received}`, ip: (issue) => `Neveljaven IP: Prejet ${issue.received}`, ipv4: (issue) => `Neveljaven IPv4: Prejet ${issue.received}`, ipv6: (issue) => `Neveljaven IPv6: Prejet ${issue.received}`, isbn: (issue) => `Neveljaven ISBN: Prejet ${issue.received}`, isoDate: (issue) => `Neveljaven datum: Prejet ${issue.received}`, isoDateTime: (issue) => `Neveljaven datum in čas: Prejet ${issue.received}`, isoTime: (issue) => `Neveljaven čas: Prejet ${issue.received}`, isoTimeSecond: (issue) => `Neveljaven iso čas v sekundah: Prejet ${issue.received}`, isoTimestamp: (issue) => `Neveljaven časovni žig iso: Prejet ${issue.received}`, isoWeek: (issue) => `Neveljaven format za teden: Prejet ${issue.received}`, isrc: (issue) => `Neveljaven ISRC: Prejet ${issue.received}`, jwsCompact: (issue) => `Neveljaven kompaktni JWS: Prejet ${issue.received}`, length: (issue) => `Neveljaven dolžina: Pričakovana ${issue.expected}, vendar prejeta ${issue.received}`, ltValue: (issue) => `Neveljavna vrednost: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, mac: (issue) => `Neveljaven MAC: Prejet ${issue.received}`, mac48: (issue) => `Neveljaven 48-bit MAC: Prejet ${issue.received}`, mac64: (issue) => `Neveljaven 64-bit MAC: Prejet ${issue.received}`, maxBytes: (issue) => `Neveljaven bajti: Pričakovani ${issue.expected}, vendar prejeti ${issue.received}`, maxEntries: (issue) => `Neveljavno število vnosov: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, maxGraphemes: (issue) => `Neveljaven grafemi: Pričakovani ${issue.expected}, vendar prejeti ${issue.received}`, maxLength: (issue) => `Neveljaven dolžina: Pričakovana ${issue.expected}, vendar prejeta ${issue.received}`, maxSize: (issue) => `Neveljaven velikost: Pričakovana ${issue.expected}, vendar prejeta ${issue.received}`, maxValue: (issue) => `Neveljaven vrednost: Pričakovana ${issue.expected}, vendar prejeta ${issue.received}`, maxWords: (issue) => `Neveljaven besede: Pričakovani ${issue.expected}, vendar prejeti ${issue.received}`, mimeType: (issue) => `Neveljaven MIME type: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, minBytes: (issue) => `Neveljaven bajt: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, minEntries: (issue) => `Neveljavno število vnosov: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, minGraphemes: (issue) => `Neveljaven grafemi: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, minLength: (issue) => `Neveljaven dolžina: Pričakovana ${issue.expected}, vendar prejeta ${issue.received}`, minSize: (issue) => `Neveljavna velikost: Pričakovana ${issue.expected}, vendar prejeta ${issue.received}`, minValue: (issue) => `Neveljavna vrednost: Pričakovana ${issue.expected}, vendar prejeta ${issue.received}`, minWords: (issue) => `Neveljavna besede: Pričakovana ${issue.expected}, vendar prejeta ${issue.received}`, multipleOf: (issue) => `Neveljaven večkratnik: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, nanoid: (issue) => `Neveljaven Nano ID: Prejet ${issue.received}`, nonEmpty: (issue) => `Neveljaven dolžina: Pričakovana ${issue.expected}, vendar prejeta ${issue.received}`, notBytes: (issue) => `Neveljavni bajti: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, notEntries: (issue) => `Neveljavno število vnosov: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, notGraphemes: (issue) => `Neveljavni grafemi: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, notLength: (issue) => `Neveljavna dolžina: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, notSize: (issue) => `Neveljaven si: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, notValue: (issue) => `Neveljavna vrednost: Pričakovana ${issue.expected}, vendar prejeta ${issue.received}`, notValues: (issue) => `Neveljavna vrednost: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, notWords: (issue) => `Neveljavna besede: Pričakovana ${issue.expected}, vendar prejeta ${issue.received}`, octal: (issue) => `Neveljavno osmiško število: Prejet ${issue.received}`, parseBoolean: (issue) => `Neveljavna logična vrednost: Prejet ${issue.received}`, parseJson: (issue) => `Neveljaven JSON: Prejet ${issue.received}`, partialCheck: (issue) => `Neveljaven input: Prejet ${issue.received}`, rawCheck: (issue) => `Neveljaven vnos: Prejet ${issue.received}`, rawTransform: (issue) => `Neveljaven vnos: Prejet ${issue.received}`, regex: (issue) => `Neveljaven format: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, rfcEmail: (issue) => `Neveljaven e-poštni naslov: Prejet ${issue.received}`, safeInteger: (issue) => `Neveljavno varno celo število: Prejeto ${issue.received}`, size: (issue) => `Neveljaven velikost: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, slug: (issue) => `Neveljaven slug: Prejet ${issue.received}`, someItem: (issue) => `Neveljaven element: Prejet ${issue.received}`, startsWith: (issue) => `Neveljaven začetek: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, stringifyJson: (issue) => `Neveljaven JSON: Prejet ${issue.received}`, toBigint: (issue) => `Neveljaven BigInt: Prejet ${issue.received}`, toDate: (issue) => `Neveljaven datum: Prejet ${issue.received}`, toNumber: (issue) => `Neveljavno število: Prejet ${issue.received}`, toString: (issue) => `Neveljaven niz: Prejet ${issue.received}`, ulid: (issue) => `Neveljaven ULID: Prejet ${issue.received}`, url: (issue) => `Neveljaven URL: Prejet ${issue.received}`, uuid: (issue) => `Neveljaven UUID: Prejet ${issue.received}`, value: (issue) => `Neveljaven value: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, values: (issue) => `Neveljavna vrednost: Pričakovan ${issue.expected}, vendar prejet ${issue.received}`, words: (issue) => `Neveljavne besede: Pričakovane ${issue.expected}, vendar prejete ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/sv.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'sv', schema: (issue) => `Ogiltig typ: Förväntade ${issue.expected}, men fick ${issue.received}`, specific: { base64: (issue) => `Ogiltig Base64: Fick ${issue.received}`, bic: (issue) => `Ogiltigt BIC: Fick ${issue.received}`, bytes: (issue) => `Ogiltiga bytes: Förväntade ${issue.expected}, men fick ${issue.received}`, check: (issue) => `Ogiltig indata: Fick ${issue.received}`, checkAsync: (issue) => `Ogiltig indata: Fick ${issue.received}`, checkItems: (issue) => `Ogiltigt element: Fick ${issue.received}`, checkItemsAsync: (issue) => `Ogiltigt element: Fick ${issue.received}`, creditCard: (issue) => `Ogiltigt kreditkort: Fick ${issue.received}`, cuid2: (issue) => `Ogiltigt Cuid2: Fick ${issue.received}`, decimal: (issue) => `Ogiltig decimal: Fick ${issue.received}`, digits: (issue) => `Ogiltigt nummer: Fick ${issue.received}`, domain: (issue) => `Ogiltig domän: Fick ${issue.received}`, email: (issue) => `Ogiltig email: Fick ${issue.received}`, emoji: (issue) => `Ogiltig emoji: Fick ${issue.received}`, empty: (issue) => `Ogiltig längd: Förväntade ${issue.expected}, men fick ${issue.received}`, endsWith: (issue) => `Ogiltigt slut: Förväntade ${issue.expected}, men fick ${issue.received}`, entries: (issue) => `Ogiltigt antal poster: Förväntade ${issue.expected}, men fick ${issue.received}`, everyItem: (issue) => `Ogiltigt element: Fick ${issue.received}`, excludes: (issue) => `Ogiltigt innehåll: Förväntade ${issue.expected}, men fick ${issue.received}`, finite: (issue) => `Ogiltig ändlig: Fick ${issue.received}`, graphemes: (issue) => `Ogiltigt grafem: Förväntade ${issue.expected}, men fick ${issue.received}`, gtValue: (issue) => `Ogiltigt värde: Förväntade ${issue.expected}, men fick ${issue.received}`, guard: (issue) => `Ogiltig indata: Fick ${issue.received}`, hash: (issue) => `Ogiltig hash: Fick ${issue.received}`, hexadecimal: (issue) => `Ogiltig hexadecimal: Fick ${issue.received}`, hexColor: (issue) => `Ogiltig hexadecimal färg: Fick ${issue.received}`, imei: (issue) => `Ogiltigt IMEI: Fick ${issue.received}`, includes: (issue) => `Ogiltigt innehåll: Förväntade ${issue.expected}, men fick ${issue.received}`, integer: (issue) => `Ogiltigt heltal: Fick ${issue.received}`, ip: (issue) => `Ogiltig IP: Fick ${issue.received}`, ipv4: (issue) => `Ogiltig IPv4: Fick ${issue.received}`, ipv6: (issue) => `Ogiltig IPv6: Fick ${issue.received}`, isbn: (issue) => `Ogiltig ISBN: Fick ${issue.received}`, isoDate: (issue) => `Ogiltigt datum: Fick ${issue.received}`, isoDateTime: (issue) => `Ogiltig datum-tid: Fick ${issue.received}`, isoTime: (issue) => `Ogiltig tid: Fick ${issue.received}`, isoTimeSecond: (issue) => `Ogiltig sekund: Fick ${issue.received}`, isoTimestamp: (issue) => `Ogiltig tidsstämpel: Fick ${issue.received}`, isoWeek: (issue) => `Ogiltig vecka: Fick ${issue.received}`, isrc: (issue) => `Ogiltig ISRC: Fick ${issue.received}`, jwsCompact: (issue) => `Ogiltig kompakt JWS: Fick ${issue.received}`, length: (issue) => `Ogiltig längd: Förväntade ${issue.expected}, men fick ${issue.received}`, ltValue: (issue) => `Ogiltigt värde: Förväntade ${issue.expected}, men fick ${issue.received}`, mac: (issue) => `Ogiltig MAC: Fick ${issue.received}`, mac48: (issue) => `Ogiltig 48-bit MAC: Fick ${issue.received}`, mac64: (issue) => `Ogiltig 64-bit MAC: Fick ${issue.received}`, maxBytes: (issue) => `Ogiltiga bytes: Förväntade ${issue.expected}, men fick ${issue.received}`, maxEntries: (issue) => `Ogiltigt antal poster: Förväntade ${issue.expected}, men fick ${issue.received}`, maxGraphemes: (issue) => `Ogiltigt grafem: Förväntade ${issue.expected}, men fick ${issue.received}`, maxLength: (issue) => `Ogiltig längd: Förväntade ${issue.expected}, men fick ${issue.received}`, maxSize: (issue) => `Ogiltig storlek: Förväntade ${issue.expected}, men fick ${issue.received}`, maxValue: (issue) => `Ogiltigt värde: Förväntade ${issue.expected}, men fick ${issue.received}`, maxWords: (issue) => `Ogiltigt ord: Förväntade ${issue.expected}, men fick ${issue.received}`, mimeType: (issue) => `Ogiltig MIME typ: Förväntade ${issue.expected}, men fick ${issue.received}`, minBytes: (issue) => `Ogiltiga bytes: Förväntade ${issue.expected}, men fick ${issue.received}`, minEntries: (issue) => `Ogiltigt antal poster: Förväntade ${issue.expected}, men fick ${issue.received}`, minGraphemes: (issue) => `Ogiltigt grafem: Förväntade ${issue.expected}, men fick ${issue.received}`, minLength: (issue) => `Ogiltig längd: Förväntade ${issue.expected}, men fick ${issue.received}`, minSize: (issue) => `Ogiltig storlek: Förväntade ${issue.expected}, men fick ${issue.received}`, minValue: (issue) => `Ogiltigt värde: Förväntade ${issue.expected}, men fick ${issue.received}`, minWords: (issue) => `Ogiltigt ord: Förväntade ${issue.expected}, men fick ${issue.received}`, multipleOf: (issue) => `Ogiltig multipel: Förväntade ${issue.expected}, men fick ${issue.received}`, nanoid: (issue) => `Ogiltigt Nano ID: Fick ${issue.received}`, nonEmpty: (issue) => `Ogiltig längd: Förväntade ${issue.expected}, men fick ${issue.received}`, notBytes: (issue) => `Ogiltiga bytes: Förväntade ${issue.expected}, men fick ${issue.received}`, notEntries: (issue) => `Ogiltigt antal poster: Förväntade ${issue.expected}, men fick ${issue.received}`, notGraphemes: (issue) => `Ogiltigt grafem: Förväntade ${issue.expected}, men fick ${issue.received}`, notLength: (issue) => `Ogiltig längd: Förväntade ${issue.expected}, men fick ${issue.received}`, notSize: (issue) => `Ogiltig storlek: Förväntade ${issue.expected}, men fick ${issue.received}`, notValue: (issue) => `Ogiltigt värde: Förväntade ${issue.expected}, men fick ${issue.received}`, notValues: (issue) => `Ogiltigt värde: Förväntade ${issue.expected}, men fick ${issue.received}`, notWords: (issue) => `Ogiltigt ord: Förväntade ${issue.expected}, men fick ${issue.received}`, octal: (issue) => `Ogiltig oktal: Fick ${issue.received}`, parseBoolean: (issue) => `Ogiltigt booleskt värde: Fick ${issue.received}`, parseJson: (issue) => `Ogiltig JSON: Fick ${issue.received}`, partialCheck: (issue) => `Ogiltig indata: Fick ${issue.received}`, rawCheck: (issue) => `Ogiltig indata: Fick ${issue.received}`, rawTransform: (issue) => `Ogiltig indata: Fick ${issue.received}`, regex: (issue) => `Ogiltigt format: Förväntade ${issue.expected}, men fick ${issue.received}`, rfcEmail: (issue) => `Ogiltig e-post: Fick ${issue.received}`, safeInteger: (issue) => `Ogiltigt säkert heltal: Fick ${issue.received}`, size: (issue) => `Ogiltig storlek: Förväntade ${issue.expected}, men fick ${issue.received}`, slug: (issue) => `Ogiltig slug: Fick ${issue.received}`, someItem: (issue) => `Ogiltigt element: Fick ${issue.received}`, startsWith: (issue) => `Ogiltig start: Förväntade ${issue.expected}, men fick ${issue.received}`, stringifyJson: (issue) => `Ogiltig JSON: Fick ${issue.received}`, toBigint: (issue) => `Ogiltig BigInt: Fick ${issue.received}`, toDate: (issue) => `Ogiltigt datum: Fick ${issue.received}`, toNumber: (issue) => `Ogiltigt nummer: Fick ${issue.received}`, toString: (issue) => `Ogiltig sträng: Fick ${issue.received}`, ulid: (issue) => `Ogiltigt ULID: Fick ${issue.received}`, url: (issue) => `Ogiltig URL: Fick ${issue.received}`, uuid: (issue) => `Ogiltigt UUID: Fick ${issue.received}`, value: (issue) => `Ogiltigt värde: Förväntade ${issue.expected}, men fick ${issue.received}`, values: (issue) => `Ogiltigt värde: Förväntade ${issue.expected}, men fick ${issue.received}`, words: (issue) => `Ogiltigt ord: Förväntade ${issue.expected}, men fick ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/tr.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'tr', schema: (issue) => `Geçersiz tip: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, specific: { base64: (issue) => `Geçersiz Base64: ${issue.received} alındı`, bic: (issue) => `Geçersiz BIC: ${issue.received} alındı`, bytes: (issue) => `Geçersiz bayt: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, check: (issue) => `Geçersiz girdi: ${issue.received} alındı`, checkAsync: (issue) => `Geçersiz girdi: ${issue.received} alındı`, checkItems: (issue) => `Geçersiz öğe: ${issue.received} alındı`, checkItemsAsync: (issue) => `Geçersiz öğe: ${issue.received} alındı`, creditCard: (issue) => `Geçersiz kredi kartı: ${issue.received} alındı`, cuid2: (issue) => `Geçersiz Cuid2: ${issue.received} alındı`, decimal: (issue) => `Geçersiz kesirli sayı: ${issue.received} alındı`, digits: (issue) => `Geçersiz rakam: ${issue.received} alındı`, domain: (issue) => `Geçersiz alan adı: ${issue.received} alındı`, email: (issue) => `Geçersiz e-posta: ${issue.received} alındı`, emoji: (issue) => `Geçersiz emoji: ${issue.received} alındı`, empty: (issue) => `Geçersiz uzunluk: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, endsWith: (issue) => `Geçersiz bitiş: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, entries: (issue) => `Geçersiz giriş sayısı: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, everyItem: (issue) => `Geçersiz öğe: ${issue.received} alındı`, excludes: (issue) => `Geçersiz içerik: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, finite: (issue) => `Geçersiz sonlu sayı: ${issue.received} alındı`, graphemes: (issue) => `Geçersiz grafem: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, gtValue: (issue) => `Geçersiz değer: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, guard: (issue) => `Geçersiz girdi: ${issue.received} alındı`, hash: (issue) => `Geçersiz hash: ${issue.received} alındı`, hexadecimal: (issue) => `Geçersiz onaltı tabanlı sayı: ${issue.received} alındı`, hexColor: (issue) => `Geçersiz hex renk kodu: ${issue.received} alındı`, imei: (issue) => `Geçersiz IMEI: ${issue.received} alındı`, includes: (issue) => `Geçersiz içerik: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, integer: (issue) => `Geçersiz tamsayı: ${issue.received} alındı`, ip: (issue) => `Geçersiz IP: ${issue.received} alındı`, ipv4: (issue) => `Geçersiz IPv4: ${issue.received} alındı`, ipv6: (issue) => `Geçersiz IPv6: ${issue.received} alındı`, isbn: (issue) => `Geçersiz ISBN: ${issue.received} alındı`, isoDate: (issue) => `Geçersiz tarih: ${issue.received} alındı`, isoDateTime: (issue) => `Geçersiz tarih-saat: ${issue.received} alındı`, isoTime: (issue) => `Geçersiz saat: ${issue.received} alındı`, isoTimeSecond: (issue) => `Geçersiz saat saniye: ${issue.received} alındı`, isoTimestamp: (issue) => `Geçersiz zaman bilgisi: ${issue.received} alındı`, isoWeek: (issue) => `Geçersiz hafta: ${issue.received} alındı`, isrc: (issue) => `Geçersiz ISRC: ${issue.received} alındı`, jwsCompact: (issue) => `Geçersiz kompakt JWS: ${issue.received} alındı`, length: (issue) => `Geçersiz uzunluk: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, ltValue: (issue) => `Geçersiz değer: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, mac: (issue) => `Geçersiz MAC: ${issue.received} alındı`, mac48: (issue) => `Geçersiz 48-bit MAC: ${issue.received} alındı`, mac64: (issue) => `Geçersiz 64-bit MAC: ${issue.received} alındı`, maxBytes: (issue) => `Geçersiz bayt: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, maxEntries: (issue) => `Geçersiz giriş sayısı: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, maxGraphemes: (issue) => `Geçersiz grafem: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, maxLength: (issue) => `Geçersiz uzunluk: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, maxSize: (issue) => `Geçersiz boyut: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, maxValue: (issue) => `Geçersiz değer: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, maxWords: (issue) => `Geçersiz kelime: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, mimeType: (issue) => `Geçersiz MIME tipi: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, minBytes: (issue) => `Geçersiz bayt: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, minEntries: (issue) => `Geçersiz giriş sayısı: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, minGraphemes: (issue) => `Geçersiz grafem: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, minLength: (issue) => `Geçersiz uzunluk: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, minSize: (issue) => `Geçersiz boyut: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, minValue: (issue) => `Geçersiz değer: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, minWords: (issue) => `Geçersiz kelime: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, multipleOf: (issue) => `Geçersiz katsayı: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, nanoid: (issue) => `Geçersiz Nano ID: ${issue.received} alındı`, nonEmpty: (issue) => `Geçersiz uzunluk: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, notBytes: (issue) => `Geçersiz bayt: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, notEntries: (issue) => `Geçersiz giriş sayısı: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, notGraphemes: (issue) => `Geçersiz grafem: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, notLength: (issue) => `Geçersiz uzunluk: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, notSize: (issue) => `Geçersiz boyut: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, notValue: (issue) => `Geçersiz değer: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, notValues: (issue) => `Geçersiz değer: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, notWords: (issue) => `Geçersiz kelime: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, octal: (issue) => `Geçersiz sekiz tabanlı sayı: ${issue.received} alındı`, parseBoolean: (issue) => `Geçersiz boole değeri: ${issue.received} alındı`, parseJson: (issue) => `Geçersiz JSON: ${issue.received} alındı`, partialCheck: (issue) => `Geçersiz girdi: ${issue.received} alındı`, rawCheck: (issue) => `Geçersiz girdi: ${issue.received} alındı`, rawTransform: (issue) => `Geçersiz girdi: ${issue.received} alındı`, regex: (issue) => `Geçersiz format: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, rfcEmail: (issue) => `Geçersiz e-posta: ${issue.received} alındı`, safeInteger: (issue) => `Geçersiz güvenli tamsayı: ${issue.received} alındı`, size: (issue) => `Geçersiz boyut: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, slug: (issue) => `Geçersiz slug: ${issue.received} alındı`, someItem: (issue) => `Geçersiz öğe: ${issue.received} alındı`, startsWith: (issue) => `Geçersiz başlangıç: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, stringifyJson: (issue) => `Geçersiz JSON: ${issue.received} alındı`, toBigint: (issue) => `Geçersiz BigInt: ${issue.received} alındı`, toDate: (issue) => `Geçersiz tarih: ${issue.received} alındı`, toNumber: (issue) => `Geçersiz sayı: ${issue.received} alındı`, toString: (issue) => `Geçersiz dize: ${issue.received} alındı`, ulid: (issue) => `Geçersiz ULID: ${issue.received} alındı`, url: (issue) => `Geçersiz URL: ${issue.received} alındı`, uuid: (issue) => `Geçersiz UUID: ${issue.received} alındı`, value: (issue) => `Geçersiz değer: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, values: (issue) => `Geçersiz değer: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, words: (issue) => `Geçersiz kelime: ${issue.expected} bekleniyordu ancak ${issue.received} alındı`, }, }; export default language; ================================================ FILE: packages/i18n/src/types.ts ================================================ import type { BaseIssue, ErrorMessage } from 'valibot'; export type Language = { code: | 'ar' | 'az' | 'ca' | 'cs' | 'de' | 'el' | 'en' | 'es' | 'fa' | 'fi' | 'fr' | 'hu' | 'id' | 'it' | 'ja' | 'ko' | 'kr' | 'mn' | 'nb' | 'nl' | 'pl' | 'pt' | 'ro' | 'ru' | 'sk' | 'sl' | 'sv' | 'tr' | 'uk' | 'vi' | 'zh-CN' | 'zh-TW'; schema: ErrorMessage>; specific: { base64: ErrorMessage>; bic: ErrorMessage>; bytes: ErrorMessage>; check: ErrorMessage>; checkAsync: ErrorMessage>; checkItems: ErrorMessage>; checkItemsAsync: ErrorMessage>; creditCard: ErrorMessage>; cuid2: ErrorMessage>; decimal: ErrorMessage>; digits: ErrorMessage>; domain: ErrorMessage>; email: ErrorMessage>; emoji: ErrorMessage>; empty: ErrorMessage>; endsWith: ErrorMessage>; entries: ErrorMessage>; everyItem: ErrorMessage>; excludes: ErrorMessage>; finite: ErrorMessage>; graphemes: ErrorMessage>; gtValue: ErrorMessage>; guard: ErrorMessage>; hash: ErrorMessage>; hexadecimal: ErrorMessage>; hexColor: ErrorMessage>; imei: ErrorMessage>; includes: ErrorMessage>; integer: ErrorMessage>; ip: ErrorMessage>; ipv4: ErrorMessage>; ipv6: ErrorMessage>; isbn: ErrorMessage>; isoDate: ErrorMessage>; isoDateTime: ErrorMessage>; isoTime: ErrorMessage>; isoTimeSecond: ErrorMessage>; isoTimestamp: ErrorMessage>; isoWeek: ErrorMessage>; isrc: ErrorMessage>; jwsCompact: ErrorMessage>; length: ErrorMessage>; ltValue: ErrorMessage>; mac: ErrorMessage>; mac48: ErrorMessage>; mac64: ErrorMessage>; maxBytes: ErrorMessage>; maxEntries: ErrorMessage>; maxGraphemes: ErrorMessage>; maxLength: ErrorMessage>; maxSize: ErrorMessage>; maxValue: ErrorMessage>; maxWords: ErrorMessage>; mimeType: ErrorMessage>; minBytes: ErrorMessage>; minEntries: ErrorMessage>; minGraphemes: ErrorMessage>; minLength: ErrorMessage>; minSize: ErrorMessage>; minValue: ErrorMessage>; minWords: ErrorMessage>; multipleOf: ErrorMessage>; nanoid: ErrorMessage>; nonEmpty: ErrorMessage>; notBytes: ErrorMessage>; notEntries: ErrorMessage>; notGraphemes: ErrorMessage>; notLength: ErrorMessage>; notSize: ErrorMessage>; notValue: ErrorMessage>; notValues: ErrorMessage>; notWords: ErrorMessage>; octal: ErrorMessage>; parseBoolean: ErrorMessage>; parseJson: ErrorMessage>; partialCheck: ErrorMessage>; rawCheck: ErrorMessage>; rawTransform: ErrorMessage>; regex: ErrorMessage>; rfcEmail: ErrorMessage>; safeInteger: ErrorMessage>; size: ErrorMessage>; slug: ErrorMessage>; someItem: ErrorMessage>; startsWith: ErrorMessage>; stringifyJson: ErrorMessage>; toBigint: ErrorMessage>; toDate: ErrorMessage>; toNumber: ErrorMessage>; toString: ErrorMessage>; ulid: ErrorMessage>; url: ErrorMessage>; uuid: ErrorMessage>; value: ErrorMessage>; values: ErrorMessage>; words: ErrorMessage>; }; }; ================================================ FILE: packages/i18n/src/uk.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'uk', schema: (issue) => `Неправильний тип: очікувався ${issue.expected}, але отримано ${issue.received}`, specific: { base64: (issue) => `Неправильний Base64: отримано ${issue.received}`, bic: (issue) => `Неправильний BIC: отримано ${issue.received}`, bytes: (issue) => `Неправильна кількість байт: очікувалося ${issue.expected}, але отримано ${issue.received}`, check: (issue) => `Неправильні дані: отримано ${issue.received}`, checkAsync: (issue) => `Неправильні дані: отримано ${issue.received}`, checkItems: (issue) => `Неправильний елемент: отримано ${issue.received}`, checkItemsAsync: (issue) => `Неправильний елемент: отримано ${issue.received}`, creditCard: (issue) => `Неправильний номер кредитної картки: отримано ${issue.received}`, cuid2: (issue) => `Неправильний Cuid2: отримано ${issue.received}`, decimal: (issue) => `Неправильне десяткове число: отримано ${issue.received}`, digits: (issue) => `Неправильне число: отримано ${issue.received}`, domain: (issue) => `Неправильний домен: отримано ${issue.received}`, email: (issue) => `Неправильний email: отримано ${issue.received}`, emoji: (issue) => `Неправильні емодзі: отримано ${issue.received}`, empty: (issue) => `Неправильна довжина: очікувалося ${issue.expected}, але отримано ${issue.received}`, endsWith: (issue) => `Неправильний кінець: очікувалося ${issue.expected}, але отримано ${issue.received}`, entries: (issue) => `Неправильна кількість записів: очікувалося ${issue.expected}, але отримано ${issue.received}`, everyItem: (issue) => `Неправильний елемент: отримано ${issue.received}`, excludes: (issue) => `Неправильний вміст: очікувалося ${issue.expected}, але отримано ${issue.received}`, finite: (issue) => `Неправильне скінченне число: отримано ${issue.received}`, graphemes: (issue) => `Неправильна кількість графем: очікувалося ${issue.expected}, але отримано ${issue.received}`, gtValue: (issue) => `Неправильне значення: очікувалося ${issue.expected}, але отримано ${issue.received}`, guard: (issue) => `Неправильні дані: отримано ${issue.received}`, hash: (issue) => `Неправильний хеш: отримано ${issue.received}`, hexadecimal: (issue) => `Неправильне шістнадцяткове значення: отримано ${issue.received}`, hexColor: (issue) => `Неправильний шістнадцятковий колір: отримано ${issue.received}`, imei: (issue) => `Неправильний IMEI: отримано ${issue.received}`, includes: (issue) => `Неправильний вміст: очікувалося ${issue.expected}, але отримано ${issue.received}`, integer: (issue) => `Неправильне ціле число: отримано ${issue.received}`, ip: (issue) => `Неправильний IP: отримано ${issue.received}`, ipv4: (issue) => `Неправильний IPv4: отримано ${issue.received}`, ipv6: (issue) => `Неправильний IPv6: отримано ${issue.received}`, isbn: (issue) => `Неправильний ISBN: отримано ${issue.received}`, isoDate: (issue) => `Неправильна дата: отримано ${issue.received}`, isoDateTime: (issue) => `Неправильна дата і час: отримано ${issue.received}`, isoTime: (issue) => `Неправильний час: отримано ${issue.received}`, isoTimeSecond: (issue) => `Неправильний час з секундами: отримано ${issue.received}`, isoTimestamp: (issue) => `Неправильна мітка часу: отримано ${issue.received}`, isoWeek: (issue) => `Неправильний тиждень: отримано ${issue.received}`, isrc: (issue) => `Неправильний ISRC: отримано ${issue.received}`, jwsCompact: (issue) => `Неправильний компактний JWS: отримано ${issue.received}`, length: (issue) => `Неправильна довжина: очікувалося ${issue.expected}, але отримано ${issue.received}`, ltValue: (issue) => `Неправильне значення: очікувалося ${issue.expected}, але отримано ${issue.received}`, mac: (issue) => `Неправильний MAC: отримано ${issue.received}`, mac48: (issue) => `Неправильний 48-бітний MAC: отримано ${issue.received}`, mac64: (issue) => `Неправильний 64-бітний MAC: отримано ${issue.received}`, maxBytes: (issue) => `Неправильна кількість байт: очікувалося ${issue.expected}, але отримано ${issue.received}`, maxEntries: (issue) => `Неправильна кількість записів: очікувалося ${issue.expected}, але отримано ${issue.received}`, maxGraphemes: (issue) => `Неправильна кількість графем: очікувалося ${issue.expected}, але отримано ${issue.received}`, maxLength: (issue) => `Неправильна довжина: очікувалося ${issue.expected}, але отримано ${issue.received}`, maxSize: (issue) => `Неправильний розмір: очікувалося ${issue.expected}, але отримано ${issue.received}`, maxValue: (issue) => `Неправильне значення: очікувалося ${issue.expected}, але отримано ${issue.received}`, maxWords: (issue) => `Неправильна кількість слів: очікувалося ${issue.expected}, але отримано ${issue.received}`, mimeType: (issue) => `Неправильний MIME тип: очікувався ${issue.expected}, але отримано ${issue.received}`, minBytes: (issue) => `Неправильна кількість байт: очікувалося ${issue.expected}, але отримано ${issue.received}`, minEntries: (issue) => `Неправильна кількість записів: очікувалося ${issue.expected}, але отримано ${issue.received}`, minGraphemes: (issue) => `Неправильна кількість графем: очікувалося ${issue.expected}, але отримано ${issue.received}`, minLength: (issue) => `Неправильна довжина: очікувалося ${issue.expected}, але отримано ${issue.received}`, minSize: (issue) => `Неправильний розмір: очікувалося ${issue.expected}, але отримано ${issue.received}`, minValue: (issue) => `Неправильне значення: очікувалося ${issue.expected}, але отримано ${issue.received}`, minWords: (issue) => `Неправильна кількість слів: очікувалося ${issue.expected}, але отримано ${issue.received}`, multipleOf: (issue) => `Неправильне кратне число: очікувалося ${issue.expected}, але отримано ${issue.received}`, nanoid: (issue) => `Неправильний Nano ID: отримано ${issue.received}`, nonEmpty: (issue) => `Неправильна довжина: очікувалося ${issue.expected}, але отримано ${issue.received}`, notBytes: (issue) => `Неправильна кількість байт: очікувалося ${issue.expected}, але отримано ${issue.received}`, notEntries: (issue) => `Неправильна кількість записів: очікувалося ${issue.expected}, але отримано ${issue.received}`, notGraphemes: (issue) => `Неправильна кількість графем: очікувалося ${issue.expected}, але отримано ${issue.received}`, notLength: (issue) => `Неправильна довжина: очікувалося ${issue.expected}, але отримано ${issue.received}`, notSize: (issue) => `Неправильний розмір: очікувалося ${issue.expected}, але отримано ${issue.received}`, notValue: (issue) => `Неправильне значення: очікувалося ${issue.expected}, але отримано ${issue.received}`, notValues: (issue) => `Неправильне значення: очікувалося ${issue.expected}, але отримано ${issue.received}`, notWords: (issue) => `Неправильна кількість слів: очікувалося ${issue.expected}, але отримано ${issue.received}`, octal: (issue) => `Неправильний вісімковий код: отримано ${issue.received}`, parseBoolean: (issue) => `Неправильне булеве значення: отримано ${issue.received}`, parseJson: (issue) => `Неправильний JSON: отримано ${issue.received}`, partialCheck: (issue) => `Неправильні дані: отримано ${issue.received}`, rawCheck: (issue) => `Неправильні дані: отримано ${issue.received}`, rawTransform: (issue) => `Неправильні дані: отримано ${issue.received}`, regex: (issue) => `Неправильний формат: очікувалося ${issue.expected}, але отримано ${issue.received}`, rfcEmail: (issue) => `Неправильний email: отримано ${issue.received}`, safeInteger: (issue) => `Неправильне безпечне ціле число: отримано ${issue.received}`, size: (issue) => `Неправильний розмір: очікувалося ${issue.expected}, але отримано ${issue.received}`, slug: (issue) => `Неправильний slug: отримано ${issue.received}`, someItem: (issue) => `Неправильний елемент: отримано ${issue.received}`, startsWith: (issue) => `Неправильний початок: очікувалося ${issue.expected}, але отримано ${issue.received}`, stringifyJson: (issue) => `Неправильний JSON: отримано ${issue.received}`, toBigint: (issue) => `Неправильний BigInt: отримано ${issue.received}`, toDate: (issue) => `Неправильна дата: отримано ${issue.received}`, toNumber: (issue) => `Неправильне число: отримано ${issue.received}`, toString: (issue) => `Неправильний рядок: отримано ${issue.received}`, ulid: (issue) => `Неправильний ULID: отримано ${issue.received}`, url: (issue) => `Неправильний URL: отримано ${issue.received}`, uuid: (issue) => `Неправильний UUID: отримано ${issue.received}`, value: (issue) => `Неправильне значення: очікувалося ${issue.expected}, але отримано ${issue.received}`, values: (issue) => `Неправильне значення: очікувалося ${issue.expected}, але отримано ${issue.received}`, words: (issue) => `Неправильна кількість слів: очікувалося ${issue.expected}, але отримано ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/vi.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'vi', schema: (issue) => `Loại không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, specific: { base64: (issue) => `Base64 không hợp lệ: Nhận được ${issue.received}`, bic: (issue) => `BIC không hợp lệ: Nhận được ${issue.received}`, bytes: (issue) => `Bytes không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, check: (issue) => `Đầu vào không hợp lệ: Nhận ${issue.received}`, checkAsync: (issue) => `Đầu vào không hợp lệ: Nhận ${issue.received}`, checkItems: (issue) => `Mục không hợp lệ: Nhận được ${issue.received}`, checkItemsAsync: (issue) => `Mục không hợp lệ: Nhận được ${issue.received}`, creditCard: (issue) => `Thẻ tín dụng không hợp lệ: Nhận được ${issue.received}`, cuid2: (issue) => `Cuid2 không hợp lệ: Nhận được ${issue.received}`, decimal: (issue) => `Số thập phân không hợp lệ: Nhận được ${issue.received}`, digits: (issue) => `Các chữ số không hợp lệ: Nhận được ${issue.received}`, domain: (issue) => `Tên miền không hợp lệ: Nhận được ${issue.received}`, email: (issue) => `Email không hợp lệ: Nhận được ${issue.received}`, emoji: (issue) => `Emoji không hợp lệ: Nhận được ${issue.received}`, empty: (issue) => `Độ dài không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, endsWith: (issue) => `Các ký tự thúc không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, entries: (issue) => `Số mục không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, everyItem: (issue) => `Mục không hợp lệ: Nhận được ${issue.received}`, excludes: (issue) => `Nội dung không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, finite: (issue) => `Số không hợp lệ: Nhận được ${issue.received}`, graphemes: (issue) => `Các chữ cái không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, gtValue: (issue) => `Giá trị không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, guard: (issue) => `Đầu vào không hợp lệ: Nhận được ${issue.received}`, hash: (issue) => `Mã hash không hợp lệ: Nhận được ${issue.received}`, hexadecimal: (issue) => `Số thập lục phân không hợp lệ: Nhận được ${issue.received}`, hexColor: (issue) => `Mã màu hex không hợp lệ: Nhận được ${issue.received}`, imei: (issue) => `IMEI không hợp lệ: Nhận được ${issue.received}`, includes: (issue) => `Nội dung không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, integer: (issue) => `Số nguyên không hợp lệ: Nhận được ${issue.received}`, ip: (issue) => `IP không hợp lệ: Nhận được ${issue.received}`, ipv4: (issue) => `IPv4 không hợp lệ: Nhận được ${issue.received}`, ipv6: (issue) => `IPv6 không hợp lệ: Nhận được ${issue.received}`, isbn: (issue) => `ISBN không hợp lệ: Nhận được ${issue.received}`, isoDate: (issue) => `Ngày không hợp lệ: Nhận được ${issue.received}`, isoDateTime: (issue) => `Ngày giờ không hợp lệ: Nhận được ${issue.received}`, isoTime: (issue) => `Giờ không hợp lệ: Nhận được ${issue.received}`, isoTimeSecond: (issue) => `Giây không hợp lệ: Nhận được ${issue.received}`, isoTimestamp: (issue) => `Dấu thời gian không hợp lệ: Nhận được ${issue.received}`, isoWeek: (issue) => `Tuần không hợp lệ: Nhận được ${issue.received}`, isrc: (issue) => `ISRC không hợp lệ: Nhận được ${issue.received}`, jwsCompact: (issue) => `JWS dạng rút gọn không hợp lệ: Nhận được ${issue.received}`, length: (issue) => `Độ dài không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, ltValue: (issue) => `Giá trị không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, mac: (issue) => `MAC không hợp lệ: Nhận được ${issue.received}`, mac48: (issue) => `MAC 48-bit không hợp lệ: Nhận được ${issue.received}`, mac64: (issue) => `MAC 64-bit không hợp lệ: Nhận được ${issue.received}`, maxBytes: (issue) => `Bytes không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, maxEntries: (issue) => `Số mục không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, maxGraphemes: (issue) => `Các chữ cái không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, maxLength: (issue) => `Độ dài không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, maxSize: (issue) => `Kích cỡ không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, maxValue: (issue) => `Giá trị không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, maxWords: (issue) => `Từ không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, mimeType: (issue) => `Loại MIME không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, minBytes: (issue) => `Bytes không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, minEntries: (issue) => `Số mục không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, minGraphemes: (issue) => `Các chữ cái không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, minLength: (issue) => `Độ dài không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, minSize: (issue) => `Kích cỡ không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, minValue: (issue) => `Giá trị không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, minWords: (issue) => `Từ không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, multipleOf: (issue) => `Lựa chọn không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, nanoid: (issue) => `Nano ID không hợp lệ: Nhận được ${issue.received}`, nonEmpty: (issue) => `Độ dài không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, notBytes: (issue) => `Bytes không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, notEntries: (issue) => `Số mục không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, notGraphemes: (issue) => `Các chữ cái không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, notLength: (issue) => `Độ dài không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, notSize: (issue) => `Kích cỡ không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, notValue: (issue) => `Giá trị không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, notValues: (issue) => `Giá trị không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, notWords: (issue) => `Từ không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, octal: (issue) => `Hệ bát phân không hợp lệ: Nhận được ${issue.received}`, parseBoolean: (issue) => `Giá trị boolean không hợp lệ: Nhận được ${issue.received}`, parseJson: (issue) => `JSON không hợp lệ: Nhận được ${issue.received}`, partialCheck: (issue) => `Đầu vào không hợp lệ: Nhận được ${issue.received}`, rawCheck: (issue) => `Đầu vào không hợp lệ: Nhận được ${issue.received}`, rawTransform: (issue) => `Đầu vào không hợp lệ: Nhận được ${issue.received}`, regex: (issue) => `Định dạng không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, rfcEmail: (issue) => `Email không hợp lệ: Nhận được ${issue.received}`, safeInteger: (issue) => `Số nguyên an toàn không hợp lệ: Nhận được ${issue.received}`, size: (issue) => `Kích cỡ không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, slug: (issue) => `Slug không hợp lệ: Nhận được ${issue.received}`, someItem: (issue) => `Mục không hợp lệ: Nhận được ${issue.received}`, startsWith: (issue) => `Các ký tự bắt đầu không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, stringifyJson: (issue) => `JSON không hợp lệ: Nhận được ${issue.received}`, toBigint: (issue) => `BigInt không hợp lệ: Nhận được ${issue.received}`, toDate: (issue) => `Ngày không hợp lệ: Nhận được ${issue.received}`, toNumber: (issue) => `Số không hợp lệ: Nhận được ${issue.received}`, toString: (issue) => `Chuỗi không hợp lệ: Nhận được ${issue.received}`, ulid: (issue) => `ULID không hợp lệ: Nhận được ${issue.received}`, url: (issue) => `URL không hợp lệ: Nhận được ${issue.received}`, uuid: (issue) => `UUID không hợp lệ: Nhận được ${issue.received}`, value: (issue) => `Giá trị không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, values: (issue) => `Giá trị không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, words: (issue) => `Từ không hợp lệ: Mong muốn ${issue.expected} nhưng nhận được ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/zh-CN.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'zh-CN', schema: (issue) => `无效的类型:预期为 ${issue.expected},而输入为 ${issue.received}`, specific: { base64: (issue) => `无效的 Base64:输入为 ${issue.received}`, bic: (issue) => `无效的商业标识符:输入为 ${issue.received}`, bytes: (issue) => `无效的字节长度:预期为 ${issue.expected},而输入为 ${issue.received}`, check: (issue) => `无效的输入:输入为 ${issue.received}`, checkAsync: (issue) => `无效的输入:输入为 ${issue.received}`, checkItems: (issue) => `无效的项:输入为 ${issue.received}`, checkItemsAsync: (issue) => `无效的项:输入为 ${issue.received}`, creditCard: (issue) => `无效的信用卡:输入为 ${issue.received}`, cuid2: (issue) => `无效的 Cuid2:输入为 ${issue.received}`, decimal: (issue) => `无效的十进制:输入为 ${issue.received}`, digits: (issue) => `无效的数字:输入为 ${issue.received}`, domain: (issue) => `无效的域名:输入为 ${issue.received}`, email: (issue) => `无效的邮箱地址:输入为 ${issue.received}`, emoji: (issue) => `无效的 emoji:输入为 ${issue.received}`, empty: (issue) => `无效的长度:预期为 ${issue.expected},而输入为 ${issue.received}`, endsWith: (issue) => `无效的结尾:预期结尾为 ${issue.expected},而输入为 ${issue.received}`, entries: (issue) => `无效的条目数:预期为 ${issue.expected},而输入为 ${issue.received}`, everyItem: (issue) => `无效的项:输入为 ${issue.received}`, excludes: (issue) => `无效的内容:预期为 ${issue.expected},而输入为 ${issue.received}`, finite: (issue) => `无效的有限数:输入为 ${issue.received}`, graphemes: (issue) => `无效的图素长度:预期为 ${issue.expected},而输入为 ${issue.received}`, gtValue: (issue) => `无效的值:预期为 ${issue.expected},而输入为 ${issue.received}`, guard: (issue) => `无效的输入:输入为 ${issue.received}`, hash: (issue) => `无效的哈希值:输入为 ${issue.received}`, hexadecimal: (issue) => `无效的十六进制:输入为 ${issue.received}`, hexColor: (issue) => `无效的十六进制颜色:输入为 ${issue.received}`, imei: (issue) => `无效的国际移动设备识别码:输入为 ${issue.received}`, includes: (issue) => `无效的内容:预期为 ${issue.expected},而输入为 ${issue.received}`, integer: (issue) => `无效的整数:输入为 ${issue.received}`, ip: (issue) => `无效的 IP:输入为 ${issue.received}`, ipv4: (issue) => `无效的 IPv4:输入为 ${issue.received}`, ipv6: (issue) => `无效的 IPv6:输入为 ${issue.received}`, isbn: (issue) => `无效的 ISBN:输入为 ${issue.received}`, isoDate: (issue) => `无效的日期:输入为 ${issue.received}`, isoDateTime: (issue) => `无效的日期时间:输入为 ${issue.received}`, isoTime: (issue) => `无效的时间:输入为 ${issue.received}`, isoTimeSecond: (issue) => `无效的秒级时间:输入为 ${issue.received}`, isoTimestamp: (issue) => `无效的时间戳:输入为 ${issue.received}`, isoWeek: (issue) => `无效的周数:输入为 ${issue.received}`, isrc: (issue) => `无效的 ISRC:输入为 ${issue.received}`, jwsCompact: (issue) => `无效的 JWS 紧凑序列化:输入为 ${issue.received}`, length: (issue) => `无效的长度:预期为 ${issue.expected},而输入为 ${issue.received}`, ltValue: (issue) => `无效的值:预期为 ${issue.expected},而输入为 ${issue.received}`, mac: (issue) => `无效的 MAC:输入为 ${issue.received}`, mac48: (issue) => `无效的 48 位 MAC:输入为 ${issue.received}`, mac64: (issue) => `无效的 64 位 MAC:输入为 ${issue.received}`, maxBytes: (issue) => `无效的字节长度:预期为 ${issue.expected},而输入为 ${issue.received}`, maxEntries: (issue) => `无效的条目数:预期为 ${issue.expected},而输入为 ${issue.received}`, maxGraphemes: (issue) => `无效的图素长度:预期为 ${issue.expected},而输入为 ${issue.received}`, maxLength: (issue) => `无效的长度:预期为 ${issue.expected},而输入为 ${issue.received}`, maxSize: (issue) => `无效的大小:预期为 ${issue.expected},而输入为 ${issue.received}`, maxValue: (issue) => `无效的值:预期为 ${issue.expected},而输入为 ${issue.received}`, maxWords: (issue) => `无效的单词数:预期为 ${issue.expected},而输入为 ${issue.received}`, mimeType: (issue) => `无效的媒体类型:预期为 ${issue.expected},而输入为 ${issue.received}`, minBytes: (issue) => `无效的字节长度:预期为 ${issue.expected},而输入为 ${issue.received}`, minEntries: (issue) => `无效的条目数:预期为 ${issue.expected},而输入为 ${issue.received}`, minGraphemes: (issue) => `无效的图素长度:预期为 ${issue.expected},而输入为 ${issue.received}`, minLength: (issue) => `无效的长度:预期为 ${issue.expected},而输入为 ${issue.received}`, minSize: (issue) => `无效的大小:预期为 ${issue.expected},而输入为 ${issue.received}`, minValue: (issue) => `无效的值:预期为 ${issue.expected},而输入为 ${issue.received}`, minWords: (issue) => `无效的单词数:预期为 ${issue.expected},而输入为 ${issue.received}`, multipleOf: (issue) => `无效的倍数:预期为 ${issue.expected},而输入为 ${issue.received}`, nanoid: (issue) => `无效的 Nano ID:输入为 ${issue.received}`, nonEmpty: (issue) => `无效的长度:预期为 ${issue.expected},而输入为 ${issue.received}`, notBytes: (issue) => `无效的字节长度:预期为 ${issue.expected},而输入为 ${issue.received}`, notEntries: (issue) => `无效的条目数:预期为 ${issue.expected},而输入为 ${issue.received}`, notGraphemes: (issue) => `无效的图素长度:预期为 ${issue.expected},而输入为 ${issue.received}`, notLength: (issue) => `无效的长度:预期为 ${issue.expected},而输入为 ${issue.received}`, notSize: (issue) => `无效的大小:预期为 ${issue.expected},而输入为 ${issue.received}`, notValue: (issue) => `无效的值:预期为 ${issue.expected},而输入为 ${issue.received}`, notValues: (issue) => `无效的值:预期为 ${issue.expected},而输入为 ${issue.received}`, notWords: (issue) => `无效的单词数:预期为 ${issue.expected},而输入为 ${issue.received}`, octal: (issue) => `无效的八进制:输入为 ${issue.received}`, parseBoolean: (issue) => `无效的布尔值:输入为 ${issue.received}`, parseJson: (issue) => `无效的 JSON:输入为 ${issue.received}`, partialCheck: (issue) => `无效的输入:输入为 ${issue.received}`, rawCheck: (issue) => `无效的输入:输入为 ${issue.received}`, rawTransform: (issue) => `无效的输入:输入为 ${issue.received}`, regex: (issue) => `无效的格式:预期为 ${issue.expected},而输入为 ${issue.received}`, rfcEmail: (issue) => `无效的电子邮箱:输入为 ${issue.received}`, safeInteger: (issue) => `无效的安全整数:输入为 ${issue.received}`, size: (issue) => `无效的大小:预期为 ${issue.expected},而输入为 ${issue.received}`, slug: (issue) => `无效的短标签:输入为 ${issue.received}`, someItem: (issue) => `无效的项:输入为 ${issue.received}`, startsWith: (issue) => `无效的开头:预期开头为 ${issue.expected},而输入为 ${issue.received}`, stringifyJson: (issue) => `无效的 JSON:输入为 ${issue.received}`, toBigint: (issue) => `无效的 BigInt:输入为 ${issue.received}`, toDate: (issue) => `无效的日期:输入为 ${issue.received}`, toNumber: (issue) => `无效的数字:输入为 ${issue.received}`, toString: (issue) => `无效的字符串:输入为 ${issue.received}`, ulid: (issue) => `无效的 ULID:输入为 ${issue.received}`, url: (issue) => `无效的 URL:输入为 ${issue.received}`, uuid: (issue) => `无效的 UUID:输入为 ${issue.received}`, value: (issue) => `无效的值:预期为 ${issue.expected},而输入为 ${issue.received}`, values: (issue) => `无效的值:预期为 ${issue.expected},而输入为 ${issue.received}`, words: (issue) => `无效的单词数:预期为 ${issue.expected},而输入为 ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/src/zh-TW.ts ================================================ import type { Language } from './types'; // prettier-ignore const language: Language = { code: 'zh-TW', schema: (issue) => `無效的類型:預期為 ${issue.expected},但輸入為 ${issue.received}`, specific: { base64: (issue) => `無效的 Base64:輸入為 ${issue.received}`, bic: (issue) => `無效的商業識別代碼:輸入為 ${issue.received}`, bytes: (issue) => `無效的位元組:預期為 ${issue.expected},但輸入為 ${issue.received}`, check: (issue) => `無效的輸入:輸入為 ${issue.received}`, checkAsync: (issue) => `無效的輸入:輸入為 ${issue.received}`, checkItems: (issue) => `無效元素:輸入為 ${issue.received}`, checkItemsAsync: (issue) => `無效元素:輸入為 ${issue.received}`, creditCard: (issue) => `無效的信用卡:輸入為 ${issue.received}`, cuid2: (issue) => `無效的 Cuid2:輸入為 ${issue.received}`, decimal: (issue) => `無效的十進位:輸入為 ${issue.received}`, digits: (issue) => `無效的數字:輸入為 ${issue.received}`, domain: (issue) => `無效的網域名稱:輸入為 ${issue.received}`, email: (issue) => `無效的電子郵件:輸入為 ${issue.received}`, emoji: (issue) => `無效的表情符號:輸入為 ${issue.received}`, empty: (issue) => `無效的長度:預期為 ${issue.expected},但輸入為 ${issue.received}`, endsWith: (issue) => `無效的結尾:預期為 ${issue.expected},但輸入為 ${issue.received}`, entries: (issue) => `無效的項目數:預期為 ${issue.expected},但輸入為 ${issue.received}`, everyItem: (issue) => `無效的元素:輸入為 ${issue.received}`, excludes: (issue) => `無效的內容:預期為 ${issue.expected},但輸入為 ${issue.received}`, finite: (issue) => `無效的有限數:輸入為 ${issue.received}`, graphemes: (issue) => `無效的字元:預期為 ${issue.expected},但輸入為 ${issue.received}`, gtValue: (issue) => `無效的值:預期為 ${issue.expected},但輸入為 ${issue.received}`, guard: (issue) => `無效的輸入:輸入為 ${issue.received}`, hash: (issue) => `無效的哈希:輸入為 ${issue.received}`, hexadecimal: (issue) => `無效的十六進位:輸入為 ${issue.received}`, hexColor: (issue) => `無效的十六進位顏色:輸入為 ${issue.received}`, imei: (issue) => `無效的 IMEI:輸入為 ${issue.received}`, includes: (issue) => `無效的內容:預期為 ${issue.expected},但輸入為 ${issue.received}`, integer: (issue) => `無效的整數:輸入為 ${issue.received}`, ip: (issue) => `無效的 IP:輸入為 ${issue.received}`, ipv4: (issue) => `無效的 IPv4:輸入為 ${issue.received}`, ipv6: (issue) => `無效的 IPv6:輸入為 ${issue.received}`, isbn: (issue) => `無效的 ISBN:輸入為 ${issue.received}`, isoDate: (issue) => `無效的日期:輸入為 ${issue.received}`, isoDateTime: (issue) => `無效的日期時間:輸入為 ${issue.received}`, isoTime: (issue) => `無效的時間:輸入為 ${issue.received}`, isoTimeSecond: (issue) => `無效的時間秒:輸入為 ${issue.received}`, isoTimestamp: (issue) => `無效的時間戳記:輸入為 ${issue.received}`, isoWeek: (issue) => `無效的週數:輸入為 ${issue.received}`, isrc: (issue) => `無效的 ISRC:輸入為 ${issue.received}`, jwsCompact: (issue) => `無效的 JWS 緊湊序列化:輸入為 ${issue.received}`, length: (issue) => `無效的長度:預期為 ${issue.expected},但輸入為 ${issue.received}`, ltValue: (issue) => `無效的值:預期為 ${issue.expected},但輸入為 ${issue.received}`, mac: (issue) => `無效的 MAC:輸入為 ${issue.received}`, mac48: (issue) => `無效的 48 位元 MAC:輸入為 ${issue.received}`, mac64: (issue) => `無效的 64 位元 MAC:輸入為 ${issue.received}`, maxBytes: (issue) => `無效的位元組:預期為 ${issue.expected},但輸入為 ${issue.received}`, maxEntries: (issue) => `無效的項目數:預期為 ${issue.expected},但輸入為 ${issue.received}`, maxGraphemes: (issue) => `無效的字元:預期為 ${issue.expected},但輸入為 ${issue.received}`, maxLength: (issue) => `無效的長度:預期為 ${issue.expected},但輸入為 ${issue.received}`, maxSize: (issue) => `無效的大小:預期為 ${issue.expected},但輸入為 ${issue.received}`, maxValue: (issue) => `無效的值:預期為 ${issue.expected},但輸入為 ${issue.received}`, maxWords: (issue) => `無效的字詞:預期為 ${issue.expected},但輸入為 ${issue.received}`, mimeType: (issue) => `無效的 MIME 類型:預期為 ${issue.expected},但輸入為 ${issue.received}`, minBytes: (issue) => `無效的位元組:預期為 ${issue.expected},但輸入為 ${issue.received}`, minEntries: (issue) => `無效的項目數:預期為 ${issue.expected},但輸入為 ${issue.received}`, minGraphemes: (issue) => `無效的字元:預期為 ${issue.expected},但輸入為 ${issue.received}`, minLength: (issue) => `無效的長度:預期為 ${issue.expected},但輸入為 ${issue.received}`, minSize: (issue) => `無效的大小:預期為 ${issue.expected},但輸入為 ${issue.received}`, minValue: (issue) => `無效的值:預期為 ${issue.expected},但輸入為 ${issue.received}`, minWords: (issue) => `無效的字詞:預期為 ${issue.expected},但輸入為 ${issue.received}`, multipleOf: (issue) => `無效的倍數:預期為 ${issue.expected},但輸入為 ${issue.received}`, nanoid: (issue) => `無效的 Nano ID:輸入為 ${issue.received}`, nonEmpty: (issue) => `無效的長度:預期為 ${issue.expected},但輸入為 ${issue.received}`, notBytes: (issue) => `無效的位元組:預期為 ${issue.expected},但輸入為 ${issue.received}`, notEntries: (issue) => `無效的項目數:預期為 ${issue.expected},但輸入為 ${issue.received}`, notGraphemes: (issue) => `無效的字元:預期為 ${issue.expected},但輸入為 ${issue.received}`, notLength: (issue) => `無效的長度:預期為 ${issue.expected},但輸入為 ${issue.received}`, notSize: (issue) => `無效的大小:預期為 ${issue.expected},但輸入為 ${issue.received}`, notValue: (issue) => `無效的值:預期為 ${issue.expected},但輸入為 ${issue.received}`, notValues: (issue) => `無效的值:預期為 ${issue.expected},但輸入為 ${issue.received}`, notWords: (issue) => `無效的字詞:預期為 ${issue.expected},但輸入為 ${issue.received}`, octal: (issue) => `無效的八進位:輸入為 ${issue.received}`, parseBoolean: (issue) => `無效的布林值:輸入為 ${issue.received}`, parseJson: (issue) => `無效的 JSON:輸入為 ${issue.received}`, partialCheck: (issue) => `無效的輸入:輸入為 ${issue.received}`, rawCheck: (issue) => `無效的輸入:輸入為 ${issue.received}`, rawTransform: (issue) => `無效的輸入:輸入為 ${issue.received}`, regex: (issue) => `無效的格式:預期為 ${issue.expected},但輸入為 ${issue.received}`, rfcEmail: (issue) => `無效的電子郵件:輸入為 ${issue.received}`, safeInteger: (issue) => `無效的安全整數:輸入為 ${issue.received}`, size: (issue) => `無效的大小:預期為 ${issue.expected},但輸入為 ${issue.received}`, slug: (issue) => `無效的短標籤:輸入為 ${issue.received}`, someItem: (issue) => `無效的元素:輸入為 ${issue.received}`, startsWith: (issue) => `無效的開始:預期為 ${issue.expected},但輸入為 ${issue.received}`, stringifyJson: (issue) => `無效的 JSON:輸入為 ${issue.received}`, toBigint: (issue) => `無效的 BigInt:輸入為 ${issue.received}`, toDate: (issue) => `無效的日期:輸入為 ${issue.received}`, toNumber: (issue) => `無效的數字:輸入為 ${issue.received}`, toString: (issue) => `無效的字串:輸入為 ${issue.received}`, ulid: (issue) => `無效的 ULID:輸入為 ${issue.received}`, url: (issue) => `無效的網址:輸入為 ${issue.received}`, uuid: (issue) => `無效的 UUID:輸入為 ${issue.received}`, value: (issue) => `無效的值:預期為 ${issue.expected},但輸入為 ${issue.received}`, values: (issue) => `無效的值:預期為 ${issue.expected},但輸入為 ${issue.received}`, words: (issue) => `無效的字詞:預期為 ${issue.expected},但輸入為 ${issue.received}`, }, }; export default language; ================================================ FILE: packages/i18n/tsconfig.json ================================================ { "compilerOptions": { "strict": true, "lib": ["ESNext", "DOM"], "target": "ES2020", "module": "ESNext", "moduleResolution": "node", "allowImportingTsExtensions": true, "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "skipLibCheck": true, "noEmit": true }, "include": ["scripts", "src"] } ================================================ FILE: packages/to-json-schema/CHANGELOG.md ================================================ # Changelog All notable changes to the library will be documented in this file. ## v1.6.0 (March 17, 2026) - Add support for `never` schema (pull request #1430) - Add support for `endsWith`, `gtValue`, `hash`, `includes`, `isoTimeSecond`, `isoWeek`, `isrc`, `ltValue`, `mac`, `mac48`, `mac64`, `notValue`, `notValues`, `rfcEmail`, `safeInteger`, `slug`, `startsWith` and `values` actions (pull request #1430) - Add JSON compatibility validation for the requirements of `value`, `values`, `notValue` and `notValues` actions (pull request #1430) - Add inferred `type` for `enum` and `picklist` schemas (pull request #1430) - Change Valibot peer dependency to v1.3.0 ## v1.5.0 (December 11, 2025) - Add support for JSON Schema draft-2020-12 and OpenAPI 3.0 Schema Object format - Add `propertyNames` support to record schemas for key validation constraints - Add support for `toBigint`, `toBoolean`, `toDate`, `toNumber` and `toString` actions for `typeMode: 'input'` - Add new `toStandardJsonSchema` function to convert Valibot schemas to Standard JSON Schema format - Change return type from `JSONSchema7` to a custom `JsonSchema` type ## v1.4.0 (December 02, 2025) - Add support for `examples` action - Add support for `integer` when used with `minValue` and `maxValue` actions (pull request #1367) - Change Valibot peer dependency to v1.2.0 - Fix conversion of `exactOptional` object properties (pull request #1220) - Fix conversion of `variant` to use `oneOf` instead of `anyOf` (pull request #1193) ## v1.3.0 (June 01, 2025) - Add `ignoreActions` configuration to be able to ignore specific actions during conversion - Add `typeMode` configuration to be able to control whether to convert input or output type of schema - Add `ConversionContext`, `OverrideSchemaContext`, `OverrideActionContext` and `OverrideRefContext` to exports - Change JSDoc comments to improve documentation - Change build step to tsdown and Rolldown ## v1.2.0 (May 17, 2025) - Add support for title, description and examples in `metadata` action (pull request #1189) - Add new override configurations to override default behaviour of JSON Schema conversion (pull request #1197) - Add storage for global definitions with `addGlobalDefs` and `getGlobalDefs` (pull request #1197) - Add new `toJsonSchemaDefs` function to convert Valibot schema definitions to JSON Schema definitions (pull request #1197) ## v1.1.0 (May 06, 2025) - Add support for `minEntries` and `maxEntries` action (pull request #1100) - Add support for `entries` action (pull request #1156) - Change Valibot peer dependency to v1.1.0 - Fix `toJsonSchema` to be independent of definition order (pull request #1133) - Fix `additionalItems` for tuple schemas and add `minItems` (pull request #1126) ## v1.0.0 (March 19, 2025) - Add support for `exactOptional` and `undefinedable` schema - Add support for `base64`, `isoTime`, `isoDateTime`, `nonEmpty` and `url` action (pull request #962) - Add support for `bic`, `cuid2`, `empty`, `decimal`, `digits`, `emoji`, `hexColor`, `hexadecimal`, `nanoid`, `octal` and `ulid` action (pull request #998) - Change Valibot peer dependency to v1.0.0 - Change extraction of default value from `nullable`, `nullish` and `optional` schema - Change `force` to `errorMode` in config for better control (issue #889) - Change `additionalProperties` for `object` and `looseObject` schema (pull request #1001) ## v0.2.1 (September 30, 2024) - Fix type export for Deno (pull request #854) ## v0.2.0 (September 15, 2024) - Add support for `title` action (discussion #826) ## v0.1.1 (September 14, 2024) - Fix maximum call stack bug for recursive schemas - Fix invalid JSON Schema ouput for recursive schemas ## v0.1.0 (September 13, 2024) - Initial release ================================================ FILE: packages/to-json-schema/LICENSE.md ================================================ MIT License Copyright (c) Fabian Hiller Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: packages/to-json-schema/README.md ================================================ # Valibot to JSON Schema Utility to convert [Valibot](https://valibot.dev) schemas to JSON Schema. Supports JSON Schema draft-07, draft-2020-12, and OpenAPI 3.0 Schema Object formats. ```js import { toJsonSchema } from '@valibot/to-json-schema'; import * as v from 'valibot'; toJsonSchema(v.string()); // { $schema: "http://json-schema.org/draft-07/schema#", type: "string" } ``` This package is particularly popular for: - **API Documentation**: Generate OpenAPI specifications from your Valibot schemas - **Code Generation**: Create client SDKs and types from your validation schemas - **LLM Integration**: Generate structured outputs for Large Language Models - **Schema Sharing**: Share validation logic between different programming languages > Some Valibot features can't be mapped to JSON schema. For example, transformation actions have no equivalent in JSON schema. Also, some Valibot schemas or validations are too JS-specific and do not have an equivalent JSON schema attribute. ## Supported features **Note**: Converted schemas may behave slightly differently in JSON schema validators (especially for string format) because their implementation is different from Valibot's. | Schema | Status | Note | | ---------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------- | | `any` | ✅ | | | `array` | ✅ | | | `boolean` | ✅ | | | `enum` | ✅ | | | `exactOptional` | ✅ | | | `intersect` | ✅ | | | `lazy` | ⚠️ | The `.getter` function is always executed with `undefined` as input | | `literal` | ⚠️ | Only JSON compatible values are supported | | `looseObject` | ✅ | | | `looseTuple` | ✅ | | | `never` | ✅ | | | `null` | ✅ | | | `nullable` | ✅ | | | `nullish` | ✅ | | | `number` | ✅ | | | `objectWithRest` | ✅ | | | `object` | ✅ | | | `optional` | ✅ | | | `picklist` | ⚠️ | Only JSON compatible values are supported | | `record` | ⚠️ | Only `string` schemas for the key of the record are supported. Adds `propertyNames` for key validation (not available in OpenAPI 3.0) | | `strictObject` | ✅ | | | `strictTuple` | ✅ | | | `string` | ✅ | | | `tupleWithRest` | ✅ | | | `tuple` | ✅ | | | `union` | ✅ | | | `undefinedable` | ✅ | | | `unknown` | ✅ | | | `variant` | ⚠️ | The discriminator key will be ignored | | Actions | Status | Note | | --------------- | ------ | ----------------------------------------------------------- | | `base64` | ✅ | | | `bic` | ✅ | | | `cuid2` | ✅ | | | `decimal` | ✅ | | | `description` | ✅ | | | `digits` | ✅ | | | `domain` | ✅ | | | `email` | ✅ | | | `emoji` | ✅ | | | `empty` | ✅ | | | `endsWith` | ✅ | | | `entries` | ✅ | | | `examples` | ✅ | | | `gtValue` | ⚠️ | Only in combination with `number` and `integer` schema | | `hash` | ✅ | | | `hexadecimal` | ✅ | | | `hexColor` | ✅ | | | `includes` | ✅ | | | `integer` | ✅ | | | `ipv4` | ✅ | | | `ipv6` | ✅ | | | `isoDate` | ✅ | | | `isoDateTime` | ✅ | | | `isoTime` | ✅ | | | `isoTimeSecond` | ✅ | | | `isoTimestamp` | ✅ | | | `isoWeek` | ✅ | | | `isrc` | ✅ | | | `jwsCompact` | ✅ | | | `length` | ⚠️ | Only in combination with `string` and `array` schema | | `ltValue` | ⚠️ | Only in combination with `number` and `integer` schema | | `mac` | ✅ | | | `mac48` | ✅ | | | `mac64` | ✅ | | | `maxEntries` | ✅ | | | `maxLength` | ⚠️ | Only in combination with `string` and `array` schema | | `maxValue` | ⚠️ | Only in combination with `number` schema | | `metadata` | ⚠️ | Only for valid `title`, `description` and `examples` values | | `minEntries` | ✅ | | | `minLength` | ⚠️ | Only in combination with `string` and `array` schema | | `minValue` | ⚠️ | Only in combination with `number` schema | | `multipleOf` | ✅ | | | `nanoid` | ✅ | | | `nonEmpty` | ✅ | | | `notValue` | ⚠️ | Only JSON compatible values are supported | | `notValues` | ⚠️ | Only JSON compatible values are supported | | `octal` | ✅ | | | `regex` | ⚠️ | RegExp flags are not supported in JSON Schema | | `rfcEmail` | ✅ | | | `safeInteger` | ✅ | | | `slug` | ✅ | | | `startsWith` | ✅ | | | `title` | ✅ | | | `ulid` | ✅ | | | `url` | ✅ | | | `uuid` | ✅ | | | `value` | ⚠️ | Only JSON compatible values are supported | | `values` | ⚠️ | Only JSON compatible values are supported | ## Configurations | Option | Type | Note | | -------------- | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | | target | `'draft-07' \| 'draft-2020-12' \| 'openapi-3.0'` | The target JSON Schema format. Defaults to `'draft-07'`. | | typeMode | `'ignore' \| 'input' \| 'output'` | Whether to convert the input or output type of the Valibot schema to JSON Schema. | | errorMode | `'throw' \| 'warn' \| 'ignore'` | The policy for handling incompatible schemas and actions. | | definitions | `Record` | The schema definitions for constructing recursive schemas. If not specified, the definitions are generated automatically. | | overrideSchema | `(context: OverrideSchemaContext) => JsonSchema \| null \| undefined` | Overrides the JSON Schema conversion for a specific Valibot schema. | | ignoreActions | `string[]` | The actions that should be ignored during the conversion. | | overrideAction | `(context: OverrideActionContext) => JsonSchema \| null \| undefined` | Overrides the JSON Schema reference for a specific Valibot action. | | overrideRef | `(context: OverrideRefContext) => string \| null \| undefined` | Overrides the JSON Schema reference for a specific reference ID. | ### Target format The `target` configuration allows you to specify which JSON Schema format to generate. Different targets have different capabilities and syntax: ```js import { toJsonSchema } from '@valibot/to-json-schema'; import * as v from 'valibot'; const schema = v.nullable(v.string()); // JSON Schema draft-07 (default) toJsonSchema(schema); // { $schema: "http://json-schema.org/draft-07/schema#", anyOf: [{ type: "string" }, { type: "null" }] } // JSON Schema draft-2020-12 toJsonSchema(schema, { target: 'draft-2020-12' }); // { $schema: "https://json-schema.org/draft/2020-12/schema", anyOf: [{ type: "string" }, { type: "null" }] } // OpenAPI 3.0 Schema Object toJsonSchema(schema, { target: 'openapi-3.0' }); // { type: "string", nullable: true } ``` **Note**: Some features like `propertyNames` for record schemas are not available in OpenAPI 3.0. ### Type mode The `typeMode` configuration controls 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. - When set to `'ignore'` (default), the entire pipeline is converted. This is particularly useful when defining API endpoints where external developers need different schema information for requests vs responses: ```js import { toJsonSchema } from '@valibot/to-json-schema'; import * as v from 'valibot'; const ValibotSchema = v.pipe( v.string(), v.decimal(), v.transform(Number), v.number(), v.maxValue(100) ); toJsonSchema(ValibotSchema, { typeMode: 'input' }); // { // $schema: "http://json-schema.org/draft-07/schema#", // type: "string", // pattern: "^[+-]?(?:\\d*\\.)?\\d+$" // } toJsonSchema(ValibotSchema, { typeMode: 'output' }); // { // $schema: "http://json-schema.org/draft-07/schema#", // type: "number", // maximum: 100 // } ``` ### Error mode The `errorMode` configuration controls how the converter handles unsupported schemas and actions. By default, the error mode is set to `'throw'`. To force the conversion of unsupported Valibot features, you can set it to `'ignore'`. > Unsupported schemas usually return an empty JSON schema (`{}`) and unsupported actions are usually ignored. ```js import { toJsonSchema } from '@valibot/to-json-schema'; import * as v from 'valibot'; toJsonSchema(v.file(), { errorMode: 'ignore' }); // {} toJsonSchema(v.pipe(v.string(), v.creditCard()), { errorMode: 'ignore' }); // { type: "string" } ``` ### Override functions The package provides powerful override capabilities to customize the JSON Schema conversion process. You can override the conversion of specific schemas, actions, or references. #### Override schema conversion Handle unsupported schemas or customize conversion behavior: ```js import { toJsonSchema } from '@valibot/to-json-schema'; import * as v from 'valibot'; const ValibotSchema = v.object({ createdAt: v.date() }); toJsonSchema(ValibotSchema, { overrideSchema(context) { if (context.valibotSchema.type === 'date') { return { type: 'string', format: 'date-time' }; } }, }); // { // $schema: "http://json-schema.org/draft-07/schema#", // type: "object", // properties: { // createdAt: { type: "string" format: "date-time" } // }, // required: ["createdAt"] // } ``` #### Override reference IDs Customize reference IDs for OpenAPI or other specifications: ```js import { toJsonSchemaDefs } from '@valibot/to-json-schema'; import * as v from 'valibot'; const UserSchema = v.object({ name: v.string() }); toJsonSchemaDefs( { UserSchema }, { overrideRef: (context) => `#/schemas/${context.referenceId}` } ); ``` ### Enhanced metadata support Use the generic `metadata` action to add title, description, and examples to your schemas or the individual `title`and `description` actions: ```js import { toJsonSchema } from '@valibot/to-json-schema'; import * as v from 'valibot'; const ValibotSchema = v.pipe( v.string(), v.email(), v.metadata({ title: 'Email Schema', description: 'A schema that validates email addresses.', examples: ['jane@example.com'], }) ); toJsonSchema(ValibotSchema); // { // $schema: "http://json-schema.org/draft-07/schema#", // type: "string", // format: "email", // title: "Email Schema", // description: "A schema that validates email addresses.", // examples: ["jane@example.com"] // } ``` ### Definitions Nested and recursive schemas can be broken in multiple reusable definitions. ```js import { toJsonSchema } from '@valibot/to-json-schema'; import * as v from 'valibot'; const EmailSchema = v.pipe(v.string(), v.email()); toJsonSchema(v.object({ email: EmailSchema }), { definitions: { EmailSchema }, }); // { // $schema: "http://json-schema.org/draft-07/schema#", // type: "object", // properties: { // email: { // $ref: "#/$defs/EmailSchema" // } // }, // required: ["email"], // $defs: { // EmailSchema: { // type: "string", // format: "email" // } // } // } ``` Definitions are not required for converting `lazy` schemas. Missing definitions will be generated automatically. ```js import { toJsonSchema } from '@valibot/to-json-schema'; import * as v from 'valibot'; const StringSchema = v.string(); toJsonSchema(v.object({ key: v.lazy(() => StringSchema) })); // { // $schema: "http://json-schema.org/draft-07/schema#", // type: "object", // properties: { // key: { // $ref: "#/$defs/0" // } // }, // required: ["key"], // $defs: { // 0: { // type: "string" // } // } // } ``` ## Additional functions ### `toStandardJsonSchema` Converts a Valibot schema to the [Standard JSON Schema](https://standardschema.dev/) format. This format is useful when working with tools and libraries that support the Standard JSON Schema specification. ```js import { toStandardJsonSchema } from '@valibot/to-json-schema'; import * as v from 'valibot'; const schema = toStandardJsonSchema( v.object({ id: v.pipe(v.string(), v.uuid()), name: v.pipe(v.string(), v.nonEmpty()), age: v.optional(v.number()), }) ); ``` ### `toJsonSchemaDefs` Converts only the provided Valibot schema definitions to JSON Schema definitions, without wrapping them in a root schema. This is particularly useful for OpenAPI specifications where you need only the schema definitions. ```js import { toJsonSchemaDefs } from '@valibot/to-json-schema'; import * as v from 'valibot'; const EmailSchema = v.pipe(v.string(), v.email()); const UserSchema = v.object({ name: v.string(), email: EmailSchema, }); toJsonSchemaDefs({ EmailSchema, UserSchema }); // { // EmailSchema: { // type: "string", // format: "email" // }, // UserSchema: { // type: "object", // properties: { // name: { // type: "string" // }, // email: { // $ref: "#/$defs/EmailSchema" // } // }, // required: ["name", "email"] // } // } ``` #### OpenAPI integration For OpenAPI specifications, you can customize reference IDs: ```js import { toJsonSchemaDefs } from '@valibot/to-json-schema'; import * as v from 'valibot'; const ValibotSchema1 = v.string(); const ValibotSchema2 = v.number(); const ValibotSchema3 = v.tuple([ValibotSchema1, ValibotSchema2]); toJsonSchemaDefs( { ValibotSchema1, ValibotSchema2, ValibotSchema3 }, { overrideRef: (context) => `#/schemas/${context.referenceId}` } ); // { // ValibotSchema1: { type: "string" }, // ValibotSchema2: { type: "number" }, // ValibotSchema3: { // type: "array", // items: [ // { $ref: "#/schemas/ValibotSchema1" }, // { $ref: "#/schemas/ValibotSchema2" } // ], // minItems: 2 // } // } ``` ### Global definitions For advanced use cases, you can manage global schema definitions that will be automatically used when converting schemas. This is particularly useful for larger projects with many reusable schemas. ```js import { addGlobalDefs, toJsonSchema } from '@valibot/to-json-schema'; import * as v from 'valibot'; const ValibotSchema1 = v.string(); const ValibotSchema2 = v.number(); addGlobalDefs({ ValibotSchema1, ValibotSchema2 }); const ValibotSchema3 = v.tuple([ValibotSchema1, ValibotSchema2]); toJsonSchema(ValibotSchema3); // { // $schema: "http://json-schema.org/draft-07/schema#", // type: "array", // items: [ // { $ref: "#/$defs/ValibotSchema1" }, // { $ref: "#/$defs/ValibotSchema2" } // ], // minItems: 2, // $defs: { // ValibotSchema1: { type: "string" }, // ValibotSchema2: { type: "number" } // } // } ``` You can also convert global definitions directly using `toJsonSchemaDefs`: ```js const globalDefs = getGlobalDefs(); if (globalDefs) { const schemaDefs = toJsonSchemaDefs(globalDefs); } ``` ================================================ FILE: packages/to-json-schema/eslint.config.js ================================================ import eslint from '@eslint/js'; import importPlugin from 'eslint-plugin-import'; import jsdoc from 'eslint-plugin-jsdoc'; import pluginSecurity from 'eslint-plugin-security'; import tseslint from 'typescript-eslint'; export default tseslint.config( { ignores: ['eslint.config.js', 'tsdown.config.ts', 'vitest.config.ts'], }, eslint.configs.recommended, tseslint.configs.strict, tseslint.configs.stylistic, jsdoc.configs['flat/recommended'], pluginSecurity.configs.recommended, { files: ['src/**/*.ts'], extends: [importPlugin.flatConfigs.recommended], languageOptions: { parserOptions: { project: './tsconfig.json', tsconfigRootDir: import.meta.dirname, }, }, plugins: { jsdoc }, settings: { 'import/resolver': { typescript: { project: './tsconfig.json', }, }, }, rules: { // Enable rules ----------------------------------------------------------- // TypeScript '@typescript-eslint/consistent-type-definitions': 'error', // Enforce declaring types using `interface` keyword for better TS performance. '@typescript-eslint/consistent-type-imports': 'warn', // Import 'import/extensions': ['error', 'always'], // Require file extensions // JSDoc 'jsdoc/tag-lines': ['error', 'any', { startLines: 1 }], 'jsdoc/sort-tags': [ 'error', { linesBetween: 1, tagSequence: [ { tags: ['deprecated'] }, { tags: ['param'] }, { tags: ['returns'] }, ], }, ], // NOTE: For overloads functions, we only require a JSDoc at the top // SEE: https://github.com/gajus/eslint-plugin-jsdoc/issues/666 'jsdoc/require-jsdoc': [ 'error', { contexts: [ 'ExportNamedDeclaration[declaration.type="TSDeclareFunction"]:not(ExportNamedDeclaration[declaration.type="TSDeclareFunction"] + ExportNamedDeclaration[declaration.type="TSDeclareFunction"])', 'ExportNamedDeclaration[declaration.type="FunctionDeclaration"]:not(ExportNamedDeclaration[declaration.type="TSDeclareFunction"] + ExportNamedDeclaration[declaration.type="FunctionDeclaration"])', ], require: { FunctionDeclaration: false, }, }, ], 'jsdoc/check-tag-names': [ 'error', { definedTags: ['alpha', 'beta'], }, ], // Disable rules ---------------------------------------------------------- // TypeScript '@typescript-eslint/ban-ts-comment': 'off', '@typescript-eslint/no-non-null-assertion': 'off', // Imports 'no-duplicate-imports': 'off', // JSDoc 'jsdoc/require-param-type': 'off', 'jsdoc/require-returns-type': 'off', // Security 'security/detect-object-injection': 'off', // Too many false positives }, } ); ================================================ FILE: packages/to-json-schema/jsr.json ================================================ { "name": "@valibot/to-json-schema", "version": "1.6.0", "exports": "./src/index.ts", "publish": { "include": ["src/**/*.ts", "README.md"], "exclude": ["src/**/*.test.ts", "src/vitest/**/*.ts"] } } ================================================ FILE: packages/to-json-schema/package.json ================================================ { "name": "@valibot/to-json-schema", "description": "The official JSON schema converter for Valibot", "version": "1.6.0", "license": "MIT", "author": "Fabian Hiller", "homepage": "https://valibot.dev", "contributors": [ { "name": "Guillaume Cornut" } ], "repository": { "type": "git", "url": "https://github.com/open-circle/valibot" }, "keywords": [ "valibot", "schema", "converter", "json-schema" ], "type": "module", "main": "./dist/index.mjs", "types": "./dist/index.d.mts", "exports": { ".": { "import": { "types": "./dist/index.d.mts", "default": "./dist/index.mjs" }, "require": { "types": "./dist/index.d.cts", "default": "./dist/index.cjs" } } }, "sideEffects": false, "files": [ "dist" ], "publishConfig": { "access": "public" }, "scripts": { "test": "vitest --typecheck", "coverage": "vitest run --coverage --isolate", "lint": "eslint \"src/**/*.ts*\" && tsc --noEmit && deno check ./src/index.ts", "lint.fix": "eslint \"src/**/*.ts*\" --fix", "format": "prettier --write ./src", "format.check": "prettier --check ./src", "build": "tsdown" }, "devDependencies": { "@eslint/js": "^9.39.1", "@types/node": "^24.10.1", "@vitest/coverage-v8": "^4.0.13", "eslint": "^9.39.1", "eslint-import-resolver-typescript": "^4.4.4", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsdoc": "^61.4.0", "eslint-plugin-security": "^3.0.1", "globals": "^16.5.0", "tsdown": "^0.16.6", "typescript": "^5.9.3", "typescript-eslint": "^8.47.0", "valibot": "^1.3.0", "vite": "^7.2.4", "vite-tsconfig-paths": "^5.1.4", "vitest": "4.0.13" }, "peerDependencies": { "valibot": "^1.3.0" } } ================================================ FILE: packages/to-json-schema/src/converters/convertAction/convertAction.test.ts ================================================ import * as v from 'valibot'; import { describe, expect, test, vi } from 'vitest'; import { convertAction } from './convertAction.ts'; console.warn = vi.fn(); describe('convertAction', () => { test('should ignore specified actions', () => { expect( convertAction({}, v.email(), { ignoreActions: ['email'] }) ).toStrictEqual({}); expect( convertAction({ type: 'string' }, v.email(), { ignoreActions: ['email'], }) ).toStrictEqual({ type: 'string', }); }); test('should convert base64 action', () => { expect(convertAction({}, v.base64(), undefined)).toStrictEqual({ contentEncoding: 'base64', }); expect( convertAction({ type: 'string' }, v.base64(), undefined) ).toStrictEqual({ type: 'string', contentEncoding: 'base64', }); }); test('should convert bic action', () => { expect(convertAction({}, v.bic(), undefined)).toStrictEqual({ pattern: v.BIC_REGEX.source, }); expect( convertAction({ type: 'string' }, v.bic(), undefined) ).toStrictEqual({ type: 'string', pattern: v.BIC_REGEX.source, }); }); test('should convert cuid2 action', () => { expect(convertAction({}, v.cuid2(), undefined)).toStrictEqual({ pattern: v.CUID2_REGEX.source, }); expect( convertAction({ type: 'string' }, v.cuid2(), undefined) ).toStrictEqual({ type: 'string', pattern: v.CUID2_REGEX.source, }); }); test('should convert decimal action', () => { expect(convertAction({}, v.decimal(), undefined)).toStrictEqual({ pattern: v.DECIMAL_REGEX.source, }); expect( convertAction({ type: 'string' }, v.decimal(), undefined) ).toStrictEqual({ type: 'string', pattern: v.DECIMAL_REGEX.source, }); }); test('should convert digits action', () => { expect(convertAction({}, v.digits(), undefined)).toStrictEqual({ pattern: v.DIGITS_REGEX.source, }); expect( convertAction({ type: 'string' }, v.digits(), undefined) ).toStrictEqual({ type: 'string', pattern: v.DIGITS_REGEX.source, }); }); test('should convert domain action', () => { expect(convertAction({}, v.domain(), undefined)).toStrictEqual({ pattern: v.DOMAIN_REGEX.source, }); expect( convertAction({ type: 'string' }, v.domain(), undefined) ).toStrictEqual({ type: 'string', pattern: v.DOMAIN_REGEX.source, }); }); test('should convert emoji action', () => { expect(convertAction({}, v.emoji(), undefined)).toStrictEqual({ pattern: v.EMOJI_REGEX.source, }); expect( convertAction({ type: 'string' }, v.emoji(), undefined) ).toStrictEqual({ type: 'string', pattern: v.EMOJI_REGEX.source, }); }); test('should convert hash action', () => { const action = v.hash(['md5']); expect(convertAction({ type: 'string' }, action, undefined)).toStrictEqual({ type: 'string', pattern: action.requirement.source, }); }); test('should convert hexadecimal action', () => { expect(convertAction({}, v.hexadecimal(), undefined)).toStrictEqual( { pattern: v.HEXADECIMAL_REGEX.source, } ); expect( convertAction({ type: 'string' }, v.hexadecimal(), undefined) ).toStrictEqual({ type: 'string', pattern: v.HEXADECIMAL_REGEX.source, }); }); test('should convert hex color action', () => { expect(convertAction({}, v.hexColor(), undefined)).toStrictEqual({ pattern: v.HEX_COLOR_REGEX.source, }); expect( convertAction({ type: 'string' }, v.hexColor(), undefined) ).toStrictEqual({ type: 'string', pattern: v.HEX_COLOR_REGEX.source, }); }); test('should convert isrc action', () => { expect(convertAction({}, v.isrc(), undefined)).toStrictEqual({ pattern: v.ISRC_REGEX.source, }); expect( convertAction({ type: 'string' }, v.isrc(), undefined) ).toStrictEqual({ type: 'string', pattern: v.ISRC_REGEX.source, }); }); test('should convert iso time second action', () => { expect( convertAction({}, v.isoTimeSecond(), undefined) ).toStrictEqual({ pattern: v.ISO_TIME_SECOND_REGEX.source, }); expect( convertAction({ type: 'string' }, v.isoTimeSecond(), undefined) ).toStrictEqual({ type: 'string', pattern: v.ISO_TIME_SECOND_REGEX.source, }); }); test('should convert iso week action', () => { expect(convertAction({}, v.isoWeek(), undefined)).toStrictEqual({ pattern: v.ISO_WEEK_REGEX.source, }); expect( convertAction({ type: 'string' }, v.isoWeek(), undefined) ).toStrictEqual({ type: 'string', pattern: v.ISO_WEEK_REGEX.source, }); }); test('should convert mac action', () => { expect(convertAction({}, v.mac(), undefined)).toStrictEqual({ pattern: v.MAC_REGEX.source, }); expect( convertAction({ type: 'string' }, v.mac(), undefined) ).toStrictEqual({ type: 'string', pattern: v.MAC_REGEX.source, }); }); test('should convert mac48 action', () => { expect(convertAction({}, v.mac48(), undefined)).toStrictEqual({ pattern: v.MAC48_REGEX.source, }); expect( convertAction({ type: 'string' }, v.mac48(), undefined) ).toStrictEqual({ type: 'string', pattern: v.MAC48_REGEX.source, }); }); test('should convert mac64 action', () => { expect(convertAction({}, v.mac64(), undefined)).toStrictEqual({ pattern: v.MAC64_REGEX.source, }); expect( convertAction({ type: 'string' }, v.mac64(), undefined) ).toStrictEqual({ type: 'string', pattern: v.MAC64_REGEX.source, }); }); test('should convert Nano ID action', () => { expect(convertAction({}, v.nanoid(), undefined)).toStrictEqual({ pattern: v.NANO_ID_REGEX.source, }); expect( convertAction({ type: 'string' }, v.nanoid(), undefined) ).toStrictEqual({ type: 'string', pattern: v.NANO_ID_REGEX.source, }); }); test('should convert octal action', () => { expect(convertAction({}, v.octal(), undefined)).toStrictEqual({ pattern: v.OCTAL_REGEX.source, }); expect( convertAction({ type: 'string' }, v.octal(), undefined) ).toStrictEqual({ type: 'string', pattern: v.OCTAL_REGEX.source, }); }); test('should convert slug action', () => { expect(convertAction({}, v.slug(), undefined)).toStrictEqual({ pattern: v.SLUG_REGEX.source, }); expect( convertAction({ type: 'string' }, v.slug(), undefined) ).toStrictEqual({ type: 'string', pattern: v.SLUG_REGEX.source, }); }); test('should convert ULID action', () => { expect(convertAction({}, v.ulid(), undefined)).toStrictEqual({ pattern: v.ULID_REGEX.source, }); expect( convertAction({ type: 'string' }, v.ulid(), undefined) ).toStrictEqual({ type: 'string', pattern: v.ULID_REGEX.source, }); }); test('should convert description action', () => { expect(convertAction({}, v.description('test'), undefined)).toStrictEqual({ description: 'test', }); }); test('should convert email action', () => { expect(convertAction({}, v.email(), undefined)).toStrictEqual({ format: 'email', }); expect( convertAction({ type: 'string' }, v.email(), undefined) ).toStrictEqual({ type: 'string', format: 'email', }); }); test('should convert rfc email action', () => { expect(convertAction({}, v.rfcEmail(), undefined)).toStrictEqual({ format: 'email', }); expect( convertAction({ type: 'string' }, v.rfcEmail(), undefined) ).toStrictEqual({ type: 'string', format: 'email', }); }); test('should convert ends with action', () => { expect( convertAction( { type: 'string' }, v.endsWith('foo'), undefined ) ).toStrictEqual({ type: 'string', pattern: 'foo$', }); }); test('should convert ends with action with special characters', () => { expect( convertAction( { type: 'string' }, v.endsWith('.com'), undefined ) ).toStrictEqual({ type: 'string', pattern: '\\.com$', }); }); test('should throw error for pattern action with existing pattern', () => { const jsonSchema = convertAction( { type: 'string' }, v.startsWith('pre'), undefined ); const error = 'The "ends_with" action is not supported in combination with another regex action.'; expect(() => convertAction(jsonSchema, v.endsWith('suf'), undefined) ).toThrowError(error); }); test('should convert empty action for strings', () => { expect( convertAction({ type: 'string' }, v.empty(), undefined) ).toStrictEqual({ type: 'string', maxLength: 0, }); }); test('should convert empty action for arrays', () => { expect( convertAction({ type: 'array' }, v.empty(), undefined) ).toStrictEqual({ type: 'array', maxItems: 0, }); }); test('should throw error for empty action with invalid type', () => { const action = v.empty(); const error1 = 'The "empty" action is not supported on type "undefined".'; expect(() => convertAction({}, action, undefined)).toThrowError(error1); expect(() => convertAction({}, action, { errorMode: 'throw' }) ).toThrowError(error1); const error2 = 'The "empty" action is not supported on type "object".'; expect(() => convertAction({ type: 'object' }, action, undefined) ).toThrowError(error2); expect(() => convertAction({ type: 'object' }, action, { errorMode: 'throw' }) ).toThrowError(error2); }); test('should warn error for empty action with invalid type', () => { expect(convertAction({}, v.empty(), { errorMode: 'warn' })).toStrictEqual({ maxLength: 0, }); expect(console.warn).toHaveBeenLastCalledWith( 'The "empty" action is not supported on type "undefined".' ); expect( convertAction({ type: 'object' }, v.empty(), { errorMode: 'warn', }) ).toStrictEqual({ type: 'object', maxLength: 0 }); expect(console.warn).toHaveBeenLastCalledWith( 'The "empty" action is not supported on type "object".' ); }); test('should convert entries action', () => { expect( convertAction( { type: 'object' }, v.entries(3), undefined ) ).toStrictEqual({ type: 'object', minProperties: 3, maxProperties: 3, }); }); test('should convert examples action', () => { expect( convertAction({}, v.examples(['foo', 'bar']), undefined) ).toStrictEqual({ examples: ['foo', 'bar'], }); expect( convertAction( { examples: ['baz'] }, v.examples(['foo', 'bar']), undefined ) ).toStrictEqual({ examples: ['baz', 'foo', 'bar'], }); }); test('should merge examples from multiple actions', () => { const jsonSchema = {}; convertAction(jsonSchema, v.examples(['foo']), undefined); convertAction(jsonSchema, v.metadata({ examples: ['bar'] }), undefined); expect(jsonSchema).toStrictEqual({ examples: ['foo', 'bar'], }); }); test('should convert gt value action for numbers', () => { expect( convertAction( { type: 'number' }, v.gtValue(3), undefined ) ).toStrictEqual({ type: 'number', exclusiveMinimum: 3, }); }); test('should convert gt value action for integers', () => { expect( convertAction( { type: 'integer' }, v.gtValue(0), undefined ) ).toStrictEqual({ type: 'integer', exclusiveMinimum: 0, }); }); test('should throw error for gt value action with invalid type', () => { const action = v.gtValue(3); const error1 = 'The "gt_value" action is not supported on type "undefined".'; expect(() => convertAction({}, action, undefined)).toThrowError(error1); const error2 = 'The "gt_value" action is not supported on type "string".'; expect(() => convertAction({ type: 'string' }, action, undefined) ).toThrowError(error2); }); test('should throw error for gt value action with openapi-3.0', () => { const error = 'The "gt_value" action is not supported for OpenAPI 3.0.'; expect(() => convertAction({ type: 'number' }, v.gtValue(3), { target: 'openapi-3.0', }) ).toThrowError(error); }); test('should convert includes action', () => { expect( convertAction( { type: 'string' }, v.includes('foo'), undefined ) ).toStrictEqual({ type: 'string', pattern: 'foo', }); }); test('should convert includes action with special characters', () => { expect( convertAction( { type: 'string' }, v.includes('foo.bar'), undefined ) ).toStrictEqual({ type: 'string', pattern: 'foo\\.bar', }); }); test('should warn error for pattern action with existing pattern', () => { expect( convertAction( { type: 'string', pattern: '^pre' }, v.includes('foo'), { errorMode: 'warn' } ) ).toStrictEqual({ type: 'string', pattern: '^pre', }); expect(console.warn).toHaveBeenLastCalledWith( 'The "includes" action is not supported in combination with another regex action.' ); }); test('should convert integer action', () => { expect(convertAction({}, v.integer(), undefined)).toStrictEqual({ type: 'integer', }); expect( convertAction({ type: 'number' }, v.integer(), undefined) ).toStrictEqual({ type: 'integer', }); }); test('should convert IPv4 action', () => { expect(convertAction({}, v.ipv4(), undefined)).toStrictEqual({ format: 'ipv4', }); expect( convertAction({ type: 'string' }, v.ipv4(), undefined) ).toStrictEqual({ type: 'string', format: 'ipv4', }); }); test('should convert IPv6 action', () => { expect(convertAction({}, v.ipv6(), undefined)).toStrictEqual({ format: 'ipv6', }); expect( convertAction({ type: 'string' }, v.ipv6(), undefined) ).toStrictEqual({ type: 'string', format: 'ipv6', }); }); test('should convert ISO date action', () => { expect(convertAction({}, v.isoDate(), undefined)).toStrictEqual({ format: 'date', }); expect( convertAction({ type: 'string' }, v.isoDate(), undefined) ).toStrictEqual({ type: 'string', format: 'date', }); }); test('should convert ISO date time action', () => { expect(convertAction({}, v.isoDateTime(), undefined)).toStrictEqual( { format: 'date-time', } ); expect( convertAction({ type: 'string' }, v.isoDateTime(), undefined) ).toStrictEqual({ type: 'string', format: 'date-time', }); }); test('should convert ISO timestamp action', () => { expect( convertAction({}, v.isoTimestamp(), undefined) ).toStrictEqual({ format: 'date-time', }); expect( convertAction({ type: 'string' }, v.isoTimestamp(), undefined) ).toStrictEqual({ type: 'string', format: 'date-time', }); }); test('should convert ISO time action', () => { expect(convertAction({}, v.isoTime(), undefined)).toStrictEqual({ format: 'time', }); expect( convertAction({ type: 'string' }, v.isoTime(), undefined) ).toStrictEqual({ type: 'string', format: 'time', }); }); test('should convert jwsCompact action', () => { expect(convertAction({}, v.jwsCompact(), undefined)).toStrictEqual({ pattern: v.JWS_COMPACT_REGEX.source, }); expect( convertAction({ type: 'string' }, v.jwsCompact(), undefined) ).toStrictEqual({ type: 'string', pattern: v.JWS_COMPACT_REGEX.source, }); }); test('should convert length action for strings', () => { expect( convertAction( { type: 'string' }, v.length(3), undefined ) ).toStrictEqual({ type: 'string', minLength: 3, maxLength: 3, }); }); test('should convert length action for arrays', () => { expect( convertAction({ type: 'array' }, v.length(3), undefined) ).toStrictEqual({ type: 'array', minItems: 3, maxItems: 3, }); }); test('should throw error for length action with invalid type', () => { const action = v.length(3); const error1 = 'The "length" action is not supported on type "undefined".'; expect(() => convertAction({}, action, undefined)).toThrowError(error1); expect(() => convertAction({}, action, { errorMode: 'throw' }) ).toThrowError(error1); const error2 = 'The "length" action is not supported on type "object".'; expect(() => convertAction({ type: 'object' }, action, undefined) ).toThrowError(error2); expect(() => convertAction({ type: 'object' }, action, { errorMode: 'throw' }) ).toThrowError(error2); }); test('should warn error for length action with invalid type', () => { expect( convertAction({}, v.length(3), { errorMode: 'warn' }) ).toStrictEqual({ minLength: 3, maxLength: 3, }); expect(console.warn).toHaveBeenLastCalledWith( 'The "length" action is not supported on type "undefined".' ); expect( convertAction({ type: 'object' }, v.length(3), { errorMode: 'warn', }) ).toStrictEqual({ type: 'object', minLength: 3, maxLength: 3 }); expect(console.warn).toHaveBeenLastCalledWith( 'The "length" action is not supported on type "object".' ); }); test('should convert lt value action for numbers', () => { expect( convertAction( { type: 'number' }, v.ltValue(10), undefined ) ).toStrictEqual({ type: 'number', exclusiveMaximum: 10, }); }); test('should convert lt value action for integers', () => { expect( convertAction( { type: 'integer' }, v.ltValue(100), undefined ) ).toStrictEqual({ type: 'integer', exclusiveMaximum: 100, }); }); test('should throw error for lt value action with invalid type', () => { const action = v.ltValue(10); const error1 = 'The "lt_value" action is not supported on type "undefined".'; expect(() => convertAction({}, action, undefined)).toThrowError(error1); const error2 = 'The "lt_value" action is not supported on type "string".'; expect(() => convertAction({ type: 'string' }, action, undefined) ).toThrowError(error2); }); test('should throw error for lt value action with openapi-3.0', () => { const error = 'The "lt_value" action is not supported for OpenAPI 3.0.'; expect(() => convertAction({ type: 'number' }, v.ltValue(10), { target: 'openapi-3.0', }) ).toThrowError(error); }); test('should convert max entries action', () => { expect( convertAction( { type: 'object' }, v.maxEntries(3), undefined ) ).toStrictEqual({ type: 'object', maxProperties: 3, }); }); test('should convert max length action for strings', () => { expect( convertAction( { type: 'string' }, v.maxLength(3), undefined ) ).toStrictEqual({ type: 'string', maxLength: 3, }); }); test('should convert max length action for arrays', () => { expect( convertAction( { type: 'array' }, v.maxLength(3), undefined ) ).toStrictEqual({ type: 'array', maxItems: 3, }); }); test('should throw error for max length action with invalid type', () => { const action = v.maxLength(3); const error1 = 'The "max_length" action is not supported on type "undefined".'; expect(() => convertAction({}, action, undefined)).toThrowError(error1); expect(() => convertAction({}, action, { errorMode: 'throw' }) ).toThrowError(error1); const error2 = 'The "max_length" action is not supported on type "object".'; expect(() => convertAction({ type: 'object' }, action, undefined) ).toThrowError(error2); expect(() => convertAction({ type: 'object' }, action, { errorMode: 'throw' }) ).toThrowError(error2); }); test('should warn error for max length action with invalid type', () => { expect( convertAction({}, v.maxLength(3), { errorMode: 'warn' }) ).toStrictEqual({ maxLength: 3, }); expect(console.warn).toHaveBeenLastCalledWith( 'The "max_length" action is not supported on type "undefined".' ); expect( convertAction({ type: 'object' }, v.maxLength(3), { errorMode: 'warn', }) ).toStrictEqual({ type: 'object', maxLength: 3 }); expect(console.warn).toHaveBeenLastCalledWith( 'The "max_length" action is not supported on type "object".' ); }); test('should convert max value action for numbers', () => { expect( convertAction( { type: 'number' }, v.maxValue(3), undefined ) ).toStrictEqual({ type: 'number', maximum: 3, }); }); test('should convert max value action for integers', () => { expect( convertAction( { type: 'integer' }, v.maxValue(100), undefined ) ).toStrictEqual({ type: 'integer', maximum: 100, }); }); test('should throw error for max value action with invalid type', () => { const action = v.maxValue(3); const error1 = 'The "max_value" action is not supported on type "undefined".'; expect(() => convertAction({}, action, undefined)).toThrowError(error1); expect(() => convertAction({}, action, { errorMode: 'throw' }) ).toThrowError(error1); const error2 = 'The "max_value" action is not supported on type "string".'; expect(() => convertAction({ type: 'string' }, action, undefined) ).toThrowError(error2); expect(() => convertAction({ type: 'string' }, action, { errorMode: 'throw' }) ).toThrowError(error2); }); test('should warn error for max value action with invalid type', () => { expect( convertAction({}, v.maxValue(3), { errorMode: 'warn' }) ).toStrictEqual({ maximum: 3, }); expect(console.warn).toHaveBeenLastCalledWith( 'The "max_value" action is not supported on type "undefined".' ); expect( convertAction({ type: 'string' }, v.maxValue(3), { errorMode: 'warn', }) ).toStrictEqual({ type: 'string', maximum: 3 }); expect(console.warn).toHaveBeenLastCalledWith( 'The "max_value" action is not supported on type "string".' ); }); test('should convert metadata action', () => { expect( convertAction( {}, v.metadata({ title: 'title', description: 'description', examples: ['example'], other: 'other', }), undefined ) ).toStrictEqual({ title: 'title', description: 'description', examples: ['example'], }); expect( convertAction( { examples: ['existing'] }, v.metadata({ examples: ['new'], }), undefined ) ).toStrictEqual({ examples: ['existing', 'new'], }); }); test('should skip invalid metadata properties', () => { expect( convertAction( {}, v.metadata({ title: 123, description: null, examples: { foo: 'bar' }, other: 'other', }), undefined ) ).toStrictEqual({}); }); test('should convert min entries action', () => { expect( convertAction( { type: 'object' }, v.minEntries(3), undefined ) ).toStrictEqual({ type: 'object', minProperties: 3, }); }); test('should convert min length action for strings', () => { expect( convertAction( { type: 'string' }, v.minLength(3), undefined ) ).toStrictEqual({ type: 'string', minLength: 3, }); }); test('should convert min length action for arrays', () => { expect( convertAction( { type: 'array' }, v.minLength(3), undefined ) ).toStrictEqual({ type: 'array', minItems: 3, }); }); test('should throw error for min length action with invalid type', () => { const action = v.minLength(3); const error1 = 'The "min_length" action is not supported on type "undefined".'; expect(() => convertAction({}, action, undefined)).toThrowError(error1); expect(() => convertAction({}, action, { errorMode: 'throw' }) ).toThrowError(error1); const error2 = 'The "min_length" action is not supported on type "object".'; expect(() => convertAction({ type: 'object' }, action, undefined) ).toThrowError(error2); expect(() => convertAction({ type: 'object' }, action, { errorMode: 'throw' }) ).toThrowError(error2); }); test('should warn error for min length action with invalid type', () => { expect( convertAction({}, v.minLength(3), { errorMode: 'warn' }) ).toStrictEqual({ minLength: 3, }); expect(console.warn).toHaveBeenLastCalledWith( 'The "min_length" action is not supported on type "undefined".' ); expect( convertAction({ type: 'object' }, v.minLength(3), { errorMode: 'warn', }) ).toStrictEqual({ type: 'object', minLength: 3 }); expect(console.warn).toHaveBeenLastCalledWith( 'The "min_length" action is not supported on type "object".' ); }); test('should convert min value action for numbers', () => { expect( convertAction( { type: 'number' }, v.minValue(3), undefined ) ).toStrictEqual({ type: 'number', minimum: 3, }); }); test('should convert min value action for integers', () => { expect( convertAction( { type: 'integer' }, v.minValue(1), undefined ) ).toStrictEqual({ type: 'integer', minimum: 1, }); }); test('should throw error for min value action with invalid type', () => { const action = v.minValue(3); const error1 = 'The "min_value" action is not supported on type "undefined".'; expect(() => convertAction({}, action, undefined)).toThrowError(error1); expect(() => convertAction({}, action, { errorMode: 'throw' }) ).toThrowError(error1); const error2 = 'The "min_value" action is not supported on type "string".'; expect(() => convertAction({ type: 'string' }, action, undefined) ).toThrowError(error2); expect(() => convertAction({ type: 'string' }, action, { errorMode: 'throw' }) ).toThrowError(error2); }); test('should warn error for min value action with invalid type', () => { expect( convertAction({}, v.minValue(3), { errorMode: 'warn' }) ).toStrictEqual({ minimum: 3, }); expect(console.warn).toHaveBeenLastCalledWith( 'The "min_value" action is not supported on type "undefined".' ); expect( convertAction({ type: 'string' }, v.minValue(3), { errorMode: 'warn', }) ).toStrictEqual({ type: 'string', minimum: 3 }); expect(console.warn).toHaveBeenLastCalledWith( 'The "min_value" action is not supported on type "string".' ); }); test('should convert multiple of action', () => { expect( convertAction({}, v.multipleOf(5), undefined) ).toStrictEqual({ multipleOf: 5, }); expect( convertAction({ type: 'number' }, v.multipleOf(5), undefined) ).toStrictEqual({ type: 'number', multipleOf: 5, }); }); test('should convert non empty action for strings', () => { expect( convertAction({ type: 'string' }, v.nonEmpty(), undefined) ).toStrictEqual({ type: 'string', minLength: 1, }); }); test('should convert non empty action for arrays', () => { expect( convertAction({ type: 'array' }, v.nonEmpty(), undefined) ).toStrictEqual({ type: 'array', minItems: 1, }); }); test('should throw error for non empty action with invalid type', () => { const action = v.nonEmpty(); const error1 = 'The "non_empty" action is not supported on type "undefined".'; expect(() => convertAction({}, action, undefined)).toThrowError(error1); expect(() => convertAction({}, action, { errorMode: 'throw' }) ).toThrowError(error1); const error2 = 'The "non_empty" action is not supported on type "object".'; expect(() => convertAction({ type: 'object' }, action, undefined) ).toThrowError(error2); expect(() => convertAction({ type: 'object' }, action, { errorMode: 'throw' }) ).toThrowError(error2); }); test('should warn error for non empty action with invalid type', () => { expect( convertAction({}, v.nonEmpty(), { errorMode: 'warn' }) ).toStrictEqual({ minLength: 1, }); expect(console.warn).toHaveBeenLastCalledWith( 'The "non_empty" action is not supported on type "undefined".' ); expect( convertAction({ type: 'object' }, v.nonEmpty(), { errorMode: 'warn', }) ).toStrictEqual({ type: 'object', minLength: 1 }); expect(console.warn).toHaveBeenLastCalledWith( 'The "non_empty" action is not supported on type "object".' ); }); test('should convert not value action', () => { expect( convertAction( { type: 'number' }, v.notValue(0), undefined ) ).toStrictEqual({ type: 'number', not: { const: 0 }, }); }); test('should convert not value action for openapi-3.0', () => { expect( convertAction({ type: 'number' }, v.notValue(0), { target: 'openapi-3.0', }) ).toStrictEqual({ type: 'number', not: { enum: [0] }, }); }); test('should convert not values action', () => { expect( convertAction( { type: 'number' }, v.notValues([0, 1]), undefined ) ).toStrictEqual({ type: 'number', not: { enum: [0, 1] }, }); }); test('should throw error for unsupported not value action', () => { const error = 'The requirement of the "not_value" action is not JSON compatible.'; expect(() => convertAction({}, v.notValue(1n), undefined) ).toThrowError(error); expect(() => convertAction({}, v.notValue(new Date(0)), { errorMode: 'throw', }) ).toThrowError(error); }); test('should warn error for unsupported not value action', () => { expect( convertAction({ type: 'number' }, v.notValue(1n), { errorMode: 'warn', }) ).toStrictEqual({ type: 'number', }); expect(console.warn).toHaveBeenLastCalledWith( 'The requirement of the "not_value" action is not JSON compatible.' ); }); test('should throw error for unsupported not values action', () => { const error = 'A requirement of the "not_values" action is not JSON compatible.'; expect(() => convertAction({}, v.notValues([1n]), undefined) ).toThrowError(error); expect(() => convertAction( {}, v.notValues([new Date(0), new Date(1)]), { errorMode: 'throw' } ) ).toThrowError(error); }); test('should warn error for unsupported not values action', () => { expect( convertAction({ type: 'number' }, v.notValues([1n]), { errorMode: 'warn', }) ).toStrictEqual({ type: 'number', }); expect(console.warn).toHaveBeenLastCalledWith( 'A requirement of the "not_values" action is not JSON compatible.' ); }); test('should convert supported regex action', () => { expect( convertAction({ type: 'string' }, v.regex(/[a-zA-Z]/), undefined) ).toStrictEqual({ type: 'string', pattern: '[a-zA-Z]', }); }); test('should throw error for unsupported regex action', () => { const action = v.regex(/[a-z]/im); const error = 'RegExp flags are not supported by JSON Schema.'; expect(() => convertAction({}, action, undefined)).toThrowError(error); expect(() => convertAction({}, action, { errorMode: 'throw' }) ).toThrowError(error); }); test('should warn error for unsupported regex action', () => { expect( convertAction({ type: 'string' }, v.regex(/[a-z]/im), { errorMode: 'warn', }) ).toStrictEqual({ type: 'string', pattern: '[a-z]', }); expect(console.warn).toHaveBeenLastCalledWith( 'RegExp flags are not supported by JSON Schema.' ); }); test('should convert safe integer action', () => { expect( convertAction({ type: 'number' }, v.safeInteger(), undefined) ).toStrictEqual({ type: 'integer', minimum: Number.MIN_SAFE_INTEGER, maximum: Number.MAX_SAFE_INTEGER, }); }); test('should preserve stricter safe integer bounds', () => { expect( convertAction( { type: 'number', minimum: 10, maximum: 20 }, v.safeInteger(), undefined ) ).toStrictEqual({ type: 'integer', minimum: 10, maximum: 20, }); expect( convertAction( { type: 'number', exclusiveMinimum: 10, exclusiveMaximum: 20, }, v.safeInteger(), undefined ) ).toStrictEqual({ type: 'integer', minimum: Number.MIN_SAFE_INTEGER, maximum: Number.MAX_SAFE_INTEGER, exclusiveMinimum: 10, exclusiveMaximum: 20, }); }); test('should clamp broader safe integer bounds', () => { expect( convertAction( { type: 'number', minimum: Number.MIN_SAFE_INTEGER - 1, maximum: Number.MAX_SAFE_INTEGER + 1, }, v.safeInteger(), undefined ) ).toStrictEqual({ type: 'integer', minimum: Number.MIN_SAFE_INTEGER, maximum: Number.MAX_SAFE_INTEGER, }); }); test('should convert starts with action', () => { expect( convertAction( { type: 'string' }, v.startsWith('foo'), undefined ) ).toStrictEqual({ type: 'string', pattern: '^foo', }); }); test('should convert starts with action with special characters', () => { expect( convertAction( { type: 'string' }, v.startsWith('https://'), undefined ) ).toStrictEqual({ type: 'string', pattern: '^https://', }); }); test('should convert title action', () => { expect(convertAction({}, v.title('test'), undefined)).toStrictEqual({ title: 'test', }); }); test('should convert url action', () => { expect(convertAction({}, v.url(), undefined)).toStrictEqual({ format: 'uri', }); expect( convertAction({ type: 'string' }, v.url(), undefined) ).toStrictEqual({ type: 'string', format: 'uri', }); }); test('should convert UUID action', () => { expect(convertAction({}, v.uuid(), undefined)).toStrictEqual({ format: 'uuid', }); expect( convertAction({ type: 'string' }, v.uuid(), undefined) ).toStrictEqual({ type: 'string', format: 'uuid', }); }); test('should convert value action', () => { expect( convertAction( { type: 'boolean' }, v.value(true), undefined ) ).toStrictEqual({ type: 'boolean', const: true, }); expect( convertAction( { type: 'number' }, v.value(123), undefined ) ).toStrictEqual({ type: 'number', const: 123, }); expect( convertAction( { type: 'string' }, v.value('foo'), undefined ) ).toStrictEqual({ type: 'string', const: 'foo', }); }); test('should convert value action for openapi-3.0', () => { expect( convertAction({ type: 'string' }, v.value('foo'), { target: 'openapi-3.0', }) ).toStrictEqual({ type: 'string', enum: ['foo'], }); }); test('should throw error for unsupported value action', () => { const error = 'The requirement of the "value" action is not JSON compatible.'; expect(() => convertAction({}, v.value(1n), undefined) ).toThrowError(error); expect(() => convertAction({}, v.value(new Date(0)), { errorMode: 'throw', }) ).toThrowError(error); expect(() => convertAction( { type: 'number' }, v.value(NaN), undefined ) ).toThrowError(error); expect(() => convertAction( { type: 'number' }, v.value(Infinity), undefined ) ).toThrowError(error); }); test('should warn error for unsupported value action', () => { expect( convertAction({ type: 'number' }, v.value(1n), { errorMode: 'warn', }) ).toStrictEqual({ type: 'number', }); expect(console.warn).toHaveBeenLastCalledWith( 'The requirement of the "value" action is not JSON compatible.' ); }); test('should convert values action', () => { expect( convertAction( { type: 'number' }, v.values([1, 2, 3]), undefined ) ).toStrictEqual({ type: 'number', enum: [1, 2, 3], }); expect( convertAction( { type: 'string' }, v.values(['foo', 'bar']), undefined ) ).toStrictEqual({ type: 'string', enum: ['foo', 'bar'], }); expect( convertAction( { type: 'boolean' }, v.values([true, false]), undefined ) ).toStrictEqual({ type: 'boolean', enum: [true, false], }); }); test('should throw error for unsupported values action', () => { const error = 'A requirement of the "values" action is not JSON compatible.'; expect(() => convertAction({}, v.values([1n]), undefined) ).toThrowError(error); expect(() => convertAction( {}, v.values(['foo', new Date(0)]), { errorMode: 'throw' } ) ).toThrowError(error); }); test('should warn error for unsupported values action', () => { expect( convertAction({ type: 'number' }, v.values([1n]), { errorMode: 'warn', }) ).toStrictEqual({ type: 'number', }); expect(console.warn).toHaveBeenLastCalledWith( 'A requirement of the "values" action is not JSON compatible.' ); }); test('should throw error for unsupported transform action', () => { const action = v.transform(parseInt); const error = 'The "transform" action cannot be converted to JSON Schema.'; expect(() => convertAction({}, action as never, undefined)).toThrowError( error ); expect(() => convertAction({}, action as never, { errorMode: 'throw' }) ).toThrowError(error); }); test('should warn error for unsupported transform action', () => { expect( convertAction({}, v.transform(parseInt) as never, { errorMode: 'warn' }) ).toStrictEqual({}); expect(console.warn).toHaveBeenLastCalledWith( 'The "transform" action cannot be converted to JSON Schema.' ); expect( convertAction({ type: 'string' }, v.transform(parseInt) as never, { errorMode: 'warn', }) ).toStrictEqual({ type: 'string' }); expect(console.warn).toHaveBeenLastCalledWith( 'The "transform" action cannot be converted to JSON Schema.' ); }); test('should override JSON Schema output of action', () => { expect( convertAction({}, v.decimal(), { overrideAction({ valibotAction }) { if (valibotAction.type === 'decimal') { return { format: 'decimal' }; } }, }) ).toStrictEqual({ format: 'decimal', }); expect( convertAction({ type: 'string' }, v.decimal(), { overrideAction({ valibotAction, jsonSchema }) { if (valibotAction.type === 'decimal') { return { ...jsonSchema, format: 'decimal' }; } }, }) ).toStrictEqual({ type: 'string', pattern: v.DECIMAL_REGEX.source, format: 'decimal', }); }); test('should override action to suppress error', () => { expect( convertAction({}, v.transform(parseInt) as never, { overrideAction({ valibotAction, jsonSchema }) { if (valibotAction.type === 'transform') { return jsonSchema; } }, }) ).toStrictEqual({}); }); }); ================================================ FILE: packages/to-json-schema/src/converters/convertAction/convertAction.ts ================================================ import type * as v from 'valibot'; import type { ConversionConfig, JsonSchema } from '../../types/index.ts'; import { addError, escapeRegExp, handleError, isJsonConstValue, isJsonEnumValues, } from '../../utils/index.ts'; /** * Action type. */ type Action = | v.Base64Action> | undefined> | v.BicAction> | undefined> | v.Cuid2Action> | undefined> | v.DecimalAction> | undefined> | v.DescriptionAction | v.DigitsAction> | undefined> | v.DomainAction> | undefined> | v.EmailAction> | undefined> | v.EmojiAction> | undefined> | v.EmptyAction< v.LengthInput, v.ErrorMessage> | undefined > | v.EndsWithAction< string, string, v.ErrorMessage> | undefined > | v.EntriesAction< v.EntriesInput, number, v.ErrorMessage> | undefined > | v.ExamplesAction | v.GtValueAction< v.ValueInput, v.ValueInput, v.ErrorMessage> | undefined > | v.HashAction> | undefined> | v.HexadecimalAction< string, v.ErrorMessage> | undefined > | v.HexColorAction< string, v.ErrorMessage> | undefined > | v.IncludesAction< string, string, v.ErrorMessage> | undefined > | v.IntegerAction> | undefined> | v.Ipv4Action> | undefined> | v.Ipv6Action> | undefined> | v.IsoDateAction> | undefined> | v.IsoDateTimeAction< string, v.ErrorMessage> | undefined > | v.IsoTimeAction> | undefined> | v.IsoTimeSecondAction< string, v.ErrorMessage> | undefined > | v.IsoTimestampAction< string, v.ErrorMessage> | undefined > | v.IsoWeekAction> | undefined> | v.IsrcAction> | undefined> | v.JwsCompactAction< string, v.ErrorMessage> | undefined > | v.LengthAction< v.LengthInput, number, v.ErrorMessage> | undefined > | v.LtValueAction< v.ValueInput, v.ValueInput, v.ErrorMessage> | undefined > | v.MacAction> | undefined> | v.Mac48Action> | undefined> | v.Mac64Action> | undefined> | v.MaxEntriesAction< v.EntriesInput, number, v.ErrorMessage> | undefined > | v.MaxLengthAction< v.LengthInput, number, v.ErrorMessage> | undefined > | v.MaxValueAction< v.ValueInput, v.ValueInput, v.ErrorMessage> | undefined > | v.MetadataAction> | v.MinEntriesAction< v.EntriesInput, number, v.ErrorMessage> | undefined > | v.MinLengthAction< v.LengthInput, number, v.ErrorMessage> | undefined > | v.MinValueAction< v.ValueInput, v.ValueInput, v.ErrorMessage> | undefined > | v.MultipleOfAction< number, number, v.ErrorMessage> | undefined > | v.NanoIdAction> | undefined> | v.NonEmptyAction< v.LengthInput, v.ErrorMessage> | undefined > | v.NotValueAction< v.ValueInput, v.ValueInput, v.ErrorMessage> | undefined > | v.NotValuesAction< v.ValueInput, v.ValueInput[], v.ErrorMessage> | undefined > | v.OctalAction> | undefined> | v.RegexAction> | undefined> | v.RfcEmailAction< string, v.ErrorMessage> | undefined > | v.SafeIntegerAction< number, v.ErrorMessage> | undefined > | v.SlugAction> | undefined> | v.StartsWithAction< string, string, v.ErrorMessage> | undefined > | v.TitleAction | v.UlidAction> | undefined> | v.UrlAction> | undefined> | v.UuidAction> | undefined> | v.ValueAction< v.ValueInput, v.ValueInput, v.ErrorMessage> | undefined > | v.ValuesAction< v.ValueInput, v.ValueInput[], v.ErrorMessage> | undefined >; /** * 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. */ export function convertAction( jsonSchema: JsonSchema, valibotAction: Action, config: ConversionConfig | undefined ): JsonSchema { // Ignore action if specified in configuration if (config?.ignoreActions?.includes(valibotAction.type)) { return jsonSchema; } // Create errors variable let errors: [string, ...string[]] | undefined; // Convert Valibot action to JSON Schema switch (valibotAction.type) { case 'base64': { jsonSchema.contentEncoding = 'base64'; break; } case 'bic': case 'cuid2': case 'decimal': case 'digits': case 'domain': case 'emoji': case 'hash': case 'hexadecimal': case 'hex_color': case 'isrc': case 'iso_time_second': case 'iso_week': case 'mac': case 'mac48': case 'mac64': case 'nanoid': case 'octal': case 'slug': case 'ulid': { if (jsonSchema.pattern) { errors = addError( errors, `The "${valibotAction.type}" action is not supported in combination with another regex action.` ); } else { jsonSchema.pattern = valibotAction.requirement.source; } break; } case 'description': { jsonSchema.description = valibotAction.description; break; } case 'email': case 'rfc_email': { jsonSchema.format = 'email'; break; } case 'ends_with': { if (jsonSchema.pattern) { errors = addError( errors, `The "${valibotAction.type}" action is not supported in combination with another regex action.` ); } else { jsonSchema.pattern = `${escapeRegExp(valibotAction.requirement)}$`; } 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)) { // @ts-expect-error jsonSchema.examples = [ ...jsonSchema.examples, ...valibotAction.examples, ]; } else { // @ts-expect-error jsonSchema.examples = valibotAction.examples; } break; } case 'gt_value': { if (jsonSchema.type !== 'number' && jsonSchema.type !== 'integer') { errors = addError( errors, `The "gt_value" action is not supported on type "${jsonSchema.type}".` ); } if (config?.target === 'openapi-3.0') { errors = addError( errors, 'The "gt_value" action is not supported for OpenAPI 3.0.' ); break; } jsonSchema.exclusiveMinimum = valibotAction.requirement as number; break; } case 'includes': { if (jsonSchema.pattern) { errors = addError( errors, `The "${valibotAction.type}" action is not supported in combination with another regex action.` ); } else { jsonSchema.pattern = escapeRegExp(valibotAction.requirement); } 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 'jws_compact': { if (jsonSchema.pattern) { errors = addError( errors, `The "${valibotAction.type}" action is not supported in combination with another regex action.` ); } else { jsonSchema.pattern = valibotAction.requirement.source; } 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 'lt_value': { if (jsonSchema.type !== 'number' && jsonSchema.type !== 'integer') { errors = addError( errors, `The "lt_value" action is not supported on type "${jsonSchema.type}".` ); } if (config?.target === 'openapi-3.0') { errors = addError( errors, 'The "lt_value" action is not supported for OpenAPI 3.0.' ); break; } jsonSchema.exclusiveMaximum = valibotAction.requirement as number; 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 as number; 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 as number; 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 'not_value': { if (!isJsonConstValue(valibotAction.requirement)) { errors = addError( errors, 'The requirement of the "not_value" action is not JSON compatible.' ); break; } if (config?.target === 'openapi-3.0') { jsonSchema.not = { enum: [valibotAction.requirement] }; } else { jsonSchema.not = { const: valibotAction.requirement }; } break; } case 'not_values': { if (!isJsonEnumValues(valibotAction.requirement)) { errors = addError( errors, 'A requirement of the "not_values" action is not JSON compatible.' ); break; } jsonSchema.not = { enum: valibotAction.requirement }; break; } case 'regex': { if (valibotAction.requirement.flags) { errors = addError( errors, 'RegExp flags are not supported by JSON Schema.' ); } if (jsonSchema.pattern) { errors = addError( errors, `The "${valibotAction.type}" action is not supported in combination with another regex action.` ); } else { jsonSchema.pattern = valibotAction.requirement.source; } break; } case 'safe_integer': { jsonSchema.type = 'integer'; if ( typeof jsonSchema.minimum !== 'number' || jsonSchema.minimum < Number.MIN_SAFE_INTEGER ) { jsonSchema.minimum = Number.MIN_SAFE_INTEGER; } if ( typeof jsonSchema.maximum !== 'number' || jsonSchema.maximum > Number.MAX_SAFE_INTEGER ) { jsonSchema.maximum = Number.MAX_SAFE_INTEGER; } break; } case 'starts_with': { if (jsonSchema.pattern) { errors = addError( errors, `The "${valibotAction.type}" action is not supported in combination with another regex action.` ); } else { jsonSchema.pattern = `^${escapeRegExp(valibotAction.requirement)}`; } break; } case 'title': { jsonSchema.title = valibotAction.title; break; } case 'url': { jsonSchema.format = 'uri'; break; } case 'uuid': { jsonSchema.format = 'uuid'; break; } case 'value': { // Hint: It is not necessary to validate the type of the JSON schema or // Valibot action requirement, as this action can only follow a valid // schema in the pipeline anyway. if (!isJsonConstValue(valibotAction.requirement)) { errors = addError( errors, 'The requirement of the "value" action is not JSON compatible.' ); break; } if (config?.target === 'openapi-3.0') { // Hint: OpenAPI 3.0 does not support const. That's why we use an // enum instead. jsonSchema.enum = [valibotAction.requirement]; } else { jsonSchema.const = valibotAction.requirement; } break; } case 'values': { if (!isJsonEnumValues(valibotAction.requirement)) { errors = addError( errors, 'A requirement of the "values" action is not JSON compatible.' ); break; } jsonSchema.enum = valibotAction.requirement; break; } default: { errors = addError( errors, // @ts-expect-error `The "${valibotAction.type}" action cannot be converted to JSON Schema.` ); } } // Override JSON Schema if specified and necessary if (config?.overrideAction) { const actionOverride = config.overrideAction({ valibotAction, jsonSchema, errors, }); if (actionOverride) { return { ...actionOverride }; } } // Handle errors based on configuration if (errors) { for (const message of errors) { handleError(message, config); } } // Return converted JSON Schema return jsonSchema; } ================================================ FILE: packages/to-json-schema/src/converters/convertAction/index.ts ================================================ export * from './convertAction.ts'; ================================================ FILE: packages/to-json-schema/src/converters/convertSchema/convertSchema.test.ts ================================================ import * as v from 'valibot'; import { describe, expect, test, vi } from 'vitest'; import { createContext } from '../../vitest/index.ts'; import { convertSchema } from './convertSchema.ts'; console.warn = vi.fn(); describe('convertSchema', () => { describe('definitions', () => { test('should convert schema using definitions', () => { const schema = v.string(); expect( convertSchema( {}, schema, undefined, createContext({ definitions: { foo: { type: 'string' } }, referenceMap: new Map().set(schema, 'foo'), }) ) ).toStrictEqual({ $ref: '#/$defs/foo', }); }); test('should skip definition if specified', () => { const stringSchema = v.string(); expect( convertSchema( {}, stringSchema, undefined, createContext({ definitions: { foo: { type: 'string' } }, referenceMap: new Map().set(stringSchema, 'foo'), }), true ) ).toStrictEqual({ type: 'string', }); }); test('should not skip definition if specified', () => { const stringSchema = v.string(); expect( convertSchema( {}, stringSchema, undefined, createContext({ definitions: { foo: { type: 'string' } }, referenceMap: new Map().set(stringSchema, 'foo'), }), false ) ).toStrictEqual({ $ref: '#/$defs/foo', }); }); test('should skip only root definition of nested schema if specified', () => { const stringSchema = v.string(); const arraySchema = v.array(stringSchema); const definitions = { string: { type: 'string' }, array: { type: 'array', items: { $ref: '#/$defs/string' }, }, } as const; const referenceMap = new Map([ [stringSchema, 'string'], [arraySchema, 'array'], ]); expect( convertSchema( {}, arraySchema, undefined, createContext({ definitions, referenceMap }), true ) ).toStrictEqual({ type: 'array', items: { $ref: '#/$defs/string' }, }); }); test('should override reference ID if specified', () => { const foo = v.string(); const bar = v.number(); const schema = v.object({ foo, bar }); expect( convertSchema( {}, schema, { overrideRef({ referenceId }) { if (referenceId === 'bar') { return '#/$custom/reference'; } }, }, createContext({ definitions: { foo: { type: 'string' }, bar: { type: 'number' } }, referenceMap: new Map().set(foo, 'foo').set(bar, 'bar'), }) ) ).toStrictEqual({ type: 'object', properties: { foo: { $ref: '#/$defs/foo' }, bar: { $ref: '#/$custom/reference' }, }, required: ['foo', 'bar'], }); }); }); describe('schema with pipe', () => { test('should convert pipe items', () => { expect( convertSchema( {}, v.pipe(v.string(), v.email(), v.description('foo')), undefined, createContext() ) ).toStrictEqual({ type: 'string', format: 'email', description: 'foo', }); }); test('should convert domain pipe items', () => { expect( convertSchema( {}, v.pipe(v.string(), v.domain(), v.description('foo')), undefined, createContext() ) ).toStrictEqual({ type: 'string', pattern: v.DOMAIN_REGEX.source, description: 'foo', }); }); test('should convert pipe schema in definitions', () => { const schema = v.string(); expect( convertSchema( {}, v.pipe(schema, v.email(), v.description('foo')), undefined, createContext({ definitions: { foo: { type: 'string' } }, referenceMap: new Map().set(schema, 'foo'), }) ) ).toStrictEqual({ type: 'string', format: 'email', description: 'foo', }); }); test('should throw error for multiple schemas in pipe', () => { const schema = v.pipe( v.nullable(v.string()), v.string(), v.description('foo') ); const error = 'Set the "typeMode" config to "input" or "output" to convert pipelines with multiple schemas.'; expect(() => convertSchema({}, schema, undefined, createContext()) ).toThrowError(error); expect(() => convertSchema({}, schema, { errorMode: 'throw' }, createContext()) ).toThrowError(error); expect(() => convertSchema({}, schema, { typeMode: 'ignore' }, createContext()) ).toThrowError(error); }); test('should warn error for multiple schemas in pipe', () => { const schema = v.pipe( v.nullable(v.string()), v.string(), v.description('foo') ); const error = 'Set the "typeMode" config to "input" or "output" to convert pipelines with multiple schemas.'; expect( convertSchema({}, schema, { errorMode: 'warn' }, createContext()) ).toStrictEqual({ anyOf: [{ type: 'string' }, { type: 'null' }], type: 'string', description: 'foo', }); expect(console.warn).toHaveBeenLastCalledWith(error); expect( convertSchema( {}, schema, { errorMode: 'warn', typeMode: 'ignore' }, createContext() ) ).toStrictEqual({ anyOf: [{ type: 'string' }, { type: 'null' }], type: 'string', description: 'foo', }); expect(console.warn).toHaveBeenLastCalledWith(error); }); // Hint: This schema is intentionally complex to test the conversion of nested pipelines const inputOutputSchema = v.pipe( v.pipe( v.pipe(v.string(), v.nonEmpty()), v.decimal(), v.transform(Number), v.pipe(v.number(), v.minValue(0)) ), v.maxValue(100) ); test('should convert only input type of pipeline', () => { expect( convertSchema( {}, // @ts-expect-error inputOutputSchema, { typeMode: 'input' }, createContext() ) ).toStrictEqual({ type: 'string', minLength: 1, pattern: '^[+-]?(?:\\d*\\.)?\\d+$', }); }); test('should convert only output type of pipeline', () => { expect( convertSchema( {}, // @ts-expect-error inputOutputSchema, { typeMode: 'output' }, createContext() ) ).toStrictEqual({ type: 'number', minimum: 0, maximum: 100, }); }); }); describe('primitive schemas', () => { test('should convert boolean schema', () => { expect( convertSchema({}, v.boolean(), undefined, createContext()) ).toStrictEqual({ type: 'boolean', }); }); test('should convert null schema', () => { expect( convertSchema({}, v.null(), undefined, createContext()) ).toStrictEqual({ type: 'null', }); }); test('should convert null schema for openapi-3.0', () => { expect( convertSchema({}, v.null_(), { target: 'openapi-3.0' }, createContext()) ).toStrictEqual({ enum: [null], }); }); test('should convert number schema', () => { expect( convertSchema({}, v.number(), undefined, createContext()) ).toStrictEqual({ type: 'number', }); }); test('should convert string schema', () => { expect( convertSchema({}, v.string(), undefined, createContext()) ).toStrictEqual({ type: 'string', }); }); }); describe('complex schemas', () => { test('should convert array schema', () => { expect( convertSchema({}, v.array(v.number()), undefined, createContext()) ).toStrictEqual({ type: 'array', items: { type: 'number' }, }); }); test('should convert tuple schema', () => { expect( convertSchema( {}, v.tuple([v.number(), v.string()]), undefined, createContext() ) ).toStrictEqual({ type: 'array', items: [{ type: 'number' }, { type: 'string' }], minItems: 2, }); }); test('should convert tuple schema for draft-2020-12', () => { expect( convertSchema( {}, v.tuple([v.string(), v.number()]), { target: 'draft-2020-12' }, createContext() ) ).toStrictEqual({ type: 'array', prefixItems: [{ type: 'string' }, { type: 'number' }], minItems: 2, }); }); test('should convert tuple schema for openapi-3.0', () => { expect( convertSchema( {}, v.tuple([v.string(), v.number()]), { target: 'openapi-3.0' }, createContext() ) ).toStrictEqual({ type: 'array', items: { anyOf: [{ type: 'string' }, { type: 'number' }], }, minItems: 2, maxItems: 2, }); }); test('should convert tuple with rest schema', () => { expect( convertSchema( {}, v.tupleWithRest([v.number(), v.string()], v.boolean()), undefined, createContext() ) ).toStrictEqual({ type: 'array', items: [{ type: 'number' }, { type: 'string' }], minItems: 2, additionalItems: { type: 'boolean' }, }); }); test('should convert tuple with rest schema for draft-2020-12', () => { expect( convertSchema( {}, v.tupleWithRest([v.string()], v.number()), { target: 'draft-2020-12' }, createContext() ) ).toStrictEqual({ type: 'array', prefixItems: [{ type: 'string' }], minItems: 1, items: { type: 'number' }, }); }); test('should convert tuple with rest schema for openapi-3.0', () => { expect( convertSchema( {}, v.tupleWithRest([v.string()], v.number()), { target: 'openapi-3.0' }, createContext() ) ).toStrictEqual({ type: 'array', items: { anyOf: [{ type: 'string' }, { type: 'number' }], }, minItems: 1, }); }); test('should convert loose tuple schema', () => { expect( convertSchema( {}, v.looseTuple([v.number(), v.string()]), undefined, createContext() ) ).toStrictEqual({ type: 'array', items: [{ type: 'number' }, { type: 'string' }], minItems: 2, }); }); test('should convert loose tuple schema for draft-2020-12', () => { expect( convertSchema( {}, v.looseTuple([v.string(), v.number()]), { target: 'draft-2020-12' }, createContext() ) ).toStrictEqual({ type: 'array', prefixItems: [{ type: 'string' }, { type: 'number' }], minItems: 2, }); }); test('should convert loose tuple schema for openapi-3.0', () => { expect( convertSchema( {}, v.looseTuple([v.string(), v.number()]), { target: 'openapi-3.0' }, createContext() ) ).toStrictEqual({ type: 'array', items: { anyOf: [{ type: 'string' }, { type: 'number' }], }, minItems: 2, }); }); test('should convert strict tuple schema', () => { expect( convertSchema( {}, v.strictTuple([v.number(), v.string()]), undefined, createContext() ) ).toStrictEqual({ type: 'array', items: [{ type: 'number' }, { type: 'string' }], minItems: 2, additionalItems: false, }); }); test('should convert strict tuple schema for draft-2020-12', () => { expect( convertSchema( {}, v.strictTuple([v.string(), v.boolean()]), { target: 'draft-2020-12' }, createContext() ) ).toStrictEqual({ type: 'array', prefixItems: [{ type: 'string' }, { type: 'boolean' }], minItems: 2, items: false, }); }); test('should convert strict tuple schema for openapi-3.0', () => { expect( convertSchema( {}, v.strictTuple([v.string(), v.boolean()]), { target: 'openapi-3.0' }, createContext() ) ).toStrictEqual({ type: 'array', items: { anyOf: [{ type: 'string' }, { type: 'boolean' }], }, minItems: 2, maxItems: 2, }); }); test('should convert object schema', () => { expect( convertSchema( {}, v.object({ key1: v.string(), key2: v.optional(v.string()), key3: v.boolean(), key4: v.exactOptional(v.boolean()), key5: v.number(), key6: v.nullish(v.number()), }), undefined, createContext() ) ).toStrictEqual({ type: 'object', properties: { key1: { type: 'string' }, key2: { type: 'string' }, key3: { type: 'boolean' }, key4: { type: 'boolean' }, key5: { type: 'number' }, key6: { anyOf: [{ type: 'number' }, { type: 'null' }] }, }, required: ['key1', 'key3', 'key5'], }); }); test('should convert object with rest schema', () => { expect( convertSchema( {}, v.objectWithRest( { key1: v.string(), key2: v.optional(v.string()), key3: v.boolean(), key4: v.exactOptional(v.boolean()), key5: v.number(), key6: v.nullish(v.number()), }, v.number() ), undefined, createContext() ) ).toStrictEqual({ type: 'object', properties: { key1: { type: 'string' }, key2: { type: 'string' }, key3: { type: 'boolean' }, key4: { type: 'boolean' }, key5: { type: 'number' }, key6: { anyOf: [{ type: 'number' }, { type: 'null' }] }, }, required: ['key1', 'key3', 'key5'], additionalProperties: { type: 'number' }, }); }); test('should convert loose object schema', () => { expect( convertSchema( {}, v.looseObject({ key1: v.string(), key2: v.optional(v.string()), key3: v.boolean(), key4: v.exactOptional(v.boolean()), key5: v.number(), key6: v.nullish(v.number()), }), undefined, createContext() ) ).toStrictEqual({ type: 'object', properties: { key1: { type: 'string' }, key2: { type: 'string' }, key3: { type: 'boolean' }, key4: { type: 'boolean' }, key5: { type: 'number' }, key6: { anyOf: [{ type: 'number' }, { type: 'null' }] }, }, required: ['key1', 'key3', 'key5'], }); }); test('should convert strict object schema', () => { expect( convertSchema( {}, v.strictObject({ key1: v.string(), key2: v.optional(v.string()), key3: v.boolean(), key4: v.exactOptional(v.boolean()), key5: v.number(), key6: v.nullish(v.number()), }), undefined, createContext() ) ).toStrictEqual({ type: 'object', properties: { key1: { type: 'string' }, key2: { type: 'string' }, key3: { type: 'boolean' }, key4: { type: 'boolean' }, key5: { type: 'number' }, key6: { anyOf: [{ type: 'number' }, { type: 'null' }] }, }, required: ['key1', 'key3', 'key5'], additionalProperties: false, }); }); test('should convert record schema', () => { expect( convertSchema( {}, v.record(v.string(), v.number()), undefined, createContext() ) ).toStrictEqual({ type: 'object', propertyNames: { type: 'string' }, additionalProperties: { type: 'number' }, }); }); test('should convert record schema for openapi-3.0', () => { expect( convertSchema( {}, v.record(v.string(), v.number()), { target: 'openapi-3.0' }, createContext() ) ).toStrictEqual({ type: 'object', additionalProperties: { type: 'number' }, }); }); test('should convert record schema with pipe in key', () => { expect( convertSchema( {}, v.record(v.pipe(v.string(), v.email()), v.number()), undefined, createContext() ) ).toStrictEqual({ type: 'object', propertyNames: { type: 'string', format: 'email' }, additionalProperties: { type: 'number' }, }); }); test('should throw error for record with piped key schema for openapi-3.0', () => { const schema = v.record(v.pipe(v.string(), v.email()), v.number()); const error = 'The "record" schema with a schema for the key that contains a "pipe" cannot be converted to JSON Schema.'; expect(() => convertSchema({}, schema, { target: 'openapi-3.0' }, createContext()) ).toThrowError(error); expect(() => convertSchema( {}, schema, { target: 'openapi-3.0', errorMode: 'throw' }, createContext() ) ).toThrowError(error); }); test('should throw error for record schema with non-string schema key', () => { // @ts-expect-error const schema = v.record(v.number(), v.number()); const error = 'The "record" schema with the "number" schema for the key cannot be converted to JSON Schema.'; expect(() => convertSchema({}, schema, undefined, createContext()) ).toThrowError(error); expect(() => convertSchema({}, schema, { errorMode: 'throw' }, createContext()) ).toThrowError(error); }); test('should warn error for record schema with non-string schema key', () => { // @ts-expect-error const schema = v.record(v.pipe(v.number(), v.minValue(10)), v.number()); expect( convertSchema({}, schema, { errorMode: 'warn' }, createContext()) ).toStrictEqual({ type: 'object', propertyNames: { type: 'number', minimum: 10 }, additionalProperties: { type: 'number' }, }); expect(console.warn).toHaveBeenLastCalledWith( 'The "record" schema with the "number" schema for the key cannot be converted to JSON Schema.' ); }); }); describe('special schemas', () => { test('should convert any schema', () => { expect( convertSchema({}, v.any(), undefined, createContext()) ).toStrictEqual({}); }); test('should convert unknown schema', () => { expect( convertSchema({}, v.unknown(), undefined, createContext()) ).toStrictEqual({}); }); test('should convert nullable schema without default', () => { expect( convertSchema({}, v.nullable(v.string()), undefined, createContext()) ).toStrictEqual({ anyOf: [{ type: 'string' }, { type: 'null' }], }); }); test('should convert nullable schema for openapi-3.0', () => { expect( convertSchema( {}, v.nullable(v.string()), { target: 'openapi-3.0' }, createContext() ) ).toStrictEqual({ type: 'string', nullable: true, }); }); test('should convert nullable schema with default for openapi-3.0', () => { expect( convertSchema( {}, v.nullable(v.string(), 'foo'), { target: 'openapi-3.0' }, createContext() ) ).toStrictEqual({ type: 'string', nullable: true, default: 'foo', }); }); test('should convert nullable schema with default', () => { expect( convertSchema( {}, v.nullable(v.string(), 'foo'), undefined, createContext() ) ).toStrictEqual({ anyOf: [{ type: 'string' }, { type: 'null' }], default: 'foo', }); expect( convertSchema( {}, v.nullable(v.string(), () => 'foo'), undefined, createContext() ) ).toStrictEqual({ anyOf: [{ type: 'string' }, { type: 'null' }], default: 'foo', }); }); test('should convert nullish schema without default', () => { expect( convertSchema({}, v.nullish(v.string()), undefined, createContext()) ).toStrictEqual({ anyOf: [{ type: 'string' }, { type: 'null' }], }); }); test('should convert nullish schema for openapi-3.0', () => { expect( convertSchema( {}, v.nullish(v.number()), { target: 'openapi-3.0' }, createContext() ) ).toStrictEqual({ type: 'number', nullable: true, }); }); test('should convert nullish schema with default for openapi-3.0', () => { expect( convertSchema( {}, v.nullish(v.number(), 42), { target: 'openapi-3.0' }, createContext() ) ).toStrictEqual({ type: 'number', nullable: true, default: 42, }); }); test('should convert nullish schema with default', () => { expect( convertSchema( {}, v.nullish(v.string(), 'foo'), undefined, createContext() ) ).toStrictEqual({ anyOf: [{ type: 'string' }, { type: 'null' }], default: 'foo', }); expect( convertSchema( {}, v.nullable(v.string(), () => 'foo'), undefined, createContext() ) ).toStrictEqual({ anyOf: [{ type: 'string' }, { type: 'null' }], default: 'foo', }); }); test('should convert never schema', () => { expect( convertSchema({}, v.never(), undefined, createContext()) ).toStrictEqual({ not: {}, }); }); test('should convert exact optional schema without default', () => { expect( convertSchema( {}, v.exactOptional(v.string()), undefined, createContext() ) ).toStrictEqual({ type: 'string', }); }); test('should convert exact optional schema with default', () => { expect( convertSchema( {}, v.exactOptional(v.string(), 'foo'), undefined, createContext() ) ).toStrictEqual({ type: 'string', default: 'foo', }); expect( convertSchema( {}, v.exactOptional(v.string(), () => 'foo'), undefined, createContext() ) ).toStrictEqual({ type: 'string', default: 'foo', }); }); test('should convert optional schema without default', () => { expect( convertSchema({}, v.optional(v.string()), undefined, createContext()) ).toStrictEqual({ type: 'string', }); }); test('should convert optional schema with default', () => { expect( convertSchema( {}, v.optional(v.string(), 'foo'), undefined, createContext() ) ).toStrictEqual({ type: 'string', default: 'foo', }); expect( convertSchema( {}, v.optional(v.string(), () => 'foo'), undefined, createContext() ) ).toStrictEqual({ type: 'string', default: 'foo', }); }); test('should convert undefinedable schema without default', () => { expect( convertSchema( {}, v.undefinedable(v.string()), undefined, createContext() ) ).toStrictEqual({ type: 'string', }); }); test('should convert undefinedable schema with default', () => { expect( convertSchema( {}, v.undefinedable(v.string(), 'foo'), undefined, createContext() ) ).toStrictEqual({ type: 'string', default: 'foo', }); expect( convertSchema( {}, v.undefinedable(v.string(), () => 'foo'), undefined, createContext() ) ).toStrictEqual({ type: 'string', default: 'foo', }); }); test('should convert supported literal schema', () => { expect( convertSchema({}, v.literal(true), undefined, createContext()) ).toStrictEqual({ const: true, }); expect( convertSchema({}, v.literal(123), undefined, createContext()) ).toStrictEqual({ const: 123, }); expect( convertSchema({}, v.literal('foo'), undefined, createContext()) ).toStrictEqual({ const: 'foo', }); }); test('should convert literal schema for openapi-3.0', () => { expect( convertSchema( {}, v.literal('test'), { target: 'openapi-3.0' }, createContext() ) ).toStrictEqual({ enum: ['test'], }); expect( convertSchema( {}, v.literal(42), { target: 'openapi-3.0' }, createContext() ) ).toStrictEqual({ enum: [42], }); expect( convertSchema( {}, v.literal(true), { target: 'openapi-3.0' }, createContext() ) ).toStrictEqual({ enum: [true], }); }); test('should throw error for unsupported literal schema', () => { const schema1 = v.literal(123n); const schema2 = v.literal(Symbol('foo')); const error = 'The value of the "literal" schema is not JSON compatible.'; expect(() => convertSchema({}, schema1, undefined, createContext()) ).toThrowError(error); expect(() => convertSchema({}, schema1, { errorMode: 'throw' }, createContext()) ).toThrowError(error); expect(() => convertSchema({}, schema2, undefined, createContext()) ).toThrowError(error); expect(() => convertSchema({}, schema2, { errorMode: 'throw' }, createContext()) ).toThrowError(error); }); test('should warn error for unsupported literal schema', () => { expect( convertSchema( {}, v.literal(123n), { errorMode: 'warn' }, createContext() ) ).toStrictEqual({ const: 123n, }); expect(console.warn).toHaveBeenLastCalledWith( 'The value of the "literal" schema is not JSON compatible.' ); const symbol = Symbol('foo'); expect( convertSchema( {}, v.literal(symbol), { errorMode: 'warn' }, createContext() ) ).toStrictEqual({ const: symbol, }); expect(console.warn).toHaveBeenLastCalledWith( 'The value of the "literal" schema is not JSON compatible.' ); }); test('should convert enum schema', () => { enum TestEnum { KEY1, KEY2, KEY3 = 'foo', KEY4 = 123, } expect( convertSchema( {}, // @ts-expect-error v.enum(TestEnum), undefined, createContext() ) ).toStrictEqual({ type: ['string', 'number'], enum: [0, 1, 'foo', 123], }); enum TestOnlyNumbersEnum { KEY1, KEY2, } expect( convertSchema( {}, // @ts-expect-error v.enum(TestOnlyNumbersEnum), undefined, createContext() ) ).toStrictEqual({ type: 'number', enum: [0, 1], }); enum TestOnlyStringsEnum { KEY1 = 'key1', KEY2 = 'key2', } expect( convertSchema( {}, // @ts-expect-error v.enum(TestOnlyStringsEnum), undefined, createContext() ) ).toStrictEqual({ type: 'string', enum: ['key1', 'key2'], }); }); test('should convert enum schema for openapi-3.0', () => { enum TestEnum { KEY1, KEY2, KEY3 = 'foo', KEY4 = 123, } expect( convertSchema( {}, // @ts-expect-error v.enum(TestEnum), { target: 'openapi-3.0' }, createContext() ) ).toStrictEqual({ enum: [0, 1, 'foo', 123], }); enum TestOnlyNumbersEnum { KEY1, KEY2, } expect( convertSchema( {}, // @ts-expect-error v.enum(TestOnlyNumbersEnum), { target: 'openapi-3.0' }, createContext() ) ).toStrictEqual({ type: 'number', enum: [0, 1], }); enum TestOnlyStringsEnum { KEY1 = 'key1', KEY2 = 'key2', } expect( convertSchema( {}, // @ts-expect-error v.enum(TestOnlyStringsEnum), { target: 'openapi-3.0' }, createContext() ) ).toStrictEqual({ type: 'string', enum: ['key1', 'key2'], }); }); test('should convert supported picklist schema', () => { expect( convertSchema( {}, v.picklist(['foo', 123, 'bar', 456]), undefined, createContext() ) ).toStrictEqual({ type: ['string', 'number'], enum: ['foo', 123, 'bar', 456], }); expect( convertSchema( {}, v.picklist(['foo', 'bar']), undefined, createContext() ) ).toStrictEqual({ type: 'string', enum: ['foo', 'bar'], }); expect( convertSchema({}, v.picklist([123, 456]), undefined, createContext()) ).toStrictEqual({ type: 'number', enum: [123, 456], }); }); test('should convert supported picklist schema for openapi-3.0', () => { expect( convertSchema( {}, v.picklist(['foo', 123, 'bar', 456]), { target: 'openapi-3.0' }, createContext() ) ).toStrictEqual({ enum: ['foo', 123, 'bar', 456], }); expect( convertSchema( {}, v.picklist(['foo', 'bar']), { target: 'openapi-3.0' }, createContext() ) ).toStrictEqual({ type: 'string', enum: ['foo', 'bar'], }); expect( convertSchema( {}, v.picklist([123, 456]), { target: 'openapi-3.0' }, createContext() ) ).toStrictEqual({ type: 'number', enum: [123, 456], }); }); test('should throw error for unsupported picklist schema', () => { const schema = v.picklist([123n, 456n]); const error = 'An option of the "picklist" schema is not JSON compatible.'; expect(() => convertSchema({}, schema, undefined, createContext()) ).toThrowError(error); expect(() => convertSchema({}, schema, { errorMode: 'throw' }, createContext()) ).toThrowError(error); }); test('should warn error for unsupported picklist schema', () => { expect( convertSchema( {}, v.picklist([123n, 456n]), { errorMode: 'warn' }, createContext() ) ).toStrictEqual({ enum: [123n, 456n] }); expect(console.warn).toHaveBeenLastCalledWith( 'An option of the "picklist" schema is not JSON compatible.' ); }); test('should convert union schema', () => { expect( convertSchema( {}, v.union([v.string(), v.boolean()]), undefined, createContext() ) ).toStrictEqual({ anyOf: [{ type: 'string' }, { type: 'boolean' }], }); }); test('should convert variant schema', () => { expect( convertSchema( {}, v.variant('type', [ v.object({ type: v.literal('foo'), foo: v.string() }), v.object({ type: v.literal('bar'), bar: v.number() }), ]), undefined, createContext() ) ).toStrictEqual({ oneOf: [ { type: 'object', properties: { type: { const: 'foo' }, foo: { type: 'string' }, }, required: ['type', 'foo'], }, { type: 'object', properties: { type: { const: 'bar' }, bar: { type: 'number' }, }, required: ['type', 'bar'], }, ], }); }); test('should convert intersect schema', () => { expect( convertSchema( {}, v.intersect([ v.object({ foo: v.string() }), v.object({ bar: v.number() }), ]), undefined, createContext() ) ).toStrictEqual({ allOf: [ { type: 'object', properties: { foo: { type: 'string' }, }, required: ['foo'], }, { type: 'object', properties: { bar: { type: 'number' }, }, required: ['bar'], }, ], }); }); test('should convert simple lazy schema without definitions', () => { const stringSchema = v.string(); const lazyGetter = () => stringSchema; const context = createContext(); expect( convertSchema({}, v.lazy(lazyGetter), undefined, context) ).toStrictEqual({ $ref: '#/$defs/0' }); expect(context).toStrictEqual({ definitions: { '0': { type: 'string' } }, referenceMap: new Map().set(stringSchema, '0'), getterMap: new Map().set(lazyGetter, stringSchema), }); }); test('should convert simple lazy schema with definitions', () => { const stringSchema = v.string(); const lazyGetter = () => stringSchema; const context = createContext({ definitions: { testSchema: { type: 'string' } }, referenceMap: new Map().set(stringSchema, 'stringSchema'), }); expect( convertSchema( {}, v.lazy(lazyGetter), { definitions: { stringSchema } }, context ) ).toStrictEqual({ $ref: '#/$defs/stringSchema' }); expect(context).toStrictEqual({ definitions: { testSchema: { type: 'string' } }, referenceMap: new Map().set(stringSchema, 'stringSchema'), getterMap: new Map().set(lazyGetter, stringSchema), }); }); test('should convert recursive lazy schema with static getter', () => { // Returns a static reference that never changes const lazyGetter = () => nodeSchema; const nodeSchema: v.GenericSchema = v.object({ node: v.optional(v.lazy(lazyGetter)), }); const context = createContext(); expect( convertSchema( {}, // @ts-expect-error nodeSchema, undefined, context ) ).toStrictEqual({ type: 'object', properties: { node: { $ref: '#/$defs/1' } }, required: [], }); expect(context).toStrictEqual({ definitions: { '1': { type: 'object', properties: { node: { $ref: '#/$defs/1' } }, required: [], }, }, referenceMap: new Map().set(nodeSchema, '1'), getterMap: new Map().set(lazyGetter, nodeSchema), }); }); test('should convert recursive lazy schema with dynamic getter', () => { // Returns a dynamic reference that always changes const lazyGetter = () => v.nullable(nodeSchema); const nodeSchema: v.GenericSchema = v.object({ node: v.lazy(lazyGetter), }); const context = createContext(); expect( convertSchema( {}, // @ts-expect-error nodeSchema, undefined, context ) ).toStrictEqual({ type: 'object', properties: { node: { $ref: '#/$defs/2' } }, required: ['node'], }); expect(context).toStrictEqual({ definitions: { '2': { anyOf: [ { type: 'object', properties: { node: { $ref: '#/$defs/2' } }, required: ['node'], }, { type: 'null' }, ], }, }, referenceMap: new Map().set(expect.any(Object), '2'), getterMap: new Map().set(lazyGetter, expect.any(Object)), }); }); test('should convert simple lazy schema without custom reference ID', () => { const wrappedSchema = v.string(); expect( convertSchema( {}, v.lazy(() => wrappedSchema), { overrideRef({ valibotSchema }) { if (valibotSchema === wrappedSchema) { return '#/$custom/reference'; } }, }, createContext() ) ).toStrictEqual({ $ref: '#/$custom/reference' }); }); }); describe('other schemas', () => { test('should throw error for unsupported file schema', () => { const schema = v.file(); const error = 'The "file" schema cannot be converted to JSON Schema.'; expect(() => convertSchema( {}, // @ts-expect-error schema, undefined, createContext() ) ).toThrowError(error); expect(() => convertSchema( {}, // @ts-expect-error schema, { errorMode: 'throw' }, createContext() ) ).toThrowError(error); }); test('should warn error for unsupported file schema', () => { expect( // @ts-expect-error convertSchema({}, v.file(), { errorMode: 'warn' }, createContext()) ).toStrictEqual({}); expect(console.warn).toHaveBeenLastCalledWith( 'The "file" schema cannot be converted to JSON Schema.' ); }); }); describe('custom config', () => { test('should override JSON Schema and suppress error', () => { expect(() => convertSchema( {}, // @ts-expect-error v.date(), { overrideSchema: () => null }, createContext() ) ).toThrowError('The "date" schema cannot be converted to JSON Schema.'); expect( convertSchema( {}, // @ts-expect-error v.date(), { overrideSchema({ valibotSchema }) { if (valibotSchema.type === 'date') { return { type: 'string', format: 'date-time' }; } }, }, createContext() ) ).toStrictEqual({ type: 'string', format: 'date-time', }); }); }); }); ================================================ FILE: packages/to-json-schema/src/converters/convertSchema/convertSchema.ts ================================================ import * as v from 'valibot'; import type { ConversionConfig, ConversionContext, JsonSchema, } from '../../types/index.ts'; import { addError, handleError } from '../../utils/index.ts'; import { convertAction } from '../convertAction/index.ts'; /** * Schema type. */ type Schema = | v.AnySchema | v.UnknownSchema | v.NullableSchema< v.BaseSchema>, v.Default>, null> > | v.NullishSchema< v.BaseSchema>, v.Default< v.BaseSchema>, null | undefined > > | v.NullSchema | undefined> | v.StringSchema | undefined> | v.BooleanSchema | undefined> | v.NumberSchema | undefined> | v.LiteralSchema | undefined> | v.PicklistSchema< v.PicklistOptions, v.ErrorMessage | undefined > | v.EnumSchema | undefined> | v.VariantSchema< string, v.VariantOptions, v.ErrorMessage | undefined > | v.UnionSchema< v.UnionOptions, v.ErrorMessage>> | undefined > | v.IntersectSchema< v.IntersectOptions, v.ErrorMessage | undefined > | v.ObjectSchema | undefined> | v.ObjectWithRestSchema< v.ObjectEntries, v.BaseSchema>, v.ErrorMessage | undefined > | v.ExactOptionalSchema< v.BaseSchema>, v.Default>, undefined> > | v.OptionalSchema< v.BaseSchema>, v.Default>, undefined> > | v.UndefinedableSchema< v.BaseSchema>, v.Default>, undefined> > | v.StrictObjectSchema< v.ObjectEntries, v.ErrorMessage | undefined > | v.LooseObjectSchema< v.ObjectEntries, v.ErrorMessage | undefined > | v.RecordSchema< v.BaseSchema>, v.BaseSchema>, v.ErrorMessage | undefined > | v.TupleSchema | undefined> | v.TupleWithRestSchema< v.TupleItems, v.BaseSchema>, v.ErrorMessage | undefined > | v.LooseTupleSchema< v.TupleItems, v.ErrorMessage | undefined > | v.StrictTupleSchema< v.TupleItems, v.ErrorMessage | undefined > | v.ArraySchema< v.BaseSchema>, v.ErrorMessage | undefined > | v.NeverSchema | undefined> | v.LazySchema>>; /** * Pipe type. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any type Pipe = readonly (Schema | v.PipeAction>)[]; /** * Schema or pipe type. */ type SchemaOrPipe = Schema | v.SchemaWithPipe; /** * Flattens a Valibot pipe by recursively expanding nested pipes. * * @param pipe The pipeline to flatten. * * @returns A flat pipeline. */ function flattenPipe(pipe: Pipe): Pipe { return pipe.flatMap((item) => 'pipe' in item ? flattenPipe(item.pipe as Pipe) : item ); } // Create global reference count 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. */ export function convertSchema( jsonSchema: JsonSchema, valibotSchema: SchemaOrPipe, config: ConversionConfig | undefined, context: ConversionContext, skipRef = false ): JsonSchema { if (!skipRef) { // If schema is in reference map use reference and skip conversion 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 it is schema with pipe, convert each item of pipe if ('pipe' in valibotSchema) { // Flatten pipe by expanding nested pipes const flatPipe = flattenPipe(valibotSchema.pipe); // Create start and stop index variables let startIndex = 0; let stopIndex = flatPipe.length - 1; // If type mode is set to input, update stop index 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; } // Otherwise, if type mode is set to output, update start index } else if (config?.typeMode === 'output') { const outputStartIndex = flatPipe.findLastIndex( (item) => item.kind === 'schema' ); if (outputStartIndex !== -1) { startIndex = outputStartIndex; } } // Convert each item of pipe in specified range for (let index = startIndex; index <= stopIndex; index++) { // Get current pipe item const valibotPipeItem = flatPipe[index]; // Convert Valibot schema or action to JSON Schema if (valibotPipeItem.kind === 'schema') { // Handle error if pipe contains another schema after start index if (index > startIndex) { handleError( 'Set the "typeMode" config to "input" or "output" to convert pipelines with multiple schemas.', config ); } // Convert Valibot schema to JSON Schema jsonSchema = convertSchema( jsonSchema, valibotPipeItem, config, context, // Hint: We skip using a reference because subsequent pipe elements // may change the JSON schema, which could result in invalid output // if we were to use a reference. true ); // Convert Valibot action to JSON Schema } else { // @ts-expect-error jsonSchema = convertAction(jsonSchema, valibotPipeItem, config); } } // Return converted JSON Schema return jsonSchema; } // Create errors variable let errors: [string, ...string[]] | undefined; // Otherwise, convert individual schema to JSON Schema switch (valibotSchema.type) { // Primitive schemas case 'boolean': { jsonSchema.type = 'boolean'; break; } case 'null': { if (config?.target === 'openapi-3.0') { // Hint: OpenAPI 3.0 does not have a null type. That's why we're using // an enum as a workaround. jsonSchema.enum = [null]; } else { jsonSchema.type = 'null'; } break; } case 'number': { jsonSchema.type = 'number'; break; } case 'string': { jsonSchema.type = 'string'; break; } // Complex schemas case 'array': { jsonSchema.type = 'array'; jsonSchema.items = convertSchema( {}, valibotSchema.item as SchemaOrPipe, config, context ); break; } case 'tuple': case 'tuple_with_rest': case 'loose_tuple': case 'strict_tuple': { jsonSchema.type = 'array'; // If target is OpenAPI 3.0 if (config?.target === 'openapi-3.0') { // Uses anyOf pattern with minItems/maxItems jsonSchema.items = { anyOf: [] }; jsonSchema.minItems = valibotSchema.items.length; for (const item of valibotSchema.items) { // @ts-expect-error jsonSchema.items.anyOf.push( convertSchema({}, item as SchemaOrPipe, config, context) ); } // Add rest item to anyOf if present if (valibotSchema.type === 'tuple_with_rest') { // @ts-expect-error jsonSchema.items.anyOf.push( convertSchema( {}, valibotSchema.rest as SchemaOrPipe, config, context ) ); // Set maxItems for tuples with fixed length } else if ( valibotSchema.type === 'strict_tuple' || valibotSchema.type === 'tuple' ) { jsonSchema.maxItems = valibotSchema.items.length; } // If target is draft-2020-12 } else if (config?.target === 'draft-2020-12') { // Use prefixItems for draft-2020-12 jsonSchema.prefixItems = []; jsonSchema.minItems = valibotSchema.items.length; for (const item of valibotSchema.items) { jsonSchema.prefixItems.push( convertSchema({}, item as SchemaOrPipe, config, context) ); } // Add additional items depending on schema type if (valibotSchema.type === 'tuple_with_rest') { jsonSchema.items = convertSchema( {}, valibotSchema.rest as SchemaOrPipe, config, context ); } else if (valibotSchema.type === 'strict_tuple') { jsonSchema.items = false; } // If target is draft-07 or unspecified } else { // Use items array for draft-07 jsonSchema.items = []; jsonSchema.minItems = valibotSchema.items.length; for (const item of valibotSchema.items) { jsonSchema.items.push( convertSchema({}, item as SchemaOrPipe, config, context) ); } // Add additional items depending on schema type if (valibotSchema.type === 'tuple_with_rest') { jsonSchema.additionalItems = convertSchema( {}, valibotSchema.rest as SchemaOrPipe, 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'; // Add JSON Schema of properties and mark required keys jsonSchema.properties = {}; jsonSchema.required = []; for (const key in valibotSchema.entries) { const entry = valibotSchema.entries[key] as SchemaOrPipe; jsonSchema.properties[key] = convertSchema({}, entry, config, context); if ( entry.type !== 'exact_optional' && entry.type !== 'nullish' && entry.type !== 'optional' ) { jsonSchema.required.push(key); } } // Add additional properties depending on schema type if (valibotSchema.type === 'object_with_rest') { jsonSchema.additionalProperties = convertSchema( {}, valibotSchema.rest as SchemaOrPipe, 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'; // propertyNames is not supported in OpenAPI 3.0 if (config?.target !== 'openapi-3.0') { jsonSchema.propertyNames = convertSchema( {}, valibotSchema.key as SchemaOrPipe, config, context ); } jsonSchema.additionalProperties = convertSchema( {}, valibotSchema.value as SchemaOrPipe, config, context ); break; } // Special schemas case 'any': case 'unknown': { break; } case 'never': { jsonSchema.not = {}; break; } case 'nullable': case 'nullish': { // If target is OpenAPI 3.0 use nullable property if (config?.target === 'openapi-3.0') { const innerSchema = convertSchema( {}, valibotSchema.wrapped as SchemaOrPipe, config, context ); Object.assign(jsonSchema, innerSchema); jsonSchema.nullable = true; // Otherwise, use union of wrapped schema and null } else { jsonSchema.anyOf = [ convertSchema( {}, valibotSchema.wrapped as SchemaOrPipe, config, context ), { type: 'null' }, ]; } // Add default value to JSON Schema, if available if (valibotSchema.default !== undefined) { // @ts-expect-error jsonSchema.default = v.getDefault(valibotSchema); } break; } case 'exact_optional': case 'optional': case 'undefinedable': { // Convert wrapped schema to JSON Schema jsonSchema = convertSchema( jsonSchema, valibotSchema.wrapped as SchemaOrPipe, config, context ); // Add default value to JSON Schema, if available if (valibotSchema.default !== undefined) { // @ts-expect-error 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') { // Hint: OpenAPI 3.0 does not support const. That's why we use an enum instead. // @ts-expect-error jsonSchema.enum = [valibotSchema.literal]; } else { // @ts-expect-error jsonSchema.const = valibotSchema.literal; } break; } case 'enum': { jsonSchema.enum = valibotSchema.options; if (valibotSchema.options.every((option) => typeof option === 'string')) { jsonSchema.type = 'string'; } else if ( valibotSchema.options.every((option) => typeof option === 'number') ) { jsonSchema.type = 'number'; } else if (config?.target !== 'openapi-3.0') { // Hint: OpenAPI 3.0 does not support multi-type arrays. jsonSchema.type = ['string', 'number']; } break; } case 'picklist': { const hasInvalidOption = valibotSchema.options.some( (option) => typeof option !== 'number' && typeof option !== 'string' ); if (hasInvalidOption) { errors = addError( errors, 'An option of the "picklist" schema is not JSON compatible.' ); } // @ts-expect-error jsonSchema.enum = valibotSchema.options; if (valibotSchema.options.every((option) => typeof option === 'string')) { jsonSchema.type = 'string'; } else if ( valibotSchema.options.every((option) => typeof option === 'number') ) { jsonSchema.type = 'number'; } else if (!hasInvalidOption && config?.target !== 'openapi-3.0') { // Hint: OpenAPI 3.0 does not support multi-type arrays. jsonSchema.type = ['string', 'number']; } break; } case 'union': { jsonSchema.anyOf = valibotSchema.options.map((option) => convertSchema({}, option as SchemaOrPipe, config, context) ); break; } case 'variant': { jsonSchema.oneOf = valibotSchema.options.map((option) => convertSchema({}, option as SchemaOrPipe, config, context) ); break; } case 'intersect': { jsonSchema.allOf = valibotSchema.options.map((option) => convertSchema({}, option as SchemaOrPipe, config, context) ); break; } case 'lazy': { // Get wrapped Valibot schema let wrappedValibotSchema = context.getterMap.get(valibotSchema.getter); // Add wrapped Valibot schema to getter map, if necessary if (!wrappedValibotSchema) { wrappedValibotSchema = valibotSchema.getter(undefined); context.getterMap.set(valibotSchema.getter, wrappedValibotSchema); } // Get reference ID of wrapped Valibot schema let referenceId = context.referenceMap.get(wrappedValibotSchema); // Add wrapped Valibot schema to reference map and definitions, if necessary if (!referenceId) { referenceId = `${refCount++}`; context.referenceMap.set(wrappedValibotSchema, referenceId); context.definitions[referenceId] = convertSchema( {}, wrappedValibotSchema as SchemaOrPipe, config, context, true ); } // Add reference to JSON Schema object jsonSchema.$ref = `#/$defs/${referenceId}`; // Override reference, if necessary if (config?.overrideRef) { const refOverride = config.overrideRef({ ...context, referenceId, valibotSchema: wrappedValibotSchema, jsonSchema, }); if (refOverride) { jsonSchema.$ref = refOverride; } } break; } // Other schemas default: { errors = addError( errors, // @ts-expect-error `The "${valibotSchema.type}" schema cannot be converted to JSON Schema.` ); } } // Override JSON Schema if specified and necessary if (config?.overrideSchema) { const schemaOverride = config.overrideSchema({ ...context, referenceId: context.referenceMap.get(valibotSchema), valibotSchema, jsonSchema, errors, }); if (schemaOverride) { return { ...schemaOverride }; } } // Handle errors based on configuration if (errors) { for (const message of errors) { handleError(message, config); } } // Return converted JSON Schema return jsonSchema; } ================================================ FILE: packages/to-json-schema/src/converters/convertSchema/index.ts ================================================ export * from './convertSchema.ts'; ================================================ FILE: packages/to-json-schema/src/converters/index.ts ================================================ export * from './convertAction/index.ts'; export * from './convertSchema/index.ts'; ================================================ FILE: packages/to-json-schema/src/functions/index.ts ================================================ export * from './toJsonSchema/index.ts'; export * from './toJsonSchemaDefs/index.ts'; export * from './toStandardJsonSchema/index.ts'; ================================================ FILE: packages/to-json-schema/src/functions/toJsonSchema/index.ts ================================================ export * from './toJsonSchema.ts'; ================================================ FILE: packages/to-json-schema/src/functions/toJsonSchema/toJsonSchema.test.ts ================================================ import * as v from 'valibot'; import { describe, expect, test, vi } from 'vitest'; import { toJsonSchema } from './toJsonSchema.ts'; // TODO: Add tests for override configs console.warn = vi.fn(); describe('toJsonSchema', () => { describe('should convert schema', () => { test('for simple string schema', () => { expect(toJsonSchema(v.string())).toStrictEqual({ $schema: 'http://json-schema.org/draft-07/schema#', type: 'string', }); }); test('for complex schema with definitions', () => { const stringSchema = v.string(); const complexSchema = v.pipe( v.object({ name: v.lazy(() => stringSchema), email: v.pipe(stringSchema, v.email(), v.minLength(10)), age: v.optional(v.number()), }), v.description('foo') ); expect( toJsonSchema(complexSchema, { definitions: { stringSchema, complexSchema }, }) ).toStrictEqual({ $schema: 'http://json-schema.org/draft-07/schema#', $ref: '#/$defs/complexSchema', $defs: { stringSchema: { type: 'string' }, complexSchema: { type: 'object', properties: { name: { $ref: '#/$defs/stringSchema' }, email: { type: 'string', format: 'email', minLength: 10 }, age: { type: 'number' }, }, required: ['name', 'email'], description: 'foo', }, }, }); }); test('for complex schema with any order of definitions', () => { const stringSchema = v.string(); const aliasesSchema = v.array(stringSchema); const complexSchema = v.pipe( v.object({ name: v.lazy(() => stringSchema), aliases: v.optional(aliasesSchema), email: v.pipe(stringSchema, v.email(), v.minLength(10)), }), v.description('foo') ); const expectedJsonSchema = { $schema: 'http://json-schema.org/draft-07/schema#', $ref: '#/$defs/complexSchema', $defs: { stringSchema: { type: 'string' }, aliasesSchema: { type: 'array', items: { $ref: '#/$defs/stringSchema' }, }, complexSchema: { type: 'object', properties: { name: { $ref: '#/$defs/stringSchema' }, aliases: { $ref: '#/$defs/aliasesSchema' }, email: { type: 'string', format: 'email', minLength: 10 }, }, required: ['name', 'email'], description: 'foo', }, }, }; const definitionPermutations = [ { stringSchema, aliasesSchema, complexSchema }, { stringSchema, complexSchema, aliasesSchema }, { aliasesSchema, stringSchema, complexSchema }, { aliasesSchema, complexSchema, stringSchema }, { complexSchema, stringSchema, aliasesSchema }, { complexSchema, aliasesSchema, stringSchema }, ]; for (const definitions of definitionPermutations) { expect(toJsonSchema(complexSchema, { definitions })).toStrictEqual( expectedJsonSchema ); } }); test('for recursive schema', () => { const ul = v.object({ type: v.literal('ul'), children: v.array(v.lazy(() => li)), }); const li: v.GenericSchema = v.object({ type: v.literal('li'), children: v.array(v.union([v.string(), ul])), }); expect( toJsonSchema(ul, { definitions: { ul, li }, }) ).toStrictEqual({ $schema: 'http://json-schema.org/draft-07/schema#', $ref: '#/$defs/ul', $defs: { ul: { properties: { children: { items: { $ref: '#/$defs/li' }, type: 'array', }, type: { const: 'ul' }, }, required: ['type', 'children'], type: 'object', }, li: { properties: { children: { items: { anyOf: [{ type: 'string' }, { $ref: '#/$defs/ul' }], }, type: 'array', }, type: { const: 'li' }, }, required: ['type', 'children'], type: 'object', }, }, }); }); }); describe('should throw error', () => { test('for invalid file schema', () => { expect(() => toJsonSchema(v.file())).toThrowError( 'The "file" schema cannot be converted to JSON Schema.' ); expect(() => toJsonSchema(v.file(), { errorMode: 'throw' })).toThrowError( 'The "file" schema cannot be converted to JSON Schema.' ); }); test('for invalid credit card action', () => { expect(() => toJsonSchema(v.pipe(v.string(), v.creditCard())) ).toThrowError( 'The "credit_card" action cannot be converted to JSON Schema.' ); expect(() => toJsonSchema(v.pipe(v.string(), v.creditCard()), { errorMode: 'throw' }) ).toThrowError( 'The "credit_card" action cannot be converted to JSON Schema.' ); }); }); describe('should warn error', () => { test('for invalid file schema', () => { expect(toJsonSchema(v.file(), { errorMode: 'warn' })).toStrictEqual({ $schema: 'http://json-schema.org/draft-07/schema#', }); expect(console.warn).toHaveBeenLastCalledWith( 'The "file" schema cannot be converted to JSON Schema.' ); }); test('for invalid credit card action', () => { expect( toJsonSchema(v.pipe(v.string(), v.creditCard()), { errorMode: 'warn' }) ).toStrictEqual({ $schema: 'http://json-schema.org/draft-07/schema#', type: 'string', }); expect(console.warn).toHaveBeenLastCalledWith( 'The "credit_card" action cannot be converted to JSON Schema.' ); }); }); describe('should ignore error', () => { test('for invalid file schema', () => { expect(toJsonSchema(v.file(), { errorMode: 'ignore' })).toStrictEqual({ $schema: 'http://json-schema.org/draft-07/schema#', }); }); test('for invalid credit card action', () => { expect( toJsonSchema(v.pipe(v.string(), v.creditCard()), { errorMode: 'ignore', }) ).toStrictEqual({ $schema: 'http://json-schema.org/draft-07/schema#', type: 'string', }); }); }); describe('should handle target config', () => { test('for draft-07', () => { expect(toJsonSchema(v.string(), { target: 'draft-07' })).toStrictEqual({ $schema: 'http://json-schema.org/draft-07/schema#', type: 'string', }); }); test('for draft-2020-12', () => { expect( toJsonSchema(v.string(), { target: 'draft-2020-12' }) ).toStrictEqual({ $schema: 'https://json-schema.org/draft/2020-12/schema', type: 'string', }); }); test('for openapi-3.0', () => { expect(toJsonSchema(v.string(), { target: 'openapi-3.0' })).toStrictEqual( { type: 'string', } ); }); }); }); ================================================ FILE: packages/to-json-schema/src/functions/toJsonSchema/toJsonSchema.ts ================================================ import type * as v from 'valibot'; import { convertSchema } from '../../converters/index.ts'; import { getGlobalDefs } from '../../storages/index.ts'; import type { ConversionConfig, ConversionContext, JsonSchema, } from '../../types/index.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. */ export function toJsonSchema( schema: v.BaseSchema>, config?: ConversionConfig ): JsonSchema { // Initialize JSON Schema context const context: ConversionContext = { definitions: {}, referenceMap: new Map(), getterMap: new Map(), }; // Get definitions from config or global storage const definitions = config?.definitions ?? getGlobalDefs(); // Add provided definitions to context, if necessary if (definitions) { for (const key in definitions) { context.referenceMap.set(definitions[key], key); } for (const key in definitions) { context.definitions[key] = convertSchema( {}, // @ts-expect-error definitions[key], config, context, true ); } } // Convert Valibot schema to JSON Schema const jsonSchema = convertSchema( {}, // @ts-expect-error schema, config, context ); // Add schema URI to JSON Schema, if necessary // Hint: OpenAPI 3.0 has no `$schema` property 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#'; } // Add definitions to JSON Schema, if necessary if (context.referenceMap.size) { jsonSchema.$defs = context.definitions; } // Return converted JSON Schema return jsonSchema; } ================================================ FILE: packages/to-json-schema/src/functions/toJsonSchemaDefs/index.ts ================================================ export * from './toJsonSchemaDefs.ts'; ================================================ FILE: packages/to-json-schema/src/functions/toJsonSchemaDefs/toJsonSchemaDefs.test.ts ================================================ import * as v from 'valibot'; import { describe, expect, test, vi } from 'vitest'; import { toJsonSchemaDefs } from './toJsonSchemaDefs.ts'; // TODO: Add tests for override configs console.warn = vi.fn(); describe('toJsonSchemaDefs', () => { describe('should convert schema', () => { test('for simple schema', () => { expect( toJsonSchemaDefs({ foo: v.string(), bar: v.number() }) ).toStrictEqual({ foo: { type: 'string' }, bar: { type: 'number' }, }); }); test('for complex schema with linked definitions', () => { const stringSchema = v.string(); const complexSchema = v.pipe( v.object({ name: v.lazy(() => stringSchema), email: v.pipe(stringSchema, v.email(), v.minLength(10)), age: v.optional(v.number()), }), v.description('foo') ); expect(toJsonSchemaDefs({ stringSchema, complexSchema })).toStrictEqual({ stringSchema: { type: 'string' }, complexSchema: { type: 'object', properties: { name: { $ref: '#/$defs/stringSchema' }, email: { type: 'string', format: 'email', minLength: 10 }, age: { type: 'number' }, }, required: ['name', 'email'], description: 'foo', }, }); }); test('for complex schema with any order of linked definitions', () => { const stringSchema = v.string(); const aliasesSchema = v.array(stringSchema); const complexSchema = v.pipe( v.object({ name: v.lazy(() => stringSchema), aliases: v.optional(aliasesSchema), email: v.pipe(stringSchema, v.email(), v.minLength(10)), }), v.description('foo') ); const expectedJsonSchemaDefs = { stringSchema: { type: 'string' }, aliasesSchema: { type: 'array', items: { $ref: '#/$defs/stringSchema' }, }, complexSchema: { type: 'object', properties: { name: { $ref: '#/$defs/stringSchema' }, aliases: { $ref: '#/$defs/aliasesSchema' }, email: { type: 'string', format: 'email', minLength: 10 }, }, required: ['name', 'email'], description: 'foo', }, }; const definitionPermutations = [ { stringSchema, aliasesSchema, complexSchema }, { stringSchema, complexSchema, aliasesSchema }, { aliasesSchema, stringSchema, complexSchema }, { aliasesSchema, complexSchema, stringSchema }, { complexSchema, stringSchema, aliasesSchema }, { complexSchema, aliasesSchema, stringSchema }, ]; for (const definitions of definitionPermutations) { expect(toJsonSchemaDefs(definitions)).toStrictEqual( expectedJsonSchemaDefs ); } }); test('for recursive schema', () => { const ul = v.object({ type: v.literal('ul'), children: v.array(v.lazy(() => li)), }); const li: v.GenericSchema = v.object({ type: v.literal('li'), children: v.array(v.union([v.string(), ul])), }); expect(toJsonSchemaDefs({ ul, li })).toStrictEqual({ ul: { properties: { children: { items: { $ref: '#/$defs/li' }, type: 'array', }, type: { const: 'ul' }, }, required: ['type', 'children'], type: 'object', }, li: { properties: { children: { items: { anyOf: [{ type: 'string' }, { $ref: '#/$defs/ul' }], }, type: 'array', }, type: { const: 'li' }, }, required: ['type', 'children'], type: 'object', }, }); }); }); describe('should throw error', () => { test('for invalid file schema', () => { expect(() => toJsonSchemaDefs({ foo: v.file() })).toThrowError( 'The "file" schema cannot be converted to JSON Schema.' ); expect(() => toJsonSchemaDefs({ foo: v.file() }, { errorMode: 'throw' }) ).toThrowError('The "file" schema cannot be converted to JSON Schema.'); }); test('for invalid credit card action', () => { expect(() => toJsonSchemaDefs({ foo: v.pipe(v.string(), v.creditCard()) }) ).toThrowError( 'The "credit_card" action cannot be converted to JSON Schema.' ); expect(() => toJsonSchemaDefs( { foo: v.pipe(v.string(), v.creditCard()) }, { errorMode: 'throw' } ) ).toThrowError( 'The "credit_card" action cannot be converted to JSON Schema.' ); }); }); describe('should warn error', () => { test('for invalid file schema', () => { expect( toJsonSchemaDefs({ foo: v.file() }, { errorMode: 'warn' }) ).toStrictEqual({ foo: {} }); expect(console.warn).toHaveBeenLastCalledWith( 'The "file" schema cannot be converted to JSON Schema.' ); }); test('for invalid credit card action', () => { expect( toJsonSchemaDefs( { foo: v.pipe(v.string(), v.creditCard()) }, { errorMode: 'warn' } ) ).toStrictEqual({ foo: { type: 'string' } }); expect(console.warn).toHaveBeenLastCalledWith( 'The "credit_card" action cannot be converted to JSON Schema.' ); }); }); describe('should ignore error', () => { test('for invalid file schema', () => { expect( toJsonSchemaDefs({ foo: v.file() }, { errorMode: 'ignore' }) ).toStrictEqual({ foo: {} }); }); test('for invalid credit card action', () => { expect( toJsonSchemaDefs( { foo: v.pipe(v.string(), v.creditCard()) }, { errorMode: 'ignore' } ) ).toStrictEqual({ foo: { type: 'string' } }); }); }); }); ================================================ FILE: packages/to-json-schema/src/functions/toJsonSchemaDefs/toJsonSchemaDefs.ts ================================================ import type * as v from 'valibot'; import { convertSchema } from '../../converters/index.ts'; import type { ConversionConfig, ConversionContext, JsonSchema, } from '../../types/index.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. */ export function toJsonSchemaDefs< TDefinitions extends Record< string, v.BaseSchema> >, >( definitions: TDefinitions, config?: Omit ): { [TKey in keyof TDefinitions]: JsonSchema } { // Initialize JSON Schema context const context: ConversionContext = { definitions: {}, referenceMap: new Map(), getterMap: new Map(), }; // Add provided definitions to context, if necessary for (const key in definitions) { context.referenceMap.set(definitions[key], key); } for (const key in definitions) { context.definitions[key] = convertSchema( {}, // @ts-expect-error definitions[key], config, context, true ); } // Return JSON Schema definitions // @ts-expect-error return context.definitions; } ================================================ FILE: packages/to-json-schema/src/functions/toStandardJsonSchema/index.ts ================================================ export * from './toStandardJsonSchema.ts'; ================================================ FILE: packages/to-json-schema/src/functions/toStandardJsonSchema/toStandardJsonSchema.test.ts ================================================ import * as v from 'valibot'; import { describe, expect, test } from 'vitest'; import { toStandardJsonSchema } from './toStandardJsonSchema.ts'; describe('toStandardJsonSchema', () => { const schema = v.pipe( v.string(), v.decimal(), v.toNumber(), v.number(), v.minValue(10) ); describe('should return schema object', () => { test('with string schema', () => { const result = toStandardJsonSchema(schema); expect(result).toStrictEqual({ '~standard': { version: 1, vendor: 'valibot', validate: expect.any(Function), jsonSchema: { input: expect.any(Function), output: expect.any(Function), }, }, }); }); }); describe('should throw error for unsupported target', () => { test('throws error for input conversion with unsupported target', () => { const result = toStandardJsonSchema(schema); expect(() => result['~standard'].jsonSchema.input({ target: 'unsupported-target', }) ).toThrowError('Unsupported target: unsupported-target'); }); test('throws error for output conversion with unsupported target', () => { const result = toStandardJsonSchema(schema); expect(() => result['~standard'].jsonSchema.output({ target: 'unsupported-target', }) ).toThrowError('Unsupported target: unsupported-target'); }); }); describe('should convert schema to JSON Schema', () => { test('converts schema to input JSON Schema', () => { const result = toStandardJsonSchema(schema); const jsonSchema = result['~standard'].jsonSchema.input({ target: 'draft-07', }); expect(jsonSchema).toStrictEqual({ $schema: 'http://json-schema.org/draft-07/schema#', type: 'string', pattern: '^[+-]?(?:\\d*\\.)?\\d+$', }); }); test('converts schema to output JSON Schema', () => { const result = toStandardJsonSchema(schema); const jsonSchema = result['~standard'].jsonSchema.output({ target: 'draft-07', }); expect(jsonSchema).toStrictEqual({ $schema: 'http://json-schema.org/draft-07/schema#', type: 'number', minimum: 10, }); }); }); }); ================================================ FILE: packages/to-json-schema/src/functions/toStandardJsonSchema/toStandardJsonSchema.ts ================================================ import type * as v from 'valibot'; import type { StandardJsonSchema } from '../../types/index.ts'; import { toJsonSchema } from '../toJsonSchema/index.ts'; type Target = 'draft-07' | 'draft-2020-12' | 'openapi-3.0'; 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. */ export function toStandardJsonSchema< TSchema extends v.BaseSchema>, >( schema: TSchema ): StandardJsonSchema, v.InferOutput> { return { '~standard': { ...schema['~standard'], jsonSchema: { input(options) { if (SUPPORTED_TARGETS.includes(options.target)) { return toJsonSchema(schema, { typeMode: 'input', target: options.target as Target, ...options.libraryOptions, }) as Record; } throw new Error(`Unsupported target: ${options.target}`); }, output(options) { if (SUPPORTED_TARGETS.includes(options.target)) { return toJsonSchema(schema, { typeMode: 'output', target: options.target as Target, ...options.libraryOptions, }) as Record; } throw new Error(`Unsupported target: ${options.target}`); }, }, }, }; } ================================================ FILE: packages/to-json-schema/src/index.ts ================================================ export * from './types/index.ts'; export * from './functions/index.ts'; export * from './storages/index.ts'; ================================================ FILE: packages/to-json-schema/src/storages/globalDefs/globalDefs.test.ts ================================================ import * as v from 'valibot'; import { describe, expect, test } from 'vitest'; import { addGlobalDefs, getGlobalDefs } from './globalDefs.ts'; describe('globalDefs', () => { test('should be undefined initially', () => { expect(getGlobalDefs()).toBeUndefined(); }); test('should return an empty object', () => { addGlobalDefs({}); expect(getGlobalDefs()).toStrictEqual({}); }); const schema1 = v.string(); const schema2 = v.number(); const schema3 = v.boolean(); test('should add global definitions', () => { addGlobalDefs({ schema1, schema2 }); expect(getGlobalDefs()).toStrictEqual({ schema1, schema2 }); addGlobalDefs({ schema3 }); expect(getGlobalDefs()).toStrictEqual({ schema1, schema2, schema3 }); }); test('should overwrite existing definitions', () => { const otherSchema = v.null(); addGlobalDefs({ schema2: otherSchema }); expect(getGlobalDefs()).toStrictEqual({ schema1, schema2: otherSchema, schema3, }); }); }); ================================================ FILE: packages/to-json-schema/src/storages/globalDefs/globalDefs.ts ================================================ import type * as v from 'valibot'; // Create global definitions store let store: | Record>> | undefined; /** * Adds new definitions to the global schema definitions. * * @param definitions The schema definitions. * * @beta */ export function addGlobalDefs( definitions: Record< string, v.BaseSchema> > ): void { store = { ...(store ?? {}), ...definitions }; } /** * Returns the current global schema definitions. * * @returns The schema definitions. * * @beta */ export function getGlobalDefs(): | Record>> | undefined { return store; } ================================================ FILE: packages/to-json-schema/src/storages/globalDefs/index.ts ================================================ export * from './globalDefs.ts'; ================================================ FILE: packages/to-json-schema/src/storages/index.ts ================================================ export * from './globalDefs/index.ts'; ================================================ FILE: packages/to-json-schema/src/types/config.ts ================================================ import type * as v from 'valibot'; import type { JsonSchema } from './schema.ts'; /** * JSON Schema conversion context interface. */ export interface ConversionContext { /** * The JSON Schema definitions that have already been created. */ readonly definitions: Record; /** * The JSON Schema reference map that is used to look up the reference ID * for a given Valibot schema. */ readonly referenceMap: Map< v.BaseSchema>, 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) => v.BaseSchema>, v.BaseSchema> >; } /** * JSON Schema override context interface for schemas. * * @beta */ export interface OverrideSchemaContext extends ConversionContext { /** * The JSON Schema reference ID. */ readonly referenceId: string | undefined; /** * The Valibot schema to be converted. */ readonly valibotSchema: v.BaseSchema>; /** * 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 */ export interface OverrideActionContext { /** * The Valibot action to be converted. */ // eslint-disable-next-line @typescript-eslint/no-explicit-any readonly valibotAction: v.PipeAction>; /** * 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 */ export interface OverrideRefContext extends ConversionContext { /** * The JSON Schema reference ID. */ readonly referenceId: string; /** * The Valibot schema to be converted. */ readonly valibotSchema: v.BaseSchema>; /** * The converted JSON Schema. */ readonly jsonSchema: JsonSchema; } /** * JSON Schema conversion config interface. */ export 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, v.BaseSchema> >; /** * 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; } ================================================ FILE: packages/to-json-schema/src/types/index.ts ================================================ export * from './config.ts'; export * from './schema.ts'; export * from './standard.ts'; ================================================ FILE: packages/to-json-schema/src/types/schema.ts ================================================ type JsonSchemaTypeName = | 'string' | 'number' | 'integer' | 'boolean' | 'object' | 'array' | 'null'; type JsonSchemaType = | string | number | boolean | JsonSchemaObject | JsonSchemaArray | null; interface JsonSchemaObject { [key: string]: JsonSchemaType; } // eslint-disable-next-line @typescript-eslint/no-empty-object-type interface JsonSchemaArray extends Array {} type JsonSchemaDefinition = JsonSchema | boolean; /** * JSON Schema interface. */ export interface JsonSchema { $id?: string | undefined; $ref?: string | undefined; $schema?: string | undefined; $comment?: string | undefined; $defs?: Record | 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 | undefined; patternProperties?: Record | undefined; additionalProperties?: JsonSchemaDefinition | undefined; dependencies?: Record | 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 | 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. */ // eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface JSONSchema7 extends JsonSchema {} ================================================ FILE: packages/to-json-schema/src/types/standard.ts ================================================ import type { StandardProps } from 'valibot'; /** * JSON Schema interface. */ export interface StandardJsonSchema { /** * The Standard JSON Schema properties. */ readonly '~standard': StandardJsonProps; } /** * The Standard JSON Schema properties interface. */ interface StandardJsonProps extends StandardProps { /** * 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; /** * Converts the output type to JSON Schema. May throw if conversion is not supported. */ readonly output: (options: StandardJsonOptions) => Record; } /** * 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 | undefined; } ================================================ FILE: packages/to-json-schema/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. */ export function addError( errors: [string, ...string[]] | undefined, message: string ): [string, ...string[]] { if (errors) { errors.push(message); return errors; } return [message]; } ================================================ FILE: packages/to-json-schema/src/utils/escapeRegExp.ts ================================================ // RegExp for matching special regex characters const ESCAPE_REGEX = /[.*+?^${}()|[\]\\]/g; /** * Escapes special regex characters in a string. * * @param string The string to escape. * * @returns The escaped string. */ export function escapeRegExp(string: string): string { return string.replace(ESCAPE_REGEX, '\\$&'); } ================================================ FILE: packages/to-json-schema/src/utils/handleError.ts ================================================ import type { ConversionConfig } from '../types/index.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. */ export function handleError( message: string, config: ConversionConfig | undefined ): void { switch (config?.errorMode) { case 'ignore': { break; } case 'warn': { console.warn(message); break; } default: { throw new Error(message); } } } ================================================ FILE: packages/to-json-schema/src/utils/index.ts ================================================ export * from './addError.ts'; export * from './escapeRegExp.ts'; export * from './handleError.ts'; export * from './isJsonConstValue.ts'; export * from './isJsonEnumValues.ts'; ================================================ FILE: packages/to-json-schema/src/utils/isJsonConstValue.ts ================================================ /** * Whether a value is JSON compatible for a const keyword. * * @param value The value to check. * * @returns Whether the value is JSON compatible. */ export function isJsonConstValue( value: unknown ): value is boolean | number | string { return ( typeof value === 'boolean' || (typeof value === 'number' && Number.isFinite(value)) || typeof value === 'string' ); } ================================================ FILE: packages/to-json-schema/src/utils/isJsonEnumValues.ts ================================================ import { isJsonConstValue } from './isJsonConstValue.ts'; /** * Whether values are JSON compatible for an enum keyword. * * @param values The values to check. * * @returns Whether the values are JSON compatible. */ export function isJsonEnumValues( values: readonly unknown[] ): values is (boolean | number | string)[] { return values.every(isJsonConstValue); } ================================================ FILE: packages/to-json-schema/src/vitest/createContext.ts ================================================ import type { ConversionContext } from '../types/index.ts'; /** * Creates a new conversion context. * * @param initial The initial context to use. * * @returns A new conversion context. */ export function createContext( initial?: Omit ): ConversionContext { return { definitions: initial?.definitions ?? {}, referenceMap: initial?.referenceMap ?? new Map(), getterMap: new Map(), }; } ================================================ FILE: packages/to-json-schema/src/vitest/index.ts ================================================ export * from './createContext.ts'; ================================================ FILE: packages/to-json-schema/tsconfig.json ================================================ { "compilerOptions": { "allowImportingTsExtensions": true, "declaration": true, "exactOptionalPropertyTypes": true, "isolatedDeclarations": true, "lib": ["ESNext", "DOM"], "module": "ESNext", "moduleResolution": "node", "noEmit": true, "skipLibCheck": true, "strict": true, "target": "ES2020", "paths": { "valibot": ["../../library/src/index.ts"], "valibot/*": ["../../library/src/*"] } }, "include": ["src"] } ================================================ FILE: packages/to-json-schema/tsdown.config.ts ================================================ import { defineConfig } from 'tsdown'; export default defineConfig([ { entry: ['./src/index.ts'], clean: true, format: ['es', 'cjs'], minify: false, dts: true, outDir: './dist', }, { entry: ['./src/index.ts'], clean: true, format: ['es', 'cjs'], minify: true, dts: false, outDir: './dist', outExtensions: ({ format }) => ({ js: format === 'cjs' ? '.min.cjs' : '.min.mjs', }), }, ]); ================================================ FILE: packages/to-json-schema/vitest.config.ts ================================================ import tsconfigPaths from 'vite-tsconfig-paths'; import { defineConfig } from 'vitest/config'; export default defineConfig({ plugins: [tsconfigPaths()], test: { isolate: false, coverage: { include: ['src'], exclude: ['**/index.ts', '**/types.ts', '**/*.test.ts'], }, }, }); ================================================ FILE: pnpm-workspace.yaml ================================================ packages: - 'codemod/*' - 'library' - 'packages/*' - 'website' ================================================ FILE: prettier.config.cjs ================================================ module.exports = { plugins: [ '@trivago/prettier-plugin-sort-imports', 'prettier-plugin-tailwindcss', ], printWidth: 80, tabWidth: 2, useTabs: false, semi: true, singleQuote: true, quoteProps: 'as-needed', jsxSingleQuote: false, trailingComma: 'es5', bracketSpacing: true, bracketSameLine: false, arrowParens: 'always', endOfLine: 'lf', // prettier-ignore importOrder: ['^\w', '^[./]'], importOrderSortSpecifiers: true, importOrderCaseInsensitive: true, }; ================================================ FILE: website/.gitignore ================================================ public/sitemap.xml public/llms.txt public/llms-full.txt public/llms-guides.txt public/llms-api.txt public/guides/ public/api/ ================================================ FILE: website/.node-version ================================================ 20 ================================================ FILE: website/.prettierignore ================================================ **/*.log **/.DS_Store *. .vscode/settings.json dist node_modules tmp server .cache .vscode *.spec.tsx *.spec.ts .netlify .vercel zod ================================================ FILE: website/README.md ================================================ # Website Our [website](https://valibot.dev/) contains guides, an API reference and a playground to quickly learn and understand Valibot. ## Getting started Step 1: Clone repository ```bash git clone git@github.com:open-circle/valibot.git ``` Step 2: Install dependencies ```bash pnpm install ``` Step 3: Build library ```bash cd ./library && pnpm build ``` Step 4: Start website ```bash cd ../website && pnpm start ``` ================================================ FILE: website/adapters/vercel-edge/vite.config.ts ================================================ import { vercelEdgeAdapter } from '@builder.io/qwik-city/adapters/vercel-edge/vite'; import { extendConfig } from '@builder.io/qwik-city/vite'; import { viteStaticCopy } from 'vite-plugin-static-copy'; import baseConfig from '../../vite.config'; export default extendConfig(baseConfig, () => { return { ssr: { external: ['@vercel/og'], }, build: { ssr: true, rollupOptions: { input: ['src/entry.vercel-edge.tsx', '@qwik-city-plan'], }, outDir: '.vercel/output/functions/_qwik-city.func', }, plugins: [ vercelEdgeAdapter({ ssg: { include: [], sitemapOutFile: null, }, }), viteStaticCopy({ targets: [ { src: 'node_modules/@vercel/og/**/*', dest: 'node_modules/@vercel/og/', }, ], }), ], }; }); ================================================ FILE: website/eslint.config.js ================================================ import js from '@eslint/js'; import { qwikEslint9Plugin } from 'eslint-plugin-qwik'; import { globalIgnores } from 'eslint/config'; import globals from 'globals'; import tseslint from 'typescript-eslint'; const ignores = [ '**/*.log', '**/.DS_Store', '**/*.', '.vscode/settings.json', '**/.history', '**/.yarn', '**/bazel-*', '**/bazel-bin', '**/bazel-out', '**/bazel-qwik', '**/bazel-testlogs', '**/dist', '**/dist-dev', '**/lib', '**/lib-types', '**/etc', '**/external', '**/node_modules', '**/temp', '**/tsc-out', '**/tsdoc-metadata.json', '**/target', '**/output', '**/rollup.config.js', '**/build', '**/.cache', '**/.vscode', '**/.rollup.cache', '**/dist', '**/tsconfig.tsbuildinfo', '**/vite.config.ts', '**/*.spec.tsx', '**/*.spec.ts', '**/.netlify', '**/pnpm-lock.yaml', '**/package-lock.json', '**/yarn.lock', '**/server', '**/zod', 'eslint.config.js', ]; export default tseslint.config( globalIgnores(ignores), js.configs.recommended, tseslint.configs.recommended, qwikEslint9Plugin.configs.recommended, { languageOptions: { globals: { ...globals.browser, ...globals.node, ...globals.es2021, ...globals.serviceworker, }, parserOptions: { projectService: true, tsconfigRootDir: import.meta.dirname, }, }, }, { rules: { '@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/ban-ts-comment': 'off', }, } ); ================================================ FILE: website/package.json ================================================ { "name": "website", "description": "The website and docs of Valibot", "version": "0.1.0", "license": "MIT", "author": "Fabian Hiller", "homepage": "https://valibot.dev", "repository": { "type": "git", "url": "https://github.com/open-circle/valibot" }, "type": "module", "scripts": { "build": "qwik build", "build.client": "vite build", "build.preview": "vite build --ssr src/entry.preview.tsx", "build.server": "vite build -c adapters/vercel-edge/vite.config.ts", "build.types": "tsc --incremental --noEmit", "contributors": "tsm ./scripts/contributors.ts", "deploy": "vercel deploy", "dev": "vite --mode ssr", "dev.debug": "node --inspect-brk ./node_modules/vite/bin/vite.js --mode ssr --force", "format": "prettier --write .", "format.check": "prettier --check .", "lint": "eslint \"src/**/*.ts*\" && tsc --noEmit", "preview": "qwik build preview && vite preview --open", "sitemap": "tsm ./scripts/sitemap.ts", "llms": "tsm ./scripts/llms.ts", "sources": "tsm ./scripts/sources.ts", "start": "vite --open --mode ssr", "qwik": "qwik" }, "devDependencies": { "@builder.io/qwik": "~1.17.2", "@builder.io/qwik-city": "~1.17.2", "@eslint/js": "^9.39.1", "@mapbox/rehype-prism": "^0.9.0", "@tailwindcss/vite": "^4.1.17", "@types/jscodeshift": "17.3.0", "@types/mapbox__rehype-prism": "^0.8.3", "@types/node": "^24.10.1", "dotenv": "^17.2.3", "eslint": "^9.39.1", "eslint-plugin-qwik": "~1.17.2", "globals": "^16.5.0", "gray-matter": "^4.0.3", "prettier": "^3.6.2", "rehype-external-links": "^3.0.0", "sharp": "^0.34.5", "tailwindcss": "^4.1.17", "tsm": "^2.3.0", "typescript": "^5.9.3", "typescript-eslint": "^8.47.0", "undici": "^7.16.0", "vercel": "^48.10.10", "vite": "^7.2.4", "vite-imagetools": "^9.0.0", "vite-plugin-node-polyfills": "^0.24.0", "vite-plugin-static-copy": "^3.1.4", "vite-tsconfig-paths": "^5.1.4" }, "dependencies": { "@valibot/zod-to-valibot": "workspace:*", "@vercel/og": "0.7.2", "@vercel/speed-insights": "^1.2.0", "clsx": "^2.1.1", "jscodeshift": "^17.3.0", "lz-string": "^1.5.0", "monaco-editor": "^0.55.1", "monaco-editor-textmate": "^4.0.0", "monaco-textmate": "^3.0.1", "onigasm": "^2.2.5", "satori-html": "^0.3.2", "sucrase": "^3.35.1", "valibot": "workspace:*" }, "engines": { "node": ">=20.0.0" } } ================================================ FILE: website/public/manifest.json ================================================ { "$schema": "https://json.schemastore.org/web-manifest-combined.json", "name": "Valibot", "short_name": "Valibot", "description": "Modular and type safe schema library", "theme_color": "#111827", "background_color": "#111827", "display": "standalone", "start_url": ".", "icons": [ { "src": "/icon-192px.png", "sizes": "192x192", "type": "image/png" }, { "src": "/icon-192px.jpeg", "sizes": "192x192", "type": "image/jpeg" }, { "src": "/icon-512px.png", "sizes": "512x512", "type": "image/png" }, { "src": "/icon-512px.jpeg", "sizes": "512x512", "type": "image/jpeg" } ] } ================================================ FILE: website/public/robots.txt ================================================ User-agent: * Disallow: Sitemap: https://valibot.dev/sitemap.xml ================================================ FILE: website/scripts/contributors.ts ================================================ import dotenv from 'dotenv'; import graymatter from 'gray-matter'; import fs from 'node:fs'; import path from 'node:path'; import { fetch } from 'undici'; import { findNestedFiles } from './utils/index'; // Load environment variables dotenv.config({ path: '.env.local', override: true }); /** * NOTE: Please create `.env.local`, and set your own `GITHUB_PERSONAL_ACCESS_TOKEN`. * This token is required because of the GitHub API rate limit. https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting * How to create a personal access token: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token */ const GITHUB_PERSONAL_ACCESS_TOKEN = process.env.GITHUB_PERSONAL_ACCESS_TOKEN; const EXCLUDED_COMMITS = ['2cc351f6db7798cf60276225abcbacbc1ea491db']; /** * Updates the contributors of the guides and API reference. */ async function updateContributors() { // Check if GitHub personal access token is available if (!GITHUB_PERSONAL_ACCESS_TOKEN) { throw new Error('Missing GITHUB_PERSONAL_ACCESS_TOKEN'); } // Find all MDX files of guides and API reference const filePaths = findNestedFiles( [path.join('src', 'routes', 'guides'), path.join('src', 'routes', 'api')], (fileName) => fileName === 'index.mdx' ); // Update contributors of each MDX file for (const filePath of filePaths) { // Log info to console console.log('Update:', filePath); // Read frontmatter of MDX file const frontmatter = graymatter.read(filePath); // Create API URL and add query parameters const url = new URL( 'https://api.github.com/repos/open-circle/valibot/commits' ); url.searchParams.set('since', '2023-07-13T00:00:00.000Z'); url.searchParams.set('path', `website/${filePath.replace(/\\/g, '/')}`); // Fetch commits of file from GitHub const response = await fetch(url.href, { headers: { Authorization: `Bearer ${GITHUB_PERSONAL_ACCESS_TOKEN}`, }, }); // Continue if GitHub responded with status code 200 if (response.status === 200) { // Get commits from response const commits = (await response.json()) as { sha: string; author: { login: string } | null; }[]; // Create contributors list const contributors: { author: string; count: number }[] = []; // Count commits of each author for (const commit of commits) { if (!EXCLUDED_COMMITS.includes(commit.sha) && commit.author) { const author = commit.author.login; const contributor = contributors.find( (contributor) => contributor.author === author ); if (contributor) { contributor.count++; } else { contributors.push({ author, count: 1 }); } } } // Sort contributors by commit count contributors.sort((a, b) => a.count < b.count ? 1 : a.count > b.count ? -1 : 0 ); // Add contributors to frontmatter frontmatter.data.contributors = [ ...new Set([ ...contributors.map((contributor) => contributor.author), ...(frontmatter.data.contributors || []), ]), ]; // Write changes to MDX file fs.writeFileSync( filePath, graymatter.stringify(frontmatter.content, frontmatter.data) ); // Otherwise, log error to console } else { console.log( 'error', response.status, response.statusText, await response.text() ); } } } // Start update process updateContributors(); ================================================ FILE: website/scripts/llms.ts ================================================ import graymatter from 'gray-matter'; import fs from 'node:fs'; import path from 'node:path'; // Read menu.md of guides and API const menuOfGuides = fs.readFileSync( path.join('src', 'routes', 'guides', 'menu.md'), 'utf-8' ); const menuOfApi = fs.readFileSync( path.join('src', 'routes', 'api', 'menu.md'), 'utf-8' ); /** * Converts a markdown menu to a string suitable for our llms.txt file. * * @param markdown The markdown string to convert. * * @returns A llms.txt compatible string. */ function convertMenuToLlms(markdown: string): string { return ( markdown // Change levels of headings to one level down .replaceAll(/^#/gm, '##') // Replace relative paths with URLs to MD files .replaceAll(/\(\/(.+)\/\)$/gm, '(https://valibot.dev/$1.md)') ); } // Create llms.txt intro text const introText = '# Valibot\n\nThe modular and type safe schema library for validating structural data.\n'; // Create llms.txt file with content of guides and API menus const llmsTxt = `${introText}\n${convertMenuToLlms(menuOfGuides)}\n${convertMenuToLlms(menuOfApi)}`; // Write llms.txt file to public directory fs.writeFileSync(path.join('public', 'llms.txt'), llmsTxt); /** * Extracts grouped file paths from a markdown menu. * * @param markdown The markdown menu string. * * @returns A grouped array of file paths. */ function extractFilePathsOfMenu( markdown: string ): { title: string; files: { name: string; path: string }[] }[] { // Split menu into groups based on level 2 headings const groups = markdown.split(/^## /gm).slice(1); // Convert groups into an array of MDX file paths return groups.map((group) => { // Extract title and create slug const groupTitle = group.match(/(^.+)\n/)![1]; const groupSlug = groupTitle.toLowerCase().replace(/\s+/g, '-'); // Create object to hold title and file data const groupData: { title: string; files: { name: string; path: string }[]; } = { title: groupTitle, files: [] }; // Extract file paths from group using regex const filePaths = group.matchAll(/\(\/(.+)\/(.+)\/\)/gm); // Add data of each file path to group data for (const regexMatch of filePaths) { // Extract area and name from regex match const fileArea = regexMatch[1]; const fileName = regexMatch[2]; // Create MDX file path based on area, group slug and name const filePath = path.join( 'src', 'routes', fileArea, `(${groupSlug})`, fileName, 'index.mdx' ); // Add file data to fiels of group data groupData.files.push({ name: fileName, path: filePath, }); } // Return final group data return groupData; }); } // Create object to hold content for specific llms files const llms: Record<'full' | 'guides' | 'api', string> = { full: introText, guides: introText, api: introText, }; // Define content areas with all necessary data const contentAreas = [ { id: 'guides', name: 'guides', publicDir: path.join('public', 'guides'), groups: extractFilePathsOfMenu(menuOfGuides), }, { id: 'api', name: 'API', publicDir: path.join('public', 'api'), groups: extractFilePathsOfMenu(menuOfApi), }, ] as const; // Copy content of MDX files to public dir and add it to llms files for (const contentArea of contentAreas) { // Ensure directory of content area exists if (!fs.existsSync(contentArea.publicDir)) { fs.mkdirSync(contentArea.publicDir); } // Add group title to llms files and process its files for (const areaGroup of contentArea.groups) { // Create level 2 heading for group const heading = `## ${areaGroup.title}`; // Add heading to specific llms files llms.full += `\n${heading} (${contentArea.name})\n`; llms[contentArea.id] += `\n${heading}\n`; // Copy content of MDX files to public dir and add content to llms files for (const mdxFile of areaGroup.files) { // Read MDX file and extract frontmatter const frontmatter = graymatter.read(mdxFile.path); // Remove MDX import statements from MDX content const mdxContent = frontmatter.content.slice( frontmatter.content.indexOf('# ') // Index of first heading ); // Copy MDX content into public directory fs.writeFileSync( path.join(contentArea.publicDir, `${mdxFile.name}.md`), mdxContent ); // Change level of headings two levels down const llmsContent = mdxContent.replaceAll(/^#/gm, '###'); // Add content to specific llms files llms.full += `\n${llmsContent}`; llms[contentArea.id] += `\n${llmsContent}`; } } } // Write specific llms files to public directory fs.writeFileSync(path.join('public', 'llms-full.txt'), llms.full); fs.writeFileSync(path.join('public', 'llms-guides.txt'), llms.guides); fs.writeFileSync(path.join('public', 'llms-api.txt'), llms.api); ================================================ FILE: website/scripts/sitemap.ts ================================================ import fs from 'node:fs'; import path from 'node:path'; import { findNestedFiles } from './utils/index'; const ORIGIN = 'https://valibot.dev'; // Find all route index files const filePaths = findNestedFiles( [path.join('src', 'routes')], (fileName) => fileName === 'index.tsx' || fileName === 'index.mdx' ); // Create URL paths and sort them let urlSet = filePaths // Transform file paths to URL paths .map((filePath) => filePath .replace(/\\/g, '/') .replace(/src\/routes\//, '') .replace(/\(.+\)\//, '') .replace(/index\.(tsx|mdx)/, '') ) // Sort URL paths alphabetically .sort() // Reduce URL paths to URL set .reduce( (urlPaths, urlPath) => `${urlPaths}${ORIGIN}/${urlPath}`, '' ); // Add thesis to URL set urlSet += `${ORIGIN}/thesis.pdf`; // Write sitemap.xml to public directory fs.writeFileSync( path.join('public', 'sitemap.xml'), `${urlSet}` ); ================================================ FILE: website/scripts/sources.ts ================================================ import graymatter from 'gray-matter'; import fs from 'node:fs'; import path from 'node:path'; import { findNestedFiles } from './utils/index'; // Find all MDX files of API reference const filePaths = findNestedFiles( [path.join('src', 'routes', 'api')], (fileName) => fileName === 'index.mdx' ); // Update source file paths of MDX files for (const filePath of filePaths) { if (!filePath.includes('(types)')) { // Log info to console console.log('Update:', filePath); // Get group and name of source code file const pathList = filePath.split('/'); let group = pathList.slice(3, 4)[0].replace('(', '').replace(')', ''); const name = pathList.slice(4, 5)[0]; // If group is async, find non-async group if (group === 'async') { const nonAsync = filePaths.find( (filePath) => !filePath.includes('(async)') && filePath.includes(name.replace('Async', '')) ); group = nonAsync! .split('/') .slice(3, 4)[0] .replace('(', '') .replace(')', ''); } // Create path to source code file const source = `/${group}/${name.replace('Async', '')}/${name}.ts`; // Read frontmatter of MDX file const frontmatter = graymatter.read(filePath); // Add source code file path to frontmatter frontmatter.data.source = source; // Write changes to MDX file fs.writeFileSync( filePath, graymatter.stringify(frontmatter.content, frontmatter.data) ); } } ================================================ FILE: website/scripts/utils/findNestedFiles.ts ================================================ import fs from 'node:fs'; import path from 'node:path'; /** * Finds nested files in the given directories. * * @param directories The directories to search in. * @param requirement The requirement for a file to be included. * * @returns A list of file paths. */ export function findNestedFiles( directories: string[], requirement: (fileName: string) => boolean ) { // Create file paths list const filePaths: string[] = []; // Search for index files in each directory for (const directory of directories) { // Get items of directory const items = fs.readdirSync(directory); for (const itemName of items) { // If item matches requirement, add it to list if (requirement(itemName)) { filePaths.push(path.join(directory, itemName)); // Otherwise, search for nested files } else { const itemPath = path.join(directory, itemName); const itemStat = fs.statSync(itemPath); if (itemStat.isDirectory()) { filePaths.push(...findNestedFiles([itemPath], requirement)); } } } } // Return file paths list return filePaths; } ================================================ FILE: website/scripts/utils/index.ts ================================================ export * from './findNestedFiles'; ================================================ FILE: website/src/components/ActionButton.tsx ================================================ import { component$ } from '@builder.io/qwik'; import clsx from 'clsx'; import { type DefaultButtonProps, UnstyledButton } from './UnstyledButton'; type ActionButtonProps = DefaultButtonProps & { variant: 'primary' | 'secondary'; label: string; }; /** * Button that is used for navigation, to confirm form entries or perform * individual actions. */ export const ActionButton = component$( ({ label, variant, ...props }) => ( {label} ) ); ================================================ FILE: website/src/components/ApiList.tsx ================================================ import { component$ } from '@builder.io/qwik'; import { Link } from './Link'; type ApiListProps = { label?: string; items: string[]; }; /** * List to display APIs and navigate to their documentation. */ export const ApiList = component$(({ label, items }) => (
    {label && label + ': '} {items.map((item, index) => (
  • {item} {index < items.length - 1 && ','}
  • ))}
)); ================================================ FILE: website/src/components/ButtonGroup.tsx ================================================ import { component$, Slot } from '@builder.io/qwik'; import clsx from 'clsx'; type ButtonGroupProps = { class?: string; }; /** * Button group displays multiple related actions side-by-side and helps with * arrangement and spacing. */ export const ButtonGroup = component$((props) => (
)); ================================================ FILE: website/src/components/Chapters.tsx ================================================ import { component$, useComputed$, useSignal, useTask$, useVisibleTask$, } from '@builder.io/qwik'; import { useContent } from '@builder.io/qwik-city'; import clsx from 'clsx'; /** * Navigation list used to display the current page's content structure. */ export const Chapters = component$(() => { // Use content and active ID signal const content = useContent(); const activeId = useSignal(); // Use list element and indicator style signal const listElement = useSignal(); const indicatorStyle = useSignal<{ top: string; height: string; }>(); // Compute filtererd level 2 headings const headings = useComputed$( () => // Use level 2 headings for subpages content.headings?.filter((heading) => heading.level === 2) || // Or use main menu items for top level pages content.menu?.items?.map((heading) => ({ text: heading.text, id: heading.text.toLowerCase(), })) || [] ); // Reset active ID when headings change useTask$(({ track }) => { track(headings); activeId.value = undefined; }); // Update active ID when heading is intersecting // eslint-disable-next-line qwik/no-use-visible-task useVisibleTask$(({ track, cleanup }) => { // Update observer when headings change track(headings); // Create intersection observer const observer = new IntersectionObserver( (entries) => { // Check every intersection entry for (let index = 0; index < entries.length; index++) { const entry = entries[index]; // Mark first visible heading or last heading that is above viewport // as active if ( entry.isIntersecting || (index > 0 && index === entries.length - 1 && entry.boundingClientRect.top < 0) ) { activeId.value = entry.target.id; break; } // Mark previous heading of first heading below intersection // bounding box, if any, as active if (entry.boundingClientRect.top > 0) { activeId.value = headings.value[ headings.value.findIndex( (heading) => heading.id === entry.target.id ) - 1 ]?.id; break; } } }, // Observe only top 30% of window { rootMargin: '0px 0px -70% 0px' } ); // Observe every heading element headings.value.forEach((heading) => observer.observe(document.getElementById(heading.id)!) ); // Disconnect observer on cleanup cleanup(() => observer.disconnect()); }); // Update indicator style when active ID changes // eslint-disable-next-line qwik/no-use-visible-task useVisibleTask$(({ track }) => { track(activeId); // Get active list element by pathname and href const activeElement = [...listElement.value!.children].find((e) => (e.children[0] as HTMLAnchorElement).href.endsWith(`#${activeId.value}`) ) as HTMLLIElement | undefined; // Update indicator style to active element or reset it to undefined indicatorStyle.value = activeElement ? { top: `${activeElement.offsetTop}px`, height: `${activeElement.offsetHeight}px`, } : undefined; }); return ( ); }); ================================================ FILE: website/src/components/CodeEditor.tsx ================================================ import { $, component$, type NoSerialize, noSerialize, type QRL, type Signal, sync$, useComputed$, useSignal, useTask$, useVisibleTask$, } from '@builder.io/qwik'; import { isBrowser } from '@builder.io/qwik/build'; import clsx from 'clsx'; import * as monaco from 'monaco-editor'; import { wireTmGrammars } from 'monaco-editor-textmate'; import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'; import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'; import { Registry } from 'monaco-textmate'; import { loadWASM } from 'onigasm'; import onigasm from 'onigasm/lib/onigasm.wasm?url'; import prettierPluginEstree from 'prettier/plugins/estree'; import prettierPluginTypeScript from 'prettier/plugins/typescript'; import { formatWithCursor } from 'prettier/standalone'; import { useTheme } from '~/routes/plugin@theme'; import valibotTypes from '../../../library/dist/index.d.mts?raw'; import valibotPackageJson from '../../../library/package.json?raw'; import valibotToJsonSchemaTypes from '../../../packages/to-json-schema/dist/index.d.mts?raw'; import valibotToJsonSchemaPackageJson from '../../../packages/to-json-schema/package.json?raw'; import typescriptTm from '../json/TypeScript.tmLanguage.json'; type CodeEditorProps = { class: string; value: Signal; model: Signal>; onSave$?: QRL<() => void>; }; /** * Monaco code editor with TypeScript support and syntax highlighting. */ export const CodeEditor = component$( ({ value, model, onSave$, ...props }) => { // Use theme const theme = useTheme(); // Use element and editor signal const element = useSignal(); const editor = useSignal>(); // Compute editor theme name const editorTheme = useComputed$(() => theme.value === 'dark' ? 'pace-dark' : 'pace-light' ); /** * Returns device specific editor options. */ const getDeviceOptions = $(() => window.innerWidth <= 640 ? { fontSize: 16, padding: { top: 20, bottom: 20 }, lineNumbersMinChars: 3, } : { fontSize: 18, padding: { top: 40, bottom: 40 }, lineNumbersMinChars: 4, } ); // Initialize and setup Monaco editor // eslint-disable-next-line qwik/no-use-visible-task useVisibleTask$(async ({ cleanup }) => { // Initialize Monaco editor environment await initializeMonaco(); // Create model for Monaco editor instance model.value = noSerialize( monaco.editor.createModel( value.value, 'typescript', monaco.Uri.parse('file:///index.ts') ) ); // Create Monaco editor instance with model editor.value = noSerialize( monaco.editor.create(element.value!, { ...(await getDeviceOptions()), autoDetectHighContrast: false, automaticLayout: true, // @ts-expect-error 'bracketPairColorization.enabled': false, fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace', model: model.value, minimap: { enabled: false }, scrollBeyondLastLine: false, theme: editorTheme.value, }) ); // Dispose editor and model on cleanup cleanup(() => { editor.value!.dispose(); model.value!.dispose(); }); }); // Update theme on change useTask$(async ({ track }) => { track(editorTheme); if (isBrowser) { editor.value?.updateOptions({ theme: editorTheme.value, }); } }); /** * Updates the device options of the code editor. */ const updateDeviceOptions = $(async () => editor.value?.updateOptions(await getDeviceOptions()) ); /** * Handles keyboard keydown events. */ const handleKeyDown = $(async (event: KeyboardEvent) => { if ((event.ctrlKey || event.metaKey) && event.key === 's') { // Format code with Prettier try { const prettier = await formatWithCursor(model.value!.getValue(), { cursorOffset: model.value!.getOffsetAt( editor.value!.getPosition()! ), parser: 'typescript', plugins: [prettierPluginEstree, prettierPluginTypeScript], singleQuote: true, }); model.value!.pushEditOperations( null, [ { range: model.value!.getFullModelRange(), text: prettier.formatted, }, ], () => null ); editor.value!.setPosition( model.value!.getPositionAt(prettier.cursorOffset) ); } catch { // Ignore formatting errors } // Execute save event onSave$?.(); } }); /** * Prevents default behavior of keydown events. */ const preventDefault = sync$((event: KeyboardEvent) => { if ((event.ctrlKey || event.metaKey) && event.key === 's') { event.preventDefault(); } }); return (
); } ); /** * Sets up the Monaco editor environment. */ async function setupMonaco() { // Load Onigasm WebAssembly module await loadWASM(onigasm); // Wire TypeScript TextMate grammar await wireTmGrammars( monaco, new Registry({ getGrammarDefinition: async () => ({ format: 'json', content: typescriptTm, }), }), new Map().set('typescript', 'source.ts') ); // Setup TypeScript and edior workers window.MonacoEnvironment = { getWorker: (_, label) => label === 'typescript' ? new tsWorker() : new editorWorker(), }; // Define pace dark mode theme monaco.editor.defineTheme('pace-dark', { base: 'vs-dark', inherit: false, colors: { 'editor.foreground': '#CBD5E1', 'editor.background': '#111827', 'editor.selectionBackground': '#334155', 'editor.lineHighlightBackground': '#1E293B', 'editorCursor.foreground': '#E2E8F0', 'editorHoverWidget.border': '#1E293B', 'editorLineNumber.foreground': '#64748B', 'editorLineNumber.activeForeground': '#CBD5E1', 'editorIndentGuide.background': '#334155', 'editorWhitespace.foreground': '#334155', 'editorWidget.background': '#0A101C', 'scrollbarSlider.activeBackground': '#64748B80', 'scrollbarSlider.background': '#33415580', 'scrollbarSlider.hoverBackground': '#47556980', }, rules: [ { token: 'comment', foreground: '#6B7280', }, { token: 'string', foreground: '#FDE68A', }, { token: 'string.regex', foreground: '#CBD5E1', }, { token: 'constant', foreground: '#2DD4BF', }, { token: 'constant.numeric', foreground: '#C084FC', }, { token: 'keyword', foreground: '#F87171', }, { token: 'keyword.operator.assignment', foreground: '#94A3B8', }, { token: 'storage', foreground: '#2DD4BF', }, { token: 'entity', foreground: '#34D399', }, { token: 'entity.name.type', foreground: '#38BDF8', }, { token: 'variable', foreground: '#38BDF8', }, { token: 'variable.parameter', foreground: '#FDBA74', }, { token: 'punctuation', foreground: '#94A3B8', }, { token: 'punctuation.definition.string', foreground: '#FDE68A', }, { token: 'punctuation.definition.group.regexp', foreground: '#F87171', }, { token: 'punctuation.definition.character-class', foreground: '#2DD4BF', }, { token: 'support', foreground: '#2DD4BF', }, { token: 'support.class', foreground: '#38BDF8', }, ], }); // Define pace light mode theme monaco.editor.defineTheme('pace-light', { base: 'vs', inherit: false, colors: { 'editor.foreground': '#334155', 'editor.background': '#FFFFFF', 'editor.selectionBackground': '#CBD5E1', 'editor.lineHighlightBackground': '#F1F5F9', 'editorCursor.foreground': '#0F172A', 'editorHoverWidget.border': '#E2E8F0', 'editorIndentGuide.background': '#CBD5E1', 'editorLineNumber.foreground': '#94A3B8', 'editorLineNumber.activeForeground': '#334155', 'editorWhitespace.foreground': '#CBD5E1', 'editorWidget.background': '#F1F5F9', 'scrollbarSlider.activeBackground': '#94A3B880', 'scrollbarSlider.background': '#E2E8F080', 'scrollbarSlider.hoverBackground': '#CBD5E180', }, rules: [ { token: 'comment', foreground: '#94A3B8', }, { token: 'string', foreground: '#CA8A04', }, { token: 'string.regex', foreground: '#334155', }, { token: 'constant', foreground: '#0D9488', }, { token: 'constant.numeric', foreground: '#9333EA', }, { token: 'keyword', foreground: '#DC2626', }, { token: 'keyword.operator.assignment', foreground: '#64748B', }, { token: 'storage', foreground: '#0D9488', }, { token: 'entity', foreground: '#059669', }, { token: 'entity.name.type', foreground: '#0284C7', }, { token: 'variable', foreground: '#0284C7', }, { token: 'variable.parameter', foreground: '#F97316', }, { token: 'punctuation', foreground: '#64748B', }, { token: 'punctuation.definition.string', foreground: '#CA8A04', }, { token: 'punctuation.definition.group.regexp', foreground: '#DC2626', }, { token: 'punctuation.definition.character-class', foreground: '#0D9488', }, { token: 'support', foreground: '#059669', }, { token: 'support.class', foreground: '#0284C7', }, ], }); // Add Valibot to context of editor monaco.typescript.typescriptDefaults.addExtraLib( valibotPackageJson, 'file:///node_modules/valibot/package.json' ); monaco.typescript.typescriptDefaults.addExtraLib( valibotTypes, 'file:///node_modules/valibot/dist/index.d.mts' ); // Add to-json-schema to context of editor monaco.typescript.typescriptDefaults.addExtraLib( valibotToJsonSchemaPackageJson, 'file:///node_modules/@valibot/to-json-schema/package.json' ); monaco.typescript.typescriptDefaults.addExtraLib( valibotToJsonSchemaTypes, 'file:///node_modules/@valibot/to-json-schema/dist/index.d.mts' ); // Set TypeScript compiler options monaco.typescript.typescriptDefaults.setCompilerOptions({ strict: true, exactOptionalPropertyTypes: true, target: monaco.typescript.ScriptTarget.ESNext, module: monaco.typescript.ModuleKind.ESNext, moduleResolution: monaco.typescript.ModuleResolutionKind.NodeJs, skipLibCheck: true, }); } // Create initialization promise let promise: Promise | undefined; /** * Initializes Monaco editor environment. */ async function initializeMonaco() { if (!promise) { promise = setupMonaco(); } await promise; } ================================================ FILE: website/src/components/Credits.tsx ================================================ import { component$ } from '@builder.io/qwik'; import { useDocumentHead } from '@builder.io/qwik-city'; import { AlgoliaLogo, BoltLogo, BuilderLogo, DigitalOceanLogo, HdmLogo, MotionLogo, PaceLogo, StainlessLogo, TestMuAiLogo, VercelLogo, } from '~/logos'; /** * Displays the contributors of the current page as well as partners and * sponsors of the project. */ export const Credits = component$(() => { const head = useDocumentHead<{ contributors?: string[] }>(); return (
{!!head.frontmatter.contributors?.length && ( <>

Contributors

Thanks to all the contributors who helped make this page better!

    {head.frontmatter.contributors.map((contributor) => (
  • {`GitHub
  • ))}
)}

Partners

Thanks to our partners who support the project ideally and financially.

    {[ { Logo: PaceLogo, href: 'https://www.pace.edu' }, { Logo: HdmLogo, href: 'https://www.hdm-stuttgart.de' }, { Logo: BoltLogo, href: 'https://bolt.new/' }, { Logo: MotionLogo, href: 'https://www.usemotion.com/' }, { Logo: VercelLogo, href: 'https://vercel.com' }, { Logo: StainlessLogo, href: 'https://www.stainless.com/' }, { Logo: TestMuAiLogo, href: 'https://www.testmuai.com/?utm_medium=sponsor&utm_source=valibot', }, { Logo: AlgoliaLogo, href: 'https://www.algolia.com' }, { Logo: DigitalOceanLogo, href: 'https://www.digitalocean.com/' }, { Logo: BuilderLogo, href: 'https://www.builder.io' }, ].map(({ Logo, href }) => (
  • ))}

Sponsors

Thanks to our GitHub sponsors who support the project financially.

    {[ 'antfu', 'UpwayShop', 'vasilii-kovalev', 'saturnonearth', 'ruiaraujo012', 'hyunbinseo', 'nickytonline', 'KubaJastrz', 'kibertoad', 'Thanaen', 'caegdeveloper', 'bmoyroud', 'dslatkin', ].map((sponsor) => (
  • {`GitHub
  • ))}
); }); ================================================ FILE: website/src/components/DiscordIconLink.tsx ================================================ import { component$ } from '@builder.io/qwik'; import { DiscordIcon } from '~/icons'; import { SystemIcon } from './SystemIcon'; /** * Discord icon pointing to our community server. */ export const DiscordIconLink = component$(() => ( )); ================================================ FILE: website/src/components/DocSearch.tsx ================================================ import { $, component$, type Signal, sync$, useComputed$, useSignal, useTask$, } from '@builder.io/qwik'; import { useLocation, useNavigate } from '@builder.io/qwik-city'; import { isBrowser } from '@builder.io/qwik/build'; import clsx from 'clsx'; import { useFocusTrap, useStorageSignal } from '~/hooks'; import { AngleRightIcon, CloseIcon, HashtagIcon, PageIcon, SearchIcon, } from '~/icons'; import { AlgoliaLogo } from '~/logos'; import { trackEvent } from '~/utils'; import { Link } from './Link'; import { SystemIcon } from './SystemIcon'; import { TextLink } from './TextLink'; type HitType = 'lvl2' | 'lvl3' | 'lvl4' | 'lvl5' | 'content'; type AlgoliaResult = { hits: { type: HitType; hierarchy: { lvl0: string; lvl1: string; lvl2: string; lvl3: string | null; lvl4: string | null; }; content: string | null; url: string; _highlightResult: { hierarchy: { lvl0: { value: string }; lvl1: { value: string }; lvl2: { value: string }; lvl3: { value: string } | undefined; lvl4: { value: string } | undefined; lvl5: { value: string } | undefined; }; }; _snippetResult?: { content: { value: string }; }; }[]; }; type SearchItem = { group: string; relation: 'page' | 'child' | 'none'; type: HitType; page: string; text: string; path: string; }; type SearchStorage = { [key: string]: | { result: SearchItem[]; expires: number; } | undefined; }; type DocSearchProps = { open: Signal; }; /** * Provides a search box for the documentation. */ export const DocSearch = component$(({ open }) => { // Use location and navigate const location = useLocation(); const navigate = useNavigate(); // Use input, loading, active index and error signal const input = useSignal(''); const loading = useSignal(false); const activeIndex = useSignal(0); const error = useSignal(false); // Use modal and input element signal const modalElement = useSignal(); const inputElement = useSignal(); // Use storage, recent, result and clicked signal const storage = useStorageSignal('search-index', {}); const recent = useStorageSignal('search-recent', []); const result = useSignal([]); const clicked = useSignal(null); // Compute search items const searchItems = useComputed$(() => input.value ? result.value : recent.value ); // Use focus trap when search is open useFocusTrap(modalElement, open); // Do stuff when search is opened or closed useTask$(({ track }) => { track(inputElement); track(open); if (isBrowser && inputElement.value) { // Focus input and block background scrolling when search is opened if (open.value) { inputElement.value.focus(); document.body.style.overflow = 'hidden'; // Tracke open search event trackEvent('open_search'); // Otherwise when search is closed, add clicked item to recent and // reset state and background scrolling } else { const item = clicked.value; if (item) { recent.value = [ item, ...recent.value.filter((i) => i !== item).slice(0, 5), ]; // Track seleact search item event trackEvent('select_search_item', { input: input.value, path: item.path, }); } // Reset state and background scrolling input.value = ''; activeIndex.value = 0; result.value = []; clicked.value = null; document.body.style.overflow = ''; } } }); // Close search when location changes useTask$(({ track }) => { track(() => location.prevUrl); if (isBrowser) { open.value = false; } }); // Update search result and active index when input changes useTask$(({ track, cleanup }) => { const currentInput = track(input); if (isBrowser) { // Reset error state error.value = false; // If input is present, query and set search result if (currentInput) { // Get its current value const storageValue = storage.value[currentInput]; // Set result of index values is present and not expired if (storageValue && storageValue.expires >= Date.now()) { activeIndex.value = storageValue.result.length ? 0 : -1; result.value = storageValue.result; loading.value = false; // Otherwise query search result from Algolia with a short timeout to // reduce unnecessary queries } else { const timeout = setTimeout(async () => { try { const algoliaResult = (await ( await fetch( `https://${ import.meta.env.PUBLIC_ALGOLIA_APP_ID }-dsn.algolia.net/1/indexes/${ import.meta.env.PUBLIC_ALGOLIA_INDEX_NAME }/query`, { method: 'POST', headers: { 'X-Algolia-Application-Id': import.meta.env .PUBLIC_ALGOLIA_APP_ID, 'X-Algolia-API-Key': import.meta.env .PUBLIC_ALGOLIA_PUBLIC_API_KEY, 'Content-Type': 'application/json', }, body: JSON.stringify({ query: currentInput, filters: 'NOT type:lvl1', }), } ) ).json()) as AlgoliaResult; // Transform hits of Algolia result to our schema let prevItem: SearchItem | undefined; const searchResult: SearchItem[] = algoliaResult.hits.map( (hit) => { // Create path by removing origin from URL const path = hit.url.replace( import.meta.env.PUBLIC_WEBSITE_URL, '' ); // Create search item object const searchItem: SearchItem = { group: `${hit.hierarchy.lvl0}${hit.hierarchy.lvl1 ? `: ${hit.hierarchy.lvl1}` : ''}`, relation: hit.type === 'lvl2' ? 'page' : prevItem && prevItem.relation !== 'none' && prevItem.path.split('#')[0] === path.split('#')[0] ? 'child' : 'none', type: hit.type, page: hit._highlightResult.hierarchy.lvl2.value, text: hit.type === 'content' ? hit._snippetResult!.content.value : hit._highlightResult.hierarchy[hit.type]!.value, path, }; // Update previous item variable prevItem = searchItem; // Return search item object return searchItem; } ); // Add search result to search storage storage.value = { ...storage.value, [currentInput]: { result: searchResult, expires: Date.now() + 6.048e8, // 7 days }, }; // Set search result if input has not changed if (currentInput === input.value) { activeIndex.value = 0; result.value = searchResult; loading.value = false; } // Update state in case of an error } catch { error.value = true; } }, 150); // Set loading to "true" loading.value = true; // Clear timeout if the input has changed in the meantime cleanup(() => clearTimeout(timeout)); } // Otherwise if input is empty, reset state } else { activeIndex.value = 0; result.value = []; loading.value = false; } } }); /** * Handles the click on a search item. */ const handleClick = $((item: SearchItem) => { if (item.path === location.url.pathname) { open.value = false; } clicked.value = item; }); /** * Handles keyboard keydown events. */ const handleKeyDown = $((event: KeyboardEvent) => { // Open or close search if ( ((event.ctrlKey || event.metaKey) && event.key === 'k') || (open.value && event.key === 'Escape') ) { open.value = !open.value; } if (open.value) { // Change active index if (event.key === 'ArrowUp' || event.key === 'ArrowDown') { const maxIndex = searchItems.value.length - 1; activeIndex.value = event.key === 'ArrowUp' ? activeIndex.value === 0 ? maxIndex : activeIndex.value - 1 : activeIndex.value === maxIndex ? 0 : activeIndex.value + 1; } // Select current active index if (event.key === 'Enter') { const item = searchItems.value[activeIndex.value]; if (item) { if (item.path === location.url.pathname) { open.value = false; } else { navigate(item.path); } clicked.value = item; } } } }); /** * Prevents default behavior of keydown events. */ const preventDefault = sync$((event: KeyboardEvent) => { if ((event.ctrlKey || event.metaKey) && event.key === 'k') { event.preventDefault(); } }); return (
{open.value && ( <>
{/* Header */}
inputElement.value!.focus()} loading={loading.value} > (input.value = element.value)} />
(open.value = false)} >
{/* Content */}
{ // Error error.value ? (

An unexpected error has occurred. If this happens regularly, please create an{' '} issue {' '} on Github.

) : // No result input.value && !loading.value && !result.value.length ? (

No results for " {input.value} "

) : // Result input.value && result.value.length ? (
    {result.value.map((item, index) => { const getPrevItem = () => index > 0 ? result.value[index - 1] : undefined; const getGroup = () => getPrevItem()?.group !== item.group ? item.group : undefined; return (
  • 0 && (getGroup() ? 'mt-9' : item.relation === 'page' && getPrevItem()?.relation !== 'page' ? 'mt-6' : item.relation === 'child' ? 'border-l-2 border-l-slate-200 pt-2.5 pl-2 dark:border-l-slate-800' : 'mt-2.5') )} > {getGroup() && (
    {getGroup()}
    )} handleClick(item)} />
  • ); })}
) : // Resent recent.value!.length ? ( <>
Recent
    {recent.value.map((item, index) => (
  • handleClick(item)} recent />
  • ))}
) : null }
{/* Footer */}
Search by
); }); type SearchItemProps = SearchItem & { index: number; activeIndex: Signal; onClick$: () => void; recent?: boolean; }; /** * Displays relevant info of a single search result and links to its page. */ const SearchItem = component$( ({ type, relation, page, text, path, index, activeIndex, onClick$, recent, }) => { // Use element signal const element = useSignal(); // Compute active state const active = useComputed$(() => index === activeIndex.value); // Scroll element into view if active useTask$(({ track }) => { track(element); track(active); if (isBrowser && element.value && active.value) { element.value.scrollIntoView({ block: 'nearest' }); } }); return ( (activeIndex.value = index)} onFocusIn$={() => (activeIndex.value = index)} // eslint-disable-next-line qwik/valid-lexical-scope onClick$={onClick$} > {relation === 'page' ? ( ) : ( )}
{type === 'content' && (relation === 'none' || recent) && (
)}
); } ); ================================================ FILE: website/src/components/DocsLayout.tsx ================================================ import { component$, type ReadonlySignal, Slot, useComputed$, } from '@builder.io/qwik'; import { type ContentMenu, Form, useContent, useDocumentHead, useLocation, } from '@builder.io/qwik-city'; import clsx from 'clsx'; import { ArrowLeftIcon, ArrowRightIcon, GitHubIcon, MarkdownIcon, MenuIcon, PenIcon, } from '~/icons'; import { useChapters, useChaptersToggle } from '~/routes/plugin@chapters'; import { trackEvent } from '~/utils'; import '../styles/pace.css'; import { Chapters } from './Chapters'; import { Credits } from './Credits'; import { IconButton } from './IconButton'; import { Navigation } from './Navigation'; import { SideBar, useSideBarToggle } from './SideBar'; const MDX_PATH_REGEX = /^\/(?:[\w-]+\/){2}$/; type NavItem = ContentMenu & { group: string }; /** * Provides the layout for the documentation pages. */ export const DocsLayout = component$(() => { // Use location, content, docuemnt head and chapters const location = useLocation(); const content = useContent(); const documentHead = useDocumentHead(); const chapters = useChapters(); // Use side bar and chapters toggle const sideBarToggle = useSideBarToggle(); const chaptersToggle = useChaptersToggle(); // Compute navigation items const navItems = useComputed$( () => content.menu?.items?.reduce( (list, { text, items }) => items ? [...list, ...items.map((item) => ({ ...item, group: text }))] : list, [] ) || [] ); // Compute current navigation index const navIndex = useComputed$(() => navItems.value.findIndex((item) => item.href === location.url.pathname) ); // Compute previous, current and next page const prevPage = useComputed$( () => navItems.value[navIndex.value - 1] ); const currentPage = useComputed$( () => navItems.value[navIndex.value] ); const nextPage = useComputed$( () => navItems.value[navIndex.value + 1] ); // Optimistically compute whether to show chapters const showChapters = useComputed$(() => chaptersToggle.isRunning ? !chapters.value : chapters.value ); // Compute Markdown path from current location const markdownPath = useComputed$(() => MDX_PATH_REGEX.test(location.url.pathname) ? `${location.url.pathname.replace(/\/$/, '')}.md` : undefined ); return (
{/* Side bar navigation */}
{/* Navigation buttons */} {/* Article */}
{currentPage.value?.href && ( )} {/* Credits */}
{showChapters.value && ( )}
); }); type NavButtonsProps = { pageIndex: number; sourcePath: string | undefined; markdownPath: string | undefined; prevPage: ContentMenu | undefined; nextPage: ContentMenu | undefined; chapters?: ReadonlySignal; chaptersToggle?: ReturnType; }; /** * Buttons to navigate to the previous or next page. */ export const NavButtons = component$( ({ pageIndex, sourcePath, markdownPath, prevPage, nextPage, chapters, chaptersToggle, }) => ( <> {pageIndex !== -1 && ( <> {prevPage?.href ? ( ) : (
)} {nextPage?.href ? ( ) : (
)} )} {chaptersToggle && ( )} {sourcePath && ( )} {markdownPath && ( )} ) ); ================================================ FILE: website/src/components/Expandable.tsx ================================================ import { $, component$, Slot, useSignal, useTask$ } from '@builder.io/qwik'; import { isBrowser } from '@builder.io/qwik/build'; import clsx from 'clsx'; type ExpandableProps = { class?: string; id?: string; expanded: boolean; }; /** * Wrapper component to vertically expand or collapse content. */ export const Expandable = component$( ({ id, expanded, ...props }) => { // Use element signal const element = useSignal(); /** * Updates the expandable element height. */ const updateElementHeight = $(() => { element.value!.style.maxHeight = '0'; element.value!.style.height = `${ expanded ? element.value!.scrollHeight : 0 }px`; element.value!.style.maxHeight = ''; }); // Expand or collapse content when expanded prop change useTask$(({ track }) => { track(() => expanded); if (isBrowser && element.value) { updateElementHeight(); } }); return (
); } ); ================================================ FILE: website/src/components/Footer.tsx ================================================ import { component$ } from '@builder.io/qwik'; import { TextLink } from './TextLink'; /** * Footer with copyright notice and links to legal text. */ export const Footer = component$(() => (
© {new Date().getFullYear()} Fabian Hiller
)); ================================================ FILE: website/src/components/GitHubIconLink.tsx ================================================ import { component$ } from '@builder.io/qwik'; import { GitHubIcon } from '~/icons'; import { SystemIcon } from './SystemIcon'; /** * GitHub icon pointing to our repository. */ export const GitHubIconLink = component$(() => ( )); ================================================ FILE: website/src/components/Head.tsx ================================================ import { component$, useComputed$ } from '@builder.io/qwik'; import { useDocumentHead, useLocation } from '@builder.io/qwik-city'; import { useTheme } from '~/routes/plugin@theme'; /** * Head with title, meta, link, script and style elements. */ export const Head = component$(() => { // Use document head, location and theme const head = useDocumentHead(); const location = useLocation(); const theme = useTheme(); // Compute document title const documentTitle = useComputed$(() => location.url.pathname === '/' ? head.title : `${head.title} | Valibot` ); // Compute theme color code const themeColor = useComputed$(() => theme.value === 'dark' ? '#111827' : '#fff' ); // Compute Open Graph type const ogType = useComputed$(() => location.url.pathname === '/' || location.url.pathname === '/playground/' ? 'website' : 'article' ); // Compute description from metadata const description = useComputed$( () => head.meta.find((item) => item.name === 'description')?.content ); // Compute Open Graph image URL const imageUrl = useComputed$(() => { // Create base URL let imageUrl = `${location.url.origin}/og-image`; // Add title and path to URL if (location.url.pathname !== '/') { imageUrl += `?title=${encodeURIComponent(head.title)}&path=${ location.url.pathname.split('/')[1] }`; // Add description to URL if (description.value) { imageUrl += `&description=${encodeURIComponent(description.value)}`; } } // Return image URL return imageUrl; }); return ( {/* Document title */} {documentTitle.value} {/* Default metadata */} {/* Icon metadata */} {/* Preload fonts */} {/* Open Graph metadata */} {description.value && ( )} {/* Dynamic metadata */} {head.meta.map(({ key, ...props }) => ( ))} {/* Umami tracking script */} `} /> ); }); type EditorButtonsProps = { class: string; model: Signal>; executeCode$: QRL<() => void>; }; const EditorButtons = component$( ({ model, executeCode$, ...props }) => { // Use navigate and location const navigate = useNavigate(); const location = useLocation(); // Use copied and shared reset signal const copied = useResetSignal(false); const shared = useResetSignal(false); /** * Copies the current code of the editor. */ const copyCode = $(() => { // Copy code to clipboard copied.value = true; navigator.clipboard.writeText(model.value!.getValue()); // Track playground event trackEvent('copy_playground_code'); }); /** * Shares the current code of the editor. */ const shareCode = $(async () => { // Add compressed code to search params await navigate( `?code=${lz.compressToEncodedURIComponent(model.value!.getValue())}`, { replaceState: true } ); // Get current URL with search params const url = location.url.href; // Share URL or copy it to clipboard if (navigator.share) { navigator.share({ title: 'Playground', url }); } else { shared.value = true; navigator.clipboard.writeText(url); } // Track playground event trackEvent('share_playground_code'); }); return (
{copied.value ? ( ) : ( )} {shared.value ? ( ) : ( )}
); } ); ================================================ FILE: website/src/routes/plugin@chapters.ts ================================================ import { type RequestEventAction, routeAction$, routeLoader$, } from '@builder.io/qwik-city'; const COOKIE_NAME = 'chapters'; /** * Returns the value of the chapters cookie. */ function getCookie(request: RequestEventAction) { return request.cookie.get(COOKIE_NAME)?.value ?? 'true'; } /** * Returns whether chapters are enabled. */ export const useChapters = routeLoader$( (request) => getCookie(request) === 'true' ); /** * Toggles the chapters by changing the chapters cookie. */ export const useChaptersToggle = routeAction$((_, request) => { request.cookie.set(COOKIE_NAME, `${getCookie(request) !== 'true'}`, { httpOnly: true, maxAge: 31557600, // 1 year path: '/', sameSite: 'lax', secure: import.meta.env.PROD, }); }); ================================================ FILE: website/src/routes/plugin@theme.ts ================================================ import { type RequestEventAction, routeAction$, routeLoader$, } from '@builder.io/qwik-city'; const COOKIE_NAME = 'theme'; /** * Returns the value of the theme cookie. */ function getCookie(request: RequestEventAction) { return request.cookie.get(COOKIE_NAME)?.value ?? 'dark'; } /** * Returns the current theme. */ export const useTheme = routeLoader$((request) => getCookie(request)); /** * Toggles the theme by changing the theme cookie. */ export const useThemeToggle = routeAction$((_, request) => { request.cookie.set( COOKIE_NAME, getCookie(request) === 'dark' ? 'light' : 'dark', { httpOnly: true, maxAge: 31557600, // 1 year path: '/', sameSite: 'lax', secure: import.meta.env.PROD, } ); }); ================================================ FILE: website/src/styles/pace.css ================================================ @reference './root.css'; /* Important */ code.language-bash * { @apply text-slate-700! dark:text-slate-300!; } /* Gray */ code .script, code .spread, code .imports span { @apply text-slate-700 dark:text-slate-300; } code .operator, code .tag .punctuation, code .attr-value .punctuation.attr-equals { @apply text-slate-600 dark:text-slate-400; } code .comment { @apply text-slate-500; } /* Amber */ code .string, code .attr-value, code .attr-value .punctuation { @apply text-yellow-600 dark:text-amber-200; } /* Emerald */ code .function, code .tag .attr-name, code .tag .script .function { @apply text-emerald-600 dark:text-emerald-400; } /* Teal */ code .keyword, code .builtin, code .boolean, code .imports .operator { @apply text-teal-600 dark:text-teal-400; } /* Sky */ code .tag .class-name, code .maybe-class-name { @apply text-sky-600 dark:text-sky-400; } /* Purple */ code .number { @apply text-purple-600 dark:text-purple-400; } /* Red */ code .tag, code .keyword.module, code .keyword.control-flow, code .spread.operator { @apply text-red-600 dark:text-red-400; } ================================================ FILE: website/src/styles/root.css ================================================ /* Tailwind CSS */ @import 'tailwindcss'; @custom-variant dark (&:where(.dark, .dark *)); @theme { --font-lexend: 'Lexend', ui-sans-serif, system-ui, sans-serif; --font-lexend-exa: 'Lexend Exa', ui-sans-serif, system-ui, sans-serif; } /* Custom utils */ @utility focus-ring { @apply focus-visible:ring-4 focus-visible:ring-sky-600/10 focus-visible:ring-offset-[3px] focus-visible:ring-offset-white focus-visible:outline-2 focus-visible:outline-sky-600/50 dark:focus-visible:ring-sky-400/10 dark:focus-visible:ring-offset-gray-900 dark:focus-visible:outline-sky-400/50; } @utility scrollbar-none { -ms-overflow-style: none; scrollbar-width: none; &::-webkit-scrollbar { display: none; } } /* Base layer */ @layer base { /* Disable tap highlight color */ html { -webkit-tap-highlight-color: transparent; } /* Reset appearance */ [type='search']::-webkit-search-cancel-button { @apply hidden; } /* Disable transitions */ .disable-transitions, .disable-transitions * { transition: none !important; } /* Scrollbar */ * { scrollbar-width: thin; scrollbar-color: var(--color-slate-300) transparent; } .dark, .dark * { scrollbar-color: var(--color-slate-700) transparent; } /* Monaco editor */ .monaco-editor, .monaco-editor > div { @apply border-0 outline-none lg:rounded-3xl; } /* Lexend 400 */ @font-face { font-family: 'Lexend'; font-style: normal; font-weight: 400; font-display: swap; src: url(/fonts/lexend-400.woff2) format('woff2'); } /* Lexend 500 */ @font-face { font-family: 'Lexend'; font-style: normal; font-weight: 500; font-display: swap; src: url(/fonts/lexend-500.woff2) format('woff2'); } /* Lexend Exa 500 */ @font-face { font-family: 'Lexend Exa'; font-style: normal; font-weight: 500; font-display: swap; src: url(/fonts/lexend-exa-500.woff2) format('woff2'); } /* Typography */ .mdx :is(h1, h2, h3, h4) { @apply scroll-mt-24 leading-normal font-medium text-slate-900 md:scroll-mt-32 lg:scroll-mt-48 dark:text-slate-200; } .mdx h1 { @apply text-2xl md:text-3xl lg:text-4xl; } .mdx h2 { @apply border-b-2 border-b-slate-200 pb-4 text-xl md:pb-6 md:text-2xl lg:pb-8 lg:text-3xl dark:border-b-slate-800; } .mdx h3 { @apply text-lg md:text-xl lg:text-2xl; } .mdx h4 { @apply md:text-lg lg:text-xl; } .mdx :is(p, blockquote, ul, ol) { @apply leading-loose md:text-lg lg:text-xl; } .mdx p strong { @apply text-slate-800 dark:text-slate-300; } /* Blockquote */ .mdx blockquote p { @apply border-l-4 border-l-yellow-600 pl-6 lg:pl-8 dark:border-l-yellow-400; } /* Links */ .mdx a { @apply focus-ring rounded-md text-sky-600 underline decoration-slate-400 decoration-dashed underline-offset-[3px] focus-visible:ring-offset-[6px] focus-visible:outline-offset-4 dark:text-sky-400 dark:decoration-slate-600; } /* Images */ .mdx > img { @apply w-auto rounded-2xl border-2 border-slate-200 lg:rounded-3xl lg:border-[3px] dark:border-slate-800; } /* Lists */ .mdx :is(ul, ol) { @apply flex flex-col gap-2; } .mdx :is(ul, ol) :is(ul, ol) { @apply pt-2 pl-4 lg:pl-5; } .mdx ul { @apply list-disc; } .mdx ol { @apply list-decimal; } .mdx :is(ul, ol) li { @apply pl-2.5; } /* Table */ .mdx .table-wrapper { @apply overflow-x-auto rounded-2xl border-2 border-slate-200 px-5 py-2.5 lg:rounded-3xl lg:border-[3px] lg:px-10 lg:py-7 dark:border-slate-800; } .mdx table { @apply w-full md:text-lg lg:text-xl; } .mdx tbody tr { @apply border-t border-t-slate-200 lg:border-t-2 dark:border-t-slate-800; } .mdx th { @apply text-left font-medium text-slate-700 dark:text-slate-300; } .mdx :is(th, td) { @apply py-2.5 whitespace-nowrap lg:py-3; } .mdx :is(th, td) + :is(th, td) { @apply pl-3; } .mdx table strong { @apply font-normal text-emerald-600 dark:text-emerald-400; } /* Code */ .mdx :not(pre) > code { @apply rounded-lg bg-slate-100 px-2 py-1 text-slate-700 dark:bg-gray-800 dark:text-slate-300; } .mdx p > code { @apply whitespace-nowrap; } /* Horizontal spacing */ .mdx > :is(h1, h2, h3, h4, p, blockquote) { @apply mx-8 lg:mx-10; } .mdx > :is(ul, ol) { @apply mr-8 ml-12 lg:mr-10 lg:ml-14; } .mdx > :is(img, .code-wrapper, .table-wrapper) { @apply mx-3 lg:mx-10 2xl:mx-0; } /* Vertical spacing */ .mdx > :is(h1, h2, h3, h4, p) + p { @apply mt-7 md:mt-9 lg:mt-11; } .mdx > * + * { @apply mt-10 md:mt-12 lg:mt-14; } .mdx > * + h2 { @apply mt-12 md:mt-14 lg:mt-16; } } ================================================ FILE: website/src/utils/disableTransitions.ts ================================================ let timeout: NodeJS.Timeout | undefined; /** * Disables CSS transitions for a short moment. */ export function disableTransitions() { if (timeout) clearTimeout(timeout); const { classList } = document.documentElement; classList.add('disable-transitions'); timeout = setTimeout(() => classList.remove('disable-transitions'), 500); } ================================================ FILE: website/src/utils/index.ts ================================================ export * from './disableTransitions'; export * from './trackEvent'; ================================================ FILE: website/src/utils/trackEvent.ts ================================================ type EventName = | 'change_theme' | 'change_chapters' | 'open_search' | 'select_search_item' | 'copy_code_snippet' | 'open_code_snippet_in_playground' | 'copy_playground_code' | 'share_playground_code' | 'save_playground_code' | 'execute_playground_code' | 'clear_playground_logs' | 'resize_playground' | 'copy_zod_codemod_result' | 'execute_zod_codemod'; type EventData = { [key: string]: string | number | boolean | undefined }; declare global { interface Window { umami?: { track: (name: EventName, data?: EventData) => void }; } } /** * Tracks custom Umami events. * * @param name The event name. * @param data The event data. */ export function trackEvent(name: EventName, data?: EventData) { window.umami?.track(name, data); } ================================================ FILE: website/tsconfig.json ================================================ { "compilerOptions": { "allowJs": true, "target": "ES2017", "module": "ES2022", "lib": ["es2022", "DOM", "WebWorker", "DOM.Iterable"], "jsx": "react-jsx", "jsxImportSource": "@builder.io/qwik", "strict": true, "forceConsistentCasingInFileNames": true, "resolveJsonModule": true, "moduleResolution": "bundler", "esModuleInterop": true, "skipLibCheck": true, "incremental": true, "isolatedModules": true, "outDir": "tmp", "noEmit": true, "types": ["node", "vite/client"], "paths": { "~/*": ["./src/*"] } }, "include": ["scripts", "src", "./*.d.ts", "./*.config.ts"], "exclude": ["src/routes/guides/(migration)/migrate-from-zod/zod"] } ================================================ FILE: website/vercel.json ================================================ { "buildCommand": "cd ../library && npm run build && cd ../packages/to-json-schema && npm run build && cd ../../codemod/zod-to-valibot && pnpm build && cd ../../website && npm run sitemap && npm run llms && npm run build", "headers": [ { "source": "/(.*)?service-worker.js", "headers": [ { "key": "Cache-Control", "value": "public, max-age=0, must-revalidate" } ] }, { "source": "/build/(.*)", "headers": [ { "key": "Cache-Control", "value": "public, max-age=31536000, s-maxage=31536000, immutable" } ] }, { "source": "/assets/(.*)", "headers": [ { "key": "Cache-Control", "value": "public, max-age=31536000, s-maxage=31536000, immutable" } ] }, { "source": "/assets/(.*)-index.min.mjs", "headers": [ { "key": "Access-Control-Allow-Origin", "value": "*" } ] } ] } ================================================ FILE: website/vite.config.ts ================================================ import { qwikCity } from '@builder.io/qwik-city/vite'; import { qwikVite } from '@builder.io/qwik/optimizer'; import rehypePrism from '@mapbox/rehype-prism'; import tailwindcss from '@tailwindcss/vite'; import rehypeExternalLinks from 'rehype-external-links'; import { defineConfig } from 'vite'; import { nodePolyfills } from 'vite-plugin-node-polyfills'; import tsconfigPaths from 'vite-tsconfig-paths'; export default defineConfig(({ isSsrBuild }) => { return { plugins: [ qwikCity({ mdxPlugins: { remarkGfm: true, rehypeSyntaxHighlight: false, rehypeAutolinkHeadings: true, }, mdx: { providerImportSource: '~/hooks/useMDXComponents.tsx', rehypePlugins: [ // @ts-expect-error rehypePrism, [rehypeExternalLinks, { rel: 'noreferrer', target: '_blank' }], ], }, }), qwikVite(), tsconfigPaths(), !isSsrBuild && nodePolyfills(), tailwindcss(), ], preview: { headers: { 'Cache-Control': 'public, max-age=600', }, }, }; });