Full Code of jquense/yup for AI

master ff31eee8a2b1 cached
73 files
445.6 KB
120.2k tokens
340 symbols
1 requests
Download .txt
Showing preview only (467K chars total). Download the full file or copy to clipboard to get everything.
Repository: jquense/yup
Branch: master
Commit: ff31eee8a2b1
Files: 73
Total size: 445.6 KB

Directory structure:
gitextract_was633h2/

├── .babelrc.js
├── .eslintignore
├── .eslintrc
├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── question.md
│   └── workflows/
│       └── ci.yml
├── .gitignore
├── .nvmrc
├── .yarn/
│   └── patches/
│       └── @4c-rollout-npm-4.0.2-ab2b6d0bab.patch
├── .yarnrc.yml
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── docs/
│   └── extending.md
├── package.json
├── renovate.json
├── rollup.config.js
├── src/
│   ├── Condition.ts
│   ├── Lazy.ts
│   ├── Reference.ts
│   ├── ValidationError.ts
│   ├── array.ts
│   ├── boolean.ts
│   ├── date.ts
│   ├── globals.d.ts
│   ├── index.ts
│   ├── locale.ts
│   ├── mixed.ts
│   ├── number.ts
│   ├── object.ts
│   ├── schema.ts
│   ├── setLocale.ts
│   ├── standardSchema.ts
│   ├── string.ts
│   ├── tuple.ts
│   ├── types.ts
│   └── util/
│       ├── ReferenceSet.ts
│       ├── cloneDeep.ts
│       ├── createValidation.ts
│       ├── isAbsent.ts
│       ├── isSchema.ts
│       ├── objectTypes.ts
│       ├── parseIsoDate.ts
│       ├── parseJson.ts
│       ├── printValue.ts
│       ├── reach.ts
│       ├── sortByKeyOrder.ts
│       ├── sortFields.ts
│       ├── toArray.ts
│       └── types.ts
├── test/
│   ├── .eslintignore
│   ├── ValidationError.ts
│   ├── array.ts
│   ├── bool.ts
│   ├── date.ts
│   ├── helpers.ts
│   ├── lazy.ts
│   ├── mixed.ts
│   ├── number.ts
│   ├── object.ts
│   ├── setLocale.ts
│   ├── standardSchema.ts
│   ├── string.ts
│   ├── tsconfig.json
│   ├── tuple.ts
│   ├── types/
│   │   ├── .eslintrc.js
│   │   └── types.ts
│   ├── util/
│   │   └── parseIsoDate.ts
│   └── yup.js
├── test-setup.mjs
├── tsconfig.json
└── vitest.config.ts

================================================
FILE CONTENTS
================================================

================================================
FILE: .babelrc.js
================================================
module.exports = (api) => ({
  presets: [
    [
      'babel-preset-env-modules',
      api.env() !== 'test'
        ? {
            ignoreBrowserslistConfig: true,
            modules: api.env() === 'esm' ? false : 'commonjs',
          }
        : {
            target: 'node',
            targets: { node: 'current' },
          },
    ],
    ['@babel/preset-typescript', { allowDeclareFields: true }],
  ],
});


================================================
FILE: .eslintignore
================================================
.eslintrc
.eslintrc.js


================================================
FILE: .eslintrc
================================================
{
  "extends": ["jason", "prettier"],
  "env": {
    "browser": true
  },
  "parserOptions": {
    "requireConfigFile": false
  },
  "rules": {
    "@typescript-eslint/no-shadow": "off",
    "@typescript-eslint/no-empty-interface": "off"
  },
  "overrides": [
    {
      "files": ["test/**"],
      "plugins": ["jest"],
      "env": {
        "jest/globals": true
      },
      "rules": {
        "global-require": "off",
        "no-await-in-loop": "off",
        "jest/no-disabled-tests": "warn",
        "jest/no-focused-tests": "error",
        "jest/no-identical-title": "error",
        "jest/prefer-to-have-length": "warn",
        "@typescript-eslint/no-empty-function": "off"
      }
    }
  ]
}


================================================
FILE: .gitattributes
================================================
# Auto detect text files and perform LF normalization
* text=auto

# Custom for Visual Studio
*.cs     diff=csharp
*.sln    merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union

# Standard to msysgit
*.doc	 diff=astextplain
*.DOC	 diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot  diff=astextplain
*.DOT  diff=astextplain
*.pdf  diff=astextplain
*.PDF	 diff=astextplain
*.rtf	 diff=astextplain
*.RTF	 diff=astextplain


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**

Write a **runnable** test case using the code sandbox template: https://codesandbox.io/s/yup-test-case-gg1g1 
In the `index.test.js` file change the passing test to a failing one demostrating your issue

> NOTE: if you do not provide a runnable reproduction the chances of getting feedback are significantly lower


**Expected behavior**
A clear and concise description of what you expected to happen.

**Platform (please complete the following information):**
 - Browser [e.g. chrome, safari]
 - Version [e.g. 22]


**Additional context**
Add any other context about the problem here.


================================================
FILE: .github/ISSUE_TEMPLATE/question.md
================================================
---
name: Question
about: General questions about yup or how it works
title: ''
labels: ''
assignees: ''

---

- Write a title that summarizes the specific problem
- Describe what you are trying to accomplish AND what you have tried

**Help Others Reproduce**

Write a **runnable** test case using the code sandbox template: https://codesandbox.io/s/yup-test-case-gg1g1 

> NOTE: if you do not provide a runnable reproduction the chances of getting feedback are significantly lower


================================================
FILE: .github/workflows/ci.yml
================================================
name: Test
on:
  push:
    branches: [master, next]
  pull_request:
    branches: [master, next]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version: 'lts/*'
      - run: |
          corepack enable
      - run: yarn install --frozen-lockfile
      - run: yarn test


================================================
FILE: .gitignore
================================================
# Logs
logs
*.log
dts/
# Runtime data
pids
*.pid
*.seed

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directory
# Commenting this out is preferred by some people, see
# https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git
node_modules

# Users Environment Variables
.lock-wscript

# =========================
# Operating System Files
# =========================

# OSX
# =========================

.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon


# Thumbnails
._*

# Files that might appear on external disk
.Spotlight-V100
.Trashes

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

# Windows
# =========================

# Windows image file caches
Thumbs.db
ehthumbs.db

# Folder config file
Desktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msm
*.msp

# Ignore build files
lib/
es/


================================================
FILE: .nvmrc
================================================
22.19.0


================================================
FILE: .yarn/patches/@4c-rollout-npm-4.0.2-ab2b6d0bab.patch
================================================
diff --git a/command.js b/command.js
index 9608bffb4a52e5b8066e263d1286420ae92988bb..86ca58d70f315dae45fc739707dcff07a99a2be4 100644
--- a/command.js
+++ b/command.js
@@ -292,8 +292,7 @@ const handlerImpl = async (argv) => {
                 task: () =>
                   exec('yarn', [
                     'install',
-                    '--frozen-lockfile',
-                    '--production=false',
+                    '--immutable',
                   ]),
               }
             : {


================================================
FILE: .yarnrc.yml
================================================
nodeLinker: node-modules


================================================
FILE: CHANGELOG.md
================================================
## [1.7.1](https://github.com/jquense/yup/compare/v1.7.0...v1.7.1) (2025-09-21)





# [1.7.0](https://github.com/jquense/yup/compare/v1.6.1...v1.7.0) (2025-08-01)


### Features

* Implement standard schema interface ([#2258](https://github.com/jquense/yup/issues/2258)) ([ced5f51](https://github.com/jquense/yup/commit/ced5f514a6033a96f5de3b4ae9c17fe0de86d68f))
* resolve ref params if present when describing ([ef53030](https://github.com/jquense/yup/commit/ef5303025c38e6e0dc0de53c990e7277cc74164e)), closes [#2276](https://github.com/jquense/yup/issues/2276)





## [1.6.1](https://github.com/jquense/yup/compare/v1.6.0...v1.6.1) (2024-12-17)


### Bug Fixes

* lazy validation errors thrown in builders should resolve async like other validations ([c7d7f97](https://github.com/jquense/yup/commit/c7d7f977e02a7e578950dff192057e0b200999bd))





# [1.6.0](https://github.com/jquense/yup/compare/v1.5.0...v1.6.0) (2024-12-16)


### Features

* expose LazySchema ([2b0f126](https://github.com/jquense/yup/commit/2b0f1264083fccb646f7f6bd43adfbff2caaf295))





# [1.5.0](https://github.com/jquense/yup/compare/v1.4.0...v1.5.0) (2024-12-03)


### Bug Fixes

* **readme:** some typos and update CustomizingErrors doc ([#2163](https://github.com/jquense/yup/issues/2163)) ([5c77e0d](https://github.com/jquense/yup/commit/5c77e0d4f9373151bcf0cd558c95986b6e4800d7))


### Features

* Add exact and stripUnknown method to object() ([adcdd8d](https://github.com/jquense/yup/commit/adcdd8dd500c627b1efbe3595b6b37dec2847ad8))





# [1.4.0](https://github.com/jquense/yup/compare/v1.3.3...v1.4.0) (2024-03-06)


### Bug Fixes

* add optional message to nonNullable schema methods ([#2119](https://github.com/jquense/yup/issues/2119)) ([9e1df49](https://github.com/jquense/yup/commit/9e1df4938c1964a21e6ece0c458bb96dc5aff108))


### Features

* **string:** Create .datetime() ([#2087](https://github.com/jquense/yup/issues/2087)) ([2a9e060](https://github.com/jquense/yup/commit/2a9e060594423018f517419ef5d2f10e417c9fbd))





## [1.3.3](https://github.com/jquense/yup/compare/v1.3.2...v1.3.3) (2023-12-14)


### Bug Fixes

* **addMethod:** allow Schema without making TypeScript upset ([f921fe6](https://github.com/jquense/yup/commit/f921fe69a2d6ecc6e7d0101d2bd81148dfe83e64))





## [1.3.2](https://github.com/jquense/yup/compare/v1.3.1...v1.3.2) (2023-09-29)


### Bug Fixes

* pick and omit with excluded edges ([6956ee7](https://github.com/jquense/yup/commit/6956ee788369dff00e5ecadb506726af3598a87e)), closes [#2097](https://github.com/jquense/yup/issues/2097)





## [1.3.1](https://github.com/jquense/yup/compare/v1.3.0...v1.3.1) (2023-09-26)


### Bug Fixes

* ValidationError extends Error ([bc5121b](https://github.com/jquense/yup/commit/bc5121b92d8e16baf8fe9b83f0247a4e90e169b8))





# [1.3.0](https://github.com/jquense/yup/compare/v1.2.0...v1.3.0) (2023-09-23)


### Bug Fixes

* add tuple to locale object ([#2100](https://github.com/jquense/yup/issues/2100)) ([809b55a](https://github.com/jquense/yup/commit/809b55a9c16e0cd567f4eced9b9ab02ad8b0bffa))
* performance improvement ([#2043](https://github.com/jquense/yup/issues/2043)) ([#2044](https://github.com/jquense/yup/issues/2044)) ([ee1b731](https://github.com/jquense/yup/commit/ee1b7317b0a9fc0e16a7d33064c3e5584bd7f2d5))


### Features

* Allow schema metadata to be strongly typed ([#2021](https://github.com/jquense/yup/issues/2021)) ([e593f8f](https://github.com/jquense/yup/commit/e593f8f72e7195cf0ac48fa8e1cd82d95c1e6bb5))


### Reverts

* Revert "fix: performance improvement (#2043) (#2044)" (#2071) ([b940eef](https://github.com/jquense/yup/commit/b940eef48eb7456622ae384d0ffa7363d4fbad25)), closes [#2043](https://github.com/jquense/yup/issues/2043) [#2044](https://github.com/jquense/yup/issues/2044) [#2071](https://github.com/jquense/yup/issues/2071)





# [1.2.0](https://github.com/jquense/yup/compare/v1.1.1...v1.2.0) (2023-05-25)


### Features

* expose printValue ([#2002](https://github.com/jquense/yup/issues/2002)) ([#2008](https://github.com/jquense/yup/issues/2008)) ([1fadba1](https://github.com/jquense/yup/commit/1fadba10b0d1cad60f3708bd28282ab04a55eff6))
* pass options to `default(options => value)` ([e5c5440](https://github.com/jquense/yup/commit/e5c5440767d32a8be6c4a12a5f6176924e058fd2)), closes [#1984](https://github.com/jquense/yup/issues/1984)





## [1.1.1](https://github.com/jquense/yup/compare/v1.1.0...v1.1.1) (2023-04-14)


### Bug Fixes

* **docs:** Broken anchores ([#1979](https://github.com/jquense/yup/issues/1979)) ([4ed4576](https://github.com/jquense/yup/commit/4ed45762e955ac6af0dec935a91e815a5a1cf5b9))
* make null validation errors consistent across schema ([#1982](https://github.com/jquense/yup/issues/1982)) ([f999497](https://github.com/jquense/yup/commit/f99949747456d7bf55da3dd38dcf86bbddba3169))
* **object:** excluded edges are merged when concating schema ([c07b08f](https://github.com/jquense/yup/commit/c07b08f033be8eea00d74a5da1cf735cf97e69df)), closes [#1969](https://github.com/jquense/yup/issues/1969)





# [1.1.0](https://github.com/jquense/yup/compare/v1.0.2...v1.1.0) (2023-04-12)


### Bug Fixes

* tuple describe() method ([#1947](https://github.com/jquense/yup/issues/1947)) ([297f168](https://github.com/jquense/yup/commit/297f1682296ee0b53e5e252477d5a6d7d82df707))


### Features

* only resolve "strip()" for schema when used as an object field ([#1977](https://github.com/jquense/yup/issues/1977)) ([2ba1104](https://github.com/jquense/yup/commit/2ba1104798dcf3b9385997e5fbaa41b4d711472d))
* respect context for object's children ([#1971](https://github.com/jquense/yup/issues/1971)) ([edfe6ac](https://github.com/jquense/yup/commit/edfe6acde9e11ec2bfe2ad41aad867daae7041ce))





## [1.0.2](https://github.com/jquense/yup/compare/v1.0.0...v1.0.2) (2023-02-27)


### Bug Fixes

* fix array describe not including conditions ([4040592](https://github.com/jquense/yup/commit/4040592ccd068ab71e06417b4d355007636cb78c)), closes [#1920](https://github.com/jquense/yup/issues/1920)





## [1.0.1](https://github.com/jquense/yup/compare/v1.0.0...v1.0.1) (2023-02-25)





# [1.0.0](https://github.com/jquense/yup/compare/v1.0.0-beta.8...v1.0.0) (2023-02-08)

### Migrating from 0.x to 1.0.0: [#1906](https://github.com/jquense/yup/issues/1906)




# [1.0.0-beta.8](https://github.com/jquense/yup/compare/v1.0.0-beta.7...v1.0.0-beta.8) (2022-11-10)


### Bug Fixes

* check if field exists when generating defaults ([37f686c](https://github.com/jquense/yup/commit/37f686c217a9ee5d6f21f07a812a20467ee83578))
* correct minor typo in README ([#1760](https://github.com/jquense/yup/issues/1760)) ([62786c4](https://github.com/jquense/yup/commit/62786c42ca07a2b84b05ca8c473bc01f0c868a94))
* don't return any for oneOf ([74c5bc5](https://github.com/jquense/yup/commit/74c5bc54220cae5ff491ed92845ecd9c1ed7fbf3)), closes [#1675](https://github.com/jquense/yup/issues/1675)
* export more types ([f250109](https://github.com/jquense/yup/commit/f250109dbf7158f1ee31ccd11f8309d660880252))
* string().notRequired() ([#1824](https://github.com/jquense/yup/issues/1824)) ([dcb4b63](https://github.com/jquense/yup/commit/dcb4b6381eac21f8f28297066e71920a788c8a47))
* TS 4.8 compat ([bc74c34](https://github.com/jquense/yup/commit/bc74c340721da2ea6e65cb27b967c2970af44d35))
* **types:** undefined defaults produce optional outputs ([1afbac0](https://github.com/jquense/yup/commit/1afbac06edfd3277a8c76bb4c8874cf16d4d346d))


### Features

* add some more type exports ([d5e9c99](https://github.com/jquense/yup/commit/d5e9c99e6ef068bff4c4f92db5ccc0835f6b84b3))
* Export ValidateOptions, ISchema for external use ([#1812](https://github.com/jquense/yup/issues/1812)) ([584df11](https://github.com/jquense/yup/commit/584df11b60e5d47876946872973764d0e0e0c9ed))
* respect nullable() with oneOf ([#1757](https://github.com/jquense/yup/issues/1757)) ([61ec302](https://github.com/jquense/yup/commit/61ec3027caba72cb795ee64f571ca0a7aa6bc9a6)), closes [#768](https://github.com/jquense/yup/issues/768) [#104](https://github.com/jquense/yup/issues/104)
* simplify email validation ([440db3e](https://github.com/jquense/yup/commit/440db3e6177d25c06be76995a1deff6e25a90c10))


### BREAKING CHANGES

* previously `oneOf` required adding `null` explicitly to allowed values when using oneOf. Folks have found this confusing and unintuitive so I am deferring and adjusting the behavior
* Use a simpler regex for email addresses that aligns with browsers, and add docs about how to override.





# [1.0.0-beta.7](https://github.com/jquense/yup/compare/v1.0.0-beta.6...v1.0.0-beta.7) (2022-08-20)





# [1.0.0-beta.6](https://github.com/jquense/yup/compare/v1.0.0-beta.5...v1.0.0-beta.6) (2022-08-20)


### Bug Fixes

* change mixed generic to unknown from any ([5e8e8ef](https://github.com/jquense/yup/commit/5e8e8ef132574b31056bc7c504b8ba62c9ae4d1e))
* count stripping unknown fields as changes for object casts ([2b4773c](https://github.com/jquense/yup/commit/2b4773ca8d4dc7b1f30e3927a113eb807d254f37)), closes [#1620](https://github.com/jquense/yup/issues/1620)
* **types:** export more types ([433a452](https://github.com/jquense/yup/commit/433a45252cac4621c00adbeb3c9320caca55cced))





# [1.0.0-beta.5](https://github.com/jquense/yup/compare/v1.0.0-beta.4...v1.0.0-beta.5) (2022-08-19)


### Bug Fixes

* coarce -> coerce ([#1677](https://github.com/jquense/yup/issues/1677)) ([99aa257](https://github.com/jquense/yup/commit/99aa25787a8ff15fe42e54db88ec3ed547357302))
* **docs:** correct typo "coarce" to "coerce" ([#1654](https://github.com/jquense/yup/issues/1654)) ([f29ff71](https://github.com/jquense/yup/commit/f29ff71e4ae04927d85a00a993a014de652ae9fe))


### Features

* add cast nullability migration path. ([#1749](https://github.com/jquense/yup/issues/1749)) ([2bb099e](https://github.com/jquense/yup/commit/2bb099e26f62dd4734fe7bd525d011ce2b1583b5))
* better Lazy types and deepPartial fixes ([#1748](https://github.com/jquense/yup/issues/1748)) ([e4ae6ed](https://github.com/jquense/yup/commit/e4ae6edeb171f25c43ca9367038ad5f09ce9de7c))


### BREAKING CHANGES

* The types for Lazy have changes a bit, it's unlikely that this affects anyone but it is technically a breaking change.





# [1.0.0-beta.4](https://github.com/jquense/yup/compare/v1.0.0-beta.3...v1.0.0-beta.4) (2022-04-10)


### Bug Fixes

* **boolean:** calling optional made it non-optional ([4ba02a1](https://github.com/jquense/yup/commit/4ba02a15b649dccaa090a2e72476c1ea448a3fc1)), closes [#1627](https://github.com/jquense/yup/issues/1627)





# [1.0.0-beta.3](https://github.com/jquense/yup/compare/v1.0.0-beta.2...v1.0.0-beta.3) (2022-03-09)


### Bug Fixes

* correct minor typo in README ([#1582](https://github.com/jquense/yup/issues/1582)) ([facea53](https://github.com/jquense/yup/commit/facea53e3508d041d86076ef065fb80b8ec74286))
* partial() ([1207261](https://github.com/jquense/yup/commit/120726175aa97a9066fb765155ae4fef15b1e0ad))


### BREAKING CHANGES

* 'required' no longer adds a test for most schema, to determine if a schema is required, check it's `spec.optional` and `spec.nullable` values, also accessible via `describe()`





# [1.0.0-beta.2](https://github.com/jquense/yup/compare/v0.32.11...v1.0.0-beta.2) (2022-01-21)


### Bug Fixes

* add originalValue to TestContext type ([#1527](https://github.com/jquense/yup/issues/1527)) ([fcc5ae7](https://github.com/jquense/yup/commit/fcc5ae710a1b3ef4b799532291faf894bdbcc11b)), closes [/github.com/abnersajr/DefinitelyTyped/blob/a186d99d0c3a92424691a82130374a1b9145c7cd/types/yup/index.d.ts#L446](https://github.com//github.com/abnersajr/DefinitelyTyped/blob/a186d99d0c3a92424691a82130374a1b9145c7cd/types/yup/index.d.ts/issues/L446)


* Merge next into master (#1547) ([366f7d8](https://github.com/jquense/yup/commit/366f7d8e280b021bbd7a4a4d3cfc8fa0cce00c8b)), closes [#1547](https://github.com/jquense/yup/issues/1547) [#1542](https://github.com/jquense/yup/issues/1542) [#1541](https://github.com/jquense/yup/issues/1541) [#1543](https://github.com/jquense/yup/issues/1543) [#1545](https://github.com/jquense/yup/issues/1545)


### Features

*  add Tuple type ([#1546](https://github.com/jquense/yup/issues/1546)) ([a8febdd](https://github.com/jquense/yup/commit/a8febddcfbe42358e63194ae8da582e66b746edf))


### BREAKING CHANGES

* The builder object version of `when()` requires `then` and `otherwise` to be
  functions `(schema: Schema) => Schema`.

* The function version of `when()` has been changed to make it easier to type. values are always passed as an array and schema, and options always the second and third argument. `this` is no longer set to the schema instance.  and all functions _must_ return a schema to be type safe

```diff
 string()
-   .when('other', function (other) => {
-      if (other) return this.required()
+   .when('other', ([other], schema) => {
+     return other ? schema.required() : schema
  })
```
* concat works shallowly now. Previously concat functioned like a deep merge for object, which produced confusing behavior with incompatible concat'ed schema. Now concat for objects works similar to how it works for other types, the provided schema is applied on top of the existing schema, producing a new schema that is the same as calling each builder method in order

* docs: update readme

* chore: update to readonly arrays and test string type narrowing

* test: add boolean tests

* docs: more docs

* feat: allow mixed schema to specify type check
* `mixed` schema are no longer treated as the base class for other schema types. It hasn't been for a while, but we've done some nasty prototype slinging to make it behave like it was. Now typescript types should be 1 to 1 with the actual classes yup exposes. 

In general this should not affect anything unless you are extending (via `addMethod` or otherwise) `mixed` prototype. 

```diff
import {
-  mixed,
+  Schema,
} from 'yup';

- addMethod(mixed, 'method', impl)
+ addMethod(Schema, 'method', impl)
```

* chore: prep work for toggling coercion

* Publish v1.0.0-alpha.4

* chore: docs

* feat!: add json() method and remove default object/array coercion
* object and array schema no longer parse JSON strings by default, nor do they return `null` for invalid casts.

```ts
object().json().cast('{}')
array().json().cast('[]')
```
to mimic the previous behavior

* feat: Make Array generic consistent with others
* types only, `ArraySchema`  initial generic is the array type not the type of the array element. `array<T>()` is still the inner type.

* Publish v1.0.0-beta.0

* docs


# [1.0.0-beta.1](https://github.com/jquense/yup/compare/v1.0.0-beta.0...v1.0.0-beta.1) (2022-01-03)


### Features

* flat bundles and size reductions ([753abdf](https://github.com/jquense/yup/commit/753abdf329e33e43c334e405baa9c71999079480))



# [1.0.0-beta.0](https://github.com/jquense/yup/compare/v1.0.0-alpha.4...v1.0.0-beta.0) (2021-12-29)


* feat!: add json() method and remove default object/array coercion ([94b73c4](https://github.com/jquense/yup/commit/94b73c438b3d355253f488325e06c69378e71fc1))


### Features

* Make Array generic consistent with others ([a82353f](https://github.com/jquense/yup/commit/a82353f37735daec6e42d18bd4cc0efe52a20f50))


### BREAKING CHANGES

* types only, `ArraySchema`  initial generic is the array type not the type of the array element. `array<T>()` is still the inner type.
* object and array schema no longer parse JSON strings by default, nor do they return `null` for invalid casts.

```ts
object().json().cast('{}')
array().json().cast('[]')
```
to mimic the previous behavior



# [1.0.0-alpha.4](https://github.com/jquense/yup/compare/v1.0.0-alpha.3...v1.0.0-alpha.4) (2021-12-29)

### Bug Fixes

- add originalValue to TestContext type ([#1527](https://github.com/jquense/yup/issues/1527)) ([fcc5ae7](https://github.com/jquense/yup/commit/fcc5ae710a1b3ef4b799532291faf894bdbcc11b)), closes [/github.com/abnersajr/DefinitelyTyped/blob/a186d99d0c3a92424691a82130374a1b9145c7cd/types/yup/index.d.ts#L446](https://github.com//github.com/abnersajr/DefinitelyTyped/blob/a186d99d0c3a92424691a82130374a1b9145c7cd/types/yup/index.d.ts/issues/L446)

### Features

- allow mixed schema to specify type check ([3923039](https://github.com/jquense/yup/commit/3923039558733d34586df2b282d34c5b6cbc5111))
- concat() is shallow and does not merge ([#1541](https://github.com/jquense/yup/issues/1541)) ([a2f99d9](https://github.com/jquense/yup/commit/a2f99d9e8d8ba1b285fa6f48a0dd77a77f629ee4))
- simplify base class hierarchy ([#1543](https://github.com/jquense/yup/issues/1543)) ([c184dcf](https://github.com/jquense/yup/commit/c184dcf644c09f3c4697cd3e5c795784a5315f77))
- stricter `when` types and API ([#1542](https://github.com/jquense/yup/issues/1542)) ([da74254](https://github.com/jquense/yup/commit/da742545a228b909fef6f7fa526ea7b459d96051))

### BREAKING CHANGES

- `mixed` schema are no longer treated as the base class for other schema types. It hasn't been for a while, but we've done some nasty prototype slinging to make it behave like it was. Now typescript types should be 1 to 1 with the actual classes yup exposes.

In general this should not affect anything unless you are extending (via `addMethod` or otherwise) `mixed` prototype.

```diff
import {
-  mixed,
+  Schema,
} from 'yup';

- addMethod(mixed, 'method', impl)
+ addMethod(Schema, 'method', impl)
```

- concat works shallowly now. Previously concat functioned like a deep merge for object, which produced confusing behavior with incompatible concat'ed schema. Now concat for objects works similar to how it works for other types, the provided schema is applied on top of the existing schema, producing a new schema that is the same as calling each builder method in order
- The builder object version of `when()` requires `then` and `otherwise` to be
  functions `(schema: Schema) => Schema`.
- The function version of `when()` has been changed to make it easier to type. values are always passed as an array and schema, and options always the second and third argument. `this` is no longer set to the schema instance. and all functions _must_ return a schema to be type safe

```diff
 string()
-   .when('other', function (other) => {
-      if (other) return this.required()
+   .when('other', ([other], schema) => {
+     return other ? schema.required() : schema
  })
```

# [1.0.0-alpha.3](https://github.com/jquense/yup/compare/v0.32.11...v1.0.0-alpha.3) (2021-12-28)

### Bug Fixes

- schemaOf handles Dates ([c1fc816](https://github.com/jquense/yup/commit/c1fc816cdb03f7c9ff2e6745ff38a2b4f119d556))
- **types:** use type import/export ([#1238](https://github.com/jquense/yup/issues/1238)) ([bc284b5](https://github.com/jquense/yup/commit/bc284b5dbd4541464eb4a4edee73cb4d50c00fa7))

### Features

- More intuitive Object generics, faster types ([#1540](https://github.com/jquense/yup/issues/1540)) ([912e0be](https://github.com/jquense/yup/commit/912e0bed1e0184ba9c94015dc187eb6f86bb84d5))

# [1.0.0-alpha.2](https://github.com/jquense/yup/compare/v1.0.0-alpha.1...v1.0.0-alpha.2) (2020-12-18)

# [1.0.0-alpha.1](https://github.com/jquense/yup/compare/v1.0.0-alpha.0...v1.0.0-alpha.1) (2020-12-18)

### Bug Fixes

- **types:** make properties optional ([ba107cb](https://github.com/jquense/yup/commit/ba107cb50302e5245b960ed9a33f1c2167cc5d73))
- **types:** make properties optional ([495ae84](https://github.com/jquense/yup/commit/495ae84f8bfc22b9f4310700d4d8e9586584a4c7))

### Features

- remove unneeded Out type from schema ([0bf9732](https://github.com/jquense/yup/commit/0bf97327d406c9d982b2c0a93069bd047b53d5ef))

# [1.0.0-alpha.0](https://github.com/jquense/yup/compare/v0.32.8...v1.0.0-alpha.0) (2020-12-14)

### Features

- add describe and meta to lazy, with resolve options ([e56fea3](https://github.com/jquense/yup/commit/e56fea3d09707e975fa1e3bc19fadaac4d8b065b))


## [0.32.11](https://github.com/jquense/yup/compare/v0.32.10...v0.32.11) (2021-10-12)


### Bug Fixes

* dep ranges ([2015c0f](https://github.com/jquense/yup/commit/2015c0f717065360076d5c460a139a2fff410166))





## [0.32.10](https://github.com/jquense/yup/compare/v0.32.9...v0.32.10) (2021-10-11)


### Bug Fixes

* carry over excluded edges when concating objects ([5334349](https://github.com/jquense/yup/commit/53343491f0624120812182a70919a2fc3ebe11f5)), closes [#1423](https://github.com/jquense/yup/issues/1423)
* fix the typo for the array length validation ([#1287](https://github.com/jquense/yup/issues/1287)) ([4c17508](https://github.com/jquense/yup/commit/4c175086ce8e53df529bbdff6f215929a5a39167))
* missing transforms on concat ([f3056f2](https://github.com/jquense/yup/commit/f3056f2cbade92eaf0427848f43df97eae010555)), closes [#1260](https://github.com/jquense/yup/issues/1260)
* oneOf, notOneOf swallowing multiple errors ([#1434](https://github.com/jquense/yup/issues/1434)) ([7842afb](https://github.com/jquense/yup/commit/7842afbaca0a44fc2fea72b44a90c2000ca2b8f0))
* prevent unhandled Promise rejection when returning rejected Promise inside test function ([#1327](https://github.com/jquense/yup/issues/1327)) ([5eda549](https://github.com/jquense/yup/commit/5eda549dfce95be225b0eb6dbe3cbe7bcd5d3347))
* SchemaOf<>'s treatment of Date objects. ([#1305](https://github.com/jquense/yup/issues/1305)) ([91ace1e](https://github.com/jquense/yup/commit/91ace1e8be3fc23c775ec8117c47b406bf29da4a)), closes [#1243](https://github.com/jquense/yup/issues/1243) [#1302](https://github.com/jquense/yup/issues/1302)
* update lodash/lodash-es to fix CVEs flagged in 4.17.20 ([#1334](https://github.com/jquense/yup/issues/1334)) ([70d0b67](https://github.com/jquense/yup/commit/70d0b67e172f695168c5d00bc9856f2f775e0957))
* **utils:** use named functions for default exports ([#1329](https://github.com/jquense/yup/issues/1329)) ([acbb8b4](https://github.com/jquense/yup/commit/acbb8b4f3c24ceaf65eab09abaf8e086a9f11a73))


### Features

* add resolved to params ([#1437](https://github.com/jquense/yup/issues/1437)) ([03584f6](https://github.com/jquense/yup/commit/03584f6758ff43409113c41f58fd41e065aa18a3))
* add types to setLocale ([#1427](https://github.com/jquense/yup/issues/1427)) ([7576cd8](https://github.com/jquense/yup/commit/7576cd836ce9b660c054f9117795dbd9be12f747)), closes [#1321](https://github.com/jquense/yup/issues/1321)
* allows custom types to be passed to avoid cast to ObjectSchema ([#1358](https://github.com/jquense/yup/issues/1358)) ([94cfd11](https://github.com/jquense/yup/commit/94cfd11b3f23e10f731efac05c5525829d10ded1))





## [0.32.9](https://github.com/jquense/yup/compare/v0.32.6...v0.32.9) (2021-02-17)


### Bug Fixes

* **types:** Array required() and defined() will no longer return any ([#1256](https://github.com/jquense/yup/issues/1256)) ([52e5876](https://github.com/jquense/yup/commit/52e5876))
* export MixedSchema to fix ts with --declarations ([#1204](https://github.com/jquense/yup/issues/1204)) ([67c96ae](https://github.com/jquense/yup/commit/67c96ae))
* **types:** add generic to Reference.create() ([#1208](https://github.com/jquense/yup/issues/1208)) ([be3d1b4](https://github.com/jquense/yup/commit/be3d1b4))
* **types:** reach and getIn make last 2 arguments optional ([#1194](https://github.com/jquense/yup/issues/1194)) ([5cf2c48](https://github.com/jquense/yup/commit/5cf2c48))
* do not initialize spec values with undefined ([#1177](https://github.com/jquense/yup/issues/1177)) ([e8e5b46](https://github.com/jquense/yup/commit/e8e5b46)), closes [jquense/yup#1160](https://github.com/jquense/yup/issues/1160) [jquense/yup#1160](https://github.com/jquense/yup/issues/1160)
* **types:** meta() return type ([e41040a](https://github.com/jquense/yup/commit/e41040a))
* array handling in SchemaOf type ([#1169](https://github.com/jquense/yup/issues/1169)) ([e785e1a](https://github.com/jquense/yup/commit/e785e1a))
* **types:** make StringSchema.matches options optional ([#1166](https://github.com/jquense/yup/issues/1166)) ([b53e5f2](https://github.com/jquense/yup/commit/b53e5f2))
* **types:** SchemaOf doesn't produce a union of base schema ([2d71f32](https://github.com/jquense/yup/commit/2d71f32))





## [0.32.6](https://github.com/jquense/yup/compare/v0.32.5...v0.32.6) (2020-12-08)


### Bug Fixes

* mixed() is the the base class ([7f8591d](https://github.com/jquense/yup/commit/7f8591d)), closes [#1156](https://github.com/jquense/yup/issues/1156)





## [0.32.5](https://github.com/jquense/yup/compare/v0.32.4...v0.32.5) (2020-12-07)


### Bug Fixes

* **types:** change base.default() to any ([01c6930](https://github.com/jquense/yup/commit/01c6930))





## [0.32.4](https://github.com/jquense/yup/compare/v0.32.3...v0.32.4) (2020-12-07)


### Bug Fixes

* **types:** rm base pick/omit types as they conflict with more specific ones ([14e2c8c](https://github.com/jquense/yup/commit/14e2c8c))


### Features

* add additional functions to Lazy class ([#1148](https://github.com/jquense/yup/issues/1148)) ([ecad1a3](https://github.com/jquense/yup/commit/ecad1a3))





## [0.32.3](https://github.com/jquense/yup/compare/v0.32.2...v0.32.3) (2020-12-07)


### Bug Fixes

* **types:** AnyObjectSchema anys ([1c54665](https://github.com/jquense/yup/commit/1c54665))





## [0.32.2](https://github.com/jquense/yup/compare/v0.32.1...v0.32.2) (2020-12-07)


### Bug Fixes

* **types:** array type with lazy ([ba92dfc](https://github.com/jquense/yup/commit/ba92dfc)), closes [#1146](https://github.com/jquense/yup/issues/1146)





## [0.32.1](https://github.com/jquense/yup/compare/v0.32.0...v0.32.1) (2020-12-04)


### Bug Fixes

* cyclical import ([d5c5391](https://github.com/jquense/yup/commit/d5c5391)), closes [#1138](https://github.com/jquense/yup/issues/1138)
* some strict fn type improvements ([8092218](https://github.com/jquense/yup/commit/8092218))





# [0.32.0](https://github.com/jquense/yup/compare/v0.31.1...v0.32.0) (2020-12-03)


### Features

* typescript support ([#1134](https://github.com/jquense/yup/issues/1134)) ([b97c39d](https://github.com/jquense/yup/commit/b97c39d))


### BREAKING CHANGES

* `concat` doesn't check for "unset" nullable or presence when merging meaning the nullability and presence will always be the same as the schema passed to `concat()`. They can be overridden if needed after concatenation
* schema factory functions are no longer constructors. The classes are now also exported for extension or whatever else. e.g. `import { StringSchema, string } from 'yup'`





## [0.31.1](https://github.com/jquense/yup/compare/v0.31.0...v0.31.1) (2020-12-01)


### Bug Fixes

* swallowed errors on nested schema with no tests ([5316ab9](https://github.com/jquense/yup/commit/5316ab9)), closes [#1127](https://github.com/jquense/yup/issues/1127)


### Features

* add `isTrue` and `isFalse` checks on boolean ([#910](https://github.com/jquense/yup/issues/910)) ([630a641](https://github.com/jquense/yup/commit/630a641))





# [0.31.0](https://github.com/jquense/yup/compare/v0.30.0...v0.31.0) (2020-11-23)


### Bug Fixes

* path params incorrectly mutated ([ba23eb7](https://github.com/jquense/yup/commit/ba23eb7)), closes [#1122](https://github.com/jquense/yup/issues/1122)


### Features

* add array.length() and treat empty arrays as valid for required() ([fbc158d](https://github.com/jquense/yup/commit/fbc158d))
* add object.pick and object.omit ([425705a](https://github.com/jquense/yup/commit/425705a))
* deprecate the getter overload of `default()` ([#1119](https://github.com/jquense/yup/issues/1119)) ([5dae837](https://github.com/jquense/yup/commit/5dae837))
* more strictly coerce strings, exclude arrays and plain objects ([963d2e8](https://github.com/jquense/yup/commit/963d2e8))


### BREAKING CHANGES

* array().required() will no longer consider an empty array missing and required checks will pass.

To maintain the old behavior change to:
```js
array().required().min(1)
```
* plain objects and arrays are no long cast to strings automatically

to recreate the old behavior:
```js
string().transform((_, input) => input != null && input.toString ? input.toString() : value);
```





# [0.30.0](https://github.com/jquense/yup/compare/v0.29.3...v0.30.0) (2020-11-19)


### Bug Fixes

* defined() so it doesn't mark a schema as nullable ([f08d507](https://github.com/jquense/yup/commit/f08d507))
* IE11 clone() ([#1029](https://github.com/jquense/yup/issues/1029)) ([7fd80aa](https://github.com/jquense/yup/commit/7fd80aa))
* security Fix for Prototype Pollution - huntr.dev ([#1088](https://github.com/jquense/yup/issues/1088)) ([15a0f43](https://github.com/jquense/yup/commit/15a0f43))
* uuid's regexp ([#1112](https://github.com/jquense/yup/issues/1112)) ([57d42a8](https://github.com/jquense/yup/commit/57d42a8))


### Features

* exposes context on mixed.test function and add originalValue to context ([#1021](https://github.com/jquense/yup/issues/1021)) ([6096064](https://github.com/jquense/yup/commit/6096064))


### Performance Improvements

* reduce function calls for shallower stacks ([#1022](https://github.com/jquense/yup/issues/1022)) ([01da7e1](https://github.com/jquense/yup/commit/01da7e1))


### BREAKING CHANGES

* defined() now doesn't automatically allow null, this was a bug. to mimic the old behavior add nullable() to schema with defined()





## [0.29.3](https://github.com/jquense/yup/compare/v0.29.2...v0.29.3) (2020-08-04)





## [0.29.2](https://github.com/jquense/yup/compare/v0.29.1...v0.29.2) (2020-07-27)


### Bug Fixes

* handle sparse array positions as undefined ([#950](https://github.com/jquense/yup/issues/950)) ([4e77348](https://github.com/jquense/yup/commit/4e77348))


### Features

* string UUID validation via a regex ([#909](https://github.com/jquense/yup/issues/909)) ([8f2bd2b](https://github.com/jquense/yup/commit/8f2bd2b))





## [0.29.1](https://github.com/jquense/yup/compare/v0.29.0...v0.29.1) (2020-05-27)


### Bug Fixes

* present checks for array and strings ([ecd8ebe](https://github.com/jquense/yup/commit/ecd8ebe483456805d743c888a82e180394ba8a22)), closes [#913](https://github.com/jquense/yup/issues/913)


### Features

* allow access to parent schema (and unlimited ancestors!) in test context ([#556](https://github.com/jquense/yup/issues/556)) ([db35920](https://github.com/jquense/yup/commit/db35920b1ede4ea41ea90e1204b3da2a39787635))





# [0.29.0](https://github.com/jquense/yup/compare/v0.28.5...v0.29.0) (2020-05-19)


* feat!: update docs to account for changes in types and add additional example (#891) ([e105a71](https://github.com/jquense/yup/commit/e105a71)), closes [#891](https://github.com/jquense/yup/issues/891)


### Bug Fixes

* object bug when nested object has a property with strict ([#871](https://github.com/jquense/yup/issues/871)) ([7f52b8a](https://github.com/jquense/yup/commit/7f52b8a))


### Features

* expose oneOf and notOneOf values on description ([#885](https://github.com/jquense/yup/issues/885)) ([08dad5f](https://github.com/jquense/yup/commit/08dad5f))


### BREAKING CHANGES

* For users of `@types/yup` only, no function changes but the type def change is large enough that it warranted a major bump here





## [0.28.5](https://github.com/jquense/yup/compare/v0.28.4...v0.28.5) (2020-04-30)

### Bug Fixes

- allow passing of function to .matches() options/message param ([#850](https://github.com/jquense/yup/issues/850)) ([16efe88](https://github.com/jquense/yup/commit/16efe88a8953db60438f77f43bd5bf614079803d))
- bug in object.noUnknown for nullish values https://github.com/jquense/yup/issues/854 ([#855](https://github.com/jquense/yup/issues/855)) ([ccb7c7d](https://github.com/jquense/yup/commit/ccb7c7d3c450537dffbb7d589e3111fc1f9a86fd))

## [0.28.4](https://github.com/jquense/yup/compare/v0.28.3...v0.28.4) (2020-04-20)

### Bug Fixes

- array reaching ([81e4058](https://github.com/jquense/yup/commit/81e4058))

### Features

- make schema.type and array.innerType public API's ([8f00d50](https://github.com/jquense/yup/commit/8f00d50))
- provide keys in default noUnknown message ([#579](https://github.com/jquense/yup/issues/579)) ([ad5d015](https://github.com/jquense/yup/commit/ad5d015))

## [0.28.3](https://github.com/jquense/yup/compare/v0.28.2...v0.28.3) (2020-03-06)

### Bug Fixes

- array.ensure ([94659c2](https://github.com/jquense/yup/commit/94659c2)), closes [#343](https://github.com/jquense/yup/issues/343)
- match options ([493cc61](https://github.com/jquense/yup/commit/493cc61)), closes [#802](https://github.com/jquense/yup/issues/802) [#801](https://github.com/jquense/yup/issues/801) [#799](https://github.com/jquense/yup/issues/799) [#798](https://github.com/jquense/yup/issues/798)

# [0.28.0](https://github.com/jquense/yup/compare/v0.26.10...v0.28.0) (2019-12-16)

### Bug Fixes

- [#473](https://github.com/jquense/yup/issues/473) make concat compatible with (not)oneOf ([#492](https://github.com/jquense/yup/issues/492)) ([8d21cc9](https://github.com/jquense/yup/commit/8d21cc9))
- array path resolve for descendants ([#669](https://github.com/jquense/yup/issues/669)) ([d31e34d](https://github.com/jquense/yup/commit/d31e34d))
- change @babel/runtime version to be a range ([#488](https://github.com/jquense/yup/issues/488)) ([1c9b362](https://github.com/jquense/yup/commit/1c9b362)), closes [#486](https://github.com/jquense/yup/issues/486)
- concat of mixed and subtype ([#444](https://github.com/jquense/yup/issues/444)) ([7705972](https://github.com/jquense/yup/commit/7705972))
- default message for test with object ([#453](https://github.com/jquense/yup/issues/453)) ([f1be37f](https://github.com/jquense/yup/commit/f1be37f))
- noUnknown() overriding ([#452](https://github.com/jquense/yup/issues/452)) ([3047b33](https://github.com/jquense/yup/commit/3047b33))
- string.matches() and regex global flag ([#450](https://github.com/jquense/yup/issues/450)) ([a8935b7](https://github.com/jquense/yup/commit/a8935b7))
- synchronous conditional object validation with unknown dependencies ([#598](https://github.com/jquense/yup/issues/598)) ([1081c41](https://github.com/jquense/yup/commit/1081c41))
- typo README (about excludeEmptyString) ([#441](https://github.com/jquense/yup/issues/441)) ([d02ff5e](https://github.com/jquense/yup/commit/d02ff5e))
- unix epoc bug in date parser ([#655](https://github.com/jquense/yup/issues/655)) ([0d14827](https://github.com/jquense/yup/commit/0d14827))

### Features

- add \_isFilled as overrideable `mixed` method to control required behavior ([#459](https://github.com/jquense/yup/issues/459)) ([5b01f18](https://github.com/jquense/yup/commit/5b01f18))
- add function test names to email and url ([#292](https://github.com/jquense/yup/issues/292)) ([7e94395](https://github.com/jquense/yup/commit/7e94395))
- aliases `optional()` and `unknown()` ([#460](https://github.com/jquense/yup/issues/460)) ([51e8661](https://github.com/jquense/yup/commit/51e8661))
- allow toggling strict() ([#457](https://github.com/jquense/yup/issues/457)) ([851d421](https://github.com/jquense/yup/commit/851d421))
- allow withMutation() nesting ([#456](https://github.com/jquense/yup/issues/456)) ([e53ea8c](https://github.com/jquense/yup/commit/e53ea8c))
- do concat in mutation mode ([#461](https://github.com/jquense/yup/issues/461)) ([02be4ca](https://github.com/jquense/yup/commit/02be4ca))
- finalize resolve() ([#447](https://github.com/jquense/yup/issues/447)) ([afc5119](https://github.com/jquense/yup/commit/afc5119))
- replace integer check with Number.isInteger ([#405](https://github.com/jquense/yup/issues/405)) ([1c18442](https://github.com/jquense/yup/commit/1c18442))
- support self references ([#443](https://github.com/jquense/yup/issues/443)) ([1cac515](https://github.com/jquense/yup/commit/1cac515)), closes [/github.com/jquense/yup/blob/d02ff5e59e004b4c5189d1b9fc0055cff45c61df/src/Reference.js#L3](https://github.com//github.com/jquense/yup/blob/d02ff5e59e004b4c5189d1b9fc0055cff45c61df/src/Reference.js/issues/L3)
- use the alternate object index path syntax if the key contains dots (fixes [#536](https://github.com/jquense/yup/issues/536)) ([#539](https://github.com/jquense/yup/issues/539)) ([13e8c76](https://github.com/jquense/yup/commit/13e8c76))

### BREAKING CHANGES

- use Number.isInteger. This works correctly for large numbers.

Related to https://github.com/jquense/yup/pull/147

- reach() no longer resolves the returned schema meaning it's conditions have not been processed yet; prefer validateAt/castAt where it makes sense
- required no longer shows up twice in describe() output for array and strings, which also no longer override required

# [0.27.0](https://github.com/jquense/yup/compare/v0.26.10...v0.27.0) (2019-03-14)

### Bug Fixes

- change @babel/runtime version to be a range ([#488](https://github.com/jquense/yup/issues/488)) ([1c9b362](https://github.com/jquense/yup/commit/1c9b362)), closes [#486](https://github.com/jquense/yup/issues/486)
- concat of mixed and subtype ([#444](https://github.com/jquense/yup/issues/444)) ([7705972](https://github.com/jquense/yup/commit/7705972))
- default message for test with object ([#453](https://github.com/jquense/yup/issues/453)) ([f1be37f](https://github.com/jquense/yup/commit/f1be37f))
- noUnknown() overriding ([#452](https://github.com/jquense/yup/issues/452)) ([3047b33](https://github.com/jquense/yup/commit/3047b33))
- typo README (about excludeEmptyString) ([#441](https://github.com/jquense/yup/issues/441)) ([d02ff5e](https://github.com/jquense/yup/commit/d02ff5e))

### Features

- add \_isFilled as overrideable `mixed` method to control required behavior ([#459](https://github.com/jquense/yup/issues/459)) ([5b01f18](https://github.com/jquense/yup/commit/5b01f18))
- aliases `optional()` and `unknown()` ([#460](https://github.com/jquense/yup/issues/460)) ([51e8661](https://github.com/jquense/yup/commit/51e8661))
- allow toggling strict() ([#457](https://github.com/jquense/yup/issues/457)) ([851d421](https://github.com/jquense/yup/commit/851d421))
- allow withMutation() nesting ([#456](https://github.com/jquense/yup/issues/456)) ([e53ea8c](https://github.com/jquense/yup/commit/e53ea8c))
- do concat in mutation mode ([#461](https://github.com/jquense/yup/issues/461)) ([02be4ca](https://github.com/jquense/yup/commit/02be4ca))
- finalize resolve() ([#447](https://github.com/jquense/yup/issues/447)) ([afc5119](https://github.com/jquense/yup/commit/afc5119))
- support self references ([#443](https://github.com/jquense/yup/issues/443)) ([1cac515](https://github.com/jquense/yup/commit/1cac515)), closes [/github.com/jquense/yup/blob/d02ff5e59e004b4c5189d1b9fc0055cff45c61df/src/Reference.js#L3](https://github.com//github.com/jquense/yup/blob/d02ff5e59e004b4c5189d1b9fc0055cff45c61df/src/Reference.js/issues/L3)

### BREAKING CHANGES

- reach() no longer resolves the returned schema meaning it's conditions have not been processed yet; prefer validateAt/castAt where it makes sense
- required no longer shows up twice in describe() output for array and strings, which also no longer override required

## v0.26.3 - Tue, 28 Aug 2018 15:00:04 GMT

## v0.26.0 - Fri, 20 Jul 2018 15:39:03 GMT

### BREAKING CHANGES

- locale `number` config properties `less` and `more` are now `lessThan` and `moreThan`

## v0.25.1 - Wed, 16 May 2018 23:59:14 GMT

## v0.25.0 - Tue, 15 May 2018 21:43:54 GMT

- remove default export, there are only named exports now!
- fix message defaults for built-in tests, default is only used for `undefined` messages
- fix the `describe()` method so it works with nested schemas

## v0.24.1 - Fri, 09 Feb 2018 19:09:02 GMT

## v0.24.0 - Tue, 16 Jan 2018 14:44:32 GMT

- [f2a0b75](../../commit/f2a0b75), [061e590](../../commit/061e590) [added] number methods lessThan, moreThan

## v0.23.0 - Thu, 12 Oct 2017 17:08:47 GMT

** Probably not breaking but we are being safe about it **

- 🎉 Add Synchronous validation! [#94](https://github.com/jquense/yup/pull/94)

** Features **

- Custom locales without import order [#125](https://github.com/jquense/yup/pull/125)

## v0.22.1 - Thu, 12 Oct 2017 14:49:16 GMT

- Fix bug in browsers without symbol [#132](https://github.com/jquense/yup/pull/132)

## v0.22.0 - Sat, 26 Aug 2017 14:48:57 GMT

** Breaking **

- Use native Set and lodash CloneDeep: [#109](https://github.com/jquense/yup/pull/109)

\*\* Fixes and Features

- Better custom locale support: [#105](https://github.com/jquense/yup/pull/105)
- fix some messages: [#112](https://github.com/jquense/yup/pull/112)
- Clearer errors for common mistakes: [#108](https://github.com/jquense/yup/pull/108)
- New string validation length: [#67](https://github.com/jquense/yup/pull/67)

## v0.21.3 - Wed, 18 Jan 2017 15:39:25 GMT

- [7bc01e0](../../commit/7bc01e0) [added] deep path support for `from`

## v0.21.2 - Fri, 09 Sep 2016 16:52:44 GMT

- [be80413](../../commit/be80413) [fixed] default in concat()

## v0.21.1 - Mon, 29 Aug 2016 18:39:29 GMT

## v0.21.0 - Mon, 29 Aug 2016 18:29:31 GMT

- [8a8cc5b](../../commit/8a8cc5b) [changed] remove case aliases and simplify camelCase

## v0.20.0 - Wed, 20 Jul 2016 02:02:08 GMT

- [f7446d2](../../commit/f7446d2) [fixed] pass path correctly to cast()
- [9b5232a](../../commit/9b5232a) [added] allow function then/otherwise bodies
- [73858fe](../../commit/73858fe) [changed] Don't throw on undefined values in cast()

## v0.19.1 - Mon, 18 Jul 2016 21:53:05 GMT

- [69c0ad4](../../commit/69c0ad4) [fixed] array().concat() incorrectly cleared the sub-schema

## v0.19.0 - Fri, 24 Jun 2016 15:19:48 GMT

- [b0dd021](../../commit/b0dd021) [changed] Split integer(), remove transform
- [758ac51](../../commit/758ac51) [added] string.ensure
- [f2b0078](../../commit/f2b0078) [changed] Less aggressive type coercions
- [ab94510](../../commit/ab94510) [fixed] boxed number allowed NaN

## v0.18.3 - Mon, 09 May 2016 15:50:47 GMT

## v0.18.2 - Mon, 25 Apr 2016 18:23:13 GMT

## v0.18.1 - Mon, 25 Apr 2016 15:01:16 GMT

- [816e607](../../commit/816e607) [added] validation params to ValidationError

## v0.18.0 - Sat, 23 Apr 2016 01:20:27 GMT

- [f827822](../../commit/f827822) [changed] validate() on objects won't cast nested schema with strict()

## v0.17.6 - Thu, 21 Apr 2016 14:59:59 GMT

- [139dd24](../../commit/139dd24) [changed] lazy qualifies as a yup schema

## v0.17.5 - Thu, 21 Apr 2016 11:20:16 GMT

- [c553cc0](../../commit/c553cc0) [added] options to lazy resolve

## v0.17.4 - Wed, 20 Apr 2016 14:15:39 GMT

## v0.17.3 - Tue, 19 Apr 2016 20:24:09 GMT

- [6c309e4](../../commit/6c309e4) [fixed] array.ensure()

## v0.17.2 - Tue, 19 Apr 2016 16:46:54 GMT

## v0.17.1 - Thu, 14 Apr 2016 19:12:22 GMT

- [ab78f54](../../commit/ab78f54) [fixed] reach with lazy()

## v0.17.0 - Thu, 14 Apr 2016 17:13:50 GMT

- [6e9046b](../../commit/6e9046b) [changed] clean up interface, added lazy(), and fixed object strict semantics

## v0.16.5 - Tue, 12 Apr 2016 13:36:38 GMT

- [c3b613b](../../commit/c3b613b) [added] strip() method for objects
- [68fc010](../../commit/68fc010) [added] array.of shorthand

## v0.16.4 - Sat, 09 Apr 2016 20:13:13 GMT

- [f30d1e3](../../commit/f30d1e3) [fixed] bug in date min/max with ref

## v0.16.3 - Thu, 07 Apr 2016 19:13:23 GMT

## v0.16.2 - Thu, 07 Apr 2016 17:57:44 GMT

- [83c0656](../../commit/83c0656) [added] meta() and describe()

## v0.16.1 - Tue, 05 Apr 2016 20:56:45 GMT

- [9d70a7b](../../commit/9d70a7b) [changed] doesn't throw when context is missing.
- [594fa53](../../commit/594fa53) [changed] added reach error

## v0.16.0 - Tue, 05 Apr 2016 20:17:40 GMT

- [75739b8](../../commit/75739b8) [added] context sensitive reach()

## v0.15.0 - Tue, 29 Mar 2016 14:56:15 GMT

- [3ae5fdc](../../commit/3ae5fdc) [changed] `null` is not considered an empty value for isValid
- [9eb42c6](../../commit/9eb42c6) [added] refs!

## v0.14.2 - Tue, 29 Mar 2016 14:48:37 GMT

## v0.14.1 - Tue, 16 Feb 2016 19:51:25 GMT

- [ff19720](../../commit/ff19720) [fixed] noUnknown and stripUnknown work and propagate to children

## v0.14.0 - Mon, 08 Feb 2016 16:17:40 GMT

- [86b6446](../../commit/86b6446) [fixed] camelCase should maintain leading underscores

## v0.13.0 - Mon, 01 Feb 2016 20:49:40 GMT

- [335eb18](../../commit/335eb18) [fixed] pass options to array sub schema
- [f7f631d](../../commit/f7f631d) [changed] oneOf doesn't include empty values
- [0a7b2d4](../../commit/0a7b2d4) [fixed] type and whitelist/blacklist checks threw inconsistent errors
- [1274a45](../../commit/1274a45) [changed] required() to non-exclusive

## v0.12.0 - Tue, 12 Jan 2016 19:12:18 GMT

- [5bc250f](../../commit/5bc250f) [changed] don't clone unspecified object keys
- [069c6fd](../../commit/069c6fd) [added] withMutation() method
- [e1d4891](../../commit/e1d4891) [fixed] don't alias non existent fields

## v0.11.0 - Sun, 08 Nov 2015 17:17:09 GMT

- [686f6b1](../../commit/686f6b1) [changed] concat() allows mixing "mixed" and other type

## 0.9.0

**breaking**

- `test` functions are no longer passed `path` and `context` as arguments, Instead they are now values on `this` inside the test function.
- test functions are longer called with the schema as their `this` value, use `this.schema` instead.

**other changes**

- test functions are call with with a new context object, including, options, parent and `createError` for dynamically altering validation errors.

## 0.8.3

- document `stripUnknown`
- add `recursive` option
- add `noUnknown()` test to objects

## 0.8.2

- default for objects now adds keys for all fields, not just fields with non empty defaults

## 0.8.1

- bug fix

## 0.8.0

**breaking**

- `test` functions are now passed `path` and `context` values along with the field value. Only breaks if using the callback style of defining custom validations

## 0.7.0

**breaking**

- the `validation()` method has been renamed to `test()` and has a new signature requiring a `name` argument
- exclusive validations now trump the previous one instead of defering to it e.g: `string().max(10).max(15)` has a max of `15` instead of `10`

**other changes**

- expose advanced signature for custom validation tests, gives finer grained control over how tests are added
- added the `abortEarly` (default: `true`) option
- transforms are passed an addition parameter: 'originalValue' you allow recovering from a bad transform further up the chain (provided no one mutated the value)

## 0.6.3

- fix `concat()` method and add tests

## 0.6.2

- fix validations where nullable fields were failing due to `null` values e.g `string.max()`

## 0.6.1

- fix export error

## 0.6.0

**breaking**

- Removed the `extend` and `create` methods. Use whatever javascript inheritance patterns you want instead.
- the resolution order of defaults and coercions has changed. as well as the general handling of `null` values.
  - Number: `null` will coerce to `false` when `nullable()` is not specified. `NaN` values will now fail `isType()` checks
  - String: `null` will coerce to `''` when `nullable()` is not specified
  - Date: Invalid dates will not be coerced to `null`, but left as invalid date, This is probably not a problem for anyone as invalid dates will also fail `isType()` checks
- default values are cloned everytime they are returned, so it is impossible to share references to defaults across schemas. No one should be doing that anyway
- stopped pretending that using schemas as conditions in `when()` actually worked (it didn't)

**other changes**

- `transform()` now passes the original value to each transformer. Allowing you to recover from a bad transform.
- added the `equals()` alias for `oneOf`
-

## 0.5.0

**breaking**

- isValid is now async, provide a node style callback, or use the promise the method returns to read the validity. This change allows for more robust validations, specifically remote ones for client code (or db queries for server code). The cast method is still, and will remain, synchronous.
-

**other changes**

- added validate method (also async) which resolves to the value, and rejects with a new ValidationError


================================================
FILE: LICENSE.md
================================================
The MIT License (MIT)

Copyright (c) 2014 Jason Quense

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: README.md
================================================
# Yup

Yup is a schema builder for runtime value parsing and validation. Define a schema, transform a value to match, assert the shape of an existing value, or both. Yup schema are extremely expressive and allow modeling complex, interdependent validations, or value transformation.

> **You are viewing docs for the v1.0.0 of yup, pre-v1 docs are available: [here](https://github.com/jquense/yup/tree/pre-v1)**

**Killer Features**:

- Concise yet expressive schema interface, equipped to model simple to complex data models
- Powerful TypeScript support. Infer static types from schema, or ensure schema correctly implement a type
- Built-in async validation support. Model server-side and client-side validation equally well
- Extensible: add your own type-safe methods and schema
- Rich error details, make debugging a breeze
- Compatible with [Standard Schema](https://github.com/standard-schema/standard-schema)

## Getting Started

Schema are comprised of parsing actions (transforms) as well as assertions (tests) about the input value.
Validate an input value to parse it and run the configured set of assertions. Chain together methods to build a schema.

```ts
import { object, string, number, date, InferType } from 'yup';

let userSchema = object({
  name: string().required(),
  age: number().required().positive().integer(),
  email: string().email(),
  website: string().url().nullable(),
  createdOn: date().default(() => new Date()),
});

// parse and assert validity
let user = await userSchema.validate(await fetchUser());

type User = InferType<typeof userSchema>;
/* {
  name: string;
  age: number;
  email?: string | undefined
  website?: string | null | undefined
  createdOn: Date
}*/
```

Use a schema to coerce or "cast" an input value into the correct type, and optionally
transform that value into more concrete and specific values, without making further assertions.

```ts
// Attempts to coerce values to the correct type
let parsedUser = userSchema.cast({
  name: 'jimmy',
  age: '24',
  createdOn: '2014-09-23T19:25:25Z',
});
// ✅  { name: 'jimmy', age: 24, createdOn: Date }
```

Know that your input value is already parsed? You can "strictly" validate an input, and avoid the overhead
of running parsing logic.

```ts
// ❌  ValidationError "age is not a number"
let parsedUser = await userSchema.validate(
  {
    name: 'jimmy',
    age: '24',
  },
  { strict: true },
);
```

## Table of Contents

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->

- [Schema basics](#schema-basics)
  - [Parsing: Transforms](#parsing-transforms)
  - [Validation: Tests](#validation-tests)
    - [Customizing errors](#customizing-errors)
  - [Composition and Reuse](#composition-and-reuse)
- [TypeScript integration](#typescript-integration)
  - [Schema defaults](#schema-defaults)
  - [Ensuring a schema matches an existing type](#ensuring-a-schema-matches-an-existing-type)
  - [Extending built-in schema with new methods](#extending-built-in-schema-with-new-methods)
  - [TypeScript configuration](#typescript-configuration)
- [Error message customization](#error-message-customization)
  - [localization and i18n](#localization-and-i18n)
- [Standard Schema Support](#standard-schema-support)
- [API](#api)
  - [`yup`](#yup)
    - [`reach(schema: Schema, path: string, value?: object, context?: object): Schema`](#reachschema-schema-path-string-value-object-context-object-schema)
    - [`addMethod(schemaType: Schema, name: string, method: ()=> Schema): void`](#addmethodschematype-schema-name-string-method--schema-void)
    - [`ref(path: string, options: { contextPrefix: string }): Ref`](#refpath-string-options--contextprefix-string--ref)
    - [`lazy((value: any) => Schema): Lazy`](#lazyvalue-any--schema-lazy)
    - [`ValidationError(errors: string | Array<string>, value: any, path: string)`](#validationerrorerrors-string--arraystring-value-any-path-string)
  - [`Schema`](#schema)
    - [`Schema.clone(): Schema`](#schemaclone-schema)
    - [`Schema.label(label: string): Schema`](#schemalabellabel-string-schema)
    - [`Schema.meta(metadata: SchemaMetadata): Schema`](#schemametametadata-schemametadata-schema)
    - [`Schema.describe(options?: ResolveOptions): SchemaDescription`](#schemadescribeoptions-resolveoptions-schemadescription)
    - [`Schema.concat(schema: Schema): Schema`](#schemaconcatschema-schema-schema)
    - [`Schema.validate(value: any, options?: object): Promise<InferType<Schema>, ValidationError>`](#schemavalidatevalue-any-options-object-promiseinfertypeschema-validationerror)
    - [`Schema.validateSync(value: any, options?: object): InferType<Schema>`](#schemavalidatesyncvalue-any-options-object-infertypeschema)
    - [`Schema.validateAt(path: string, value: any, options?: object): Promise<InferType<Schema>, ValidationError>`](#schemavalidateatpath-string-value-any-options-object-promiseinfertypeschema-validationerror)
    - [`Schema.validateSyncAt(path: string, value: any, options?: object): InferType<Schema>`](#schemavalidatesyncatpath-string-value-any-options-object-infertypeschema)
    - [`Schema.isValid(value: any, options?: object): Promise<boolean>`](#schemaisvalidvalue-any-options-object-promiseboolean)
    - [`Schema.isValidSync(value: any, options?: object): boolean`](#schemaisvalidsyncvalue-any-options-object-boolean)
    - [`Schema.cast(value: any, options = {}): InferType<Schema>`](#schemacastvalue-any-options---infertypeschema)
    - [`Schema.isType(value: any): value is InferType<Schema>`](#schemaistypevalue-any-value-is-infertypeschema)
    - [`Schema.strict(enabled: boolean = false): Schema`](#schemastrictenabled-boolean--false-schema)
    - [`Schema.strip(enabled: boolean = true): Schema`](#schemastripenabled-boolean--true-schema)
    - [`Schema.withMutation(builder: (current: Schema) => void): void`](#schemawithmutationbuilder-current-schema--void-void)
    - [`Schema.default(value: any): Schema`](#schemadefaultvalue-any-schema)
    - [`Schema.getDefault(options?: object): Any`](#schemagetdefaultoptions-object-any)
    - [`Schema.nullable(message?: string | function): Schema`](#schemanullablemessage-string--function-schema)
    - [`Schema.nonNullable(message?: string | function): Schema`](#schemanonnullablemessage-string--function-schema)
    - [`Schema.defined(): Schema`](#schemadefined-schema)
    - [`Schema.optional(): Schema`](#schemaoptional-schema)
    - [`Schema.required(message?: string | function): Schema`](#schemarequiredmessage-string--function-schema)
    - [`Schema.notRequired(): Schema`](#schemanotrequired-schema)
    - [`Schema.typeError(message: string): Schema`](#schematypeerrormessage-string-schema)
    - [`Schema.oneOf(arrayOfValues: Array<any>, message?: string | function): Schema` Alias: `equals`](#schemaoneofarrayofvalues-arrayany-message-string--function-schema-alias-equals)
    - [`Schema.notOneOf(arrayOfValues: Array<any>, message?: string | function)`](#schemanotoneofarrayofvalues-arrayany-message-string--function)
    - [`Schema.when(keys: string | string[], builder: object | (values: any[], schema) => Schema): Schema`](#schemawhenkeys-string--string-builder-object--values-any-schema--schema-schema)
    - [`Schema.test(name: string, message: string | function | any, test: function): Schema`](#schematestname-string-message-string--function--any-test-function-schema)
    - [`Schema.test(options: object): Schema`](#schematestoptions-object-schema)
    - [`Schema.transform((currentValue: any, originalValue: any, schema: Schema,  options: object) => any): Schema`](#schematransformcurrentvalue-any-originalvalue-any-schema-schema--options-object--any-schema)
  - [mixed](#mixed)
  - [string](#string)
    - [`string.required(message?: string | function): Schema`](#stringrequiredmessage-string--function-schema)
    - [`string.length(limit: number | Ref, message?: string | function): Schema`](#stringlengthlimit-number--ref-message-string--function-schema)
    - [`string.min(limit: number | Ref, message?: string | function): Schema`](#stringminlimit-number--ref-message-string--function-schema)
    - [`string.max(limit: number | Ref, message?: string | function): Schema`](#stringmaxlimit-number--ref-message-string--function-schema)
    - [`string.matches(regex: Regex, message?: string | function): Schema`](#stringmatchesregex-regex-message-string--function-schema)
    - [`string.matches(regex: Regex, options: { message: string, excludeEmptyString: bool }): Schema`](#stringmatchesregex-regex-options--message-string-excludeemptystring-bool--schema)
    - [`string.email(message?: string | function): Schema`](#stringemailmessage-string--function-schema)
    - [`string.url(message?: string | function): Schema`](#stringurlmessage-string--function-schema)
    - [`string.uuid(message?: string | function): Schema`](#stringuuidmessage-string--function-schema)
    - [`string.datetime(options?: {message?: string | function, allowOffset?: boolean, precision?: number})`](#stringdatetimeoptions-message-string--function-allowoffset-boolean-precision-number)
    - [`string.datetime(message?: string | function)`](#stringdatetimemessage-string--function)
    - [`string.ensure(): Schema`](#stringensure-schema)
    - [`string.trim(message?: string | function): Schema`](#stringtrimmessage-string--function-schema)
    - [`string.lowercase(message?: string | function): Schema`](#stringlowercasemessage-string--function-schema)
    - [`string.uppercase(message?: string | function): Schema`](#stringuppercasemessage-string--function-schema)
  - [number](#number)
    - [`number.min(limit: number | Ref, message?: string | function): Schema`](#numberminlimit-number--ref-message-string--function-schema)
    - [`number.max(limit: number | Ref, message?: string | function): Schema`](#numbermaxlimit-number--ref-message-string--function-schema)
    - [`number.lessThan(max: number | Ref, message?: string | function): Schema`](#numberlessthanmax-number--ref-message-string--function-schema)
    - [`number.moreThan(min: number | Ref, message?: string | function): Schema`](#numbermorethanmin-number--ref-message-string--function-schema)
    - [`number.positive(message?: string | function): Schema`](#numberpositivemessage-string--function-schema)
    - [`number.negative(message?: string | function): Schema`](#numbernegativemessage-string--function-schema)
    - [`number.integer(message?: string | function): Schema`](#numberintegermessage-string--function-schema)
    - [`number.truncate(): Schema`](#numbertruncate-schema)
    - [`number.round(type: 'floor' | 'ceil' | 'trunc' | 'round' = 'round'): Schema`](#numberroundtype-floor--ceil--trunc--round--round-schema)
  - [boolean](#boolean)
  - [date](#date)
    - [`date.min(limit: Date | string | Ref, message?: string | function): Schema`](#dateminlimit-date--string--ref-message-string--function-schema)
    - [`date.max(limit: Date | string | Ref, message?: string | function): Schema`](#datemaxlimit-date--string--ref-message-string--function-schema)
  - [array](#array)
    - [`array.of(type: Schema): this`](#arrayoftype-schema-this)
    - [`array.json(): this`](#arrayjson-this)
    - [`array.length(length: number | Ref, message?: string | function): this`](#arraylengthlength-number--ref-message-string--function-this)
    - [`array.min(limit: number | Ref, message?: string | function): this`](#arrayminlimit-number--ref-message-string--function-this)
    - [`array.max(limit: number | Ref, message?: string | function): this`](#arraymaxlimit-number--ref-message-string--function-this)
    - [`array.ensure(): this`](#arrayensure-this)
    - [`array.compact(rejector: (value) => boolean): Schema`](#arraycompactrejector-value--boolean-schema)
  - [tuple](#tuple)
  - [object](#object)
    - [Object schema defaults](#object-schema-defaults)
    - [`object.shape(fields: object, noSortEdges?: Array<[string, string]>): Schema`](#objectshapefields-object-nosortedges-arraystring-string-schema)
    - [`object.json(): this`](#objectjson-this)
    - [`object.concat(schemaB: ObjectSchema): ObjectSchema`](#objectconcatschemab-objectschema-objectschema)
    - [`object.pick(keys: string[]): Schema`](#objectpickkeys-string-schema)
    - [`object.omit(keys: string[]): Schema`](#objectomitkeys-string-schema)
    - [`object.from(fromKey: string, toKey: string, alias: boolean = false): this`](#objectfromfromkey-string-tokey-string-alias-boolean--false-this)
    - [`object.exact(message?: string | function): Schema`](#objectexactmessage-string--function-schema)
    - [`object.stripUnknown(): Schema`](#objectstripunknown-schema)
    - [`object.noUnknown(onlyKnownKeys: boolean = true, message?: string | function): Schema`](#objectnounknownonlyknownkeys-boolean--true-message-string--function-schema)
    - [`object.camelCase(): Schema`](#objectcamelcase-schema)
    - [`object.constantCase(): Schema`](#objectconstantcase-schema)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

## Schema basics

Schema definitions, are comprised of parsing "transforms" which manipulate inputs into the desired shape and type, "tests", which make assertions over parsed data. Schema also store a bunch of "metadata", details about the schema itself, which can be used to improve error messages, build tools that dynamically consume schema, or serialize schema into another format.

In order to be maximally flexible yup allows running both parsing and assertions separately to match specific needs

### Parsing: Transforms

Each built-in type implements basic type parsing, which comes in handy when parsing serialized data, such as JSON.
Additionally types implement type specific transforms that can be enabled.

```ts
let num = number().cast('1'); // 1

let obj = object({
  firstName: string().lowercase().trim(),
})
  .json()
  .camelCase()
  .cast('{"first_name": "jAnE "}'); // { firstName: 'jane' }
```

Custom transforms can be added

```ts
let reversedString = string()
  .transform((currentValue) => currentValue.split('').reverse().join(''))
  .cast('dlrow olleh'); // "hello world"
```

Transforms form a "pipeline", where the value of a previous transform is piped into the next one.
When an input value is `undefined` yup will apply the schema default if it's configured.

> Watch out! values are not guaranteed to be valid types in transform functions. Previous transforms
> may have failed. For example a number transform may be receive the input value, `NaN`, or a number.

### Validation: Tests

Yup schema run "tests" over input values. Tests assert that inputs conform to some
criteria. Tests are distinct from transforms, in that they do not change or alter the input (or its type)
and are usually reserved for checks that are hard, if not impossible, to represent in static types.

```ts
string()
  .min(3, 'must be at least 3 characters long')
  .email('must be a valid email')
  .validate('no'); // ValidationError
```

As with transforms, tests can be customized on the fly

```ts
let jamesSchema = string().test(
  'is-james',
  (d) => `${d.path} is not James`,
  (value) => value == null || value === 'James',
);

jamesSchema.validateSync('James'); // "James"

jamesSchema.validateSync('Jane'); // ValidationError "this is not James"
```

> Heads up: unlike transforms, `value` in a custom test is guaranteed to be the correct type
> (in this case an optional string). It still may be `undefined` or `null` depending on your schema
> in those cases, you may want to return `true` for absent values unless your transform makes presence
> related assertions. The test option `skipAbsent` will do this for you if set.

#### Customizing errors

In the simplest case a test function returns `true` or `false` depending on the whether the check
passed. In the case of a failing test, yup will throw
a [`ValidationError`](#validationerrorerrors-string--arraystring-value-any-path-string) with your (or the default)
message for that test. ValidationErrors also contain a bunch of other metadata about the test,
including it's name, what arguments (if any) it was called with, and the path to the failing field
in the case of a nested validation.

Error messages can also be constructed on the fly to customize how the schema fails.

```ts
let order = object({
  no: number().required(),
  sku: string().test({
    name: 'is-sku',
    skipAbsent: true,
    test(value, ctx) {
      if (!value.startsWith('s-')) {
        return ctx.createError({ message: 'SKU missing correct prefix' });
      }
      if (!value.endsWith('-42a')) {
        return ctx.createError({ message: 'SKU missing correct suffix' });
      }
      if (value.length < 10) {
        return ctx.createError({ message: 'SKU is not the right length' });
      }
      return true;
    },
  }),
});

order.validate({ no: 1234, sku: 's-1a45-14a' });
```

### Composition and Reuse

Schema are immutable, each method call returns a new schema object. Reuse and pass them around without
fear of mutating another instance.

```ts
let optionalString = string().optional();

let definedString = optionalString.defined();

let value = undefined;
optionalString.isValid(value); // true
definedString.isValid(value); // false
```

## TypeScript integration

Yup schema produce static TypeScript interfaces. Use `InferType` to extract that interface:

```ts
import * as yup from 'yup';

let personSchema = yup.object({
  firstName: yup.string().defined(),
  nickName: yup.string().default('').nullable(),
  sex: yup
    .mixed()
    .oneOf(['male', 'female', 'other'] as const)
    .defined(),
  email: yup.string().nullable().email(),
  birthDate: yup.date().nullable().min(new Date(1900, 0, 1)),
});

interface Person extends yup.InferType<typeof personSchema> {
  // using interface instead of type generally gives nicer editor feedback
}
```

### Schema defaults

A schema's default is used when casting produces an `undefined` output value. Because of this,
setting a default affects the output type of the schema, essentially marking it as "defined()".

```ts
import { string } from 'yup';

let value: string = string().default('hi').validate(undefined);

// vs

let value: string | undefined = string().validate(undefined);
```

### Ensuring a schema matches an existing type

In some cases a TypeScript type already exists, and you want to ensure that
your schema produces a compatible type:

```ts
import { object, number, string, ObjectSchema } from 'yup';

interface Person {
  name: string;
  age?: number;
  sex: 'male' | 'female' | 'other' | null;
}

// will raise a compile-time type error if the schema does not produce a valid Person
let schema: ObjectSchema<Person> = object({
  name: string().defined(),
  age: number().optional(),
  sex: string<'male' | 'female' | 'other'>().nullable().defined(),
});

// ❌ errors:
// "Type 'number | undefined' is not assignable to type 'string'."
let badSchema: ObjectSchema<Person> = object({
  name: number(),
});
```

### Extending built-in schema with new methods

You can use TypeScript's interface merging behavior to extend the schema types
if needed. Type extensions should go in an "ambient" type definition file such as your
`globals.d.ts`. Remember to actually extend the yup type in your application code!

> Watch out! merging only works if the type definition is _exactly_ the same, including
> generics. Consult the yup source code for each type to ensure you are defining it correctly

```ts
// globals.d.ts
declare module 'yup' {
  interface StringSchema<TType, TContext, TDefault, TFlags> {
    append(appendStr: string): this;
  }
}

// app.ts
import { addMethod, string } from 'yup';

addMethod(string, 'append', function append(appendStr: string) {
  return this.transform((value) => `${value}${appendStr}`);
});

string().append('~~~~').cast('hi'); // 'hi~~~~'
```

### TypeScript configuration

You **must** have the `strictNullChecks` compiler option enabled for type inference to work.

We also recommend settings `strictFunctionTypes` to `false`, for functionally better types. Yes
this reduces overall soundness, however TypeScript already disables this check
for methods and constructors (note from TS docs):

> During development of this feature, we discovered a large number of inherently
> unsafe class hierarchies, including some in the DOM. Because of this,
> the setting only applies to functions written in function syntax, not to those in method syntax:

Your mileage will vary, but we've found that this check doesn't prevent many of
real bugs, while increasing the amount of onerous explicit type casting in apps.

## Error message customization

Default error messages can be customized for when no message is provided with a validation test.
If any message is missing in the custom dictionary the error message will default to Yup's one.

```js
import { setLocale } from 'yup';

setLocale({
  mixed: {
    default: 'Não é válido',
  },
  number: {
    min: 'Deve ser maior que ${min}',
  },
});

// now use Yup schemas AFTER you defined your custom dictionary
let schema = yup.object().shape({
  name: yup.string(),
  age: yup.number().min(18),
});

try {
  await schema.validate({ name: 'jimmy', age: 11 });
} catch (err) {
  err.name; // => 'ValidationError'
  err.errors; // => ['Deve ser maior que 18']
}
```

### localization and i18n

If you need multi-language support, yup has got you covered. The function `setLocale` accepts functions that can be used to
generate error objects with translation keys and values. These can be fed it into your favorite i18n library.

```js
import { setLocale } from 'yup';

setLocale({
  // use constant translation keys for messages without values
  mixed: {
    default: 'field_invalid',
  },
  // use functions to generate an error object that includes the value from the schema
  number: {
    min: ({ min }) => ({ key: 'field_too_short', values: { min } }),
    max: ({ max }) => ({ key: 'field_too_big', values: { max } }),
  },
});

// ...

let schema = yup.object().shape({
  name: yup.string(),
  age: yup.number().min(18),
});

try {
  await schema.validate({ name: 'jimmy', age: 11 });
} catch (err) {
  messages = err.errors.map((err) => i18next.t(err.key));
}
```

## Standard Schema Support

Yup is compatible with [Standard Schema](https://github.com/standard-schema/standard-schema).

## API

### `yup`

The module export.

```ts
// core schema
import {
  mixed,
  string,
  number,
  boolean,
  bool,
  date,
  object,
  array,
  ref,
  lazy,
} from 'yup';

// Classes
import {
  Schema,
  MixedSchema,
  StringSchema,
  NumberSchema,
  BooleanSchema,
  DateSchema,
  ArraySchema,
  ObjectSchema,
} from 'yup';

// Types
import type { InferType, ISchema, AnySchema, AnyObjectSchema } from 'yup';
```

#### `reach(schema: Schema, path: string, value?: object, context?: object): Schema`

For nested schemas, `reach` will retrieve an inner schema based on the provided path.

For nested schemas that need to resolve dynamically, you can provide a `value` and optionally
a `context` object.

```js
import { reach } from 'yup';

let schema = object({
  nested: object({
    arr: array(object({ num: number().max(4) })),
  }),
});

reach(schema, 'nested.arr.num');
reach(schema, 'nested.arr[].num');
reach(schema, 'nested.arr[1].num');
reach(schema, 'nested["arr"][1].num');
```

#### `addMethod(schemaType: Schema, name: string, method: ()=> Schema): void`

Adds a new method to the core schema types. A friendlier convenience method for `schemaType.prototype[name] = method`.

```ts
import { addMethod, date } from 'yup';

addMethod(date, 'format', function format(formats, parseStrict) {
  return this.transform((value, originalValue, ctx) => {
    if (ctx.isType(value)) return value;

    value = Moment(originalValue, formats, parseStrict);

    return value.isValid() ? value.toDate() : new Date('');
  });
});
```

If you want to add a method to ALL schema types, extend the abstract base class: `Schema`

```ts
import { addMethod, Schema } from 'yup';

addMethod(Schema, 'myMethod', ...)
```

#### `ref(path: string, options: { contextPrefix: string }): Ref`

Creates a reference to another sibling or sibling descendant field. Refs are resolved
at _validation/cast time_ and supported where specified. Refs are evaluated in the proper order so that
the ref value is resolved before the field using the ref (be careful of circular dependencies!).

```js
import { ref, object, string } from 'yup';

let schema = object({
  baz: ref('foo.bar'),
  foo: object({
    bar: string(),
  }),
  x: ref('$x'),
});

schema.cast({ foo: { bar: 'boom' } }, { context: { x: 5 } });
// => { baz: 'boom',  x: 5, foo: { bar: 'boom' } }
```

#### `lazy((value: any) => Schema): Lazy`

Creates a schema that is evaluated at validation/cast time. Useful for creating
recursive schema like Trees, for polymorphic fields and arrays.

**CAUTION!** When defining parent-child recursive object schema, you want to reset the `default()`
to `null` on the child—otherwise the object will infinitely nest itself when you cast it!

```js
let node = object({
  id: number(),
  child: yup.lazy(() => node.default(undefined)),
});

let renderable = yup.lazy((value) => {
  switch (typeof value) {
    case 'number':
      return number();
    case 'string':
      return string();
    default:
      return mixed();
  }
});

let renderables = array().of(renderable);
```

#### `ValidationError(errors: string | Array<string>, value: any, path: string)`

Thrown on failed validations, with the following properties

- `name`: "ValidationError"
- `type`: the specific test type or test "name", that failed.
- `value`: The field value that was tested;
- `params`?: The test inputs, such as max value, regex, etc;
- `path`: a string, indicating where there error was thrown. `path` is empty at the root level.
- `errors`: array of error messages
- `inner`: in the case of aggregate errors, inner is an array of `ValidationErrors` throw earlier in the
  validation chain. When the `abortEarly` option is `false` this is where you can inspect each error thrown,
  alternatively, `errors` will have all of the messages from each inner error.

### `Schema`

`Schema` is the abstract base class that all schema type inherit from. It provides a number of base methods and properties
to all other schema types.

> Note: unless you are creating a custom schema type, Schema should never be used directly. For unknown/any types use [`mixed()`](#mixed)

#### `Schema.clone(): Schema`

Creates a deep copy of the schema. Clone is used internally to return a new schema with every schema state change.

#### `Schema.label(label: string): Schema`

Overrides the key name which is used in error messages.

#### `Schema.meta(metadata: SchemaMetadata): Schema`

Adds to a metadata object, useful for storing data with a schema, that doesn't belong
to the cast object itself.

A custom `SchemaMetadata` interface can be defined through
[merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#merging-interfaces)
with the `CustomSchemaMetadata` interface. Start by creating a `yup.d.ts` file
in your package and creating your desired `CustomSchemaMetadata` interface:

```ts
// yup.d.ts
import 'yup';

declare module 'yup' {
  // Define your desired `SchemaMetadata` interface by merging the
  // `CustomSchemaMetadata` interface.
  export interface CustomSchemaMetadata {
    placeholderText?: string;
    tooltipText?: string;
    // …
  }
}
```

#### `Schema.describe(options?: ResolveOptions): SchemaDescription`

Collects schema details (like meta, labels, and active tests) into a serializable
description object.

```ts
let schema = object({
  name: string().required(),
});

let description = schema.describe();
```

For schema with dynamic components (references, lazy, or conditions), describe requires
more context to accurately return the schema description. In these cases provide `options`

```ts
import { ref, object, string, boolean } from 'yup';

let schema = object({
  isBig: boolean(),
  count: number().when('isBig', {
    is: true,
    then: (schema) => schema.min(5),
    otherwise: (schema) => schema.min(0),
  }),
});

schema.describe({ value: { isBig: true } });
```

And below are the description types, which differ a bit depending on the schema type.

```ts
interface SchemaDescription {
  type: string;
  label?: string;
  meta: object | undefined;
  oneOf: unknown[];
  notOneOf: unknown[];
  default?: unknown;
  nullable: boolean;
  optional: boolean;
  tests: Array<{ name?: string; params: ExtraParams | undefined }>;

  // Present on object schema descriptions
  fields: Record<string, SchemaFieldDescription>;

  // Present on array schema descriptions
  innerType?: SchemaFieldDescription;
}

type SchemaFieldDescription =
  | SchemaDescription
  | SchemaRefDescription
  | SchemaLazyDescription;

interface SchemaRefDescription {
  type: 'ref';
  key: string;
}

interface SchemaLazyDescription {
  type: string;
  label?: string;
  meta: object | undefined;
}
```

#### `Schema.concat(schema: Schema): Schema`

Creates a new instance of the schema by combining two schemas. Only schemas of the same type can be concatenated.
`concat` is not a "merge" function in the sense that all settings from the provided schema, override ones in the
base, including type, presence and nullability.

```ts
mixed<string>().defined().concat(mixed<number>().nullable());

// produces the equivalent to:

mixed<number>().defined().nullable();
```

#### `Schema.validate(value: any, options?: object): Promise<InferType<Schema>, ValidationError>`

Returns the parses and validates an input value, returning the parsed value or throwing an error. This method is **asynchronous** and returns a Promise object, that is fulfilled with the value, or rejected
with a `ValidationError`.

```js
value = await schema.validate({ name: 'jimmy', age: 24 });
```

Provide `options` to more specifically control the behavior of `validate`.

```js
interface Options {
  // when true, parsing is skipped and the input is validated "as-is"
  strict: boolean = false;
  // Throw on the first error or collect and return all
  abortEarly: boolean = true;
  // Remove unspecified keys from objects
  stripUnknown: boolean = false;
  // when `false` validations will be performed shallowly
  recursive: boolean = true;
  // External values that can be provided to validations and conditionals
  context?: object;
}
```

#### `Schema.validateSync(value: any, options?: object): InferType<Schema>`

Runs validatations synchronously _if possible_ and returns the resulting value,
or throws a ValidationError. Accepts all the same options as `validate`.

Synchronous validation only works if there are no configured async tests, e.g tests that return a Promise.
For instance this will work:

```js
let schema = number().test(
  'is-42',
  "this isn't the number i want",
  (value) => value != 42,
);

schema.validateSync(23); // throws ValidationError
```

however this will not:

```js
let schema = number().test('is-42', "this isn't the number i want", (value) =>
  Promise.resolve(value != 42),
);

schema.validateSync(42); // throws Error
```

#### `Schema.validateAt(path: string, value: any, options?: object): Promise<InferType<Schema>, ValidationError>`

Validate a deeply nested path within the schema. Similar to how `reach` works,
but uses the resulting schema as the subject for validation.

> Note! The `value` here is the _root_ value relative to the starting schema, not the value at the nested path.

```js
let schema = object({
  foo: array().of(
    object({
      loose: boolean(),
      bar: string().when('loose', {
        is: true,
        otherwise: (schema) => schema.strict(),
      }),
    }),
  ),
});

let rootValue = {
  foo: [{ bar: 1 }, { bar: 1, loose: true }],
};

await schema.validateAt('foo[0].bar', rootValue); // => ValidationError: must be a string

await schema.validateAt('foo[1].bar', rootValue); // => '1'
```

#### `Schema.validateSyncAt(path: string, value: any, options?: object): InferType<Schema>`

Same as `validateAt` but synchronous.

#### `Schema.isValid(value: any, options?: object): Promise<boolean>`

Returns `true` when the passed in value matches the schema. `isValid`
is **asynchronous** and returns a Promise object.

Takes the same options as `validate()`.

#### `Schema.isValidSync(value: any, options?: object): boolean`

Synchronously returns `true` when the passed in value matches the schema.

Takes the same options as `validateSync()` and has the same caveats around async tests.

#### `Schema.cast(value: any, options = {}): InferType<Schema>`

Attempts to coerce the passed in value to a value that matches the schema. For example: `'5'` will
cast to `5` when using the `number()` type. Failed casts generally return `null`, but may also
return results like `NaN` and unexpected strings.

Provide `options` to more specifically control the behavior of `validate`.

```js
interface CastOptions<TContext extends {}> {
  // Remove undefined properties from objects
  stripUnknown: boolean = false;

  // Throws a TypeError if casting doesn't produce a valid type
  // note that the TS return type is inaccurate when this is `false`, use with caution
  assert?: boolean = true;

  // External values that used to resolve conditions and references
  context?: TContext;
}
```

#### `Schema.isType(value: any): value is InferType<Schema>`

Runs a type check against the passed in `value`. It returns true if it matches,
it does not cast the value. When `nullable()` is set `null` is considered a valid value of the type.
You should use `isType` for all Schema type checks.

#### `Schema.strict(enabled: boolean = false): Schema`

Sets the `strict` option to `true`. Strict schemas skip coercion and transformation attempts,
validating the value "as is".

#### `Schema.strip(enabled: boolean = true): Schema`

Marks a schema to be removed from an output object. Only works as a nested schema.

```js
let schema = object({
  useThis: number(),
  notThis: string().strip(),
});

schema.cast({ notThis: 'foo', useThis: 4 }); // => { useThis: 4 }
```

Schema with `strip` enabled have an inferred type of `never`, allowing them to be
removed from the overall type:

```ts
let schema = object({
  useThis: number(),
  notThis: string().strip(),
});

InferType<typeof schema>; /*
{
   useThis?: number | undefined
}
*/
```

#### `Schema.withMutation(builder: (current: Schema) => void): void`

First the legally required Rich Hickey quote:

> If a tree falls in the woods, does it make a sound?
>
> If a pure function mutates some local data in order to produce an immutable return value, is that ok?

`withMutation` allows you to mutate the schema in place, instead of the default behavior which clones before each change. Generally this isn't necessary since the vast majority of schema changes happen during the initial
declaration, and only happen once over the lifetime of the schema, so performance isn't an issue.
However certain mutations _do_ occur at cast/validation time, (such as conditional schema using [`when()`](#schemawhenkeys-string--string-builder-object--values-any-schema--schema-schema)), or
when instantiating a schema object.

```js
object()
  .shape({ key: string() })
  .withMutation((schema) => {
    return arrayOfObjectTests.forEach((test) => {
      schema.test(test);
    });
  });
```

#### `Schema.default(value: any): Schema`

Sets a default value to use when the value is `undefined`.
Defaults are created after transformations are executed, but before validations, to help ensure that safe
defaults are specified. The default value will be cloned on each use, which can incur performance penalty
for objects and arrays. To avoid this overhead you can also pass a function that returns a new default.
Note that `null` is considered a separate non-empty value.

```js
yup.string.default('nothing');

yup.object.default({ number: 5 }); // object will be cloned every time a default is needed

yup.object.default(() => ({ number: 5 })); // this is cheaper

yup.date.default(() => new Date()); // also helpful for defaults that change over time
```

#### `Schema.getDefault(options?: object): Any`

Retrieve a previously set default value. `getDefault` will resolve any conditions that may alter the default. Optionally pass `options` with `context` (for more info on `context` see `Schema.validate`).

#### `Schema.nullable(message?: string | function): Schema`

Indicates that `null` is a valid value for the schema. Without `nullable()`
`null` is treated as a different type and will fail `Schema.isType()` checks.

```ts
let schema = number().nullable();

schema.cast(null); // null

InferType<typeof schema>; // number | null
```

#### `Schema.nonNullable(message?: string | function): Schema`

The opposite of `nullable`, removes `null` from valid type values for the schema.
**Schema are non nullable by default**.

```ts
let schema = number().nonNullable();

schema.cast(null); // TypeError

InferType<typeof schema>; // number
```

#### `Schema.defined(): Schema`

Require a value for the schema. All field values apart from `undefined` meet this requirement.

```ts
let schema = string().defined();

schema.cast(undefined); // TypeError

InferType<typeof schema>; // string
```

#### `Schema.optional(): Schema`

The opposite of `defined()` allows `undefined` values for the given type.

```ts
let schema = string().optional();

schema.cast(undefined); // undefined

InferType<typeof schema>; // string | undefined
```

#### `Schema.required(message?: string | function): Schema`

Mark the schema as required, which will not allow `undefined` or `null` as a value. `required`
negates the effects of calling `optional()` and `nullable()`

> Watch out! [`string().required`](#stringrequiredmessage-string--function-schema)) works a little
> different and additionally prevents empty string values (`''`) when required.

#### `Schema.notRequired(): Schema`

Mark the schema as not required. This is a shortcut for `schema.nullable().optional()`;

#### `Schema.typeError(message: string): Schema`

Define an error message for failed type checks. The `${value}` and `${type}` interpolation can
be used in the `message` argument.

#### `Schema.oneOf(arrayOfValues: Array<any>, message?: string | function): Schema` Alias: `equals`

Only allow values from set of values. Values added are removed from any `notOneOf` values if present.
The `${values}` interpolation can be used in the `message` argument. If a ref or refs are provided,
the `${resolved}` interpolation can be used in the message argument to get the resolved values that were checked
at validation time.

Note that `undefined` does not fail this validator, even when `undefined` is not included in `arrayOfValues`.
If you don't want `undefined` to be a valid value, you can use `Schema.required`.

```js
let schema = yup.mixed().oneOf(['jimmy', 42]);

await schema.isValid(42); // => true
await schema.isValid('jimmy'); // => true
await schema.isValid(new Date()); // => false
```

#### `Schema.notOneOf(arrayOfValues: Array<any>, message?: string | function)`

Disallow values from a set of values. Values added are removed from `oneOf` values if present.
The `${values}` interpolation can be used in the `message` argument. If a ref or refs are provided,
the `${resolved}` interpolation can be used in the message argument to get the resolved values that were checked
at validation time.

```js
let schema = yup.mixed().notOneOf(['jimmy', 42]);

await schema.isValid(42); // => false
await schema.isValid(new Date()); // => true
```

#### `Schema.when(keys: string | string[], builder: object | (values: any[], schema) => Schema): Schema`

Adjust the schema based on a sibling or sibling children fields. You can provide an object
literal where the key `is` is value or a matcher function, `then` provides the true schema and/or
`otherwise` for the failure condition.

`is` conditions are strictly compared (`===`) if you want to use a different form of equality you
can provide a function like: `is: (value) => value == true`.

You can also prefix properties with `$` to specify a property that is dependent
on `context` passed in by `validate()` or `cast` instead of the input value.

`when` conditions are additive.

`then` and `otherwise` are specified functions `(schema: Schema) => Schema`.

```js
let schema = object({
  isBig: boolean(),
  count: number()
    .when('isBig', {
      is: true, // alternatively: (val) => val == true
      then: (schema) => schema.min(5),
      otherwise: (schema) => schema.min(0),
    })
    .when('$other', ([other], schema) =>
      other === 4 ? schema.max(6) : schema,
    ),
});

await schema.validate(value, { context: { other: 4 } });
```

You can also specify more than one dependent key, in which case each value will be spread as an argument.

```js
let schema = object({
  isSpecial: boolean(),
  isBig: boolean(),
  count: number().when(['isBig', 'isSpecial'], {
    is: true, // alternatively: (isBig, isSpecial) => isBig && isSpecial
    then: (schema) => schema.min(5),
    otherwise: (schema) => schema.min(0),
  }),
});

await schema.validate({
  isBig: true,
  isSpecial: true,
  count: 10,
});
```

Alternatively you can provide a function that returns a schema, called with an array of values for each provided key the current schema.

```js
let schema = yup.object({
  isBig: yup.boolean(),
  count: yup.number().when('isBig', ([isBig], schema) => {
    return isBig ? schema.min(5) : schema.min(0);
  }),
});

await schema.validate({ isBig: false, count: 4 });
```

#### `Schema.test(name: string, message: string | function | any, test: function): Schema`

Adds a test function to the validation chain. Tests are run after any object is cast.
Many types have some tests built in, but you can create custom ones easily.
In order to allow asynchronous custom validations _all_ (or no) tests are run asynchronously.
A consequence of this is that test execution order cannot be guaranteed.

All tests must provide a `name`, an error `message` and a validation function that must return
`true` when the current `value` is valid and `false` or a `ValidationError` otherwise.
To make a test async return a promise that resolves `true` or `false` or a `ValidationError`.

For the `message` argument you can provide a string which will interpolate certain values
if specified using the `${param}` syntax. By default all test messages are passed a `path` value
which is valuable in nested schemas.

The `test` function is called with the current `value`. For more advanced validations you can
use the alternate signature to provide more options (see below):

```js
let jimmySchema = string().test(
  'is-jimmy',
  '${path} is not Jimmy',
  (value, context) => value === 'jimmy',
);

// or make it async by returning a promise
let asyncJimmySchema = string()
  .label('First name')
  .test(
    'is-jimmy',
    ({ label }) => `${label} is not Jimmy`, // a message can also be a function
    async (value, testContext) =>
      (await fetch('/is-jimmy/' + value)).responseText === 'true',
  );

await schema.isValid('jimmy'); // => true
await schema.isValid('john'); // => false
```

Test functions are called with a special context value, as the second argument, that exposes some useful metadata
and functions. For non arrow functions, the test context is also set as the function `this`. Watch out, if you access
it via `this` it won't work in an arrow function.

- `testContext.path`: the string path of the current validation
- `testContext.schema`: the resolved schema object that the test is running against.
- `testContext.options`: the `options` object that validate() or isValid() was called with
- `testContext.parent`: in the case of nested schema, this is the value of the parent object
- `testContext.originalValue`: the original value that is being tested
- `testContext.createError(Object: { path: String, message: String, params: Object })`: create and return a
  validation error. Useful for dynamically setting the `path`, `params`, or more likely, the error `message`.
  If either option is omitted it will use the current path, or default message.

#### `Schema.test(options: object): Schema`

Alternative `test(..)` signature. `options` is an object containing some of the following options:

```js
Options = {
  // unique name identifying the test
  name: string;
  // test function, determines schema validity
  test: (value: any) => boolean;
  // the validation error message
  message: string;
  // values passed to message for interpolation
  params: ?object;
  // mark the test as exclusive, meaning only one test of the same name can be active at once
  exclusive: boolean = false;
}
```

In the case of mixing exclusive and non-exclusive tests the following logic is used.
If a non-exclusive test is added to a schema with an exclusive test of the same name
the exclusive test is removed and further tests of the same name will be stacked.

If an exclusive test is added to a schema with non-exclusive tests of the same name
the previous tests are removed and further tests of the same name will replace each other.

```js
let max = 64;
let schema = yup.string().test({
  name: 'max',
  exclusive: true,
  params: { max },
  message: '${path} must be less than ${max} characters',
  test: (value) => value == null || value.length <= max,
});
```

#### `Schema.transform((currentValue: any, originalValue: any, schema: Schema,  options: object) => any): Schema`

Adds a transformation to the transform chain. Transformations are central to the casting process,
default transforms for each type coerce values to the specific type (as verified by [`isType()`](#schemaistypevalue-any-value-is-infertypeschema)). transforms are run before validations and only applied when the schema is not marked as `strict` (the default). Some types have built in transformations.

Transformations are useful for arbitrarily altering how the object is cast, **however, you should take care
not to mutate the passed in value.** Transforms are run sequentially so each `value` represents the
current state of the cast, you can use the `originalValue` param if you need to work on the raw initial value.

```js
let schema = string().transform((value, originalValue) => {
  return this.isType(value) && value !== null ? value.toUpperCase() : value;
});

schema.cast('jimmy'); // => 'JIMMY'
```

Each types will handle basic coercion of values to the proper type for you, but occasionally
you may want to adjust or refine the default behavior. For example, if you wanted to use a different
date parsing strategy than the default one you could do that with a transform.

```js
module.exports = function (formats = 'MMM dd, yyyy') {
  return date().transform((value, originalValue, context) => {
    // check to see if the previous transform already parsed the date
    if (context.isType(value)) return value;

    // the default coercion failed so let's try it with Moment.js instead
    value = Moment(originalValue, formats);

    // if it's valid return the date object, otherwise return an `InvalidDate`
    return value.isValid() ? value.toDate() : new Date('');
  });
};
```

### mixed

Creates a schema that matches all types, or just the ones you configure. Inherits from [`Schema`](#Schema).
Mixed types extends `{}` by default instead of `any` or `unknown`. This is because in TypeScript `{}` means
anything that isn't `null` or `undefined` which yup treats distinctly.

```ts
import { mixed, InferType } from 'yup';

let schema = mixed().nullable();

schema.validateSync('string'); // 'string';

schema.validateSync(1); // 1;

schema.validateSync(new Date()); // Date;

InferType<typeof schema>; // {} | undefined

InferType<typeof schema.nullable().defined()>; // {} | null
```

Custom types can be implemented by passing a type `check` function. This will also
narrow the TypeScript type for the schema.

```ts
import { mixed, InferType } from 'yup';

let objectIdSchema = yup
  .mixed((input): input is ObjectId => input instanceof ObjectId)
  .transform((value: any, input, ctx) => {
    if (ctx.isType(value)) return value;
    return new ObjectId(value);
  });

await objectIdSchema.validate(ObjectId('507f1f77bcf86cd799439011')); // ObjectId("507f1f77bcf86cd799439011")

await objectIdSchema.validate('507f1f77bcf86cd799439011'); // ObjectId("507f1f77bcf86cd799439011")

InferType<typeof objectIdSchema>; // ObjectId
```

### string

Define a string schema. Inherits from [`Schema`](#Schema).

```js
let schema = yup.string();

await schema.isValid('hello'); // => true
```

By default, the `cast` logic of `string` is to call `toString` on the value if it exists.

empty values are not coerced (use `ensure()` to coerce empty values to empty strings).

Failed casts return the input value.

#### `string.required(message?: string | function): Schema`

The same as the `mixed()` schema required, **except** that empty strings are also considered 'missing' values.

#### `string.length(limit: number | Ref, message?: string | function): Schema`

Set a required length for the string value. The `${length}` interpolation can be used in the `message` argument

#### `string.min(limit: number | Ref, message?: string | function): Schema`

Set a minimum length limit for the string value. The `${min}` interpolation can be used in the `message` argument

#### `string.max(limit: number | Ref, message?: string | function): Schema`

Set a maximum length limit for the string value. The `${max}` interpolation can be used in the `message` argument

#### `string.matches(regex: Regex, message?: string | function): Schema`

Provide an arbitrary `regex` to match the value against.

```js
let schema = string().matches(/(hi|bye)/);

await schema.isValid('hi'); // => true
await schema.isValid('nope'); // => false
```

#### `string.matches(regex: Regex, options: { message: string, excludeEmptyString: bool }): Schema`

An alternate signature for `string.matches` with an options object. `excludeEmptyString`, when true,
short circuits the regex test when the value is an empty string, making it a easier to avoid
matching nothing without complicating the regex.

```js
let schema = string().matches(/(hi|bye)/, { excludeEmptyString: true });

await schema.isValid(''); // => true
```

#### `string.email(message?: string | function): Schema`

Validates the value as an email address using the same regex as defined by the HTML spec.

WATCH OUT: Validating email addresses is nearly impossible with just code. Different
clients and servers accept different things and many diverge from the various specs defining
"valid" emails. The ONLY real way to validate an email address is to send a verification email
to it and check that the user got it. With that in mind, yup picks a relatively simple regex
that does not cover all cases, but aligns with browser input validation behavior since HTML
forms are a common use case for yup.

If you have more specific needs please override the email method with your own logic or regex:

```ts
yup.addMethod(yup.string, 'email', function validateEmail(message) {
  return this.matches(myEmailRegex, {
    message,
    name: 'email',
    excludeEmptyString: true,
  });
});
```

#### `string.url(message?: string | function): Schema`

Validates the value as a valid URL via a regex.

#### `string.uuid(message?: string | function): Schema`

Validates the value as a valid UUID via a regex.

#### `string.datetime(options?: {message?: string | function, allowOffset?: boolean, precision?: number})`

Validates the value as an ISO datetime via a regex. Defaults to UTC validation; timezone offsets are not permitted (see `options.allowOffset`).

Unlike `.date()`, `datetime` will not convert the string to a `Date` object. `datetime` also provides greater customization over the required format of the datetime string than `date` does.

`options.allowOffset`: Allow a time zone offset. False requires UTC 'Z' timezone. _(default: false)_
`options.precision`: Require a certain sub-second precision on the date. _(default: null -- any (or no) sub-second precision)_

#### `string.datetime(message?: string | function)`

An alternate signature for `string.datetime` that can be used when you don't need to pass options other than `message`.

#### `string.ensure(): Schema`

Transforms `undefined` and `null` values to an empty string along with
setting the `default` to an empty string.

#### `string.trim(message?: string | function): Schema`

Transforms string values by removing leading and trailing whitespace. If
`strict()` is set it will only validate that the value is trimmed.

#### `string.lowercase(message?: string | function): Schema`

Transforms the string value to lowercase. If `strict()` is set it
will only validate that the value is lowercase.

#### `string.uppercase(message?: string | function): Schema`

Transforms the string value to uppercase. If `strict()` is set it
will only validate that the value is uppercase.

### number

Define a number schema. Inherits from [`Schema`](#Schema).

```js
let schema = yup.number();

await schema.isValid(10); // => true
```

The default `cast` logic of `number` is: [`parseFloat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat).

Failed casts return `NaN`.

#### `number.min(limit: number | Ref, message?: string | function): Schema`

Set the minimum value allowed. The `${min}` interpolation can be used in the
`message` argument.

#### `number.max(limit: number | Ref, message?: string | function): Schema`

Set the maximum value allowed. The `${max}` interpolation can be used in the
`message` argument.

#### `number.lessThan(max: number | Ref, message?: string | function): Schema`

Value must be less than `max`. The `${less}` interpolation can be used in the
`message` argument.

#### `number.moreThan(min: number | Ref, message?: string | function): Schema`

Value must be strictly greater than `min`. The `${more}` interpolation can be used in the
`message` argument.

#### `number.positive(message?: string | function): Schema`

Value must be a positive number.

#### `number.negative(message?: string | function): Schema`

Value must be a negative number.

#### `number.integer(message?: string | function): Schema`

Validates that a number is an integer.

#### `number.truncate(): Schema`

Transformation that coerces the value to an integer by stripping off the digits
to the right of the decimal point.

#### `number.round(type: 'floor' | 'ceil' | 'trunc' | 'round' = 'round'): Schema`

Adjusts the value via the specified method of `Math` (defaults to 'round').

### boolean

Define a boolean schema. Inherits from [`Schema`](#Schema).

```js
let schema = yup.boolean();

await schema.isValid(true); // => true
```

### date

Define a Date schema. By default ISO date strings will parse correctly,
for more robust parsing options see the extending schema types at the end of the readme.
Inherits from [`Schema`](#Schema).

```js
let schema = yup.date();

await schema.isValid(new Date()); // => true
```

The default `cast` logic of `date` is pass the value to the `Date` constructor, failing that, it will attempt
to parse the date as an ISO date string.

> If you would like ISO strings to not be cast to a `Date` object, use `.datetime()` instead.

Failed casts return an invalid Date.

#### `date.min(limit: Date | string | Ref, message?: string | function): Schema`

Set the minimum date allowed. When a string is provided it will attempt to cast to a date first
and use the result as the limit.

#### `date.max(limit: Date | string | Ref, message?: string | function): Schema`

Set the maximum date allowed, When a string is provided it will attempt to cast to a date first
and use the result as the limit.

### array

Define an array schema. Arrays can be typed or not, When specifying the element type, `cast` and `isValid`
will apply to the elements as well. Options passed into `isValid` are also passed to child schemas.

Inherits from [`Schema`](#Schema).

```js
let schema = yup.array().of(yup.number().min(2));

await schema.isValid([2, 3]); // => true
await schema.isValid([1, -24]); // => false

schema.cast(['2', '3']); // => [2, 3]
```

You can also pass a subtype schema to the array constructor as a convenience.

```js
array().of(yup.number());
// or
array(yup.number());
```

Arrays have no default casting behavior.

#### `array.of(type: Schema): this`

Specify the schema of array elements. `of()` is optional and when omitted the array schema will
not validate its contents.

#### `array.json(): this`

Attempt to parse input string values as JSON using [`JSON.parse`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse).

#### `array.length(length: number | Ref, message?: string | function): this`

Set a specific length requirement for the array. The `${length}` interpolation can be used in the `message` argument.

#### `array.min(limit: number | Ref, message?: string | function): this`

Set a minimum length limit for the array. The `${min}` interpolation can be used in the `message` argument.

#### `array.max(limit: number | Ref, message?: string | function): this`

Set a maximum length limit for the array. The `${max}` interpolation can be used in the `message` argument.

#### `array.ensure(): this`

Ensures that the value is an array, by setting the default to `[]` and transforming `null` and `undefined`
values to an empty array as well. Any non-empty, non-array value will be wrapped in an array.

```js
array().ensure().cast(null); // => []
array().ensure().cast(1); // => [1]
array().ensure().cast([1]); // => [1]
```

#### `array.compact(rejector: (value) => boolean): Schema`

Removes falsey values from the array. Providing a rejecter function lets you specify the rejection criteria yourself.

```js
array().compact().cast(['', 1, 0, 4, false, null]); // => [1, 4]

array()
  .compact(function (v) {
    return v == null;
  })
  .cast(['', 1, 0, 4, false, null]); // => ['', 1, 0, 4, false]
```

### tuple

Tuples, are fixed length arrays where each item has a distinct type.

Inherits from [`Schema`](#Schema).

```js
import { tuple, string, number, InferType } from 'yup';

let schema = tuple([
  string().label('name'),
  number().label('age').positive().integer(),
]);

await schema.validate(['James', 3]); // ['James', 3]

await schema.validate(['James', -24]); // => ValidationError: age must be a positive number

InferType<typeof schema> // [string, number] | undefined
```

tuples have no default casting behavior.

### object

Define an object schema. Options passed into `isValid` are also passed to child schemas.
Inherits from [`Schema`](#Schema).

```js
yup.object({
  name: string().required(),
  age: number().required().positive().integer(),
  email: string().email(),
  website: string().url(),
});
```

object schema do not have any default transforms applied.

#### Object schema defaults

Object schema come with a default value already set, which "builds" out the object shape, a
sets any defaults for fields:

```js
let schema = object({
  name: string().default(''),
});

schema.default(); // -> { name: '' }
```

This may be a bit surprising, but is usually helpful since it allows large, nested
schema to create default values that fill out the whole shape and not just the root object. There is
one gotcha! though. For nested object schema that are optional but include non optional fields
may fail in unexpected ways:

```js
let schema = object({
  id: string().required(),
  names: object({
    first: string().required(),
  }),
});

schema.isValid({ id: 1 }); // false! names.first is required
```

This is because yup casts the input object before running validation
which will produce:

> `{ id: '1', names: { first: undefined }}`

During the validation phase `names` exists, and is validated, finding `names.first` missing.
If you wish to avoid this behavior do one of the following:

- Set the nested default to undefined: `names.default(undefined)`
- mark it nullable and default to null: `names.nullable().default(null)`

#### `object.shape(fields: object, noSortEdges?: Array<[string, string]>): Schema`

Define the keys of the object and the schemas for said keys.

Note that you can chain `shape` method, which acts like `Object.assign`.

```ts
object({
  a: string(),
  b: number(),
}).shape({
  b: string(),
  c: number(),
});
```

would be exactly the same as:

```ts
object({
  a: string(),
  b: string(),
  c: number(),
});
```

#### `object.json(): this`

Attempt to parse input string values as JSON using [`JSON.parse`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse).

#### `object.concat(schemaB: ObjectSchema): ObjectSchema`

Creates a object schema, by applying all settings and fields from `schemaB` to the base, producing a new schema.
The object shape is shallowly merged with common fields from `schemaB` taking precedence over the base
fields.

#### `object.pick(keys: string[]): Schema`

Create a new schema from a subset of the original's fields.

```js
let person = object({
  age: number().default(30).required(),
  name: string().default('pat').required(),
  color: string().default('red').required(),
});

let nameAndAge = person.pick(['name', 'age']);
nameAndAge.getDefault(); // => { age: 30, name: 'pat'}
```

#### `object.omit(keys: string[]): Schema`

Create a new schema with fields omitted.

```js
let person = object({
  age: number().default(30).required(),
  name: string().default('pat').required(),
  color: string().default('red').required(),
});

let nameAndAge = person.omit(['color']);
nameAndAge.getDefault(); // => { age: 30, name: 'pat'}
```

#### `object.from(fromKey: string, toKey: string, alias: boolean = false): this`

Transforms the specified key to a new key. If `alias` is `true` then the old key will be left.

```js
let schema = object({
  myProp: mixed(),
  Other: mixed(),
})
  .from('prop', 'myProp')
  .from('other', 'Other', true);

schema.cast({ prop: 5, other: 6 }); // => { myProp: 5, other: 6, Other: 6 }
```

#### `object.exact(message?: string | function): Schema`

Validates that the object does not contain extra or unknown properties

#### `object.stripUnknown(): Schema`

The same as `object().validate(value, { stripUnknown: true})`, but as a transform method. When set
any unknown properties will be removed.

#### `object.noUnknown(onlyKnownKeys: boolean = true, message?: string | function): Schema`

Validate that the object value only contains keys specified in `shape`, pass `false` as the first
argument to disable the check. Restricting keys to known, also enables `stripUnknown` option, when not in strict mode.

> Watch Out!: this method performs a transform and a validation, which may produce unexpected results.
> For more explicit behavior use `object().stripUnknown` and `object().exact()`

#### `object.camelCase(): Schema`

Transforms all object keys to camelCase

#### `object.constantCase(): Schema`

Transforms all object keys to CONSTANT_CASE.


================================================
FILE: docs/extending.md
================================================
# Extending Schema

For simple cases where you want to reuse common schema configurations, creating
and passing around instances works great and is automatically typed correctly

```js
import * as yup from 'yup';

const requiredString = yup.string().required().default('');

const momentDate = (parseFormats = ['MMM dd, yyy']) =>
  yup.date().transform((value, originalValue, schema) => {
    if (schema.isType(value)) return value;

    // the default coercion transform failed so let's try it with Moment instead
    value = Moment(originalValue, parseFormats);
    return value.isValid() ? value.toDate() : yup.date.INVALID_DATE;
  });

export { momentDate, requiredString };
```

Schema are immutable so each can be configured further without changing the original.

## Extending Schema with new methods

`yup` provides a `addMethod()` utility for extending built-in schema:

```js
function parseDateFromFormats(formats, parseStrict) {
  return this.transform((value, originalValue, schema) => {
    if (schema.isType(value)) return value;

    value = Moment(originalValue, formats, parseStrict);

    return value.isValid() ? value.toDate() : yup.date.INVALID_DATE;
  });
}

yup.addMethod(yup.date, 'format', parseDateFromFormats);
```

Note that `addMethod` isn't magic, it mutates the prototype of the passed in schema.

> Note: if you are using TypeScript you also need to adjust the class or interface
> see the [typescript](./typescript.md) docs for details.

## Creating new Schema types

If you're using case calls for creating an entirely new type, inheriting from
an existing schema class may be best: Generally you should not be inheriting from
the abstract `Schema` unless you know what you are doing. The other types are fair game though.

You should keep in mind some basic guidelines when extending schemas:

- never mutate an existing schema, always `clone()` and then mutate the new one before returning it.
  Built-in methods like `test` and `transform` take care of this for you, so you can safely use them (see below) without worrying

- transforms should never mutate the `value` passed in, and should return an invalid object when one exists
  (`NaN`, `InvalidDate`, etc) instead of `null` for bad values.

- by the time validations run, the `value` is guaranteed to be the correct type, however it still may
  be `null` or `undefined`

```js
import { DateSchema } from 'yup';

class MomentDateSchema extends DateSchema {
  static create() {
    return MomentDateSchema();
  }

  constructor() {
    super();
    this._validFormats = [];

    this.withMutation(() => {
      this.transform(function (value, originalValue) {
        if (this.isType(value))
          // we have a valid value
          return value;
        return Moment(originalValue, this._validFormats, true);
      });
    });
  }

  _typeCheck(value) {
    return (
      super._typeCheck(value) || (moment.isMoment(value) && value.isValid())
    );
  }

  format(formats) {
    if (!formats) throw new Error('must enter a valid format');
    let next = this.clone();
    next._validFormats = {}.concat(formats);
  }
}

let schema = new MomentDateSchema();

schema.format('YYYY-MM-DD').cast('It is 2012-05-25'); // => Fri May 25 2012 00:00:00 GMT-0400 (Eastern Daylight Time)
```


================================================
FILE: package.json
================================================
{
  "name": "yup",
  "version": "1.7.1",
  "description": "Dead simple Object schema validation",
  "main": "lib/index.js",
  "module": "lib/index.esm.js",
  "runkitExampleFilename": "./runkit-example.js",
  "scripts": {
    "test": "yarn lint && yarn testonly",
    "testonly": "vitest run",
    "test-sync": "vitest run --project sync",
    "tdd": "vitest --project async",
    "lint": "eslint src test",
    "precommit": "lint-staged",
    "toc": "doctoc README.md --github",
    "release": "rollout",
    "build:dts": "yarn tsc --emitDeclarationOnly -p . --outDir dts",
    "build": "rm -rf dts && yarn build:dts && yarn rollup -c rollup.config.js  && yarn toc",
    "prepublishOnly": "yarn build"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/jquense/yup.git"
  },
  "author": {
    "name": "@monasticpanic Jason Quense"
  },
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/jquense/yup/issues"
  },
  "homepage": "https://github.com/jquense/yup",
  "release": {
    "conventionalCommits": true,
    "publishDir": "lib"
  },
  "prettier": {
    "singleQuote": true,
    "trailingComma": "all"
  },
  "lint-staged": {
    "*.{js,json,css,md}": [
      "prettier --write",
      "git add"
    ]
  },
  "devDependencies": {
    "@4c/cli": "^4.0.4",
    "@4c/rollout": "patch:@4c/rollout@npm%3A4.0.2#~/.yarn/patches/@4c-rollout-npm-4.0.2-ab2b6d0bab.patch",
    "@4c/tsconfig": "^0.4.1",
    "@babel/cli": "^7.28.3",
    "@babel/core": "^7.28.4",
    "@babel/preset-typescript": "^7.27.1",
    "@rollup/plugin-babel": "^5.3.1",
    "@rollup/plugin-node-resolve": "^13.3.0",
    "@standard-schema/spec": "^1.0.0",
    "@typescript-eslint/eslint-plugin": "^5.62.0",
    "@typescript-eslint/parser": "^5.62.0",
    "babel-jest": "^27.5.1",
    "babel-preset-env-modules": "^1.0.1",
    "doctoc": "^2.2.1",
    "dts-bundle-generator": "^6.13.0",
    "eslint": "^8.57.1",
    "eslint-config-jason": "^8.2.2",
    "eslint-config-prettier": "^8.10.2",
    "eslint-plugin-import": "^2.32.0",
    "eslint-plugin-jest": "^25.7.0",
    "eslint-plugin-react": "^7.37.5",
    "eslint-plugin-react-hooks": "^4.6.2",
    "eslint-plugin-ts-expect": "^2.1.0",
    "eslint-plugin-typescript": "^0.14.0",
    "hookem": "^2.0.1",
    "lint-staged": "^13.3.0",
    "prettier": "^2.8.8",
    "rollup": "^2.79.2",
    "rollup-plugin-babel": "^4.4.0",
    "rollup-plugin-dts": "^4.2.3",
    "rollup-plugin-filesize": "^9.1.2",
    "rollup-plugin-node-resolve": "^5.2.0",
    "synchronous-promise": "^2.0.17",
    "typescript": "^4.9.5",
    "vitest": "^3.2.4"
  },
  "dependencies": {
    "property-expr": "^2.0.5",
    "tiny-case": "^1.0.3",
    "toposort": "^2.0.2",
    "type-fest": "^2.19.0"
  },
  "packageManager": "yarn@4.10.0+sha512.8dd111dbb1658cf17089636e5bf490795958158755f36cb75c5a2db0bda6be4d84b95447753627f3330d1457cb6f7e8c1e466eaed959073c82be0242c2cd41e7",
  "resolutions": {
    "@4c/rollout@npm:^4.0.2": "patch:@4c/rollout@npm%3A4.0.2#~/.yarn/patches/@4c-rollout-npm-4.0.2-ab2b6d0bab.patch"
  }
}


================================================
FILE: renovate.json
================================================
{
  "extends": ["github>4Catalyzer/renovate-config:library", ":automergeMinor"]
}


================================================
FILE: rollup.config.js
================================================
import nodeResolve from '@rollup/plugin-node-resolve';
import babel from '@rollup/plugin-babel';
import dts from 'rollup-plugin-dts';
import filesize from 'rollup-plugin-filesize';

const base = {
  input: './src/index.ts',
  plugins: [
    nodeResolve({ extensions: ['.js', '.ts'] }),
    babel({
      babelrc: true,
      envName: 'esm',
      extensions: ['.js', '.ts'],
    }),
  ],
  external: ['tiny-case', 'toposort', 'fn-name', 'property-expr'],
};

module.exports = [
  {
    input: './dts/index.d.ts',
    output: [{ file: 'lib/index.d.ts', format: 'es' }],
    plugins: [dts()],
  },
  {
    ...base,
    output: [
      {
        file: 'lib/index.js',
        format: 'cjs',
      },
      {
        file: 'lib/index.esm.js',
        format: 'es',
      },
    ],
    plugins: [...base.plugins, filesize()],
  },
];


================================================
FILE: src/Condition.ts
================================================
import isSchema from './util/isSchema';
import Reference from './Reference';
import type { ISchema } from './types';

export type ConditionBuilder<T extends ISchema<any, any>> = (
  values: any[],
  schema: T,
  options: ResolveOptions,
) => ISchema<any>;

export type ConditionConfig<T extends ISchema<any>> = {
  is: any | ((...values: any[]) => boolean);
  then?: (schema: T) => ISchema<any>;
  otherwise?: (schema: T) => ISchema<any>;
};

export type ResolveOptions<TContext = any> = {
  value?: any;
  parent?: any;
  context?: TContext;
};

class Condition<TIn extends ISchema<any, any> = ISchema<any, any>> {
  fn: ConditionBuilder<TIn>;

  static fromOptions<TIn extends ISchema<any, any>>(
    refs: Reference[],
    config: ConditionConfig<TIn>,
  ) {
    if (!config.then && !config.otherwise)
      throw new TypeError(
        'either `then:` or `otherwise:` is required for `when()` conditions',
      );

    let { is, then, otherwise } = config;

    let check =
      typeof is === 'function'
        ? is
        : (...values: any[]) => values.every((value) => value === is);

    return new Condition<TIn>(refs, (values, schema: any) => {
      let branch = check(...values) ? then : otherwise;

      return branch?.(schema) ?? schema;
    });
  }

  constructor(
    public refs: readonly Reference[],
    builder: ConditionBuilder<TIn>,
  ) {
    this.refs = refs;
    this.fn = builder;
  }

  resolve(base: TIn, options: ResolveOptions) {
    let values = this.refs.map((ref) =>
      // TODO: ? operator here?
      ref.getValue(options?.value, options?.parent, options?.context),
    );

    let schema = this.fn(values, base, options);

    if (
      schema === undefined ||
      // @ts-ignore this can be base
      schema === base
    ) {
      return base;
    }

    if (!isSchema(schema))
      throw new TypeError('conditions must return a schema object');

    return schema.resolve(options);
  }
}

export default Condition;


================================================
FILE: src/Lazy.ts
================================================
import isSchema from './util/isSchema';
import type {
  AnyObject,
  ISchema,
  ValidateOptions,
  NestedTestConfig,
  InferType,
} from './types';
import type { ResolveOptions } from './Condition';

import type {
  CastOptionalityOptions,
  CastOptions,
  SchemaFieldDescription,
  SchemaLazyDescription,
} from './schema';
import { Flags, Maybe, ResolveFlags } from './util/types';
import ValidationError from './ValidationError';
import Schema from './schema';
import {
  issuesFromValidationError,
  StandardResult,
  StandardSchemaProps,
} from './standardSchema';

export type LazyBuilder<
  TSchema extends ISchema<TContext>,
  TContext = AnyObject,
> = (value: any, options: ResolveOptions) => TSchema;

export function create<
  TSchema extends ISchema<any, TContext>,
  TContext extends Maybe<AnyObject> = AnyObject,
>(builder: (value: any, options: ResolveOptions<TContext>) => TSchema) {
  return new Lazy<InferType<TSchema>, TContext>(builder);
}

function catchValidationError(fn: () => any) {
  try {
    return fn();
  } catch (err) {
    if (ValidationError.isError(err)) return Promise.reject(err);
    throw err;
  }
}

export interface LazySpec {
  meta: Record<string, unknown> | undefined;
  optional: boolean;
}

class Lazy<T, TContext = AnyObject, TFlags extends Flags = any>
  implements ISchema<T, TContext, TFlags, undefined>
{
  type = 'lazy' as const;

  __isYupSchema__ = true;

  declare readonly __outputType: T;
  declare readonly __context: TContext;
  declare readonly __flags: TFlags;
  declare readonly __default: undefined;

  spec: LazySpec;

  constructor(private builder: any) {
    this.spec = { meta: undefined, optional: false };
  }

  clone(spec?: Partial<LazySpec>): Lazy<T, TContext, TFlags> {
    const next = new Lazy<T, TContext, TFlags>(this.builder);
    next.spec = { ...this.spec, ...spec };
    return next;
  }

  private _resolve = (
    value: any,
    options: ResolveOptions<TContext> = {},
  ): Schema<T, TContext, undefined, TFlags> => {
    let schema = this.builder(value, options) as Schema<
      T,
      TContext,
      undefined,
      TFlags
    >;

    if (!isSchema(schema))
      throw new TypeError('lazy() functions must return a valid schema');

    if (this.spec.optional) schema = schema.optional();

    return schema.resolve(options);
  };

  private optionality(optional: boolean) {
    const next = this.clone({ optional });
    return next;
  }

  optional(): Lazy<T | undefined, TContext, TFlags> {
    return this.optionality(true);
  }

  resolve(options: ResolveOptions<TContext>) {
    return this._resolve(options.value, options);
  }

  cast(value: any, options?: CastOptions<TContext>): T;
  cast(
    value: any,
    options?: CastOptionalityOptions<TContext>,
  ): T | null | undefined;
  cast(
    value: any,
    options?: CastOptions<TContext> | CastOptionalityOptions<TContext>,
  ): any {
    return this._resolve(value, options).cast(value, options as any);
  }

  asNestedTest(config: NestedTestConfig) {
    let { key, index, parent, options } = config;
    let value = parent[index ?? key!];

    return this._resolve(value, {
      ...options,
      value,
      parent,
    }).asNestedTest(config);
  }

  validate(value: any, options?: ValidateOptions<TContext>): Promise<T> {
    return catchValidationError(() =>
      this._resolve(value, options).validate(value, options),
    );
  }

  validateSync(value: any, options?: ValidateOptions<TContext>): T {
    return this._resolve(value, options).validateSync(value, options);
  }

  validateAt(path: string, value: any, options?: ValidateOptions<TContext>) {
    return catchValidationError(() =>
      this._resolve(value, options).validateAt(path, value, options),
    );
  }

  validateSyncAt(
    path: string,
    value: any,
    options?: ValidateOptions<TContext>,
  ) {
    return this._resolve(value, options).validateSyncAt(path, value, options);
  }

  isValid(value: any, options?: ValidateOptions<TContext>) {
    try {
      return this._resolve(value, options).isValid(value, options);
    } catch (err) {
      if (ValidationError.isError(err)) {
        return Promise.resolve(false);
      }
      throw err;
    }
  }

  isValidSync(value: any, options?: ValidateOptions<TContext>) {
    return this._resolve(value, options).isValidSync(value, options);
  }

  describe(
    options?: ResolveOptions<TContext>,
  ): SchemaLazyDescription | SchemaFieldDescription {
    return options
      ? this.resolve(options).describe(options)
      : { type: 'lazy', meta: this.spec.meta, label: undefined };
  }

  meta(): Record<string, unknown> | undefined;
  meta(obj: Record<string, unknown>): Lazy<T, TContext, TFlags>;
  meta(...args: [Record<string, unknown>?]) {
    if (args.length === 0) return this.spec.meta;

    let next = this.clone();
    next.spec.meta = Object.assign(next.spec.meta || {}, args[0]);
    return next;
  }

  get ['~standard']() {
    const schema = this;

    const standard: StandardSchemaProps<
      T,
      ResolveFlags<T, TFlags, undefined>
    > = {
      version: 1,
      vendor: 'yup',
      async validate(
        value: unknown,
      ): Promise<StandardResult<ResolveFlags<T, TFlags, undefined>>> {
        try {
          const result = await schema.validate(value, {
            abortEarly: false,
          });

          return {
            value: result as ResolveFlags<T, TFlags, undefined>,
          };
        } catch (err) {
          if (ValidationError.isError(err)) {
            return {
              issues: issuesFromValidationError(err),
            };
          }

          throw err;
        }
      },
    };

    return standard;
  }
}

export default Lazy;


================================================
FILE: src/Reference.ts
================================================
import { getter } from 'property-expr';
import type { SchemaRefDescription } from './schema';

const prefixes = {
  context: '$',
  value: '.',
} as const;

export type ReferenceOptions<TValue = unknown> = {
  map?: (value: unknown) => TValue;
};

export function create<TValue = unknown>(
  key: string,
  options?: ReferenceOptions<TValue>,
) {
  return new Reference<TValue>(key, options);
}

export default class Reference<TValue = unknown> {
  readonly key: string;
  readonly isContext: boolean;
  readonly isValue: boolean;
  readonly isSibling: boolean;
  readonly path: any;

  readonly getter: (data: unknown) => unknown;
  readonly map?: (value: unknown) => TValue;

  declare readonly __isYupRef: boolean;

  constructor(key: string, options: ReferenceOptions<TValue> = {}) {
    if (typeof key !== 'string')
      throw new TypeError('ref must be a string, got: ' + key);

    this.key = key.trim();

    if (key === '') throw new TypeError('ref must be a non-empty string');

    this.isContext = this.key[0] === prefixes.context;
    this.isValue = this.key[0] === prefixes.value;
    this.isSibling = !this.isContext && !this.isValue;

    let prefix = this.isContext
      ? prefixes.context
      : this.isValue
      ? prefixes.value
      : '';

    this.path = this.key.slice(prefix.length);
    this.getter = this.path && getter(this.path, true);
    this.map = options.map;
  }

  getValue(value: any, parent?: {}, context?: {}): TValue {
    let result = this.isContext ? context : this.isValue ? value : parent;

    if (this.getter) result = this.getter(result || {});

    if (this.map) result = this.map(result);

    return result;
  }

  /**
   *
   * @param {*} value
   * @param {Object} options
   * @param {Object=} options.context
   * @param {Object=} options.parent
   */
  cast(value: any, options?: { parent?: {}; context?: {} }) {
    return this.getValue(value, options?.parent, options?.context);
  }

  resolve() {
    return this;
  }

  describe(): SchemaRefDescription {
    return {
      type: 'ref',
      key: this.key,
    };
  }

  toString() {
    return `Ref(${this.key})`;
  }

  static isRef(value: any): value is Reference {
    return value && value.__isYupRef;
  }
}

// @ts-ignore
Reference.prototype.__isYupRef = true;


================================================
FILE: src/ValidationError.ts
================================================
import printValue from './util/printValue';
import toArray from './util/toArray';

let strReg = /\$\{\s*(\w+)\s*\}/g;

type Params = Record<string, unknown>;

class ValidationErrorNoStack implements ValidationError {
  name: string;
  message: string;

  value: any;
  path?: string;
  type?: string;
  params?: Params;

  errors: string[];
  inner: ValidationError[];

  constructor(
    errorOrErrors: string | ValidationError | readonly ValidationError[],
    value?: any,
    field?: string,
    type?: string,
  ) {
    this.name = 'ValidationError';
    this.value = value;
    this.path = field;
    this.type = type;

    this.errors = [];
    this.inner = [];

    toArray(errorOrErrors).forEach((err) => {
      if (ValidationError.isError(err)) {
        this.errors.push(...err.errors);
        const innerErrors = err.inner.length ? err.inner : [err];
        this.inner.push(...innerErrors);
      } else {
        this.errors.push(err);
      }
    });

    this.message =
      this.errors.length > 1
        ? `${this.errors.length} errors occurred`
        : this.errors[0];
  }

  [Symbol.toStringTag] = 'Error';
}

export default class ValidationError extends Error {
  value: any;
  path?: string;
  type?: string;
  params?: Params;

  errors: string[] = [];
  inner: ValidationError[] = [];

  static formatError(
    message: string | ((params: Params) => string) | unknown,
    params: Params,
  ) {
    // Attempt to make the path more friendly for error message interpolation.
    const path = params.label || params.path || 'this';
    // Store the original path under `originalPath` so it isn't lost to custom
    // message functions; e.g., ones provided in `setLocale()` calls.
    params = { ...params, path, originalPath: params.path };

    if (typeof message === 'string')
      return message.replace(strReg, (_, key) => printValue(params[key]));
    if (typeof message === 'function') return message(params);

    return message;
  }

  static isError(err: any): err is ValidationError {
    return err && err.name === 'ValidationError';
  }

  constructor(
    errorOrErrors: string | ValidationError | readonly ValidationError[],
    value?: any,
    field?: string,
    type?: string,
    disableStack?: boolean,
  ) {
    const errorNoStack = new ValidationErrorNoStack(
      errorOrErrors,
      value,
      field,
      type,
    );

    if (disableStack) {
      return errorNoStack;
    }

    super();

    this.name = errorNoStack.name;
    this.message = errorNoStack.message;
    this.type = errorNoStack.type;
    this.value = errorNoStack.value;
    this.path = errorNoStack.path;
    this.errors = errorNoStack.errors;
    this.inner = errorNoStack.inner;

    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, ValidationError);
    }
  }

  static [Symbol.hasInstance](inst: any) {
    return (
      ValidationErrorNoStack[Symbol.hasInstance](inst) ||
      super[Symbol.hasInstance](inst)
    );
  }

  [Symbol.toStringTag] = 'Error';
}


================================================
FILE: src/array.ts
================================================
import isSchema from './util/isSchema';
import printValue from './util/printValue';
import parseJson from './util/parseJson';
import { array as locale } from './locale';
import type {
  AnyObject,
  InternalOptions,
  Message,
  ISchema,
  DefaultThunk,
} from './types';
import type Reference from './Reference';
import type {
  Defined,
  Flags,
  NotNull,
  SetFlag,
  Maybe,
  Optionals,
  ToggleDefault,
  UnsetFlag,
  Concat,
} from './util/types';
import Schema, {
  RunTest,
  SchemaInnerTypeDescription,
  SchemaSpec,
} from './schema';
import type { ResolveOptions } from './Condition';
import type ValidationError from './ValidationError';

type InnerType<T> = T extends Array<infer I> ? I : never;

export type RejectorFn = (
  value: any,
  index: number,
  array: readonly any[],
) => boolean;

export function create<C extends Maybe<AnyObject> = AnyObject, T = any>(
  type?: ISchema<T, C>,
) {
  return new ArraySchema<T[] | undefined, C>(type as any);
}

interface ArraySchemaSpec<TIn, TContext> extends SchemaSpec<any> {
  types?: ISchema<InnerType<TIn>, TContext>;
}

export default class ArraySchema<
  TIn extends any[] | null | undefined,
  TContext,
  TDefault = undefined,
  TFlags extends Flags = '',
> extends Schema<TIn, TContext, TDefault, TFlags> {
  declare spec: ArraySchemaSpec<TIn, TContext>;
  readonly innerType?: ISchema<InnerType<TIn>, TContext>;

  constructor(type?: ISchema<InnerType<TIn>, TContext>) {
    super({
      type: 'array',
      spec: { types: type } as ArraySchemaSpec<TIn, TContext>,
      check(v: any): v is NonNullable<TIn> {
        return Array.isArray(v);
      },
    });

    // `undefined` specifically means uninitialized, as opposed to "no subtype"
    this.innerType = type;
  }

  protected _cast(_value: any, _opts: InternalOptions<TContext>) {
    const value = super._cast(_value, _opts);

    // should ignore nulls here
    if (!this._typeCheck(value) || !this.innerType) {
      return value;
    }

    let isChanged = false;
    const castArray = value.map((v, idx) => {
      const castElement = this.innerType!.cast(v, {
        ..._opts,
        path: `${_opts.path || ''}[${idx}]`,
        parent: value,
        originalValue: v,
        value: v,
        index: idx,

      });
      
      if (castElement !== v) {
        isChanged = true;
      }

      return castElement;
    });

    return isChanged ? castArray : value;
  }

  protected _validate(
    _value: any,
    options: InternalOptions<TContext> = {},

    panic: (err: Error, value: unknown) => void,
    next: (err: ValidationError[], value: unknown) => void,
  ) {
    // let sync = options.sync;
    // let path = options.path;
    let innerType = this.innerType;
    // let endEarly = options.abortEarly ?? this.spec.abortEarly;
    let recursive = options.recursive ?? this.spec.recursive;

    let originalValue =
      options.originalValue != null ? options.originalValue : _value;

    super._validate(_value, options, panic, (arrayErrors, value) => {
      if (!recursive || !innerType || !this._typeCheck(value)) {
        next(arrayErrors, value);
        return;
      }

      originalValue = originalValue || value;

      // #950 Ensure that sparse array empty slots are validated
      let tests: RunTest[] = new Array(value.length);
      for (let index = 0; index < value.length; index++) {
        tests[index] = innerType!.asNestedTest({
          options,
          index,
          parent: value,
          parentPath: options.path,
          originalParent: options.originalValue ?? _value,
        });
      }

      this.runTests(
        {
          value,
          tests,
          originalValue: options.originalValue ?? _value,
          options,
        },
        panic,
        (innerTypeErrors) => next(innerTypeErrors.concat(arrayErrors), value),
      );
    });
  }

  clone(spec?: SchemaSpec<any>) {
    const next = super.clone(spec);
    // @ts-expect-error readonly
    next.innerType = this.innerType;
    return next;
  }

  /** Parse an input JSON string to an object */
  json() {
    return this.transform(parseJson);
  }

  concat<IIn extends Maybe<any[]>, IC, ID, IF extends Flags>(
    schema: ArraySchema<IIn, IC, ID, IF>,
  ): ArraySchema<
    Concat<TIn, IIn>,
    TContext & IC,
    Extract<IF, 'd'> extends never ? TDefault : ID,
    TFlags | IF
  >;
  concat(schema: this): this;
  concat(schema: any): any {
    let next = super.concat(schema) as this;

    // @ts-expect-error readonly
    next.innerType = this.innerType;

    if (schema.innerType)
      // @ts-expect-error readonly
      next.innerType = next.innerType
        ? // @ts-expect-error Lazy doesn't have concat and will break
          next.innerType.concat(schema.innerType)
        : schema.innerType;

    return next;
  }

  of<U>(
    schema: ISchema<U, TContext>,
  ): ArraySchema<U[] | Optionals<TIn>, TContext, TFlags> {
    // FIXME: this should return a new instance of array without the default to be
    let next = this.clone();

    if (!isSchema(schema))
      throw new TypeError(
        '`array.of()` sub-schema must be a valid yup schema not: ' +
          printValue(schema),
      );

    // @ts-expect-error readonly
    next.innerType = schema;

    next.spec = {
      ...next.spec,
      types: schema as ISchema<InnerType<TIn>, TContext>,
    };

    return next as any;
  }

  length(
    length: number | Reference<number>,
    message: Message<{ length: number }> = locale.length,
  ) {
    return this.test({
      message,
      name: 'length',
      exclusive: true,
      params: { length },
      skipAbsent: true,
      test(value) {
        return value!.length === this.resolve(length);
      },
    });
  }

  min(min: number | Reference<number>, message?: Message<{ min: number }>) {
    message = message || locale.min;

    return this.test({
      message,
      name: 'min',
      exclusive: true,
      params: { min },
      skipAbsent: true,
      // FIXME(ts): Array<typeof T>
      test(value) {
        return value!.length >= this.resolve(min);
      },
    });
  }

  max(max: number | Reference<number>, message?: Message<{ max: number }>) {
    message = message || locale.max;
    return this.test({
      message,
      name: 'max',
      exclusive: true,
      params: { max },
      skipAbsent: true,
      test(value) {
        return value!.length <= this.resolve(max);
      },
    });
  }

  ensure() {
    return this.default<TIn>(() => [] as any).transform(
      (val: TIn, original: any) => {
        // We don't want to return `null` for nullable schema
        if (this._typeCheck(val)) return val;
        return original == null ? [] : [].concat(original);
      },
    );
  }

  compact(rejector?: RejectorFn) {
    let reject: RejectorFn = !rejector
      ? (v) => !!v
      : (v, i, a) => !rejector(v, i, a);

    return this.transform((values: readonly any[]) =>
      values != null ? values.filter(reject) : values,
    );
  }

  describe(options?: ResolveOptions<TContext>) {
    const next = (options ? this.resolve(options) : this).clone();
    const base = super.describe(options) as SchemaInnerTypeDescription;
    if (next.innerType) {
      let innerOptions = options;
      if (innerOptions?.value) {
        innerOptions = {
          ...innerOptions,
          parent: innerOptions.value,
          value: innerOptions.value[0],
        };
      }
      base.innerType = next.innerType.describe(innerOptions);
    }
    return base;
  }
}

create.prototype = ArraySchema.prototype;

export default interface ArraySchema<
  TIn extends any[] | null | undefined,
  TContext,
  TDefault = undefined,
  TFlags extends Flags = '',
> extends Schema<TIn, TContext, TDefault, TFlags> {
  default<D extends Maybe<TIn>>(
    def: DefaultThunk<D, TContext>,
  ): ArraySchema<TIn, TContext, D, ToggleDefault<TFlags, D>>;

  defined(msg?: Message): ArraySchema<Defined<TIn>, TContext, TDefault, TFlags>;
  optional(): ArraySchema<TIn | undefined, TContext, TDefault, TFlags>;

  required(
    msg?: Message,
  ): ArraySchema<NonNullable<TIn>, TContext, TDefault, TFlags>;
  notRequired(): ArraySchema<Maybe<TIn>, TContext, TDefault, TFlags>;

  nullable(msg?: Message): ArraySchema<TIn | null, TContext, TDefault, TFlags>;
  nonNullable(
    msg?: Message,
  ): ArraySchema<NotNull<TIn>, TContext, TDefault, TFlags>;

  strip(
    enabled: false,
  ): ArraySchema<TIn, TContext, TDefault, UnsetFlag<TFlags, 's'>>;
  strip(
    enabled?: true,
  ): ArraySchema<TIn, TContext, TDefault, SetFlag<TFlags, 's'>>;
}


================================================
FILE: src/boolean.ts
================================================
import Schema from './schema';
import type { AnyObject, DefaultThunk, Message } from './types';
import type {
  Defined,
  Flags,
  NotNull,
  SetFlag,
  ToggleDefault,
  UnsetFlag,
  Maybe,
  Optionals,
} from './util/types';
import { boolean as locale } from './locale';
import isAbsent from './util/isAbsent';

export function create(): BooleanSchema;
export function create<
  T extends boolean,
  TContext extends Maybe<AnyObject> = AnyObject,
>(): BooleanSchema<T | undefined, TContext>;
export function create() {
  return new BooleanSchema();
}

export default class BooleanSchema<
  TType extends Maybe<boolean> = boolean | undefined,
  TContext = AnyObject,
  TDefault = undefined,
  TFlags extends Flags = '',
> extends Schema<TType, TContext, TDefault, TFlags> {
  constructor() {
    super({
      type: 'boolean',
      check(v: any): v is NonNullable<TType> {
        if (v instanceof Boolean) v = v.valueOf();

        return typeof v === 'boolean';
      },
    });

    this.withMutation(() => {
      this.transform((value, _raw) => {
        if (this.spec.coerce && !this.isType(value)) {
          if (/^(true|1)$/i.test(String(value))) return true;
          if (/^(false|0)$/i.test(String(value))) return false;
        }
        return value;
      });
    });
  }

  isTrue(
    message = locale.isValue,
  ): BooleanSchema<true | Optionals<TType>, TContext, TFlags> {
    return this.test({
      message,
      name: 'is-value',
      exclusive: true,
      params: { value: 'true' },
      test(value) {
        return isAbsent(value) || value === true;
      },
    }) as any;
  }

  isFalse(
    message = locale.isValue,
  ): BooleanSchema<false | Optionals<TType>, TContext, TFlags> {
    return this.test({
      message,
      name: 'is-value',
      exclusive: true,
      params: { value: 'false' },
      test(value) {
        return isAbsent(value) || value === false;
      },
    }) as any;
  }

  override default<D extends Maybe<TType>>(
    def: DefaultThunk<D, TContext>,
  ): BooleanSchema<TType, TContext, D, ToggleDefault<TFlags, D>> {
    return super.default(def);
  }

  defined(
    msg?: Message,
  ): BooleanSchema<Defined<TType>, TContext, TDefault, TFlags> {
    return super.defined(msg);
  }
  optional(): BooleanSchema<TType | undefined, TContext, TDefault, TFlags> {
    return super.optional();
  }
  required(
    msg?: Message,
  ): BooleanSchema<NonNullable<TType>, TContext, TDefault, TFlags> {
    return super.required(msg);
  }
  notRequired(): BooleanSchema<Maybe<TType>, TContext, TDefault, TFlags> {
    return super.notRequired();
  }
  nullable(): BooleanSchema<TType | null, TContext, TDefault, TFlags> {
    return super.nullable();
  }
  nonNullable(
    msg?: Message,
  ): BooleanSchema<NotNull<TType>, TContext, TDefault, TFlags> {
    return super.nonNullable(msg);
  }

  strip(
    enabled: false,
  ): BooleanSchema<TType, TContext, TDefault, UnsetFlag<TFlags, 's'>>;
  strip(
    enabled?: true,
  ): BooleanSchema<TType, TContext, TDefault, SetFlag<TFlags, 's'>>;
  strip(v: any) {
    return super.strip(v);
  }
}

create.prototype = BooleanSchema.prototype;


================================================
FILE: src/date.ts
================================================
import { parseIsoDate } from './util/parseIsoDate';
import { date as locale } from './locale';
import Ref from './Reference';
import type { AnyObject, DefaultThunk, Message } from './types';
import type {
  Defined,
  Flags,
  NotNull,
  SetFlag,
  Maybe,
  ToggleDefault,
  UnsetFlag,
} from './util/types';
import Schema from './schema';

let invalidDate = new Date('');

let isDate = (obj: any): obj is Date =>
  Object.prototype.toString.call(obj) === '[object Date]';

export function create(): DateSchema;
export function create<
  T extends Date,
  TContext extends Maybe<AnyObject> = AnyObject,
>(): DateSchema<T | undefined, TContext>;
export function create() {
  return new DateSchema();
}

export default class DateSchema<
  TType extends Maybe<Date> = Date | undefined,
  TContext = AnyObject,
  TDefault = undefined,
  TFlags extends Flags = '',
> extends Schema<TType, TContext, TDefault, TFlags> {
  static INVALID_DATE = invalidDate;

  constructor() {
    super({
      type: 'date',
      check(v: any): v is NonNullable<TType> {
        return isDate(v) && !isNaN(v.getTime());
      },
    });

    this.withMutation(() => {
      this.transform((value, _raw) => {
        // null -> InvalidDate isn't useful; treat all nulls as null and let it fail on
        // nullability check vs TypeErrors
        if (!this.spec.coerce || this.isType(value) || value === null)
          return value;

        value = parseIsoDate(value);

        // 0 is a valid timestamp equivalent to 1970-01-01T00:00:00Z(unix epoch) or before.
        return !isNaN(value) ? new Date(value) : DateSchema.INVALID_DATE;
      });
    });
  }

  private prepareParam(
    ref: unknown | Ref<Date>,
    name: string,
  ): Date | Ref<Date> {
    let param: Date | Ref<Date>;

    if (!Ref.isRef(ref)) {
      let cast = this.cast(ref);
      if (!this._typeCheck(cast))
        throw new TypeError(
          `\`${name}\` must be a Date or a value that can be \`cast()\` to a Date`,
        );
      param = cast;
    } else {
      param = ref as Ref<Date>;
    }
    return param;
  }

  min(min: unknown | Ref<Date>, message = locale.min) {
    let limit = this.prepareParam(min, 'min');

    return this.test({
      message,
      name: 'min',
      exclusive: true,
      params: { min },
      skipAbsent: true,
      test(value) {
        return value! >= this.resolve(limit);
      },
    });
  }

  max(max: unknown | Ref, message = locale.max) {
    let limit = this.prepareParam(max, 'max');

    return this.test({
      message,
      name: 'max',
      exclusive: true,
      params: { max },
      skipAbsent: true,
      test(value) {
        return value! <= this.resolve(limit);
      },
    });
  }
}

create.prototype = DateSchema.prototype;
create.INVALID_DATE = invalidDate;

export default interface DateSchema<
  TType extends Maybe<Date>,
  TContext = AnyObject,
  TDefault = undefined,
  TFlags extends Flags = '',
> extends Schema<TType, TContext, TDefault, TFlags> {
  default<D extends Maybe<TType>>(
    def: DefaultThunk<D, TContext>,
  ): DateSchema<TType, TContext, D, ToggleDefault<TFlags, D>>;

  concat<TOther extends DateSchema<any, any>>(schema: TOther): TOther;

  defined(
    msg?: Message,
  ): DateSchema<Defined<TType>, TContext, TDefault, TFlags>;
  optional(): DateSchema<TType | undefined, TContext, TDefault, TFlags>;

  required(
    msg?: Message,
  ): DateSchema<NonNullable<TType>, TContext, TDefault, TFlags>;
  notRequired(): DateSchema<Maybe<TType>, TContext, TDefault, TFlags>;

  nullable(msg?: Message): DateSchema<TType | null, TContext, TDefault, TFlags>;
  nonNullable(
    msg?: Message,
  ): DateSchema<NotNull<TType>, TContext, TDefault, TFlags>;

  strip(
    enabled: false,
  ): DateSchema<TType, TContext, TDefault, UnsetFlag<TFlags, 's'>>;
  strip(
    enabled?: true,
  ): DateSchema<TType, TContext, TDefault, SetFlag<TFlags, 's'>>;
}


================================================
FILE: src/globals.d.ts
================================================



================================================
FILE: src/index.ts
================================================
import MixedSchema, {
  create as mixedCreate,
  MixedOptions,
  TypeGuard,
} from './mixed';
import BooleanSchema, { create as boolCreate } from './boolean';
import StringSchema, { create as stringCreate } from './string';
import NumberSchema, { create as numberCreate } from './number';
import DateSchema, { create as dateCreate } from './date';
import ObjectSchema, { AnyObject, create as objectCreate } from './object';
import ArraySchema, { create as arrayCreate } from './array';
import TupleSchema, { create as tupleCreate } from './tuple';
import Reference, { create as refCreate } from './Reference';
import Lazy, { create as lazyCreate } from './Lazy';
import ValidationError from './ValidationError';
import reach, { getIn } from './util/reach';
import isSchema from './util/isSchema';
import printValue from './util/printValue';
import setLocale, { LocaleObject } from './setLocale';
import defaultLocale from './locale';
import Schema, {
  AnySchema,
  CastOptions as BaseCastOptions,
  SchemaSpec,
  SchemaRefDescription,
  SchemaInnerTypeDescription,
  SchemaObjectDescription,
  SchemaLazyDescription,
  SchemaFieldDescription,
  SchemaDescription,
  SchemaMetadata,
  CustomSchemaMetadata,
} from './schema';
import type {
  AnyMessageParams,
  InferType,
  ISchema,
  Message,
  MessageParams,
  ValidateOptions,
  DefaultThunk,
} from './types';

function addMethod<T extends ISchema<any>>(
  schemaType: (...arg: any[]) => T,
  name: string,
  fn: (this: T, ...args: any[]) => T,
): void;
function addMethod<T extends abstract new (...args: any) => ISchema<any>>(
  schemaType: T,
  name: string,
  fn: (this: InstanceType<T>, ...args: any[]) => InstanceType<T>,
): void;
function addMethod(schemaType: any, name: string, fn: any) {
  if (!schemaType || !isSchema(schemaType.prototype))
    throw new TypeError('You must provide a yup schema constructor function');

  if (typeof name !== 'string')
    throw new TypeError('A Method name must be provided');
  if (typeof fn !== 'function')
    throw new TypeError('Method function must be provided');

  schemaType.prototype[name] = fn;
}

export type AnyObjectSchema = ObjectSchema<any, any, any, any>;

export type CastOptions = Omit<BaseCastOptions, 'path' | 'resolved'>;

export type {
  AnyMessageParams,
  AnyObject,
  InferType,
  InferType as Asserts,
  ISchema,
  Message,
  MessageParams,
  AnySchema,
  MixedOptions,
  TypeGuard as MixedTypeGuard,
  SchemaSpec,
  SchemaRefDescription,
  SchemaInnerTypeDescription,
  SchemaObjectDescription,
  SchemaLazyDescription,
  SchemaFieldDescription,
  SchemaDescription,
  SchemaMetadata,
  CustomSchemaMetadata,
  LocaleObject,
  ValidateOptions,
  DefaultThunk,
  Lazy,
  Reference,
};

export {
  mixedCreate as mixed,
  boolCreate as bool,
  boolCreate as boolean,
  stringCreate as string,
  numberCreate as number,
  dateCreate as date,
  objectCreate as object,
  arrayCreate as array,
  refCreate as ref,
  lazyCreate as lazy,
  tupleCreate as tuple,
  reach,
  getIn,
  isSchema,
  printValue,
  addMethod,
  setLocale,
  defaultLocale,
  ValidationError,
};

export {
  Schema,
  MixedSchema,
  BooleanSchema,
  StringSchema,
  NumberSchema,
  DateSchema,
  ObjectSchema,
  ArraySchema,
  TupleSchema,
  Lazy as LazySchema,
};

export type {
  CreateErrorOptions,
  TestContext,
  TestFunction,
  TestOptions,
  TestConfig,
} from './util/createValidation';

export type {
  ObjectShape,
  TypeFromShape,
  DefaultFromShape,
  MakePartial,
} from './util/objectTypes';

export type {
  Maybe,
  Flags,
  Optionals,
  ToggleDefault,
  Defined,
  NotNull,
  UnsetFlag,
  SetFlag,
} from './util/types';


================================================
FILE: src/locale.ts
================================================
import printValue from './util/printValue';
import { Message } from './types';
import ValidationError from './ValidationError';

export interface MixedLocale {
  default?: Message;
  required?: Message;
  oneOf?: Message<{ values: any }>;
  notOneOf?: Message<{ values: any }>;
  notNull?: Message;
  notType?: Message;
  defined?: Message;
}

export interface StringLocale {
  length?: Message<{ length: number }>;
  min?: Message<{ min: number }>;
  max?: Message<{ max: number }>;
  matches?: Message<{ regex: RegExp }>;
  email?: Message<{ regex: RegExp }>;
  url?: Message<{ regex: RegExp }>;
  uuid?: Message<{ regex: RegExp }>;
  datetime?: Message;
  datetime_offset?: Message;
  datetime_precision?: Message<{ precision: number }>;
  trim?: Message;
  lowercase?: Message;
  uppercase?: Message;
}

export interface NumberLocale {
  min?: Message<{ min: number }>;
  max?: Message<{ max: number }>;
  lessThan?: Message<{ less: number }>;
  moreThan?: Message<{ more: number }>;
  positive?: Message<{ more: number }>;
  negative?: Message<{ less: number }>;
  integer?: Message;
}

export interface DateLocale {
  min?: Message<{ min: Date | string }>;
  max?: Message<{ max: Date | string }>;
}

export interface ObjectLocale {
  noUnknown?: Message<{ unknown: string[] }>;
  exact?: Message<{ properties: string[] }>;
}

export interface ArrayLocale {
  length?: Message<{ length: number }>;
  min?: Message<{ min: number }>;
  max?: Message<{ max: number }>;
}

export interface TupleLocale {
  notType?: Message;
}

export interface BooleanLocale {
  isValue?: Message;
}

export interface LocaleObject {
  mixed?: MixedLocale;
  string?: StringLocale;
  number?: NumberLocale;
  date?: DateLocale;
  boolean?: BooleanLocale;
  object?: ObjectLocale;
  array?: ArrayLocale;
  tuple?: TupleLocale;
}

export let mixed: Required<MixedLocale> = {
  default: '${path} is invalid',
  required: '${path} is a required field',
  defined: '${path} must be defined',
  notNull: '${path} cannot be null',
  oneOf: '${path} must be one of the following values: ${values}',
  notOneOf: '${path} must not be one of the following values: ${values}',
  notType: ({ path, type, value, originalValue }) => {
    const castMsg =
      originalValue != null && originalValue !== value
        ? ` (cast from the value \`${printValue(originalValue, true)}\`).`
        : '.';

    return type !== 'mixed'
      ? `${path} must be a \`${type}\` type, ` +
          `but the final value was: \`${printValue(value, true)}\`` +
          castMsg
      : `${path} must match the configured type. ` +
          `The validated value was: \`${printValue(value, true)}\`` +
          castMsg;
  },
};

export let string: Required<StringLocale> = {
  length: '${path} must be exactly ${length} characters',
  min: '${path} must be at least ${min} characters',
  max: '${path} must be at most ${max} characters',
  matches: '${path} must match the following: "${regex}"',
  email: '${path} must be a valid email',
  url: '${path} must be a valid URL',
  uuid: '${path} must be a valid UUID',
  datetime: '${path} must be a valid ISO date-time',
  datetime_precision:
    '${path} must be a valid ISO date-time with a sub-second precision of exactly ${precision} digits',
  datetime_offset:
    '${path} must be a valid ISO date-time with UTC "Z" timezone',
  trim: '${path} must be a trimmed string',
  lowercase: '${path} must be a lowercase string',
  uppercase: '${path} must be a upper case string',
};

export let number: Required<NumberLocale> = {
  min: '${path} must be greater than or equal to ${min}',
  max: '${path} must be less than or equal to ${max}',
  lessThan: '${path} must be less than ${less}',
  moreThan: '${path} must be greater than ${more}',
  positive: '${path} must be a positive number',
  negative: '${path} must be a negative number',
  integer: '${path} must be an integer',
};

export let date: Required<DateLocale> = {
  min: '${path} field must be later than ${min}',
  max: '${path} field must be at earlier than ${max}',
};

export let boolean: BooleanLocale = {
  isValue: '${path} field must be ${value}',
};

export let object: Required<ObjectLocale> = {
  noUnknown: '${path} field has unspecified keys: ${unknown}',
  exact: '${path} object contains unknown properties: ${properties}',
};

export let array: Required<ArrayLocale> = {
  min: '${path} field must have at least ${min} items',
  max: '${path} field must have less than or equal to ${max} items',
  length: '${path} must have ${length} items',
};

export let tuple: Required<TupleLocale> = {
  notType: (params) => {
    const { path, value, spec } = params;
    const typeLen = spec.types.length;
    if (Array.isArray(value)) {
      if (value.length < typeLen)
        return `${path} tuple value has too few items, expected a length of ${typeLen} but got ${
          value.length
        } for value: \`${printValue(value, true)}\``;
      if (value.length > typeLen)
        return `${path} tuple value has too many items, expected a length of ${typeLen} but got ${
          value.length
        } for value: \`${printValue(value, true)}\``;
    }

    return ValidationError.formatError(mixed.notType, params);
  },
};

export default Object.assign(Object.create(null), {
  mixed,
  string,
  number,
  date,
  object,
  array,
  boolean,
  tuple,
}) as LocaleObject;


================================================
FILE: src/mixed.ts
================================================
import { AnyObject, DefaultThunk, Message } from './types';
import type {
  Concat,
  Defined,
  Flags,
  SetFlag,
  Maybe,
  ToggleDefault,
  UnsetFlag,
} from './util/types';
import Schema from './schema';

const returnsTrue: any = () => true;

type AnyPresentValue = {};

export type TypeGuard<TType> = (value: any) => value is NonNullable<TType>;
export interface MixedOptions<TType> {
  type?: string;
  check?: TypeGuard<TType>;
}

export function create<TType extends AnyPresentValue>(
  spec?: MixedOptions<TType> | TypeGuard<TType>,
) {
  return new MixedSchema<TType | undefined>(spec);
}

export default class MixedSchema<
  TType extends Maybe<AnyPresentValue> = AnyPresentValue | undefined,
  TContext = AnyObject,
  TDefault = undefined,
  TFlags extends Flags = '',
> extends Schema<TType, TContext, TDefault, TFlags> {
  constructor(spec?: MixedOptions<TType> | TypeGuard<TType>) {
    super(
      typeof spec === 'function'
        ? { type: 'mixed', check: spec }
        : { type: 'mixed', check: returnsTrue as TypeGuard<TType>, ...spec },
    );
  }
}

export default interface MixedSchema<
  TType extends Maybe<AnyPresentValue> = AnyPresentValue | undefined,
  TContext = AnyObject,
  TDefault = undefined,
  TFlags extends Flags = '',
> extends Schema<TType, TContext, TDefault, TFlags> {
  default<D extends Maybe<TType>>(
    def: DefaultThunk<D, TContext>,
  ): MixedSchema<TType, TContext, D, ToggleDefault<TFlags, D>>;

  concat<IT, IC, ID, IF extends Flags>(
    schema: MixedSchema<IT, IC, ID, IF>,
  ): MixedSchema<Concat<TType, IT>, TContext & IC, ID, TFlags | IF>;
  concat<IT, IC, ID, IF extends Flags>(
    schema: Schema<IT, IC, ID, IF>,
  ): MixedSchema<Concat<TType, IT>, TContext & IC, ID, TFlags | IF>;
  concat(schema: this): this;

  defined(
    msg?: Message,
  ): MixedSchema<Defined<TType>, TContext, TDefault, TFlags>;
  optional(): MixedSchema<TType | undefined, TContext, TDefault, TFlags>;

  required(
    msg?: Message,
  ): MixedSchema<NonNullable<TType>, TContext, TDefault, TFlags>;
  notRequired(): MixedSchema<Maybe<TType>, TContext, TDefault, TFlags>;

  nullable(
    msg?: Message,
  ): MixedSchema<TType | null, TContext, TDefault, TFlags>;

  nonNullable(
    msg?: Message,
  ): MixedSchema<Exclude<TType, null>, TContext, TDefault, TFlags>;

  strip(
    enabled: false,
  ): MixedSchema<TType, TContext, TDefault, UnsetFlag<TFlags, 's'>>;
  strip(
    enabled?: true,
  ): MixedSchema<TType, TContext, TDefault, SetFlag<TFlags, 's'>>;
}

create.prototype = MixedSchema.prototype;


================================================
FILE: src/number.ts
================================================
import { number as locale } from './locale';
import isAbsent from './util/isAbsent';
import type { AnyObject, DefaultThunk, Message } from './types';
import type Reference from './Reference';
import type {
  Concat,
  Defined,
  Flags,
  NotNull,
  SetFlag,
  Maybe,
  ToggleDefault,
  UnsetFlag,
} from './util/types';
import Schema from './schema';

let isNaN = (value: Maybe<number>) => value != +value!;

export function create(): NumberSchema;
export function create<
  T extends number,
  TContext extends Maybe<AnyObject> = AnyObject,
>(): NumberSchema<T | undefined, TContext>;
export function create() {
  return new NumberSchema();
}

export default class NumberSchema<
  TType extends Maybe<number> = number | undefined,
  TContext = AnyObject,
  TDefault = undefined,
  TFlags extends Flags = '',
> extends Schema<TType, TContext, TDefault, TFlags> {
  constructor() {
    super({
      type: 'number',
      check(value: any): value is NonNullable<TType> {
        if (value instanceof Number) value = value.valueOf();

        return typeof value === 'number' && !isNaN(value);
      },
    });

    this.withMutation(() => {
      this.transform((value, _raw) => {
        if (!this.spec.coerce) return value;

        let parsed = value;
        if (typeof parsed === 'string') {
          parsed = parsed.replace(/\s/g, '');
          if (parsed === '') return NaN;
          // don't use parseFloat to avoid positives on alpha-numeric strings
          parsed = +parsed;
        }

        // null -> NaN isn't useful; treat all nulls as null and let it fail on
        // nullability check vs TypeErrors
        if (this.isType(parsed) || parsed === null) return parsed;

        return parseFloat(parsed);
      });
    });
  }

  min(min: number | Reference<number>, message = locale.min) {
    return this.test({
      message,
      name: 'min',
      exclusive: true,
      params: { min },
      skipAbsent: true,
      test(value: Maybe<number>) {
        return value! >= this.resolve(min);
      },
    });
  }

  max(max: number | Reference<number>, message = locale.max) {
    return this.test({
      message,
      name: 'max',
      exclusive: true,
      params: { max },
      skipAbsent: true,
      test(value: Maybe<number>) {
        return value! <= this.resolve(max);
      },
    });
  }

  lessThan(less: number | Reference<number>, message = locale.lessThan) {
    return this.test({
      message,
      name: 'max',
      exclusive: true,
      params: { less },
      skipAbsent: true,
      test(value: Maybe<number>) {
        return value! < this.resolve(less);
      },
    });
  }

  moreThan(more: number | Reference<number>, message = locale.moreThan) {
    return this.test({
      message,
      name: 'min',
      exclusive: true,
      params: { more },
      skipAbsent: true,
      test(value: Maybe<number>) {
        return value! > this.resolve(more);
      },
    });
  }

  positive(msg = locale.positive) {
    return this.moreThan(0, msg);
  }

  negative(msg = locale.negative) {
    return this.lessThan(0, msg);
  }

  integer(message = locale.integer) {
    return this.test({
      name: 'integer',
      message,
      skipAbsent: true,
      test: (val) => Number.isInteger(val),
    });
  }

  truncate() {
    return this.transform((value) => (!isAbsent(value) ? value | 0 : value));
  }

  round(method?: 'ceil' | 'floor' | 'round' | 'trunc') {
    let avail = ['ceil', 'floor', 'round', 'trunc'];
    method = (method?.toLowerCase() as any) || ('round' as const);

    // this exists for symemtry with the new Math.trunc
    if (method === 'trunc') return this.truncate();

    if (avail.indexOf(method!.toLowerCase()) === -1)
      throw new TypeError(
        'Only valid options for round() are: ' + avail.join(', '),
      );

    return this.transform((value) =>
      !isAbsent(value) ? Math[method!](value) : value,
    );
  }
}

create.prototype = NumberSchema.prototype;

//
// Number Interfaces
//

export default interface NumberSchema<
  TType extends Maybe<number> = number | undefined,
  TContext = AnyObject,
  TDefault = undefined,
  TFlags extends Flags = '',
> extends Schema<TType, TContext, TDefault, TFlags> {
  default<D extends Maybe<TType>>(
    def: DefaultThunk<D, TContext>,
  ): NumberSchema<TType, TContext, D, ToggleDefault<TFlags, D>>;

  concat<UType extends Maybe<number>, UContext, UFlags extends Flags, UDefault>(
    schema: NumberSchema<UType, UContext, UDefault, UFlags>,
  ): NumberSchema<
    Concat<TType, UType>,
    TContext & UContext,
    UDefault,
    TFlags | UFlags
  >;
  concat(schema: this): this;

  defined(
    msg?: Message,
  ): NumberSchema<Defined<TType>, TContext, TDefault, TFlags>;
  optional(): NumberSchema<TType | undefined, TContext, TDefault, TFlags>;

  required(
    msg?: Message,
  ): NumberSchema<NonNullable<TType>, TContext, TDefault, TFlags>;
  notRequired(): NumberSchema<Maybe<TType>, TContext, TDefault, TFlags>;

  nullable(
    msg?: Message,
  ): NumberSchema<TType | null, TContext, TDefault, TFlags>;
  nonNullable(
    msg?: Message,
  ): NumberSchema<NotNull<TType>, TContext, TDefault, TFlags>;

  strip(
    enabled: false,
  ): NumberSchema<TType, TContext, TDefault, UnsetFlag<TFlags, 's'>>;
  strip(
    enabled?: true,
  ): NumberSchema<TType, TContext, TDefault, SetFlag<TFlags, 's'>>;
}


================================================
FILE: src/object.ts
================================================
// @ts-ignore
import { getter, normalizePath, join } from 'property-expr';
import { camelCase, snakeCase } from 'tiny-case';

import { Flags, Maybe, SetFlag, ToggleDefault, UnsetFlag } from './util/types';
import { object as locale } from './locale';
import sortFields from './util/sortFields';
import sortByKeyOrder from './util/sortByKeyOrder';
import { DefaultThunk, InternalOptions, ISchema, Message } from './types';
import type { Defined, NotNull, _ } from './util/types';
import Reference from './Reference';
import Schema, { SchemaObjectDescription, SchemaSpec } from './schema';
import { ResolveOptions } from './Condition';
import type {
  AnyObject,
  ConcatObjectTypes,
  DefaultFromShape,
  MakePartial,
  MergeObjectTypes,
  ObjectShape,
  PartialDeep,
  TypeFromShape,
} from './util/objectTypes';
import parseJson from './util/parseJson';
import type { Test } from './util/createValidation';
import type ValidationError from './ValidationError';
export type { AnyObject };

type MakeKeysOptional<T> = T extends AnyObject ? _<MakePartial<T>> : T;

export type Shape<T extends Maybe<AnyObject>, C = any> = {
  [field in keyof T]-?: ISchema<T[field], C> | Reference;
};

export type ObjectSchemaSpec = SchemaSpec<any> & {
  noUnknown?: boolean;
};

function deepPartial(schema: any) {
  if ('fields' in schema) {
    const partial: any = {};
    for (const [key, fieldSchema] of Object.entries(schema.fields)) {
      partial[key] = deepPartial(fieldSchema);
    }
    return schema.setFields(partial);
  }
  if (schema.type === 'array') {
    const nextArray = schema.optional();
    if (nextArray.innerType)
      nextArray.innerType = deepPartial(nextArray.innerType);
    return nextArray;
  }
  if (schema.type === 'tuple') {
    return schema
      .optional()
      .clone({ types: schema.spec.types.map(deepPartial) });
  }
  if ('optional' in schema) {
    return schema.optional();
  }
  return schema;
}

const deepHas = (obj: any, p: string) => {
  const path = [...normalizePath(p)];
  if (path.length === 1) return path[0] in obj;
  let last = path.pop()!;
  let parent = getter(join(path), true)(obj);
  return !!(parent && last in parent);
};

let isObject = (obj: any): obj is Record<PropertyKey, unknown> =>
  Object.prototype.toString.call(obj) === '[object Object]';

function unknown(ctx: ObjectSchema<any, any, any>, value: any) {
  let known = Object.keys(ctx.fields);
  return Object.keys(value).filter((key) => known.indexOf(key) === -1);
}

const defaultSort = sortByKeyOrder([]);

export function create<
  C extends Maybe<AnyObject> = AnyObject,
  S extends ObjectShape = {},
>(spec?: S) {
  type TIn = _<TypeFromShape<S, C>>;
  type TDefault = _<DefaultFromShape<S>>;

  return new ObjectSchema<TIn, C, TDefault>(spec as any);
}

export default interface ObjectSchema<
  TIn extends Maybe<AnyObject>,
  TContext = AnyObject,
  // important that this is `any` so that using `ObjectSchema<MyType>`'s default
  // will match object schema regardless of defaults
  TDefault = any,
  TFlags extends Flags = '',
> extends Schema<MakeKeysOptional<TIn>, TContext, TDefault, TFlags> {
  default<D extends Maybe<AnyObject>>(
    def: DefaultThunk<D, TContext>,
  ): ObjectSchema<TIn, TContext, D, ToggleDefault<TFlags, 'd'>>;

  defined(
    msg?: Message,
  ): ObjectSchema<Defined<TIn>, TContext, TDefault, TFlags>;
  optional(): ObjectSchema<TIn | undefined, TContext, TDefault, TFlags>;

  required(
    msg?: Message,
  ): ObjectSchema<NonNullable<TIn>, TContext, TDefault, TFlags>;
  notRequired(): ObjectSchema<Maybe<TIn>, TContext, TDefault, TFlags>;

  nullable(msg?: Message): ObjectSchema<TIn | null, TContext, TDefault, TFlags>;
  nonNullable(
    msg?: Message,
  ): ObjectSchema<NotNull<TIn>, TContext, TDefault, TFlags>;

  strip(
    enabled: false,
  ): ObjectSchema<TIn, TContext, TDefault, UnsetFlag<TFlags, 's'>>;
  strip(
    enabled?: true,
  ): ObjectSchema<TIn, TContext, TDefault, SetFlag<TFlags, 's'>>;
}

export default class ObjectSchema<
  TIn extends Maybe<AnyObject>,
  TContext = AnyObject,
  TDefault = any,
  TFlags extends Flags = '',
> extends Schema<MakeKeysOptional<TIn>, TContext, TDefault, TFlags> {
  fields: Shape<NonNullable<TIn>, TContext> = Object.create(null);

  declare spec: ObjectSchemaSpec;

  private _sortErrors = defaultSort;
  private _nodes: string[] = [];

  private _excludedEdges: readonly [nodeA: string, nodeB: string][] = [];

  constructor(spec?: Shape<TIn, TContext>) {
    super({
      type: 'object',
      check(value): value is NonNullable<MakeKeysOptional<TIn>> {
        return isObject(value) || typeof value === 'function';
      },
    });

    this.withMutation(() => {
      if (spec) {
        this.shape(spec as any);
      }
    });
  }

  protected _cast(_value: any, options: InternalOptions<TContext> = {}) {
    let value = super._cast(_value, options);

    //should ignore nulls here
    if (value === undefined) return this.getDefault(options);

    if (!this._typeCheck(value)) return value;

    let fields = this.fields;

    let strip = options.stripUnknown ?? this.spec.noUnknown;
    let props = ([] as string[]).concat(
      this._nodes,
      Object.keys(value).filter((v) => !this._nodes.includes(v)),
    );

    let intermediateValue: Record<string, unknown> = {}; // is filled during the transform below
    let innerOptions: InternalOptions<TContext> = {
      ...options,
      parent: intermediateValue,
      __validating: options.__validating || false,
    };

    let isChanged = false;
    for (const prop of props) {
      let field = fields[prop];
      let exists = prop in (value as {})!;
      let inputValue = value[prop];

      if (field) {
        let fieldValue;

        // safe to mutate since this is fired in sequence
        innerOptions.path = (options.path ? `${options.path}.` : '') + prop;

        field = field.resolve({
          value: inputValue,
          context: options.context,
          parent: intermediateValue,
        });

        let fieldSpec = field instanceof Schema ? field.spec : undefined;
        let strict = fieldSpec?.strict;

        if (fieldSpec?.strip) {
          isChanged = isChanged || prop in (value as {});
          continue;
        }

        fieldValue =
          !options.__validating || !strict
            ? (field as ISchema<any>).cast(inputValue, innerOptions)
            : inputValue;

        if (fieldValue !== undefined) {
          intermediateValue[prop] = fieldValue;
        }
      } else if (exists && !strip) {
        intermediateValue[prop] = inputValue;
      }

      if (
        exists !== prop in intermediateValue ||
        intermediateValue[prop] !== inputValue
      ) {
        isChanged = true;
      }
    }

    return isChanged ? intermediateValue : value;
  }

  protected _validate(
    _value: any,
    options: InternalOptions<TContext> = {},
    panic: (err: Error, value: unknown) => void,
    next: (err: ValidationError[], value: unknown) => void,
  ) {
    let {
      from = [],
      originalValue = _value,
      recursive = this.spec.recursive,
    } = options;

    options.from = [{ schema: this, value: originalValue }, ...from];
    // this flag is needed for handling `strict` correctly in the context of
    // validation vs just casting. e.g strict() on a field is only used when validating
    options.__validating = true;
    options.originalValue = originalValue;

    super._validate(_value, options, panic, (objectErrors, value) => {
      if (!recursive || !isObject(value)) {
        next(objectErrors, value);
        return;
      }

      originalValue = originalValue || value;

      let tests = [] as Test[];
      for (let key of this._nodes) {
        let field = this.fields[key];

        if (!field || Reference.isRef(field)) {
          continue;
        }

        tests.push(
          field.asNestedTest({
            options,
            key,
            parent: value,
            parentPath: options.path,
            originalParent: originalValue,
          }),
        );
      }

      this.runTests(
        { tests, value, originalValue, options },
        panic,
        (fieldErrors) => {
          next(fieldErrors.sort(this._sortErrors).concat(objectErrors), value);
        },
      );
    });
  }

  clone(spec?: Partial<ObjectSchemaSpec>): this {
    const next = super.clone(spec);
    next.fields = { ...this.fields };
    next._nodes = this._nodes;
    next._excludedEdges = this._excludedEdges;
    next._sortErrors = this._sortErrors;

    return next;
  }

  concat<IIn extends Maybe<AnyObject>, IC, ID, IF extends Flags>(
    schema: ObjectSchema<IIn, IC, ID, IF>,
  ): ObjectSchema<
    ConcatObjectTypes<TIn, IIn>,
    TContext & IC,
    Extract<IF, 'd'> extends never
      ? // this _attempts_ to cover the default from shape case
        TDefault extends AnyObject
        ? ID extends AnyObject
          ? _<ConcatObjectTypes<TDefault, ID>>
          : ID
        : ID
      : ID,
    TFlags | IF
  >;
  concat(schema: this): this;
  concat(schema: any): any {
    let next = super.concat(schema) as any;

    let nextFields = next.fields;
    for (let [field, schemaOrRef] of Object.entries(this.fields)) {
      const target = nextFields[field];
      nextFields[field] = target === undefined ? schemaOrRef : target;
    }

    return next.withMutation((s: any) =>
      // XXX: excludes here is wrong
      s.setFields(nextFields, [
        ...this._excludedEdges,
        ...schema._excludedEdges,
      ]),
    );
  }

  protected _getDefault(options?: ResolveOptions<TContext>) {
    if ('default' in this.spec) {
      return super._getDefault(options);
    }

    // if there is no default set invent one
    if (!this._nodes.length) {
      return undefined;
    }

    let dft: any = {};
    this._nodes.forEach((key) => {
      const field = this.fields[key] as any;

      let innerOptions = options;
      if (innerOptions?.value) {
        innerOptions = {
          ...innerOptions,
          parent: innerOptions.value,
          value: innerOptions.value[key],
        };
      }

      dft[key] =
        field && 'getDefault' in field
          ? field.getDefault(innerOptions)
          : undefined;
    });

    return dft;
  }

  private setFields<TInNext extends Maybe<AnyObject>, TDefaultNext>(
    shape: Shape<TInNext, TContext>,
    excludedEdges?: readonly [string, string][],
  ): ObjectSchema<TInNext, TContext, TDefaultNext, TFlags> {
    let next = this.clone() as any;
    next.fields = shape;

    next._nodes = sortFields(shape, excludedEdges);
    next._sortErrors = sortByKeyOrder(Object.keys(shape));
    // XXX: this carries over edges which may not be what you want
    if (excludedEdges) next._excludedEdges = excludedEdges;
    return next;
  }

  shape<U extends ObjectShape>(
    additions: U,
    excludes: readonly [string, string][] = [],
  ) {
    type UIn = TypeFromShape<U, TContext>;
    type UDefault = Extract<TFlags, 'd'> extends never
      ? // not defaulted then assume the default is derived and should be merged
        _<TDefault & DefaultFromShape<U>>
      : TDefault;

    return this.clone().withMutation((next) => {
      let edges = next._excludedEdges;
      if (excludes.length) {
        if (!Array.isArray(excludes[0])) excludes = [excludes as any];

        edges = [...next._excludedEdges, ...excludes];
      }

      // XXX: excludes here is wrong
      return next.setFields<_<MergeObjectTypes<TIn, UIn>>, UDefault>(
        Object.assign(next.fields, additions) as any,
        edges,
      );
    });
  }

  partial() {
    const partial: any = {};
    for (const [key, schema] of Object.entries(this.fields)) {
      partial[key] =
        'optional' in schema && schema.optional instanceof Function
          ? schema.optional()
          : schema;
    }

    return this.setFields<Partial<TIn>, TDefault>(partial);
  }

  deepPartial(): ObjectSchema<PartialDeep<TIn>, TContext, TDefault, TFlags> {
    const next = deepPartial(this);
    return next;
  }

  pick<TKey extends keyof TIn>(keys: readonly TKey[]) {
    const picked: any = {};
    for (const key of keys) {
      if (this.fields[key]) picked[key] = this.fields[key];
    }

    return this.setFields<{ [K in TKey]: TIn[K] }, TDefault>(
      picked,
      this._excludedEdges.filter(
        ([a, b]) => keys.includes(a as TKey) && keys.includes(b as TKey),
      ),
    );
  }

  omit<TKey extends keyof TIn>(keys: readonly TKey[]) {
    const remaining: TKey[] = [];

    for (const key of Object.keys(this.fields) as TKey[]) {
      if (keys.includes(key)) continue;
      remaining.push(key);
    }

    return this.pick<keyof Omit<TIn, TKey>>(remaining as any);
  }

  from(from: string, to: keyof TIn, alias?: boolean) {
    let fromGetter = getter(from, true);

    return this.transform((obj) => {
      if (!obj) return obj;
      let newObj = obj;
      if (deepHas(obj, from)) {
        newObj = { ...obj };
        if (!alias) delete newObj[from];

        newObj[to] = fromGetter(obj);
      }

      return newObj;
    });
  }

  /** Parse an input JSON string to an object */
  json() {
    return this.transform(parseJson);
  }

  /**
   * Similar to `noUnknown` but only validates that an object is the right shape without stripping the unknown keys
   */
  exact(message?: Message): this {
    return this.test({
      name: 'exact',
      exclusive: true,
      message: message || locale.exact,
      test(value) {
        if (value == null) return true;

        const unknownKeys = unknown(this.schema, value);

        return (
          unknownKeys.length === 0 ||
          this.createError({ params: { properties: unknownKeys.join(', ') } })
        );
      },
    });
  }

  stripUnknown(): this {
    return this.clone({ noUnknown: true });
  }

  noUnknown(message?: Message): this;
  noUnknown(noAllow: boolean, message?: Message): this;
  noUnknown(noAllow: Message | boolean = true, message = locale.noUnknown) {
    if (typeof noAllow !== 'boolean') {
      message = noAllow;
      noAllow = true;
    }

    let next = this.test({
      name: 'noUnknown',
      exclusive: true,
      message: message,
      test(value) {
        if (value == null) return true;
        const unknownKeys = unknown(this.schema, value);
        return (
          !noAllow ||
          unknownKeys.length === 0 ||
          this.createError({ params: { unknown: unknownKeys.join(', ') } })
        );
      },
    });

    next.spec.noUnknown = noAllow;

    return next;
  }

  unknown(allow = true, message = locale.noUnknown) {
    return this.noUnknown(!allow, message);
  }

  transformKeys(fn: (key: string) => string) {
    return this.transform((obj) => {
      if (!obj) return obj;
      const result: AnyObject = {};
      for (const key of Object.keys(obj)) result[fn(key)] = obj[key];
      return result;
    });
  }

  camelCase() {
    return this.transformKeys(camelCase);
  }

  snakeCase() {
    return this.transformKeys(snakeCase);
  }

  constantCase() {
    return this.transformKeys((key) => snakeCase(key).toUpperCase());
  }

  describe(options?: ResolveOptions<TContext>) {
    const next = (options ? this.resolve(options) : this).clone();
    const base = super.describe(options) as SchemaObjectDescription;
    base.fields = {};
    for (const [key, value] of Object.entries(next.fields)) {
      let innerOptions = options;
      if (innerOptions?.value) {
        innerOptions = {
          ...innerOptions,
          parent: innerOptions.value,
          value: innerOptions.value[key],
        };
      }
      base.fields[key] = value.describe(innerOptions);
    }
    return base;
  }
}

create.prototype = ObjectSchema.prototype;


================================================
FILE: src/schema.ts
================================================
import { mixed as locale } from './locale';
import Condition, {
  ConditionBuilder,
  ConditionConfig,
  ResolveOptions,
} from './Condition';
import createValidation, {
  TestFunction,
  Test,
  TestConfig,
  NextCallback,
  PanicCallback,
  TestOptions,
  resolveParams,
} from './util/createValidation';
import printValue from './util/printValue';
import Ref from './Reference';
import { getIn } from './util/reach';
import {
  ValidateOptions,
  TransformFunction,
  Message,
  InternalOptions,
  ExtraParams,
  ISchema,
  NestedTestConfig,
  DefaultThunk,
} from './types';

import ValidationError from './ValidationError';
import ReferenceSet from './util/ReferenceSet';
import Reference from './Reference';
import isAbsent from './util/isAbsent';
import type { Flags, Maybe, ResolveFlags, _ } from './util/types';
import toArray from './util/toArray';
import cloneDeep from './util/cloneDeep';
import {
  issuesFromValidationError,
  StandardResult,
  type StandardSchema,
  type StandardSchemaProps,
} from './standardSchema';

export type SchemaSpec<TDefault> = {
  coerce: boolean;
  nullable: boolean;
  optional: boolean;
  default?: TDefault | (() => TDefault);
  abortEarly?: boolean;
  strip?: boolean;
  strict?: boolean;
  recursive?: boolean;
  disableStackTrace?: boolean;
  label?: string | undefined;
  meta?: SchemaMetadata;
};

export interface CustomSchemaMetadata {}

// If `CustomSchemaMeta` isn't extended with any keys, we'll fall back to a
// loose Record definition allowing free form usage.
export type SchemaMetadata = keyof CustomSchemaMetadata extends never
  ? Record<PropertyKey, any>
  : CustomSchemaMetadata;

export type SchemaOptions<TType, TDefault> = {
  type: string;
  spec?: Partial<SchemaSpec<TDefault>>;
  check: (value: any) => value is NonNullable<TType>;
};

export type AnySchema<
  TType = any,
  C = any,
  D = any,
  F extends Flags = Flags,
> = Schema<TType, C, D, F>;

export interface CastOptions<C = {}> {
  parent?: any;
  context?: C;
  assert?: boolean;
  stripUnknown?: boolean;
  // XXX: should be private?
  path?: string;
  index?: number;
  key?: string;
  originalValue?: any;
  value?: any;
  resolved?: boolean;
}

export interface CastOptionalityOptions<C = {}>
  extends Omit<CastOptions<C>, 'assert'> {
  /**
   * Whether or not to throw TypeErrors if casting fails to produce a valid type.
   * defaults to `true`. The `'ignore-optionality'` options is provided as a migration
   * path from pre-v1 where `schema.nullable().required()` was allowed. When provided
   * cast will only throw for values that are the wrong type *not* including `null` and `undefined`
   */
  assert: 'ignore-optionality';
}

export type RunTest = (
  opts: TestOptions,
  panic: PanicCallback,
  next: NextCallback,
) => void;

export type TestRunOptions = {
  tests: RunTest[];
  path?: string | undefined;
  options: InternalOptions;
  originalValue: any;
  value: any;
};

export interface SchemaRefDescription {
  type: 'ref';
  key: string;
}

export interface SchemaInnerTypeDescription extends SchemaDescription {
  innerType?: SchemaFieldDescription | SchemaFieldDescription[];
}

export interface SchemaObjectDescription extends SchemaDescription {
  fields: Record<string, SchemaFieldDescription>;
}

export interface SchemaLazyDescription {
  type: string;
  label?: string;
  meta?: SchemaMetadata;
}

export type SchemaFieldDescription =
  | SchemaDescription
  | SchemaRefDescription
  | SchemaObjectDescription
  | SchemaInnerTypeDescription
  | SchemaLazyDescription;

export interface SchemaDescription {
  type: string;
  label?: string;
  meta?: SchemaMetadata;
  oneOf: unknown[];
  notOneOf: unknown[];
  default?: unknown;
  nullable: boolean;
  optional: boolean;
  tests: Array<{ name?: string; params: ExtraParams | undefined }>;
}

export default abstract class Schema<
  TType = any,
  TContext = any,
  TDefault = any,
  TFlags extends Flags = '',
> implements
    ISchema<TType, TContext, TFlags, TDefault>,
    StandardSchema<TType, ResolveFlags<TType, TFlags, TDefault>>
{
  readonly type: string;

  declare readonly __outputType: ResolveFlags<TType, TFlags, TDefault>;
  declare readonly __context: TContext;
  declare readonly __flags: TFlags;
  declare readonly __isYupSchema__: boolean;
  declare readonly __default: TDefault;

  readonly deps: readonly string[] = [];

  tests: Test[];
  transforms: TransformFunction<AnySchema, TContext>[];

  private conditions: Condition[] = [];

  private _mutate?: boolean;

  private internalTests: Record<string, Test | null> = {};

  protected _whitelist = new ReferenceSet();
  protected _blacklist = new ReferenceSet();

  protected exclusiveTests: Record<string, boolean> = Object.create(null);
  protected _typeCheck: (value: any) => value is NonNullable<TType>;

  spec: SchemaSpec<any>;

  constructor(options: SchemaOptions<TType, any>) {
    this.tests = [];
    this.transforms = [];

    this.withMutation(() => {
      this.typeError(locale.notType);
    });

    this.type = options.type;
    this._typeCheck = options.check;

    this.spec = {
      strip: false,
      strict: false,
      abortEarly: true,
      recursive: true,
      disableStackTrace: false,
      nullable: false,
      optional: true,
      coerce: true,
      ...options?.spec,
    };

    this.withMutation((s) => {
      s.nonNullable();
    });
  }

  // TODO: remove
  get _type() {
    return this.type;
  }

  clone(spec?: Partial<SchemaSpec<any>>): this {
    if (this._mutate) {
      if (spec) Object.assign(this.spec, spec);
      return this;
    }

    // if the nested value is a schema we can skip cloning, since
    // they are already immutable
    const next: AnySchema = Object.create(Object.getPrototypeOf(this));

    // @ts-expect-error this is readonly
    next.type = this.type;
    next._typeCheck = this._typeCheck;

    next._whitelist = this._whitelist.clone();
    next._blacklist = this._blacklist.clone();
    next.internalTests = { ...this.internalTests };
    next.exclusiveTests = { ...this.exclusiveTests };

    // @ts-expect-error this is readonly
    next.deps = [...this.deps];
    next.conditions = [...this.conditions];
    next.tests = [...this.tests];
    next.transforms = [...this.transforms];
    next.spec = cloneDeep({ ...this.spec, ...spec });

    return next as this;
  }

  label(label: string) {
    let next = this.clone();
    next.spec.label = label;
    return next;
  }

  meta(): SchemaMetadata | undefined;
  meta(obj: SchemaMetadata): this;
  meta(...args: [SchemaMetadata?]) {
    if (args.length === 0) return this.spec.meta;

    let next = this.clone();
    next.spec.meta = Object.assign(next.spec.meta || {}, args[0]);
    return next;
  }

  withMutation<T>(fn: (schema: this) => T): T {
    let before = this._mutate;
    this._mutate = true;
    let result = fn(this);
    this._mutate = before;
    return result;
  }

  concat(schema: this): this;
  concat(schema: AnySchema): AnySchema;
  concat(schema: AnySchema): AnySchema {
    if (!schema || schema === this) return this;

    if (schema.type !== this.type && this.type !== 'mixed')
      throw new TypeError(
        `You cannot \`concat()\` schema's of different types: ${this.type} and ${schema.type}`,
      );

    let base = this;
    let combined = schema.clone();

    const mergedSpec = { ...base.spec, ...combined.spec };

    combined.spec = mergedSpec;
    combined.internalTests = {
      ...base.internalTests,
      ...combined.internalTests,
    };

    // manually merge the blacklist/whitelist (the other `schema` takes
    // precedence in case of conflicts)
    combined._whitelist = base._whitelist.merge(
      schema._whitelist,
      schema._blacklist,
    );
    combined._blacklist = base._blacklist.merge(
      schema._blacklist,
      schema._whitelist,
    );

    // start with the current tests
    combined.tests = base.tests;
    combined.exclusiveTests = base.exclusiveTests;

    // manually add the new tests to ensure
    // the deduping logic is consistent
    combined.withMutation((next) => {
      schema.tests.forEach((fn) => {
        next.test(fn.OPTIONS!);
      });
    });

    combined.transforms = [...base.transforms, ...combined.transforms];
    return combined as any;
  }

  isType(v: unknown): v is TType {
    if (v == null) {
      if (this.spec.nullable && v === null) return true;
      if (this.spec.optional && v === undefined) return true;
      return false;
    }

    return this._typeCheck(v);
  }

  resolve(options: ResolveOptions<TContext>) {
    let schema = this;

    if (schema.conditions.length) {
      let conditions = schema.conditions;

      schema = schema.clone();
      schema.conditions = [];
      schema = conditions.reduce(
        (prevSchema, condition) =>
          condition.resolve(prevSchema, options) as any,
        schema,
      ) as any as this;

      schema = schema.resolve(options);
    }

    return schema;
  }

  protected resolveOptions<T extends InternalOptions<any>>(options: T): T {
    return {
      ...options,
      from: options.from || [],
      strict: options.strict ?? this.spec.strict,
      abortEarly: options.abortEarly ?? this.spec.abortEarly,
      recursive: options.recursive ?? this.spec.recursive,
      disableStackTrace:
        options.disableStackTrace ?? this.spec.disableStackTrace,
    };
  }

  /**
   * Run the configured transform pipeline over an input value.
   */
  cast(value: any, options?: CastOptions<TContext>): this['__outputType'];
  cast(
    value: any,
    options: CastOptionalityOptions<TContext>,
  ): this['__outputType'] | null | undefined;
  cast(
    value: any,
    options: CastOptions<TContext> | CastOptionalityOptions<TContext> = {},
  ): this['__outputType'] {
    let resolvedSchema = this.resolve({
      ...options,
      value,
      // parent: options.parent,
      // context: options.context,
    });
    let allowOptionality = options.assert === 'ignore-optionality';

    let result = resolvedSchema._cast(value, options as any);

    if (options.assert !== false && !resolvedSchema.isType(result)) {
      if (allowOptionality && isAbsent(result)) {
        return result as any;
      }

      let formattedValue = printValue(value);
      let formattedResult = printValue(result);

      throw new TypeError(
        `The value of ${
          options.path || 'field'
        } could not be cast to a value ` +
          `that satis
Download .txt
gitextract_was633h2/

├── .babelrc.js
├── .eslintignore
├── .eslintrc
├── .gitattributes
├── .github/
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── question.md
│   └── workflows/
│       └── ci.yml
├── .gitignore
├── .nvmrc
├── .yarn/
│   └── patches/
│       └── @4c-rollout-npm-4.0.2-ab2b6d0bab.patch
├── .yarnrc.yml
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── docs/
│   └── extending.md
├── package.json
├── renovate.json
├── rollup.config.js
├── src/
│   ├── Condition.ts
│   ├── Lazy.ts
│   ├── Reference.ts
│   ├── ValidationError.ts
│   ├── array.ts
│   ├── boolean.ts
│   ├── date.ts
│   ├── globals.d.ts
│   ├── index.ts
│   ├── locale.ts
│   ├── mixed.ts
│   ├── number.ts
│   ├── object.ts
│   ├── schema.ts
│   ├── setLocale.ts
│   ├── standardSchema.ts
│   ├── string.ts
│   ├── tuple.ts
│   ├── types.ts
│   └── util/
│       ├── ReferenceSet.ts
│       ├── cloneDeep.ts
│       ├── createValidation.ts
│       ├── isAbsent.ts
│       ├── isSchema.ts
│       ├── objectTypes.ts
│       ├── parseIsoDate.ts
│       ├── parseJson.ts
│       ├── printValue.ts
│       ├── reach.ts
│       ├── sortByKeyOrder.ts
│       ├── sortFields.ts
│       ├── toArray.ts
│       └── types.ts
├── test/
│   ├── .eslintignore
│   ├── ValidationError.ts
│   ├── array.ts
│   ├── bool.ts
│   ├── date.ts
│   ├── helpers.ts
│   ├── lazy.ts
│   ├── mixed.ts
│   ├── number.ts
│   ├── object.ts
│   ├── setLocale.ts
│   ├── standardSchema.ts
│   ├── string.ts
│   ├── tsconfig.json
│   ├── tuple.ts
│   ├── types/
│   │   ├── .eslintrc.js
│   │   └── types.ts
│   ├── util/
│   │   └── parseIsoDate.ts
│   └── yup.js
├── test-setup.mjs
├── tsconfig.json
└── vitest.config.ts
Download .txt
SYMBOL INDEX (340 symbols across 37 files)

FILE: src/Condition.ts
  type ConditionBuilder (line 5) | type ConditionBuilder<T extends ISchema<any, any>> = (
  type ConditionConfig (line 11) | type ConditionConfig<T extends ISchema<any>> = {
  type ResolveOptions (line 17) | type ResolveOptions<TContext = any> = {
  class Condition (line 23) | class Condition<TIn extends ISchema<any, any> = ISchema<any, any>> {
    method fromOptions (line 26) | static fromOptions<TIn extends ISchema<any, any>>(
    method constructor (line 49) | constructor(
    method resolve (line 57) | resolve(base: TIn, options: ResolveOptions) {

FILE: src/Lazy.ts
  type LazyBuilder (line 26) | type LazyBuilder<
  function create (line 31) | function create<
  function catchValidationError (line 38) | function catchValidationError(fn: () => any) {
  type LazySpec (line 47) | interface LazySpec {
  class Lazy (line 52) | class Lazy<T, TContext = AnyObject, TFlags extends Flags = any>
    method constructor (line 66) | constructor(private builder: any) {
    method clone (line 70) | clone(spec?: Partial<LazySpec>): Lazy<T, TContext, TFlags> {
    method optionality (line 95) | private optionality(optional: boolean) {
    method optional (line 100) | optional(): Lazy<T | undefined, TContext, TFlags> {
    method resolve (line 104) | resolve(options: ResolveOptions<TContext>) {
    method cast (line 113) | cast(
    method asNestedTest (line 120) | asNestedTest(config: NestedTestConfig) {
    method validate (line 131) | validate(value: any, options?: ValidateOptions<TContext>): Promise<T> {
    method validateSync (line 137) | validateSync(value: any, options?: ValidateOptions<TContext>): T {
    method validateAt (line 141) | validateAt(path: string, value: any, options?: ValidateOptions<TContex...
    method validateSyncAt (line 147) | validateSyncAt(
    method isValid (line 155) | isValid(value: any, options?: ValidateOptions<TContext>) {
    method isValidSync (line 166) | isValidSync(value: any, options?: ValidateOptions<TContext>) {
    method describe (line 170) | describe(
    method meta (line 180) | meta(...args: [Record<string, unknown>?]) {
    method ['~standard'] (line 188) | get ['~standard']() {

FILE: src/Reference.ts
  type ReferenceOptions (line 9) | type ReferenceOptions<TValue = unknown> = {
  function create (line 13) | function create<TValue = unknown>(
  class Reference (line 20) | class Reference<TValue = unknown> {
    method constructor (line 32) | constructor(key: string, options: ReferenceOptions<TValue> = {}) {
    method getValue (line 55) | getValue(value: any, parent?: {}, context?: {}): TValue {
    method cast (line 72) | cast(value: any, options?: { parent?: {}; context?: {} }) {
    method resolve (line 76) | resolve() {
    method describe (line 80) | describe(): SchemaRefDescription {
    method toString (line 87) | toString() {
    method isRef (line 91) | static isRef(value: any): value is Reference {

FILE: src/ValidationError.ts
  type Params (line 6) | type Params = Record<string, unknown>;
  class ValidationErrorNoStack (line 8) | class ValidationErrorNoStack implements ValidationError {
    method constructor (line 20) | constructor(
  class ValidationError (line 53) | class ValidationError extends Error {
    method formatError (line 62) | static formatError(
    method isError (line 79) | static isError(err: any): err is ValidationError {
    method constructor (line 83) | constructor(
  method [Symbol.hasInstance] (line 116) | static [Symbol.hasInstance](inst: any) {

FILE: src/array.ts
  type InnerType (line 32) | type InnerType<T> = T extends Array<infer I> ? I : never;
  type RejectorFn (line 34) | type RejectorFn = (
  function create (line 40) | function create<C extends Maybe<AnyObject> = AnyObject, T = any>(
  type ArraySchemaSpec (line 46) | interface ArraySchemaSpec<TIn, TContext> extends SchemaSpec<any> {
  class ArraySchema (line 50) | class ArraySchema<
    method constructor (line 59) | constructor(type?: ISchema<InnerType<TIn>, TContext>) {
    method _cast (line 72) | protected _cast(_value: any, _opts: InternalOptions<TContext>) {
    method _validate (line 102) | protected _validate(
    method clone (line 151) | clone(spec?: SchemaSpec<any>) {
    method json (line 159) | json() {
    method concat (line 172) | concat(schema: any): any {
    method of (line 188) | of<U>(
    method length (line 211) | length(
    method min (line 227) | min(min: number | Reference<number>, message?: Message<{ min: number }...
    method max (line 243) | max(max: number | Reference<number>, message?: Message<{ max: number }...
    method ensure (line 257) | ensure() {
    method compact (line 267) | compact(rejector?: RejectorFn) {
    method describe (line 277) | describe(options?: ResolveOptions<TContext>) {
  type ArraySchema (line 297) | interface ArraySchema<
    method constructor (line 59) | constructor(type?: ISchema<InnerType<TIn>, TContext>) {
    method _cast (line 72) | protected _cast(_value: any, _opts: InternalOptions<TContext>) {
    method _validate (line 102) | protected _validate(
    method clone (line 151) | clone(spec?: SchemaSpec<any>) {
    method json (line 159) | json() {
    method concat (line 172) | concat(schema: any): any {
    method of (line 188) | of<U>(
    method length (line 211) | length(
    method min (line 227) | min(min: number | Reference<number>, message?: Message<{ min: number }...
    method max (line 243) | max(max: number | Reference<number>, message?: Message<{ max: number }...
    method ensure (line 257) | ensure() {
    method compact (line 267) | compact(rejector?: RejectorFn) {
    method describe (line 277) | describe(options?: ResolveOptions<TContext>) {

FILE: src/boolean.ts
  function create (line 21) | function create() {
  class BooleanSchema (line 25) | class BooleanSchema<
    method constructor (line 31) | constructor() {
    method isTrue (line 52) | isTrue(
    method isFalse (line 66) | isFalse(
    method default (line 80) | override default<D extends Maybe<TType>>(
    method defined (line 86) | defined(
    method optional (line 91) | optional(): BooleanSchema<TType | undefined, TContext, TDefault, TFlag...
    method required (line 94) | required(
    method notRequired (line 99) | notRequired(): BooleanSchema<Maybe<TType>, TContext, TDefault, TFlags> {
    method nullable (line 102) | nullable(): BooleanSchema<TType | null, TContext, TDefault, TFlags> {
    method nonNullable (line 105) | nonNullable(
    method strip (line 117) | strip(v: any) {

FILE: src/date.ts
  function create (line 26) | function create() {
  class DateSchema (line 30) | class DateSchema<
    method constructor (line 38) | constructor() {
    method prepareParam (line 61) | private prepareParam(
    method min (line 80) | min(min: unknown | Ref<Date>, message = locale.min) {
    method max (line 95) | max(max: unknown | Ref, message = locale.max) {
  type DateSchema (line 114) | interface DateSchema<
    method constructor (line 38) | constructor() {
    method prepareParam (line 61) | private prepareParam(
    method min (line 80) | min(min: unknown | Ref<Date>, message = locale.min) {
    method max (line 95) | max(max: unknown | Ref, message = locale.max) {

FILE: src/index.ts
  function addMethod (line 54) | function addMethod(schemaType: any, name: string, fn: any) {
  type AnyObjectSchema (line 66) | type AnyObjectSchema = ObjectSchema<any, any, any, any>;
  type CastOptions (line 68) | type CastOptions = Omit<BaseCastOptions, 'path' | 'resolved'>;

FILE: src/locale.ts
  type MixedLocale (line 5) | interface MixedLocale {
  type StringLocale (line 15) | interface StringLocale {
  type NumberLocale (line 31) | interface NumberLocale {
  type DateLocale (line 41) | interface DateLocale {
  type ObjectLocale (line 46) | interface ObjectLocale {
  type ArrayLocale (line 51) | interface ArrayLocale {
  type TupleLocale (line 57) | interface TupleLocale {
  type BooleanLocale (line 61) | interface BooleanLocale {
  type LocaleObject (line 65) | interface LocaleObject {

FILE: src/mixed.ts
  type AnyPresentValue (line 15) | type AnyPresentValue = {};
  type TypeGuard (line 17) | type TypeGuard<TType> = (value: any) => value is NonNullable<TType>;
  type MixedOptions (line 18) | interface MixedOptions<TType> {
  function create (line 23) | function create<TType extends AnyPresentValue>(
  class MixedSchema (line 29) | class MixedSchema<
    method constructor (line 35) | constructor(spec?: MixedOptions<TType> | TypeGuard<TType>) {
  type MixedSchema (line 44) | interface MixedSchema<
    method constructor (line 35) | constructor(spec?: MixedOptions<TType> | TypeGuard<TType>) {

FILE: src/number.ts
  function create (line 24) | function create() {
  class NumberSchema (line 28) | class NumberSchema<
    method constructor (line 34) | constructor() {
    method min (line 65) | min(min: number | Reference<number>, message = locale.min) {
    method max (line 78) | max(max: number | Reference<number>, message = locale.max) {
    method lessThan (line 91) | lessThan(less: number | Reference<number>, message = locale.lessThan) {
    method moreThan (line 104) | moreThan(more: number | Reference<number>, message = locale.moreThan) {
    method positive (line 117) | positive(msg = locale.positive) {
    method negative (line 121) | negative(msg = locale.negative) {
    method integer (line 125) | integer(message = locale.integer) {
    method truncate (line 134) | truncate() {
    method round (line 138) | round(method?: 'ceil' | 'floor' | 'round' | 'trunc') {
  type NumberSchema (line 162) | interface NumberSchema<
    method constructor (line 34) | constructor() {
    method min (line 65) | min(min: number | Reference<number>, message = locale.min) {
    method max (line 78) | max(max: number | Reference<number>, message = locale.max) {
    method lessThan (line 91) | lessThan(less: number | Reference<number>, message = locale.lessThan) {
    method moreThan (line 104) | moreThan(more: number | Reference<number>, message = locale.moreThan) {
    method positive (line 117) | positive(msg = locale.positive) {
    method negative (line 121) | negative(msg = locale.negative) {
    method integer (line 125) | integer(message = locale.integer) {
    method truncate (line 134) | truncate() {
    method round (line 138) | round(method?: 'ceil' | 'floor' | 'round' | 'trunc') {

FILE: src/object.ts
  type MakeKeysOptional (line 29) | type MakeKeysOptional<T> = T extends AnyObject ? _<MakePartial<T>> : T;
  type Shape (line 31) | type Shape<T extends Maybe<AnyObject>, C = any> = {
  type ObjectSchemaSpec (line 35) | type ObjectSchemaSpec = SchemaSpec<any> & {
  function deepPartial (line 39) | function deepPartial(schema: any) {
  function unknown (line 75) | function unknown(ctx: ObjectSchema<any, any, any>, value: any) {
  function create (line 82) | function create<
  type ObjectSchema (line 92) | interface ObjectSchema<
    method constructor (line 142) | constructor(spec?: Shape<TIn, TContext>) {
    method _cast (line 157) | protected _cast(_value: any, options: InternalOptions<TContext> = {}) {
    method _validate (line 229) | protected _validate(
    method clone (line 284) | clone(spec?: Partial<ObjectSchemaSpec>): this {
    method concat (line 310) | concat(schema: any): any {
    method _getDefault (line 328) | protected _getDefault(options?: ResolveOptions<TContext>) {
    method setFields (line 360) | private setFields<TInNext extends Maybe<AnyObject>, TDefaultNext>(
    method shape (line 374) | shape<U extends ObjectShape>(
    method partial (line 400) | partial() {
    method deepPartial (line 412) | deepPartial(): ObjectSchema<PartialDeep<TIn>, TContext, TDefault, TFla...
    method pick (line 417) | pick<TKey extends keyof TIn>(keys: readonly TKey[]) {
    method omit (line 431) | omit<TKey extends keyof TIn>(keys: readonly TKey[]) {
    method from (line 442) | from(from: string, to: keyof TIn, alias?: boolean) {
    method json (line 460) | json() {
    method exact (line 467) | exact(message?: Message): this {
    method stripUnknown (line 485) | stripUnknown(): this {
    method noUnknown (line 491) | noUnknown(noAllow: Message | boolean = true, message = locale.noUnknow...
    method unknown (line 517) | unknown(allow = true, message = locale.noUnknown) {
    method transformKeys (line 521) | transformKeys(fn: (key: string) => string) {
    method camelCase (line 530) | camelCase() {
    method snakeCase (line 534) | snakeCase() {
    method constantCase (line 538) | constantCase() {
    method describe (line 542) | describe(options?: ResolveOptions<TContext>) {
  class ObjectSchema (line 127) | class ObjectSchema<
    method constructor (line 142) | constructor(spec?: Shape<TIn, TContext>) {
    method _cast (line 157) | protected _cast(_value: any, options: InternalOptions<TContext> = {}) {
    method _validate (line 229) | protected _validate(
    method clone (line 284) | clone(spec?: Partial<ObjectSchemaSpec>): this {
    method concat (line 310) | concat(schema: any): any {
    method _getDefault (line 328) | protected _getDefault(options?: ResolveOptions<TContext>) {
    method setFields (line 360) | private setFields<TInNext extends Maybe<AnyObject>, TDefaultNext>(
    method shape (line 374) | shape<U extends ObjectShape>(
    method partial (line 400) | partial() {
    method deepPartial (line 412) | deepPartial(): ObjectSchema<PartialDeep<TIn>, TContext, TDefault, TFla...
    method pick (line 417) | pick<TKey extends keyof TIn>(keys: readonly TKey[]) {
    method omit (line 431) | omit<TKey extends keyof TIn>(keys: readonly TKey[]) {
    method from (line 442) | from(from: string, to: keyof TIn, alias?: boolean) {
    method json (line 460) | json() {
    method exact (line 467) | exact(message?: Message): this {
    method stripUnknown (line 485) | stripUnknown(): this {
    method noUnknown (line 491) | noUnknown(noAllow: Message | boolean = true, message = locale.noUnknow...
    method unknown (line 517) | unknown(allow = true, message = locale.noUnknown) {
    method transformKeys (line 521) | transformKeys(fn: (key: string) => string) {
    method camelCase (line 530) | camelCase() {
    method snakeCase (line 534) | snakeCase() {
    method constantCase (line 538) | constantCase() {
    method describe (line 542) | describe(options?: ResolveOptions<TContext>) {

FILE: src/schema.ts
  type SchemaSpec (line 44) | type SchemaSpec<TDefault> = {
  type CustomSchemaMetadata (line 58) | interface CustomSchemaMetadata {}
  type SchemaMetadata (line 62) | type SchemaMetadata = keyof CustomSchemaMetadata extends never
  type SchemaOptions (line 66) | type SchemaOptions<TType, TDefault> = {
  type AnySchema (line 72) | type AnySchema<
  type CastOptions (line 79) | interface CastOptions<C = {}> {
  type CastOptionalityOptions (line 93) | interface CastOptionalityOptions<C = {}>
  type RunTest (line 104) | type RunTest = (
  type TestRunOptions (line 110) | type TestRunOptions = {
  type SchemaRefDescription (line 118) | interface SchemaRefDescription {
  type SchemaInnerTypeDescription (line 123) | interface SchemaInnerTypeDescription extends SchemaDescription {
  type SchemaObjectDescription (line 127) | interface SchemaObjectDescription extends SchemaDescription {
  type SchemaLazyDescription (line 131) | interface SchemaLazyDescription {
  type SchemaFieldDescription (line 137) | type SchemaFieldDescription =
  type SchemaDescription (line 144) | interface SchemaDescription {
  method constructor (line 192) | constructor(options: SchemaOptions<TType, any>) {
  method _type (line 221) | get _type() {
  method clone (line 225) | clone(spec?: Partial<SchemaSpec<any>>): this {
  method label (line 254) | label(label: string) {
  method meta (line 262) | meta(...args: [SchemaMetadata?]) {
  method withMutation (line 270) | withMutation<T>(fn: (schema: this) => T): T {
  method concat (line 280) | concat(schema: AnySchema): AnySchema {
  method isType (line 326) | isType(v: unknown): v is TType {
  method resolve (line 336) | resolve(options: ResolveOptions<TContext>) {
  method resolveOptions (line 356) | protected resolveOptions<T extends InternalOptions<any>>(options: T): T {
  method cast (line 376) | cast(
  method _cast (line 413) | protected _cast(rawValue: any, options: CastOptions<TContext>): any {
  method _validate (line 429) | protected _validate(
  method runTests (line 481) | protected runTests(
  method asNestedTest (line 530) | asNestedTest({
  method validate (line 570) | validate(
  method validateSync (line 603) | validateSync(
  method isValid (line 635) | isValid(value: any, options?: ValidateOptions<TContext>): Promise<boolea...
  method isValidSync (line 645) | isValidSync(
  method _getDefault (line 658) | protected _getDefault(options?: ResolveOptions<TContext>) {
  method getDefault (line 670) | getDefault(
  method default (line 678) | default(def: DefaultThunk<any>): any {
  method strict (line 688) | strict(isStrict = true) {
  method nullability (line 692) | protected nullability(nullable: boolean, message?: Message<any>) {
  method optionality (line 704) | protected optionality(optional: boolean, message?: Message<any>) {
  method optional (line 716) | optional(): any {
  method defined (line 719) | defined(message = locale.defined): any {
  method nullable (line 723) | nullable(): any {
  method nonNullable (line 726) | nonNullable(message = locale.notNull): any {
  method required (line 730) | required(message: Message<any> = locale.required): any {
  method notRequired (line 735) | notRequired(): any {
  method transform (line 739) | transform(fn: TransformFunction<this>) {
  method test (line 766) | test(...args: any[]) {
  method when (line 818) | when(
  method typeError (line 844) | typeError(message: Message) {
  method oneOf (line 872) | oneOf<U extends TType>(
  method notOneOf (line 905) | notOneOf<U extends TType>(
  method strip (line 935) | strip(strip = true): any {
  method describe (line 946) | describe(options?: ResolveOptions<TContext>) {
  method ['~standard'] (line 979) | get ['~standard']() {
  type Schema (line 1015) | interface Schema<

FILE: src/setLocale.ts
  function setLocale (line 5) | function setLocale(custom: LocaleObject) {

FILE: src/standardSchema.ts
  type StandardSchema (line 8) | interface StandardSchema<Input = unknown, Output = Input> {
  type StandardSchemaProps (line 12) | interface StandardSchemaProps<Input = unknown, Output = Input> {
  type StandardResult (line 21) | type StandardResult<Output> =
  type StandardSuccessResult (line 25) | interface StandardSuccessResult<Output> {
  type StandardFailureResult (line 30) | interface StandardFailureResult {
  type StandardIssue (line 34) | interface StandardIssue {
  type StandardPathSegment (line 39) | interface StandardPathSegment {
  type StandardTypes (line 43) | interface StandardTypes<Input, Output> {
  function createStandardPath (line 48) | function createStandardPath(
  function createStandardIssues (line 118) | function createStandardIssues(
  function issuesFromValidationError (line 133) | function issuesFromValidationError(

FILE: src/string.ts
  type MatchOptions (line 42) | type MatchOptions = {
  type DateTimeOptions (line 48) | type DateTimeOptions = {
  function create (line 63) | function create() {
  class StringSchema (line 69) | class StringSchema<
    method constructor (line 75) | constructor() {
    method required (line 102) | required(message?: Message<any>) {
    method notRequired (line 113) | notRequired() {
    method length (line 120) | length(
    method min (line 136) | min(
    method max (line 152) | max(
    method matches (line 168) | matches(regex: RegExp, options?: MatchOptions | MatchOptions['message'...
    method email (line 195) | email(message = locale.email) {
    method url (line 203) | url(message = locale.url) {
    method uuid (line 211) | uuid(message = locale.uuid) {
    method datetime (line 219) | datetime(options?: DateTimeOptions | DateTimeOptions['message']) {
    method ensure (line 268) | ensure(): StringSchema<NonNullable<TType>> {
    method trim (line 274) | trim(message = locale.trim) {
    method lowercase (line 282) | lowercase(message = locale.lowercase) {
    method uppercase (line 295) | uppercase(message = locale.uppercase) {
  type StringSchema (line 315) | interface StringSchema<
    method constructor (line 75) | constructor() {
    method required (line 102) | required(message?: Message<any>) {
    method notRequired (line 113) | notRequired() {
    method length (line 120) | length(
    method min (line 136) | min(
    method max (line 152) | max(
    method matches (line 168) | matches(regex: RegExp, options?: MatchOptions | MatchOptions['message'...
    method email (line 195) | email(message = locale.email) {
    method url (line 203) | url(message = locale.url) {
    method uuid (line 211) | uuid(message = locale.uuid) {
    method datetime (line 219) | datetime(options?: DateTimeOptions | DateTimeOptions['message']) {
    method ensure (line 268) | ensure(): StringSchema<NonNullable<TType>> {
    method trim (line 274) | trim(message = locale.trim) {
    method lowercase (line 282) | lowercase(message = locale.lowercase) {
    method uppercase (line 295) | uppercase(message = locale.uppercase) {

FILE: src/tuple.ts
  type AnyTuple (line 28) | type AnyTuple = [unknown, ...unknown[]];
  function create (line 30) | function create<T extends AnyTuple>(schemas: {
  type TupleSchema (line 36) | interface TupleSchema<
    method constructor (line 89) | constructor(schemas: [ISchema<any>, ...ISchema<any>[]]) {
    method _cast (line 104) | protected _cast(inputValue: any, options: InternalOptions<TContext>) {
    method _validate (line 129) | protected _validate(
    method describe (line 168) | describe(options?: ResolveOptions<TContext>) {
  type TupleSchemaSpec (line 73) | interface TupleSchemaSpec<T> extends SchemaSpec<any> {
  class TupleSchema (line 81) | class TupleSchema<
    method constructor (line 89) | constructor(schemas: [ISchema<any>, ...ISchema<any>[]]) {
    method _cast (line 104) | protected _cast(inputValue: any, options: InternalOptions<TContext>) {
    method _validate (line 129) | protected _validate(
    method describe (line 168) | describe(options?: ResolveOptions<TContext>) {

FILE: src/types.ts
  type ISchema (line 15) | interface ISchema<T, C = any, F extends Flags = any, D = any> {
  type DefaultThunk (line 32) | type DefaultThunk<T, C = any> = T | ((options?: ResolveOptions<C>) => T);
  type InferType (line 34) | type InferType<T extends ISchema<any, any>> = T['__outputType'];
  type TransformFunction (line 36) | type TransformFunction<T extends AnySchema, C = any> = (
  type Ancester (line 44) | interface Ancester<TContext> {
  type ValidateOptions (line 48) | interface ValidateOptions<TContext = {}> {
  type InternalOptions (line 75) | interface InternalOptions<TContext = any>
  type MessageParams (line 87) | interface MessageParams {
  type Message (line 97) | type Message<Extra extends Record<string, unknown> = any> =
  type ExtraParams (line 102) | type ExtraParams = Record<string, unknown>;
  type AnyMessageParams (line 104) | type AnyMessageParams = MessageParams & ExtraParams;
  type NestedTestConfig (line 106) | interface NestedTestConfig {

FILE: src/util/ReferenceSet.ts
  class ReferenceSet (line 4) | class ReferenceSet extends Set<unknown | Reference> {
    method describe (line 5) | describe() {
    method resolveAll (line 14) | resolveAll(resolve: (v: unknown | Reference) => unknown) {
    method clone (line 22) | clone() {
    method merge (line 26) | merge(newItems: ReferenceSet, removeItems: ReferenceSet) {

FILE: src/util/cloneDeep.ts
  function clone (line 6) | function clone(src: unknown, seen: Map<any, any> = new Map()) {

FILE: src/util/createValidation.ts
  type PanicCallback (line 15) | type PanicCallback = (err: Error) => void;
  type NextCallback (line 17) | type NextCallback = (
  type CreateErrorOptions (line 21) | type CreateErrorOptions = {
  type TestContext (line 29) | type TestContext<TContext = {}> = {
  type TestFunction (line 40) | type TestFunction<T = unknown, TContext = {}> = (
  type TestOptions (line 46) | type TestOptions<TSchema extends AnySchema = AnySchema> = {
  type TestConfig (line 54) | type TestConfig<TValue = unknown, TContext = {}> = {
  type Test (line 63) | type Test = ((
  function createValidation (line 71) | function createValidation(config: {
  function resolveParams (line 176) | function resolveParams<T extends ExtraParams>(
  function resolveMaybeRef (line 190) | function resolveMaybeRef<T>(item: T | Reference<T>, options: ResolveOpti...

FILE: src/util/objectTypes.ts
  type ObjectShape (line 5) | type ObjectShape = { [k: string]: ISchema<any> | Reference };
  type AnyObject (line 7) | type AnyObject = { [k: string]: any };
  type ResolveStrip (line 9) | type ResolveStrip<T extends ISchema<any>> = T extends ISchema<
  type TypeFromShape (line 19) | type TypeFromShape<S extends ObjectShape, _C> = {
  type DefaultFromShape (line 27) | type DefaultFromShape<Shape extends ObjectShape> = {
  type MergeObjectTypes (line 33) | type MergeObjectTypes<T extends Maybe<AnyObject>, U extends AnyObject> =
  type ConcatObjectTypes (line 37) | type ConcatObjectTypes<
  type PartialDeep (line 46) | type PartialDeep<T> = T extends
  type OptionalKeys (line 62) | type OptionalKeys<T extends {}> = {
  type RequiredKeys (line 66) | type RequiredKeys<T extends object> = Exclude<keyof T, OptionalKeys<T>>;
  type MakePartial (line 68) | type MakePartial<T extends object> = {

FILE: src/util/parseIsoDate.ts
  function parseIsoDate (line 13) | function parseIsoDate(date: string): number {
  function parseDateStruct (line 47) | function parseDateStruct(date: string) {
  function toNumber (line 72) | function toNumber(str: string, defaultValue = 0) {

FILE: src/util/printValue.ts
  constant SYMBOL_REGEXP (line 7) | const SYMBOL_REGEXP = /^Symbol\((.*)\)(.*)$/;
  function printNumber (line 9) | function printNumber(val: any) {
  function printSimpleValue (line 15) | function printSimpleValue(val: any, quoteStrings = false) {
  function printValue (line 36) | function printValue(value: any, quoteStrings?: boolean) {

FILE: src/util/reach.ts
  function getIn (line 6) | function getIn<C = any>(
  function reach (line 68) | function reach<P extends string, S extends ISchema<any>>(

FILE: src/util/sortByKeyOrder.ts
  function findIndex (line 3) | function findIndex(arr: readonly string[], err: ValidationError) {
  function sortByKeyOrder (line 14) | function sortByKeyOrder(keys: readonly string[]) {

FILE: src/util/sortFields.ts
  function sortFields (line 9) | function sortFields(

FILE: src/util/toArray.ts
  function toArray (line 1) | function toArray<T>(value?: null | T | readonly T[]) {

FILE: src/util/types.ts
  type IfAny (line 1) | type IfAny<T, Y, N> = 0 extends 1 & T ? Y : N;
  type Maybe (line 3) | type Maybe<T> = T | null | undefined;
  type Preserve (line 5) | type Preserve<T, U> = T extends U ? U : never;
  type Optionals (line 7) | type Optionals<T> = Extract<T, null | undefined>;
  type Defined (line 9) | type Defined<T> = T extends undefined ? never : T;
  type NotNull (line 11) | type NotNull<T> = T extends null ? never : T;
  type _ (line 14) | type _<T> = T extends {} ? { [k in keyof T]: T[k] } : T;
  type Flags (line 20) | type Flags = 's' | 'd' | '';
  type SetFlag (line 22) | type SetFlag<Old extends Flags, F extends Flags> = Exclude<Old, ''> | F;
  type UnsetFlag (line 24) | type UnsetFlag<Old extends Flags, F extends Flags> = Exclude<
  type ToggleDefault (line 31) | type ToggleDefault<F extends Flags, D> = Preserve<
  type ResolveFlags (line 38) | type ResolveFlags<T, F extends Flags, D = T> = Extract<
  type Concat (line 47) | type Concat<T, U> = NonNullable<T> & NonNullable<U> extends never

FILE: test/date.ts
  function isInvalidDate (line 5) | function isInvalidDate(date: any): date is Date {

FILE: test/helpers.ts
  type Options (line 9) | type Options = {
  function runValidations (line 42) | function runValidations(arr: any[], isValid: boolean) {
  function validationErrorWithMessages (line 57) | function validationErrorWithMessages(...errors: any[]) {
  function ensureSync (line 63) | function ensureSync(fn: () => Promise<any>) {

FILE: test/mixed.ts
  method test (line 470) | test() {
  method test (line 504) | test() {
  method test (line 531) | test() {

FILE: test/number.ts
  class MyNumber (line 8) | class MyNumber extends NumberSchema {
    method foo (line 9) | foo() {

FILE: test/object.ts
  type Nested (line 538) | type Nested = {
  type Nested (line 590) | type Nested = {

FILE: test/standardSchema.ts
  function verifyStandardSchema (line 16) | function verifyStandardSchema<Input, Output>(
  function getYupValidationError (line 29) | async function getYupValidationError(
  function expectValidationConsistency (line 45) | async function expectValidationConsistency(

FILE: test/string.ts
  function getErrorString (line 297) | function getErrorString(schema: AnySchema, value: string) {

FILE: test/types/types.ts
  type _a (line 23) | type _a = ResolveFlags<string | undefined, 'd'>;
  type _b (line 26) | type _b = ResolveFlags<string | undefined, 's'>;
  type _c (line 29) | type _c = ResolveFlags<string | undefined, 's' | 'd', string>;
  type _d (line 32) | type _d = ResolveFlags<string | undefined, 's' | '', string>;
  type _e (line 35) | type _e = ResolveFlags<string | undefined, SetFlag<'s', 'd'>, string>;
  type _f (line 38) | type _f = UnsetFlag<'d', 'd'>;
  type _f2 (line 41) | type _f2 = UnsetFlag<'d' | 's', 'd'>;
  type _f3 (line 44) | type _f3 = UnsetFlag<'', 'd'>;
  type _f4 (line 47) | type _f4 = SetFlag<'', 'd'>;
  type Person (line 767) | interface Person {
  type Employee (line 907) | type Employee = {
  type EmployeeWithPromotions (line 919) | type EmployeeWithPromotions = {
  type DocumentWithFullHistory (line 931) | type DocumentWithFullHistory = {
Condensed preview — 73 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (476K chars).
[
  {
    "path": ".babelrc.js",
    "chars": 415,
    "preview": "module.exports = (api) => ({\n  presets: [\n    [\n      'babel-preset-env-modules',\n      api.env() !== 'test'\n        ? {"
  },
  {
    "path": ".eslintignore",
    "chars": 23,
    "preview": ".eslintrc\n.eslintrc.js\n"
  },
  {
    "path": ".eslintrc",
    "chars": 707,
    "preview": "{\n  \"extends\": [\"jason\", \"prettier\"],\n  \"env\": {\n    \"browser\": true\n  },\n  \"parserOptions\": {\n    \"requireConfigFile\": "
  },
  {
    "path": ".gitattributes",
    "chars": 483,
    "preview": "# Auto detect text files and perform LF normalization\n* text=auto\n\n# Custom for Visual Studio\n*.cs     diff=csharp\n*.sln"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 782,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the b"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/question.md",
    "chars": 482,
    "preview": "---\nname: Question\nabout: General questions about yup or how it works\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n- Write a"
  },
  {
    "path": ".github/workflows/ci.yml",
    "chars": 399,
    "preview": "name: Test\non:\n  push:\n    branches: [master, next]\n  pull_request:\n    branches: [master, next]\njobs:\n  build:\n    runs"
  },
  {
    "path": ".gitignore",
    "chars": 1230,
    "preview": "# Logs\nlogs\n*.log\ndts/\n# Runtime data\npids\n*.pid\n*.seed\n\n# Directory for instrumented libs generated by jscoverage/JSCov"
  },
  {
    "path": ".nvmrc",
    "chars": 8,
    "preview": "22.19.0\n"
  },
  {
    "path": ".yarn/patches/@4c-rollout-npm-4.0.2-ab2b6d0bab.patch",
    "chars": 498,
    "preview": "diff --git a/command.js b/command.js\nindex 9608bffb4a52e5b8066e263d1286420ae92988bb..86ca58d70f315dae45fc739707dcff07a99"
  },
  {
    "path": ".yarnrc.yml",
    "chars": 25,
    "preview": "nodeLinker: node-modules\n"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 47944,
    "preview": "## [1.7.1](https://github.com/jquense/yup/compare/v1.7.0...v1.7.1) (2025-09-21)\n\n\n\n\n\n# [1.7.0](https://github.com/jquens"
  },
  {
    "path": "LICENSE.md",
    "chars": 1078,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2014 Jason Quense\n\nPermission is hereby granted, free of charge, to any person obta"
  },
  {
    "path": "README.md",
    "chars": 63139,
    "preview": "# Yup\n\nYup is a schema builder for runtime value parsing and validation. Define a schema, transform a value to match, as"
  },
  {
    "path": "docs/extending.md",
    "chars": 3278,
    "preview": "# Extending Schema\n\nFor simple cases where you want to reuse common schema configurations, creating\nand passing around i"
  },
  {
    "path": "package.json",
    "chars": 3035,
    "preview": "{\n  \"name\": \"yup\",\n  \"version\": \"1.7.1\",\n  \"description\": \"Dead simple Object schema validation\",\n  \"main\": \"lib/index.j"
  },
  {
    "path": "renovate.json",
    "chars": 82,
    "preview": "{\n  \"extends\": [\"github>4Catalyzer/renovate-config:library\", \":automergeMinor\"]\n}\n"
  },
  {
    "path": "rollup.config.js",
    "chars": 829,
    "preview": "import nodeResolve from '@rollup/plugin-node-resolve';\nimport babel from '@rollup/plugin-babel';\nimport dts from 'rollup"
  },
  {
    "path": "src/Condition.ts",
    "chars": 1962,
    "preview": "import isSchema from './util/isSchema';\nimport Reference from './Reference';\nimport type { ISchema } from './types';\n\nex"
  },
  {
    "path": "src/Lazy.ts",
    "chars": 5698,
    "preview": "import isSchema from './util/isSchema';\nimport type {\n  AnyObject,\n  ISchema,\n  ValidateOptions,\n  NestedTestConfig,\n  I"
  },
  {
    "path": "src/Reference.ts",
    "chars": 2280,
    "preview": "import { getter } from 'property-expr';\nimport type { SchemaRefDescription } from './schema';\n\nconst prefixes = {\n  cont"
  },
  {
    "path": "src/ValidationError.ts",
    "chars": 3011,
    "preview": "import printValue from './util/printValue';\nimport toArray from './util/toArray';\n\nlet strReg = /\\$\\{\\s*(\\w+)\\s*\\}/g;\n\nt"
  },
  {
    "path": "src/array.ts",
    "chars": 8555,
    "preview": "import isSchema from './util/isSchema';\nimport printValue from './util/printValue';\nimport parseJson from './util/parseJ"
  },
  {
    "path": "src/boolean.ts",
    "chars": 3144,
    "preview": "import Schema from './schema';\nimport type { AnyObject, DefaultThunk, Message } from './types';\nimport type {\n  Defined,"
  },
  {
    "path": "src/date.ts",
    "chars": 3901,
    "preview": "import { parseIsoDate } from './util/parseIsoDate';\nimport { date as locale } from './locale';\nimport Ref from './Refere"
  },
  {
    "path": "src/globals.d.ts",
    "chars": 1,
    "preview": "\n"
  },
  {
    "path": "src/index.ts",
    "chars": 3636,
    "preview": "import MixedSchema, {\n  create as mixedCreate,\n  MixedOptions,\n  TypeGuard,\n} from './mixed';\nimport BooleanSchema, { cr"
  },
  {
    "path": "src/locale.ts",
    "chars": 5363,
    "preview": "import printValue from './util/printValue';\nimport { Message } from './types';\nimport ValidationError from './Validation"
  },
  {
    "path": "src/mixed.ts",
    "chars": 2547,
    "preview": "import { AnyObject, DefaultThunk, Message } from './types';\nimport type {\n  Concat,\n  Defined,\n  Flags,\n  SetFlag,\n  May"
  },
  {
    "path": "src/number.ts",
    "chars": 5357,
    "preview": "import { number as locale } from './locale';\nimport isAbsent from './util/isAbsent';\nimport type { AnyObject, DefaultThu"
  },
  {
    "path": "src/object.ts",
    "chars": 15731,
    "preview": "// @ts-ignore\nimport { getter, normalizePath, join } from 'property-expr';\nimport { camelCase, snakeCase } from 'tiny-ca"
  },
  {
    "path": "src/schema.ts",
    "chars": 27557,
    "preview": "import { mixed as locale } from './locale';\nimport Condition, {\n  ConditionBuilder,\n  ConditionConfig,\n  ResolveOptions,"
  },
  {
    "path": "src/setLocale.ts",
    "chars": 339,
    "preview": "import locale, { LocaleObject } from './locale';\n\nexport type { LocaleObject };\n\nexport default function setLocale(custo"
  },
  {
    "path": "src/standardSchema.ts",
    "chars": 3854,
    "preview": "/**\n * Copied from @standard-schema/spec to avoid having a dependency on it.\n * https://github.com/standard-schema/stand"
  },
  {
    "path": "src/string.ts",
    "chars": 10962,
    "preview": "import { MixedLocale, mixed as mixedLocale, string as locale } from './locale';\nimport isAbsent from './util/isAbsent';\n"
  },
  {
    "path": "src/tuple.ts",
    "chars": 4940,
    "preview": "// @ts-ignore\n\nimport type {\n  AnyObject,\n  DefaultThunk,\n  InternalOptions,\n  ISchema,\n  Message,\n} from './types';\nimp"
  },
  {
    "path": "src/types.ts",
    "chars": 2987,
    "preview": "import type { ResolveOptions } from './Condition';\nimport type {\n  AnySchema,\n  CastOptionalityOptions,\n  CastOptions,\n "
  },
  {
    "path": "src/util/ReferenceSet.ts",
    "chars": 877,
    "preview": "import type { SchemaRefDescription } from '../schema';\nimport Reference from '../Reference';\n\nexport default class Refer"
  },
  {
    "path": "src/util/cloneDeep.ts",
    "chars": 1314,
    "preview": "// tweaked from https://github.com/Kelin2025/nanoclone/blob/0abeb7635bda9b68ef2277093f76dbe3bf3948e1/src/index.js\n// MIT"
  },
  {
    "path": "src/util/createValidation.ts",
    "chars": 5031,
    "preview": "import ValidationError from '../ValidationError';\nimport Ref from '../Reference';\nimport {\n  ValidateOptions,\n  Message,"
  },
  {
    "path": "src/util/isAbsent.ts",
    "chars": 101,
    "preview": "const isAbsent = (value: any): value is undefined | null => value == null;\n\nexport default isAbsent;\n"
  },
  {
    "path": "src/util/isSchema.ts",
    "chars": 148,
    "preview": "import type { ISchema } from '../types';\n\nconst isSchema = (obj: any): obj is ISchema<any> => obj && obj.__isYupSchema__"
  },
  {
    "path": "src/util/objectTypes.ts",
    "chars": 1864,
    "preview": "import type { Maybe, Optionals } from './types';\nimport type Reference from '../Reference';\nimport type { ISchema } from"
  },
  {
    "path": "src/util/parseIsoDate.ts",
    "chars": 2484,
    "preview": "/**\n * This file is a modified version of the file from the following repository:\n * Date.parse with progressive enhance"
  },
  {
    "path": "src/util/parseJson.ts",
    "chars": 376,
    "preview": "import type { AnySchema, TransformFunction } from '../types';\n\nconst parseJson: TransformFunction<any> = (value, _, sche"
  },
  {
    "path": "src/util/printValue.ts",
    "chars": 1598,
    "preview": "const toString = Object.prototype.toString;\nconst errorToString = Error.prototype.toString;\nconst regExpToString = RegEx"
  },
  {
    "path": "src/util/reach.ts",
    "chars": 2533,
    "preview": "import { forEach } from 'property-expr';\nimport type Reference from '../Reference';\nimport type { InferType, ISchema } f"
  },
  {
    "path": "src/util/sortByKeyOrder.ts",
    "chars": 445,
    "preview": "import ValidationError from '../ValidationError';\n\nfunction findIndex(arr: readonly string[], err: ValidationError) {\n  "
  },
  {
    "path": "src/util/sortFields.ts",
    "chars": 1014,
    "preview": "// @ts-expect-error\nimport toposort from 'toposort';\nimport { split } from 'property-expr';\n\nimport Ref from '../Referen"
  },
  {
    "path": "src/util/toArray.ts",
    "chars": 129,
    "preview": "export default function toArray<T>(value?: null | T | readonly T[]) {\n  return value == null ? [] : ([] as T[]).concat(v"
  },
  {
    "path": "src/util/types.ts",
    "chars": 1161,
    "preview": "export type IfAny<T, Y, N> = 0 extends 1 & T ? Y : N;\n\nexport type Maybe<T> = T | null | undefined;\n\nexport type Preserv"
  },
  {
    "path": "test/.eslintignore",
    "chars": 23,
    "preview": ".eslintrc\n.eslintrc.js\n"
  },
  {
    "path": "test/ValidationError.ts",
    "chars": 2031,
    "preview": "import { describe, it, expect } from 'vitest';\nimport ValidationError from '../src/ValidationError';\n\ndescribe('Validati"
  },
  {
    "path": "test/array.ts",
    "chars": 8072,
    "preview": "import { describe, it, expect, test, vi } from 'vitest';\nimport {\n  string,\n  number,\n  object,\n  array,\n  StringSchema,"
  },
  {
    "path": "test/bool.ts",
    "chars": 2156,
    "preview": "import { describe, it, expect } from 'vitest';\nimport { bool } from '../src';\nimport * as TestHelpers from './helpers';\n"
  },
  {
    "path": "test/date.ts",
    "chars": 4417,
    "preview": "import { describe, it, expect } from 'vitest';\nimport { ref, date } from '../src';\nimport * as TestHelpers from './helpe"
  },
  {
    "path": "test/helpers.ts",
    "chars": 1900,
    "preview": "import { describe, it, expect } from 'vitest';\nimport { ISchema } from '../src/types';\nimport printValue from '../src/ut"
  },
  {
    "path": "test/lazy.ts",
    "chars": 2243,
    "preview": "import { describe, it, expect, beforeEach, vi } from 'vitest';\nimport { lazy, object, mixed, ValidationError } from '../"
  },
  {
    "path": "test/mixed.ts",
    "chars": 34872,
    "preview": "import { describe, it, expect, beforeEach, vi } from 'vitest';\nimport {\n  array,\n  bool,\n  lazy,\n  mixed,\n  number,\n  ob"
  },
  {
    "path": "test/number.ts",
    "chars": 6539,
    "preview": "import { describe, it, expect } from 'vitest';\nimport * as TestHelpers from './helpers';\n\nimport { number, NumberSchema,"
  },
  {
    "path": "test/object.ts",
    "chars": 29746,
    "preview": "import { describe, it, expect, beforeEach, vi } from 'vitest';\nimport {\n  mixed,\n  string,\n  date,\n  number,\n  bool,\n  a"
  },
  {
    "path": "test/setLocale.ts",
    "chars": 1115,
    "preview": "import { describe, it, expect } from 'vitest';\nimport { setLocale } from '../src';\nimport locale from '../src/locale';\n\n"
  },
  {
    "path": "test/standardSchema.ts",
    "chars": 47638,
    "preview": "import { describe, it, expect, test, beforeAll } from 'vitest';\nimport {\n  string,\n  number,\n  array,\n  bool,\n  object,\n"
  },
  {
    "path": "test/string.ts",
    "chars": 12682,
    "preview": "import { describe, it, expect, assert } from 'vitest';\nimport * as TestHelpers from './helpers';\n\nimport {\n  string,\n  n"
  },
  {
    "path": "test/tsconfig.json",
    "chars": 185,
    "preview": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"noEmit\": true,\n    \"noImplicitAny\": true,\n    \"types\": [\""
  },
  {
    "path": "test/tuple.ts",
    "chars": 3989,
    "preview": "import { describe, it, expect, test } from 'vitest';\nimport { string, number, object, tuple, mixed } from '../src';\n\ndes"
  },
  {
    "path": "test/types/.eslintrc.js",
    "chars": 227,
    "preview": "module.exports = {\n  parser: '@typescript-eslint/parser',\n  parserOptions: {\n    tsconfigRootDir: __dirname,\n    project"
  },
  {
    "path": "test/types/types.ts",
    "chars": 26062,
    "preview": "/* eslint-disable @typescript-eslint/no-unused-expressions */\n/* eslint-disable no-unused-labels */\nimport {\n  array,\n  "
  },
  {
    "path": "test/util/parseIsoDate.ts",
    "chars": 9325,
    "preview": "/**\n * This file is a modified version of the test file from the following repository:\n * Date.parse with progressive en"
  },
  {
    "path": "test/yup.js",
    "chars": 6316,
    "preview": "import { describe, it, expect, test } from 'vitest';\nimport reach, { getIn } from '../src/util/reach';\n\nimport {\n  addMe"
  },
  {
    "path": "test-setup.mjs",
    "chars": 583,
    "preview": "import { beforeAll } from 'vitest';\nimport { SynchronousPromise } from 'synchronous-promise';\nimport * as yup from './sr"
  },
  {
    "path": "tsconfig.json",
    "chars": 148,
    "preview": "{\n  \"extends\": \"@4c/tsconfig/web\",\n  \"compilerOptions\": {\n    \"rootDir\": \"src\",\n    \"strictFunctionTypes\": true\n  },\n  \""
  },
  {
    "path": "vitest.config.ts",
    "chars": 691,
    "preview": "import { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n  test: {\n    environment: 'node',\n    setu"
  }
]

About this extraction

This page contains the full source code of the jquense/yup GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 73 files (445.6 KB), approximately 120.2k tokens, and a symbol index with 340 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!