From a0e1662e1de0229b6b2359dd800945d3edfe026b Mon Sep 17 00:00:00 2001 From: Simone Tesini Date: Fri, 1 Aug 2025 19:13:09 +0200 Subject: [PATCH 001/114] pull --- backend/src/app.py | 2 +- backend/src/room.py | 33 +++++++++++++++++++++++++++++++-- ruff.toml | 1 + 3 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 ruff.toml diff --git a/backend/src/app.py b/backend/src/app.py index 2484d2c..39ff440 100644 --- a/backend/src/app.py +++ b/backend/src/app.py @@ -1,6 +1,6 @@ from flask import Flask, Response, jsonify, request from flask_cors import CORS -from room import Room +from src.room import Room app = Flask(__name__) CORS(app) diff --git a/backend/src/room.py b/backend/src/room.py index bdf4026..a9ddd7c 100644 --- a/backend/src/room.py +++ b/backend/src/room.py @@ -2,7 +2,16 @@ from dataclasses import dataclass from song import Song -type UserScoredSong = tuple[Song, int] +USER_SCORE_WEIGHT = 0.7 +GENRE_WEIGHT = 0.1 +RANDOM_WEIGHT = 0.1 +RECENT_PENALTY = 0.5 +RECENT_COUNT = 10 + + +@dataclass +class UserScoredSong(Song): + user_score: int @dataclass @@ -14,5 +23,25 @@ class Room: tags: set[str] creative: bool - playlist: set[UserScoredSong] + songs: dict[str, UserScoredSong] history: list[Song] + + def rank_song( + self, + song: UserScoredSong, + ) -> float: + rank = 0.0 + song_items = self.songs.items() + + lowest_score = min(song_items, key=lambda item: item[1].user_score)[1].user_score + highest_score = min(song_items, key=lambda item: item[1].user_score)[1].user_score + + rank += translate(song.user_score, lowest_score, highest_score, 0.0, USER_SCORE_WEIGHT) + + last10items = self.history[-10:] + + return rank + + +def translate(value: float, in_min: float, in_max: float, out_min: float, out_max: float): + return (value - in_min) / (in_max - in_min) * (out_max - out_min) + out_min diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 0000000..d461c74 --- /dev/null +++ b/ruff.toml @@ -0,0 +1 @@ +line-length = 200 From adce5d7c65e745014002a6dfdf023decb0cd6e81 Mon Sep 17 00:00:00 2001 From: Leonardo Segala Date: Fri, 1 Aug 2025 19:13:12 +0200 Subject: [PATCH 002/114] ops --- backend/src/app.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/src/app.py b/backend/src/app.py index 8602d86..41ecd9d 100644 --- a/backend/src/app.py +++ b/backend/src/app.py @@ -1,7 +1,11 @@ from flask import Flask, request, Response, jsonify from flask_cors import CORS +import dotenv from .classes import Room +# from . import song_fetch + +dotenv.load_dotenv() app = Flask(__name__) CORS(app) From 4bb6254396e60f3aa2c22f36699e8a43777cb280 Mon Sep 17 00:00:00 2001 From: Simone Tesini Date: Fri, 1 Aug 2025 19:14:07 +0200 Subject: [PATCH 003/114] add basic ranking algo --- backend/src/room.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/room.py b/backend/src/room.py index a9ddd7c..4c405c0 100644 --- a/backend/src/room.py +++ b/backend/src/room.py @@ -38,7 +38,7 @@ class Room: rank += translate(song.user_score, lowest_score, highest_score, 0.0, USER_SCORE_WEIGHT) - last10items = self.history[-10:] + # last10items = self.history[-10:] return rank From 7f6a36439f54cc2be580a81b65b0206743807398 Mon Sep 17 00:00:00 2001 From: panzerotto Date: Fri, 1 Aug 2025 19:14:10 +0200 Subject: [PATCH 004/114] add db creation --- backend/src/app.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/src/app.py b/backend/src/app.py index 2484d2c..1326446 100644 --- a/backend/src/app.py +++ b/backend/src/app.py @@ -1,6 +1,7 @@ from flask import Flask, Response, jsonify, request from flask_cors import CORS from room import Room +from song import init_db app = Flask(__name__) CORS(app) @@ -38,4 +39,5 @@ def join(): if __name__ == "__main__": + init_db() app.run(debug=True) From 8bb582148df4a928e665ccd928468969bf3c2818 Mon Sep 17 00:00:00 2001 From: Leonardo Segala Date: Fri, 1 Aug 2025 19:16:20 +0200 Subject: [PATCH 005/114] Add song fetch test --- backend/Dockerfile | 4 +++ backend/requirements.txt | 2 ++ backend/src/app.py | 12 ++++---- backend/src/room.py | 2 +- backend/src/song.py | 2 +- backend/src/song_fetch.py | 63 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 76 insertions(+), 9 deletions(-) create mode 100644 backend/src/song_fetch.py diff --git a/backend/Dockerfile b/backend/Dockerfile index 56023cb..dc8f66f 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -2,6 +2,10 @@ FROM python:3.13.5-alpine WORKDIR /app +RUN apk update && apk add git + +RUN git clone --depth 1 'https://github.com/yt-dlp/yt-dlp.git' /yt-dlp + COPY requirements.txt ./ RUN pip install --no-cache-dir -r requirements.txt diff --git a/backend/requirements.txt b/backend/requirements.txt index 4b83363..7623d9f 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -1,2 +1,4 @@ Flask==3.1.0 flask-cors +dotenv +requests \ No newline at end of file diff --git a/backend/src/app.py b/backend/src/app.py index 665603a..3fadaf6 100644 --- a/backend/src/app.py +++ b/backend/src/app.py @@ -1,15 +1,13 @@ from flask import Flask, Response, jsonify, request from flask_cors import CORS -<<<<<<< HEAD -import dotenv -from .classes import Room -# from . import song_fetch +import dotenv +from .room import Room + +from . import song_fetch dotenv.load_dotenv() -======= -from room import Room ->>>>>>> refs/remotes/origin/main + app = Flask(__name__) CORS(app) diff --git a/backend/src/room.py b/backend/src/room.py index bdf4026..996a5a1 100644 --- a/backend/src/room.py +++ b/backend/src/room.py @@ -1,6 +1,6 @@ from dataclasses import dataclass -from song import Song +from .song import Song type UserScoredSong = tuple[Song, int] diff --git a/backend/src/song.py b/backend/src/song.py index 2260838..8570033 100644 --- a/backend/src/song.py +++ b/backend/src/song.py @@ -1,5 +1,5 @@ from dataclasses import dataclass -from connect import get_connection +from .connect import get_connection def init_db(): diff --git a/backend/src/song_fetch.py b/backend/src/song_fetch.py new file mode 100644 index 0000000..96288e9 --- /dev/null +++ b/backend/src/song_fetch.py @@ -0,0 +1,63 @@ +import requests +import urllib.parse +import os.path +import os +import sys + +sys.path.append("/yt-dlp") +import yt_dlp + + +def lastfm_search(query: str) -> tuple[str, str]: + response = requests.get( + url="https://ws.audioscrobbler.com/2.0/?method=track.search&format=json", + params={"limit": 5, "track": query, "api_key": os.environ["LASTFM_API_KEY"]}, + ) + + assert response.status_code == 200 + + track_info = response.json()["results"]["trackmatches"]["track"][0] + + return track_info["name"], track_info["artist"] + + +def lastfm_getinfo( + name: str, artist: str +) -> tuple[str, str, str, str, list[str]]: # ( id, image_id, tags ) + response = requests.get( + url="https://ws.audioscrobbler.com/2.0/?method=track.getInfo&format=json", + params={ + "track": name, + "artist": artist, + "api_key": os.environ["LASTFM_API_KEY"], + }, + ) + + track_info = response.json()["track"] + + image_url = urllib.parse.urlparse(track_info["album"]["image"][0]["#text"]) + + return ( + track_info["mbid"], + [t["name"] for t in track_info["toptags"]["tag"]], + os.path.splitext(os.path.basename(image_url.path))[0], + ) + + +print(yt_dlp, flush=True) + +# # def get_yt_mp3link(name: str, artist: str) -> str: ... +# # os.popen("/yt-dlp ") + +# # /yt-dlp/yt-dlp.sh "ytsearch1:Never gonna give you up" --get-url -f "ba" + +# import json + +# print(json.dumps(lastfm_getinfo(*lastfm_search("money")), indent=2)) +# exit(1) + + +# # def + + +# ## query ==> lastfm ==> list of songs ==> take first ==> request song info ==> get YT link ==> save in DB ==> From 036b64b51efc9188ec7bee86c825e6840c45ba97 Mon Sep 17 00:00:00 2001 From: Simone Tesini Date: Fri, 1 Aug 2025 19:31:47 +0200 Subject: [PATCH 006/114] theoretically finish the algorithm --- backend/src/room.py | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/backend/src/room.py b/backend/src/room.py index 92b0ee6..6332fd0 100644 --- a/backend/src/room.py +++ b/backend/src/room.py @@ -3,15 +3,14 @@ from dataclasses import dataclass from .song import Song USER_SCORE_WEIGHT = 0.7 -GENRE_WEIGHT = 0.1 +ARTIST_WEIGHT = 0.1 +TAG_WEIGHT = 0.1 RANDOM_WEIGHT = 0.1 RECENT_PENALTY = 0.5 RECENT_COUNT = 10 -@dataclass -class UserScoredSong(Song): - user_score: int +type UserScoredSong = tuple[Song, int] @dataclass @@ -26,19 +25,38 @@ class Room: songs: dict[str, UserScoredSong] history: list[Song] - def rank_song( - self, - song: UserScoredSong, - ) -> float: + def rank_song(self, song: Song, user_score: int) -> float: rank = 0.0 song_items = self.songs.items() - lowest_score = min(song_items, key=lambda item: item[1].user_score)[1].user_score - highest_score = min(song_items, key=lambda item: item[1].user_score)[1].user_score + lowest_score = min(song_items, key=lambda item: item[1][1])[1][1] + highest_score = min(song_items, key=lambda item: item[1][1])[1][1] - rank += translate(song.user_score, lowest_score, highest_score, 0.0, USER_SCORE_WEIGHT) + rank += translate(user_score, lowest_score, highest_score, 0.0, USER_SCORE_WEIGHT) - # last10items = self.history[-10:] + recent_songs = self.history[-RECENT_COUNT:] + + tag_counts = {} + artist_counts = {} + for song in recent_songs: + for tag in song.tags: + if tag not in tag_counts: + tag_counts[tag] = 0 + tag_counts[tag] += 1 + if song.artist not in artist_counts: + artist_counts[song.artist] = 0 + artist_counts[song.artist] += 1 + + tag_total = 0 + for tag in song.tags: + if tag in tag_counts: + tag_total += tag_counts[tag] + + rank += translate(tag_total, 0, RECENT_COUNT, 0, TAG_WEIGHT) + rank += translate(artist_counts[song.artist], 0, RECENT_COUNT, 0, ARTIST_WEIGHT) + + if song in recent_songs: + rank -= RECENT_PENALTY return rank From 41f6f5ba1af381a00722501a94361a5c388ae465 Mon Sep 17 00:00:00 2001 From: Simone Tesini Date: Fri, 1 Aug 2025 20:46:42 +0200 Subject: [PATCH 007/114] pull --- backend/src/room.py | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/room.py b/backend/src/room.py index 6332fd0..51b96e2 100644 --- a/backend/src/room.py +++ b/backend/src/room.py @@ -20,7 +20,6 @@ class Room: name: str pin: int | None tags: set[str] - creative: bool songs: dict[str, UserScoredSong] history: list[Song] From 248c9bc278d2e9491c7d5c0328fd835673374312 Mon Sep 17 00:00:00 2001 From: panzerotto Date: Fri, 1 Aug 2025 20:56:48 +0200 Subject: [PATCH 008/114] fix db creation --- backend/src/app.py | 2 +- backend/src/connect.py | 2 +- docker-compose.yml | 32 ++++++++++++++++---------------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/backend/src/app.py b/backend/src/app.py index 9dda54a..2df573d 100644 --- a/backend/src/app.py +++ b/backend/src/app.py @@ -45,6 +45,6 @@ def join(): return {"success": True, "ws": f"/ws/{room_id}"} +init_db() if __name__ == "__main__": - init_db() app.run(debug=True) diff --git a/backend/src/connect.py b/backend/src/connect.py index 12e53d8..962528c 100644 --- a/backend/src/connect.py +++ b/backend/src/connect.py @@ -2,5 +2,5 @@ import sqlite3 def get_connection(): - conn = sqlite3.connect("jukebox.db") + conn = sqlite3.connect(".data/jukebox.db") return conn diff --git a/docker-compose.yml b/docker-compose.yml index ea7e2ca..3b05616 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,18 +1,18 @@ services: - backend: - build: ./backend - ports: - - 5001:5000 - environment: - NODE_ENV: development - volumes: - - ./backend:/app - - ./.data/jukebox.sqlite3:/app/.data/jukebox.sqlite3 + backend: + build: ./backend + ports: + - 5001:5000 + environment: + NODE_ENV: development + volumes: + - ./backend:/app + - ./.data:/app/.data - frontend: - build: ./frontend - ports: - - 5173:5173 - volumes: - - ./frontend:/app - - /app/node_modules + frontend: + build: ./frontend + ports: + - 5173:5173 + volumes: + - ./frontend:/app + - /app/node_modules From 70f4b89d9e05ab608541ff4f8372c5296ca15ff3 Mon Sep 17 00:00:00 2001 From: Simone Tesini Date: Fri, 1 Aug 2025 20:59:09 +0200 Subject: [PATCH 009/114] pull --- backend/src/app.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/backend/src/app.py b/backend/src/app.py index 9dda54a..645b827 100644 --- a/backend/src/app.py +++ b/backend/src/app.py @@ -1,12 +1,10 @@ +import dotenv from flask import Flask, Response, jsonify, request from flask_cors import CORS -import dotenv from .room import Room from .song import init_db -from . import song_fetch - dotenv.load_dotenv() From ac7ef89b011e5a801acb27fe96fa91a9d308686d Mon Sep 17 00:00:00 2001 From: Mat12143 Date: Fri, 1 Aug 2025 21:10:03 +0200 Subject: [PATCH 010/114] feat: added queue slider & input field --- .../src/lib/components/QueueSlider.svelte | 29 + .../src/lib/components/SuggestionInput.svelte | 7 + .../src/lib/components/SuggestionList.svelte | 2 + frontend/src/lib/index.ts | 1 - frontend/src/lib/types.ts | 8 + frontend/src/routes/+layout.svelte | 4 +- frontend/src/routes/+page.svelte | 40 +- node_modules/.package-lock.json | 16 + node_modules/zod/LICENSE | 21 + node_modules/zod/README.md | 208 + node_modules/zod/index.cjs | 33 + node_modules/zod/index.d.cts | 4 + node_modules/zod/index.d.ts | 4 + node_modules/zod/index.js | 4 + node_modules/zod/locales/index.cjs | 17 + node_modules/zod/locales/index.d.cts | 1 + node_modules/zod/locales/index.d.ts | 1 + node_modules/zod/locales/index.js | 1 + node_modules/zod/mini/index.cjs | 17 + node_modules/zod/mini/index.d.cts | 1 + node_modules/zod/mini/index.d.ts | 1 + node_modules/zod/mini/index.js | 1 + node_modules/zod/package.json | 134 + node_modules/zod/src/index.ts | 4 + node_modules/zod/src/locales/index.ts | 1 + node_modules/zod/src/mini/index.ts | 1 + node_modules/zod/src/v3/ZodError.ts | 330 ++ .../zod/src/v3/benchmarks/datetime.ts | 58 + .../src/v3/benchmarks/discriminatedUnion.ts | 80 + node_modules/zod/src/v3/benchmarks/index.ts | 59 + node_modules/zod/src/v3/benchmarks/ipv4.ts | 57 + node_modules/zod/src/v3/benchmarks/object.ts | 69 + .../zod/src/v3/benchmarks/primitives.ts | 162 + .../zod/src/v3/benchmarks/realworld.ts | 63 + node_modules/zod/src/v3/benchmarks/string.ts | 55 + node_modules/zod/src/v3/benchmarks/union.ts | 80 + node_modules/zod/src/v3/errors.ts | 13 + node_modules/zod/src/v3/external.ts | 6 + node_modules/zod/src/v3/helpers/enumUtil.ts | 17 + node_modules/zod/src/v3/helpers/errorUtil.ts | 8 + node_modules/zod/src/v3/helpers/parseUtil.ts | 176 + .../zod/src/v3/helpers/partialUtil.ts | 34 + .../zod/src/v3/helpers/typeAliases.ts | 2 + node_modules/zod/src/v3/helpers/util.ts | 224 + node_modules/zod/src/v3/index.ts | 4 + node_modules/zod/src/v3/locales/en.ts | 124 + node_modules/zod/src/v3/standard-schema.ts | 113 + node_modules/zod/src/v3/tests/Mocker.ts | 54 + .../zod/src/v3/tests/all-errors.test.ts | 157 + .../zod/src/v3/tests/anyunknown.test.ts | 28 + node_modules/zod/src/v3/tests/array.test.ts | 71 + .../zod/src/v3/tests/async-parsing.test.ts | 388 ++ .../src/v3/tests/async-refinements.test.ts | 46 + node_modules/zod/src/v3/tests/base.test.ts | 29 + node_modules/zod/src/v3/tests/bigint.test.ts | 55 + node_modules/zod/src/v3/tests/branded.test.ts | 53 + node_modules/zod/src/v3/tests/catch.test.ts | 220 + node_modules/zod/src/v3/tests/coerce.test.ts | 133 + node_modules/zod/src/v3/tests/complex.test.ts | 56 + node_modules/zod/src/v3/tests/custom.test.ts | 31 + node_modules/zod/src/v3/tests/date.test.ts | 32 + .../zod/src/v3/tests/deepmasking.test.ts | 186 + node_modules/zod/src/v3/tests/default.test.ts | 112 + .../zod/src/v3/tests/description.test.ts | 33 + .../src/v3/tests/discriminated-unions.test.ts | 315 + node_modules/zod/src/v3/tests/enum.test.ts | 80 + node_modules/zod/src/v3/tests/error.test.ts | 551 ++ .../zod/src/v3/tests/firstparty.test.ts | 87 + .../v3/tests/firstpartyschematypes.test.ts | 21 + .../zod/src/v3/tests/function.test.ts | 257 + .../zod/src/v3/tests/generics.test.ts | 48 + .../zod/src/v3/tests/instanceof.test.ts | 37 + .../zod/src/v3/tests/intersection.test.ts | 110 + .../src/v3/tests/language-server.source.ts | 76 + .../zod/src/v3/tests/language-server.test.ts | 207 + node_modules/zod/src/v3/tests/literal.test.ts | 36 + node_modules/zod/src/v3/tests/map.test.ts | 110 + node_modules/zod/src/v3/tests/masking.test.ts | 4 + node_modules/zod/src/v3/tests/mocker.test.ts | 19 + node_modules/zod/src/v3/tests/nan.test.ts | 21 + .../zod/src/v3/tests/nativeEnum.test.ts | 87 + .../zod/src/v3/tests/nullable.test.ts | 42 + node_modules/zod/src/v3/tests/number.test.ts | 176 + .../src/v3/tests/object-augmentation.test.ts | 29 + .../src/v3/tests/object-in-es5-env.test.ts | 29 + node_modules/zod/src/v3/tests/object.test.ts | 434 ++ .../zod/src/v3/tests/optional.test.ts | 42 + .../zod/src/v3/tests/parseUtil.test.ts | 23 + node_modules/zod/src/v3/tests/parser.test.ts | 41 + .../zod/src/v3/tests/partials.test.ts | 243 + .../zod/src/v3/tests/pickomit.test.ts | 111 + .../zod/src/v3/tests/pipeline.test.ts | 29 + .../zod/src/v3/tests/preprocess.test.ts | 186 + .../zod/src/v3/tests/primitive.test.ts | 440 ++ node_modules/zod/src/v3/tests/promise.test.ts | 90 + .../zod/src/v3/tests/readonly.test.ts | 194 + node_modules/zod/src/v3/tests/record.test.ts | 171 + .../zod/src/v3/tests/recursive.test.ts | 197 + node_modules/zod/src/v3/tests/refine.test.ts | 313 + .../zod/src/v3/tests/safeparse.test.ts | 27 + node_modules/zod/src/v3/tests/set.test.ts | 142 + .../zod/src/v3/tests/standard-schema.test.ts | 83 + node_modules/zod/src/v3/tests/string.test.ts | 916 +++ .../zod/src/v3/tests/transformer.test.ts | 233 + node_modules/zod/src/v3/tests/tuple.test.ts | 90 + node_modules/zod/src/v3/tests/unions.test.ts | 57 + .../zod/src/v3/tests/validations.test.ts | 133 + node_modules/zod/src/v3/tests/void.test.ts | 15 + node_modules/zod/src/v3/types.ts | 5138 +++++++++++++++++ node_modules/zod/src/v4-mini/index.ts | 1 + node_modules/zod/src/v4/classic/checks.ts | 31 + node_modules/zod/src/v4/classic/coerce.ts | 27 + node_modules/zod/src/v4/classic/compat.ts | 70 + node_modules/zod/src/v4/classic/errors.ts | 82 + node_modules/zod/src/v4/classic/external.ts | 50 + node_modules/zod/src/v4/classic/index.ts | 5 + node_modules/zod/src/v4/classic/iso.ts | 90 + node_modules/zod/src/v4/classic/parse.ts | 33 + node_modules/zod/src/v4/classic/schemas.ts | 2031 +++++++ .../src/v4/classic/tests/anyunknown.test.ts | 26 + .../zod/src/v4/classic/tests/array.test.ts | 264 + .../v4/classic/tests/assignability.test.ts | 210 + .../v4/classic/tests/async-parsing.test.ts | 381 ++ .../classic/tests/async-refinements.test.ts | 68 + .../zod/src/v4/classic/tests/base.test.ts | 7 + .../zod/src/v4/classic/tests/bigint.test.ts | 54 + .../zod/src/v4/classic/tests/brand.test.ts | 63 + .../zod/src/v4/classic/tests/catch.test.ts | 251 + .../zod/src/v4/classic/tests/coalesce.test.ts | 20 + .../zod/src/v4/classic/tests/coerce.test.ts | 160 + .../v4/classic/tests/continuability.test.ts | 352 ++ .../zod/src/v4/classic/tests/custom.test.ts | 40 + .../zod/src/v4/classic/tests/date.test.ts | 31 + .../zod/src/v4/classic/tests/datetime.test.ts | 302 + .../zod/src/v4/classic/tests/default.test.ts | 313 + .../src/v4/classic/tests/description.test.ts | 32 + .../tests/discriminated-unions.test.ts | 661 +++ .../zod/src/v4/classic/tests/enum.test.ts | 285 + .../src/v4/classic/tests/error-utils.test.ts | 595 ++ .../zod/src/v4/classic/tests/error.test.ts | 711 +++ .../zod/src/v4/classic/tests/file.test.ts | 94 + .../src/v4/classic/tests/firstparty.test.ts | 175 + .../zod/src/v4/classic/tests/function.test.ts | 268 + .../zod/src/v4/classic/tests/generics.test.ts | 72 + .../zod/src/v4/classic/tests/index.test.ts | 829 +++ .../src/v4/classic/tests/instanceof.test.ts | 34 + .../src/v4/classic/tests/intersection.test.ts | 171 + .../zod/src/v4/classic/tests/json.test.ts | 108 + .../zod/src/v4/classic/tests/lazy.test.ts | 227 + .../zod/src/v4/classic/tests/literal.test.ts | 117 + .../zod/src/v4/classic/tests/map.test.ts | 196 + .../zod/src/v4/classic/tests/nan.test.ts | 21 + .../v4/classic/tests/nested-refine.test.ts | 168 + .../src/v4/classic/tests/nonoptional.test.ts | 86 + .../zod/src/v4/classic/tests/nullable.test.ts | 22 + .../zod/src/v4/classic/tests/number.test.ts | 270 + .../zod/src/v4/classic/tests/object.test.ts | 563 ++ .../zod/src/v4/classic/tests/optional.test.ts | 136 + .../zod/src/v4/classic/tests/partial.test.ts | 340 ++ .../zod/src/v4/classic/tests/pickomit.test.ts | 127 + .../zod/src/v4/classic/tests/pipe.test.ts | 81 + .../zod/src/v4/classic/tests/prefault.test.ts | 37 + .../src/v4/classic/tests/preprocess.test.ts | 287 + .../src/v4/classic/tests/primitive.test.ts | 175 + .../zod/src/v4/classic/tests/promise.test.ts | 81 + .../src/v4/classic/tests/prototypes.test.ts | 23 + .../zod/src/v4/classic/tests/readonly.test.ts | 252 + .../zod/src/v4/classic/tests/record.test.ts | 356 ++ .../v4/classic/tests/recursive-types.test.ts | 477 ++ .../zod/src/v4/classic/tests/refine.test.ts | 532 ++ .../src/v4/classic/tests/registries.test.ts | 204 + .../zod/src/v4/classic/tests/set.test.ts | 179 + .../v4/classic/tests/standard-schema.test.ts | 57 + .../v4/classic/tests/string-formats.test.ts | 109 + .../zod/src/v4/classic/tests/string.test.ts | 996 ++++ .../src/v4/classic/tests/stringbool.test.ts | 66 + .../v4/classic/tests/template-literal.test.ts | 761 +++ .../v4/classic/tests/to-json-schema.test.ts | 2341 ++++++++ .../src/v4/classic/tests/transform.test.ts | 354 ++ .../zod/src/v4/classic/tests/tuple.test.ts | 163 + .../zod/src/v4/classic/tests/union.test.ts | 181 + .../src/v4/classic/tests/validations.test.ts | 283 + .../zod/src/v4/classic/tests/void.test.ts | 12 + node_modules/zod/src/v4/core/api.ts | 1628 ++++++ node_modules/zod/src/v4/core/checks.ts | 1285 +++++ node_modules/zod/src/v4/core/config.ts | 15 + node_modules/zod/src/v4/core/core.ts | 134 + node_modules/zod/src/v4/core/doc.ts | 44 + node_modules/zod/src/v4/core/errors.ts | 423 ++ node_modules/zod/src/v4/core/function.ts | 176 + node_modules/zod/src/v4/core/index.ts | 15 + node_modules/zod/src/v4/core/json-schema.ts | 146 + node_modules/zod/src/v4/core/parse.ts | 94 + node_modules/zod/src/v4/core/regexes.ts | 138 + node_modules/zod/src/v4/core/registries.ts | 97 + node_modules/zod/src/v4/core/schemas.ts | 3900 +++++++++++++ .../zod/src/v4/core/standard-schema.ts | 64 + .../zod/src/v4/core/tests/extend.test.ts | 18 + .../zod/src/v4/core/tests/index.test.ts | 46 + .../zod/src/v4/core/tests/locales/be.test.ts | 124 + .../zod/src/v4/core/tests/locales/en.test.ts | 22 + .../zod/src/v4/core/tests/locales/ru.test.ts | 128 + .../zod/src/v4/core/tests/locales/tr.test.ts | 69 + .../zod/src/v4/core/to-json-schema.ts | 1004 ++++ node_modules/zod/src/v4/core/util.ts | 827 +++ node_modules/zod/src/v4/core/versions.ts | 5 + node_modules/zod/src/v4/core/zsf.ts | 323 ++ node_modules/zod/src/v4/index.ts | 4 + node_modules/zod/src/v4/locales/ar.ts | 125 + node_modules/zod/src/v4/locales/az.ts | 121 + node_modules/zod/src/v4/locales/be.ts | 184 + node_modules/zod/src/v4/locales/bg.ts | 136 + node_modules/zod/src/v4/locales/ca.ts | 127 + node_modules/zod/src/v4/locales/cs.ts | 142 + node_modules/zod/src/v4/locales/da.ts | 141 + node_modules/zod/src/v4/locales/de.ts | 124 + node_modules/zod/src/v4/locales/en.ts | 127 + node_modules/zod/src/v4/locales/eo.ts | 125 + node_modules/zod/src/v4/locales/es.ts | 125 + node_modules/zod/src/v4/locales/fa.ts | 134 + node_modules/zod/src/v4/locales/fi.ts | 131 + node_modules/zod/src/v4/locales/fr-CA.ts | 126 + node_modules/zod/src/v4/locales/fr.ts | 124 + node_modules/zod/src/v4/locales/he.ts | 125 + node_modules/zod/src/v4/locales/hu.ts | 126 + node_modules/zod/src/v4/locales/id.ts | 125 + node_modules/zod/src/v4/locales/index.ts | 42 + node_modules/zod/src/v4/locales/is.ts | 127 + node_modules/zod/src/v4/locales/it.ts | 125 + node_modules/zod/src/v4/locales/ja.ts | 122 + node_modules/zod/src/v4/locales/kh.ts | 126 + node_modules/zod/src/v4/locales/ko.ts | 131 + node_modules/zod/src/v4/locales/mk.ts | 127 + node_modules/zod/src/v4/locales/ms.ts | 124 + node_modules/zod/src/v4/locales/nl.ts | 126 + node_modules/zod/src/v4/locales/no.ts | 124 + node_modules/zod/src/v4/locales/ota.ts | 125 + node_modules/zod/src/v4/locales/pl.ts | 126 + node_modules/zod/src/v4/locales/ps.ts | 133 + node_modules/zod/src/v4/locales/pt.ts | 123 + node_modules/zod/src/v4/locales/ru.ts | 184 + node_modules/zod/src/v4/locales/sl.ts | 126 + node_modules/zod/src/v4/locales/sv.ts | 127 + node_modules/zod/src/v4/locales/ta.ts | 125 + node_modules/zod/src/v4/locales/th.ts | 126 + node_modules/zod/src/v4/locales/tr.ts | 121 + node_modules/zod/src/v4/locales/ua.ts | 126 + node_modules/zod/src/v4/locales/ur.ts | 126 + node_modules/zod/src/v4/locales/vi.ts | 125 + node_modules/zod/src/v4/locales/yo.ts | 131 + node_modules/zod/src/v4/locales/zh-CN.ts | 123 + node_modules/zod/src/v4/locales/zh-TW.ts | 125 + node_modules/zod/src/v4/mini/checks.ts | 32 + node_modules/zod/src/v4/mini/coerce.ts | 22 + node_modules/zod/src/v4/mini/external.ts | 40 + node_modules/zod/src/v4/mini/index.ts | 3 + node_modules/zod/src/v4/mini/iso.ts | 62 + node_modules/zod/src/v4/mini/parse.ts | 1 + node_modules/zod/src/v4/mini/schemas.ts | 1592 +++++ .../src/v4/mini/tests/assignability.test.ts | 129 + .../zod/src/v4/mini/tests/brand.test.ts | 51 + .../zod/src/v4/mini/tests/checks.test.ts | 144 + .../zod/src/v4/mini/tests/computed.test.ts | 36 + .../zod/src/v4/mini/tests/error.test.ts | 22 + .../zod/src/v4/mini/tests/functions.test.ts | 43 + .../zod/src/v4/mini/tests/index.test.ts | 871 +++ .../zod/src/v4/mini/tests/number.test.ts | 95 + .../zod/src/v4/mini/tests/object.test.ts | 185 + .../zod/src/v4/mini/tests/prototypes.test.ts | 43 + .../src/v4/mini/tests/recursive-types.test.ts | 275 + .../zod/src/v4/mini/tests/string.test.ts | 299 + node_modules/zod/v3/ZodError.cjs | 138 + node_modules/zod/v3/ZodError.d.cts | 164 + node_modules/zod/v3/ZodError.d.ts | 164 + node_modules/zod/v3/ZodError.js | 133 + node_modules/zod/v3/errors.cjs | 17 + node_modules/zod/v3/errors.d.cts | 5 + node_modules/zod/v3/errors.d.ts | 5 + node_modules/zod/v3/errors.js | 9 + node_modules/zod/v3/external.cjs | 22 + node_modules/zod/v3/external.d.cts | 6 + node_modules/zod/v3/external.d.ts | 6 + node_modules/zod/v3/external.js | 6 + node_modules/zod/v3/helpers/enumUtil.cjs | 2 + node_modules/zod/v3/helpers/enumUtil.d.cts | 8 + node_modules/zod/v3/helpers/enumUtil.d.ts | 8 + node_modules/zod/v3/helpers/enumUtil.js | 1 + node_modules/zod/v3/helpers/errorUtil.cjs | 9 + node_modules/zod/v3/helpers/errorUtil.d.cts | 9 + node_modules/zod/v3/helpers/errorUtil.d.ts | 9 + node_modules/zod/v3/helpers/errorUtil.js | 6 + node_modules/zod/v3/helpers/parseUtil.cjs | 124 + node_modules/zod/v3/helpers/parseUtil.d.cts | 78 + node_modules/zod/v3/helpers/parseUtil.d.ts | 78 + node_modules/zod/v3/helpers/parseUtil.js | 109 + node_modules/zod/v3/helpers/partialUtil.cjs | 2 + node_modules/zod/v3/helpers/partialUtil.d.cts | 8 + node_modules/zod/v3/helpers/partialUtil.d.ts | 8 + node_modules/zod/v3/helpers/partialUtil.js | 1 + node_modules/zod/v3/helpers/typeAliases.cjs | 2 + node_modules/zod/v3/helpers/typeAliases.d.cts | 2 + node_modules/zod/v3/helpers/typeAliases.d.ts | 2 + node_modules/zod/v3/helpers/typeAliases.js | 1 + node_modules/zod/v3/helpers/util.cjs | 137 + node_modules/zod/v3/helpers/util.d.cts | 85 + node_modules/zod/v3/helpers/util.d.ts | 85 + node_modules/zod/v3/helpers/util.js | 133 + node_modules/zod/v3/index.cjs | 33 + node_modules/zod/v3/index.d.cts | 4 + node_modules/zod/v3/index.d.ts | 4 + node_modules/zod/v3/index.js | 4 + node_modules/zod/v3/locales/en.cjs | 112 + node_modules/zod/v3/locales/en.d.cts | 3 + node_modules/zod/v3/locales/en.d.ts | 3 + node_modules/zod/v3/locales/en.js | 109 + node_modules/zod/v3/standard-schema.cjs | 2 + node_modules/zod/v3/standard-schema.d.cts | 102 + node_modules/zod/v3/standard-schema.d.ts | 102 + node_modules/zod/v3/standard-schema.js | 1 + node_modules/zod/v3/types.cjs | 3777 ++++++++++++ node_modules/zod/v3/types.d.cts | 1034 ++++ node_modules/zod/v3/types.d.ts | 1034 ++++ node_modules/zod/v3/types.js | 3695 ++++++++++++ node_modules/zod/v4-mini/index.cjs | 17 + node_modules/zod/v4-mini/index.d.cts | 1 + node_modules/zod/v4-mini/index.d.ts | 1 + node_modules/zod/v4-mini/index.js | 1 + node_modules/zod/v4/classic/checks.cjs | 32 + node_modules/zod/v4/classic/checks.d.cts | 1 + node_modules/zod/v4/classic/checks.d.ts | 1 + node_modules/zod/v4/classic/checks.js | 1 + node_modules/zod/v4/classic/coerce.cjs | 47 + node_modules/zod/v4/classic/coerce.d.cts | 17 + node_modules/zod/v4/classic/coerce.d.ts | 17 + node_modules/zod/v4/classic/coerce.js | 17 + node_modules/zod/v4/classic/compat.cjs | 61 + node_modules/zod/v4/classic/compat.d.cts | 50 + node_modules/zod/v4/classic/compat.d.ts | 50 + node_modules/zod/v4/classic/compat.js | 31 + node_modules/zod/v4/classic/errors.cjs | 74 + node_modules/zod/v4/classic/errors.d.cts | 30 + node_modules/zod/v4/classic/errors.d.ts | 30 + node_modules/zod/v4/classic/errors.js | 48 + node_modules/zod/v4/classic/external.cjs | 70 + node_modules/zod/v4/classic/external.d.cts | 13 + node_modules/zod/v4/classic/external.d.ts | 13 + node_modules/zod/v4/classic/external.js | 18 + node_modules/zod/v4/classic/index.cjs | 33 + node_modules/zod/v4/classic/index.d.cts | 4 + node_modules/zod/v4/classic/index.d.ts | 4 + node_modules/zod/v4/classic/index.js | 4 + node_modules/zod/v4/classic/iso.cjs | 60 + node_modules/zod/v4/classic/iso.d.cts | 22 + node_modules/zod/v4/classic/iso.d.ts | 22 + node_modules/zod/v4/classic/iso.js | 30 + node_modules/zod/v4/classic/parse.cjs | 32 + node_modules/zod/v4/classic/parse.d.cts | 23 + node_modules/zod/v4/classic/parse.d.ts | 23 + node_modules/zod/v4/classic/parse.js | 6 + node_modules/zod/v4/classic/schemas.cjs | 1096 ++++ node_modules/zod/v4/classic/schemas.d.cts | 619 ++ node_modules/zod/v4/classic/schemas.d.ts | 619 ++ node_modules/zod/v4/classic/schemas.js | 992 ++++ node_modules/zod/v4/core/api.cjs | 1065 ++++ node_modules/zod/v4/core/api.d.cts | 296 + node_modules/zod/v4/core/api.d.ts | 296 + node_modules/zod/v4/core/api.js | 930 +++ node_modules/zod/v4/core/checks.cjs | 593 ++ node_modules/zod/v4/core/checks.d.cts | 278 + node_modules/zod/v4/core/checks.d.ts | 278 + node_modules/zod/v4/core/checks.js | 567 ++ node_modules/zod/v4/core/core.cjs | 67 + node_modules/zod/v4/core/core.d.cts | 49 + node_modules/zod/v4/core/core.d.ts | 49 + node_modules/zod/v4/core/core.js | 61 + node_modules/zod/v4/core/doc.cjs | 39 + node_modules/zod/v4/core/doc.d.cts | 14 + node_modules/zod/v4/core/doc.d.ts | 14 + node_modules/zod/v4/core/doc.js | 35 + node_modules/zod/v4/core/errors.cjs | 221 + node_modules/zod/v4/core/errors.d.cts | 210 + node_modules/zod/v4/core/errors.d.ts | 210 + node_modules/zod/v4/core/errors.js | 190 + node_modules/zod/v4/core/function.cjs | 102 + node_modules/zod/v4/core/function.d.cts | 52 + node_modules/zod/v4/core/function.d.ts | 52 + node_modules/zod/v4/core/function.js | 75 + node_modules/zod/v4/core/index.cjs | 44 + node_modules/zod/v4/core/index.d.cts | 15 + node_modules/zod/v4/core/index.d.ts | 15 + node_modules/zod/v4/core/index.js | 15 + node_modules/zod/v4/core/json-schema.cjs | 2 + node_modules/zod/v4/core/json-schema.d.cts | 87 + node_modules/zod/v4/core/json-schema.d.ts | 87 + node_modules/zod/v4/core/json-schema.js | 1 + node_modules/zod/v4/core/parse.cjs | 87 + node_modules/zod/v4/core/parse.d.cts | 25 + node_modules/zod/v4/core/parse.d.ts | 25 + node_modules/zod/v4/core/parse.js | 57 + node_modules/zod/v4/core/regexes.cjs | 104 + node_modules/zod/v4/core/regexes.d.cts | 62 + node_modules/zod/v4/core/regexes.d.ts | 62 + node_modules/zod/v4/core/regexes.js | 96 + node_modules/zod/v4/core/registries.cjs | 57 + node_modules/zod/v4/core/registries.d.cts | 35 + node_modules/zod/v4/core/registries.d.ts | 35 + node_modules/zod/v4/core/registries.js | 52 + node_modules/zod/v4/core/schemas.cjs | 1734 ++++++ node_modules/zod/v4/core/schemas.d.cts | 1055 ++++ node_modules/zod/v4/core/schemas.d.ts | 1055 ++++ node_modules/zod/v4/core/schemas.js | 1703 ++++++ node_modules/zod/v4/core/standard-schema.cjs | 2 + .../zod/v4/core/standard-schema.d.cts | 55 + node_modules/zod/v4/core/standard-schema.d.ts | 55 + node_modules/zod/v4/core/standard-schema.js | 1 + node_modules/zod/v4/core/to-json-schema.cjs | 882 +++ node_modules/zod/v4/core/to-json-schema.d.cts | 89 + node_modules/zod/v4/core/to-json-schema.d.ts | 89 + node_modules/zod/v4/core/to-json-schema.js | 877 +++ node_modules/zod/v4/core/util.cjs | 577 ++ node_modules/zod/v4/core/util.d.cts | 185 + node_modules/zod/v4/core/util.d.ts | 185 + node_modules/zod/v4/core/util.js | 529 ++ node_modules/zod/v4/core/versions.cjs | 8 + node_modules/zod/v4/core/versions.d.cts | 5 + node_modules/zod/v4/core/versions.d.ts | 5 + node_modules/zod/v4/core/versions.js | 5 + node_modules/zod/v4/index.cjs | 22 + node_modules/zod/v4/index.d.cts | 3 + node_modules/zod/v4/index.d.ts | 3 + node_modules/zod/v4/index.js | 3 + node_modules/zod/v4/locales/ar.cjs | 143 + node_modules/zod/v4/locales/ar.d.cts | 5 + node_modules/zod/v4/locales/ar.d.ts | 4 + node_modules/zod/v4/locales/ar.js | 116 + node_modules/zod/v4/locales/az.cjs | 142 + node_modules/zod/v4/locales/az.d.cts | 5 + node_modules/zod/v4/locales/az.d.ts | 4 + node_modules/zod/v4/locales/az.js | 115 + node_modules/zod/v4/locales/be.cjs | 191 + node_modules/zod/v4/locales/be.d.cts | 5 + node_modules/zod/v4/locales/be.d.ts | 4 + node_modules/zod/v4/locales/be.js | 164 + node_modules/zod/v4/locales/bg.cjs | 156 + node_modules/zod/v4/locales/bg.d.cts | 5 + node_modules/zod/v4/locales/bg.d.ts | 5 + node_modules/zod/v4/locales/bg.js | 128 + node_modules/zod/v4/locales/ca.cjs | 145 + node_modules/zod/v4/locales/ca.d.cts | 5 + node_modules/zod/v4/locales/ca.d.ts | 4 + node_modules/zod/v4/locales/ca.js | 118 + node_modules/zod/v4/locales/cs.cjs | 162 + node_modules/zod/v4/locales/cs.d.cts | 5 + node_modules/zod/v4/locales/cs.d.ts | 4 + node_modules/zod/v4/locales/cs.js | 135 + node_modules/zod/v4/locales/da.cjs | 158 + node_modules/zod/v4/locales/da.d.cts | 5 + node_modules/zod/v4/locales/da.d.ts | 4 + node_modules/zod/v4/locales/da.js | 131 + node_modules/zod/v4/locales/de.cjs | 143 + node_modules/zod/v4/locales/de.d.cts | 5 + node_modules/zod/v4/locales/de.d.ts | 4 + node_modules/zod/v4/locales/de.js | 116 + node_modules/zod/v4/locales/en.cjs | 145 + node_modules/zod/v4/locales/en.d.cts | 5 + node_modules/zod/v4/locales/en.d.ts | 5 + node_modules/zod/v4/locales/en.js | 117 + node_modules/zod/v4/locales/eo.cjs | 144 + node_modules/zod/v4/locales/eo.d.cts | 5 + node_modules/zod/v4/locales/eo.d.ts | 5 + node_modules/zod/v4/locales/eo.js | 116 + node_modules/zod/v4/locales/es.cjs | 144 + node_modules/zod/v4/locales/es.d.cts | 5 + node_modules/zod/v4/locales/es.d.ts | 4 + node_modules/zod/v4/locales/es.js | 117 + node_modules/zod/v4/locales/fa.cjs | 149 + node_modules/zod/v4/locales/fa.d.cts | 5 + node_modules/zod/v4/locales/fa.d.ts | 4 + node_modules/zod/v4/locales/fa.js | 122 + node_modules/zod/v4/locales/fi.cjs | 149 + node_modules/zod/v4/locales/fi.d.cts | 5 + node_modules/zod/v4/locales/fi.d.ts | 4 + node_modules/zod/v4/locales/fi.js | 122 + node_modules/zod/v4/locales/fr-CA.cjs | 144 + node_modules/zod/v4/locales/fr-CA.d.cts | 5 + node_modules/zod/v4/locales/fr-CA.d.ts | 4 + node_modules/zod/v4/locales/fr-CA.js | 117 + node_modules/zod/v4/locales/fr.cjs | 143 + node_modules/zod/v4/locales/fr.d.cts | 5 + node_modules/zod/v4/locales/fr.d.ts | 4 + node_modules/zod/v4/locales/fr.js | 116 + node_modules/zod/v4/locales/he.cjs | 144 + node_modules/zod/v4/locales/he.d.cts | 5 + node_modules/zod/v4/locales/he.d.ts | 4 + node_modules/zod/v4/locales/he.js | 117 + node_modules/zod/v4/locales/hu.cjs | 144 + node_modules/zod/v4/locales/hu.d.cts | 5 + node_modules/zod/v4/locales/hu.d.ts | 4 + node_modules/zod/v4/locales/hu.js | 117 + node_modules/zod/v4/locales/id.cjs | 143 + node_modules/zod/v4/locales/id.d.cts | 5 + node_modules/zod/v4/locales/id.d.ts | 4 + node_modules/zod/v4/locales/id.js | 116 + node_modules/zod/v4/locales/index.cjs | 90 + node_modules/zod/v4/locales/index.d.cts | 42 + node_modules/zod/v4/locales/index.d.ts | 42 + node_modules/zod/v4/locales/index.js | 42 + node_modules/zod/v4/locales/is.cjs | 145 + node_modules/zod/v4/locales/is.d.cts | 5 + node_modules/zod/v4/locales/is.d.ts | 5 + node_modules/zod/v4/locales/is.js | 117 + node_modules/zod/v4/locales/it.cjs | 144 + node_modules/zod/v4/locales/it.d.cts | 5 + node_modules/zod/v4/locales/it.d.ts | 4 + node_modules/zod/v4/locales/it.js | 117 + node_modules/zod/v4/locales/ja.cjs | 142 + node_modules/zod/v4/locales/ja.d.cts | 5 + node_modules/zod/v4/locales/ja.d.ts | 4 + node_modules/zod/v4/locales/ja.js | 115 + node_modules/zod/v4/locales/kh.cjs | 144 + node_modules/zod/v4/locales/kh.d.cts | 5 + node_modules/zod/v4/locales/kh.d.ts | 4 + node_modules/zod/v4/locales/kh.js | 117 + node_modules/zod/v4/locales/ko.cjs | 148 + node_modules/zod/v4/locales/ko.d.cts | 5 + node_modules/zod/v4/locales/ko.d.ts | 4 + node_modules/zod/v4/locales/ko.js | 121 + node_modules/zod/v4/locales/mk.cjs | 145 + node_modules/zod/v4/locales/mk.d.cts | 5 + node_modules/zod/v4/locales/mk.d.ts | 4 + node_modules/zod/v4/locales/mk.js | 118 + node_modules/zod/v4/locales/ms.cjs | 143 + node_modules/zod/v4/locales/ms.d.cts | 5 + node_modules/zod/v4/locales/ms.d.ts | 4 + node_modules/zod/v4/locales/ms.js | 116 + node_modules/zod/v4/locales/nl.cjs | 144 + node_modules/zod/v4/locales/nl.d.cts | 5 + node_modules/zod/v4/locales/nl.d.ts | 4 + node_modules/zod/v4/locales/nl.js | 117 + node_modules/zod/v4/locales/no.cjs | 143 + node_modules/zod/v4/locales/no.d.cts | 5 + node_modules/zod/v4/locales/no.d.ts | 4 + node_modules/zod/v4/locales/no.js | 116 + node_modules/zod/v4/locales/ota.cjs | 144 + node_modules/zod/v4/locales/ota.d.cts | 5 + node_modules/zod/v4/locales/ota.d.ts | 4 + node_modules/zod/v4/locales/ota.js | 117 + node_modules/zod/v4/locales/pl.cjs | 144 + node_modules/zod/v4/locales/pl.d.cts | 5 + node_modules/zod/v4/locales/pl.d.ts | 4 + node_modules/zod/v4/locales/pl.js | 117 + node_modules/zod/v4/locales/ps.cjs | 149 + node_modules/zod/v4/locales/ps.d.cts | 5 + node_modules/zod/v4/locales/ps.d.ts | 4 + node_modules/zod/v4/locales/ps.js | 122 + node_modules/zod/v4/locales/pt.cjs | 143 + node_modules/zod/v4/locales/pt.d.cts | 5 + node_modules/zod/v4/locales/pt.d.ts | 4 + node_modules/zod/v4/locales/pt.js | 116 + node_modules/zod/v4/locales/ru.cjs | 191 + node_modules/zod/v4/locales/ru.d.cts | 5 + node_modules/zod/v4/locales/ru.d.ts | 4 + node_modules/zod/v4/locales/ru.js | 164 + node_modules/zod/v4/locales/sl.cjs | 144 + node_modules/zod/v4/locales/sl.d.cts | 5 + node_modules/zod/v4/locales/sl.d.ts | 4 + node_modules/zod/v4/locales/sl.js | 117 + node_modules/zod/v4/locales/sv.cjs | 145 + node_modules/zod/v4/locales/sv.d.cts | 5 + node_modules/zod/v4/locales/sv.d.ts | 4 + node_modules/zod/v4/locales/sv.js | 118 + node_modules/zod/v4/locales/ta.cjs | 144 + node_modules/zod/v4/locales/ta.d.cts | 5 + node_modules/zod/v4/locales/ta.d.ts | 4 + node_modules/zod/v4/locales/ta.js | 117 + node_modules/zod/v4/locales/th.cjs | 144 + node_modules/zod/v4/locales/th.d.cts | 5 + node_modules/zod/v4/locales/th.d.ts | 4 + node_modules/zod/v4/locales/th.js | 117 + node_modules/zod/v4/locales/tr.cjs | 143 + node_modules/zod/v4/locales/tr.d.cts | 5 + node_modules/zod/v4/locales/tr.d.ts | 5 + node_modules/zod/v4/locales/tr.js | 115 + node_modules/zod/v4/locales/ua.cjs | 144 + node_modules/zod/v4/locales/ua.d.cts | 5 + node_modules/zod/v4/locales/ua.d.ts | 4 + node_modules/zod/v4/locales/ua.js | 117 + node_modules/zod/v4/locales/ur.cjs | 144 + node_modules/zod/v4/locales/ur.d.cts | 5 + node_modules/zod/v4/locales/ur.d.ts | 4 + node_modules/zod/v4/locales/ur.js | 117 + node_modules/zod/v4/locales/vi.cjs | 143 + node_modules/zod/v4/locales/vi.d.cts | 5 + node_modules/zod/v4/locales/vi.d.ts | 4 + node_modules/zod/v4/locales/vi.js | 116 + node_modules/zod/v4/locales/yo.cjs | 142 + node_modules/zod/v4/locales/yo.d.cts | 5 + node_modules/zod/v4/locales/yo.d.ts | 4 + node_modules/zod/v4/locales/yo.js | 115 + node_modules/zod/v4/locales/zh-CN.cjs | 143 + node_modules/zod/v4/locales/zh-CN.d.cts | 5 + node_modules/zod/v4/locales/zh-CN.d.ts | 4 + node_modules/zod/v4/locales/zh-CN.js | 116 + node_modules/zod/v4/locales/zh-TW.cjs | 144 + node_modules/zod/v4/locales/zh-TW.d.cts | 5 + node_modules/zod/v4/locales/zh-TW.d.ts | 4 + node_modules/zod/v4/locales/zh-TW.js | 117 + node_modules/zod/v4/mini/checks.cjs | 34 + node_modules/zod/v4/mini/checks.d.cts | 1 + node_modules/zod/v4/mini/checks.d.ts | 1 + node_modules/zod/v4/mini/checks.js | 1 + node_modules/zod/v4/mini/coerce.cjs | 47 + node_modules/zod/v4/mini/coerce.d.cts | 7 + node_modules/zod/v4/mini/coerce.d.ts | 7 + node_modules/zod/v4/mini/coerce.js | 17 + node_modules/zod/v4/mini/external.cjs | 62 + node_modules/zod/v4/mini/external.d.cts | 11 + node_modules/zod/v4/mini/external.d.ts | 11 + node_modules/zod/v4/mini/external.js | 13 + node_modules/zod/v4/mini/index.cjs | 32 + node_modules/zod/v4/mini/index.d.cts | 3 + node_modules/zod/v4/mini/index.d.ts | 3 + node_modules/zod/v4/mini/index.js | 3 + node_modules/zod/v4/mini/iso.cjs | 60 + node_modules/zod/v4/mini/iso.d.cts | 22 + node_modules/zod/v4/mini/iso.d.ts | 22 + node_modules/zod/v4/mini/iso.js | 30 + node_modules/zod/v4/mini/parse.cjs | 8 + node_modules/zod/v4/mini/parse.d.cts | 1 + node_modules/zod/v4/mini/parse.d.ts | 1 + node_modules/zod/v4/mini/parse.js | 1 + node_modules/zod/v4/mini/schemas.cjs | 850 +++ node_modules/zod/v4/mini/schemas.d.cts | 358 ++ node_modules/zod/v4/mini/schemas.d.ts | 358 ++ node_modules/zod/v4/mini/schemas.js | 741 +++ package-lock.json | 21 + package.json | 5 + 637 files changed, 101735 insertions(+), 12 deletions(-) create mode 100644 frontend/src/lib/components/QueueSlider.svelte create mode 100644 frontend/src/lib/components/SuggestionInput.svelte create mode 100644 frontend/src/lib/components/SuggestionList.svelte delete mode 100644 frontend/src/lib/index.ts create mode 100644 frontend/src/lib/types.ts create mode 100644 node_modules/.package-lock.json create mode 100644 node_modules/zod/LICENSE create mode 100644 node_modules/zod/README.md create mode 100644 node_modules/zod/index.cjs create mode 100644 node_modules/zod/index.d.cts create mode 100644 node_modules/zod/index.d.ts create mode 100644 node_modules/zod/index.js create mode 100644 node_modules/zod/locales/index.cjs create mode 100644 node_modules/zod/locales/index.d.cts create mode 100644 node_modules/zod/locales/index.d.ts create mode 100644 node_modules/zod/locales/index.js create mode 100644 node_modules/zod/mini/index.cjs create mode 100644 node_modules/zod/mini/index.d.cts create mode 100644 node_modules/zod/mini/index.d.ts create mode 100644 node_modules/zod/mini/index.js create mode 100644 node_modules/zod/package.json create mode 100644 node_modules/zod/src/index.ts create mode 100644 node_modules/zod/src/locales/index.ts create mode 100644 node_modules/zod/src/mini/index.ts create mode 100644 node_modules/zod/src/v3/ZodError.ts create mode 100644 node_modules/zod/src/v3/benchmarks/datetime.ts create mode 100644 node_modules/zod/src/v3/benchmarks/discriminatedUnion.ts create mode 100644 node_modules/zod/src/v3/benchmarks/index.ts create mode 100644 node_modules/zod/src/v3/benchmarks/ipv4.ts create mode 100644 node_modules/zod/src/v3/benchmarks/object.ts create mode 100644 node_modules/zod/src/v3/benchmarks/primitives.ts create mode 100644 node_modules/zod/src/v3/benchmarks/realworld.ts create mode 100644 node_modules/zod/src/v3/benchmarks/string.ts create mode 100644 node_modules/zod/src/v3/benchmarks/union.ts create mode 100644 node_modules/zod/src/v3/errors.ts create mode 100644 node_modules/zod/src/v3/external.ts create mode 100644 node_modules/zod/src/v3/helpers/enumUtil.ts create mode 100644 node_modules/zod/src/v3/helpers/errorUtil.ts create mode 100644 node_modules/zod/src/v3/helpers/parseUtil.ts create mode 100644 node_modules/zod/src/v3/helpers/partialUtil.ts create mode 100644 node_modules/zod/src/v3/helpers/typeAliases.ts create mode 100644 node_modules/zod/src/v3/helpers/util.ts create mode 100644 node_modules/zod/src/v3/index.ts create mode 100644 node_modules/zod/src/v3/locales/en.ts create mode 100644 node_modules/zod/src/v3/standard-schema.ts create mode 100644 node_modules/zod/src/v3/tests/Mocker.ts create mode 100644 node_modules/zod/src/v3/tests/all-errors.test.ts create mode 100644 node_modules/zod/src/v3/tests/anyunknown.test.ts create mode 100644 node_modules/zod/src/v3/tests/array.test.ts create mode 100644 node_modules/zod/src/v3/tests/async-parsing.test.ts create mode 100644 node_modules/zod/src/v3/tests/async-refinements.test.ts create mode 100644 node_modules/zod/src/v3/tests/base.test.ts create mode 100644 node_modules/zod/src/v3/tests/bigint.test.ts create mode 100644 node_modules/zod/src/v3/tests/branded.test.ts create mode 100644 node_modules/zod/src/v3/tests/catch.test.ts create mode 100644 node_modules/zod/src/v3/tests/coerce.test.ts create mode 100644 node_modules/zod/src/v3/tests/complex.test.ts create mode 100644 node_modules/zod/src/v3/tests/custom.test.ts create mode 100644 node_modules/zod/src/v3/tests/date.test.ts create mode 100644 node_modules/zod/src/v3/tests/deepmasking.test.ts create mode 100644 node_modules/zod/src/v3/tests/default.test.ts create mode 100644 node_modules/zod/src/v3/tests/description.test.ts create mode 100644 node_modules/zod/src/v3/tests/discriminated-unions.test.ts create mode 100644 node_modules/zod/src/v3/tests/enum.test.ts create mode 100644 node_modules/zod/src/v3/tests/error.test.ts create mode 100644 node_modules/zod/src/v3/tests/firstparty.test.ts create mode 100644 node_modules/zod/src/v3/tests/firstpartyschematypes.test.ts create mode 100644 node_modules/zod/src/v3/tests/function.test.ts create mode 100644 node_modules/zod/src/v3/tests/generics.test.ts create mode 100644 node_modules/zod/src/v3/tests/instanceof.test.ts create mode 100644 node_modules/zod/src/v3/tests/intersection.test.ts create mode 100644 node_modules/zod/src/v3/tests/language-server.source.ts create mode 100644 node_modules/zod/src/v3/tests/language-server.test.ts create mode 100644 node_modules/zod/src/v3/tests/literal.test.ts create mode 100644 node_modules/zod/src/v3/tests/map.test.ts create mode 100644 node_modules/zod/src/v3/tests/masking.test.ts create mode 100644 node_modules/zod/src/v3/tests/mocker.test.ts create mode 100644 node_modules/zod/src/v3/tests/nan.test.ts create mode 100644 node_modules/zod/src/v3/tests/nativeEnum.test.ts create mode 100644 node_modules/zod/src/v3/tests/nullable.test.ts create mode 100644 node_modules/zod/src/v3/tests/number.test.ts create mode 100644 node_modules/zod/src/v3/tests/object-augmentation.test.ts create mode 100644 node_modules/zod/src/v3/tests/object-in-es5-env.test.ts create mode 100644 node_modules/zod/src/v3/tests/object.test.ts create mode 100644 node_modules/zod/src/v3/tests/optional.test.ts create mode 100644 node_modules/zod/src/v3/tests/parseUtil.test.ts create mode 100644 node_modules/zod/src/v3/tests/parser.test.ts create mode 100644 node_modules/zod/src/v3/tests/partials.test.ts create mode 100644 node_modules/zod/src/v3/tests/pickomit.test.ts create mode 100644 node_modules/zod/src/v3/tests/pipeline.test.ts create mode 100644 node_modules/zod/src/v3/tests/preprocess.test.ts create mode 100644 node_modules/zod/src/v3/tests/primitive.test.ts create mode 100644 node_modules/zod/src/v3/tests/promise.test.ts create mode 100644 node_modules/zod/src/v3/tests/readonly.test.ts create mode 100644 node_modules/zod/src/v3/tests/record.test.ts create mode 100644 node_modules/zod/src/v3/tests/recursive.test.ts create mode 100644 node_modules/zod/src/v3/tests/refine.test.ts create mode 100644 node_modules/zod/src/v3/tests/safeparse.test.ts create mode 100644 node_modules/zod/src/v3/tests/set.test.ts create mode 100644 node_modules/zod/src/v3/tests/standard-schema.test.ts create mode 100644 node_modules/zod/src/v3/tests/string.test.ts create mode 100644 node_modules/zod/src/v3/tests/transformer.test.ts create mode 100644 node_modules/zod/src/v3/tests/tuple.test.ts create mode 100644 node_modules/zod/src/v3/tests/unions.test.ts create mode 100644 node_modules/zod/src/v3/tests/validations.test.ts create mode 100644 node_modules/zod/src/v3/tests/void.test.ts create mode 100644 node_modules/zod/src/v3/types.ts create mode 100644 node_modules/zod/src/v4-mini/index.ts create mode 100644 node_modules/zod/src/v4/classic/checks.ts create mode 100644 node_modules/zod/src/v4/classic/coerce.ts create mode 100644 node_modules/zod/src/v4/classic/compat.ts create mode 100644 node_modules/zod/src/v4/classic/errors.ts create mode 100644 node_modules/zod/src/v4/classic/external.ts create mode 100644 node_modules/zod/src/v4/classic/index.ts create mode 100644 node_modules/zod/src/v4/classic/iso.ts create mode 100644 node_modules/zod/src/v4/classic/parse.ts create mode 100644 node_modules/zod/src/v4/classic/schemas.ts create mode 100644 node_modules/zod/src/v4/classic/tests/anyunknown.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/array.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/assignability.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/async-parsing.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/async-refinements.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/base.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/bigint.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/brand.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/catch.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/coalesce.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/coerce.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/continuability.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/custom.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/date.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/datetime.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/default.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/description.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/discriminated-unions.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/enum.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/error-utils.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/error.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/file.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/firstparty.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/function.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/generics.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/index.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/instanceof.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/intersection.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/json.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/lazy.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/literal.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/map.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/nan.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/nested-refine.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/nonoptional.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/nullable.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/number.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/object.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/optional.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/partial.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/pickomit.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/pipe.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/prefault.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/preprocess.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/primitive.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/promise.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/prototypes.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/readonly.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/record.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/recursive-types.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/refine.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/registries.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/set.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/standard-schema.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/string-formats.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/string.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/stringbool.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/template-literal.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/to-json-schema.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/transform.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/tuple.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/union.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/validations.test.ts create mode 100644 node_modules/zod/src/v4/classic/tests/void.test.ts create mode 100644 node_modules/zod/src/v4/core/api.ts create mode 100644 node_modules/zod/src/v4/core/checks.ts create mode 100644 node_modules/zod/src/v4/core/config.ts create mode 100644 node_modules/zod/src/v4/core/core.ts create mode 100644 node_modules/zod/src/v4/core/doc.ts create mode 100644 node_modules/zod/src/v4/core/errors.ts create mode 100644 node_modules/zod/src/v4/core/function.ts create mode 100644 node_modules/zod/src/v4/core/index.ts create mode 100644 node_modules/zod/src/v4/core/json-schema.ts create mode 100644 node_modules/zod/src/v4/core/parse.ts create mode 100644 node_modules/zod/src/v4/core/regexes.ts create mode 100644 node_modules/zod/src/v4/core/registries.ts create mode 100644 node_modules/zod/src/v4/core/schemas.ts create mode 100644 node_modules/zod/src/v4/core/standard-schema.ts create mode 100644 node_modules/zod/src/v4/core/tests/extend.test.ts create mode 100644 node_modules/zod/src/v4/core/tests/index.test.ts create mode 100644 node_modules/zod/src/v4/core/tests/locales/be.test.ts create mode 100644 node_modules/zod/src/v4/core/tests/locales/en.test.ts create mode 100644 node_modules/zod/src/v4/core/tests/locales/ru.test.ts create mode 100644 node_modules/zod/src/v4/core/tests/locales/tr.test.ts create mode 100644 node_modules/zod/src/v4/core/to-json-schema.ts create mode 100644 node_modules/zod/src/v4/core/util.ts create mode 100644 node_modules/zod/src/v4/core/versions.ts create mode 100644 node_modules/zod/src/v4/core/zsf.ts create mode 100644 node_modules/zod/src/v4/index.ts create mode 100644 node_modules/zod/src/v4/locales/ar.ts create mode 100644 node_modules/zod/src/v4/locales/az.ts create mode 100644 node_modules/zod/src/v4/locales/be.ts create mode 100644 node_modules/zod/src/v4/locales/bg.ts create mode 100644 node_modules/zod/src/v4/locales/ca.ts create mode 100644 node_modules/zod/src/v4/locales/cs.ts create mode 100644 node_modules/zod/src/v4/locales/da.ts create mode 100644 node_modules/zod/src/v4/locales/de.ts create mode 100644 node_modules/zod/src/v4/locales/en.ts create mode 100644 node_modules/zod/src/v4/locales/eo.ts create mode 100644 node_modules/zod/src/v4/locales/es.ts create mode 100644 node_modules/zod/src/v4/locales/fa.ts create mode 100644 node_modules/zod/src/v4/locales/fi.ts create mode 100644 node_modules/zod/src/v4/locales/fr-CA.ts create mode 100644 node_modules/zod/src/v4/locales/fr.ts create mode 100644 node_modules/zod/src/v4/locales/he.ts create mode 100644 node_modules/zod/src/v4/locales/hu.ts create mode 100644 node_modules/zod/src/v4/locales/id.ts create mode 100644 node_modules/zod/src/v4/locales/index.ts create mode 100644 node_modules/zod/src/v4/locales/is.ts create mode 100644 node_modules/zod/src/v4/locales/it.ts create mode 100644 node_modules/zod/src/v4/locales/ja.ts create mode 100644 node_modules/zod/src/v4/locales/kh.ts create mode 100644 node_modules/zod/src/v4/locales/ko.ts create mode 100644 node_modules/zod/src/v4/locales/mk.ts create mode 100644 node_modules/zod/src/v4/locales/ms.ts create mode 100644 node_modules/zod/src/v4/locales/nl.ts create mode 100644 node_modules/zod/src/v4/locales/no.ts create mode 100644 node_modules/zod/src/v4/locales/ota.ts create mode 100644 node_modules/zod/src/v4/locales/pl.ts create mode 100644 node_modules/zod/src/v4/locales/ps.ts create mode 100644 node_modules/zod/src/v4/locales/pt.ts create mode 100644 node_modules/zod/src/v4/locales/ru.ts create mode 100644 node_modules/zod/src/v4/locales/sl.ts create mode 100644 node_modules/zod/src/v4/locales/sv.ts create mode 100644 node_modules/zod/src/v4/locales/ta.ts create mode 100644 node_modules/zod/src/v4/locales/th.ts create mode 100644 node_modules/zod/src/v4/locales/tr.ts create mode 100644 node_modules/zod/src/v4/locales/ua.ts create mode 100644 node_modules/zod/src/v4/locales/ur.ts create mode 100644 node_modules/zod/src/v4/locales/vi.ts create mode 100644 node_modules/zod/src/v4/locales/yo.ts create mode 100644 node_modules/zod/src/v4/locales/zh-CN.ts create mode 100644 node_modules/zod/src/v4/locales/zh-TW.ts create mode 100644 node_modules/zod/src/v4/mini/checks.ts create mode 100644 node_modules/zod/src/v4/mini/coerce.ts create mode 100644 node_modules/zod/src/v4/mini/external.ts create mode 100644 node_modules/zod/src/v4/mini/index.ts create mode 100644 node_modules/zod/src/v4/mini/iso.ts create mode 100644 node_modules/zod/src/v4/mini/parse.ts create mode 100644 node_modules/zod/src/v4/mini/schemas.ts create mode 100644 node_modules/zod/src/v4/mini/tests/assignability.test.ts create mode 100644 node_modules/zod/src/v4/mini/tests/brand.test.ts create mode 100644 node_modules/zod/src/v4/mini/tests/checks.test.ts create mode 100644 node_modules/zod/src/v4/mini/tests/computed.test.ts create mode 100644 node_modules/zod/src/v4/mini/tests/error.test.ts create mode 100644 node_modules/zod/src/v4/mini/tests/functions.test.ts create mode 100644 node_modules/zod/src/v4/mini/tests/index.test.ts create mode 100644 node_modules/zod/src/v4/mini/tests/number.test.ts create mode 100644 node_modules/zod/src/v4/mini/tests/object.test.ts create mode 100644 node_modules/zod/src/v4/mini/tests/prototypes.test.ts create mode 100644 node_modules/zod/src/v4/mini/tests/recursive-types.test.ts create mode 100644 node_modules/zod/src/v4/mini/tests/string.test.ts create mode 100644 node_modules/zod/v3/ZodError.cjs create mode 100644 node_modules/zod/v3/ZodError.d.cts create mode 100644 node_modules/zod/v3/ZodError.d.ts create mode 100644 node_modules/zod/v3/ZodError.js create mode 100644 node_modules/zod/v3/errors.cjs create mode 100644 node_modules/zod/v3/errors.d.cts create mode 100644 node_modules/zod/v3/errors.d.ts create mode 100644 node_modules/zod/v3/errors.js create mode 100644 node_modules/zod/v3/external.cjs create mode 100644 node_modules/zod/v3/external.d.cts create mode 100644 node_modules/zod/v3/external.d.ts create mode 100644 node_modules/zod/v3/external.js create mode 100644 node_modules/zod/v3/helpers/enumUtil.cjs create mode 100644 node_modules/zod/v3/helpers/enumUtil.d.cts create mode 100644 node_modules/zod/v3/helpers/enumUtil.d.ts create mode 100644 node_modules/zod/v3/helpers/enumUtil.js create mode 100644 node_modules/zod/v3/helpers/errorUtil.cjs create mode 100644 node_modules/zod/v3/helpers/errorUtil.d.cts create mode 100644 node_modules/zod/v3/helpers/errorUtil.d.ts create mode 100644 node_modules/zod/v3/helpers/errorUtil.js create mode 100644 node_modules/zod/v3/helpers/parseUtil.cjs create mode 100644 node_modules/zod/v3/helpers/parseUtil.d.cts create mode 100644 node_modules/zod/v3/helpers/parseUtil.d.ts create mode 100644 node_modules/zod/v3/helpers/parseUtil.js create mode 100644 node_modules/zod/v3/helpers/partialUtil.cjs create mode 100644 node_modules/zod/v3/helpers/partialUtil.d.cts create mode 100644 node_modules/zod/v3/helpers/partialUtil.d.ts create mode 100644 node_modules/zod/v3/helpers/partialUtil.js create mode 100644 node_modules/zod/v3/helpers/typeAliases.cjs create mode 100644 node_modules/zod/v3/helpers/typeAliases.d.cts create mode 100644 node_modules/zod/v3/helpers/typeAliases.d.ts create mode 100644 node_modules/zod/v3/helpers/typeAliases.js create mode 100644 node_modules/zod/v3/helpers/util.cjs create mode 100644 node_modules/zod/v3/helpers/util.d.cts create mode 100644 node_modules/zod/v3/helpers/util.d.ts create mode 100644 node_modules/zod/v3/helpers/util.js create mode 100644 node_modules/zod/v3/index.cjs create mode 100644 node_modules/zod/v3/index.d.cts create mode 100644 node_modules/zod/v3/index.d.ts create mode 100644 node_modules/zod/v3/index.js create mode 100644 node_modules/zod/v3/locales/en.cjs create mode 100644 node_modules/zod/v3/locales/en.d.cts create mode 100644 node_modules/zod/v3/locales/en.d.ts create mode 100644 node_modules/zod/v3/locales/en.js create mode 100644 node_modules/zod/v3/standard-schema.cjs create mode 100644 node_modules/zod/v3/standard-schema.d.cts create mode 100644 node_modules/zod/v3/standard-schema.d.ts create mode 100644 node_modules/zod/v3/standard-schema.js create mode 100644 node_modules/zod/v3/types.cjs create mode 100644 node_modules/zod/v3/types.d.cts create mode 100644 node_modules/zod/v3/types.d.ts create mode 100644 node_modules/zod/v3/types.js create mode 100644 node_modules/zod/v4-mini/index.cjs create mode 100644 node_modules/zod/v4-mini/index.d.cts create mode 100644 node_modules/zod/v4-mini/index.d.ts create mode 100644 node_modules/zod/v4-mini/index.js create mode 100644 node_modules/zod/v4/classic/checks.cjs create mode 100644 node_modules/zod/v4/classic/checks.d.cts create mode 100644 node_modules/zod/v4/classic/checks.d.ts create mode 100644 node_modules/zod/v4/classic/checks.js create mode 100644 node_modules/zod/v4/classic/coerce.cjs create mode 100644 node_modules/zod/v4/classic/coerce.d.cts create mode 100644 node_modules/zod/v4/classic/coerce.d.ts create mode 100644 node_modules/zod/v4/classic/coerce.js create mode 100644 node_modules/zod/v4/classic/compat.cjs create mode 100644 node_modules/zod/v4/classic/compat.d.cts create mode 100644 node_modules/zod/v4/classic/compat.d.ts create mode 100644 node_modules/zod/v4/classic/compat.js create mode 100644 node_modules/zod/v4/classic/errors.cjs create mode 100644 node_modules/zod/v4/classic/errors.d.cts create mode 100644 node_modules/zod/v4/classic/errors.d.ts create mode 100644 node_modules/zod/v4/classic/errors.js create mode 100644 node_modules/zod/v4/classic/external.cjs create mode 100644 node_modules/zod/v4/classic/external.d.cts create mode 100644 node_modules/zod/v4/classic/external.d.ts create mode 100644 node_modules/zod/v4/classic/external.js create mode 100644 node_modules/zod/v4/classic/index.cjs create mode 100644 node_modules/zod/v4/classic/index.d.cts create mode 100644 node_modules/zod/v4/classic/index.d.ts create mode 100644 node_modules/zod/v4/classic/index.js create mode 100644 node_modules/zod/v4/classic/iso.cjs create mode 100644 node_modules/zod/v4/classic/iso.d.cts create mode 100644 node_modules/zod/v4/classic/iso.d.ts create mode 100644 node_modules/zod/v4/classic/iso.js create mode 100644 node_modules/zod/v4/classic/parse.cjs create mode 100644 node_modules/zod/v4/classic/parse.d.cts create mode 100644 node_modules/zod/v4/classic/parse.d.ts create mode 100644 node_modules/zod/v4/classic/parse.js create mode 100644 node_modules/zod/v4/classic/schemas.cjs create mode 100644 node_modules/zod/v4/classic/schemas.d.cts create mode 100644 node_modules/zod/v4/classic/schemas.d.ts create mode 100644 node_modules/zod/v4/classic/schemas.js create mode 100644 node_modules/zod/v4/core/api.cjs create mode 100644 node_modules/zod/v4/core/api.d.cts create mode 100644 node_modules/zod/v4/core/api.d.ts create mode 100644 node_modules/zod/v4/core/api.js create mode 100644 node_modules/zod/v4/core/checks.cjs create mode 100644 node_modules/zod/v4/core/checks.d.cts create mode 100644 node_modules/zod/v4/core/checks.d.ts create mode 100644 node_modules/zod/v4/core/checks.js create mode 100644 node_modules/zod/v4/core/core.cjs create mode 100644 node_modules/zod/v4/core/core.d.cts create mode 100644 node_modules/zod/v4/core/core.d.ts create mode 100644 node_modules/zod/v4/core/core.js create mode 100644 node_modules/zod/v4/core/doc.cjs create mode 100644 node_modules/zod/v4/core/doc.d.cts create mode 100644 node_modules/zod/v4/core/doc.d.ts create mode 100644 node_modules/zod/v4/core/doc.js create mode 100644 node_modules/zod/v4/core/errors.cjs create mode 100644 node_modules/zod/v4/core/errors.d.cts create mode 100644 node_modules/zod/v4/core/errors.d.ts create mode 100644 node_modules/zod/v4/core/errors.js create mode 100644 node_modules/zod/v4/core/function.cjs create mode 100644 node_modules/zod/v4/core/function.d.cts create mode 100644 node_modules/zod/v4/core/function.d.ts create mode 100644 node_modules/zod/v4/core/function.js create mode 100644 node_modules/zod/v4/core/index.cjs create mode 100644 node_modules/zod/v4/core/index.d.cts create mode 100644 node_modules/zod/v4/core/index.d.ts create mode 100644 node_modules/zod/v4/core/index.js create mode 100644 node_modules/zod/v4/core/json-schema.cjs create mode 100644 node_modules/zod/v4/core/json-schema.d.cts create mode 100644 node_modules/zod/v4/core/json-schema.d.ts create mode 100644 node_modules/zod/v4/core/json-schema.js create mode 100644 node_modules/zod/v4/core/parse.cjs create mode 100644 node_modules/zod/v4/core/parse.d.cts create mode 100644 node_modules/zod/v4/core/parse.d.ts create mode 100644 node_modules/zod/v4/core/parse.js create mode 100644 node_modules/zod/v4/core/regexes.cjs create mode 100644 node_modules/zod/v4/core/regexes.d.cts create mode 100644 node_modules/zod/v4/core/regexes.d.ts create mode 100644 node_modules/zod/v4/core/regexes.js create mode 100644 node_modules/zod/v4/core/registries.cjs create mode 100644 node_modules/zod/v4/core/registries.d.cts create mode 100644 node_modules/zod/v4/core/registries.d.ts create mode 100644 node_modules/zod/v4/core/registries.js create mode 100644 node_modules/zod/v4/core/schemas.cjs create mode 100644 node_modules/zod/v4/core/schemas.d.cts create mode 100644 node_modules/zod/v4/core/schemas.d.ts create mode 100644 node_modules/zod/v4/core/schemas.js create mode 100644 node_modules/zod/v4/core/standard-schema.cjs create mode 100644 node_modules/zod/v4/core/standard-schema.d.cts create mode 100644 node_modules/zod/v4/core/standard-schema.d.ts create mode 100644 node_modules/zod/v4/core/standard-schema.js create mode 100644 node_modules/zod/v4/core/to-json-schema.cjs create mode 100644 node_modules/zod/v4/core/to-json-schema.d.cts create mode 100644 node_modules/zod/v4/core/to-json-schema.d.ts create mode 100644 node_modules/zod/v4/core/to-json-schema.js create mode 100644 node_modules/zod/v4/core/util.cjs create mode 100644 node_modules/zod/v4/core/util.d.cts create mode 100644 node_modules/zod/v4/core/util.d.ts create mode 100644 node_modules/zod/v4/core/util.js create mode 100644 node_modules/zod/v4/core/versions.cjs create mode 100644 node_modules/zod/v4/core/versions.d.cts create mode 100644 node_modules/zod/v4/core/versions.d.ts create mode 100644 node_modules/zod/v4/core/versions.js create mode 100644 node_modules/zod/v4/index.cjs create mode 100644 node_modules/zod/v4/index.d.cts create mode 100644 node_modules/zod/v4/index.d.ts create mode 100644 node_modules/zod/v4/index.js create mode 100644 node_modules/zod/v4/locales/ar.cjs create mode 100644 node_modules/zod/v4/locales/ar.d.cts create mode 100644 node_modules/zod/v4/locales/ar.d.ts create mode 100644 node_modules/zod/v4/locales/ar.js create mode 100644 node_modules/zod/v4/locales/az.cjs create mode 100644 node_modules/zod/v4/locales/az.d.cts create mode 100644 node_modules/zod/v4/locales/az.d.ts create mode 100644 node_modules/zod/v4/locales/az.js create mode 100644 node_modules/zod/v4/locales/be.cjs create mode 100644 node_modules/zod/v4/locales/be.d.cts create mode 100644 node_modules/zod/v4/locales/be.d.ts create mode 100644 node_modules/zod/v4/locales/be.js create mode 100644 node_modules/zod/v4/locales/bg.cjs create mode 100644 node_modules/zod/v4/locales/bg.d.cts create mode 100644 node_modules/zod/v4/locales/bg.d.ts create mode 100644 node_modules/zod/v4/locales/bg.js create mode 100644 node_modules/zod/v4/locales/ca.cjs create mode 100644 node_modules/zod/v4/locales/ca.d.cts create mode 100644 node_modules/zod/v4/locales/ca.d.ts create mode 100644 node_modules/zod/v4/locales/ca.js create mode 100644 node_modules/zod/v4/locales/cs.cjs create mode 100644 node_modules/zod/v4/locales/cs.d.cts create mode 100644 node_modules/zod/v4/locales/cs.d.ts create mode 100644 node_modules/zod/v4/locales/cs.js create mode 100644 node_modules/zod/v4/locales/da.cjs create mode 100644 node_modules/zod/v4/locales/da.d.cts create mode 100644 node_modules/zod/v4/locales/da.d.ts create mode 100644 node_modules/zod/v4/locales/da.js create mode 100644 node_modules/zod/v4/locales/de.cjs create mode 100644 node_modules/zod/v4/locales/de.d.cts create mode 100644 node_modules/zod/v4/locales/de.d.ts create mode 100644 node_modules/zod/v4/locales/de.js create mode 100644 node_modules/zod/v4/locales/en.cjs create mode 100644 node_modules/zod/v4/locales/en.d.cts create mode 100644 node_modules/zod/v4/locales/en.d.ts create mode 100644 node_modules/zod/v4/locales/en.js create mode 100644 node_modules/zod/v4/locales/eo.cjs create mode 100644 node_modules/zod/v4/locales/eo.d.cts create mode 100644 node_modules/zod/v4/locales/eo.d.ts create mode 100644 node_modules/zod/v4/locales/eo.js create mode 100644 node_modules/zod/v4/locales/es.cjs create mode 100644 node_modules/zod/v4/locales/es.d.cts create mode 100644 node_modules/zod/v4/locales/es.d.ts create mode 100644 node_modules/zod/v4/locales/es.js create mode 100644 node_modules/zod/v4/locales/fa.cjs create mode 100644 node_modules/zod/v4/locales/fa.d.cts create mode 100644 node_modules/zod/v4/locales/fa.d.ts create mode 100644 node_modules/zod/v4/locales/fa.js create mode 100644 node_modules/zod/v4/locales/fi.cjs create mode 100644 node_modules/zod/v4/locales/fi.d.cts create mode 100644 node_modules/zod/v4/locales/fi.d.ts create mode 100644 node_modules/zod/v4/locales/fi.js create mode 100644 node_modules/zod/v4/locales/fr-CA.cjs create mode 100644 node_modules/zod/v4/locales/fr-CA.d.cts create mode 100644 node_modules/zod/v4/locales/fr-CA.d.ts create mode 100644 node_modules/zod/v4/locales/fr-CA.js create mode 100644 node_modules/zod/v4/locales/fr.cjs create mode 100644 node_modules/zod/v4/locales/fr.d.cts create mode 100644 node_modules/zod/v4/locales/fr.d.ts create mode 100644 node_modules/zod/v4/locales/fr.js create mode 100644 node_modules/zod/v4/locales/he.cjs create mode 100644 node_modules/zod/v4/locales/he.d.cts create mode 100644 node_modules/zod/v4/locales/he.d.ts create mode 100644 node_modules/zod/v4/locales/he.js create mode 100644 node_modules/zod/v4/locales/hu.cjs create mode 100644 node_modules/zod/v4/locales/hu.d.cts create mode 100644 node_modules/zod/v4/locales/hu.d.ts create mode 100644 node_modules/zod/v4/locales/hu.js create mode 100644 node_modules/zod/v4/locales/id.cjs create mode 100644 node_modules/zod/v4/locales/id.d.cts create mode 100644 node_modules/zod/v4/locales/id.d.ts create mode 100644 node_modules/zod/v4/locales/id.js create mode 100644 node_modules/zod/v4/locales/index.cjs create mode 100644 node_modules/zod/v4/locales/index.d.cts create mode 100644 node_modules/zod/v4/locales/index.d.ts create mode 100644 node_modules/zod/v4/locales/index.js create mode 100644 node_modules/zod/v4/locales/is.cjs create mode 100644 node_modules/zod/v4/locales/is.d.cts create mode 100644 node_modules/zod/v4/locales/is.d.ts create mode 100644 node_modules/zod/v4/locales/is.js create mode 100644 node_modules/zod/v4/locales/it.cjs create mode 100644 node_modules/zod/v4/locales/it.d.cts create mode 100644 node_modules/zod/v4/locales/it.d.ts create mode 100644 node_modules/zod/v4/locales/it.js create mode 100644 node_modules/zod/v4/locales/ja.cjs create mode 100644 node_modules/zod/v4/locales/ja.d.cts create mode 100644 node_modules/zod/v4/locales/ja.d.ts create mode 100644 node_modules/zod/v4/locales/ja.js create mode 100644 node_modules/zod/v4/locales/kh.cjs create mode 100644 node_modules/zod/v4/locales/kh.d.cts create mode 100644 node_modules/zod/v4/locales/kh.d.ts create mode 100644 node_modules/zod/v4/locales/kh.js create mode 100644 node_modules/zod/v4/locales/ko.cjs create mode 100644 node_modules/zod/v4/locales/ko.d.cts create mode 100644 node_modules/zod/v4/locales/ko.d.ts create mode 100644 node_modules/zod/v4/locales/ko.js create mode 100644 node_modules/zod/v4/locales/mk.cjs create mode 100644 node_modules/zod/v4/locales/mk.d.cts create mode 100644 node_modules/zod/v4/locales/mk.d.ts create mode 100644 node_modules/zod/v4/locales/mk.js create mode 100644 node_modules/zod/v4/locales/ms.cjs create mode 100644 node_modules/zod/v4/locales/ms.d.cts create mode 100644 node_modules/zod/v4/locales/ms.d.ts create mode 100644 node_modules/zod/v4/locales/ms.js create mode 100644 node_modules/zod/v4/locales/nl.cjs create mode 100644 node_modules/zod/v4/locales/nl.d.cts create mode 100644 node_modules/zod/v4/locales/nl.d.ts create mode 100644 node_modules/zod/v4/locales/nl.js create mode 100644 node_modules/zod/v4/locales/no.cjs create mode 100644 node_modules/zod/v4/locales/no.d.cts create mode 100644 node_modules/zod/v4/locales/no.d.ts create mode 100644 node_modules/zod/v4/locales/no.js create mode 100644 node_modules/zod/v4/locales/ota.cjs create mode 100644 node_modules/zod/v4/locales/ota.d.cts create mode 100644 node_modules/zod/v4/locales/ota.d.ts create mode 100644 node_modules/zod/v4/locales/ota.js create mode 100644 node_modules/zod/v4/locales/pl.cjs create mode 100644 node_modules/zod/v4/locales/pl.d.cts create mode 100644 node_modules/zod/v4/locales/pl.d.ts create mode 100644 node_modules/zod/v4/locales/pl.js create mode 100644 node_modules/zod/v4/locales/ps.cjs create mode 100644 node_modules/zod/v4/locales/ps.d.cts create mode 100644 node_modules/zod/v4/locales/ps.d.ts create mode 100644 node_modules/zod/v4/locales/ps.js create mode 100644 node_modules/zod/v4/locales/pt.cjs create mode 100644 node_modules/zod/v4/locales/pt.d.cts create mode 100644 node_modules/zod/v4/locales/pt.d.ts create mode 100644 node_modules/zod/v4/locales/pt.js create mode 100644 node_modules/zod/v4/locales/ru.cjs create mode 100644 node_modules/zod/v4/locales/ru.d.cts create mode 100644 node_modules/zod/v4/locales/ru.d.ts create mode 100644 node_modules/zod/v4/locales/ru.js create mode 100644 node_modules/zod/v4/locales/sl.cjs create mode 100644 node_modules/zod/v4/locales/sl.d.cts create mode 100644 node_modules/zod/v4/locales/sl.d.ts create mode 100644 node_modules/zod/v4/locales/sl.js create mode 100644 node_modules/zod/v4/locales/sv.cjs create mode 100644 node_modules/zod/v4/locales/sv.d.cts create mode 100644 node_modules/zod/v4/locales/sv.d.ts create mode 100644 node_modules/zod/v4/locales/sv.js create mode 100644 node_modules/zod/v4/locales/ta.cjs create mode 100644 node_modules/zod/v4/locales/ta.d.cts create mode 100644 node_modules/zod/v4/locales/ta.d.ts create mode 100644 node_modules/zod/v4/locales/ta.js create mode 100644 node_modules/zod/v4/locales/th.cjs create mode 100644 node_modules/zod/v4/locales/th.d.cts create mode 100644 node_modules/zod/v4/locales/th.d.ts create mode 100644 node_modules/zod/v4/locales/th.js create mode 100644 node_modules/zod/v4/locales/tr.cjs create mode 100644 node_modules/zod/v4/locales/tr.d.cts create mode 100644 node_modules/zod/v4/locales/tr.d.ts create mode 100644 node_modules/zod/v4/locales/tr.js create mode 100644 node_modules/zod/v4/locales/ua.cjs create mode 100644 node_modules/zod/v4/locales/ua.d.cts create mode 100644 node_modules/zod/v4/locales/ua.d.ts create mode 100644 node_modules/zod/v4/locales/ua.js create mode 100644 node_modules/zod/v4/locales/ur.cjs create mode 100644 node_modules/zod/v4/locales/ur.d.cts create mode 100644 node_modules/zod/v4/locales/ur.d.ts create mode 100644 node_modules/zod/v4/locales/ur.js create mode 100644 node_modules/zod/v4/locales/vi.cjs create mode 100644 node_modules/zod/v4/locales/vi.d.cts create mode 100644 node_modules/zod/v4/locales/vi.d.ts create mode 100644 node_modules/zod/v4/locales/vi.js create mode 100644 node_modules/zod/v4/locales/yo.cjs create mode 100644 node_modules/zod/v4/locales/yo.d.cts create mode 100644 node_modules/zod/v4/locales/yo.d.ts create mode 100644 node_modules/zod/v4/locales/yo.js create mode 100644 node_modules/zod/v4/locales/zh-CN.cjs create mode 100644 node_modules/zod/v4/locales/zh-CN.d.cts create mode 100644 node_modules/zod/v4/locales/zh-CN.d.ts create mode 100644 node_modules/zod/v4/locales/zh-CN.js create mode 100644 node_modules/zod/v4/locales/zh-TW.cjs create mode 100644 node_modules/zod/v4/locales/zh-TW.d.cts create mode 100644 node_modules/zod/v4/locales/zh-TW.d.ts create mode 100644 node_modules/zod/v4/locales/zh-TW.js create mode 100644 node_modules/zod/v4/mini/checks.cjs create mode 100644 node_modules/zod/v4/mini/checks.d.cts create mode 100644 node_modules/zod/v4/mini/checks.d.ts create mode 100644 node_modules/zod/v4/mini/checks.js create mode 100644 node_modules/zod/v4/mini/coerce.cjs create mode 100644 node_modules/zod/v4/mini/coerce.d.cts create mode 100644 node_modules/zod/v4/mini/coerce.d.ts create mode 100644 node_modules/zod/v4/mini/coerce.js create mode 100644 node_modules/zod/v4/mini/external.cjs create mode 100644 node_modules/zod/v4/mini/external.d.cts create mode 100644 node_modules/zod/v4/mini/external.d.ts create mode 100644 node_modules/zod/v4/mini/external.js create mode 100644 node_modules/zod/v4/mini/index.cjs create mode 100644 node_modules/zod/v4/mini/index.d.cts create mode 100644 node_modules/zod/v4/mini/index.d.ts create mode 100644 node_modules/zod/v4/mini/index.js create mode 100644 node_modules/zod/v4/mini/iso.cjs create mode 100644 node_modules/zod/v4/mini/iso.d.cts create mode 100644 node_modules/zod/v4/mini/iso.d.ts create mode 100644 node_modules/zod/v4/mini/iso.js create mode 100644 node_modules/zod/v4/mini/parse.cjs create mode 100644 node_modules/zod/v4/mini/parse.d.cts create mode 100644 node_modules/zod/v4/mini/parse.d.ts create mode 100644 node_modules/zod/v4/mini/parse.js create mode 100644 node_modules/zod/v4/mini/schemas.cjs create mode 100644 node_modules/zod/v4/mini/schemas.d.cts create mode 100644 node_modules/zod/v4/mini/schemas.d.ts create mode 100644 node_modules/zod/v4/mini/schemas.js create mode 100644 package-lock.json create mode 100644 package.json diff --git a/frontend/src/lib/components/QueueSlider.svelte b/frontend/src/lib/components/QueueSlider.svelte new file mode 100644 index 0000000..ca36495 --- /dev/null +++ b/frontend/src/lib/components/QueueSlider.svelte @@ -0,0 +1,29 @@ + + +
+
+ {#each displaySongs as song, i} + {#if song.name != ""} +
+ Song cover + {#if i === 1} +

{song.name}

+ {/if} +
+ {/if} + {/each} +
+
diff --git a/frontend/src/lib/components/SuggestionInput.svelte b/frontend/src/lib/components/SuggestionInput.svelte new file mode 100644 index 0000000..c93c8b7 --- /dev/null +++ b/frontend/src/lib/components/SuggestionInput.svelte @@ -0,0 +1,7 @@ + + +
+ + +
diff --git a/frontend/src/lib/components/SuggestionList.svelte b/frontend/src/lib/components/SuggestionList.svelte new file mode 100644 index 0000000..0fbba99 --- /dev/null +++ b/frontend/src/lib/components/SuggestionList.svelte @@ -0,0 +1,2 @@ + diff --git a/frontend/src/lib/index.ts b/frontend/src/lib/index.ts deleted file mode 100644 index 856f2b6..0000000 --- a/frontend/src/lib/index.ts +++ /dev/null @@ -1 +0,0 @@ -// place files you want to import through the `$lib` alias in this folder. diff --git a/frontend/src/lib/types.ts b/frontend/src/lib/types.ts new file mode 100644 index 0000000..328e641 --- /dev/null +++ b/frontend/src/lib/types.ts @@ -0,0 +1,8 @@ +import * as z from "zod" + +export const SongSchema = z.object({ + name: z.string(), + image: z.string(), +}) + +export type Song = z.infer diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte index ada8c4f..79a3f7e 100644 --- a/frontend/src/routes/+layout.svelte +++ b/frontend/src/routes/+layout.svelte @@ -4,6 +4,4 @@ let { children } = $props() -
- {@render children()} -
+{@render children()} diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index 323ffa3..3ca5a15 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -1,12 +1,36 @@ -

Welcome to SvelteKit

-

{text}

+
+ +
+ +
+
diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json new file mode 100644 index 0000000..411ffd3 --- /dev/null +++ b/node_modules/.package-lock.json @@ -0,0 +1,16 @@ +{ + "name": "team-1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "node_modules/zod": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.0.14.tgz", + "integrity": "sha512-nGFJTnJN6cM2v9kXL+SOBq3AtjQby3Mv5ySGFof5UGRHrRioSJ5iG680cYNjE/yWk671nROcpPj4hAS8nyLhSw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/node_modules/zod/LICENSE b/node_modules/zod/LICENSE new file mode 100644 index 0000000..c065796 --- /dev/null +++ b/node_modules/zod/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Colin McDonnell + +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. diff --git a/node_modules/zod/README.md b/node_modules/zod/README.md new file mode 100644 index 0000000..010708c --- /dev/null +++ b/node_modules/zod/README.md @@ -0,0 +1,208 @@ +

+ Zod logo +

Zod

+

+ TypeScript-first schema validation with static type inference +
+ by @colinhacks +

+

+
+ +

+Zod CI status +License +npm +discord server +stars +

+ +
+ Docs +   •   + Discord +   •   + 𝕏 +   •   + Bluesky +
+
+ +
+
+ +

Featured sponsor: Jazz

+ +
+ + + + jazz logo + + +
+

Learn more about featured sponsorships

+
+ +
+
+
+ +### [Read the docs →](https://zod.dev/api) + +
+
+ +## What is Zod? + +Zod is a TypeScript-first validation library. Define a schema and parse some data with it. You'll get back a strongly typed, validated result. + +```ts +import * as z from "zod"; + +const User = z.object({ + name: z.string(), +}); + +// some untrusted data... +const input = { + /* stuff */ +}; + +// the parsed result is validated and type safe! +const data = User.parse(input); + +// so you can use it with confidence :) +console.log(data.name); +``` + +
+ +## Features + +- Zero external dependencies +- Works in Node.js and all modern browsers +- Tiny: `2kb` core bundle (gzipped) +- Immutable API: methods return a new instance +- Concise interface +- Works with TypeScript and plain JS +- Built-in JSON Schema conversion +- Extensive ecosystem + +
+ +## Installation + +```sh +npm install zod +``` + +
+ +## Basic usage + +Before you can do anything else, you need to define a schema. For the purposes of this guide, we'll use a simple object schema. + +```ts +import * as z from "zod"; + +const Player = z.object({ + username: z.string(), + xp: z.number(), +}); +``` + +### Parsing data + +Given any Zod schema, use `.parse` to validate an input. If it's valid, Zod returns a strongly-typed _deep clone_ of the input. + +```ts +Player.parse({ username: "billie", xp: 100 }); +// => returns { username: "billie", xp: 100 } +``` + +**Note** — If your schema uses certain asynchronous APIs like `async` [refinements](#refine) or [transforms](#transform), you'll need to use the `.parseAsync()` method instead. + +```ts +const schema = z.string().refine(async (val) => val.length <= 8); + +await schema.parseAsync("hello"); +// => "hello" +``` + +### Handling errors + +When validation fails, the `.parse()` method will throw a `ZodError` instance with granular information about the validation issues. + +```ts +try { + Player.parse({ username: 42, xp: "100" }); +} catch (err) { + if (err instanceof z.ZodError) { + err.issues; + /* [ + { + expected: 'string', + code: 'invalid_type', + path: [ 'username' ], + message: 'Invalid input: expected string' + }, + { + expected: 'number', + code: 'invalid_type', + path: [ 'xp' ], + message: 'Invalid input: expected number' + } + ] */ + } +} +``` + +To avoid a `try/catch` block, you can use the `.safeParse()` method to get back a plain result object containing either the successfully parsed data or a `ZodError`. The result type is a [discriminated union](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#discriminated-unions), so you can handle both cases conveniently. + +```ts +const result = Player.safeParse({ username: 42, xp: "100" }); +if (!result.success) { + result.error; // ZodError instance +} else { + result.data; // { username: string; xp: number } +} +``` + +**Note** — If your schema uses certain asynchronous APIs like `async` [refinements](#refine) or [transforms](#transform), you'll need to use the `.safeParseAsync()` method instead. + +```ts +const schema = z.string().refine(async (val) => val.length <= 8); + +await schema.safeParseAsync("hello"); +// => { success: true; data: "hello" } +``` + +### Inferring types + +Zod infers a static type from your schema definitions. You can extract this type with the `z.infer<>` utility and use it however you like. + +```ts +const Player = z.object({ + username: z.string(), + xp: z.number(), +}); + +// extract the inferred type +type Player = z.infer; + +// use it in your code +const player: Player = { username: "billie", xp: 100 }; +``` + +In some cases, the input & output types of a schema can diverge. For instance, the `.transform()` API can convert the input from one type to another. In these cases, you can extract the input and output types independently: + +```ts +const mySchema = z.string().transform((val) => val.length); + +type MySchemaIn = z.input; +// => string + +type MySchemaOut = z.output; // equivalent to z.infer +// number +``` diff --git a/node_modules/zod/index.cjs b/node_modules/zod/index.cjs new file mode 100644 index 0000000..3e30380 --- /dev/null +++ b/node_modules/zod/index.cjs @@ -0,0 +1,33 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.z = void 0; +const z = __importStar(require("./v4/classic/external.cjs")); +exports.z = z; +__exportStar(require("./v4/classic/external.cjs"), exports); +exports.default = z; diff --git a/node_modules/zod/index.d.cts b/node_modules/zod/index.d.cts new file mode 100644 index 0000000..ed2f3c3 --- /dev/null +++ b/node_modules/zod/index.d.cts @@ -0,0 +1,4 @@ +import * as z from "./v4/classic/external.cjs"; +export * from "./v4/classic/external.cjs"; +export { z }; +export default z; diff --git a/node_modules/zod/index.d.ts b/node_modules/zod/index.d.ts new file mode 100644 index 0000000..b0bbaef --- /dev/null +++ b/node_modules/zod/index.d.ts @@ -0,0 +1,4 @@ +import * as z from "./v4/classic/external.js"; +export * from "./v4/classic/external.js"; +export { z }; +export default z; diff --git a/node_modules/zod/index.js b/node_modules/zod/index.js new file mode 100644 index 0000000..b0bbaef --- /dev/null +++ b/node_modules/zod/index.js @@ -0,0 +1,4 @@ +import * as z from "./v4/classic/external.js"; +export * from "./v4/classic/external.js"; +export { z }; +export default z; diff --git a/node_modules/zod/locales/index.cjs b/node_modules/zod/locales/index.cjs new file mode 100644 index 0000000..65f2079 --- /dev/null +++ b/node_modules/zod/locales/index.cjs @@ -0,0 +1,17 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("../v4/locales/index.cjs"), exports); diff --git a/node_modules/zod/locales/index.d.cts b/node_modules/zod/locales/index.d.cts new file mode 100644 index 0000000..cd70ce6 --- /dev/null +++ b/node_modules/zod/locales/index.d.cts @@ -0,0 +1 @@ +export * from "../v4/locales/index.cjs"; diff --git a/node_modules/zod/locales/index.d.ts b/node_modules/zod/locales/index.d.ts new file mode 100644 index 0000000..e6e7dd6 --- /dev/null +++ b/node_modules/zod/locales/index.d.ts @@ -0,0 +1 @@ +export * from "../v4/locales/index.js"; diff --git a/node_modules/zod/locales/index.js b/node_modules/zod/locales/index.js new file mode 100644 index 0000000..e6e7dd6 --- /dev/null +++ b/node_modules/zod/locales/index.js @@ -0,0 +1 @@ +export * from "../v4/locales/index.js"; diff --git a/node_modules/zod/mini/index.cjs b/node_modules/zod/mini/index.cjs new file mode 100644 index 0000000..fcc365e --- /dev/null +++ b/node_modules/zod/mini/index.cjs @@ -0,0 +1,17 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +__exportStar(require("../v4/mini/index.cjs"), exports); diff --git a/node_modules/zod/mini/index.d.cts b/node_modules/zod/mini/index.d.cts new file mode 100644 index 0000000..511ff3a --- /dev/null +++ b/node_modules/zod/mini/index.d.cts @@ -0,0 +1 @@ +export * from "../v4/mini/index.cjs"; diff --git a/node_modules/zod/mini/index.d.ts b/node_modules/zod/mini/index.d.ts new file mode 100644 index 0000000..87b293a --- /dev/null +++ b/node_modules/zod/mini/index.d.ts @@ -0,0 +1 @@ +export * from "../v4/mini/index.js"; diff --git a/node_modules/zod/mini/index.js b/node_modules/zod/mini/index.js new file mode 100644 index 0000000..87b293a --- /dev/null +++ b/node_modules/zod/mini/index.js @@ -0,0 +1 @@ +export * from "../v4/mini/index.js"; diff --git a/node_modules/zod/package.json b/node_modules/zod/package.json new file mode 100644 index 0000000..9315f97 --- /dev/null +++ b/node_modules/zod/package.json @@ -0,0 +1,134 @@ +{ + "name": "zod", + "version": "4.0.14", + "type": "module", + "license": "MIT", + "author": "Colin McDonnell ", + "description": "TypeScript-first schema declaration and validation library with static type inference", + "homepage": "https://zod.dev", + "llms": "https://zod.dev/llms.txt", + "llmsFull": "https://zod.dev/llms-full.txt", + "mcpServer": "https://mcp.inkeep.com/zod/mcp", + "funding": "https://github.com/sponsors/colinhacks", + "sideEffects": false, + "files": [ + "src", + "**/*.js", + "**/*.mjs", + "**/*.cjs", + "**/*.d.ts", + "**/*.d.mts", + "**/*.d.cts" + ], + "keywords": [ + "typescript", + "schema", + "validation", + "type", + "inference" + ], + "main": "./index.cjs", + "types": "./index.d.cts", + "module": "./index.js", + "zshy": { + "exports": { + "./package.json": "./package.json", + ".": "./src/index.ts", + "./mini": "./src/mini/index.ts", + "./locales": "./src/locales/index.ts", + "./v3": "./src/v3/index.ts", + "./v4": "./src/v4/index.ts", + "./v4-mini": "./src/v4-mini/index.ts", + "./v4/mini": "./src/v4/mini/index.ts", + "./v4/core": "./src/v4/core/index.ts", + "./v4/locales": "./src/v4/locales/index.ts", + "./v4/locales/*": "./src/v4/locales/*" + }, + "conditions": { + "@zod/source": "src" + } + }, + "exports": { + "./package.json": "./package.json", + ".": { + "@zod/source": "./src/index.ts", + "types": "./index.d.cts", + "import": "./index.js", + "require": "./index.cjs" + }, + "./mini": { + "@zod/source": "./src/mini/index.ts", + "types": "./mini/index.d.cts", + "import": "./mini/index.js", + "require": "./mini/index.cjs" + }, + "./locales": { + "@zod/source": "./src/locales/index.ts", + "types": "./locales/index.d.cts", + "import": "./locales/index.js", + "require": "./locales/index.cjs" + }, + "./v3": { + "@zod/source": "./src/v3/index.ts", + "types": "./v3/index.d.cts", + "import": "./v3/index.js", + "require": "./v3/index.cjs" + }, + "./v4": { + "@zod/source": "./src/v4/index.ts", + "types": "./v4/index.d.cts", + "import": "./v4/index.js", + "require": "./v4/index.cjs" + }, + "./v4-mini": { + "@zod/source": "./src/v4-mini/index.ts", + "types": "./v4-mini/index.d.cts", + "import": "./v4-mini/index.js", + "require": "./v4-mini/index.cjs" + }, + "./v4/mini": { + "@zod/source": "./src/v4/mini/index.ts", + "types": "./v4/mini/index.d.cts", + "import": "./v4/mini/index.js", + "require": "./v4/mini/index.cjs" + }, + "./v4/core": { + "@zod/source": "./src/v4/core/index.ts", + "types": "./v4/core/index.d.cts", + "import": "./v4/core/index.js", + "require": "./v4/core/index.cjs" + }, + "./v4/locales": { + "@zod/source": "./src/v4/locales/index.ts", + "types": "./v4/locales/index.d.cts", + "import": "./v4/locales/index.js", + "require": "./v4/locales/index.cjs" + }, + "./v4/locales/*": { + "@zod/source": "./src/v4/locales/*", + "types": "./v4/locales/*", + "import": "./v4/locales/*", + "require": "./v4/locales/*" + } + }, + "repository": { + "type": "git", + "url": "git+https://github.com/colinhacks/zod.git" + }, + "bugs": { + "url": "https://github.com/colinhacks/zod/issues" + }, + "support": { + "backing": { + "npm-funding": true + } + }, + "scripts": { + "clean": "git clean -xdf . -e node_modules", + "build": "zshy --project tsconfig.build.json", + "postbuild": "pnpm biome check --write .", + "test:watch": "pnpm vitest", + "test": "pnpm vitest run", + "prepublishOnly": "tsx ../../scripts/check-versions.ts" + } +} diff --git a/node_modules/zod/src/index.ts b/node_modules/zod/src/index.ts new file mode 100644 index 0000000..b0bbaef --- /dev/null +++ b/node_modules/zod/src/index.ts @@ -0,0 +1,4 @@ +import * as z from "./v4/classic/external.js"; +export * from "./v4/classic/external.js"; +export { z }; +export default z; diff --git a/node_modules/zod/src/locales/index.ts b/node_modules/zod/src/locales/index.ts new file mode 100644 index 0000000..e6e7dd6 --- /dev/null +++ b/node_modules/zod/src/locales/index.ts @@ -0,0 +1 @@ +export * from "../v4/locales/index.js"; diff --git a/node_modules/zod/src/mini/index.ts b/node_modules/zod/src/mini/index.ts new file mode 100644 index 0000000..87b293a --- /dev/null +++ b/node_modules/zod/src/mini/index.ts @@ -0,0 +1 @@ +export * from "../v4/mini/index.js"; diff --git a/node_modules/zod/src/v3/ZodError.ts b/node_modules/zod/src/v3/ZodError.ts new file mode 100644 index 0000000..6ee33c1 --- /dev/null +++ b/node_modules/zod/src/v3/ZodError.ts @@ -0,0 +1,330 @@ +import type { Primitive } from "./helpers/typeAliases.js"; +import { util, type ZodParsedType } from "./helpers/util.js"; +import type { TypeOf, ZodType } from "./index.js"; + +type allKeys = T extends any ? keyof T : never; + +export type inferFlattenedErrors, U = string> = typeToFlattenedError, U>; +export type typeToFlattenedError = { + formErrors: U[]; + fieldErrors: { + [P in allKeys]?: U[]; + }; +}; + +export const ZodIssueCode = util.arrayToEnum([ + "invalid_type", + "invalid_literal", + "custom", + "invalid_union", + "invalid_union_discriminator", + "invalid_enum_value", + "unrecognized_keys", + "invalid_arguments", + "invalid_return_type", + "invalid_date", + "invalid_string", + "too_small", + "too_big", + "invalid_intersection_types", + "not_multiple_of", + "not_finite", +]); + +export type ZodIssueCode = keyof typeof ZodIssueCode; + +export type ZodIssueBase = { + path: (string | number)[]; + message?: string | undefined; +}; + +export interface ZodInvalidTypeIssue extends ZodIssueBase { + code: typeof ZodIssueCode.invalid_type; + expected: ZodParsedType; + received: ZodParsedType; +} + +export interface ZodInvalidLiteralIssue extends ZodIssueBase { + code: typeof ZodIssueCode.invalid_literal; + expected: unknown; + received: unknown; +} + +export interface ZodUnrecognizedKeysIssue extends ZodIssueBase { + code: typeof ZodIssueCode.unrecognized_keys; + keys: string[]; +} + +export interface ZodInvalidUnionIssue extends ZodIssueBase { + code: typeof ZodIssueCode.invalid_union; + unionErrors: ZodError[]; +} + +export interface ZodInvalidUnionDiscriminatorIssue extends ZodIssueBase { + code: typeof ZodIssueCode.invalid_union_discriminator; + options: Primitive[]; +} + +export interface ZodInvalidEnumValueIssue extends ZodIssueBase { + received: string | number; + code: typeof ZodIssueCode.invalid_enum_value; + options: (string | number)[]; +} + +export interface ZodInvalidArgumentsIssue extends ZodIssueBase { + code: typeof ZodIssueCode.invalid_arguments; + argumentsError: ZodError; +} + +export interface ZodInvalidReturnTypeIssue extends ZodIssueBase { + code: typeof ZodIssueCode.invalid_return_type; + returnTypeError: ZodError; +} + +export interface ZodInvalidDateIssue extends ZodIssueBase { + code: typeof ZodIssueCode.invalid_date; +} + +export type StringValidation = + | "email" + | "url" + | "emoji" + | "uuid" + | "nanoid" + | "regex" + | "cuid" + | "cuid2" + | "ulid" + | "datetime" + | "date" + | "time" + | "duration" + | "ip" + | "cidr" + | "base64" + | "jwt" + | "base64url" + | { includes: string; position?: number | undefined } + | { startsWith: string } + | { endsWith: string }; + +export interface ZodInvalidStringIssue extends ZodIssueBase { + code: typeof ZodIssueCode.invalid_string; + validation: StringValidation; +} + +export interface ZodTooSmallIssue extends ZodIssueBase { + code: typeof ZodIssueCode.too_small; + minimum: number | bigint; + inclusive: boolean; + exact?: boolean; + type: "array" | "string" | "number" | "set" | "date" | "bigint"; +} + +export interface ZodTooBigIssue extends ZodIssueBase { + code: typeof ZodIssueCode.too_big; + maximum: number | bigint; + inclusive: boolean; + exact?: boolean; + type: "array" | "string" | "number" | "set" | "date" | "bigint"; +} + +export interface ZodInvalidIntersectionTypesIssue extends ZodIssueBase { + code: typeof ZodIssueCode.invalid_intersection_types; +} + +export interface ZodNotMultipleOfIssue extends ZodIssueBase { + code: typeof ZodIssueCode.not_multiple_of; + multipleOf: number | bigint; +} + +export interface ZodNotFiniteIssue extends ZodIssueBase { + code: typeof ZodIssueCode.not_finite; +} + +export interface ZodCustomIssue extends ZodIssueBase { + code: typeof ZodIssueCode.custom; + params?: { [k: string]: any }; +} + +export type DenormalizedError = { [k: string]: DenormalizedError | string[] }; + +export type ZodIssueOptionalMessage = + | ZodInvalidTypeIssue + | ZodInvalidLiteralIssue + | ZodUnrecognizedKeysIssue + | ZodInvalidUnionIssue + | ZodInvalidUnionDiscriminatorIssue + | ZodInvalidEnumValueIssue + | ZodInvalidArgumentsIssue + | ZodInvalidReturnTypeIssue + | ZodInvalidDateIssue + | ZodInvalidStringIssue + | ZodTooSmallIssue + | ZodTooBigIssue + | ZodInvalidIntersectionTypesIssue + | ZodNotMultipleOfIssue + | ZodNotFiniteIssue + | ZodCustomIssue; + +export type ZodIssue = ZodIssueOptionalMessage & { + fatal?: boolean | undefined; + message: string; +}; + +export const quotelessJson = (obj: any) => { + const json = JSON.stringify(obj, null, 2); + return json.replace(/"([^"]+)":/g, "$1:"); +}; + +type recursiveZodFormattedError = T extends [any, ...any[]] + ? { [K in keyof T]?: ZodFormattedError } + : T extends any[] + ? { [k: number]: ZodFormattedError } + : T extends object + ? { [K in keyof T]?: ZodFormattedError } + : unknown; + +export type ZodFormattedError = { + _errors: U[]; +} & recursiveZodFormattedError>; + +export type inferFormattedError, U = string> = ZodFormattedError, U>; + +export class ZodError extends Error { + issues: ZodIssue[] = []; + + get errors() { + return this.issues; + } + + constructor(issues: ZodIssue[]) { + super(); + + const actualProto = new.target.prototype; + if (Object.setPrototypeOf) { + // eslint-disable-next-line ban/ban + Object.setPrototypeOf(this, actualProto); + } else { + (this as any).__proto__ = actualProto; + } + this.name = "ZodError"; + this.issues = issues; + } + + format(): ZodFormattedError; + format(mapper: (issue: ZodIssue) => U): ZodFormattedError; + format(_mapper?: any) { + const mapper: (issue: ZodIssue) => any = + _mapper || + function (issue: ZodIssue) { + return issue.message; + }; + const fieldErrors: ZodFormattedError = { _errors: [] } as any; + const processError = (error: ZodError) => { + for (const issue of error.issues) { + if (issue.code === "invalid_union") { + issue.unionErrors.map(processError); + } else if (issue.code === "invalid_return_type") { + processError(issue.returnTypeError); + } else if (issue.code === "invalid_arguments") { + processError(issue.argumentsError); + } else if (issue.path.length === 0) { + (fieldErrors as any)._errors.push(mapper(issue)); + } else { + let curr: any = fieldErrors; + let i = 0; + while (i < issue.path.length) { + const el = issue.path[i]!; + const terminal = i === issue.path.length - 1; + + if (!terminal) { + curr[el] = curr[el] || { _errors: [] }; + // if (typeof el === "string") { + // curr[el] = curr[el] || { _errors: [] }; + // } else if (typeof el === "number") { + // const errorArray: any = []; + // errorArray._errors = []; + // curr[el] = curr[el] || errorArray; + // } + } else { + curr[el] = curr[el] || { _errors: [] }; + curr[el]._errors.push(mapper(issue)); + } + + curr = curr[el]; + i++; + } + } + } + }; + + processError(this); + return fieldErrors; + } + + static create = (issues: ZodIssue[]) => { + const error = new ZodError(issues); + return error; + }; + + static assert(value: unknown): asserts value is ZodError { + if (!(value instanceof ZodError)) { + throw new Error(`Not a ZodError: ${value}`); + } + } + + override toString() { + return this.message; + } + override get message() { + return JSON.stringify(this.issues, util.jsonStringifyReplacer, 2); + } + + get isEmpty(): boolean { + return this.issues.length === 0; + } + + addIssue = (sub: ZodIssue) => { + this.issues = [...this.issues, sub]; + }; + + addIssues = (subs: ZodIssue[] = []) => { + this.issues = [...this.issues, ...subs]; + }; + + flatten(): typeToFlattenedError; + flatten(mapper?: (issue: ZodIssue) => U): typeToFlattenedError; + flatten(mapper: (issue: ZodIssue) => U = (issue: ZodIssue) => issue.message as any): any { + const fieldErrors: any = {}; + const formErrors: U[] = []; + for (const sub of this.issues) { + if (sub.path.length > 0) { + const firstEl = sub.path[0]!; + fieldErrors[firstEl] = fieldErrors[firstEl] || []; + fieldErrors[firstEl].push(mapper(sub)); + } else { + formErrors.push(mapper(sub)); + } + } + return { formErrors, fieldErrors }; + } + + get formErrors() { + return this.flatten(); + } +} + +type stripPath = T extends any ? util.OmitKeys : never; + +export type IssueData = stripPath & { + path?: (string | number)[]; + fatal?: boolean | undefined; +}; + +export type ErrorMapCtx = { + defaultError: string; + data: any; +}; + +export type ZodErrorMap = (issue: ZodIssueOptionalMessage, _ctx: ErrorMapCtx) => { message: string }; diff --git a/node_modules/zod/src/v3/benchmarks/datetime.ts b/node_modules/zod/src/v3/benchmarks/datetime.ts new file mode 100644 index 0000000..85552c2 --- /dev/null +++ b/node_modules/zod/src/v3/benchmarks/datetime.ts @@ -0,0 +1,58 @@ +import Benchmark from "benchmark"; + +const datetimeValidationSuite = new Benchmark.Suite("datetime"); + +const DATA = "2021-01-01"; +const MONTHS_31 = new Set([1, 3, 5, 7, 8, 10, 12]); +const MONTHS_30 = new Set([4, 6, 9, 11]); + +const simpleDatetimeRegex = /^(\d{4})-(\d{2})-(\d{2})$/; +const datetimeRegexNoLeapYearValidation = + /^\d{4}-((0[13578]|10|12)-31|(0[13-9]|1[0-2])-30|(0[1-9]|1[0-2])-(0[1-9]|1\d|2\d))$/; +const datetimeRegexWithLeapYearValidation = + /^((\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\d|3[01])|(0[469]|11)-(0[1-9]|[12]\d|30)|(02)-(0[1-9]|1\d|2[0-8])))$/; + +datetimeValidationSuite + .add("new Date()", () => { + return !Number.isNaN(new Date(DATA).getTime()); + }) + .add("regex (no validation)", () => { + return simpleDatetimeRegex.test(DATA); + }) + .add("regex (no leap year)", () => { + return datetimeRegexNoLeapYearValidation.test(DATA); + }) + .add("regex (w/ leap year)", () => { + return datetimeRegexWithLeapYearValidation.test(DATA); + }) + .add("capture groups + code", () => { + const match = DATA.match(simpleDatetimeRegex); + if (!match) return false; + + // Extract year, month, and day from the capture groups + const year = Number.parseInt(match[1], 10); + const month = Number.parseInt(match[2], 10); // month is 0-indexed in JavaScript Date, so subtract 1 + const day = Number.parseInt(match[3], 10); + + if (month === 2) { + if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) { + return day <= 29; + } + return day <= 28; + } + if (MONTHS_30.has(month)) { + return day <= 30; + } + if (MONTHS_31.has(month)) { + return day <= 31; + } + return false; + }) + + .on("cycle", (e: Benchmark.Event) => { + console.log(`${datetimeValidationSuite.name!}: ${e.target}`); + }); + +export default { + suites: [datetimeValidationSuite], +}; diff --git a/node_modules/zod/src/v3/benchmarks/discriminatedUnion.ts b/node_modules/zod/src/v3/benchmarks/discriminatedUnion.ts new file mode 100644 index 0000000..47737e6 --- /dev/null +++ b/node_modules/zod/src/v3/benchmarks/discriminatedUnion.ts @@ -0,0 +1,80 @@ +import Benchmark from "benchmark"; + +import { z } from "zod/v3"; + +const doubleSuite = new Benchmark.Suite("z.discriminatedUnion: double"); +const manySuite = new Benchmark.Suite("z.discriminatedUnion: many"); + +const aSchema = z.object({ + type: z.literal("a"), +}); +const objA = { + type: "a", +}; + +const bSchema = z.object({ + type: z.literal("b"), +}); +const objB = { + type: "b", +}; + +const cSchema = z.object({ + type: z.literal("c"), +}); +const objC = { + type: "c", +}; + +const dSchema = z.object({ + type: z.literal("d"), +}); + +const double = z.discriminatedUnion("type", [aSchema, bSchema]); +const many = z.discriminatedUnion("type", [aSchema, bSchema, cSchema, dSchema]); + +doubleSuite + .add("valid: a", () => { + double.parse(objA); + }) + .add("valid: b", () => { + double.parse(objB); + }) + .add("invalid: null", () => { + try { + double.parse(null); + } catch (_err) {} + }) + .add("invalid: wrong shape", () => { + try { + double.parse(objC); + } catch (_err) {} + }) + .on("cycle", (e: Benchmark.Event) => { + console.log(`${(doubleSuite as any).name}: ${e.target}`); + }); + +manySuite + .add("valid: a", () => { + many.parse(objA); + }) + .add("valid: c", () => { + many.parse(objC); + }) + .add("invalid: null", () => { + try { + many.parse(null); + } catch (_err) {} + }) + .add("invalid: wrong shape", () => { + try { + many.parse({ type: "unknown" }); + } catch (_err) {} + }) + .on("cycle", (e: Benchmark.Event) => { + console.log(`${(manySuite as any).name}: ${e.target}`); + }); + +export default { + suites: [doubleSuite, manySuite], +}; diff --git a/node_modules/zod/src/v3/benchmarks/index.ts b/node_modules/zod/src/v3/benchmarks/index.ts new file mode 100644 index 0000000..ca81c5b --- /dev/null +++ b/node_modules/zod/src/v3/benchmarks/index.ts @@ -0,0 +1,59 @@ +import type Benchmark from "benchmark"; + +import datetimeBenchmarks from "./datetime.js"; +import discriminatedUnionBenchmarks from "./discriminatedUnion.js"; +import ipv4Benchmarks from "./ipv4.js"; +import objectBenchmarks from "./object.js"; +import primitiveBenchmarks from "./primitives.js"; +import realworld from "./realworld.js"; +import stringBenchmarks from "./string.js"; +import unionBenchmarks from "./union.js"; + +const argv = process.argv.slice(2); +let suites: Benchmark.Suite[] = []; + +if (!argv.length) { + suites = [ + ...realworld.suites, + ...primitiveBenchmarks.suites, + ...stringBenchmarks.suites, + ...objectBenchmarks.suites, + ...unionBenchmarks.suites, + ...discriminatedUnionBenchmarks.suites, + ]; +} else { + if (argv.includes("--realworld")) { + suites.push(...realworld.suites); + } + if (argv.includes("--primitives")) { + suites.push(...primitiveBenchmarks.suites); + } + if (argv.includes("--string")) { + suites.push(...stringBenchmarks.suites); + } + if (argv.includes("--object")) { + suites.push(...objectBenchmarks.suites); + } + if (argv.includes("--union")) { + suites.push(...unionBenchmarks.suites); + } + if (argv.includes("--discriminatedUnion")) { + suites.push(...datetimeBenchmarks.suites); + } + if (argv.includes("--datetime")) { + suites.push(...datetimeBenchmarks.suites); + } + if (argv.includes("--ipv4")) { + suites.push(...ipv4Benchmarks.suites); + } +} + +for (const suite of suites) { + suite.run({}); +} + +// exit on Ctrl-C +process.on("SIGINT", function () { + console.log("Exiting..."); + process.exit(); +}); diff --git a/node_modules/zod/src/v3/benchmarks/ipv4.ts b/node_modules/zod/src/v3/benchmarks/ipv4.ts new file mode 100644 index 0000000..913ffd4 --- /dev/null +++ b/node_modules/zod/src/v3/benchmarks/ipv4.ts @@ -0,0 +1,57 @@ +import Benchmark from "benchmark"; + +const suite = new Benchmark.Suite("ipv4"); + +const DATA = "127.0.0.1"; +const ipv4RegexA = + /^(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))$/; +const ipv4RegexB = + /^(?:(?:(?=(25[0-5]))\1|(?=(2[0-4][0-9]))\2|(?=(1[0-9]{2}))\3|(?=([0-9]{1,2}))\4)\.){3}(?:(?=(25[0-5]))\5|(?=(2[0-4][0-9]))\6|(?=(1[0-9]{2}))\7|(?=([0-9]{1,2}))\8)$/; +const ipv4RegexC = /^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/; +const ipv4RegexD = /^(\b25[0-5]|\b2[0-4][0-9]|\b[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/; +const ipv4RegexE = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.){3}(25[0-5]|(2[0-4]|1\d|[1-9]|)\d)$/; +const ipv4RegexF = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/; +const ipv4RegexG = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$/; +const ipv4RegexH = /^((25[0-5]|(2[0-4]|1[0-9]|[1-9]|)[0-9])(\.(?!$)|$)){4}$/; +const ipv4RegexI = + /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/; + +suite + .add("A", () => { + return ipv4RegexA.test(DATA); + }) + .add("B", () => { + return ipv4RegexB.test(DATA); + }) + .add("C", () => { + return ipv4RegexC.test(DATA); + }) + .add("D", () => { + return ipv4RegexD.test(DATA); + }) + .add("E", () => { + return ipv4RegexE.test(DATA); + }) + .add("F", () => { + return ipv4RegexF.test(DATA); + }) + .add("G", () => { + return ipv4RegexG.test(DATA); + }) + .add("H", () => { + return ipv4RegexH.test(DATA); + }) + .add("I", () => { + return ipv4RegexI.test(DATA); + }) + .on("cycle", (e: Benchmark.Event) => { + console.log(`${suite.name!}: ${e.target}`); + }); + +export default { + suites: [suite], +}; + +if (require.main === module) { + suite.run(); +} diff --git a/node_modules/zod/src/v3/benchmarks/object.ts b/node_modules/zod/src/v3/benchmarks/object.ts new file mode 100644 index 0000000..3c1da10 --- /dev/null +++ b/node_modules/zod/src/v3/benchmarks/object.ts @@ -0,0 +1,69 @@ +import Benchmark from "benchmark"; + +import { z } from "zod/v3"; + +const emptySuite = new Benchmark.Suite("z.object: empty"); +const shortSuite = new Benchmark.Suite("z.object: short"); +const longSuite = new Benchmark.Suite("z.object: long"); + +const empty = z.object({}); +const short = z.object({ + string: z.string(), +}); +const long = z.object({ + string: z.string(), + number: z.number(), + boolean: z.boolean(), +}); + +emptySuite + .add("valid", () => { + empty.parse({}); + }) + .add("valid: extra keys", () => { + empty.parse({ string: "string" }); + }) + .add("invalid: null", () => { + try { + empty.parse(null); + } catch (_err) {} + }) + .on("cycle", (e: Benchmark.Event) => { + console.log(`${(emptySuite as any).name}: ${e.target}`); + }); + +shortSuite + .add("valid", () => { + short.parse({ string: "string" }); + }) + .add("valid: extra keys", () => { + short.parse({ string: "string", number: 42 }); + }) + .add("invalid: null", () => { + try { + short.parse(null); + } catch (_err) {} + }) + .on("cycle", (e: Benchmark.Event) => { + console.log(`${(shortSuite as any).name}: ${e.target}`); + }); + +longSuite + .add("valid", () => { + long.parse({ string: "string", number: 42, boolean: true }); + }) + .add("valid: extra keys", () => { + long.parse({ string: "string", number: 42, boolean: true, list: [] }); + }) + .add("invalid: null", () => { + try { + long.parse(null); + } catch (_err) {} + }) + .on("cycle", (e: Benchmark.Event) => { + console.log(`${(longSuite as any).name}: ${e.target}`); + }); + +export default { + suites: [emptySuite, shortSuite, longSuite], +}; diff --git a/node_modules/zod/src/v3/benchmarks/primitives.ts b/node_modules/zod/src/v3/benchmarks/primitives.ts new file mode 100644 index 0000000..fd61b38 --- /dev/null +++ b/node_modules/zod/src/v3/benchmarks/primitives.ts @@ -0,0 +1,162 @@ +import Benchmark from "benchmark"; + +import { z } from "zod/v3"; +import { Mocker } from "../tests/Mocker.js"; + +const val = new Mocker(); + +const enumSuite = new Benchmark.Suite("z.enum"); +const enumSchema = z.enum(["a", "b", "c"]); + +enumSuite + .add("valid", () => { + enumSchema.parse("a"); + }) + .add("invalid", () => { + try { + enumSchema.parse("x"); + } catch (_e: any) {} + }) + .on("cycle", (e: Benchmark.Event) => { + console.log(`z.enum: ${e.target}`); + }); + +const longEnumSuite = new Benchmark.Suite("long z.enum"); +const longEnumSchema = z.enum([ + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "ten", + "eleven", + "twelve", + "thirteen", + "fourteen", + "fifteen", + "sixteen", + "seventeen", +]); + +longEnumSuite + .add("valid", () => { + longEnumSchema.parse("five"); + }) + .add("invalid", () => { + try { + longEnumSchema.parse("invalid"); + } catch (_e: any) {} + }) + .on("cycle", (e: Benchmark.Event) => { + console.log(`long z.enum: ${e.target}`); + }); + +const undefinedSuite = new Benchmark.Suite("z.undefined"); +const undefinedSchema = z.undefined(); + +undefinedSuite + .add("valid", () => { + undefinedSchema.parse(undefined); + }) + .add("invalid", () => { + try { + undefinedSchema.parse(1); + } catch (_e: any) {} + }) + .on("cycle", (e: Benchmark.Event) => { + console.log(`z.undefined: ${e.target}`); + }); + +const literalSuite = new Benchmark.Suite("z.literal"); +const short = "short"; +const bad = "bad"; +const literalSchema = z.literal("short"); + +literalSuite + .add("valid", () => { + literalSchema.parse(short); + }) + .add("invalid", () => { + try { + literalSchema.parse(bad); + } catch (_e: any) {} + }) + .on("cycle", (e: Benchmark.Event) => { + console.log(`z.literal: ${e.target}`); + }); + +const numberSuite = new Benchmark.Suite("z.number"); +const numberSchema = z.number().int(); + +numberSuite + .add("valid", () => { + numberSchema.parse(1); + }) + .add("invalid type", () => { + try { + numberSchema.parse("bad"); + } catch (_e: any) {} + }) + .add("invalid number", () => { + try { + numberSchema.parse(0.5); + } catch (_e: any) {} + }) + .on("cycle", (e: Benchmark.Event) => { + console.log(`z.number: ${e.target}`); + }); + +const dateSuite = new Benchmark.Suite("z.date"); + +const plainDate = z.date(); +const minMaxDate = z.date().min(new Date("2021-01-01")).max(new Date("2030-01-01")); + +dateSuite + .add("valid", () => { + plainDate.parse(new Date()); + }) + .add("invalid", () => { + try { + plainDate.parse(1); + } catch (_e: any) {} + }) + .add("valid min and max", () => { + minMaxDate.parse(new Date("2023-01-01")); + }) + .add("invalid min", () => { + try { + minMaxDate.parse(new Date("2019-01-01")); + } catch (_e: any) {} + }) + .add("invalid max", () => { + try { + minMaxDate.parse(new Date("2031-01-01")); + } catch (_e: any) {} + }) + .on("cycle", (e: Benchmark.Event) => { + console.log(`z.date: ${e.target}`); + }); + +const symbolSuite = new Benchmark.Suite("z.symbol"); +const symbolSchema = z.symbol(); + +symbolSuite + .add("valid", () => { + symbolSchema.parse(val.symbol); + }) + .add("invalid", () => { + try { + symbolSchema.parse(1); + } catch (_e: any) {} + }) + .on("cycle", (e: Benchmark.Event) => { + console.log(`z.symbol: ${e.target}`); + }); + +export default { + suites: [enumSuite, longEnumSuite, undefinedSuite, literalSuite, numberSuite, dateSuite, symbolSuite], +}; diff --git a/node_modules/zod/src/v3/benchmarks/realworld.ts b/node_modules/zod/src/v3/benchmarks/realworld.ts new file mode 100644 index 0000000..d64c4f0 --- /dev/null +++ b/node_modules/zod/src/v3/benchmarks/realworld.ts @@ -0,0 +1,63 @@ +import Benchmark from "benchmark"; + +import { z } from "zod/v3"; + +const shortSuite = new Benchmark.Suite("realworld"); + +const People = z.array( + z.object({ + type: z.literal("person"), + hair: z.enum(["blue", "brown"]), + active: z.boolean(), + name: z.string(), + age: z.number().int(), + hobbies: z.array(z.string()), + address: z.object({ + street: z.string(), + zip: z.string(), + country: z.string(), + }), + }) +); + +let i = 0; + +function num() { + return ++i; +} + +function str() { + return (++i % 100).toString(16); +} + +function array(fn: () => T): T[] { + return Array.from({ length: ++i % 10 }, () => fn()); +} + +const people = Array.from({ length: 100 }, () => { + return { + type: "person", + hair: i % 2 ? "blue" : "brown", + active: !!(i % 2), + name: str(), + age: num(), + hobbies: array(str), + address: { + street: str(), + zip: str(), + country: str(), + }, + }; +}); + +shortSuite + .add("valid", () => { + People.parse(people); + }) + .on("cycle", (e: Benchmark.Event) => { + console.log(`${(shortSuite as any).name}: ${e.target}`); + }); + +export default { + suites: [shortSuite], +}; diff --git a/node_modules/zod/src/v3/benchmarks/string.ts b/node_modules/zod/src/v3/benchmarks/string.ts new file mode 100644 index 0000000..6b3d29f --- /dev/null +++ b/node_modules/zod/src/v3/benchmarks/string.ts @@ -0,0 +1,55 @@ +import Benchmark from "benchmark"; + +import { z } from "zod/v3"; + +const SUITE_NAME = "z.string"; +const suite = new Benchmark.Suite(SUITE_NAME); + +const empty = ""; +const short = "short"; +const long = "long".repeat(256); +const manual = (str: unknown) => { + if (typeof str !== "string") { + throw new Error("Not a string"); + } + + return str; +}; +const stringSchema = z.string(); +const optionalStringSchema = z.string().optional(); +const optionalNullableStringSchema = z.string().optional().nullable(); + +suite + .add("empty string", () => { + stringSchema.parse(empty); + }) + .add("short string", () => { + stringSchema.parse(short); + }) + .add("long string", () => { + stringSchema.parse(long); + }) + .add("optional string", () => { + optionalStringSchema.parse(long); + }) + .add("nullable string", () => { + optionalNullableStringSchema.parse(long); + }) + .add("nullable (null) string", () => { + optionalNullableStringSchema.parse(null); + }) + .add("invalid: null", () => { + try { + stringSchema.parse(null); + } catch (_err) {} + }) + .add("manual parser: long", () => { + manual(long); + }) + .on("cycle", (e: Benchmark.Event) => { + console.log(`${SUITE_NAME}: ${e.target}`); + }); + +export default { + suites: [suite], +}; diff --git a/node_modules/zod/src/v3/benchmarks/union.ts b/node_modules/zod/src/v3/benchmarks/union.ts new file mode 100644 index 0000000..d716dce --- /dev/null +++ b/node_modules/zod/src/v3/benchmarks/union.ts @@ -0,0 +1,80 @@ +import Benchmark from "benchmark"; + +import { z } from "zod/v3"; + +const doubleSuite = new Benchmark.Suite("z.union: double"); +const manySuite = new Benchmark.Suite("z.union: many"); + +const aSchema = z.object({ + type: z.literal("a"), +}); +const objA = { + type: "a", +}; + +const bSchema = z.object({ + type: z.literal("b"), +}); +const objB = { + type: "b", +}; + +const cSchema = z.object({ + type: z.literal("c"), +}); +const objC = { + type: "c", +}; + +const dSchema = z.object({ + type: z.literal("d"), +}); + +const double = z.union([aSchema, bSchema]); +const many = z.union([aSchema, bSchema, cSchema, dSchema]); + +doubleSuite + .add("valid: a", () => { + double.parse(objA); + }) + .add("valid: b", () => { + double.parse(objB); + }) + .add("invalid: null", () => { + try { + double.parse(null); + } catch (_err) {} + }) + .add("invalid: wrong shape", () => { + try { + double.parse(objC); + } catch (_err) {} + }) + .on("cycle", (e: Benchmark.Event) => { + console.log(`${(doubleSuite as any).name}: ${e.target}`); + }); + +manySuite + .add("valid: a", () => { + many.parse(objA); + }) + .add("valid: c", () => { + many.parse(objC); + }) + .add("invalid: null", () => { + try { + many.parse(null); + } catch (_err) {} + }) + .add("invalid: wrong shape", () => { + try { + many.parse({ type: "unknown" }); + } catch (_err) {} + }) + .on("cycle", (e: Benchmark.Event) => { + console.log(`${(manySuite as any).name}: ${e.target}`); + }); + +export default { + suites: [doubleSuite, manySuite], +}; diff --git a/node_modules/zod/src/v3/errors.ts b/node_modules/zod/src/v3/errors.ts new file mode 100644 index 0000000..3c0dae6 --- /dev/null +++ b/node_modules/zod/src/v3/errors.ts @@ -0,0 +1,13 @@ +import type { ZodErrorMap } from "./ZodError.js"; +import defaultErrorMap from "./locales/en.js"; + +let overrideErrorMap = defaultErrorMap; +export { defaultErrorMap }; + +export function setErrorMap(map: ZodErrorMap) { + overrideErrorMap = map; +} + +export function getErrorMap() { + return overrideErrorMap; +} diff --git a/node_modules/zod/src/v3/external.ts b/node_modules/zod/src/v3/external.ts new file mode 100644 index 0000000..f0a4be4 --- /dev/null +++ b/node_modules/zod/src/v3/external.ts @@ -0,0 +1,6 @@ +export * from "./errors.js"; +export * from "./helpers/parseUtil.js"; +export * from "./helpers/typeAliases.js"; +export * from "./helpers/util.js"; +export * from "./types.js"; +export * from "./ZodError.js"; diff --git a/node_modules/zod/src/v3/helpers/enumUtil.ts b/node_modules/zod/src/v3/helpers/enumUtil.ts new file mode 100644 index 0000000..526b227 --- /dev/null +++ b/node_modules/zod/src/v3/helpers/enumUtil.ts @@ -0,0 +1,17 @@ +export namespace enumUtil { + type UnionToIntersectionFn = (T extends unknown ? (k: () => T) => void : never) extends ( + k: infer Intersection + ) => void + ? Intersection + : never; + + type GetUnionLast = UnionToIntersectionFn extends () => infer Last ? Last : never; + + type UnionToTuple = [T] extends [never] + ? Tuple + : UnionToTuple>, [GetUnionLast, ...Tuple]>; + + type CastToStringTuple = T extends [string, ...string[]] ? T : never; + + export type UnionToTupleString = CastToStringTuple>; +} diff --git a/node_modules/zod/src/v3/helpers/errorUtil.ts b/node_modules/zod/src/v3/helpers/errorUtil.ts new file mode 100644 index 0000000..319ef6b --- /dev/null +++ b/node_modules/zod/src/v3/helpers/errorUtil.ts @@ -0,0 +1,8 @@ +export namespace errorUtil { + export type ErrMessage = string | { message?: string | undefined }; + export const errToObj = (message?: ErrMessage): { message?: string | undefined } => + typeof message === "string" ? { message } : message || {}; + // biome-ignore lint: + export const toString = (message?: ErrMessage): string | undefined => + typeof message === "string" ? message : message?.message; +} diff --git a/node_modules/zod/src/v3/helpers/parseUtil.ts b/node_modules/zod/src/v3/helpers/parseUtil.ts new file mode 100644 index 0000000..1076ad9 --- /dev/null +++ b/node_modules/zod/src/v3/helpers/parseUtil.ts @@ -0,0 +1,176 @@ +import type { IssueData, ZodErrorMap, ZodIssue } from "../ZodError.js"; +import { getErrorMap } from "../errors.js"; +import defaultErrorMap from "../locales/en.js"; +import type { ZodParsedType } from "./util.js"; + +export const makeIssue = (params: { + data: any; + path: (string | number)[]; + errorMaps: ZodErrorMap[]; + issueData: IssueData; +}): ZodIssue => { + const { data, path, errorMaps, issueData } = params; + const fullPath = [...path, ...(issueData.path || [])]; + const fullIssue = { + ...issueData, + path: fullPath, + }; + + if (issueData.message !== undefined) { + return { + ...issueData, + path: fullPath, + message: issueData.message, + }; + } + + let errorMessage = ""; + const maps = errorMaps + .filter((m) => !!m) + .slice() + .reverse(); + for (const map of maps) { + errorMessage = map(fullIssue, { data, defaultError: errorMessage }).message; + } + + return { + ...issueData, + path: fullPath, + message: errorMessage, + }; +}; + +export type ParseParams = { + path: (string | number)[]; + errorMap: ZodErrorMap; + async: boolean; +}; + +export type ParsePathComponent = string | number; +export type ParsePath = ParsePathComponent[]; +export const EMPTY_PATH: ParsePath = []; + +export interface ParseContext { + readonly common: { + readonly issues: ZodIssue[]; + readonly contextualErrorMap?: ZodErrorMap | undefined; + readonly async: boolean; + }; + readonly path: ParsePath; + readonly schemaErrorMap?: ZodErrorMap | undefined; + readonly parent: ParseContext | null; + readonly data: any; + readonly parsedType: ZodParsedType; +} + +export type ParseInput = { + data: any; + path: (string | number)[]; + parent: ParseContext; +}; + +export function addIssueToContext(ctx: ParseContext, issueData: IssueData): void { + const overrideMap = getErrorMap(); + const issue = makeIssue({ + issueData: issueData, + data: ctx.data, + path: ctx.path, + errorMaps: [ + ctx.common.contextualErrorMap, // contextual error map is first priority + ctx.schemaErrorMap, // then schema-bound map if available + overrideMap, // then global override map + overrideMap === defaultErrorMap ? undefined : defaultErrorMap, // then global default map + ].filter((x) => !!x), + }); + ctx.common.issues.push(issue); +} + +export type ObjectPair = { + key: SyncParseReturnType; + value: SyncParseReturnType; +}; +export class ParseStatus { + value: "aborted" | "dirty" | "valid" = "valid"; + dirty(): void { + if (this.value === "valid") this.value = "dirty"; + } + abort(): void { + if (this.value !== "aborted") this.value = "aborted"; + } + + static mergeArray(status: ParseStatus, results: SyncParseReturnType[]): SyncParseReturnType { + const arrayValue: any[] = []; + for (const s of results) { + if (s.status === "aborted") return INVALID; + if (s.status === "dirty") status.dirty(); + arrayValue.push(s.value); + } + + return { status: status.value, value: arrayValue }; + } + + static async mergeObjectAsync( + status: ParseStatus, + pairs: { key: ParseReturnType; value: ParseReturnType }[] + ): Promise> { + const syncPairs: ObjectPair[] = []; + for (const pair of pairs) { + const key = await pair.key; + const value = await pair.value; + syncPairs.push({ + key, + value, + }); + } + return ParseStatus.mergeObjectSync(status, syncPairs); + } + + static mergeObjectSync( + status: ParseStatus, + pairs: { + key: SyncParseReturnType; + value: SyncParseReturnType; + alwaysSet?: boolean; + }[] + ): SyncParseReturnType { + const finalObject: any = {}; + for (const pair of pairs) { + const { key, value } = pair; + if (key.status === "aborted") return INVALID; + if (value.status === "aborted") return INVALID; + if (key.status === "dirty") status.dirty(); + if (value.status === "dirty") status.dirty(); + + if (key.value !== "__proto__" && (typeof value.value !== "undefined" || pair.alwaysSet)) { + finalObject[key.value] = value.value; + } + } + + return { status: status.value, value: finalObject }; + } +} +export interface ParseResult { + status: "aborted" | "dirty" | "valid"; + data: any; +} + +export type INVALID = { status: "aborted" }; +export const INVALID: INVALID = Object.freeze({ + status: "aborted", +}); + +export type DIRTY = { status: "dirty"; value: T }; +export const DIRTY = (value: T): DIRTY => ({ status: "dirty", value }); + +export type OK = { status: "valid"; value: T }; +export const OK = (value: T): OK => ({ status: "valid", value }); + +export type SyncParseReturnType = OK | DIRTY | INVALID; +export type AsyncParseReturnType = Promise>; +export type ParseReturnType = SyncParseReturnType | AsyncParseReturnType; + +export const isAborted = (x: ParseReturnType): x is INVALID => (x as any).status === "aborted"; +export const isDirty = (x: ParseReturnType): x is OK | DIRTY => (x as any).status === "dirty"; +export const isValid = (x: ParseReturnType): x is OK => (x as any).status === "valid"; +export const isAsync = (x: ParseReturnType): x is AsyncParseReturnType => + typeof Promise !== "undefined" && x instanceof Promise; diff --git a/node_modules/zod/src/v3/helpers/partialUtil.ts b/node_modules/zod/src/v3/helpers/partialUtil.ts new file mode 100644 index 0000000..0eff8ff --- /dev/null +++ b/node_modules/zod/src/v3/helpers/partialUtil.ts @@ -0,0 +1,34 @@ +import type { + ZodArray, + ZodNullable, + ZodObject, + ZodOptional, + ZodRawShape, + ZodTuple, + ZodTupleItems, + ZodTypeAny, +} from "../types.js"; + +export namespace partialUtil { + export type DeepPartial = T extends ZodObject + ? ZodObject< + { [k in keyof T["shape"]]: ZodOptional> }, + T["_def"]["unknownKeys"], + T["_def"]["catchall"] + > + : T extends ZodArray + ? ZodArray, Card> + : T extends ZodOptional + ? ZodOptional> + : T extends ZodNullable + ? ZodNullable> + : T extends ZodTuple + ? { + [k in keyof Items]: Items[k] extends ZodTypeAny ? DeepPartial : never; + } extends infer PI + ? PI extends ZodTupleItems + ? ZodTuple + : never + : never + : T; +} diff --git a/node_modules/zod/src/v3/helpers/typeAliases.ts b/node_modules/zod/src/v3/helpers/typeAliases.ts new file mode 100644 index 0000000..32df022 --- /dev/null +++ b/node_modules/zod/src/v3/helpers/typeAliases.ts @@ -0,0 +1,2 @@ +export type Primitive = string | number | symbol | bigint | boolean | null | undefined; +export type Scalars = Primitive | Primitive[]; diff --git a/node_modules/zod/src/v3/helpers/util.ts b/node_modules/zod/src/v3/helpers/util.ts new file mode 100644 index 0000000..030ea82 --- /dev/null +++ b/node_modules/zod/src/v3/helpers/util.ts @@ -0,0 +1,224 @@ +export namespace util { + type AssertEqual = (() => V extends T ? 1 : 2) extends () => V extends U ? 1 : 2 ? true : false; + + export type isAny = 0 extends 1 & T ? true : false; + export const assertEqual = (_: AssertEqual): void => {}; + export function assertIs(_arg: T): void {} + export function assertNever(_x: never): never { + throw new Error(); + } + + export type Omit = Pick>; + export type OmitKeys = Pick>; + export type MakePartial = Omit & Partial>; + export type Exactly = T & Record, never>; + export type InexactPartial = { [k in keyof T]?: T[k] | undefined }; + export const arrayToEnum = (items: U): { [k in U[number]]: k } => { + const obj: any = {}; + for (const item of items) { + obj[item] = item; + } + return obj; + }; + + export const getValidEnumValues = (obj: any): any[] => { + const validKeys = objectKeys(obj).filter((k: any) => typeof obj[obj[k]] !== "number"); + const filtered: any = {}; + for (const k of validKeys) { + filtered[k] = obj[k]; + } + return objectValues(filtered); + }; + + export const objectValues = (obj: any): any[] => { + return objectKeys(obj).map(function (e) { + return obj[e]; + }); + }; + + export const objectKeys: ObjectConstructor["keys"] = + typeof Object.keys === "function" // eslint-disable-line ban/ban + ? (obj: any) => Object.keys(obj) // eslint-disable-line ban/ban + : (object: any) => { + const keys = []; + for (const key in object) { + if (Object.prototype.hasOwnProperty.call(object, key)) { + keys.push(key); + } + } + return keys; + }; + + export const find = (arr: T[], checker: (arg: T) => any): T | undefined => { + for (const item of arr) { + if (checker(item)) return item; + } + return undefined; + }; + + export type identity = objectUtil.identity; + export type flatten = objectUtil.flatten; + + export type noUndefined = T extends undefined ? never : T; + + export const isInteger: NumberConstructor["isInteger"] = + typeof Number.isInteger === "function" + ? (val) => Number.isInteger(val) // eslint-disable-line ban/ban + : (val) => typeof val === "number" && Number.isFinite(val) && Math.floor(val) === val; + + export function joinValues(array: T, separator = " | "): string { + return array.map((val) => (typeof val === "string" ? `'${val}'` : val)).join(separator); + } + + export const jsonStringifyReplacer = (_: string, value: any): any => { + if (typeof value === "bigint") { + return value.toString(); + } + return value; + }; +} + +export namespace objectUtil { + export type MergeShapes = + // fast path when there is no keys overlap + keyof U & keyof V extends never + ? U & V + : { + [k in Exclude]: U[k]; + } & V; + + type optionalKeys = { + [k in keyof T]: undefined extends T[k] ? k : never; + }[keyof T]; + type requiredKeys = { + [k in keyof T]: undefined extends T[k] ? never : k; + }[keyof T]; + export type addQuestionMarks = { + [K in requiredKeys]: T[K]; + } & { + [K in optionalKeys]?: T[K]; + } & { [k in keyof T]?: unknown }; + + export type identity = T; + export type flatten = identity<{ [k in keyof T]: T[k] }>; + + export type noNeverKeys = { + [k in keyof T]: [T[k]] extends [never] ? never : k; + }[keyof T]; + + export type noNever = identity<{ + [k in noNeverKeys]: k extends keyof T ? T[k] : never; + }>; + + export const mergeShapes = (first: U, second: T): T & U => { + return { + ...first, + ...second, // second overwrites first + }; + }; + + export type extendShape = keyof A & keyof B extends never // fast path when there is no keys overlap + ? A & B + : { + [K in keyof A as K extends keyof B ? never : K]: A[K]; + } & { + [K in keyof B]: B[K]; + }; +} + +export const ZodParsedType: { + string: "string"; + nan: "nan"; + number: "number"; + integer: "integer"; + float: "float"; + boolean: "boolean"; + date: "date"; + bigint: "bigint"; + symbol: "symbol"; + function: "function"; + undefined: "undefined"; + null: "null"; + array: "array"; + object: "object"; + unknown: "unknown"; + promise: "promise"; + void: "void"; + never: "never"; + map: "map"; + set: "set"; +} = util.arrayToEnum([ + "string", + "nan", + "number", + "integer", + "float", + "boolean", + "date", + "bigint", + "symbol", + "function", + "undefined", + "null", + "array", + "object", + "unknown", + "promise", + "void", + "never", + "map", + "set", +]); + +export type ZodParsedType = keyof typeof ZodParsedType; + +export const getParsedType = (data: any): ZodParsedType => { + const t = typeof data; + + switch (t) { + case "undefined": + return ZodParsedType.undefined; + + case "string": + return ZodParsedType.string; + + case "number": + return Number.isNaN(data) ? ZodParsedType.nan : ZodParsedType.number; + + case "boolean": + return ZodParsedType.boolean; + + case "function": + return ZodParsedType.function; + + case "bigint": + return ZodParsedType.bigint; + + case "symbol": + return ZodParsedType.symbol; + + case "object": + if (Array.isArray(data)) { + return ZodParsedType.array; + } + if (data === null) { + return ZodParsedType.null; + } + if (data.then && typeof data.then === "function" && data.catch && typeof data.catch === "function") { + return ZodParsedType.promise; + } + if (typeof Map !== "undefined" && data instanceof Map) { + return ZodParsedType.map; + } + if (typeof Set !== "undefined" && data instanceof Set) { + return ZodParsedType.set; + } + if (typeof Date !== "undefined" && data instanceof Date) { + return ZodParsedType.date; + } + return ZodParsedType.object; + + default: + return ZodParsedType.unknown; + } +}; diff --git a/node_modules/zod/src/v3/index.ts b/node_modules/zod/src/v3/index.ts new file mode 100644 index 0000000..a9dab57 --- /dev/null +++ b/node_modules/zod/src/v3/index.ts @@ -0,0 +1,4 @@ +import * as z from "./external.js"; +export * from "./external.js"; +export { z }; +export default z; diff --git a/node_modules/zod/src/v3/locales/en.ts b/node_modules/zod/src/v3/locales/en.ts new file mode 100644 index 0000000..0264f82 --- /dev/null +++ b/node_modules/zod/src/v3/locales/en.ts @@ -0,0 +1,124 @@ +import { type ZodErrorMap, ZodIssueCode } from "../ZodError.js"; +import { util, ZodParsedType } from "../helpers/util.js"; + +const errorMap: ZodErrorMap = (issue, _ctx) => { + let message: string; + switch (issue.code) { + case ZodIssueCode.invalid_type: + if (issue.received === ZodParsedType.undefined) { + message = "Required"; + } else { + message = `Expected ${issue.expected}, received ${issue.received}`; + } + break; + case ZodIssueCode.invalid_literal: + message = `Invalid literal value, expected ${JSON.stringify(issue.expected, util.jsonStringifyReplacer)}`; + break; + case ZodIssueCode.unrecognized_keys: + message = `Unrecognized key(s) in object: ${util.joinValues(issue.keys, ", ")}`; + break; + case ZodIssueCode.invalid_union: + message = `Invalid input`; + break; + case ZodIssueCode.invalid_union_discriminator: + message = `Invalid discriminator value. Expected ${util.joinValues(issue.options)}`; + break; + case ZodIssueCode.invalid_enum_value: + message = `Invalid enum value. Expected ${util.joinValues(issue.options)}, received '${issue.received}'`; + break; + case ZodIssueCode.invalid_arguments: + message = `Invalid function arguments`; + break; + case ZodIssueCode.invalid_return_type: + message = `Invalid function return type`; + break; + case ZodIssueCode.invalid_date: + message = `Invalid date`; + break; + case ZodIssueCode.invalid_string: + if (typeof issue.validation === "object") { + if ("includes" in issue.validation) { + message = `Invalid input: must include "${issue.validation.includes}"`; + + if (typeof issue.validation.position === "number") { + message = `${message} at one or more positions greater than or equal to ${issue.validation.position}`; + } + } else if ("startsWith" in issue.validation) { + message = `Invalid input: must start with "${issue.validation.startsWith}"`; + } else if ("endsWith" in issue.validation) { + message = `Invalid input: must end with "${issue.validation.endsWith}"`; + } else { + util.assertNever(issue.validation); + } + } else if (issue.validation !== "regex") { + message = `Invalid ${issue.validation}`; + } else { + message = "Invalid"; + } + break; + case ZodIssueCode.too_small: + if (issue.type === "array") + message = `Array must contain ${ + issue.exact ? "exactly" : issue.inclusive ? `at least` : `more than` + } ${issue.minimum} element(s)`; + else if (issue.type === "string") + message = `String must contain ${ + issue.exact ? "exactly" : issue.inclusive ? `at least` : `over` + } ${issue.minimum} character(s)`; + else if (issue.type === "number") + message = `Number must be ${ + issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than ` + }${issue.minimum}`; + else if (issue.type === "bigint") + message = `Number must be ${ + issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than ` + }${issue.minimum}`; + else if (issue.type === "date") + message = `Date must be ${ + issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than ` + }${new Date(Number(issue.minimum))}`; + else message = "Invalid input"; + break; + case ZodIssueCode.too_big: + if (issue.type === "array") + message = `Array must contain ${ + issue.exact ? `exactly` : issue.inclusive ? `at most` : `less than` + } ${issue.maximum} element(s)`; + else if (issue.type === "string") + message = `String must contain ${ + issue.exact ? `exactly` : issue.inclusive ? `at most` : `under` + } ${issue.maximum} character(s)`; + else if (issue.type === "number") + message = `Number must be ${ + issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than` + } ${issue.maximum}`; + else if (issue.type === "bigint") + message = `BigInt must be ${ + issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than` + } ${issue.maximum}`; + else if (issue.type === "date") + message = `Date must be ${ + issue.exact ? `exactly` : issue.inclusive ? `smaller than or equal to` : `smaller than` + } ${new Date(Number(issue.maximum))}`; + else message = "Invalid input"; + break; + case ZodIssueCode.custom: + message = `Invalid input`; + break; + case ZodIssueCode.invalid_intersection_types: + message = `Intersection results could not be merged`; + break; + case ZodIssueCode.not_multiple_of: + message = `Number must be a multiple of ${issue.multipleOf}`; + break; + case ZodIssueCode.not_finite: + message = "Number must be finite"; + break; + default: + message = _ctx.defaultError; + util.assertNever(issue); + } + return { message }; +}; + +export default errorMap; diff --git a/node_modules/zod/src/v3/standard-schema.ts b/node_modules/zod/src/v3/standard-schema.ts new file mode 100644 index 0000000..07193fd --- /dev/null +++ b/node_modules/zod/src/v3/standard-schema.ts @@ -0,0 +1,113 @@ +/** + * The Standard Schema interface. + */ +export type StandardSchemaV1 = { + /** + * The Standard Schema properties. + */ + readonly "~standard": StandardSchemaV1.Props; +}; + +export declare namespace StandardSchemaV1 { + /** + * The Standard Schema properties interface. + */ + export interface Props { + /** + * The version number of the standard. + */ + readonly version: 1; + /** + * The vendor name of the schema library. + */ + readonly vendor: string; + /** + * Validates unknown input values. + */ + readonly validate: (value: unknown) => Result | Promise>; + /** + * Inferred types associated with the schema. + */ + readonly types?: Types | undefined; + } + + /** + * The result interface of the validate function. + */ + export type Result = SuccessResult | FailureResult; + + /** + * The result interface if validation succeeds. + */ + export interface SuccessResult { + /** + * The typed output value. + */ + readonly value: Output; + /** + * The non-existent issues. + */ + readonly issues?: undefined; + } + + /** + * The result interface if validation fails. + */ + export interface FailureResult { + /** + * The issues of failed validation. + */ + readonly issues: ReadonlyArray; + } + + /** + * The issue interface of the failure output. + */ + export interface Issue { + /** + * The error message of the issue. + */ + readonly message: string; + /** + * The path of the issue, if any. + */ + readonly path?: ReadonlyArray | undefined; + } + + /** + * The path segment interface of the issue. + */ + export interface PathSegment { + /** + * The key representing a path segment. + */ + readonly key: PropertyKey; + } + + /** + * The Standard Schema types interface. + */ + export interface Types { + /** + * The input type of the schema. + */ + readonly input: Input; + /** + * The output type of the schema. + */ + readonly output: Output; + } + + /** + * Infers the input type of a Standard Schema. + */ + export type InferInput = NonNullable["input"]; + + /** + * Infers the output type of a Standard Schema. + */ + export type InferOutput = NonNullable["output"]; + + // biome-ignore lint/complexity/noUselessEmptyExport: needed for granular visibility control of TS namespace + export {}; +} diff --git a/node_modules/zod/src/v3/tests/Mocker.ts b/node_modules/zod/src/v3/tests/Mocker.ts new file mode 100644 index 0000000..c9fbdd5 --- /dev/null +++ b/node_modules/zod/src/v3/tests/Mocker.ts @@ -0,0 +1,54 @@ +function getRandomInt(max: number) { + return Math.floor(Math.random() * Math.floor(max)); +} + +const testSymbol = Symbol("test"); + +export class Mocker { + pick = (...args: any[]): any => { + return args[getRandomInt(args.length)]; + }; + + get string(): string { + return Math.random().toString(36).substring(7); + } + get number(): number { + return Math.random() * 100; + } + get bigint(): bigint { + return BigInt(Math.floor(Math.random() * 10000)); + } + get boolean(): boolean { + return Math.random() < 0.5; + } + get date(): Date { + return new Date(Math.floor(Date.now() * Math.random())); + } + get symbol(): symbol { + return testSymbol; + } + get null(): null { + return null; + } + get undefined(): undefined { + return undefined; + } + get stringOptional(): string | undefined { + return this.pick(this.string, this.undefined); + } + get stringNullable(): string | null { + return this.pick(this.string, this.null); + } + get numberOptional(): number | undefined { + return this.pick(this.number, this.undefined); + } + get numberNullable(): number | null { + return this.pick(this.number, this.null); + } + get booleanOptional(): boolean | undefined { + return this.pick(this.boolean, this.undefined); + } + get booleanNullable(): boolean | null { + return this.pick(this.boolean, this.null); + } +} diff --git a/node_modules/zod/src/v3/tests/all-errors.test.ts b/node_modules/zod/src/v3/tests/all-errors.test.ts new file mode 100644 index 0000000..8fdf8f4 --- /dev/null +++ b/node_modules/zod/src/v3/tests/all-errors.test.ts @@ -0,0 +1,157 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { util } from "../helpers/util.js"; + +const Test = z.object({ + f1: z.number(), + f2: z.string().optional(), + f3: z.string().nullable(), + f4: z.array(z.object({ t: z.union([z.string(), z.boolean()]) })), +}); +type TestFlattenedErrors = z.inferFlattenedErrors; +type TestFormErrors = z.inferFlattenedErrors; + +test("default flattened errors type inference", () => { + type TestTypeErrors = { + formErrors: string[]; + fieldErrors: { [P in keyof z.TypeOf]?: string[] | undefined }; + }; + + util.assertEqual, TestTypeErrors>(true); + util.assertEqual, TestTypeErrors>(false); +}); + +test("custom flattened errors type inference", () => { + type ErrorType = { message: string; code: number }; + type TestTypeErrors = { + formErrors: ErrorType[]; + fieldErrors: { + [P in keyof z.TypeOf]?: ErrorType[] | undefined; + }; + }; + + util.assertEqual, TestTypeErrors>(false); + util.assertEqual, TestTypeErrors>(true); + util.assertEqual, TestTypeErrors>(false); +}); + +test("form errors type inference", () => { + type TestTypeErrors = { + formErrors: string[]; + fieldErrors: { [P in keyof z.TypeOf]?: string[] | undefined }; + }; + + util.assertEqual, TestTypeErrors>(true); +}); + +test(".flatten() type assertion", () => { + const parsed = Test.safeParse({}) as z.SafeParseError; + const validFlattenedErrors: TestFlattenedErrors = parsed.error.flatten(() => ({ message: "", code: 0 })); + // @ts-expect-error should fail assertion between `TestFlattenedErrors` and unmapped `flatten()`. + const invalidFlattenedErrors: TestFlattenedErrors = parsed.error.flatten(); + const validFormErrors: TestFormErrors = parsed.error.flatten(); + // @ts-expect-error should fail assertion between `TestFormErrors` and mapped `flatten()`. + const invalidFormErrors: TestFormErrors = parsed.error.flatten(() => ({ + message: "string", + code: 0, + })); + + [validFlattenedErrors, invalidFlattenedErrors, validFormErrors, invalidFormErrors]; +}); + +test(".formErrors type assertion", () => { + const parsed = Test.safeParse({}) as z.SafeParseError; + const validFormErrors: TestFormErrors = parsed.error.formErrors; + // @ts-expect-error should fail assertion between `TestFlattenedErrors` and `.formErrors`. + const invalidFlattenedErrors: TestFlattenedErrors = parsed.error.formErrors; + + [validFormErrors, invalidFlattenedErrors]; +}); + +test("all errors", () => { + const propertySchema = z.string(); + const schema = z + .object({ + a: propertySchema, + b: propertySchema, + }) + .refine( + (val) => { + return val.a === val.b; + }, + { message: "Must be equal" } + ); + + try { + schema.parse({ + a: "asdf", + b: "qwer", + }); + } catch (error) { + if (error instanceof z.ZodError) { + expect(error.flatten()).toEqual({ + formErrors: ["Must be equal"], + fieldErrors: {}, + }); + } + } + + try { + schema.parse({ + a: null, + b: null, + }); + } catch (_error) { + const error = _error as z.ZodError; + expect(error.flatten()).toEqual({ + formErrors: [], + fieldErrors: { + a: ["Expected string, received null"], + b: ["Expected string, received null"], + }, + }); + + expect(error.flatten((iss) => iss.message.toUpperCase())).toEqual({ + formErrors: [], + fieldErrors: { + a: ["EXPECTED STRING, RECEIVED NULL"], + b: ["EXPECTED STRING, RECEIVED NULL"], + }, + }); + // Test identity + + expect(error.flatten((i: z.ZodIssue) => i)).toEqual({ + formErrors: [], + fieldErrors: { + a: [ + { + code: "invalid_type", + expected: "string", + message: "Expected string, received null", + path: ["a"], + received: "null", + }, + ], + b: [ + { + code: "invalid_type", + expected: "string", + message: "Expected string, received null", + path: ["b"], + received: "null", + }, + ], + }, + }); + // Test mapping + expect(error.flatten((i: z.ZodIssue) => i.message.length)).toEqual({ + formErrors: [], + fieldErrors: { + a: ["Expected string, received null".length], + b: ["Expected string, received null".length], + }, + }); + } +}); diff --git a/node_modules/zod/src/v3/tests/anyunknown.test.ts b/node_modules/zod/src/v3/tests/anyunknown.test.ts new file mode 100644 index 0000000..49d07db --- /dev/null +++ b/node_modules/zod/src/v3/tests/anyunknown.test.ts @@ -0,0 +1,28 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { util } from "../helpers/util.js"; + +test("check any inference", () => { + const t1 = z.any(); + t1.optional(); + t1.nullable(); + type t1 = z.infer; + util.assertEqual(true); +}); + +test("check unknown inference", () => { + const t1 = z.unknown(); + t1.optional(); + t1.nullable(); + type t1 = z.infer; + util.assertEqual(true); +}); + +test("check never inference", () => { + const t1 = z.never(); + expect(() => t1.parse(undefined)).toThrow(); + expect(() => t1.parse("asdf")).toThrow(); + expect(() => t1.parse(null)).toThrow(); +}); diff --git a/node_modules/zod/src/v3/tests/array.test.ts b/node_modules/zod/src/v3/tests/array.test.ts new file mode 100644 index 0000000..df5b9d3 --- /dev/null +++ b/node_modules/zod/src/v3/tests/array.test.ts @@ -0,0 +1,71 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { util } from "../helpers/util.js"; + +const minTwo = z.string().array().min(2); +const maxTwo = z.string().array().max(2); +const justTwo = z.string().array().length(2); +const intNum = z.string().array().nonempty(); +const nonEmptyMax = z.string().array().nonempty().max(2); + +type t1 = z.infer; +util.assertEqual<[string, ...string[]], t1>(true); + +type t2 = z.infer; +util.assertEqual(true); + +test("passing validations", () => { + minTwo.parse(["a", "a"]); + minTwo.parse(["a", "a", "a"]); + maxTwo.parse(["a", "a"]); + maxTwo.parse(["a"]); + justTwo.parse(["a", "a"]); + intNum.parse(["a"]); + nonEmptyMax.parse(["a"]); +}); + +test("failing validations", () => { + expect(() => minTwo.parse(["a"])).toThrow(); + expect(() => maxTwo.parse(["a", "a", "a"])).toThrow(); + expect(() => justTwo.parse(["a"])).toThrow(); + expect(() => justTwo.parse(["a", "a", "a"])).toThrow(); + expect(() => intNum.parse([])).toThrow(); + expect(() => nonEmptyMax.parse([])).toThrow(); + expect(() => nonEmptyMax.parse(["a", "a", "a"])).toThrow(); +}); + +test("parse empty array in nonempty", () => { + expect(() => + z + .array(z.string()) + .nonempty() + .parse([] as any) + ).toThrow(); +}); + +test("get element", () => { + justTwo.element.parse("asdf"); + expect(() => justTwo.element.parse(12)).toThrow(); +}); + +test("continue parsing despite array size error", () => { + const schema = z.object({ + people: z.string().array().min(2), + }); + + const result = schema.safeParse({ + people: [123], + }); + expect(result.success).toEqual(false); + if (!result.success) { + expect(result.error.issues.length).toEqual(2); + } +}); + +test("parse should fail given sparse array", () => { + const schema = z.array(z.string()).nonempty().min(1).max(3); + + expect(() => schema.parse(new Array(3))).toThrow(); +}); diff --git a/node_modules/zod/src/v3/tests/async-parsing.test.ts b/node_modules/zod/src/v3/tests/async-parsing.test.ts new file mode 100644 index 0000000..01dbc4f --- /dev/null +++ b/node_modules/zod/src/v3/tests/async-parsing.test.ts @@ -0,0 +1,388 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; + +/// string +const stringSchema = z.string(); + +test("string async parse", async () => { + const goodData = "XXX"; + const badData = 12; + + const goodResult = await stringSchema.safeParseAsync(goodData); + expect(goodResult.success).toBe(true); + if (goodResult.success) expect(goodResult.data).toEqual(goodData); + + const badResult = await stringSchema.safeParseAsync(badData); + expect(badResult.success).toBe(false); + if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); +}); + +/// number +const numberSchema = z.number(); +test("number async parse", async () => { + const goodData = 1234.2353; + const badData = "1234"; + + const goodResult = await numberSchema.safeParseAsync(goodData); + expect(goodResult.success).toBe(true); + if (goodResult.success) expect(goodResult.data).toEqual(goodData); + + const badResult = await numberSchema.safeParseAsync(badData); + expect(badResult.success).toBe(false); + if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); +}); + +/// bigInt +const bigIntSchema = z.bigint(); +test("bigInt async parse", async () => { + const goodData = BigInt(145); + const badData = 134; + + const goodResult = await bigIntSchema.safeParseAsync(goodData); + expect(goodResult.success).toBe(true); + if (goodResult.success) expect(goodResult.data).toEqual(goodData); + + const badResult = await bigIntSchema.safeParseAsync(badData); + expect(badResult.success).toBe(false); + if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); +}); + +/// boolean +const booleanSchema = z.boolean(); +test("boolean async parse", async () => { + const goodData = true; + const badData = 1; + + const goodResult = await booleanSchema.safeParseAsync(goodData); + expect(goodResult.success).toBe(true); + if (goodResult.success) expect(goodResult.data).toEqual(goodData); + + const badResult = await booleanSchema.safeParseAsync(badData); + expect(badResult.success).toBe(false); + if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); +}); + +/// date +const dateSchema = z.date(); +test("date async parse", async () => { + const goodData = new Date(); + const badData = new Date().toISOString(); + + const goodResult = await dateSchema.safeParseAsync(goodData); + expect(goodResult.success).toBe(true); + if (goodResult.success) expect(goodResult.data).toEqual(goodData); + + const badResult = await dateSchema.safeParseAsync(badData); + expect(badResult.success).toBe(false); + if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); +}); + +/// undefined +const undefinedSchema = z.undefined(); +test("undefined async parse", async () => { + const goodData = undefined; + const badData = "XXX"; + + const goodResult = await undefinedSchema.safeParseAsync(goodData); + expect(goodResult.success).toBe(true); + if (goodResult.success) expect(goodResult.data).toEqual(undefined); + + const badResult = await undefinedSchema.safeParseAsync(badData); + expect(badResult.success).toBe(false); + if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); +}); + +/// null +const nullSchema = z.null(); +test("null async parse", async () => { + const goodData = null; + const badData = undefined; + + const goodResult = await nullSchema.safeParseAsync(goodData); + expect(goodResult.success).toBe(true); + if (goodResult.success) expect(goodResult.data).toEqual(goodData); + + const badResult = await nullSchema.safeParseAsync(badData); + expect(badResult.success).toBe(false); + if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); +}); + +/// any +const anySchema = z.any(); +test("any async parse", async () => { + const goodData = [{}]; + // const badData = 'XXX'; + + const goodResult = await anySchema.safeParseAsync(goodData); + expect(goodResult.success).toBe(true); + if (goodResult.success) expect(goodResult.data).toEqual(goodData); + + // const badResult = await anySchema.safeParseAsync(badData); + // expect(badResult.success).toBe(false); + // if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); +}); + +/// unknown +const unknownSchema = z.unknown(); +test("unknown async parse", async () => { + const goodData = ["asdf", 124, () => {}]; + // const badData = 'XXX'; + + const goodResult = await unknownSchema.safeParseAsync(goodData); + expect(goodResult.success).toBe(true); + if (goodResult.success) expect(goodResult.data).toEqual(goodData); + + // const badResult = await unknownSchema.safeParseAsync(badData); + // expect(badResult.success).toBe(false); + // if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); +}); + +/// void +const voidSchema = z.void(); +test("void async parse", async () => { + const goodData = undefined; + const badData = 0; + + const goodResult = await voidSchema.safeParseAsync(goodData); + expect(goodResult.success).toBe(true); + if (goodResult.success) expect(goodResult.data).toEqual(goodData); + + const badResult = await voidSchema.safeParseAsync(badData); + expect(badResult.success).toBe(false); + if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); +}); + +/// array +const arraySchema = z.array(z.string()); +test("array async parse", async () => { + const goodData = ["XXX"]; + const badData = "XXX"; + + const goodResult = await arraySchema.safeParseAsync(goodData); + expect(goodResult.success).toBe(true); + if (goodResult.success) expect(goodResult.data).toEqual(goodData); + + const badResult = await arraySchema.safeParseAsync(badData); + expect(badResult.success).toBe(false); + if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); +}); + +/// object +const objectSchema = z.object({ string: z.string() }); +test("object async parse", async () => { + const goodData = { string: "XXX" }; + const badData = { string: 12 }; + + const goodResult = await objectSchema.safeParseAsync(goodData); + expect(goodResult.success).toBe(true); + if (goodResult.success) expect(goodResult.data).toEqual(goodData); + + const badResult = await objectSchema.safeParseAsync(badData); + expect(badResult.success).toBe(false); + if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); +}); + +/// union +const unionSchema = z.union([z.string(), z.undefined()]); +test("union async parse", async () => { + const goodData = undefined; + const badData = null; + + const goodResult = await unionSchema.safeParseAsync(goodData); + expect(goodResult.success).toBe(true); + if (goodResult.success) expect(goodResult.data).toEqual(goodData); + + const badResult = await unionSchema.safeParseAsync(badData); + expect(badResult.success).toBe(false); + if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); +}); + +/// record +const recordSchema = z.record(z.object({})); +test("record async parse", async () => { + const goodData = { adsf: {}, asdf: {} }; + const badData = [{}]; + + const goodResult = await recordSchema.safeParseAsync(goodData); + expect(goodResult.success).toBe(true); + if (goodResult.success) expect(goodResult.data).toEqual(goodData); + + const badResult = await recordSchema.safeParseAsync(badData); + expect(badResult.success).toBe(false); + if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); +}); + +/// function +const functionSchema = z.function(); +test("function async parse", async () => { + const goodData = () => {}; + const badData = "XXX"; + + const goodResult = await functionSchema.safeParseAsync(goodData); + expect(goodResult.success).toBe(true); + if (goodResult.success) expect(typeof goodResult.data).toEqual("function"); + + const badResult = await functionSchema.safeParseAsync(badData); + expect(badResult.success).toBe(false); + if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); +}); + +/// literal +const literalSchema = z.literal("asdf"); +test("literal async parse", async () => { + const goodData = "asdf"; + const badData = "asdff"; + + const goodResult = await literalSchema.safeParseAsync(goodData); + expect(goodResult.success).toBe(true); + if (goodResult.success) expect(goodResult.data).toEqual(goodData); + + const badResult = await literalSchema.safeParseAsync(badData); + expect(badResult.success).toBe(false); + if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); +}); + +/// enum +const enumSchema = z.enum(["fish", "whale"]); +test("enum async parse", async () => { + const goodData = "whale"; + const badData = "leopard"; + + const goodResult = await enumSchema.safeParseAsync(goodData); + expect(goodResult.success).toBe(true); + if (goodResult.success) expect(goodResult.data).toEqual(goodData); + + const badResult = await enumSchema.safeParseAsync(badData); + expect(badResult.success).toBe(false); + if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); +}); + +/// nativeEnum +enum nativeEnumTest { + asdf = "qwer", +} +// @ts-ignore +const nativeEnumSchema = z.nativeEnum(nativeEnumTest); +test("nativeEnum async parse", async () => { + const goodData = nativeEnumTest.asdf; + const badData = "asdf"; + + const goodResult = await nativeEnumSchema.safeParseAsync(goodData); + expect(goodResult.success).toBe(true); + if (goodResult.success) expect(goodResult.data).toEqual(goodData); + + const badResult = await nativeEnumSchema.safeParseAsync(badData); + expect(badResult.success).toBe(false); + if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError); +}); + +/// promise +const promiseSchema = z.promise(z.number()); +test("promise async parse good", async () => { + const goodData = Promise.resolve(123); + + const goodResult = await promiseSchema.safeParseAsync(goodData); + expect(goodResult.success).toBe(true); + if (goodResult.success) { + expect(goodResult.data).toBeInstanceOf(Promise); + const data = await goodResult.data; + expect(data).toEqual(123); + // expect(goodResult.data).resolves.toEqual(124); + // return goodResult.data; + } else { + throw new Error("success should be true"); + } +}); + +test("promise async parse bad", async () => { + const badData = Promise.resolve("XXX"); + const badResult = await promiseSchema.safeParseAsync(badData); + expect(badResult.success).toBe(true); + if (badResult.success) { + await expect(badResult.data).rejects.toBeInstanceOf(z.ZodError); + } else { + throw new Error("success should be true"); + } +}); + +test("async validation non-empty strings", async () => { + const base = z.object({ + hello: z.string().refine((x) => x && x.length > 0), + foo: z.string().refine((x) => x && x.length > 0), + }); + + const testval = { hello: "", foo: "" }; + const result1 = base.safeParse(testval); + const result2 = base.safeParseAsync(testval); + + const r1 = result1; + await result2.then((r2) => { + if (r1.success === false && r2.success === false) expect(r1.error.issues.length).toBe(r2.error.issues.length); // <--- r1 has length 2, r2 has length 1 + }); +}); + +test("async validation multiple errors 1", async () => { + const base = z.object({ + hello: z.string(), + foo: z.number(), + }); + + const testval = { hello: 3, foo: "hello" }; + const result1 = base.safeParse(testval); + const result2 = base.safeParseAsync(testval); + + const r1 = result1; + await result2.then((r2) => { + if (r1.success === false && r2.success === false) expect(r2.error.issues.length).toBe(r1.error.issues.length); + }); +}); + +test("async validation multiple errors 2", async () => { + const base = (is_async?: boolean) => + z.object({ + hello: z.string(), + foo: z.object({ + bar: z.number().refine(is_async ? async () => false : () => false), + }), + }); + + const testval = { hello: 3, foo: { bar: 4 } }; + const result1 = base().safeParse(testval); + const result2 = base(true).safeParseAsync(testval); + + const r1 = result1; + await result2.then((r2) => { + if (r1.success === false && r2.success === false) expect(r2.error.issues.length).toBe(r1.error.issues.length); + }); +}); + +test("ensure early async failure prevents follow-up refinement checks", async () => { + let count = 0; + const base = z.object({ + hello: z.string(), + foo: z + .number() + .refine(async () => { + count++; + return true; + }) + .refine(async () => { + count++; + return true; + }, "Good"), + }); + + const testval = { hello: "bye", foo: 3 }; + const result = await base.safeParseAsync(testval); + if (result.success === false) { + expect(result.error.issues.length).toBe(1); + expect(count).toBe(1); + } + + // await result.then((r) => { + // if (r.success === false) expect(r.error.issues.length).toBe(1); + // expect(count).toBe(2); + // }); +}); diff --git a/node_modules/zod/src/v3/tests/async-refinements.test.ts b/node_modules/zod/src/v3/tests/async-refinements.test.ts new file mode 100644 index 0000000..509475d --- /dev/null +++ b/node_modules/zod/src/v3/tests/async-refinements.test.ts @@ -0,0 +1,46 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; + +test("parse async test", async () => { + const schema1 = z.string().refine(async (_val) => false); + expect(() => schema1.parse("asdf")).toThrow(); + + const schema2 = z.string().refine((_val) => Promise.resolve(true)); + return await expect(() => schema2.parse("asdf")).toThrow(); +}); + +test("parseAsync async test", async () => { + const schema1 = z.string().refine(async (_val) => true); + await schema1.parseAsync("asdf"); + + const schema2 = z.string().refine(async (_val) => false); + return await expect(schema2.parseAsync("asdf")).rejects.toBeDefined(); + // expect(async () => await schema2.parseAsync('asdf')).toThrow(); +}); + +test("parseAsync async test", async () => { + // expect.assertions(2); + + const schema1 = z.string().refine((_val) => Promise.resolve(true)); + const v1 = await schema1.parseAsync("asdf"); + expect(v1).toEqual("asdf"); + + const schema2 = z.string().refine((_val) => Promise.resolve(false)); + await expect(schema2.parseAsync("asdf")).rejects.toBeDefined(); + + const schema3 = z.string().refine((_val) => Promise.resolve(true)); + await expect(schema3.parseAsync("asdf")).resolves.toEqual("asdf"); + return await expect(schema3.parseAsync("qwer")).resolves.toEqual("qwer"); +}); + +test("parseAsync async with value", async () => { + const schema1 = z.string().refine(async (val) => { + return val.length > 5; + }); + await expect(schema1.parseAsync("asdf")).rejects.toBeDefined(); + + const v = await schema1.parseAsync("asdf123"); + return await expect(v).toEqual("asdf123"); +}); diff --git a/node_modules/zod/src/v3/tests/base.test.ts b/node_modules/zod/src/v3/tests/base.test.ts new file mode 100644 index 0000000..ab743d5 --- /dev/null +++ b/node_modules/zod/src/v3/tests/base.test.ts @@ -0,0 +1,29 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { util } from "../helpers/util.js"; + +test("type guard", () => { + const stringToNumber = z.string().transform((arg) => arg.length); + + const s1 = z.object({ + stringToNumber, + }); + type t1 = z.input; + + const data = { stringToNumber: "asdf" }; + const parsed = s1.safeParse(data); + if (parsed.success) { + util.assertEqual(true); + } +}); + +test("test this binding", () => { + const callback = (predicate: (val: string) => boolean) => { + return predicate("hello"); + }; + + expect(callback((value) => z.string().safeParse(value).success)).toBe(true); // true + expect(callback((value) => z.string().safeParse(value).success)).toBe(true); // true +}); diff --git a/node_modules/zod/src/v3/tests/bigint.test.ts b/node_modules/zod/src/v3/tests/bigint.test.ts new file mode 100644 index 0000000..9692f57 --- /dev/null +++ b/node_modules/zod/src/v3/tests/bigint.test.ts @@ -0,0 +1,55 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; + +const gtFive = z.bigint().gt(BigInt(5)); +const gteFive = z.bigint().gte(BigInt(5)); +const ltFive = z.bigint().lt(BigInt(5)); +const lteFive = z.bigint().lte(BigInt(5)); +const positive = z.bigint().positive(); +const negative = z.bigint().negative(); +const nonnegative = z.bigint().nonnegative(); +const nonpositive = z.bigint().nonpositive(); +const multipleOfFive = z.bigint().multipleOf(BigInt(5)); + +test("passing validations", () => { + z.bigint().parse(BigInt(1)); + z.bigint().parse(BigInt(0)); + z.bigint().parse(BigInt(-1)); + gtFive.parse(BigInt(6)); + gteFive.parse(BigInt(5)); + gteFive.parse(BigInt(6)); + ltFive.parse(BigInt(4)); + lteFive.parse(BigInt(5)); + lteFive.parse(BigInt(4)); + positive.parse(BigInt(3)); + negative.parse(BigInt(-2)); + nonnegative.parse(BigInt(0)); + nonnegative.parse(BigInt(7)); + nonpositive.parse(BigInt(0)); + nonpositive.parse(BigInt(-12)); + multipleOfFive.parse(BigInt(15)); +}); + +test("failing validations", () => { + expect(() => gtFive.parse(BigInt(5))).toThrow(); + expect(() => gteFive.parse(BigInt(4))).toThrow(); + expect(() => ltFive.parse(BigInt(5))).toThrow(); + expect(() => lteFive.parse(BigInt(6))).toThrow(); + expect(() => positive.parse(BigInt(0))).toThrow(); + expect(() => positive.parse(BigInt(-2))).toThrow(); + expect(() => negative.parse(BigInt(0))).toThrow(); + expect(() => negative.parse(BigInt(3))).toThrow(); + expect(() => nonnegative.parse(BigInt(-1))).toThrow(); + expect(() => nonpositive.parse(BigInt(1))).toThrow(); + expect(() => multipleOfFive.parse(BigInt(13))).toThrow(); +}); + +test("min max getters", () => { + expect(z.bigint().min(BigInt(5)).minValue).toEqual(BigInt(5)); + expect(z.bigint().min(BigInt(5)).min(BigInt(10)).minValue).toEqual(BigInt(10)); + + expect(z.bigint().max(BigInt(5)).maxValue).toEqual(BigInt(5)); + expect(z.bigint().max(BigInt(5)).max(BigInt(1)).maxValue).toEqual(BigInt(1)); +}); diff --git a/node_modules/zod/src/v3/tests/branded.test.ts b/node_modules/zod/src/v3/tests/branded.test.ts new file mode 100644 index 0000000..b19786c --- /dev/null +++ b/node_modules/zod/src/v3/tests/branded.test.ts @@ -0,0 +1,53 @@ +// @ts-ignore TS6133 +import { test } from "vitest"; + +import * as z from "zod/v3"; +import { util } from "../helpers/util.js"; + +test("branded types", () => { + const mySchema = z + .object({ + name: z.string(), + }) + .brand<"superschema">(); + + // simple branding + type MySchema = z.infer; + util.assertEqual(true); + + const doStuff = (arg: MySchema) => arg; + doStuff(mySchema.parse({ name: "hello there" })); + + // inheritance + const extendedSchema = mySchema.brand<"subschema">(); + type ExtendedSchema = z.infer; + util.assertEqual & z.BRAND<"subschema">>(true); + + doStuff(extendedSchema.parse({ name: "hello again" })); + + // number branding + const numberSchema = z.number().brand<42>(); + type NumberSchema = z.infer; + util.assertEqual(true); + + // symbol branding + const MyBrand: unique symbol = Symbol("hello"); + type MyBrand = typeof MyBrand; + const symbolBrand = z.number().brand<"sup">().brand(); + type SymbolBrand = z.infer; + // number & { [z.BRAND]: { sup: true, [MyBrand]: true } } + util.assertEqual & z.BRAND>(true); + + // keeping brands out of input types + const age = z.number().brand<"age">(); + + type Age = z.infer; + type AgeInput = z.input; + + util.assertEqual(false); + util.assertEqual(true); + util.assertEqual, Age>(true); + + // @ts-expect-error + doStuff({ name: "hello there!" }); +}); diff --git a/node_modules/zod/src/v3/tests/catch.test.ts b/node_modules/zod/src/v3/tests/catch.test.ts new file mode 100644 index 0000000..94d12aa --- /dev/null +++ b/node_modules/zod/src/v3/tests/catch.test.ts @@ -0,0 +1,220 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import { z } from "zod/v3"; +import { util } from "../helpers/util.js"; + +test("basic catch", () => { + expect(z.string().catch("default").parse(undefined)).toBe("default"); +}); + +test("catch fn does not run when parsing succeeds", () => { + let isCalled = false; + const cb = () => { + isCalled = true; + return "asdf"; + }; + expect(z.string().catch(cb).parse("test")).toBe("test"); + expect(isCalled).toEqual(false); +}); + +test("basic catch async", async () => { + const result = await z.string().catch("default").parseAsync(1243); + expect(result).toBe("default"); +}); + +test("catch replace wrong types", () => { + expect(z.string().catch("default").parse(true)).toBe("default"); + expect(z.string().catch("default").parse(true)).toBe("default"); + expect(z.string().catch("default").parse(15)).toBe("default"); + expect(z.string().catch("default").parse([])).toBe("default"); + expect(z.string().catch("default").parse(new Map())).toBe("default"); + expect(z.string().catch("default").parse(new Set())).toBe("default"); + expect(z.string().catch("default").parse({})).toBe("default"); +}); + +test("catch with transform", () => { + const stringWithDefault = z + .string() + .transform((val) => val.toUpperCase()) + .catch("default"); + expect(stringWithDefault.parse(undefined)).toBe("default"); + expect(stringWithDefault.parse(15)).toBe("default"); + expect(stringWithDefault).toBeInstanceOf(z.ZodCatch); + expect(stringWithDefault._def.innerType).toBeInstanceOf(z.ZodEffects); + expect(stringWithDefault._def.innerType._def.schema).toBeInstanceOf(z.ZodSchema); + + type inp = z.input; + util.assertEqual(true); + type out = z.output; + util.assertEqual(true); +}); + +test("catch on existing optional", () => { + const stringWithDefault = z.string().optional().catch("asdf"); + expect(stringWithDefault.parse(undefined)).toBe(undefined); + expect(stringWithDefault.parse(15)).toBe("asdf"); + expect(stringWithDefault).toBeInstanceOf(z.ZodCatch); + expect(stringWithDefault._def.innerType).toBeInstanceOf(z.ZodOptional); + expect(stringWithDefault._def.innerType._def.innerType).toBeInstanceOf(z.ZodString); + + type inp = z.input; + util.assertEqual(true); + type out = z.output; + util.assertEqual(true); +}); + +test("optional on catch", () => { + const stringWithDefault = z.string().catch("asdf").optional(); + + type inp = z.input; + util.assertEqual(true); + type out = z.output; + util.assertEqual(true); +}); + +test("complex chain example", () => { + const complex = z + .string() + .catch("asdf") + .transform((val) => val + "!") + .transform((val) => val.toUpperCase()) + .catch("qwer") + .removeCatch() + .optional() + .catch("asdfasdf"); + + expect(complex.parse("qwer")).toBe("QWER!"); + expect(complex.parse(15)).toBe("ASDF!"); + expect(complex.parse(true)).toBe("ASDF!"); +}); + +test("removeCatch", () => { + const stringWithRemovedDefault = z.string().catch("asdf").removeCatch(); + + type out = z.output; + util.assertEqual(true); +}); + +test("nested", () => { + const inner = z.string().catch("asdf"); + const outer = z.object({ inner }).catch({ + inner: "asdf", + }); + type input = z.input; + util.assertEqual(true); + type out = z.output; + util.assertEqual(true); + expect(outer.parse(undefined)).toEqual({ inner: "asdf" }); + expect(outer.parse({})).toEqual({ inner: "asdf" }); + expect(outer.parse({ inner: undefined })).toEqual({ inner: "asdf" }); +}); + +test("chained catch", () => { + const stringWithDefault = z.string().catch("inner").catch("outer"); + const result = stringWithDefault.parse(undefined); + expect(result).toEqual("inner"); + const resultDiff = stringWithDefault.parse(5); + expect(resultDiff).toEqual("inner"); +}); + +test("factory", () => { + z.ZodCatch.create(z.string(), { + catch: "asdf", + }).parse(undefined); +}); + +test("native enum", () => { + enum Fruits { + apple = "apple", + orange = "orange", + } + + const schema = z.object({ + fruit: z.nativeEnum(Fruits).catch(Fruits.apple), + }); + + expect(schema.parse({})).toEqual({ fruit: Fruits.apple }); + expect(schema.parse({ fruit: 15 })).toEqual({ fruit: Fruits.apple }); +}); + +test("enum", () => { + const schema = z.object({ + fruit: z.enum(["apple", "orange"]).catch("apple"), + }); + + expect(schema.parse({})).toEqual({ fruit: "apple" }); + expect(schema.parse({ fruit: true })).toEqual({ fruit: "apple" }); + expect(schema.parse({ fruit: 15 })).toEqual({ fruit: "apple" }); +}); + +test("reported issues with nested usage", () => { + const schema = z.object({ + string: z.string(), + obj: z.object({ + sub: z.object({ + lit: z.literal("a"), + subCatch: z.number().catch(23), + }), + midCatch: z.number().catch(42), + }), + number: z.number().catch(0), + bool: z.boolean(), + }); + + try { + schema.parse({ + string: {}, + obj: { + sub: { + lit: "b", + subCatch: "24", + }, + midCatch: 444, + }, + number: "", + bool: "yes", + }); + } catch (error) { + const issues = (error as z.ZodError).issues; + + expect(issues.length).toEqual(3); + expect(issues[0].message).toMatch("string"); + expect(issues[1].message).toMatch("literal"); + expect(issues[2].message).toMatch("boolean"); + } +}); + +test("catch error", () => { + let catchError: z.ZodError | undefined = undefined; + + const schema = z.object({ + age: z.number(), + name: z.string().catch((ctx) => { + catchError = ctx.error; + + return "John Doe"; + }), + }); + + const result = schema.safeParse({ + age: null, + name: null, + }); + + expect(result.success).toEqual(false); + expect(!result.success && result.error.issues.length).toEqual(1); + expect(!result.success && result.error.issues[0].message).toMatch("number"); + + expect(catchError).toBeInstanceOf(z.ZodError); + expect(catchError !== undefined && (catchError as z.ZodError).issues.length).toEqual(1); + expect(catchError !== undefined && (catchError as z.ZodError).issues[0].message).toMatch("string"); +}); + +test("ctx.input", () => { + const schema = z.string().catch((ctx) => { + return String(ctx.input); + }); + + expect(schema.parse(123)).toEqual("123"); +}); diff --git a/node_modules/zod/src/v3/tests/coerce.test.ts b/node_modules/zod/src/v3/tests/coerce.test.ts new file mode 100644 index 0000000..1f53004 --- /dev/null +++ b/node_modules/zod/src/v3/tests/coerce.test.ts @@ -0,0 +1,133 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; + +test("string coercion", () => { + const schema = z.coerce.string(); + expect(schema.parse("sup")).toEqual("sup"); + expect(schema.parse("")).toEqual(""); + expect(schema.parse(12)).toEqual("12"); + expect(schema.parse(0)).toEqual("0"); + expect(schema.parse(-12)).toEqual("-12"); + expect(schema.parse(3.14)).toEqual("3.14"); + expect(schema.parse(BigInt(15))).toEqual("15"); + expect(schema.parse(Number.NaN)).toEqual("NaN"); + expect(schema.parse(Number.POSITIVE_INFINITY)).toEqual("Infinity"); + expect(schema.parse(Number.NEGATIVE_INFINITY)).toEqual("-Infinity"); + expect(schema.parse(true)).toEqual("true"); + expect(schema.parse(false)).toEqual("false"); + expect(schema.parse(null)).toEqual("null"); + expect(schema.parse(undefined)).toEqual("undefined"); + expect(schema.parse({ hello: "world!" })).toEqual("[object Object]"); + expect(schema.parse(["item", "another_item"])).toEqual("item,another_item"); + expect(schema.parse([])).toEqual(""); + expect(schema.parse(new Date("2022-01-01T00:00:00.000Z"))).toEqual(new Date("2022-01-01T00:00:00.000Z").toString()); +}); + +test("number coercion", () => { + const schema = z.coerce.number(); + expect(schema.parse("12")).toEqual(12); + expect(schema.parse("0")).toEqual(0); + expect(schema.parse("-12")).toEqual(-12); + expect(schema.parse("3.14")).toEqual(3.14); + expect(schema.parse("")).toEqual(0); + expect(() => schema.parse("NOT_A_NUMBER")).toThrow(); // z.ZodError + expect(schema.parse(12)).toEqual(12); + expect(schema.parse(0)).toEqual(0); + expect(schema.parse(-12)).toEqual(-12); + expect(schema.parse(3.14)).toEqual(3.14); + expect(schema.parse(BigInt(15))).toEqual(15); + expect(() => schema.parse(Number.NaN)).toThrow(); // z.ZodError + expect(schema.parse(Number.POSITIVE_INFINITY)).toEqual(Number.POSITIVE_INFINITY); + expect(schema.parse(Number.NEGATIVE_INFINITY)).toEqual(Number.NEGATIVE_INFINITY); + expect(schema.parse(true)).toEqual(1); + expect(schema.parse(false)).toEqual(0); + expect(schema.parse(null)).toEqual(0); + expect(() => schema.parse(undefined)).toThrow(); // z.ZodError + expect(() => schema.parse({ hello: "world!" })).toThrow(); // z.ZodError + expect(() => schema.parse(["item", "another_item"])).toThrow(); // z.ZodError + expect(schema.parse([])).toEqual(0); + expect(schema.parse(new Date(1670139203496))).toEqual(1670139203496); +}); + +test("boolean coercion", () => { + const schema = z.coerce.boolean(); + expect(schema.parse("true")).toEqual(true); + expect(schema.parse("false")).toEqual(true); + expect(schema.parse("0")).toEqual(true); + expect(schema.parse("1")).toEqual(true); + expect(schema.parse("")).toEqual(false); + expect(schema.parse(1)).toEqual(true); + expect(schema.parse(0)).toEqual(false); + expect(schema.parse(-1)).toEqual(true); + expect(schema.parse(3.14)).toEqual(true); + expect(schema.parse(BigInt(15))).toEqual(true); + expect(schema.parse(Number.NaN)).toEqual(false); + expect(schema.parse(Number.POSITIVE_INFINITY)).toEqual(true); + expect(schema.parse(Number.NEGATIVE_INFINITY)).toEqual(true); + expect(schema.parse(true)).toEqual(true); + expect(schema.parse(false)).toEqual(false); + expect(schema.parse(null)).toEqual(false); + expect(schema.parse(undefined)).toEqual(false); + expect(schema.parse({ hello: "world!" })).toEqual(true); + expect(schema.parse(["item", "another_item"])).toEqual(true); + expect(schema.parse([])).toEqual(true); + expect(schema.parse(new Date(1670139203496))).toEqual(true); +}); + +test("bigint coercion", () => { + const schema = z.coerce.bigint(); + expect(schema.parse("5")).toEqual(BigInt(5)); + expect(schema.parse("0")).toEqual(BigInt(0)); + expect(schema.parse("-5")).toEqual(BigInt(-5)); + expect(() => schema.parse("3.14")).toThrow(); // not a z.ZodError! + expect(schema.parse("")).toEqual(BigInt(0)); + expect(() => schema.parse("NOT_A_NUMBER")).toThrow(); // not a z.ZodError! + expect(schema.parse(5)).toEqual(BigInt(5)); + expect(schema.parse(0)).toEqual(BigInt(0)); + expect(schema.parse(-5)).toEqual(BigInt(-5)); + expect(() => schema.parse(3.14)).toThrow(); // not a z.ZodError! + expect(schema.parse(BigInt(5))).toEqual(BigInt(5)); + expect(() => schema.parse(Number.NaN)).toThrow(); // not a z.ZodError! + expect(() => schema.parse(Number.POSITIVE_INFINITY)).toThrow(); // not a z.ZodError! + expect(() => schema.parse(Number.NEGATIVE_INFINITY)).toThrow(); // not a z.ZodError! + expect(schema.parse(true)).toEqual(BigInt(1)); + expect(schema.parse(false)).toEqual(BigInt(0)); + expect(() => schema.parse(null)).toThrow(); // not a z.ZodError! + expect(() => schema.parse(undefined)).toThrow(); // not a z.ZodError! + expect(() => schema.parse({ hello: "world!" })).toThrow(); // not a z.ZodError! + expect(() => schema.parse(["item", "another_item"])).toThrow(); // not a z.ZodError! + expect(schema.parse([])).toEqual(BigInt(0)); + expect(schema.parse(new Date(1670139203496))).toEqual(BigInt(1670139203496)); +}); + +test("date coercion", () => { + const schema = z.coerce.date(); + expect(schema.parse(new Date().toDateString())).toBeInstanceOf(Date); + expect(schema.parse(new Date().toISOString())).toBeInstanceOf(Date); + expect(schema.parse(new Date().toUTCString())).toBeInstanceOf(Date); + expect(schema.parse("5")).toBeInstanceOf(Date); + expect(schema.parse("2000-01-01")).toBeInstanceOf(Date); + // expect(schema.parse("0")).toBeInstanceOf(Date); + // expect(schema.parse("-5")).toBeInstanceOf(Date); + // expect(schema.parse("3.14")).toBeInstanceOf(Date); + expect(() => schema.parse("")).toThrow(); // z.ZodError + expect(() => schema.parse("NOT_A_DATE")).toThrow(); // z.ZodError + expect(schema.parse(5)).toBeInstanceOf(Date); + expect(schema.parse(0)).toBeInstanceOf(Date); + expect(schema.parse(-5)).toBeInstanceOf(Date); + expect(schema.parse(3.14)).toBeInstanceOf(Date); + expect(() => schema.parse(BigInt(5))).toThrow(); // not a z.ZodError! + expect(() => schema.parse(Number.NaN)).toThrow(); // z.ZodError + expect(() => schema.parse(Number.POSITIVE_INFINITY)).toThrow(); // z.ZodError + expect(() => schema.parse(Number.NEGATIVE_INFINITY)).toThrow(); // z.ZodError + expect(schema.parse(true)).toBeInstanceOf(Date); + expect(schema.parse(false)).toBeInstanceOf(Date); + expect(schema.parse(null)).toBeInstanceOf(Date); + expect(() => schema.parse(undefined)).toThrow(); // z.ZodError + expect(() => schema.parse({ hello: "world!" })).toThrow(); // z.ZodError + expect(() => schema.parse(["item", "another_item"])).toThrow(); // z.ZodError + expect(() => schema.parse([])).toThrow(); // z.ZodError + expect(schema.parse(new Date())).toBeInstanceOf(Date); +}); diff --git a/node_modules/zod/src/v3/tests/complex.test.ts b/node_modules/zod/src/v3/tests/complex.test.ts new file mode 100644 index 0000000..7807b2b --- /dev/null +++ b/node_modules/zod/src/v3/tests/complex.test.ts @@ -0,0 +1,56 @@ +import { test } from "vitest"; +import * as z from "zod/v3"; + +const crazySchema = z.object({ + tuple: z.tuple([ + z.string().nullable().optional(), + z.number().nullable().optional(), + z.boolean().nullable().optional(), + z.null().nullable().optional(), + z.undefined().nullable().optional(), + z.literal("1234").nullable().optional(), + ]), + merged: z + .object({ + k1: z.string().optional(), + }) + .merge(z.object({ k1: z.string().nullable(), k2: z.number() })), + union: z.array(z.union([z.literal("asdf"), z.literal(12)])).nonempty(), + array: z.array(z.number()), + // sumTransformer: z.transformer(z.array(z.number()), z.number(), (arg) => { + // return arg.reduce((a, b) => a + b, 0); + // }), + sumMinLength: z.array(z.number()).refine((arg) => arg.length > 5), + intersection: z.intersection(z.object({ p1: z.string().optional() }), z.object({ p1: z.number().optional() })), + enum: z.intersection(z.enum(["zero", "one"]), z.enum(["one", "two"])), + nonstrict: z.object({ points: z.number() }).nonstrict(), + numProm: z.promise(z.number()), + lenfun: z.function(z.tuple([z.string()]), z.boolean()), +}); + +// const asyncCrazySchema = crazySchema.extend({ +// // async_transform: z.transformer( +// // z.array(z.number()), +// // z.number(), +// // async (arg) => { +// // return arg.reduce((a, b) => a + b, 0); +// // } +// // ), +// async_refine: z.array(z.number()).refine(async (arg) => arg.length > 5), +// }); + +test("parse", () => { + crazySchema.parse({ + tuple: ["asdf", 1234, true, null, undefined, "1234"], + merged: { k1: "asdf", k2: 12 }, + union: ["asdf", 12, "asdf", 12, "asdf", 12], + array: [12, 15, 16], + // sumTransformer: [12, 15, 16], + sumMinLength: [12, 15, 16, 98, 24, 63], + intersection: {}, + enum: "one", + nonstrict: { points: 1234 }, + numProm: Promise.resolve(12), + lenfun: (x: string) => x.length, + }); +}); diff --git a/node_modules/zod/src/v3/tests/custom.test.ts b/node_modules/zod/src/v3/tests/custom.test.ts new file mode 100644 index 0000000..b24b676 --- /dev/null +++ b/node_modules/zod/src/v3/tests/custom.test.ts @@ -0,0 +1,31 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; + +test("passing validations", () => { + const example1 = z.custom((x) => typeof x === "number"); + example1.parse(1234); + expect(() => example1.parse({})).toThrow(); +}); + +test("string params", () => { + const example1 = z.custom((x) => typeof x !== "number", "customerr"); + const result = example1.safeParse(1234); + expect(result.success).toEqual(false); + // @ts-ignore + expect(JSON.stringify(result.error).includes("customerr")).toEqual(true); +}); + +test("async validations", async () => { + const example1 = z.custom(async (x) => { + return typeof x === "number"; + }); + const r1 = await example1.safeParseAsync(1234); + expect(r1.success).toEqual(true); + expect(r1.data).toEqual(1234); + + const r2 = await example1.safeParseAsync("asdf"); + expect(r2.success).toEqual(false); + expect(r2.error!.issues.length).toEqual(1); +}); diff --git a/node_modules/zod/src/v3/tests/date.test.ts b/node_modules/zod/src/v3/tests/date.test.ts new file mode 100644 index 0000000..c86dc84 --- /dev/null +++ b/node_modules/zod/src/v3/tests/date.test.ts @@ -0,0 +1,32 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; + +const beforeBenchmarkDate = new Date(2022, 10, 4); +const benchmarkDate = new Date(2022, 10, 5); +const afterBenchmarkDate = new Date(2022, 10, 6); + +const minCheck = z.date().min(benchmarkDate); +const maxCheck = z.date().max(benchmarkDate); + +test("passing validations", () => { + minCheck.parse(benchmarkDate); + minCheck.parse(afterBenchmarkDate); + + maxCheck.parse(benchmarkDate); + maxCheck.parse(beforeBenchmarkDate); +}); + +test("failing validations", () => { + expect(() => minCheck.parse(beforeBenchmarkDate)).toThrow(); + expect(() => maxCheck.parse(afterBenchmarkDate)).toThrow(); +}); + +test("min max getters", () => { + expect(minCheck.minDate).toEqual(benchmarkDate); + expect(minCheck.min(afterBenchmarkDate).minDate).toEqual(afterBenchmarkDate); + + expect(maxCheck.maxDate).toEqual(benchmarkDate); + expect(maxCheck.max(beforeBenchmarkDate).maxDate).toEqual(beforeBenchmarkDate); +}); diff --git a/node_modules/zod/src/v3/tests/deepmasking.test.ts b/node_modules/zod/src/v3/tests/deepmasking.test.ts new file mode 100644 index 0000000..d707e79 --- /dev/null +++ b/node_modules/zod/src/v3/tests/deepmasking.test.ts @@ -0,0 +1,186 @@ +// @ts-ignore TS6133 +import { test } from "vitest"; + +import * as z from "zod/v3"; + +test("test", () => { + z; +}); + +// const fish = z.object({ +// name: z.string(), +// props: z.object({ +// color: z.string(), +// numScales: z.number(), +// }), +// }); + +// const nonStrict = z +// .object({ +// name: z.string(), +// color: z.string(), +// }) +// .nonstrict(); + +// test('object pick type', () => { +// const modNonStrictFish = nonStrict.omit({ name: true }); +// modNonStrictFish.parse({ color: 'asdf' }); + +// const bad1 = () => fish.pick({ props: { unknown: true } } as any); +// const bad2 = () => fish.omit({ name: true, props: { unknown: true } } as any); + +// expect(bad1).toThrow(); +// expect(bad2).toThrow(); +// }); + +// test('f1', () => { +// const f1 = fish.pick(true); +// f1.parse({ name: 'a', props: { color: 'b', numScales: 3 } }); +// }); +// test('f2', () => { +// const f2 = fish.pick({ props: true }); +// f2.parse({ props: { color: 'asdf', numScales: 1 } }); +// const badcheck2 = () => f2.parse({ name: 'a', props: { color: 'b', numScales: 3 } } as any); +// expect(badcheck2).toThrow(); +// }); +// test('f3', () => { +// const f3 = fish.pick({ props: { color: true } }); +// f3.parse({ props: { color: 'b' } }); +// const badcheck3 = () => f3.parse({ name: 'a', props: { color: 'b', numScales: 3 } } as any); +// expect(badcheck3).toThrow(); +// }); +// test('f4', () => { +// const badcheck4 = () => fish.pick({ props: { color: true, unknown: true } }); +// expect(badcheck4).toThrow(); +// }); +// test('f6', () => { +// const f6 = fish.omit({ props: true }); +// const badcheck6 = () => f6.parse({ name: 'a', props: { color: 'b', numScales: 3 } } as any); +// f6.parse({ name: 'adsf' }); +// expect(badcheck6).toThrow(); +// }); +// test('f7', () => { +// const f7 = fish.omit({ props: { color: true } }); +// f7.parse({ name: 'a', props: { numScales: 3 } }); +// const badcheck7 = () => f7.parse({ name: 'a', props: { color: 'b', numScales: 3 } } as any); +// expect(badcheck7).toThrow(); +// }); +// test('f8', () => { +// const badcheck8 = () => fish.omit({ props: { color: true, unknown: true } }); +// expect(badcheck8).toThrow(); +// }); +// test('f9', () => { +// const f9 = nonStrict.pick(true); +// f9.parse({ name: 'a', color: 'asdf' }); +// }); +// test('f10', () => { +// const f10 = nonStrict.pick({ name: true }); +// f10.parse({ name: 'a' }); +// const val = f10.parse({ name: 'a', color: 'b' }); +// expect(val).toEqual({ name: 'a' }); +// }); +// test('f12', () => { +// const badfcheck12 = () => nonStrict.omit({ color: true, asdf: true }); +// expect(badfcheck12).toThrow(); +// }); + +// test('array masking', () => { +// const fishArray = z.array(fish); +// const modFishArray = fishArray.pick({ +// name: true, +// props: { +// numScales: true, +// }, +// }); + +// modFishArray.parse([{ name: 'fish', props: { numScales: 12 } }]); +// const bad1 = () => modFishArray.parse([{ name: 'fish', props: { numScales: 12, color: 'asdf' } }] as any); +// expect(bad1).toThrow(); +// }); + +// test('array masking', () => { +// const fishArray = z.array(fish); +// const fail = () => +// fishArray.pick({ +// name: true, +// props: { +// whatever: true, +// }, +// } as any); +// expect(fail).toThrow(); +// }); + +// test('array masking', () => { +// const fishArray = z.array(fish); +// const fail = () => +// fishArray.omit({ +// whateve: true, +// } as any); +// expect(fail).toThrow(); +// }); + +// test('array masking', () => { +// const fishArray = z.array(fish); +// const modFishList = fishArray.omit({ +// name: true, +// props: { +// color: true, +// }, +// }); + +// modFishList.parse([{ props: { numScales: 12 } }]); +// const fail = () => modFishList.parse([{ name: 'hello', props: { numScales: 12 } }] as any); +// expect(fail).toThrow(); +// }); + +// test('primitive array masking', () => { +// const fishArray = z.array(z.number()); +// const fail = () => fishArray.pick({} as any); +// expect(fail).toThrow(); +// }); + +// test('other array masking', () => { +// const fishArray = z.array(z.array(z.number())); +// const fail = () => fishArray.pick({} as any); +// expect(fail).toThrow(); +// }); + +// test('invalid mask #1', () => { +// const fail = () => fish.pick(1 as any); +// expect(fail).toThrow(); +// }); + +// test('invalid mask #2', () => { +// const fail = () => fish.pick([] as any); +// expect(fail).toThrow(); +// }); + +// test('invalid mask #3', () => { +// const fail = () => fish.pick(false as any); +// expect(fail).toThrow(); +// }); + +// test('invalid mask #4', () => { +// const fail = () => fish.pick('asdf' as any); +// expect(fail).toThrow(); +// }); + +// test('invalid mask #5', () => { +// const fail = () => fish.omit(1 as any); +// expect(fail).toThrow(); +// }); + +// test('invalid mask #6', () => { +// const fail = () => fish.omit([] as any); +// expect(fail).toThrow(); +// }); + +// test('invalid mask #7', () => { +// const fail = () => fish.omit(false as any); +// expect(fail).toThrow(); +// }); + +// test('invalid mask #8', () => { +// const fail = () => fish.omit('asdf' as any); +// expect(fail).toThrow(); +// }); diff --git a/node_modules/zod/src/v3/tests/default.test.ts b/node_modules/zod/src/v3/tests/default.test.ts new file mode 100644 index 0000000..29e007c --- /dev/null +++ b/node_modules/zod/src/v3/tests/default.test.ts @@ -0,0 +1,112 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import { z } from "zod/v3"; +import { util } from "../helpers/util.js"; + +test("basic defaults", () => { + expect(z.string().default("default").parse(undefined)).toBe("default"); +}); + +test("default with transform", () => { + const stringWithDefault = z + .string() + .transform((val) => val.toUpperCase()) + .default("default"); + expect(stringWithDefault.parse(undefined)).toBe("DEFAULT"); + expect(stringWithDefault).toBeInstanceOf(z.ZodDefault); + expect(stringWithDefault._def.innerType).toBeInstanceOf(z.ZodEffects); + expect(stringWithDefault._def.innerType._def.schema).toBeInstanceOf(z.ZodSchema); + + type inp = z.input; + util.assertEqual(true); + type out = z.output; + util.assertEqual(true); +}); + +test("default on existing optional", () => { + const stringWithDefault = z.string().optional().default("asdf"); + expect(stringWithDefault.parse(undefined)).toBe("asdf"); + expect(stringWithDefault).toBeInstanceOf(z.ZodDefault); + expect(stringWithDefault._def.innerType).toBeInstanceOf(z.ZodOptional); + expect(stringWithDefault._def.innerType._def.innerType).toBeInstanceOf(z.ZodString); + + type inp = z.input; + util.assertEqual(true); + type out = z.output; + util.assertEqual(true); +}); + +test("optional on default", () => { + const stringWithDefault = z.string().default("asdf").optional(); + + type inp = z.input; + util.assertEqual(true); + type out = z.output; + util.assertEqual(true); +}); + +test("complex chain example", () => { + const complex = z + .string() + .default("asdf") + .transform((val) => val.toUpperCase()) + .default("qwer") + .removeDefault() + .optional() + .default("asdfasdf"); + + expect(complex.parse(undefined)).toBe("ASDFASDF"); +}); + +test("removeDefault", () => { + const stringWithRemovedDefault = z.string().default("asdf").removeDefault(); + + type out = z.output; + util.assertEqual(true); +}); + +test("nested", () => { + const inner = z.string().default("asdf"); + const outer = z.object({ inner }).default({ + inner: undefined, + }); + type input = z.input; + util.assertEqual(true); + type out = z.output; + util.assertEqual(true); + expect(outer.parse(undefined)).toEqual({ inner: "asdf" }); + expect(outer.parse({})).toEqual({ inner: "asdf" }); + expect(outer.parse({ inner: undefined })).toEqual({ inner: "asdf" }); +}); + +test("chained defaults", () => { + const stringWithDefault = z.string().default("inner").default("outer"); + const result = stringWithDefault.parse(undefined); + expect(result).toEqual("outer"); +}); + +test("factory", () => { + expect(z.ZodDefault.create(z.string(), { default: "asdf" }).parse(undefined)).toEqual("asdf"); +}); + +test("native enum", () => { + enum Fruits { + apple = "apple", + orange = "orange", + } + + const schema = z.object({ + fruit: z.nativeEnum(Fruits).default(Fruits.apple), + }); + + expect(schema.parse({})).toEqual({ fruit: Fruits.apple }); +}); + +test("enum", () => { + const schema = z.object({ + fruit: z.enum(["apple", "orange"]).default("apple"), + }); + + expect(schema.parse({})).toEqual({ fruit: "apple" }); +}); diff --git a/node_modules/zod/src/v3/tests/description.test.ts b/node_modules/zod/src/v3/tests/description.test.ts new file mode 100644 index 0000000..1edaa1c --- /dev/null +++ b/node_modules/zod/src/v3/tests/description.test.ts @@ -0,0 +1,33 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; + +const description = "a description"; + +test("passing `description` to schema should add a description", () => { + expect(z.string({ description }).description).toEqual(description); + expect(z.number({ description }).description).toEqual(description); + expect(z.boolean({ description }).description).toEqual(description); +}); + +test("`.describe` should add a description", () => { + expect(z.string().describe(description).description).toEqual(description); + expect(z.number().describe(description).description).toEqual(description); + expect(z.boolean().describe(description).description).toEqual(description); +}); + +test("description should carry over to chained schemas", () => { + const schema = z.string({ description }); + expect(schema.description).toEqual(description); + expect(schema.optional().description).toEqual(description); + expect(schema.optional().nullable().default("default").description).toEqual(description); +}); + +test("description should not carry over to chained array schema", () => { + const schema = z.string().describe(description); + + expect(schema.description).toEqual(description); + expect(schema.array().description).toEqual(undefined); + expect(z.array(schema).description).toEqual(undefined); +}); diff --git a/node_modules/zod/src/v3/tests/discriminated-unions.test.ts b/node_modules/zod/src/v3/tests/discriminated-unions.test.ts new file mode 100644 index 0000000..7fb5cfe --- /dev/null +++ b/node_modules/zod/src/v3/tests/discriminated-unions.test.ts @@ -0,0 +1,315 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; + +test("valid", () => { + expect( + z + .discriminatedUnion("type", [ + z.object({ type: z.literal("a"), a: z.string() }), + z.object({ type: z.literal("b"), b: z.string() }), + ]) + .parse({ type: "a", a: "abc" }) + ).toEqual({ type: "a", a: "abc" }); +}); + +test("valid - discriminator value of various primitive types", () => { + const schema = z.discriminatedUnion("type", [ + z.object({ type: z.literal("1"), val: z.literal(1) }), + z.object({ type: z.literal(1), val: z.literal(2) }), + z.object({ type: z.literal(BigInt(1)), val: z.literal(3) }), + z.object({ type: z.literal("true"), val: z.literal(4) }), + z.object({ type: z.literal(true), val: z.literal(5) }), + z.object({ type: z.literal("null"), val: z.literal(6) }), + z.object({ type: z.literal(null), val: z.literal(7) }), + z.object({ type: z.literal("undefined"), val: z.literal(8) }), + z.object({ type: z.literal(undefined), val: z.literal(9) }), + z.object({ type: z.literal("transform"), val: z.literal(10) }), + z.object({ type: z.literal("refine"), val: z.literal(11) }), + z.object({ type: z.literal("superRefine"), val: z.literal(12) }), + ]); + + expect(schema.parse({ type: "1", val: 1 })).toEqual({ type: "1", val: 1 }); + expect(schema.parse({ type: 1, val: 2 })).toEqual({ type: 1, val: 2 }); + expect(schema.parse({ type: BigInt(1), val: 3 })).toEqual({ + type: BigInt(1), + val: 3, + }); + expect(schema.parse({ type: "true", val: 4 })).toEqual({ + type: "true", + val: 4, + }); + expect(schema.parse({ type: true, val: 5 })).toEqual({ + type: true, + val: 5, + }); + expect(schema.parse({ type: "null", val: 6 })).toEqual({ + type: "null", + val: 6, + }); + expect(schema.parse({ type: null, val: 7 })).toEqual({ + type: null, + val: 7, + }); + expect(schema.parse({ type: "undefined", val: 8 })).toEqual({ + type: "undefined", + val: 8, + }); + expect(schema.parse({ type: undefined, val: 9 })).toEqual({ + type: undefined, + val: 9, + }); +}); + +test("invalid - null", () => { + try { + z.discriminatedUnion("type", [ + z.object({ type: z.literal("a"), a: z.string() }), + z.object({ type: z.literal("b"), b: z.string() }), + ]).parse(null); + throw new Error(); + } catch (e: any) { + expect(JSON.parse(e.message)).toEqual([ + { + code: z.ZodIssueCode.invalid_type, + expected: z.ZodParsedType.object, + message: "Expected object, received null", + received: z.ZodParsedType.null, + path: [], + }, + ]); + } +}); + +test("invalid discriminator value", () => { + try { + z.discriminatedUnion("type", [ + z.object({ type: z.literal("a"), a: z.string() }), + z.object({ type: z.literal("b"), b: z.string() }), + ]).parse({ type: "x", a: "abc" }); + throw new Error(); + } catch (e: any) { + expect(JSON.parse(e.message)).toEqual([ + { + code: z.ZodIssueCode.invalid_union_discriminator, + options: ["a", "b"], + message: "Invalid discriminator value. Expected 'a' | 'b'", + path: ["type"], + }, + ]); + } +}); + +test("valid discriminator value, invalid data", () => { + try { + z.discriminatedUnion("type", [ + z.object({ type: z.literal("a"), a: z.string() }), + z.object({ type: z.literal("b"), b: z.string() }), + ]).parse({ type: "a", b: "abc" }); + throw new Error(); + } catch (e: any) { + expect(JSON.parse(e.message)).toEqual([ + { + code: z.ZodIssueCode.invalid_type, + expected: z.ZodParsedType.string, + message: "Required", + path: ["a"], + received: z.ZodParsedType.undefined, + }, + ]); + } +}); + +test("wrong schema - missing discriminator", () => { + try { + z.discriminatedUnion("type", [ + z.object({ type: z.literal("a"), a: z.string() }), + z.object({ b: z.string() }) as any, + ]); + throw new Error(); + } catch (e: any) { + expect(e.message.includes("could not be extracted")).toBe(true); + } +}); + +test("wrong schema - duplicate discriminator values", () => { + try { + z.discriminatedUnion("type", [ + z.object({ type: z.literal("a"), a: z.string() }), + z.object({ type: z.literal("a"), b: z.string() }), + ]); + throw new Error(); + } catch (e: any) { + expect(e.message.includes("has duplicate value")).toEqual(true); + } +}); + +test("async - valid", async () => { + expect( + await z + .discriminatedUnion("type", [ + z.object({ + type: z.literal("a"), + a: z + .string() + .refine(async () => true) + .transform(async (val) => Number(val)), + }), + z.object({ + type: z.literal("b"), + b: z.string(), + }), + ]) + .parseAsync({ type: "a", a: "1" }) + ).toEqual({ type: "a", a: 1 }); +}); + +test("async - invalid", async () => { + try { + await z + .discriminatedUnion("type", [ + z.object({ + type: z.literal("a"), + a: z + .string() + .refine(async () => true) + .transform(async (val) => val), + }), + z.object({ + type: z.literal("b"), + b: z.string(), + }), + ]) + .parseAsync({ type: "a", a: 1 }); + throw new Error(); + } catch (e: any) { + expect(JSON.parse(e.message)).toEqual([ + { + code: "invalid_type", + expected: "string", + received: "number", + path: ["a"], + message: "Expected string, received number", + }, + ]); + } +}); + +test("valid - literals with .default or .preprocess", () => { + const schema = z.discriminatedUnion("type", [ + z.object({ + type: z.literal("foo").default("foo"), + a: z.string(), + }), + z.object({ + type: z.literal("custom"), + method: z.string(), + }), + z.object({ + type: z.preprocess((val) => String(val), z.literal("bar")), + c: z.string(), + }), + ]); + expect(schema.parse({ type: "foo", a: "foo" })).toEqual({ + type: "foo", + a: "foo", + }); +}); + +test("enum and nativeEnum", () => { + enum MyEnum { + d = 0, + e = "e", + } + + const schema = z.discriminatedUnion("key", [ + z.object({ + key: z.literal("a"), + // Add other properties specific to this option + }), + z.object({ + key: z.enum(["b", "c"]), + // Add other properties specific to this option + }), + z.object({ + key: z.nativeEnum(MyEnum), + // Add other properties specific to this option + }), + ]); + + // type schema = z.infer; + + schema.parse({ key: "a" }); + schema.parse({ key: "b" }); + schema.parse({ key: "c" }); + schema.parse({ key: MyEnum.d }); + schema.parse({ key: MyEnum.e }); + schema.parse({ key: "e" }); +}); + +test("branded", () => { + const schema = z.discriminatedUnion("key", [ + z.object({ + key: z.literal("a"), + // Add other properties specific to this option + }), + z.object({ + key: z.literal("b").brand("asdfaf"), + // Add other properties specific to this option + }), + ]); + + // type schema = z.infer; + + schema.parse({ key: "a" }); + schema.parse({ key: "b" }); + expect(() => { + schema.parse({ key: "c" }); + }).toThrow(); +}); + +test("optional and nullable", () => { + const schema = z.discriminatedUnion("key", [ + z.object({ + key: z.literal("a").optional(), + a: z.literal(true), + }), + z.object({ + key: z.literal("b").nullable(), + b: z.literal(true), + // Add other properties specific to this option + }), + ]); + + type schema = z.infer; + z.util.assertEqual(true); + + schema.parse({ key: "a", a: true }); + schema.parse({ key: undefined, a: true }); + schema.parse({ key: "b", b: true }); + schema.parse({ key: null, b: true }); + expect(() => { + schema.parse({ key: null, a: true }); + }).toThrow(); + expect(() => { + schema.parse({ key: "b", a: true }); + }).toThrow(); + + const value = schema.parse({ key: null, b: true }); + + if (!("key" in value)) value.a; + if (value.key === undefined) value.a; + if (value.key === "a") value.a; + if (value.key === "b") value.b; + if (value.key === null) value.b; +}); + +test("readonly array of options", () => { + const options = [ + z.object({ type: z.literal("x"), val: z.literal(1) }), + z.object({ type: z.literal("y"), val: z.literal(2) }), + ] as const; + + expect(z.discriminatedUnion("type", options).parse({ type: "x", val: 1 })).toEqual({ type: "x", val: 1 }); +}); diff --git a/node_modules/zod/src/v3/tests/enum.test.ts b/node_modules/zod/src/v3/tests/enum.test.ts new file mode 100644 index 0000000..53f4a3e --- /dev/null +++ b/node_modules/zod/src/v3/tests/enum.test.ts @@ -0,0 +1,80 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { util } from "../helpers/util.js"; + +test("create enum", () => { + const MyEnum = z.enum(["Red", "Green", "Blue"]); + expect(MyEnum.Values.Red).toEqual("Red"); + expect(MyEnum.Enum.Red).toEqual("Red"); + expect(MyEnum.enum.Red).toEqual("Red"); +}); + +test("infer enum", () => { + const MyEnum = z.enum(["Red", "Green", "Blue"]); + type MyEnum = z.infer; + util.assertEqual(true); +}); + +test("get options", () => { + expect(z.enum(["tuna", "trout"]).options).toEqual(["tuna", "trout"]); +}); + +test("readonly enum", () => { + const HTTP_SUCCESS = ["200", "201"] as const; + const arg = z.enum(HTTP_SUCCESS); + type arg = z.infer; + util.assertEqual(true); + + arg.parse("201"); + expect(() => arg.parse("202")).toThrow(); +}); + +test("error params", () => { + const result = z.enum(["test"], { required_error: "REQUIRED" }).safeParse(undefined); + expect(result.success).toEqual(false); + if (!result.success) { + expect(result.error.issues[0].message).toEqual("REQUIRED"); + } +}); + +test("extract/exclude", () => { + const foods = ["Pasta", "Pizza", "Tacos", "Burgers", "Salad"] as const; + const FoodEnum = z.enum(foods); + const ItalianEnum = FoodEnum.extract(["Pasta", "Pizza"]); + const UnhealthyEnum = FoodEnum.exclude(["Salad"]); + const EmptyFoodEnum = FoodEnum.exclude(foods); + + util.assertEqual, "Pasta" | "Pizza">(true); + util.assertEqual, "Pasta" | "Pizza" | "Tacos" | "Burgers">(true); + // @ts-expect-error TS2344 + util.assertEqual>(true); + util.assertEqual, never>(true); +}); + +test("error map in extract/exclude", () => { + const foods = ["Pasta", "Pizza", "Tacos", "Burgers", "Salad"] as const; + const FoodEnum = z.enum(foods, { + errorMap: () => ({ message: "This is not food!" }), + }); + const ItalianEnum = FoodEnum.extract(["Pasta", "Pizza"]); + const foodsError = FoodEnum.safeParse("Cucumbers"); + const italianError = ItalianEnum.safeParse("Tacos"); + if (!foodsError.success && !italianError.success) { + expect(foodsError.error.issues[0].message).toEqual(italianError.error.issues[0].message); + } + + const UnhealthyEnum = FoodEnum.exclude(["Salad"], { + errorMap: () => ({ message: "This is not healthy food!" }), + }); + const unhealthyError = UnhealthyEnum.safeParse("Salad"); + if (!unhealthyError.success) { + expect(unhealthyError.error.issues[0].message).toEqual("This is not healthy food!"); + } +}); + +test("readonly in ZodEnumDef", () => { + let _t!: z.ZodEnumDef; + _t; +}); diff --git a/node_modules/zod/src/v3/tests/error.test.ts b/node_modules/zod/src/v3/tests/error.test.ts new file mode 100644 index 0000000..5caaa6d --- /dev/null +++ b/node_modules/zod/src/v3/tests/error.test.ts @@ -0,0 +1,551 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { ZodError, ZodIssueCode } from "../ZodError.js"; +import { ZodParsedType } from "../helpers/util.js"; + +test("error creation", () => { + const err1 = ZodError.create([]); + err1.addIssue({ + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.object, + received: ZodParsedType.string, + path: [], + message: "", + fatal: true, + }); + err1.isEmpty; + + const err2 = ZodError.create(err1.issues); + const err3 = new ZodError([]); + err3.addIssues(err1.issues); + err3.addIssue(err1.issues[0]); + err1.message; + err2.message; + err3.message; +}); + +const errorMap: z.ZodErrorMap = (error, ctx) => { + if (error.code === ZodIssueCode.invalid_type) { + if (error.expected === "string") { + return { message: "bad type!" }; + } + } + if (error.code === ZodIssueCode.custom) { + return { message: `less-than-${error.params?.minimum}` }; + } + return { message: ctx.defaultError }; +}; + +test("type error with custom error map", () => { + try { + z.string().parse(234, { errorMap }); + } catch (err) { + const zerr: z.ZodError = err as any; + + expect(zerr.issues[0].code).toEqual(z.ZodIssueCode.invalid_type); + expect(zerr.issues[0].message).toEqual(`bad type!`); + } +}); + +test("refinement fail with params", () => { + try { + z.number() + .refine((val) => val >= 3, { + params: { minimum: 3 }, + }) + .parse(2, { errorMap }); + } catch (err) { + const zerr: z.ZodError = err as any; + expect(zerr.issues[0].code).toEqual(z.ZodIssueCode.custom); + expect(zerr.issues[0].message).toEqual(`less-than-3`); + } +}); + +test("custom error with custom errormap", () => { + try { + z.string() + .refine((val) => val.length > 12, { + params: { minimum: 13 }, + message: "override", + }) + .parse("asdf", { errorMap }); + } catch (err) { + const zerr: z.ZodError = err as any; + expect(zerr.issues[0].message).toEqual("override"); + } +}); + +test("default error message", () => { + try { + z.number() + .refine((x) => x > 3) + .parse(2); + } catch (err) { + const zerr: z.ZodError = err as any; + expect(zerr.issues.length).toEqual(1); + expect(zerr.issues[0].message).toEqual("Invalid input"); + } +}); + +test("override error in refine", () => { + try { + z.number() + .refine((x) => x > 3, "override") + .parse(2); + } catch (err) { + const zerr: z.ZodError = err as any; + expect(zerr.issues.length).toEqual(1); + expect(zerr.issues[0].message).toEqual("override"); + } +}); + +test("override error in refinement", () => { + try { + z.number() + .refine((x) => x > 3, { + message: "override", + }) + .parse(2); + } catch (err) { + const zerr: z.ZodError = err as any; + expect(zerr.issues.length).toEqual(1); + expect(zerr.issues[0].message).toEqual("override"); + } +}); + +test("array minimum", () => { + try { + z.array(z.string()).min(3, "tooshort").parse(["asdf", "qwer"]); + } catch (err) { + const zerr: ZodError = err as any; + expect(zerr.issues[0].code).toEqual(ZodIssueCode.too_small); + expect(zerr.issues[0].message).toEqual("tooshort"); + } + try { + z.array(z.string()).min(3).parse(["asdf", "qwer"]); + } catch (err) { + const zerr: ZodError = err as any; + expect(zerr.issues[0].code).toEqual(ZodIssueCode.too_small); + expect(zerr.issues[0].message).toEqual(`Array must contain at least 3 element(s)`); + } +}); + +// implement test for semi-smart union logic that checks for type error on either left or right +// test("union smart errors", () => { +// // expect.assertions(2); + +// const p1 = z +// .union([z.string(), z.number().refine((x) => x > 0)]) +// .safeParse(-3.2); + +// if (p1.success === true) throw new Error(); +// expect(p1.success).toBe(false); +// expect(p1.error.issues[0].code).toEqual(ZodIssueCode.custom); + +// const p2 = z.union([z.string(), z.number()]).safeParse(false); +// // .catch(err => expect(err.issues[0].code).toEqual(ZodIssueCode.invalid_union)); +// if (p2.success === true) throw new Error(); +// expect(p2.success).toBe(false); +// expect(p2.error.issues[0].code).toEqual(ZodIssueCode.invalid_union); +// }); + +test("custom path in custom error map", () => { + const schema = z.object({ + items: z.array(z.string()).refine((data) => data.length > 3, { + path: ["items-too-few"], + }), + }); + + const errorMap: z.ZodErrorMap = (error) => { + expect(error.path.length).toBe(2); + return { message: "doesnt matter" }; + }; + const result = schema.safeParse({ items: ["first"] }, { errorMap }); + expect(result.success).toEqual(false); + if (!result.success) { + expect(result.error.issues[0].path).toEqual(["items", "items-too-few"]); + } +}); + +test("error metadata from value", () => { + const dynamicRefine = z.string().refine( + (val) => val === val.toUpperCase(), + (val) => ({ params: { val } }) + ); + + const result = dynamicRefine.safeParse("asdf"); + expect(result.success).toEqual(false); + if (!result.success) { + const sub = result.error.issues[0]; + expect(result.error.issues[0].code).toEqual("custom"); + if (sub.code === "custom") { + expect(sub.params!.val).toEqual("asdf"); + } + } +}); + +// test("don't call refine after validation failed", () => { +// const asdf = z +// .union([ +// z.number(), +// z.string().transform(z.number(), (val) => { +// return parseFloat(val); +// }), +// ]) +// .refine((v) => v >= 1); + +// expect(() => asdf.safeParse("foo")).not.toThrow(); +// }); + +test("root level formatting", () => { + const schema = z.string().email(); + const result = schema.safeParse("asdfsdf"); + expect(result.success).toEqual(false); + if (!result.success) { + expect(result.error.format()._errors).toEqual(["Invalid email"]); + } +}); + +test("custom path", () => { + const schema = z + .object({ + password: z.string(), + confirm: z.string(), + }) + .refine((val) => val.confirm === val.password, { path: ["confirm"] }); + + const result = schema.safeParse({ + password: "peanuts", + confirm: "qeanuts", + }); + + expect(result.success).toEqual(false); + if (!result.success) { + // nested errors + const error = result.error.format(); + expect(error._errors).toEqual([]); + expect(error.password?._errors).toEqual(undefined); + expect(error.confirm?._errors).toEqual(["Invalid input"]); + } +}); + +test("custom path", () => { + const schema = z + .object({ + password: z.string().min(6), + confirm: z.string().min(6), + }) + .refine((val) => val.confirm === val.password); + + const result = schema.safeParse({ + password: "qwer", + confirm: "asdf", + }); + + expect(result.success).toEqual(false); + if (!result.success) { + expect(result.error.issues.length).toEqual(3); + } +}); + +const schema = z.object({ + inner: z.object({ + name: z + .string() + .refine((val) => val.length > 5) + .array() + .refine((val) => val.length <= 1), + }), +}); + +test("no abort early on refinements", () => { + const invalidItem = { + inner: { name: ["aasd", "asdfasdfasfd"] }, + }; + + const result1 = schema.safeParse(invalidItem); + expect(result1.success).toEqual(false); + if (!result1.success) { + expect(result1.error.issues.length).toEqual(2); + } +}); +test("formatting", () => { + const invalidItem = { + inner: { name: ["aasd", "asdfasdfasfd"] }, + }; + const invalidArray = { + inner: { name: ["asdfasdf", "asdfasdfasfd"] }, + }; + const result1 = schema.safeParse(invalidItem); + const result2 = schema.safeParse(invalidArray); + + expect(result1.success).toEqual(false); + expect(result2.success).toEqual(false); + if (!result1.success) { + const error = result1.error.format(); + + expect(error._errors).toEqual([]); + expect(error.inner?._errors).toEqual([]); + // expect(error.inner?.name?._errors).toEqual(["Invalid input"]); + // expect(error.inner?.name?.[0]._errors).toEqual(["Invalid input"]); + expect(error.inner?.name?.[1]).toEqual(undefined); + } + if (!result2.success) { + type FormattedError = z.inferFormattedError; + const error: FormattedError = result2.error.format(); + expect(error._errors).toEqual([]); + expect(error.inner?._errors).toEqual([]); + expect(error.inner?.name?._errors).toEqual(["Invalid input"]); + expect(error.inner?.name?.[0]).toEqual(undefined); + expect(error.inner?.name?.[1]).toEqual(undefined); + expect(error.inner?.name?.[2]).toEqual(undefined); + } + + // test custom mapper + if (!result2.success) { + type FormattedError = z.inferFormattedError; + const error: FormattedError = result2.error.format(() => 5); + expect(error._errors).toEqual([]); + expect(error.inner?._errors).toEqual([]); + expect(error.inner?.name?._errors).toEqual([5]); + } +}); + +test("formatting with nullable and optional fields", () => { + const nameSchema = z.string().refine((val) => val.length > 5); + const schema = z.object({ + nullableObject: z.object({ name: nameSchema }).nullable(), + nullableArray: z.array(nameSchema).nullable(), + nullableTuple: z.tuple([nameSchema, nameSchema, z.number()]).nullable(), + optionalObject: z.object({ name: nameSchema }).optional(), + optionalArray: z.array(nameSchema).optional(), + optionalTuple: z.tuple([nameSchema, nameSchema, z.number()]).optional(), + }); + const invalidItem = { + nullableObject: { name: "abcd" }, + nullableArray: ["abcd"], + nullableTuple: ["abcd", "abcd", 1], + optionalObject: { name: "abcd" }, + optionalArray: ["abcd"], + optionalTuple: ["abcd", "abcd", 1], + }; + const result = schema.safeParse(invalidItem); + expect(result.success).toEqual(false); + if (!result.success) { + type FormattedError = z.inferFormattedError; + const error: FormattedError = result.error.format(); + expect(error._errors).toEqual([]); + expect(error.nullableObject?._errors).toEqual([]); + expect(error.nullableObject?.name?._errors).toEqual(["Invalid input"]); + expect(error.nullableArray?._errors).toEqual([]); + expect(error.nullableArray?.[0]?._errors).toEqual(["Invalid input"]); + expect(error.nullableTuple?._errors).toEqual([]); + expect(error.nullableTuple?.[0]?._errors).toEqual(["Invalid input"]); + expect(error.nullableTuple?.[1]?._errors).toEqual(["Invalid input"]); + expect(error.optionalObject?._errors).toEqual([]); + expect(error.optionalObject?.name?._errors).toEqual(["Invalid input"]); + expect(error.optionalArray?._errors).toEqual([]); + expect(error.optionalArray?.[0]?._errors).toEqual(["Invalid input"]); + expect(error.optionalTuple?._errors).toEqual([]); + expect(error.optionalTuple?.[0]?._errors).toEqual(["Invalid input"]); + expect(error.optionalTuple?.[1]?._errors).toEqual(["Invalid input"]); + } +}); + +const stringWithCustomError = z.string({ + errorMap: (issue, ctx) => ({ + message: issue.code === "invalid_type" ? (ctx.data ? "Invalid name" : "Name is required") : ctx.defaultError, + }), +}); + +test("schema-bound error map", () => { + const result = stringWithCustomError.safeParse(1234); + expect(result.success).toEqual(false); + if (!result.success) { + expect(result.error.issues[0].message).toEqual("Invalid name"); + } + + const result2 = stringWithCustomError.safeParse(undefined); + expect(result2.success).toEqual(false); + if (!result2.success) { + expect(result2.error.issues[0].message).toEqual("Name is required"); + } + + // support contextual override + const result3 = stringWithCustomError.safeParse(undefined, { + errorMap: () => ({ message: "OVERRIDE" }), + }); + expect(result3.success).toEqual(false); + if (!result3.success) { + expect(result3.error.issues[0].message).toEqual("OVERRIDE"); + } +}); + +test("overrideErrorMap", () => { + // support overrideErrorMap + z.setErrorMap(() => ({ message: "OVERRIDE" })); + const result4 = stringWithCustomError.min(10).safeParse("tooshort"); + expect(result4.success).toEqual(false); + if (!result4.success) { + expect(result4.error.issues[0].message).toEqual("OVERRIDE"); + } + z.setErrorMap(z.defaultErrorMap); +}); + +test("invalid and required", () => { + const str = z.string({ + invalid_type_error: "Invalid name", + required_error: "Name is required", + }); + const result1 = str.safeParse(1234); + expect(result1.success).toEqual(false); + if (!result1.success) { + expect(result1.error.issues[0].message).toEqual("Invalid name"); + } + const result2 = str.safeParse(undefined); + expect(result2.success).toEqual(false); + if (!result2.success) { + expect(result2.error.issues[0].message).toEqual("Name is required"); + } +}); + +test("Fallback to default required error", () => { + const str = z.string({ + invalid_type_error: "Invalid name", + // required_error: "Name is required", + }); + + const result2 = str.safeParse(undefined); + expect(result2.success).toEqual(false); + if (!result2.success) { + expect(result2.error.issues[0].message).toEqual("Required"); + } +}); + +test("invalid and required and errorMap", () => { + expect(() => { + return z.string({ + invalid_type_error: "Invalid name", + required_error: "Name is required", + errorMap: () => ({ message: "OVERRIDE" }), + }); + }).toThrow(); +}); + +test("strict error message", () => { + const errorMsg = "Invalid object"; + const obj = z.object({ x: z.string() }).strict(errorMsg); + const result = obj.safeParse({ x: "a", y: "b" }); + expect(result.success).toEqual(false); + if (!result.success) { + expect(result.error.issues[0].message).toEqual(errorMsg); + } +}); + +test("enum error message, invalid enum elementstring", () => { + try { + z.enum(["Tuna", "Trout"]).parse("Salmon"); + } catch (err) { + const zerr: z.ZodError = err as any; + expect(zerr.issues.length).toEqual(1); + expect(zerr.issues[0].message).toEqual("Invalid enum value. Expected 'Tuna' | 'Trout', received 'Salmon'"); + } +}); + +test("enum error message, invalid type", () => { + try { + z.enum(["Tuna", "Trout"]).parse(12); + } catch (err) { + const zerr: z.ZodError = err as any; + expect(zerr.issues.length).toEqual(1); + expect(zerr.issues[0].message).toEqual("Expected 'Tuna' | 'Trout', received number"); + } +}); + +test("nativeEnum default error message", () => { + enum Fish { + Tuna = "Tuna", + Trout = "Trout", + } + try { + z.nativeEnum(Fish).parse("Salmon"); + } catch (err) { + const zerr: z.ZodError = err as any; + expect(zerr.issues.length).toEqual(1); + expect(zerr.issues[0].message).toEqual("Invalid enum value. Expected 'Tuna' | 'Trout', received 'Salmon'"); + } +}); + +test("literal default error message", () => { + try { + z.literal("Tuna").parse("Trout"); + } catch (err) { + const zerr: z.ZodError = err as any; + expect(zerr.issues.length).toEqual(1); + expect(zerr.issues[0].message).toEqual(`Invalid literal value, expected "Tuna"`); + } +}); + +test("literal bigint default error message", () => { + try { + z.literal(BigInt(12)).parse(BigInt(13)); + } catch (err) { + const zerr: z.ZodError = err as any; + expect(zerr.issues.length).toEqual(1); + expect(zerr.issues[0].message).toEqual(`Invalid literal value, expected "12"`); + } +}); + +test("enum with message returns the custom error message", () => { + const schema = z.enum(["apple", "banana"], { + message: "the value provided is invalid", + }); + + const result1 = schema.safeParse("berries"); + expect(result1.success).toEqual(false); + if (!result1.success) { + expect(result1.error.issues[0].message).toEqual("the value provided is invalid"); + } + + const result2 = schema.safeParse(undefined); + expect(result2.success).toEqual(false); + if (!result2.success) { + expect(result2.error.issues[0].message).toEqual("the value provided is invalid"); + } + + const result3 = schema.safeParse("banana"); + expect(result3.success).toEqual(true); + + const result4 = schema.safeParse(null); + expect(result4.success).toEqual(false); + if (!result4.success) { + expect(result4.error.issues[0].message).toEqual("the value provided is invalid"); + } +}); + +test("when the message is falsy, it is used as is provided", () => { + const schema = z.string().max(1, { message: "" }); + const result = schema.safeParse("asdf"); + expect(result.success).toEqual(false); + if (!result.success) { + expect(result.error.issues[0].message).toEqual(""); + } +}); + +// test("dont short circuit on continuable errors", () => { +// const user = z +// .object({ +// password: z.string().min(6), +// confirm: z.string(), +// }) +// .refine((data) => data.password === data.confirm, { +// message: "Passwords don't match", +// path: ["confirm"], +// }); +// const result = user.safeParse({ password: "asdf", confirm: "qwer" }); +// if (!result.success) { +// expect(result.error.issues.length).toEqual(2); +// } +// }); diff --git a/node_modules/zod/src/v3/tests/firstparty.test.ts b/node_modules/zod/src/v3/tests/firstparty.test.ts new file mode 100644 index 0000000..017a1c1 --- /dev/null +++ b/node_modules/zod/src/v3/tests/firstparty.test.ts @@ -0,0 +1,87 @@ +// @ts-ignore TS6133 +import { test } from "vitest"; + +import * as z from "zod/v3"; +import { util } from "../helpers/util.js"; + +test("first party switch", () => { + const myType = z.string() as z.ZodFirstPartySchemaTypes; + const def = myType._def; + + switch (def.typeName) { + case z.ZodFirstPartyTypeKind.ZodString: + break; + case z.ZodFirstPartyTypeKind.ZodNumber: + break; + case z.ZodFirstPartyTypeKind.ZodNaN: + break; + case z.ZodFirstPartyTypeKind.ZodBigInt: + break; + case z.ZodFirstPartyTypeKind.ZodBoolean: + break; + case z.ZodFirstPartyTypeKind.ZodDate: + break; + case z.ZodFirstPartyTypeKind.ZodUndefined: + break; + case z.ZodFirstPartyTypeKind.ZodNull: + break; + case z.ZodFirstPartyTypeKind.ZodAny: + break; + case z.ZodFirstPartyTypeKind.ZodUnknown: + break; + case z.ZodFirstPartyTypeKind.ZodNever: + break; + case z.ZodFirstPartyTypeKind.ZodVoid: + break; + case z.ZodFirstPartyTypeKind.ZodArray: + break; + case z.ZodFirstPartyTypeKind.ZodObject: + break; + case z.ZodFirstPartyTypeKind.ZodUnion: + break; + case z.ZodFirstPartyTypeKind.ZodDiscriminatedUnion: + break; + case z.ZodFirstPartyTypeKind.ZodIntersection: + break; + case z.ZodFirstPartyTypeKind.ZodTuple: + break; + case z.ZodFirstPartyTypeKind.ZodRecord: + break; + case z.ZodFirstPartyTypeKind.ZodMap: + break; + case z.ZodFirstPartyTypeKind.ZodSet: + break; + case z.ZodFirstPartyTypeKind.ZodFunction: + break; + case z.ZodFirstPartyTypeKind.ZodLazy: + break; + case z.ZodFirstPartyTypeKind.ZodLiteral: + break; + case z.ZodFirstPartyTypeKind.ZodEnum: + break; + case z.ZodFirstPartyTypeKind.ZodEffects: + break; + case z.ZodFirstPartyTypeKind.ZodNativeEnum: + break; + case z.ZodFirstPartyTypeKind.ZodOptional: + break; + case z.ZodFirstPartyTypeKind.ZodNullable: + break; + case z.ZodFirstPartyTypeKind.ZodDefault: + break; + case z.ZodFirstPartyTypeKind.ZodCatch: + break; + case z.ZodFirstPartyTypeKind.ZodPromise: + break; + case z.ZodFirstPartyTypeKind.ZodBranded: + break; + case z.ZodFirstPartyTypeKind.ZodPipeline: + break; + case z.ZodFirstPartyTypeKind.ZodSymbol: + break; + case z.ZodFirstPartyTypeKind.ZodReadonly: + break; + default: + util.assertNever(def); + } +}); diff --git a/node_modules/zod/src/v3/tests/firstpartyschematypes.test.ts b/node_modules/zod/src/v3/tests/firstpartyschematypes.test.ts new file mode 100644 index 0000000..ad397d8 --- /dev/null +++ b/node_modules/zod/src/v3/tests/firstpartyschematypes.test.ts @@ -0,0 +1,21 @@ +// @ts-ignore TS6133 +import { test } from "vitest"; + +import type { ZodFirstPartySchemaTypes, ZodFirstPartyTypeKind } from "zod/v3"; +import { util } from "../helpers/util.js"; + +test("Identify missing [ZodFirstPartySchemaTypes]", () => { + type ZodFirstPartySchemaForType = ZodFirstPartySchemaTypes extends infer Schema + ? Schema extends { _def: { typeName: T } } + ? Schema + : never + : never; + type ZodMappedTypes = { + [key in ZodFirstPartyTypeKind]: ZodFirstPartySchemaForType; + }; + type ZodFirstPartySchemaTypesMissingFromUnion = keyof { + [key in keyof ZodMappedTypes as ZodMappedTypes[key] extends { _def: never } ? key : never]: unknown; + }; + + util.assertEqual(true); +}); diff --git a/node_modules/zod/src/v3/tests/function.test.ts b/node_modules/zod/src/v3/tests/function.test.ts new file mode 100644 index 0000000..a0f03bb --- /dev/null +++ b/node_modules/zod/src/v3/tests/function.test.ts @@ -0,0 +1,257 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { util } from "../helpers/util.js"; + +const args1 = z.tuple([z.string()]); +const returns1 = z.number(); +const func1 = z.function(args1, returns1); + +test("function parsing", () => { + const parsed = func1.parse((arg: any) => arg.length); + parsed("asdf"); +}); + +test("parsed function fail 1", () => { + const parsed = func1.parse((x: string) => x); + expect(() => parsed("asdf")).toThrow(); +}); + +test("parsed function fail 2", () => { + const parsed = func1.parse((x: string) => x); + expect(() => parsed(13 as any)).toThrow(); +}); + +test("function inference 1", () => { + type func1 = z.TypeOf; + util.assertEqual number>(true); +}); + +test("method parsing", () => { + const methodObject = z.object({ + property: z.number(), + method: z.function().args(z.string()).returns(z.number()), + }); + const methodInstance = { + property: 3, + method: function (s: string) { + return s.length + this.property; + }, + }; + const parsed = methodObject.parse(methodInstance); + expect(parsed.method("length=8")).toBe(11); // 8 length + 3 property +}); + +test("async method parsing", async () => { + const methodObject = z.object({ + property: z.number(), + method: z.function().args(z.string()).returns(z.promise(z.number())), + }); + const methodInstance = { + property: 3, + method: async function (s: string) { + return s.length + this.property; + }, + }; + const parsed = methodObject.parse(methodInstance); + expect(await parsed.method("length=8")).toBe(11); // 8 length + 3 property +}); + +test("args method", () => { + const t1 = z.function(); + type t1 = z.infer; + util.assertEqual unknown>(true); + + const t2 = t1.args(z.string()); + type t2 = z.infer; + util.assertEqual unknown>(true); + + const t3 = t2.returns(z.boolean()); + type t3 = z.infer; + util.assertEqual boolean>(true); +}); + +const args2 = z.tuple([ + z.object({ + f1: z.number(), + f2: z.string().nullable(), + f3: z.array(z.boolean().optional()).optional(), + }), +]); +const returns2 = z.union([z.string(), z.number()]); + +const func2 = z.function(args2, returns2); + +test("function inference 2", () => { + type func2 = z.TypeOf; + util.assertEqual< + func2, + (arg: { + f1: number; + f2: string | null; + f3?: (boolean | undefined)[] | undefined; + }) => string | number + >(true); +}); + +test("valid function run", () => { + const validFunc2Instance = func2.validate((_x) => { + return "adf" as any; + }); + + const checker = () => { + validFunc2Instance({ + f1: 21, + f2: "asdf", + f3: [true, false], + }); + }; + + checker(); +}); + +test("input validation error", () => { + const invalidFuncInstance = func2.validate((_x) => { + return "adf" as any; + }); + + const checker = () => { + invalidFuncInstance("Invalid_input" as any); + }; + + expect(checker).toThrow(); +}); + +test("output validation error", () => { + const invalidFuncInstance = func2.validate((_x) => { + return ["this", "is", "not", "valid", "output"] as any; + }); + + const checker = () => { + invalidFuncInstance({ + f1: 21, + f2: "asdf", + f3: [true, false], + }); + }; + + expect(checker).toThrow(); +}); + +z.function(z.tuple([z.string()])).args()._def.args; + +test("special function error codes", () => { + const checker = z.function(z.tuple([z.string()]), z.boolean()).implement((arg) => { + return arg.length as any; + }); + try { + checker("12" as any); + } catch (err) { + const zerr = err as z.ZodError; + const first = zerr.issues[0]; + if (first.code !== z.ZodIssueCode.invalid_return_type) throw new Error(); + + expect(first.returnTypeError).toBeInstanceOf(z.ZodError); + } + + try { + checker(12 as any); + } catch (err) { + const zerr = err as z.ZodError; + const first = zerr.issues[0]; + if (first.code !== z.ZodIssueCode.invalid_arguments) throw new Error(); + expect(first.argumentsError).toBeInstanceOf(z.ZodError); + } +}); + +test("function with async refinements", async () => { + const func = z + .function() + .args(z.string().refine(async (val) => val.length > 10)) + .returns(z.promise(z.number().refine(async (val) => val > 10))) + .implement(async (val) => { + return val.length; + }); + const results = []; + try { + await func("asdfasdf"); + results.push("success"); + } catch (_err) { + results.push("fail"); + } + try { + await func("asdflkjasdflkjsf"); + results.push("success"); + } catch (_err) { + results.push("fail"); + } + + expect(results).toEqual(["fail", "success"]); +}); + +test("non async function with async refinements should fail", async () => { + const func = z + .function() + .args(z.string().refine(async (val) => val.length > 10)) + .returns(z.number().refine(async (val) => val > 10)) + .implement((val) => { + return val.length; + }); + + const results = []; + try { + await func("asdasdfasdffasdf"); + results.push("success"); + } catch (_err) { + results.push("fail"); + } + + expect(results).toEqual(["fail"]); +}); + +test("allow extra parameters", () => { + const maxLength5 = z + .function() + .args(z.string()) + .returns(z.boolean()) + .implement((str, _arg, _qewr) => { + return str.length <= 5; + }); + + const filteredList = ["apple", "orange", "pear", "banana", "strawberry"].filter(maxLength5); + expect(filteredList.length).toEqual(2); +}); + +test("params and returnType getters", () => { + const func = z.function().args(z.string()).returns(z.string()); + + func.parameters().items[0].parse("asdf"); + func.returnType().parse("asdf"); +}); + +test("inference with transforms", () => { + const funcSchema = z + .function() + .args(z.string().transform((val) => val.length)) + .returns(z.object({ val: z.number() })); + const myFunc = funcSchema.implement((val) => { + return { val, extra: "stuff" }; + }); + myFunc("asdf"); + + util.assertEqual { val: number; extra: string }>(true); +}); + +test("fallback to OuterTypeOfFunction", () => { + const funcSchema = z + .function() + .args(z.string().transform((val) => val.length)) + .returns(z.object({ arg: z.number() }).transform((val) => val.arg)); + + const myFunc = funcSchema.implement((val) => { + return { arg: val, arg2: false }; + }); + + util.assertEqual number>(true); +}); diff --git a/node_modules/zod/src/v3/tests/generics.test.ts b/node_modules/zod/src/v3/tests/generics.test.ts new file mode 100644 index 0000000..e0af470 --- /dev/null +++ b/node_modules/zod/src/v3/tests/generics.test.ts @@ -0,0 +1,48 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { util } from "../helpers/util.js"; + +test("generics", () => { + async function stripOuter(schema: TData, data: unknown) { + return z + .object({ + nested: schema, // as z.ZodTypeAny, + }) + .transform((data) => { + return data.nested!; + }) + .parse({ nested: data }); + } + + const result = stripOuter(z.object({ a: z.string() }), { a: "asdf" }); + util.assertEqual>(true); +}); + +// test("assignability", () => { +// const createSchemaAndParse = ( +// key: K, +// valueSchema: VS, +// data: unknown +// ) => { +// const schema = z.object({ +// [key]: valueSchema, +// } as { [k in K]: VS }); +// return { [key]: valueSchema }; +// const parsed = schema.parse(data); +// return parsed; +// // const inferred: z.infer> = parsed; +// // return inferred; +// }; +// const parsed = createSchemaAndParse("foo", z.string(), { foo: "" }); +// util.assertEqual(true); +// }); + +test("nested no undefined", () => { + const inner = z.string().or(z.array(z.string())); + const outer = z.object({ inner }); + type outerSchema = z.infer; + z.util.assertEqual(true); + expect(outer.safeParse({ inner: undefined }).success).toEqual(false); +}); diff --git a/node_modules/zod/src/v3/tests/instanceof.test.ts b/node_modules/zod/src/v3/tests/instanceof.test.ts new file mode 100644 index 0000000..de66f3f --- /dev/null +++ b/node_modules/zod/src/v3/tests/instanceof.test.ts @@ -0,0 +1,37 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { util } from "../helpers/util.js"; + +test("instanceof", async () => { + class Test {} + class Subtest extends Test {} + abstract class AbstractBar { + constructor(public val: string) {} + } + class Bar extends AbstractBar {} + + const TestSchema = z.instanceof(Test); + const SubtestSchema = z.instanceof(Subtest); + const AbstractSchema = z.instanceof(AbstractBar); + const BarSchema = z.instanceof(Bar); + + TestSchema.parse(new Test()); + TestSchema.parse(new Subtest()); + SubtestSchema.parse(new Subtest()); + AbstractSchema.parse(new Bar("asdf")); + const bar = BarSchema.parse(new Bar("asdf")); + expect(bar.val).toEqual("asdf"); + + await expect(() => SubtestSchema.parse(new Test())).toThrow(/Input not instance of Subtest/); + await expect(() => TestSchema.parse(12)).toThrow(/Input not instance of Test/); + + util.assertEqual>(true); +}); + +test("instanceof fatal", () => { + const schema = z.instanceof(Date).refine((d) => d.toString()); + const res = schema.safeParse(null); + expect(res.success).toBe(false); +}); diff --git a/node_modules/zod/src/v3/tests/intersection.test.ts b/node_modules/zod/src/v3/tests/intersection.test.ts new file mode 100644 index 0000000..6d7936c --- /dev/null +++ b/node_modules/zod/src/v3/tests/intersection.test.ts @@ -0,0 +1,110 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; + +test("object intersection", () => { + const BaseTeacher = z.object({ + subjects: z.array(z.string()), + }); + const HasID = z.object({ id: z.string() }); + + const Teacher = z.intersection(BaseTeacher.passthrough(), HasID); // BaseTeacher.merge(HasID); + const data = { + subjects: ["math"], + id: "asdfasdf", + }; + expect(Teacher.parse(data)).toEqual(data); + expect(() => Teacher.parse({ subject: data.subjects })).toThrow(); + expect(Teacher.parse({ ...data, extra: 12 })).toEqual({ ...data, extra: 12 }); + + expect(() => z.intersection(BaseTeacher.strict(), HasID).parse({ ...data, extra: 12 })).toThrow(); +}); + +test("deep intersection", () => { + const Animal = z.object({ + properties: z.object({ + is_animal: z.boolean(), + }), + }); + const Cat = z + .object({ + properties: z.object({ + jumped: z.boolean(), + }), + }) + .and(Animal); + + type _Cat = z.infer; + // const cat:Cat = 'asdf' as any; + const cat = Cat.parse({ properties: { is_animal: true, jumped: true } }); + expect(cat.properties).toEqual({ is_animal: true, jumped: true }); +}); + +test("deep intersection of arrays", async () => { + const Author = z.object({ + posts: z.array( + z.object({ + post_id: z.number(), + }) + ), + }); + const Registry = z + .object({ + posts: z.array( + z.object({ + title: z.string(), + }) + ), + }) + .and(Author); + + const posts = [ + { post_id: 1, title: "Novels" }, + { post_id: 2, title: "Fairy tales" }, + ]; + const cat = Registry.parse({ posts }); + expect(cat.posts).toEqual(posts); + const asyncCat = await Registry.parseAsync({ posts }); + expect(asyncCat.posts).toEqual(posts); +}); + +test("invalid intersection types", async () => { + const numberIntersection = z.intersection( + z.number(), + z.number().transform((x) => x + 1) + ); + + const syncResult = numberIntersection.safeParse(1234); + expect(syncResult.success).toEqual(false); + if (!syncResult.success) { + expect(syncResult.error.issues[0].code).toEqual(z.ZodIssueCode.invalid_intersection_types); + } + + const asyncResult = await numberIntersection.spa(1234); + expect(asyncResult.success).toEqual(false); + if (!asyncResult.success) { + expect(asyncResult.error.issues[0].code).toEqual(z.ZodIssueCode.invalid_intersection_types); + } +}); + +test("invalid array merge", async () => { + const stringArrInt = z.intersection( + z.string().array(), + z + .string() + .array() + .transform((val) => [...val, "asdf"]) + ); + const syncResult = stringArrInt.safeParse(["asdf", "qwer"]); + expect(syncResult.success).toEqual(false); + if (!syncResult.success) { + expect(syncResult.error.issues[0].code).toEqual(z.ZodIssueCode.invalid_intersection_types); + } + + const asyncResult = await stringArrInt.spa(["asdf", "qwer"]); + expect(asyncResult.success).toEqual(false); + if (!asyncResult.success) { + expect(asyncResult.error.issues[0].code).toEqual(z.ZodIssueCode.invalid_intersection_types); + } +}); diff --git a/node_modules/zod/src/v3/tests/language-server.source.ts b/node_modules/zod/src/v3/tests/language-server.source.ts new file mode 100644 index 0000000..cbe818b --- /dev/null +++ b/node_modules/zod/src/v3/tests/language-server.source.ts @@ -0,0 +1,76 @@ +import * as z from "zod/v3"; + +export const filePath = __filename; + +// z.object() + +export const Test = z.object({ + f1: z.number(), +}); + +export type Test = z.infer; + +export const instanceOfTest: Test = { + f1: 1, +}; + +// z.object().merge() + +export const TestMerge = z + .object({ + f2: z.string().optional(), + }) + .merge(Test); + +export type TestMerge = z.infer; + +export const instanceOfTestMerge: TestMerge = { + f1: 1, + f2: "string", +}; + +// z.union() + +export const TestUnion = z.union([ + z.object({ + f2: z.string().optional(), + }), + Test, +]); + +export type TestUnion = z.infer; + +export const instanceOfTestUnion: TestUnion = { + f1: 1, + f2: "string", +}; + +// z.object().partial() + +export const TestPartial = Test.partial(); + +export type TestPartial = z.infer; + +export const instanceOfTestPartial: TestPartial = { + f1: 1, +}; + +// z.object().pick() + +export const TestPick = TestMerge.pick({ f1: true }); + +export type TestPick = z.infer; + +export const instanceOfTestPick: TestPick = { + f1: 1, +}; + +// z.object().omit() + +export const TestOmit = TestMerge.omit({ f2: true }); + +export type TestOmit = z.infer; + +export const instanceOfTestOmit: TestOmit = { + f1: 1, +}; diff --git a/node_modules/zod/src/v3/tests/language-server.test.ts b/node_modules/zod/src/v3/tests/language-server.test.ts new file mode 100644 index 0000000..851fdc4 --- /dev/null +++ b/node_modules/zod/src/v3/tests/language-server.test.ts @@ -0,0 +1,207 @@ +import { test } from "vitest"; +// import path from "path"; +// import { Node, Project, SyntaxKind } from "ts-morph"; + +// import { filePath } from "./language-server.source"; + +// The following tool is helpful for understanding the TypeScript AST associated with these tests: +// https://ts-ast-viewer.com/ (just copy the contents of language-server.source into the viewer) + +test("", () => {}); +// describe("Executing Go To Definition (and therefore Find Usages and Rename Refactoring) using an IDE works on inferred object properties", () => { +// // Compile file developmentEnvironment.source +// const project = new Project({ +// tsConfigFilePath: path.join(__dirname, "..", "..", "tsconfig.json"), +// skipAddingFilesFromTsConfig: true, +// }); +// const sourceFile = project.addSourceFileAtPath(filePath); + +// test("works for object properties inferred from z.object()", () => { +// // Find usage of Test.f1 property +// const instanceVariable = +// sourceFile.getVariableDeclarationOrThrow("instanceOfTest"); +// const propertyBeingAssigned = getPropertyBeingAssigned( +// instanceVariable, +// "f1" +// ); + +// // Find definition of Test.f1 property +// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0]; +// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind( +// SyntaxKind.VariableDeclaration +// ); + +// // Assert that find definition returned the Zod definition of Test +// expect(definitionOfProperty?.getText()).toEqual("f1: z.number()"); +// expect(parentOfProperty?.getName()).toEqual("Test"); +// }); + +// // test("works for first object properties inferred from z.object().merge()", () => { +// // // Find usage of TestMerge.f1 property +// // const instanceVariable = sourceFile.getVariableDeclarationOrThrow( +// // "instanceOfTestMerge" +// // ); +// // const propertyBeingAssigned = getPropertyBeingAssigned( +// // instanceVariable, +// // "f1" +// // ); + +// // // Find definition of TestMerge.f1 property +// // const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0]; +// // const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind( +// // SyntaxKind.VariableDeclaration +// // ); + +// // // Assert that find definition returned the Zod definition of Test +// // expect(definitionOfProperty?.getText()).toEqual("f1: z.number()"); +// // expect(parentOfProperty?.getName()).toEqual("Test"); +// // }); + +// // test("works for second object properties inferred from z.object().merge()", () => { +// // // Find usage of TestMerge.f2 property +// // const instanceVariable = sourceFile.getVariableDeclarationOrThrow( +// // "instanceOfTestMerge" +// // ); +// // const propertyBeingAssigned = getPropertyBeingAssigned( +// // instanceVariable, +// // "f2" +// // ); + +// // // Find definition of TestMerge.f2 property +// // const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0]; +// // const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind( +// // SyntaxKind.VariableDeclaration +// // ); + +// // // Assert that find definition returned the Zod definition of TestMerge +// // expect(definitionOfProperty?.getText()).toEqual( +// // "f2: z.string().optional()" +// // ); +// // expect(parentOfProperty?.getName()).toEqual("TestMerge"); +// // }); + +// test("works for first object properties inferred from z.union()", () => { +// // Find usage of TestUnion.f1 property +// const instanceVariable = sourceFile.getVariableDeclarationOrThrow( +// "instanceOfTestUnion" +// ); +// const propertyBeingAssigned = getPropertyBeingAssigned( +// instanceVariable, +// "f1" +// ); + +// // Find definition of TestUnion.f1 property +// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0]; +// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind( +// SyntaxKind.VariableDeclaration +// ); + +// // Assert that find definition returned the Zod definition of Test +// expect(definitionOfProperty?.getText()).toEqual("f1: z.number()"); +// expect(parentOfProperty?.getName()).toEqual("Test"); +// }); + +// test("works for second object properties inferred from z.union()", () => { +// // Find usage of TestUnion.f2 property +// const instanceVariable = sourceFile.getVariableDeclarationOrThrow( +// "instanceOfTestUnion" +// ); +// const propertyBeingAssigned = getPropertyBeingAssigned( +// instanceVariable, +// "f2" +// ); + +// // Find definition of TestUnion.f2 property +// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0]; +// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind( +// SyntaxKind.VariableDeclaration +// ); + +// // Assert that find definition returned the Zod definition of TestUnion +// expect(definitionOfProperty?.getText()).toEqual( +// "f2: z.string().optional()" +// ); +// expect(parentOfProperty?.getName()).toEqual("TestUnion"); +// }); + +// test("works for object properties inferred from z.object().partial()", () => { +// // Find usage of TestPartial.f1 property +// const instanceVariable = sourceFile.getVariableDeclarationOrThrow( +// "instanceOfTestPartial" +// ); +// const propertyBeingAssigned = getPropertyBeingAssigned( +// instanceVariable, +// "f1" +// ); + +// // Find definition of TestPartial.f1 property +// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0]; +// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind( +// SyntaxKind.VariableDeclaration +// ); + +// // Assert that find definition returned the Zod definition of Test +// expect(definitionOfProperty?.getText()).toEqual("f1: z.number()"); +// expect(parentOfProperty?.getName()).toEqual("Test"); +// }); + +// test("works for object properties inferred from z.object().pick()", () => { +// // Find usage of TestPick.f1 property +// const instanceVariable = +// sourceFile.getVariableDeclarationOrThrow("instanceOfTestPick"); +// const propertyBeingAssigned = getPropertyBeingAssigned( +// instanceVariable, +// "f1" +// ); + +// // Find definition of TestPick.f1 property +// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0]; +// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind( +// SyntaxKind.VariableDeclaration +// ); + +// // Assert that find definition returned the Zod definition of Test +// expect(definitionOfProperty?.getText()).toEqual("f1: z.number()"); +// expect(parentOfProperty?.getName()).toEqual("Test"); +// }); + +// test("works for object properties inferred from z.object().omit()", () => { +// // Find usage of TestOmit.f1 property +// const instanceVariable = +// sourceFile.getVariableDeclarationOrThrow("instanceOfTestOmit"); +// const propertyBeingAssigned = getPropertyBeingAssigned( +// instanceVariable, +// "f1" +// ); + +// // Find definition of TestOmit.f1 property +// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0]; +// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind( +// SyntaxKind.VariableDeclaration +// ); + +// // Assert that find definition returned the Zod definition of Test +// expect(definitionOfProperty?.getText()).toEqual("f1: z.number()"); +// expect(parentOfProperty?.getName()).toEqual("Test"); +// }); +// }); + +// const getPropertyBeingAssigned = (node: Node, name: string) => { +// const propertyAssignment = node.forEachDescendant((descendent) => +// Node.isPropertyAssignment(descendent) && descendent.getName() == name +// ? descendent +// : undefined +// ); + +// if (propertyAssignment == null) +// fail(`Could not find property assignment with name ${name}`); + +// const propertyLiteral = propertyAssignment.getFirstDescendantByKind( +// SyntaxKind.Identifier +// ); + +// if (propertyLiteral == null) +// fail(`Could not find property literal with name ${name}`); + +// return propertyLiteral; +// }; diff --git a/node_modules/zod/src/v3/tests/literal.test.ts b/node_modules/zod/src/v3/tests/literal.test.ts new file mode 100644 index 0000000..d166a24 --- /dev/null +++ b/node_modules/zod/src/v3/tests/literal.test.ts @@ -0,0 +1,36 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; + +const literalTuna = z.literal("tuna"); +const literalFortyTwo = z.literal(42); +const literalTrue = z.literal(true); + +const terrificSymbol = Symbol("terrific"); +const literalTerrificSymbol = z.literal(terrificSymbol); + +test("passing validations", () => { + literalTuna.parse("tuna"); + literalFortyTwo.parse(42); + literalTrue.parse(true); + literalTerrificSymbol.parse(terrificSymbol); +}); + +test("failing validations", () => { + expect(() => literalTuna.parse("shark")).toThrow(); + expect(() => literalFortyTwo.parse(43)).toThrow(); + expect(() => literalTrue.parse(false)).toThrow(); + expect(() => literalTerrificSymbol.parse(Symbol("terrific"))).toThrow(); +}); + +test("invalid_literal should have `received` field with data", () => { + const data = "shark"; + const result = literalTuna.safeParse(data); + if (!result.success) { + const issue = result.error.issues[0]; + if (issue.code === "invalid_literal") { + expect(issue.received).toBe(data); + } + } +}); diff --git a/node_modules/zod/src/v3/tests/map.test.ts b/node_modules/zod/src/v3/tests/map.test.ts new file mode 100644 index 0000000..9471819 --- /dev/null +++ b/node_modules/zod/src/v3/tests/map.test.ts @@ -0,0 +1,110 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { ZodIssueCode } from "zod/v3"; +import { util } from "../helpers/util.js"; + +const stringMap = z.map(z.string(), z.string()); +type stringMap = z.infer; + +test("type inference", () => { + util.assertEqual>(true); +}); + +test("valid parse", () => { + const result = stringMap.safeParse( + new Map([ + ["first", "foo"], + ["second", "bar"], + ]) + ); + expect(result.success).toEqual(true); + if (result.success) { + expect(result.data.has("first")).toEqual(true); + expect(result.data.has("second")).toEqual(true); + expect(result.data.get("first")).toEqual("foo"); + expect(result.data.get("second")).toEqual("bar"); + } +}); + +test("valid parse async", async () => { + const result = await stringMap.spa( + new Map([ + ["first", "foo"], + ["second", "bar"], + ]) + ); + expect(result.success).toEqual(true); + if (result.success) { + expect(result.data.has("first")).toEqual(true); + expect(result.data.has("second")).toEqual(true); + expect(result.data.get("first")).toEqual("foo"); + expect(result.data.get("second")).toEqual("bar"); + } +}); + +test("throws when a Set is given", () => { + const result = stringMap.safeParse(new Set([])); + expect(result.success).toEqual(false); + if (result.success === false) { + expect(result.error.issues.length).toEqual(1); + expect(result.error.issues[0].code).toEqual(ZodIssueCode.invalid_type); + } +}); + +test("throws when the given map has invalid key and invalid input", () => { + const result = stringMap.safeParse(new Map([[42, Symbol()]])); + expect(result.success).toEqual(false); + if (result.success === false) { + expect(result.error.issues.length).toEqual(2); + expect(result.error.issues[0].code).toEqual(ZodIssueCode.invalid_type); + expect(result.error.issues[0].path).toEqual([0, "key"]); + expect(result.error.issues[1].code).toEqual(ZodIssueCode.invalid_type); + expect(result.error.issues[1].path).toEqual([0, "value"]); + } +}); + +test("throws when the given map has multiple invalid entries", () => { + // const result = stringMap.safeParse(new Map([[42, Symbol()]])); + + const result = stringMap.safeParse( + new Map([ + [1, "foo"], + ["bar", 2], + ] as [any, any][]) as Map + ); + + // const result = stringMap.safeParse(new Map([[42, Symbol()]])); + expect(result.success).toEqual(false); + if (result.success === false) { + expect(result.error.issues.length).toEqual(2); + expect(result.error.issues[0].code).toEqual(ZodIssueCode.invalid_type); + expect(result.error.issues[0].path).toEqual([0, "key"]); + expect(result.error.issues[1].code).toEqual(ZodIssueCode.invalid_type); + expect(result.error.issues[1].path).toEqual([1, "value"]); + } +}); + +test("dirty", async () => { + const map = z.map( + z.string().refine((val) => val === val.toUpperCase(), { + message: "Keys must be uppercase", + }), + z.string() + ); + const result = await map.spa( + new Map([ + ["first", "foo"], + ["second", "bar"], + ]) + ); + expect(result.success).toEqual(false); + if (!result.success) { + expect(result.error.issues.length).toEqual(2); + expect(result.error.issues[0].code).toEqual(z.ZodIssueCode.custom); + expect(result.error.issues[0].message).toEqual("Keys must be uppercase"); + expect(result.error.issues[1].code).toEqual(z.ZodIssueCode.custom); + expect(result.error.issues[1].message).toEqual("Keys must be uppercase"); + } +}); diff --git a/node_modules/zod/src/v3/tests/masking.test.ts b/node_modules/zod/src/v3/tests/masking.test.ts new file mode 100644 index 0000000..63817e2 --- /dev/null +++ b/node_modules/zod/src/v3/tests/masking.test.ts @@ -0,0 +1,4 @@ +// @ts-ignore TS6133 +import { test } from "vitest"; + +test("masking test", () => {}); diff --git a/node_modules/zod/src/v3/tests/mocker.test.ts b/node_modules/zod/src/v3/tests/mocker.test.ts new file mode 100644 index 0000000..3a2506b --- /dev/null +++ b/node_modules/zod/src/v3/tests/mocker.test.ts @@ -0,0 +1,19 @@ +// @ts-ignore TS6133 +import { test } from "vitest"; + +import { Mocker } from "./Mocker.js"; + +test("mocker", () => { + const mocker = new Mocker(); + mocker.string; + mocker.number; + mocker.boolean; + mocker.null; + mocker.undefined; + mocker.stringOptional; + mocker.stringNullable; + mocker.numberOptional; + mocker.numberNullable; + mocker.booleanOptional; + mocker.booleanNullable; +}); diff --git a/node_modules/zod/src/v3/tests/nan.test.ts b/node_modules/zod/src/v3/tests/nan.test.ts new file mode 100644 index 0000000..e24567a --- /dev/null +++ b/node_modules/zod/src/v3/tests/nan.test.ts @@ -0,0 +1,21 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; + +const schema = z.nan(); + +test("passing validations", () => { + schema.parse(Number.NaN); + schema.parse(Number("Not a number")); +}); + +test("failing validations", () => { + expect(() => schema.parse(5)).toThrow(); + expect(() => schema.parse("John")).toThrow(); + expect(() => schema.parse(true)).toThrow(); + expect(() => schema.parse(null)).toThrow(); + expect(() => schema.parse(undefined)).toThrow(); + expect(() => schema.parse({})).toThrow(); + expect(() => schema.parse([])).toThrow(); +}); diff --git a/node_modules/zod/src/v3/tests/nativeEnum.test.ts b/node_modules/zod/src/v3/tests/nativeEnum.test.ts new file mode 100644 index 0000000..61eb37a --- /dev/null +++ b/node_modules/zod/src/v3/tests/nativeEnum.test.ts @@ -0,0 +1,87 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { util } from "../helpers/util.js"; + +test("nativeEnum test with consts", () => { + const Fruits: { Apple: "apple"; Banana: "banana" } = { + Apple: "apple", + Banana: "banana", + }; + const fruitEnum = z.nativeEnum(Fruits); + type fruitEnum = z.infer; + fruitEnum.parse("apple"); + fruitEnum.parse("banana"); + fruitEnum.parse(Fruits.Apple); + fruitEnum.parse(Fruits.Banana); + util.assertEqual(true); +}); + +test("nativeEnum test with real enum", () => { + enum Fruits { + Apple = "apple", + Banana = "banana", + } + // @ts-ignore + const fruitEnum = z.nativeEnum(Fruits); + type fruitEnum = z.infer; + fruitEnum.parse("apple"); + fruitEnum.parse("banana"); + fruitEnum.parse(Fruits.Apple); + fruitEnum.parse(Fruits.Banana); + util.assertIs(true); +}); + +test("nativeEnum test with const with numeric keys", () => { + const FruitValues = { + Apple: 10, + Banana: 20, + // @ts-ignore + } as const; + const fruitEnum = z.nativeEnum(FruitValues); + type fruitEnum = z.infer; + fruitEnum.parse(10); + fruitEnum.parse(20); + fruitEnum.parse(FruitValues.Apple); + fruitEnum.parse(FruitValues.Banana); + util.assertEqual(true); +}); + +test("from enum", () => { + enum Fruits { + Cantaloupe = 0, + Apple = "apple", + Banana = "banana", + } + + const FruitEnum = z.nativeEnum(Fruits as any); + type _FruitEnum = z.infer; + FruitEnum.parse(Fruits.Cantaloupe); + FruitEnum.parse(Fruits.Apple); + FruitEnum.parse("apple"); + FruitEnum.parse(0); + expect(() => FruitEnum.parse(1)).toThrow(); + expect(() => FruitEnum.parse("Apple")).toThrow(); + expect(() => FruitEnum.parse("Cantaloupe")).toThrow(); +}); + +test("from const", () => { + const Greek = { + Alpha: "a", + Beta: "b", + Gamma: 3, + // @ts-ignore + } as const; + + const GreekEnum = z.nativeEnum(Greek); + type _GreekEnum = z.infer; + GreekEnum.parse("a"); + GreekEnum.parse("b"); + GreekEnum.parse(3); + expect(() => GreekEnum.parse("v")).toThrow(); + expect(() => GreekEnum.parse("Alpha")).toThrow(); + expect(() => GreekEnum.parse(2)).toThrow(); + + expect(GreekEnum.enum.Alpha).toEqual("a"); +}); diff --git a/node_modules/zod/src/v3/tests/nullable.test.ts b/node_modules/zod/src/v3/tests/nullable.test.ts new file mode 100644 index 0000000..90c1eed --- /dev/null +++ b/node_modules/zod/src/v3/tests/nullable.test.ts @@ -0,0 +1,42 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; + +function checkErrors(a: z.ZodTypeAny, bad: any) { + let expected: any; + try { + a.parse(bad); + } catch (error) { + expected = (error as z.ZodError).formErrors; + } + try { + a.nullable().parse(bad); + } catch (error) { + expect((error as z.ZodError).formErrors).toEqual(expected); + } +} + +test("Should have error messages appropriate for the underlying type", () => { + checkErrors(z.string().min(2), 1); + z.string().min(2).nullable().parse(null); + checkErrors(z.number().gte(2), 1); + z.number().gte(2).nullable().parse(null); + checkErrors(z.boolean(), ""); + z.boolean().nullable().parse(null); + checkErrors(z.null(), null); + z.null().nullable().parse(null); + checkErrors(z.null(), {}); + z.null().nullable().parse(null); + checkErrors(z.object({}), 1); + z.object({}).nullable().parse(null); + checkErrors(z.tuple([]), 1); + z.tuple([]).nullable().parse(null); + checkErrors(z.unknown(), 1); + z.unknown().nullable().parse(null); +}); + +test("unwrap", () => { + const unwrapped = z.string().nullable().unwrap(); + expect(unwrapped).toBeInstanceOf(z.ZodString); +}); diff --git a/node_modules/zod/src/v3/tests/number.test.ts b/node_modules/zod/src/v3/tests/number.test.ts new file mode 100644 index 0000000..db3f73b --- /dev/null +++ b/node_modules/zod/src/v3/tests/number.test.ts @@ -0,0 +1,176 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; + +const gtFive = z.number().gt(5); +const gteFive = z.number().gte(-5).gte(5); +const minFive = z.number().min(0).min(5); +const ltFive = z.number().lte(10).lt(5); +const lteFive = z.number().lte(5); +const maxFive = z.number().max(10).max(5); +const intNum = z.number().int(); +const positive = z.number().positive(); +const negative = z.number().negative(); +const nonpositive = z.number().nonpositive(); +const nonnegative = z.number().nonnegative(); +const multipleOfFive = z.number().multipleOf(5); +const multipleOfNegativeFive = z.number().multipleOf(-5); +const finite = z.number().finite(); +const safe = z.number().safe(); +const stepPointOne = z.number().step(0.1); +const stepPointZeroZeroZeroOne = z.number().step(0.0001); +const stepSixPointFour = z.number().step(6.4); + +test("passing validations", () => { + z.number().parse(1); + z.number().parse(1.5); + z.number().parse(0); + z.number().parse(-1.5); + z.number().parse(-1); + z.number().parse(Number.POSITIVE_INFINITY); + z.number().parse(Number.NEGATIVE_INFINITY); + gtFive.parse(6); + gtFive.parse(Number.POSITIVE_INFINITY); + gteFive.parse(5); + gteFive.parse(Number.POSITIVE_INFINITY); + minFive.parse(5); + minFive.parse(Number.POSITIVE_INFINITY); + ltFive.parse(4); + ltFive.parse(Number.NEGATIVE_INFINITY); + lteFive.parse(5); + lteFive.parse(Number.NEGATIVE_INFINITY); + maxFive.parse(5); + maxFive.parse(Number.NEGATIVE_INFINITY); + intNum.parse(4); + positive.parse(1); + positive.parse(Number.POSITIVE_INFINITY); + negative.parse(-1); + negative.parse(Number.NEGATIVE_INFINITY); + nonpositive.parse(0); + nonpositive.parse(-1); + nonpositive.parse(Number.NEGATIVE_INFINITY); + nonnegative.parse(0); + nonnegative.parse(1); + nonnegative.parse(Number.POSITIVE_INFINITY); + multipleOfFive.parse(15); + multipleOfFive.parse(-15); + multipleOfNegativeFive.parse(-15); + multipleOfNegativeFive.parse(15); + finite.parse(123); + safe.parse(Number.MIN_SAFE_INTEGER); + safe.parse(Number.MAX_SAFE_INTEGER); + stepPointOne.parse(6); + stepPointOne.parse(6.1); + stepPointOne.parse(6.1); + stepSixPointFour.parse(12.8); + stepPointZeroZeroZeroOne.parse(3.01); +}); + +test("failing validations", () => { + expect(() => ltFive.parse(5)).toThrow(); + expect(() => lteFive.parse(6)).toThrow(); + expect(() => maxFive.parse(6)).toThrow(); + expect(() => gtFive.parse(5)).toThrow(); + expect(() => gteFive.parse(4)).toThrow(); + expect(() => minFive.parse(4)).toThrow(); + expect(() => intNum.parse(3.14)).toThrow(); + expect(() => positive.parse(0)).toThrow(); + expect(() => positive.parse(-1)).toThrow(); + expect(() => negative.parse(0)).toThrow(); + expect(() => negative.parse(1)).toThrow(); + expect(() => nonpositive.parse(1)).toThrow(); + expect(() => nonnegative.parse(-1)).toThrow(); + expect(() => multipleOfFive.parse(7.5)).toThrow(); + expect(() => multipleOfFive.parse(-7.5)).toThrow(); + expect(() => multipleOfNegativeFive.parse(-7.5)).toThrow(); + expect(() => multipleOfNegativeFive.parse(7.5)).toThrow(); + expect(() => finite.parse(Number.POSITIVE_INFINITY)).toThrow(); + expect(() => finite.parse(Number.NEGATIVE_INFINITY)).toThrow(); + expect(() => safe.parse(Number.MIN_SAFE_INTEGER - 1)).toThrow(); + expect(() => safe.parse(Number.MAX_SAFE_INTEGER + 1)).toThrow(); + + expect(() => stepPointOne.parse(6.11)).toThrow(); + expect(() => stepPointOne.parse(6.1000000001)).toThrow(); + expect(() => stepSixPointFour.parse(6.41)).toThrow(); +}); + +test("parse NaN", () => { + expect(() => z.number().parse(Number.NaN)).toThrow(); +}); + +test("min max getters", () => { + expect(z.number().minValue).toBeNull; + expect(ltFive.minValue).toBeNull; + expect(lteFive.minValue).toBeNull; + expect(maxFive.minValue).toBeNull; + expect(negative.minValue).toBeNull; + expect(nonpositive.minValue).toBeNull; + expect(intNum.minValue).toBeNull; + expect(multipleOfFive.minValue).toBeNull; + expect(finite.minValue).toBeNull; + expect(gtFive.minValue).toEqual(5); + expect(gteFive.minValue).toEqual(5); + expect(minFive.minValue).toEqual(5); + expect(minFive.min(10).minValue).toEqual(10); + expect(positive.minValue).toEqual(0); + expect(nonnegative.minValue).toEqual(0); + expect(safe.minValue).toEqual(Number.MIN_SAFE_INTEGER); + + expect(z.number().maxValue).toBeNull; + expect(gtFive.maxValue).toBeNull; + expect(gteFive.maxValue).toBeNull; + expect(minFive.maxValue).toBeNull; + expect(positive.maxValue).toBeNull; + expect(nonnegative.maxValue).toBeNull; + expect(intNum.minValue).toBeNull; + expect(multipleOfFive.minValue).toBeNull; + expect(finite.minValue).toBeNull; + expect(ltFive.maxValue).toEqual(5); + expect(lteFive.maxValue).toEqual(5); + expect(maxFive.maxValue).toEqual(5); + expect(maxFive.max(1).maxValue).toEqual(1); + expect(negative.maxValue).toEqual(0); + expect(nonpositive.maxValue).toEqual(0); + expect(safe.maxValue).toEqual(Number.MAX_SAFE_INTEGER); +}); + +test("int getter", () => { + expect(z.number().isInt).toEqual(false); + expect(z.number().multipleOf(1.5).isInt).toEqual(false); + expect(gtFive.isInt).toEqual(false); + expect(gteFive.isInt).toEqual(false); + expect(minFive.isInt).toEqual(false); + expect(positive.isInt).toEqual(false); + expect(nonnegative.isInt).toEqual(false); + expect(finite.isInt).toEqual(false); + expect(ltFive.isInt).toEqual(false); + expect(lteFive.isInt).toEqual(false); + expect(maxFive.isInt).toEqual(false); + expect(negative.isInt).toEqual(false); + expect(nonpositive.isInt).toEqual(false); + expect(safe.isInt).toEqual(false); + + expect(intNum.isInt).toEqual(true); + expect(multipleOfFive.isInt).toEqual(true); +}); + +test("finite getter", () => { + expect(z.number().isFinite).toEqual(false); + expect(gtFive.isFinite).toEqual(false); + expect(gteFive.isFinite).toEqual(false); + expect(minFive.isFinite).toEqual(false); + expect(positive.isFinite).toEqual(false); + expect(nonnegative.isFinite).toEqual(false); + expect(ltFive.isFinite).toEqual(false); + expect(lteFive.isFinite).toEqual(false); + expect(maxFive.isFinite).toEqual(false); + expect(negative.isFinite).toEqual(false); + expect(nonpositive.isFinite).toEqual(false); + + expect(finite.isFinite).toEqual(true); + expect(intNum.isFinite).toEqual(true); + expect(multipleOfFive.isFinite).toEqual(true); + expect(z.number().min(5).max(10).isFinite).toEqual(true); + expect(safe.isFinite).toEqual(true); +}); diff --git a/node_modules/zod/src/v3/tests/object-augmentation.test.ts b/node_modules/zod/src/v3/tests/object-augmentation.test.ts new file mode 100644 index 0000000..964ea3d --- /dev/null +++ b/node_modules/zod/src/v3/tests/object-augmentation.test.ts @@ -0,0 +1,29 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; + +test("object augmentation", () => { + const Animal = z + .object({ + species: z.string(), + }) + .augment({ + population: z.number(), + }); + // overwrites `species` + const ModifiedAnimal = Animal.augment({ + species: z.array(z.string()), + }); + ModifiedAnimal.parse({ + species: ["asd"], + population: 1324, + }); + + const bad = () => + ModifiedAnimal.parse({ + species: "asdf", + population: 1324, + } as any); + expect(bad).toThrow(); +}); diff --git a/node_modules/zod/src/v3/tests/object-in-es5-env.test.ts b/node_modules/zod/src/v3/tests/object-in-es5-env.test.ts new file mode 100644 index 0000000..293ebf0 --- /dev/null +++ b/node_modules/zod/src/v3/tests/object-in-es5-env.test.ts @@ -0,0 +1,29 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; + +const RealSet = Set; +const RealMap = Map; +const RealDate = Date; + +test("doesn’t throw when Date is undefined", () => { + delete (globalThis as any).Date; + const result = z.object({}).safeParse({}); + expect(result.success).toEqual(true); + globalThis.Date = RealDate; +}); + +test("doesn’t throw when Set is undefined", () => { + delete (globalThis as any).Set; + const result = z.object({}).safeParse({}); + expect(result.success).toEqual(true); + globalThis.Set = RealSet; +}); + +test("doesn’t throw when Map is undefined", () => { + delete (globalThis as any).Map; + const result = z.object({}).safeParse({}); + expect(result.success).toEqual(true); + globalThis.Map = RealMap; +}); diff --git a/node_modules/zod/src/v3/tests/object.test.ts b/node_modules/zod/src/v3/tests/object.test.ts new file mode 100644 index 0000000..d8772d4 --- /dev/null +++ b/node_modules/zod/src/v3/tests/object.test.ts @@ -0,0 +1,434 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { util } from "../helpers/util.js"; + +const Test = z.object({ + f1: z.number(), + f2: z.string().optional(), + f3: z.string().nullable(), + f4: z.array(z.object({ t: z.union([z.string(), z.boolean()]) })), +}); + +test("object type inference", () => { + type TestType = { + f1: number; + f2?: string | undefined; + f3: string | null; + f4: { t: string | boolean }[]; + }; + + util.assertEqual, TestType>(true); +}); + +test("unknown throw", () => { + const asdf: unknown = 35; + expect(() => Test.parse(asdf)).toThrow(); +}); + +test("shape() should return schema of particular key", () => { + const f1Schema = Test.shape.f1; + const f2Schema = Test.shape.f2; + const f3Schema = Test.shape.f3; + const f4Schema = Test.shape.f4; + + expect(f1Schema).toBeInstanceOf(z.ZodNumber); + expect(f2Schema).toBeInstanceOf(z.ZodOptional); + expect(f3Schema).toBeInstanceOf(z.ZodNullable); + expect(f4Schema).toBeInstanceOf(z.ZodArray); +}); + +test("correct parsing", () => { + Test.parse({ + f1: 12, + f2: "string", + f3: "string", + f4: [ + { + t: "string", + }, + ], + }); + + Test.parse({ + f1: 12, + f3: null, + f4: [ + { + t: false, + }, + ], + }); +}); + +test("incorrect #1", () => { + expect(() => Test.parse({} as any)).toThrow(); +}); + +test("nonstrict by default", () => { + z.object({ points: z.number() }).parse({ + points: 2314, + unknown: "asdf", + }); +}); + +const data = { + points: 2314, + unknown: "asdf", +}; + +test("strip by default", () => { + const val = z.object({ points: z.number() }).parse(data); + expect(val).toEqual({ points: 2314 }); +}); + +test("unknownkeys override", () => { + const val = z.object({ points: z.number() }).strict().passthrough().strip().nonstrict().parse(data); + + expect(val).toEqual(data); +}); + +test("passthrough unknown", () => { + const val = z.object({ points: z.number() }).passthrough().parse(data); + + expect(val).toEqual(data); +}); + +test("strip unknown", () => { + const val = z.object({ points: z.number() }).strip().parse(data); + + expect(val).toEqual({ points: 2314 }); +}); + +test("strict", () => { + const val = z.object({ points: z.number() }).strict().safeParse(data); + + expect(val.success).toEqual(false); +}); + +test("catchall inference", () => { + const o1 = z + .object({ + first: z.string(), + }) + .catchall(z.number()); + + const d1 = o1.parse({ first: "asdf", num: 1243 }); + util.assertEqual(true); + util.assertEqual(true); +}); + +test("catchall overrides strict", () => { + const o1 = z.object({ first: z.string().optional() }).strict().catchall(z.number()); + + // should run fine + // setting a catchall overrides the unknownKeys behavior + o1.parse({ + asdf: 1234, + }); + + // should only run catchall validation + // against unknown keys + o1.parse({ + first: "asdf", + asdf: 1234, + }); +}); + +test("catchall overrides strict", () => { + const o1 = z + .object({ + first: z.string(), + }) + .strict() + .catchall(z.number()); + + // should run fine + // setting a catchall overrides the unknownKeys behavior + o1.parse({ + first: "asdf", + asdf: 1234, + }); +}); + +test("test that optional keys are unset", async () => { + const SNamedEntity = z.object({ + id: z.string(), + set: z.string().optional(), + unset: z.string().optional(), + }); + const result = await SNamedEntity.parse({ + id: "asdf", + set: undefined, + }); + // eslint-disable-next-line ban/ban + expect(Object.keys(result)).toEqual(["id", "set"]); +}); + +test("test catchall parsing", async () => { + const result = z.object({ name: z.string() }).catchall(z.number()).parse({ name: "Foo", validExtraKey: 61 }); + + expect(result).toEqual({ name: "Foo", validExtraKey: 61 }); + + const result2 = z + .object({ name: z.string() }) + .catchall(z.number()) + .safeParse({ name: "Foo", validExtraKey: 61, invalid: "asdf" }); + + expect(result2.success).toEqual(false); +}); + +test("test nonexistent keys", async () => { + const Schema = z.union([z.object({ a: z.string() }), z.object({ b: z.number() })]); + const obj = { a: "A" }; + const result = await Schema.spa(obj); // Works with 1.11.10, breaks with 2.0.0-beta.21 + expect(result.success).toBe(true); +}); + +test("test async union", async () => { + const Schema2 = z.union([ + z.object({ + ty: z.string(), + }), + z.object({ + ty: z.number(), + }), + ]); + + const obj = { ty: "A" }; + const result = await Schema2.spa(obj); // Works with 1.11.10, breaks with 2.0.0-beta.21 + expect(result.success).toEqual(true); +}); + +test("test inferred merged type", async () => { + const asdf = z.object({ a: z.string() }).merge(z.object({ a: z.number() })); + type asdf = z.infer; + util.assertEqual(true); +}); + +test("inferred merged object type with optional properties", async () => { + const Merged = z + .object({ a: z.string(), b: z.string().optional() }) + .merge(z.object({ a: z.string().optional(), b: z.string() })); + type Merged = z.infer; + util.assertEqual(true); + // todo + // util.assertEqual(true); +}); + +test("inferred unioned object type with optional properties", async () => { + const Unioned = z.union([ + z.object({ a: z.string(), b: z.string().optional() }), + z.object({ a: z.string().optional(), b: z.string() }), + ]); + type Unioned = z.infer; + util.assertEqual(true); +}); + +test("inferred enum type", async () => { + const Enum = z.object({ a: z.string(), b: z.string().optional() }).keyof(); + + expect(Enum.Values).toEqual({ + a: "a", + b: "b", + }); + expect(Enum.enum).toEqual({ + a: "a", + b: "b", + }); + expect(Enum._def.values).toEqual(["a", "b"]); + type Enum = z.infer; + util.assertEqual(true); +}); + +test("inferred partial object type with optional properties", async () => { + const Partial = z.object({ a: z.string(), b: z.string().optional() }).partial(); + type Partial = z.infer; + util.assertEqual(true); +}); + +test("inferred picked object type with optional properties", async () => { + const Picked = z.object({ a: z.string(), b: z.string().optional() }).pick({ b: true }); + type Picked = z.infer; + util.assertEqual(true); +}); + +test("inferred type for unknown/any keys", () => { + const myType = z.object({ + anyOptional: z.any().optional(), + anyRequired: z.any(), + unknownOptional: z.unknown().optional(), + unknownRequired: z.unknown(), + }); + type myType = z.infer; + util.assertEqual< + myType, + { + anyOptional?: any; + anyRequired?: any; + unknownOptional?: unknown; + unknownRequired?: unknown; + } + >(true); +}); + +test("setKey", () => { + const base = z.object({ name: z.string() }); + const withNewKey = base.setKey("age", z.number()); + + type withNewKey = z.infer; + util.assertEqual(true); + withNewKey.parse({ name: "asdf", age: 1234 }); +}); + +test("strictcreate", async () => { + const strictObj = z.strictObject({ + name: z.string(), + }); + + const syncResult = strictObj.safeParse({ name: "asdf", unexpected: 13 }); + expect(syncResult.success).toEqual(false); + + const asyncResult = await strictObj.spa({ name: "asdf", unexpected: 13 }); + expect(asyncResult.success).toEqual(false); +}); + +test("object with refine", async () => { + const schema = z + .object({ + a: z.string().default("foo"), + b: z.number(), + }) + .refine(() => true); + expect(schema.parse({ b: 5 })).toEqual({ b: 5, a: "foo" }); + const result = await schema.parseAsync({ b: 5 }); + expect(result).toEqual({ b: 5, a: "foo" }); +}); + +test("intersection of object with date", async () => { + const schema = z.object({ + a: z.date(), + }); + expect(schema.and(schema).parse({ a: new Date(1637353595983) })).toEqual({ + a: new Date(1637353595983), + }); + const result = await schema.parseAsync({ a: new Date(1637353595983) }); + expect(result).toEqual({ a: new Date(1637353595983) }); +}); + +test("intersection of object with refine with date", async () => { + const schema = z + .object({ + a: z.date(), + }) + .refine(() => true); + expect(schema.and(schema).parse({ a: new Date(1637353595983) })).toEqual({ + a: new Date(1637353595983), + }); + const result = await schema.parseAsync({ a: new Date(1637353595983) }); + expect(result).toEqual({ a: new Date(1637353595983) }); +}); + +test("constructor key", () => { + const person = z + .object({ + name: z.string(), + }) + .strict(); + + expect(() => + person.parse({ + name: "bob dylan", + constructor: 61, + }) + ).toThrow(); +}); + +test("constructor key", () => { + const Example = z.object({ + prop: z.string(), + opt: z.number().optional(), + arr: z.string().array(), + }); + + type Example = z.infer; + util.assertEqual(true); +}); + +test("unknownkeys merging", () => { + // This one is "strict" + const schemaA = z + .object({ + a: z.string(), + }) + .strict(); + + // This one is "strip" + const schemaB = z + .object({ + b: z.string(), + }) + .catchall(z.string()); + + const mergedSchema = schemaA.merge(schemaB); + type mergedSchema = typeof mergedSchema; + util.assertEqual(true); + expect(mergedSchema._def.unknownKeys).toEqual("strip"); + + util.assertEqual(true); + expect(mergedSchema._def.catchall instanceof z.ZodString).toEqual(true); +}); + +const personToExtend = z.object({ + firstName: z.string(), + lastName: z.string(), +}); + +test("extend() should return schema with new key", () => { + const PersonWithNickname = personToExtend.extend({ nickName: z.string() }); + type PersonWithNickname = z.infer; + + const expected = { firstName: "f", nickName: "n", lastName: "l" }; + const actual = PersonWithNickname.parse(expected); + + expect(actual).toEqual(expected); + util.assertEqual(true); + util.assertEqual(true); +}); + +test("extend() should have power to override existing key", () => { + const PersonWithNumberAsLastName = personToExtend.extend({ + lastName: z.number(), + }); + type PersonWithNumberAsLastName = z.infer; + + const expected = { firstName: "f", lastName: 42 }; + const actual = PersonWithNumberAsLastName.parse(expected); + + expect(actual).toEqual(expected); + util.assertEqual(true); +}); + +test("passthrough index signature", () => { + const a = z.object({ a: z.string() }); + type a = z.infer; + util.assertEqual<{ a: string }, a>(true); + const b = a.passthrough(); + type b = z.infer; + util.assertEqual<{ a: string } & { [k: string]: unknown }, b>(true); +}); + +test("xor", () => { + type Without = { [P in Exclude]?: never }; + type XOR = T extends object ? (U extends object ? (Without & U) | (Without & T) : U) : T; + + type A = { name: string; a: number }; + type B = { name: string; b: number }; + type C = XOR; + type Outer = { data: C }; + + const _Outer: z.ZodType = z.object({ + data: z.union([z.object({ name: z.string(), a: z.number() }), z.object({ name: z.string(), b: z.number() })]), + }); +}); diff --git a/node_modules/zod/src/v3/tests/optional.test.ts b/node_modules/zod/src/v3/tests/optional.test.ts new file mode 100644 index 0000000..016c954 --- /dev/null +++ b/node_modules/zod/src/v3/tests/optional.test.ts @@ -0,0 +1,42 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; + +function checkErrors(a: z.ZodTypeAny, bad: any) { + let expected: any; + try { + a.parse(bad); + } catch (error) { + expected = (error as z.ZodError).formErrors; + } + try { + a.optional().parse(bad); + } catch (error) { + expect((error as z.ZodError).formErrors).toEqual(expected); + } +} + +test("Should have error messages appropriate for the underlying type", () => { + checkErrors(z.string().min(2), 1); + z.string().min(2).optional().parse(undefined); + checkErrors(z.number().gte(2), 1); + z.number().gte(2).optional().parse(undefined); + checkErrors(z.boolean(), ""); + z.boolean().optional().parse(undefined); + checkErrors(z.undefined(), null); + z.undefined().optional().parse(undefined); + checkErrors(z.null(), {}); + z.null().optional().parse(undefined); + checkErrors(z.object({}), 1); + z.object({}).optional().parse(undefined); + checkErrors(z.tuple([]), 1); + z.tuple([]).optional().parse(undefined); + checkErrors(z.unknown(), 1); + z.unknown().optional().parse(undefined); +}); + +test("unwrap", () => { + const unwrapped = z.string().optional().unwrap(); + expect(unwrapped).toBeInstanceOf(z.ZodString); +}); diff --git a/node_modules/zod/src/v3/tests/parseUtil.test.ts b/node_modules/zod/src/v3/tests/parseUtil.test.ts new file mode 100644 index 0000000..8882d4c --- /dev/null +++ b/node_modules/zod/src/v3/tests/parseUtil.test.ts @@ -0,0 +1,23 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import { type SyncParseReturnType, isAborted, isDirty, isValid } from "../helpers/parseUtil.js"; + +test("parseUtil isInvalid should use structural typing", () => { + // Test for issue #556: https://github.com/colinhacks/zod/issues/556 + const aborted: SyncParseReturnType = { status: "aborted" }; + const dirty: SyncParseReturnType = { status: "dirty", value: "whatever" }; + const valid: SyncParseReturnType = { status: "valid", value: "whatever" }; + + expect(isAborted(aborted)).toBe(true); + expect(isAborted(dirty)).toBe(false); + expect(isAborted(valid)).toBe(false); + + expect(isDirty(aborted)).toBe(false); + expect(isDirty(dirty)).toBe(true); + expect(isDirty(valid)).toBe(false); + + expect(isValid(aborted)).toBe(false); + expect(isValid(dirty)).toBe(false); + expect(isValid(valid)).toBe(true); +}); diff --git a/node_modules/zod/src/v3/tests/parser.test.ts b/node_modules/zod/src/v3/tests/parser.test.ts new file mode 100644 index 0000000..6e685f9 --- /dev/null +++ b/node_modules/zod/src/v3/tests/parser.test.ts @@ -0,0 +1,41 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; + +test("parse strict object with unknown keys", () => { + expect(() => + z + .object({ name: z.string() }) + .strict() + .parse({ name: "bill", unknownKey: 12 } as any) + ).toThrow(); +}); + +test("parse nonstrict object with unknown keys", () => { + z.object({ name: z.string() }).nonstrict().parse({ name: "bill", unknownKey: 12 }); +}); + +test("invalid left side of intersection", () => { + expect(() => z.intersection(z.string(), z.number()).parse(12 as any)).toThrow(); +}); + +test("invalid right side of intersection", () => { + expect(() => z.intersection(z.string(), z.number()).parse("12" as any)).toThrow(); +}); + +test("parsing non-array in tuple schema", () => { + expect(() => z.tuple([]).parse("12" as any)).toThrow(); +}); + +test("incorrect num elements in tuple", () => { + expect(() => z.tuple([]).parse(["asdf"] as any)).toThrow(); +}); + +test("invalid enum value", () => { + expect(() => z.enum(["Blue"]).parse("Red" as any)).toThrow(); +}); + +test("parsing unknown", () => { + z.string().parse("Red" as unknown); +}); diff --git a/node_modules/zod/src/v3/tests/partials.test.ts b/node_modules/zod/src/v3/tests/partials.test.ts new file mode 100644 index 0000000..a2fb6ed --- /dev/null +++ b/node_modules/zod/src/v3/tests/partials.test.ts @@ -0,0 +1,243 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { ZodNullable, ZodOptional } from "zod/v3"; +import { util } from "../helpers/util.js"; + +const nested = z.object({ + name: z.string(), + age: z.number(), + outer: z.object({ + inner: z.string(), + }), + array: z.array(z.object({ asdf: z.string() })), +}); + +test("shallow inference", () => { + const shallow = nested.partial(); + type shallow = z.infer; + type correct = { + name?: string | undefined; + age?: number | undefined; + outer?: { inner: string } | undefined; + array?: { asdf: string }[]; + }; + util.assertEqual(true); +}); + +test("shallow partial parse", () => { + const shallow = nested.partial(); + shallow.parse({}); + shallow.parse({ + name: "asdf", + age: 23143, + }); +}); + +test("deep partial inference", () => { + const deep = nested.deepPartial(); + const asdf = deep.shape.array.unwrap().element.shape.asdf.unwrap(); + asdf.parse("asdf"); + type deep = z.infer; + type correct = { + array?: { asdf?: string }[]; + name?: string | undefined; + age?: number | undefined; + outer?: { inner?: string | undefined } | undefined; + }; + + util.assertEqual(true); +}); + +test("deep partial parse", () => { + const deep = nested.deepPartial(); + + expect(deep.shape.name instanceof z.ZodOptional).toBe(true); + expect(deep.shape.outer instanceof z.ZodOptional).toBe(true); + expect(deep.shape.outer._def.innerType instanceof z.ZodObject).toBe(true); + expect(deep.shape.outer._def.innerType.shape.inner instanceof z.ZodOptional).toBe(true); + expect(deep.shape.outer._def.innerType.shape.inner._def.innerType instanceof z.ZodString).toBe(true); +}); + +test("deep partial runtime tests", () => { + const deep = nested.deepPartial(); + deep.parse({}); + deep.parse({ + outer: {}, + }); + deep.parse({ + name: "asdf", + age: 23143, + outer: { + inner: "adsf", + }, + }); +}); + +test("deep partial optional/nullable", () => { + const schema = z + .object({ + name: z.string().optional(), + age: z.number().nullable(), + }) + .deepPartial(); + + expect(schema.shape.name.unwrap()).toBeInstanceOf(ZodOptional); + expect(schema.shape.age.unwrap()).toBeInstanceOf(ZodNullable); +}); + +test("deep partial tuple", () => { + const schema = z + .object({ + tuple: z.tuple([ + z.object({ + name: z.string().optional(), + age: z.number().nullable(), + }), + ]), + }) + .deepPartial(); + + expect(schema.shape.tuple.unwrap().items[0].shape.name).toBeInstanceOf(ZodOptional); +}); + +test("deep partial inference", () => { + const mySchema = z.object({ + name: z.string(), + array: z.array(z.object({ asdf: z.string() })), + tuple: z.tuple([z.object({ value: z.string() })]), + }); + + const partialed = mySchema.deepPartial(); + type partialed = z.infer; + type expected = { + name?: string | undefined; + array?: + | { + asdf?: string | undefined; + }[] + | undefined; + tuple?: [{ value?: string }] | undefined; + }; + util.assertEqual(true); +}); + +test("required", () => { + const object = z.object({ + name: z.string(), + age: z.number().optional(), + field: z.string().optional().default("asdf"), + nullableField: z.number().nullable(), + nullishField: z.string().nullish(), + }); + + const requiredObject = object.required(); + expect(requiredObject.shape.name).toBeInstanceOf(z.ZodString); + expect(requiredObject.shape.age).toBeInstanceOf(z.ZodNumber); + expect(requiredObject.shape.field).toBeInstanceOf(z.ZodDefault); + expect(requiredObject.shape.nullableField).toBeInstanceOf(z.ZodNullable); + expect(requiredObject.shape.nullishField).toBeInstanceOf(z.ZodNullable); +}); + +test("required inference", () => { + const object = z.object({ + name: z.string(), + age: z.number().optional(), + field: z.string().optional().default("asdf"), + nullableField: z.number().nullable(), + nullishField: z.string().nullish(), + }); + + const requiredObject = object.required(); + + type required = z.infer; + type expected = { + name: string; + age: number; + field: string; + nullableField: number | null; + nullishField: string | null; + }; + util.assertEqual(true); +}); + +test("required with mask", () => { + const object = z.object({ + name: z.string(), + age: z.number().optional(), + field: z.string().optional().default("asdf"), + country: z.string().optional(), + }); + + const requiredObject = object.required({ age: true }); + expect(requiredObject.shape.name).toBeInstanceOf(z.ZodString); + expect(requiredObject.shape.age).toBeInstanceOf(z.ZodNumber); + expect(requiredObject.shape.field).toBeInstanceOf(z.ZodDefault); + expect(requiredObject.shape.country).toBeInstanceOf(z.ZodOptional); +}); + +test("required with mask -- ignore falsy values", () => { + const object = z.object({ + name: z.string(), + age: z.number().optional(), + field: z.string().optional().default("asdf"), + country: z.string().optional(), + }); + + // @ts-expect-error + const requiredObject = object.required({ age: true, country: false }); + expect(requiredObject.shape.name).toBeInstanceOf(z.ZodString); + expect(requiredObject.shape.age).toBeInstanceOf(z.ZodNumber); + expect(requiredObject.shape.field).toBeInstanceOf(z.ZodDefault); + expect(requiredObject.shape.country).toBeInstanceOf(z.ZodOptional); +}); + +test("partial with mask", async () => { + const object = z.object({ + name: z.string(), + age: z.number().optional(), + field: z.string().optional().default("asdf"), + country: z.string(), + }); + + const masked = object.partial({ age: true, field: true, name: true }).strict(); + + expect(masked.shape.name).toBeInstanceOf(z.ZodOptional); + expect(masked.shape.age).toBeInstanceOf(z.ZodOptional); + expect(masked.shape.field).toBeInstanceOf(z.ZodOptional); + expect(masked.shape.country).toBeInstanceOf(z.ZodString); + + masked.parse({ country: "US" }); + await masked.parseAsync({ country: "US" }); +}); + +test("partial with mask -- ignore falsy values", async () => { + const object = z.object({ + name: z.string(), + age: z.number().optional(), + field: z.string().optional().default("asdf"), + country: z.string(), + }); + + // @ts-expect-error + const masked = object.partial({ name: true, country: false }).strict(); + + expect(masked.shape.name).toBeInstanceOf(z.ZodOptional); + expect(masked.shape.age).toBeInstanceOf(z.ZodOptional); + expect(masked.shape.field).toBeInstanceOf(z.ZodDefault); + expect(masked.shape.country).toBeInstanceOf(z.ZodString); + + masked.parse({ country: "US" }); + await masked.parseAsync({ country: "US" }); +}); + +test("deeppartial array", () => { + const schema = z.object({ array: z.string().array().min(42) }).deepPartial(); + + // works as expected + schema.parse({}); + + // should be false, but is true + expect(schema.safeParse({ array: [] }).success).toBe(false); +}); diff --git a/node_modules/zod/src/v3/tests/pickomit.test.ts b/node_modules/zod/src/v3/tests/pickomit.test.ts new file mode 100644 index 0000000..b1056e5 --- /dev/null +++ b/node_modules/zod/src/v3/tests/pickomit.test.ts @@ -0,0 +1,111 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { util } from "../helpers/util.js"; + +const fish = z.object({ + name: z.string(), + age: z.number(), + nested: z.object({}), +}); + +test("pick type inference", () => { + const nameonlyFish = fish.pick({ name: true }); + type nameonlyFish = z.infer; + util.assertEqual(true); +}); + +test("pick parse - success", () => { + const nameonlyFish = fish.pick({ name: true }); + nameonlyFish.parse({ name: "bob" }); + + // @ts-expect-error checking runtime picks `name` only. + const anotherNameonlyFish = fish.pick({ name: true, age: false }); + anotherNameonlyFish.parse({ name: "bob" }); +}); + +test("pick parse - fail", () => { + fish.pick({ name: true }).parse({ name: "12" } as any); + fish.pick({ name: true }).parse({ name: "bob", age: 12 } as any); + fish.pick({ age: true }).parse({ age: 12 } as any); + + const nameonlyFish = fish.pick({ name: true }).strict(); + const bad1 = () => nameonlyFish.parse({ name: 12 } as any); + const bad2 = () => nameonlyFish.parse({ name: "bob", age: 12 } as any); + const bad3 = () => nameonlyFish.parse({ age: 12 } as any); + + // @ts-expect-error checking runtime picks `name` only. + const anotherNameonlyFish = fish.pick({ name: true, age: false }).strict(); + const bad4 = () => anotherNameonlyFish.parse({ name: "bob", age: 12 } as any); + + expect(bad1).toThrow(); + expect(bad2).toThrow(); + expect(bad3).toThrow(); + expect(bad4).toThrow(); +}); + +test("omit type inference", () => { + const nonameFish = fish.omit({ name: true }); + type nonameFish = z.infer; + util.assertEqual(true); +}); + +test("omit parse - success", () => { + const nonameFish = fish.omit({ name: true }); + nonameFish.parse({ age: 12, nested: {} }); + + // @ts-expect-error checking runtime omits `name` only. + const anotherNonameFish = fish.omit({ name: true, age: false }); + anotherNonameFish.parse({ age: 12, nested: {} }); +}); + +test("omit parse - fail", () => { + const nonameFish = fish.omit({ name: true }); + const bad1 = () => nonameFish.parse({ name: 12 } as any); + const bad2 = () => nonameFish.parse({ age: 12 } as any); + const bad3 = () => nonameFish.parse({} as any); + + // @ts-expect-error checking runtime omits `name` only. + const anotherNonameFish = fish.omit({ name: true, age: false }); + const bad4 = () => anotherNonameFish.parse({ nested: {} } as any); + + expect(bad1).toThrow(); + expect(bad2).toThrow(); + expect(bad3).toThrow(); + expect(bad4).toThrow(); +}); + +test("nonstrict inference", () => { + const laxfish = fish.pick({ name: true }).catchall(z.any()); + type laxfish = z.infer; + util.assertEqual(true); +}); + +test("nonstrict parsing - pass", () => { + const laxfish = fish.passthrough().pick({ name: true }); + laxfish.parse({ name: "asdf", whatever: "asdf" }); + laxfish.parse({ name: "asdf", age: 12, nested: {} }); +}); + +test("nonstrict parsing - fail", () => { + const laxfish = fish.passthrough().pick({ name: true }); + const bad = () => laxfish.parse({ whatever: "asdf" } as any); + expect(bad).toThrow(); +}); + +test("pick/omit/required/partial - do not allow unknown keys", () => { + const schema = z.object({ + name: z.string(), + age: z.number(), + }); + + // @ts-expect-error + schema.pick({ $unknown: true }); + // @ts-expect-error + schema.omit({ $unknown: true }); + // @ts-expect-error + schema.required({ $unknown: true }); + // @ts-expect-error + schema.partial({ $unknown: true }); +}); diff --git a/node_modules/zod/src/v3/tests/pipeline.test.ts b/node_modules/zod/src/v3/tests/pipeline.test.ts new file mode 100644 index 0000000..cc94fc5 --- /dev/null +++ b/node_modules/zod/src/v3/tests/pipeline.test.ts @@ -0,0 +1,29 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; + +test("string to number pipeline", () => { + const schema = z.string().transform(Number).pipe(z.number()); + expect(schema.parse("1234")).toEqual(1234); +}); + +test("string to number pipeline async", async () => { + const schema = z + .string() + .transform(async (val) => Number(val)) + .pipe(z.number()); + expect(await schema.parseAsync("1234")).toEqual(1234); +}); + +test("break if dirty", () => { + const schema = z + .string() + .refine((c) => c === "1234") + .transform(async (val) => Number(val)) + .pipe(z.number().refine((v) => v < 100)); + const r1: any = schema.safeParse("12345"); + expect(r1.error.issues.length).toBe(1); + const r2: any = schema.safeParse("3"); + expect(r2.error.issues.length).toBe(1); +}); diff --git a/node_modules/zod/src/v3/tests/preprocess.test.ts b/node_modules/zod/src/v3/tests/preprocess.test.ts new file mode 100644 index 0000000..7e1b5a1 --- /dev/null +++ b/node_modules/zod/src/v3/tests/preprocess.test.ts @@ -0,0 +1,186 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { util } from "../helpers/util.js"; + +test("preprocess", () => { + const schema = z.preprocess((data) => [data], z.string().array()); + + const value = schema.parse("asdf"); + expect(value).toEqual(["asdf"]); + util.assertEqual<(typeof schema)["_input"], unknown>(true); +}); + +test("async preprocess", async () => { + const schema = z.preprocess(async (data) => [data], z.string().array()); + + const value = await schema.parseAsync("asdf"); + expect(value).toEqual(["asdf"]); +}); + +test("preprocess ctx.addIssue with parse", () => { + expect(() => { + z.preprocess((data, ctx) => { + ctx.addIssue({ + code: "custom", + message: `${data} is not one of our allowed strings`, + }); + return data; + }, z.string()).parse("asdf"); + }).toThrow( + JSON.stringify( + [ + { + code: "custom", + message: "asdf is not one of our allowed strings", + path: [], + }, + ], + null, + 2 + ) + ); +}); + +test("preprocess ctx.addIssue non-fatal by default", () => { + try { + z.preprocess((data, ctx) => { + ctx.addIssue({ + code: "custom", + message: `custom error`, + }); + return data; + }, z.string()).parse(1234); + } catch (err) { + z.ZodError.assert(err); + expect(err.issues.length).toEqual(2); + } +}); + +test("preprocess ctx.addIssue fatal true", () => { + try { + z.preprocess((data, ctx) => { + ctx.addIssue({ + code: "custom", + message: `custom error`, + fatal: true, + }); + return data; + }, z.string()).parse(1234); + } catch (err) { + z.ZodError.assert(err); + expect(err.issues.length).toEqual(1); + } +}); + +test("async preprocess ctx.addIssue with parse", async () => { + const schema = z.preprocess(async (data, ctx) => { + ctx.addIssue({ + code: "custom", + message: `custom error`, + }); + return data; + }, z.string()); + + expect(await schema.safeParseAsync("asdf")).toMatchInlineSnapshot(` + { + "error": [ZodError: [ + { + "code": "custom", + "message": "custom error", + "path": [] + } + ]], + "success": false, + } + `); +}); + +test("preprocess ctx.addIssue with parseAsync", async () => { + const result = await z + .preprocess(async (data, ctx) => { + ctx.addIssue({ + code: "custom", + message: `${data} is not one of our allowed strings`, + }); + return data; + }, z.string()) + .safeParseAsync("asdf"); + + expect(JSON.parse(JSON.stringify(result))).toEqual({ + success: false, + error: { + issues: [ + { + code: "custom", + message: "asdf is not one of our allowed strings", + path: [], + }, + ], + name: "ZodError", + }, + }); +}); + +test("z.NEVER in preprocess", () => { + const foo = z.preprocess((val, ctx) => { + if (!val) { + ctx.addIssue({ code: z.ZodIssueCode.custom, message: "bad" }); + return z.NEVER; + } + return val; + }, z.number()); + + type foo = z.infer; + util.assertEqual(true); + const arg = foo.safeParse(undefined); + expect(arg.error!.issues).toHaveLength(2); + expect(arg.error!.issues[0].message).toEqual("bad"); +}); +test("preprocess as the second property of object", () => { + const schema = z.object({ + nonEmptyStr: z.string().min(1), + positiveNum: z.preprocess((v) => Number(v), z.number().positive()), + }); + const result = schema.safeParse({ + nonEmptyStr: "", + positiveNum: "", + }); + expect(result.success).toEqual(false); + if (!result.success) { + expect(result.error.issues.length).toEqual(2); + expect(result.error.issues[0].code).toEqual(z.ZodIssueCode.too_small); + expect(result.error.issues[1].code).toEqual(z.ZodIssueCode.too_small); + } +}); + +test("preprocess validates with sibling errors", () => { + expect(() => { + z.object({ + // Must be first + missing: z.string().refine(() => false), + preprocess: z.preprocess((data: any) => data?.trim(), z.string().regex(/ asdf/)), + }).parse({ preprocess: " asdf" }); + }).toThrow( + JSON.stringify( + [ + { + code: "invalid_type", + expected: "string", + received: "undefined", + path: ["missing"], + message: "Required", + }, + { + validation: "regex", + code: "invalid_string", + message: "Invalid", + path: ["preprocess"], + }, + ], + null, + 2 + ) + ); +}); diff --git a/node_modules/zod/src/v3/tests/primitive.test.ts b/node_modules/zod/src/v3/tests/primitive.test.ts new file mode 100644 index 0000000..48e36a2 --- /dev/null +++ b/node_modules/zod/src/v3/tests/primitive.test.ts @@ -0,0 +1,440 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { util } from "../helpers/util.js"; +import { Mocker } from "./Mocker.js"; + +const literalStringSchema = z.literal("asdf"); +const literalNumberSchema = z.literal(12); +const literalBooleanSchema = z.literal(true); +const literalBigIntSchema = z.literal(BigInt(42)); +const MySymbol = Symbol("stuff"); +const literalSymbolSchema = z.literal(MySymbol); +const stringSchema = z.string(); +const numberSchema = z.number(); +const bigintSchema = z.bigint(); +const booleanSchema = z.boolean(); +const dateSchema = z.date(); +const symbolSchema = z.symbol(); + +const nullSchema = z.null(); +const undefinedSchema = z.undefined(); +const stringSchemaOptional = z.string().optional(); +const stringSchemaNullable = z.string().nullable(); +const numberSchemaOptional = z.number().optional(); +const numberSchemaNullable = z.number().nullable(); +const bigintSchemaOptional = z.bigint().optional(); +const bigintSchemaNullable = z.bigint().nullable(); +const booleanSchemaOptional = z.boolean().optional(); +const booleanSchemaNullable = z.boolean().nullable(); +const dateSchemaOptional = z.date().optional(); +const dateSchemaNullable = z.date().nullable(); +const symbolSchemaOptional = z.symbol().optional(); +const symbolSchemaNullable = z.symbol().nullable(); + +const val = new Mocker(); + +test("literal string correct", () => { + expect(literalStringSchema.parse("asdf")).toBe("asdf"); +}); + +test("literal string incorrect", () => { + const f = () => literalStringSchema.parse("not_asdf"); + expect(f).toThrow(); +}); + +test("literal string number", () => { + const f = () => literalStringSchema.parse(123); + expect(f).toThrow(); +}); + +test("literal string boolean", () => { + const f = () => literalStringSchema.parse(true); + expect(f).toThrow(); +}); + +test("literal string boolean", () => { + const f = () => literalStringSchema.parse(true); + expect(f).toThrow(); +}); + +test("literal string object", () => { + const f = () => literalStringSchema.parse({}); + expect(f).toThrow(); +}); + +test("literal number correct", () => { + expect(literalNumberSchema.parse(12)).toBe(12); +}); + +test("literal number incorrect", () => { + const f = () => literalNumberSchema.parse(13); + expect(f).toThrow(); +}); + +test("literal number number", () => { + const f = () => literalNumberSchema.parse(val.string); + expect(f).toThrow(); +}); + +test("literal number boolean", () => { + const f = () => literalNumberSchema.parse(val.boolean); + expect(f).toThrow(); +}); + +test("literal number object", () => { + const f = () => literalStringSchema.parse({}); + expect(f).toThrow(); +}); + +test("literal boolean correct", () => { + expect(literalBooleanSchema.parse(true)).toBe(true); +}); + +test("literal boolean incorrect", () => { + const f = () => literalBooleanSchema.parse(false); + expect(f).toThrow(); +}); + +test("literal boolean number", () => { + const f = () => literalBooleanSchema.parse("asdf"); + expect(f).toThrow(); +}); + +test("literal boolean boolean", () => { + const f = () => literalBooleanSchema.parse(123); + expect(f).toThrow(); +}); + +test("literal boolean object", () => { + const f = () => literalBooleanSchema.parse({}); + expect(f).toThrow(); +}); + +test("literal bigint correct", () => { + expect(literalBigIntSchema.parse(BigInt(42))).toBe(BigInt(42)); +}); + +test("literal bigint incorrect", () => { + const f = () => literalBigIntSchema.parse(BigInt(43)); + expect(f).toThrow(); +}); + +test("literal bigint number", () => { + const f = () => literalBigIntSchema.parse("asdf"); + expect(f).toThrow(); +}); + +test("literal bigint boolean", () => { + const f = () => literalBigIntSchema.parse(123); + expect(f).toThrow(); +}); + +test("literal bigint object", () => { + const f = () => literalBigIntSchema.parse({}); + expect(f).toThrow(); +}); + +test("literal symbol", () => { + util.assertEqual, typeof MySymbol>(true); + literalSymbolSchema.parse(MySymbol); + expect(() => literalSymbolSchema.parse(Symbol("asdf"))).toThrow(); +}); + +test("parse stringSchema string", () => { + stringSchema.parse(val.string); +}); + +test("parse stringSchema number", () => { + const f = () => stringSchema.parse(val.number); + expect(f).toThrow(); +}); + +test("parse stringSchema boolean", () => { + const f = () => stringSchema.parse(val.boolean); + expect(f).toThrow(); +}); + +test("parse stringSchema undefined", () => { + const f = () => stringSchema.parse(val.undefined); + expect(f).toThrow(); +}); + +test("parse stringSchema null", () => { + const f = () => stringSchema.parse(val.null); + expect(f).toThrow(); +}); + +test("parse numberSchema string", () => { + const f = () => numberSchema.parse(val.string); + expect(f).toThrow(); +}); + +test("parse numberSchema number", () => { + numberSchema.parse(val.number); +}); + +test("parse numberSchema bigint", () => { + const f = () => numberSchema.parse(val.bigint); + expect(f).toThrow(); +}); + +test("parse numberSchema boolean", () => { + const f = () => numberSchema.parse(val.boolean); + expect(f).toThrow(); +}); + +test("parse numberSchema undefined", () => { + const f = () => numberSchema.parse(val.undefined); + expect(f).toThrow(); +}); + +test("parse numberSchema null", () => { + const f = () => numberSchema.parse(val.null); + expect(f).toThrow(); +}); + +test("parse bigintSchema string", () => { + const f = () => bigintSchema.parse(val.string); + expect(f).toThrow(); +}); + +test("parse bigintSchema number", () => { + const f = () => bigintSchema.parse(val.number); + expect(f).toThrow(); +}); + +test("parse bigintSchema bigint", () => { + bigintSchema.parse(val.bigint); +}); + +test("parse bigintSchema boolean", () => { + const f = () => bigintSchema.parse(val.boolean); + expect(f).toThrow(); +}); + +test("parse bigintSchema undefined", () => { + const f = () => bigintSchema.parse(val.undefined); + expect(f).toThrow(); +}); + +test("parse bigintSchema null", () => { + const f = () => bigintSchema.parse(val.null); + expect(f).toThrow(); +}); + +test("parse booleanSchema string", () => { + const f = () => booleanSchema.parse(val.string); + expect(f).toThrow(); +}); + +test("parse booleanSchema number", () => { + const f = () => booleanSchema.parse(val.number); + expect(f).toThrow(); +}); + +test("parse booleanSchema boolean", () => { + booleanSchema.parse(val.boolean); +}); + +test("parse booleanSchema undefined", () => { + const f = () => booleanSchema.parse(val.undefined); + expect(f).toThrow(); +}); + +test("parse booleanSchema null", () => { + const f = () => booleanSchema.parse(val.null); + expect(f).toThrow(); +}); + +// ============== + +test("parse dateSchema string", () => { + const f = () => dateSchema.parse(val.string); + expect(f).toThrow(); +}); + +test("parse dateSchema number", () => { + const f = () => dateSchema.parse(val.number); + expect(f).toThrow(); +}); + +test("parse dateSchema boolean", () => { + const f = () => dateSchema.parse(val.boolean); + expect(f).toThrow(); +}); + +test("parse dateSchema date", () => { + dateSchema.parse(val.date); +}); + +test("parse dateSchema undefined", () => { + const f = () => dateSchema.parse(val.undefined); + expect(f).toThrow(); +}); + +test("parse dateSchema null", () => { + const f = () => dateSchema.parse(val.null); + expect(f).toThrow(); +}); + +test("parse dateSchema invalid date", async () => { + try { + await dateSchema.parseAsync(new Date("invalid")); + } catch (err) { + expect((err as z.ZodError).issues[0].code).toEqual(z.ZodIssueCode.invalid_date); + } +}); +// ============== + +test("parse symbolSchema string", () => { + const f = () => symbolSchema.parse(val.string); + expect(f).toThrow(); +}); + +test("parse symbolSchema number", () => { + const f = () => symbolSchema.parse(val.number); + expect(f).toThrow(); +}); + +test("parse symbolSchema boolean", () => { + const f = () => symbolSchema.parse(val.boolean); + expect(f).toThrow(); +}); + +test("parse symbolSchema date", () => { + const f = () => symbolSchema.parse(val.date); + expect(f).toThrow(); +}); + +test("parse symbolSchema symbol", () => { + symbolSchema.parse(val.symbol); +}); + +test("parse symbolSchema undefined", () => { + const f = () => symbolSchema.parse(val.undefined); + expect(f).toThrow(); +}); + +test("parse symbolSchema null", () => { + const f = () => symbolSchema.parse(val.null); + expect(f).toThrow(); +}); + +// ============== + +test("parse undefinedSchema string", () => { + const f = () => undefinedSchema.parse(val.string); + expect(f).toThrow(); +}); + +test("parse undefinedSchema number", () => { + const f = () => undefinedSchema.parse(val.number); + expect(f).toThrow(); +}); + +test("parse undefinedSchema boolean", () => { + const f = () => undefinedSchema.parse(val.boolean); + expect(f).toThrow(); +}); + +test("parse undefinedSchema undefined", () => { + undefinedSchema.parse(val.undefined); +}); + +test("parse undefinedSchema null", () => { + const f = () => undefinedSchema.parse(val.null); + expect(f).toThrow(); +}); + +test("parse nullSchema string", () => { + const f = () => nullSchema.parse(val.string); + expect(f).toThrow(); +}); + +test("parse nullSchema number", () => { + const f = () => nullSchema.parse(val.number); + expect(f).toThrow(); +}); + +test("parse nullSchema boolean", () => { + const f = () => nullSchema.parse(val.boolean); + expect(f).toThrow(); +}); + +test("parse nullSchema undefined", () => { + const f = () => nullSchema.parse(val.undefined); + expect(f).toThrow(); +}); + +test("parse nullSchema null", () => { + nullSchema.parse(val.null); +}); + +test("primitive inference", () => { + util.assertEqual, "asdf">(true); + util.assertEqual, 12>(true); + util.assertEqual, true>(true); + util.assertEqual, bigint>(true); + util.assertEqual, string>(true); + util.assertEqual, number>(true); + util.assertEqual, bigint>(true); + util.assertEqual, boolean>(true); + util.assertEqual, Date>(true); + util.assertEqual, symbol>(true); + + util.assertEqual, null>(true); + util.assertEqual, undefined>(true); + util.assertEqual, string | undefined>(true); + util.assertEqual, string | null>(true); + util.assertEqual, number | undefined>(true); + util.assertEqual, number | null>(true); + util.assertEqual, bigint | undefined>(true); + util.assertEqual, bigint | null>(true); + util.assertEqual, boolean | undefined>(true); + util.assertEqual, boolean | null>(true); + util.assertEqual, Date | undefined>(true); + util.assertEqual, Date | null>(true); + util.assertEqual, symbol | undefined>(true); + util.assertEqual, symbol | null>(true); + + // [ + // literalStringSchemaTest, + // literalNumberSchemaTest, + // literalBooleanSchemaTest, + // literalBigIntSchemaTest, + // stringSchemaTest, + // numberSchemaTest, + // bigintSchemaTest, + // booleanSchemaTest, + // dateSchemaTest, + // symbolSchemaTest, + + // nullSchemaTest, + // undefinedSchemaTest, + // stringSchemaOptionalTest, + // stringSchemaNullableTest, + // numberSchemaOptionalTest, + // numberSchemaNullableTest, + // bigintSchemaOptionalTest, + // bigintSchemaNullableTest, + // booleanSchemaOptionalTest, + // booleanSchemaNullableTest, + // dateSchemaOptionalTest, + // dateSchemaNullableTest, + // symbolSchemaOptionalTest, + // symbolSchemaNullableTest, + + // ]; +}); + +test("get literal value", () => { + expect(literalStringSchema.value).toEqual("asdf"); +}); + +test("optional convenience method", () => { + z.ostring().parse(undefined); + z.onumber().parse(undefined); + z.oboolean().parse(undefined); +}); diff --git a/node_modules/zod/src/v3/tests/promise.test.ts b/node_modules/zod/src/v3/tests/promise.test.ts new file mode 100644 index 0000000..23b6de1 --- /dev/null +++ b/node_modules/zod/src/v3/tests/promise.test.ts @@ -0,0 +1,90 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { util } from "../helpers/util.js"; + +const promSchema = z.promise( + z.object({ + name: z.string(), + age: z.number(), + }) +); + +test("promise inference", () => { + type promSchemaType = z.infer; + util.assertEqual>(true); +}); + +test("promise parsing success", async () => { + const pr = promSchema.parse(Promise.resolve({ name: "Bobby", age: 10 })); + expect(pr).toBeInstanceOf(Promise); + const result = await pr; + expect(typeof result).toBe("object"); + expect(typeof result.age).toBe("number"); + expect(typeof result.name).toBe("string"); +}); + +test("promise parsing success 2", () => { + const fakePromise = { + then() { + return this; + }, + catch() { + return this; + }, + }; + promSchema.parse(fakePromise); +}); + +test("promise parsing fail", async () => { + const bad = promSchema.parse(Promise.resolve({ name: "Bobby", age: "10" })); + // return await expect(bad).resolves.toBe({ name: 'Bobby', age: '10' }); + return await expect(bad).rejects.toBeInstanceOf(z.ZodError); + // done(); +}); + +test("promise parsing fail 2", async () => { + const failPromise = promSchema.parse(Promise.resolve({ name: "Bobby", age: "10" })); + await expect(failPromise).rejects.toBeInstanceOf(z.ZodError); + // done();/z +}); + +test("promise parsing fail", () => { + const bad = () => promSchema.parse({ then: () => {}, catch: {} }); + expect(bad).toThrow(); +}); + +// test('sync promise parsing', () => { +// expect(() => z.promise(z.string()).parse(Promise.resolve('asfd'))).toThrow(); +// }); + +const asyncFunction = z.function(z.tuple([]), promSchema); + +test("async function pass", async () => { + const validatedFunction = asyncFunction.implement(async () => { + return { name: "jimmy", age: 14 }; + }); + await expect(validatedFunction()).resolves.toEqual({ + name: "jimmy", + age: 14, + }); +}); + +test("async function fail", async () => { + const validatedFunction = asyncFunction.implement(() => { + return Promise.resolve("asdf" as any); + }); + await expect(validatedFunction()).rejects.toBeInstanceOf(z.ZodError); +}); + +test("async promise parsing", () => { + const res = z.promise(z.number()).parseAsync(Promise.resolve(12)); + expect(res).toBeInstanceOf(Promise); +}); + +test("resolves", () => { + const foo = z.literal("foo"); + const res = z.promise(foo); + expect(res.unwrap()).toEqual(foo); +}); diff --git a/node_modules/zod/src/v3/tests/readonly.test.ts b/node_modules/zod/src/v3/tests/readonly.test.ts new file mode 100644 index 0000000..5078955 --- /dev/null +++ b/node_modules/zod/src/v3/tests/readonly.test.ts @@ -0,0 +1,194 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { util } from "../helpers/util.js"; + +enum testEnum { + A = 0, + B = 1, +} + +const schemas = [ + z.string().readonly(), + z.number().readonly(), + z.nan().readonly(), + z.bigint().readonly(), + z.boolean().readonly(), + z.date().readonly(), + z.undefined().readonly(), + z.null().readonly(), + z.any().readonly(), + z.unknown().readonly(), + z.void().readonly(), + z.function().args(z.string(), z.number()).readonly(), + + z.array(z.string()).readonly(), + z.tuple([z.string(), z.number()]).readonly(), + z.map(z.string(), z.date()).readonly(), + z.set(z.promise(z.string())).readonly(), + z.record(z.string()).readonly(), + z.record(z.string(), z.number()).readonly(), + z.object({ a: z.string(), 1: z.number() }).readonly(), + z.nativeEnum(testEnum).readonly(), + z.promise(z.string()).readonly(), +] as const; + +test("flat inference", () => { + util.assertEqual, string>(true); + util.assertEqual, number>(true); + util.assertEqual, number>(true); + util.assertEqual, bigint>(true); + util.assertEqual, boolean>(true); + util.assertEqual, Date>(true); + util.assertEqual, undefined>(true); + util.assertEqual, null>(true); + util.assertEqual, any>(true); + util.assertEqual, Readonly>(true); + util.assertEqual, void>(true); + util.assertEqual, (args_0: string, args_1: number, ...args_2: unknown[]) => unknown>( + true + ); + util.assertEqual, readonly string[]>(true); + + util.assertEqual, readonly [string, number]>(true); + util.assertEqual, ReadonlyMap>(true); + util.assertEqual, ReadonlySet>>(true); + util.assertEqual, Readonly>>(true); + util.assertEqual, Readonly>>(true); + util.assertEqual, { readonly a: string; readonly 1: number }>(true); + util.assertEqual, Readonly>(true); + util.assertEqual, Promise>(true); +}); + +// test("deep inference", () => { +// util.assertEqual, string>(true); +// util.assertEqual, number>(true); +// util.assertEqual, number>(true); +// util.assertEqual, bigint>(true); +// util.assertEqual, boolean>(true); +// util.assertEqual, Date>(true); +// util.assertEqual, undefined>(true); +// util.assertEqual, null>(true); +// util.assertEqual, any>(true); +// util.assertEqual< +// z.infer<(typeof deepReadonlySchemas_0)[9]>, +// Readonly +// >(true); +// util.assertEqual, void>(true); +// util.assertEqual< +// z.infer<(typeof deepReadonlySchemas_0)[11]>, +// (args_0: string, args_1: number, ...args_2: unknown[]) => unknown +// >(true); +// util.assertEqual< +// z.infer<(typeof deepReadonlySchemas_0)[12]>, +// readonly string[] +// >(true); +// util.assertEqual< +// z.infer<(typeof deepReadonlySchemas_0)[13]>, +// readonly [string, number] +// >(true); +// util.assertEqual< +// z.infer<(typeof deepReadonlySchemas_0)[14]>, +// ReadonlyMap +// >(true); +// util.assertEqual< +// z.infer<(typeof deepReadonlySchemas_0)[15]>, +// ReadonlySet> +// >(true); +// util.assertEqual< +// z.infer<(typeof deepReadonlySchemas_0)[16]>, +// Readonly> +// >(true); +// util.assertEqual< +// z.infer<(typeof deepReadonlySchemas_0)[17]>, +// Readonly> +// >(true); +// util.assertEqual< +// z.infer<(typeof deepReadonlySchemas_0)[18]>, +// { readonly a: string; readonly 1: number } +// >(true); +// util.assertEqual< +// z.infer<(typeof deepReadonlySchemas_0)[19]>, +// Readonly +// >(true); +// util.assertEqual< +// z.infer<(typeof deepReadonlySchemas_0)[20]>, +// Promise +// >(true); + +// util.assertEqual< +// z.infer, +// ReadonlyMap< +// ReadonlySet, +// { +// readonly a: { +// readonly [x: string]: readonly any[]; +// }; +// readonly b: { +// readonly c: { +// readonly d: { +// readonly e: { +// readonly f: { +// readonly g?: {}; +// }; +// }; +// }; +// }; +// }; +// } +// > +// >(true); +// }); + +test("object freezing", () => { + expect(Object.isFrozen(z.array(z.string()).readonly().parse(["a"]))).toBe(true); + expect(Object.isFrozen(z.tuple([z.string(), z.number()]).readonly().parse(["a", 1]))).toBe(true); + expect( + Object.isFrozen( + z + .map(z.string(), z.date()) + .readonly() + .parse(new Map([["a", new Date()]])) + ) + ).toBe(true); + expect( + Object.isFrozen( + z + .set(z.promise(z.string())) + .readonly() + .parse(new Set([Promise.resolve("a")])) + ) + ).toBe(true); + expect(Object.isFrozen(z.record(z.string()).readonly().parse({ a: "b" }))).toBe(true); + expect(Object.isFrozen(z.record(z.string(), z.number()).readonly().parse({ a: 1 }))).toBe(true); + expect(Object.isFrozen(z.object({ a: z.string(), 1: z.number() }).readonly().parse({ a: "b", 1: 2 }))).toBe(true); + expect(Object.isFrozen(z.promise(z.string()).readonly().parse(Promise.resolve("a")))).toBe(true); +}); + +test("async object freezing", async () => { + expect(Object.isFrozen(await z.array(z.string()).readonly().parseAsync(["a"]))).toBe(true); + expect(Object.isFrozen(await z.tuple([z.string(), z.number()]).readonly().parseAsync(["a", 1]))).toBe(true); + expect( + Object.isFrozen( + await z + .map(z.string(), z.date()) + .readonly() + .parseAsync(new Map([["a", new Date()]])) + ) + ).toBe(true); + expect( + Object.isFrozen( + await z + .set(z.promise(z.string())) + .readonly() + .parseAsync(new Set([Promise.resolve("a")])) + ) + ).toBe(true); + expect(Object.isFrozen(await z.record(z.string()).readonly().parseAsync({ a: "b" }))).toBe(true); + expect(Object.isFrozen(await z.record(z.string(), z.number()).readonly().parseAsync({ a: 1 }))).toBe(true); + expect( + Object.isFrozen(await z.object({ a: z.string(), 1: z.number() }).readonly().parseAsync({ a: "b", 1: 2 })) + ).toBe(true); + expect(Object.isFrozen(await z.promise(z.string()).readonly().parseAsync(Promise.resolve("a")))).toBe(true); +}); diff --git a/node_modules/zod/src/v3/tests/record.test.ts b/node_modules/zod/src/v3/tests/record.test.ts new file mode 100644 index 0000000..83c363f --- /dev/null +++ b/node_modules/zod/src/v3/tests/record.test.ts @@ -0,0 +1,171 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { util } from "../helpers/util.js"; + +const booleanRecord = z.record(z.boolean()); +type booleanRecord = z.infer; + +const recordWithEnumKeys = z.record(z.enum(["Tuna", "Salmon"]), z.string()); +type recordWithEnumKeys = z.infer; + +const recordWithLiteralKeys = z.record(z.union([z.literal("Tuna"), z.literal("Salmon")]), z.string()); +type recordWithLiteralKeys = z.infer; + +test("type inference", () => { + util.assertEqual>(true); + + util.assertEqual>>(true); + + util.assertEqual>>(true); +}); + +test("methods", () => { + booleanRecord.optional(); + booleanRecord.nullable(); +}); + +test("string record parse - pass", () => { + booleanRecord.parse({ + k1: true, + k2: false, + 1234: false, + }); +}); + +test("string record parse - fail", () => { + const badCheck = () => + booleanRecord.parse({ + asdf: 1234, + } as any); + expect(badCheck).toThrow(); + + expect(() => booleanRecord.parse("asdf")).toThrow(); +}); + +test("string record parse - fail", () => { + const badCheck = () => + booleanRecord.parse({ + asdf: {}, + } as any); + expect(badCheck).toThrow(); +}); + +test("string record parse - fail", () => { + const badCheck = () => + booleanRecord.parse({ + asdf: [], + } as any); + expect(badCheck).toThrow(); +}); + +test("key schema", () => { + const result1 = recordWithEnumKeys.parse({ + Tuna: "asdf", + Salmon: "asdf", + }); + expect(result1).toEqual({ + Tuna: "asdf", + Salmon: "asdf", + }); + + const result2 = recordWithLiteralKeys.parse({ + Tuna: "asdf", + Salmon: "asdf", + }); + expect(result2).toEqual({ + Tuna: "asdf", + Salmon: "asdf", + }); + + // shouldn't require us to specify all props in record + const result3 = recordWithEnumKeys.parse({ + Tuna: "abcd", + }); + expect(result3).toEqual({ + Tuna: "abcd", + }); + + // shouldn't require us to specify all props in record + const result4 = recordWithLiteralKeys.parse({ + Salmon: "abcd", + }); + expect(result4).toEqual({ + Salmon: "abcd", + }); + + expect(() => + recordWithEnumKeys.parse({ + Tuna: "asdf", + Salmon: "asdf", + Trout: "asdf", + }) + ).toThrow(); + + expect(() => + recordWithLiteralKeys.parse({ + Tuna: "asdf", + Salmon: "asdf", + + Trout: "asdf", + }) + ).toThrow(); +}); + +// test("record element", () => { +// expect(booleanRecord.element).toBeInstanceOf(z.ZodBoolean); +// }); + +test("key and value getters", () => { + const rec = z.record(z.string(), z.number()); + + rec.keySchema.parse("asdf"); + rec.valueSchema.parse(1234); + rec.element.parse(1234); +}); + +test("is not vulnerable to prototype pollution", async () => { + const rec = z.record( + z.object({ + a: z.string(), + }) + ); + + const data = JSON.parse(` + { + "__proto__": { + "a": "evil" + }, + "b": { + "a": "good" + } + } + `); + + const obj1 = rec.parse(data); + expect(obj1.a).toBeUndefined(); + + const obj2 = rec.safeParse(data); + expect(obj2.success).toBe(true); + if (obj2.success) { + expect(obj2.data.a).toBeUndefined(); + } + + const obj3 = await rec.parseAsync(data); + expect(obj3.a).toBeUndefined(); + + const obj4 = await rec.safeParseAsync(data); + expect(obj4.success).toBe(true); + if (obj4.success) { + expect(obj4.data.a).toBeUndefined(); + } +}); + +test("dont parse undefined values", () => { + const result1 = z.record(z.any()).parse({ foo: undefined }); + + expect(result1).toEqual({ + foo: undefined, + }); +}); diff --git a/node_modules/zod/src/v3/tests/recursive.test.ts b/node_modules/zod/src/v3/tests/recursive.test.ts new file mode 100644 index 0000000..f5bb108 --- /dev/null +++ b/node_modules/zod/src/v3/tests/recursive.test.ts @@ -0,0 +1,197 @@ +// @ts-ignore TS6133 +import { test } from "vitest"; + +import { z } from "zod/v3"; + +interface Category { + name: string; + subcategories: Category[]; +} + +const testCategory: Category = { + name: "I", + subcategories: [ + { + name: "A", + subcategories: [ + { + name: "1", + subcategories: [ + { + name: "a", + subcategories: [], + }, + ], + }, + ], + }, + ], +}; + +test("recursion with z.late.object", () => { + const Category: z.ZodType = z.late.object(() => ({ + name: z.string(), + subcategories: z.array(Category), + })); + Category.parse(testCategory); +}); + +test("recursion with z.lazy", () => { + const Category: z.ZodType = z.lazy(() => + z.object({ + name: z.string(), + subcategories: z.array(Category), + }) + ); + Category.parse(testCategory); +}); + +test("schema getter", () => { + z.lazy(() => z.string()).schema.parse("asdf"); +}); + +type LinkedList = null | { value: number; next: LinkedList }; + +const linkedListExample = { + value: 1, + next: { + value: 2, + next: { + value: 3, + next: { + value: 4, + next: null, + }, + }, + }, +}; + +test("recursion involving union type", () => { + const LinkedListSchema: z.ZodType = z.lazy(() => + z.union([ + z.null(), + z.object({ + value: z.number(), + next: LinkedListSchema, + }), + ]) + ); + LinkedListSchema.parse(linkedListExample); +}); + +// interface A { +// val: number; +// b: B; +// } + +// interface B { +// val: number; +// a: A; +// } + +// const A: z.ZodType = z.late.object(() => ({ +// val: z.number(), +// b: B, +// })); + +// const B: z.ZodType = z.late.object(() => ({ +// val: z.number(), +// a: A, +// })); + +// const Alazy: z.ZodType = z.lazy(() => z.object({ +// val: z.number(), +// b: B, +// })); + +// const Blazy: z.ZodType = z.lazy(() => z.object({ +// val: z.number(), +// a: A, +// })); + +// const a: any = { val: 1 }; +// const b: any = { val: 2 }; +// a.b = b; +// b.a = a; + +// test('valid check', () => { +// A.parse(a); +// B.parse(b); +// }); + +// test("valid check lazy", () => { +// A.parse({val:1, b:}); +// B.parse(b); +// }); + +// test('masking check', () => { +// const FragmentOnA = z +// .object({ +// val: z.number(), +// b: z +// .object({ +// val: z.number(), +// a: z +// .object({ +// val: z.number(), +// }) +// .nonstrict(), +// }) +// .nonstrict(), +// }) +// .nonstrict(); + +// const fragment = FragmentOnA.parse(a); +// fragment; +// }); + +// test('invalid check', () => { +// expect(() => A.parse({} as any)).toThrow(); +// }); + +// test('schema getter', () => { +// (A as z.ZodLazy).schema; +// }); + +// test("self recursion with cyclical data", () => { +// interface Category { +// name: string; +// subcategories: Category[]; +// } + +// const Category: z.ZodType = z.late.object(() => ({ +// name: z.string(), +// subcategories: z.array(Category), +// })); + +// const untypedCategory: any = { +// name: "Category A", +// }; +// // creating a cycle +// untypedCategory.subcategories = [untypedCategory]; +// Category.parse(untypedCategory); +// }); + +// test("self recursion with base type", () => { +// const BaseCategory = z.object({ +// name: z.string(), +// }); +// type BaseCategory = z.infer; + +// type Category = BaseCategory & { subcategories: Category[] }; + +// const Category: z.ZodType = z.late +// .object(() => ({ +// subcategories: z.array(Category), +// })) +// .extend({ +// name: z.string(), +// }); + +// const untypedCategory: any = { +// name: "Category A", +// }; +// // creating a cycle +// untypedCategory.subcategories = [untypedCategory]; +// Category.parse(untypedCategory); // parses successfully +// }); diff --git a/node_modules/zod/src/v3/tests/refine.test.ts b/node_modules/zod/src/v3/tests/refine.test.ts new file mode 100644 index 0000000..55c27fe --- /dev/null +++ b/node_modules/zod/src/v3/tests/refine.test.ts @@ -0,0 +1,313 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { ZodIssueCode } from "../ZodError.js"; +import { util } from "../helpers/util.js"; + +test("refinement", () => { + const obj1 = z.object({ + first: z.string(), + second: z.string(), + }); + const obj2 = obj1.partial().strict(); + + const obj3 = obj2.refine((data) => data.first || data.second, "Either first or second should be filled in."); + + expect(obj1 === (obj2 as any)).toEqual(false); + expect(obj2 === (obj3 as any)).toEqual(false); + + expect(() => obj1.parse({})).toThrow(); + expect(() => obj2.parse({ third: "adsf" })).toThrow(); + expect(() => obj3.parse({})).toThrow(); + obj3.parse({ first: "a" }); + obj3.parse({ second: "a" }); + obj3.parse({ first: "a", second: "a" }); +}); + +test("refinement 2", () => { + const validationSchema = z + .object({ + email: z.string().email(), + password: z.string(), + confirmPassword: z.string(), + }) + .refine((data) => data.password === data.confirmPassword, "Both password and confirmation must match"); + + expect(() => + validationSchema.parse({ + email: "aaaa@gmail.com", + password: "aaaaaaaa", + confirmPassword: "bbbbbbbb", + }) + ).toThrow(); +}); + +test("refinement type guard", () => { + const validationSchema = z.object({ + a: z.string().refine((s): s is "a" => s === "a"), + }); + type Input = z.input; + type Schema = z.infer; + + util.assertEqual<"a", Input["a"]>(false); + util.assertEqual(true); + + util.assertEqual<"a", Schema["a"]>(true); + util.assertEqual(false); +}); + +test("refinement Promise", async () => { + const validationSchema = z + .object({ + email: z.string().email(), + password: z.string(), + confirmPassword: z.string(), + }) + .refine( + (data) => Promise.resolve().then(() => data.password === data.confirmPassword), + "Both password and confirmation must match" + ); + + await validationSchema.parseAsync({ + email: "aaaa@gmail.com", + password: "password", + confirmPassword: "password", + }); +}); + +test("custom path", async () => { + const result = await z + .object({ + password: z.string(), + confirm: z.string(), + }) + .refine((data) => data.confirm === data.password, { path: ["confirm"] }) + .spa({ password: "asdf", confirm: "qewr" }); + expect(result.success).toEqual(false); + if (!result.success) { + expect(result.error.issues[0].path).toEqual(["confirm"]); + } +}); + +test("use path in refinement context", async () => { + const noNested = z.string()._refinement((_val, ctx) => { + if (ctx.path.length > 0) { + ctx.addIssue({ + code: ZodIssueCode.custom, + message: `schema cannot be nested. path: ${ctx.path.join(".")}`, + }); + return false; + } else { + return true; + } + }); + + const data = z.object({ + foo: noNested, + }); + + const t1 = await noNested.spa("asdf"); + const t2 = await data.spa({ foo: "asdf" }); + + expect(t1.success).toBe(true); + expect(t2.success).toBe(false); + if (t2.success === false) { + expect(t2.error.issues[0].message).toEqual("schema cannot be nested. path: foo"); + } +}); + +test("superRefine", () => { + const Strings = z.array(z.string()).superRefine((val, ctx) => { + if (val.length > 3) { + ctx.addIssue({ + code: z.ZodIssueCode.too_big, + maximum: 3, + type: "array", + inclusive: true, + exact: true, + message: "Too many items 😡", + }); + } + + if (val.length !== new Set(val).size) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `No duplicates allowed.`, + }); + } + }); + + const result = Strings.safeParse(["asfd", "asfd", "asfd", "asfd"]); + + expect(result.success).toEqual(false); + if (!result.success) expect(result.error.issues.length).toEqual(2); + + Strings.parse(["asfd", "qwer"]); +}); + +test("superRefine async", async () => { + const Strings = z.array(z.string()).superRefine(async (val, ctx) => { + if (val.length > 3) { + ctx.addIssue({ + code: z.ZodIssueCode.too_big, + maximum: 3, + type: "array", + inclusive: true, + exact: true, + message: "Too many items 😡", + }); + } + + if (val.length !== new Set(val).size) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: `No duplicates allowed.`, + }); + } + }); + + const result = await Strings.safeParseAsync(["asfd", "asfd", "asfd", "asfd"]); + + expect(result.success).toEqual(false); + if (!result.success) expect(result.error.issues.length).toEqual(2); + + Strings.parseAsync(["asfd", "qwer"]); +}); + +test("superRefine - type narrowing", () => { + type NarrowType = { type: string; age: number }; + const schema = z + .object({ + type: z.string(), + age: z.number(), + }) + .nullable() + .superRefine((arg, ctx): arg is NarrowType => { + if (!arg) { + // still need to make a call to ctx.addIssue + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "cannot be null", + fatal: true, + }); + return false; + } + return true; + }); + + util.assertEqual, NarrowType>(true); + + expect(schema.safeParse({ type: "test", age: 0 }).success).toEqual(true); + expect(schema.safeParse(null).success).toEqual(false); +}); + +test("chained mixed refining types", () => { + type firstRefinement = { first: string; second: number; third: true }; + type secondRefinement = { first: "bob"; second: number; third: true }; + type thirdRefinement = { first: "bob"; second: 33; third: true }; + const schema = z + .object({ + first: z.string(), + second: z.number(), + third: z.boolean(), + }) + .nullable() + .refine((arg): arg is firstRefinement => !!arg?.third) + .superRefine((arg, ctx): arg is secondRefinement => { + util.assertEqual(true); + if (arg.first !== "bob") { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "`first` property must be `bob`", + }); + return false; + } + return true; + }) + .refine((arg): arg is thirdRefinement => { + util.assertEqual(true); + return arg.second === 33; + }); + + util.assertEqual, thirdRefinement>(true); +}); + +test("get inner type", () => { + z.string() + .refine(() => true) + .innerType() + .parse("asdf"); +}); + +test("chained refinements", () => { + const objectSchema = z + .object({ + length: z.number(), + size: z.number(), + }) + .refine(({ length }) => length > 5, { + path: ["length"], + message: "length greater than 5", + }) + .refine(({ size }) => size > 7, { + path: ["size"], + message: "size greater than 7", + }); + const r1 = objectSchema.safeParse({ + length: 4, + size: 9, + }); + expect(r1.success).toEqual(false); + if (!r1.success) expect(r1.error.issues.length).toEqual(1); + + const r2 = objectSchema.safeParse({ + length: 4, + size: 3, + }); + expect(r2.success).toEqual(false); + if (!r2.success) expect(r2.error.issues.length).toEqual(2); +}); + +test("fatal superRefine", () => { + const Strings = z + .string() + .superRefine((val, ctx) => { + if (val === "") { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "foo", + fatal: true, + }); + } + }) + .superRefine((val, ctx) => { + if (val !== " ") { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: "bar", + }); + } + }); + + const result = Strings.safeParse(""); + + expect(result.success).toEqual(false); + if (!result.success) expect(result.error.issues.length).toEqual(1); +}); + +test("superRefine after skipped transform", () => { + const schema = z + .string() + .regex(/^\d+$/) + .transform((val) => Number(val)) + .superRefine((val) => { + if (typeof val !== "number") { + throw new Error("Called without transform"); + } + }); + + const result = schema.safeParse(""); + + expect(result.success).toEqual(false); +}); diff --git a/node_modules/zod/src/v3/tests/safeparse.test.ts b/node_modules/zod/src/v3/tests/safeparse.test.ts new file mode 100644 index 0000000..950a2df --- /dev/null +++ b/node_modules/zod/src/v3/tests/safeparse.test.ts @@ -0,0 +1,27 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +const stringSchema = z.string(); + +test("safeparse fail", () => { + const safe = stringSchema.safeParse(12); + expect(safe.success).toEqual(false); + expect(safe.error).toBeInstanceOf(z.ZodError); +}); + +test("safeparse pass", () => { + const safe = stringSchema.safeParse("12"); + expect(safe.success).toEqual(true); + expect(safe.data).toEqual("12"); +}); + +test("safeparse unexpected error", () => { + expect(() => + stringSchema + .refine((data) => { + throw new Error(data); + }) + .safeParse("12") + ).toThrow(); +}); diff --git a/node_modules/zod/src/v3/tests/set.test.ts b/node_modules/zod/src/v3/tests/set.test.ts new file mode 100644 index 0000000..890cdd2 --- /dev/null +++ b/node_modules/zod/src/v3/tests/set.test.ts @@ -0,0 +1,142 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { ZodIssueCode } from "zod/v3"; +import { util } from "../helpers/util.js"; + +const stringSet = z.set(z.string()); +type stringSet = z.infer; + +const minTwo = z.set(z.string()).min(2); +const maxTwo = z.set(z.string()).max(2); +const justTwo = z.set(z.string()).size(2); +const nonEmpty = z.set(z.string()).nonempty(); +const nonEmptyMax = z.set(z.string()).nonempty().max(2); + +test("type inference", () => { + util.assertEqual>(true); +}); + +test("valid parse", () => { + const result = stringSet.safeParse(new Set(["first", "second"])); + expect(result.success).toEqual(true); + if (result.success) { + expect(result.data.has("first")).toEqual(true); + expect(result.data.has("second")).toEqual(true); + expect(result.data.has("third")).toEqual(false); + } + + expect(() => { + minTwo.parse(new Set(["a", "b"])); + minTwo.parse(new Set(["a", "b", "c"])); + maxTwo.parse(new Set(["a", "b"])); + maxTwo.parse(new Set(["a"])); + justTwo.parse(new Set(["a", "b"])); + nonEmpty.parse(new Set(["a"])); + nonEmptyMax.parse(new Set(["a"])); + }).not.toThrow(); +}); + +test("valid parse async", async () => { + const result = await stringSet.spa(new Set(["first", "second"])); + expect(result.success).toEqual(true); + if (result.success) { + expect(result.data.has("first")).toEqual(true); + expect(result.data.has("second")).toEqual(true); + expect(result.data.has("third")).toEqual(false); + } + + const asyncResult = await stringSet.safeParse(new Set(["first", "second"])); + expect(asyncResult.success).toEqual(true); + if (asyncResult.success) { + expect(asyncResult.data.has("first")).toEqual(true); + expect(asyncResult.data.has("second")).toEqual(true); + expect(asyncResult.data.has("third")).toEqual(false); + } +}); + +test("valid parse: size-related methods", () => { + expect(() => { + minTwo.parse(new Set(["a", "b"])); + minTwo.parse(new Set(["a", "b", "c"])); + maxTwo.parse(new Set(["a", "b"])); + maxTwo.parse(new Set(["a"])); + justTwo.parse(new Set(["a", "b"])); + nonEmpty.parse(new Set(["a"])); + nonEmptyMax.parse(new Set(["a"])); + }).not.toThrow(); + + const sizeZeroResult = stringSet.parse(new Set()); + expect(sizeZeroResult.size).toBe(0); + + const sizeTwoResult = minTwo.parse(new Set(["a", "b"])); + expect(sizeTwoResult.size).toBe(2); +}); + +test("failing when parsing empty set in nonempty ", () => { + const result = nonEmpty.safeParse(new Set()); + expect(result.success).toEqual(false); + + if (result.success === false) { + expect(result.error.issues.length).toEqual(1); + expect(result.error.issues[0].code).toEqual(ZodIssueCode.too_small); + } +}); + +test("failing when set is smaller than min() ", () => { + const result = minTwo.safeParse(new Set(["just_one"])); + expect(result.success).toEqual(false); + + if (result.success === false) { + expect(result.error.issues.length).toEqual(1); + expect(result.error.issues[0].code).toEqual(ZodIssueCode.too_small); + } +}); + +test("failing when set is bigger than max() ", () => { + const result = maxTwo.safeParse(new Set(["one", "two", "three"])); + expect(result.success).toEqual(false); + + if (result.success === false) { + expect(result.error.issues.length).toEqual(1); + expect(result.error.issues[0].code).toEqual(ZodIssueCode.too_big); + } +}); + +test("doesn’t throw when an empty set is given", () => { + const result = stringSet.safeParse(new Set([])); + expect(result.success).toEqual(true); +}); + +test("throws when a Map is given", () => { + const result = stringSet.safeParse(new Map([])); + expect(result.success).toEqual(false); + if (result.success === false) { + expect(result.error.issues.length).toEqual(1); + expect(result.error.issues[0].code).toEqual(ZodIssueCode.invalid_type); + } +}); + +test("throws when the given set has invalid input", () => { + const result = stringSet.safeParse(new Set([Symbol()])); + expect(result.success).toEqual(false); + if (result.success === false) { + expect(result.error.issues.length).toEqual(1); + expect(result.error.issues[0].code).toEqual(ZodIssueCode.invalid_type); + expect(result.error.issues[0].path).toEqual([0]); + } +}); + +test("throws when the given set has multiple invalid entries", () => { + const result = stringSet.safeParse(new Set([1, 2] as any[]) as Set); + + expect(result.success).toEqual(false); + if (result.success === false) { + expect(result.error.issues.length).toEqual(2); + expect(result.error.issues[0].code).toEqual(ZodIssueCode.invalid_type); + expect(result.error.issues[0].path).toEqual([0]); + expect(result.error.issues[1].code).toEqual(ZodIssueCode.invalid_type); + expect(result.error.issues[1].path).toEqual([1]); + } +}); diff --git a/node_modules/zod/src/v3/tests/standard-schema.test.ts b/node_modules/zod/src/v3/tests/standard-schema.test.ts new file mode 100644 index 0000000..74b3d2b --- /dev/null +++ b/node_modules/zod/src/v3/tests/standard-schema.test.ts @@ -0,0 +1,83 @@ +// import type { StandardSchemaV1 } from "@standard-schema/spec"; +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { util } from "../helpers/util.js"; +import type { StandardSchemaV1 } from "../standard-schema.js"; + +test("assignability", () => { + const _s1: StandardSchemaV1 = z.string(); + const _s2: StandardSchemaV1 = z.string(); + const _s3: StandardSchemaV1 = z.string(); + const _s4: StandardSchemaV1 = z.string(); + [_s1, _s2, _s3, _s4]; +}); + +test("type inference", () => { + const stringToNumber = z.string().transform((x) => x.length); + type input = StandardSchemaV1.InferInput; + util.assertEqual(true); + type output = StandardSchemaV1.InferOutput; + util.assertEqual(true); +}); + +test("valid parse", () => { + const schema = z.string(); + const result = schema["~standard"].validate("hello"); + if (result instanceof Promise) { + throw new Error("Expected sync result"); + } + expect(result.issues).toEqual(undefined); + if (result.issues) { + throw new Error("Expected no issues"); + } else { + expect(result.value).toEqual("hello"); + } +}); + +test("invalid parse", () => { + const schema = z.string(); + const result = schema["~standard"].validate(1234); + if (result instanceof Promise) { + throw new Error("Expected sync result"); + } + expect(result.issues).toBeDefined(); + if (!result.issues) { + throw new Error("Expected issues"); + } + expect(result.issues.length).toEqual(1); + expect(result.issues[0].path).toEqual([]); +}); + +test("valid parse async", async () => { + const schema = z.string().refine(async () => true); + const _result = schema["~standard"].validate("hello"); + if (_result instanceof Promise) { + const result = await _result; + expect(result.issues).toEqual(undefined); + if (result.issues) { + throw new Error("Expected no issues"); + } else { + expect(result.value).toEqual("hello"); + } + } else { + throw new Error("Expected async result"); + } +}); + +test("invalid parse async", async () => { + const schema = z.string().refine(async () => false); + const _result = schema["~standard"].validate("hello"); + if (_result instanceof Promise) { + const result = await _result; + expect(result.issues).toBeDefined(); + if (!result.issues) { + throw new Error("Expected issues"); + } + expect(result.issues.length).toEqual(1); + expect(result.issues[0].path).toEqual([]); + } else { + throw new Error("Expected async result"); + } +}); diff --git a/node_modules/zod/src/v3/tests/string.test.ts b/node_modules/zod/src/v3/tests/string.test.ts new file mode 100644 index 0000000..2d712e1 --- /dev/null +++ b/node_modules/zod/src/v3/tests/string.test.ts @@ -0,0 +1,916 @@ +import { Buffer } from "node:buffer"; +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; + +const minFive = z.string().min(5, "min5"); +const maxFive = z.string().max(5, "max5"); +const justFive = z.string().length(5); +const nonempty = z.string().nonempty("nonempty"); +const includes = z.string().includes("includes"); +const includesFromIndex2 = z.string().includes("includes", { position: 2 }); +const startsWith = z.string().startsWith("startsWith"); +const endsWith = z.string().endsWith("endsWith"); + +test("passing validations", () => { + minFive.parse("12345"); + minFive.parse("123456"); + maxFive.parse("12345"); + maxFive.parse("1234"); + nonempty.parse("1"); + justFive.parse("12345"); + includes.parse("XincludesXX"); + includesFromIndex2.parse("XXXincludesXX"); + startsWith.parse("startsWithX"); + endsWith.parse("XendsWith"); +}); + +test("failing validations", () => { + expect(() => minFive.parse("1234")).toThrow(); + expect(() => maxFive.parse("123456")).toThrow(); + expect(() => nonempty.parse("")).toThrow(); + expect(() => justFive.parse("1234")).toThrow(); + expect(() => justFive.parse("123456")).toThrow(); + expect(() => includes.parse("XincludeXX")).toThrow(); + expect(() => includesFromIndex2.parse("XincludesXX")).toThrow(); + expect(() => startsWith.parse("x")).toThrow(); + expect(() => endsWith.parse("x")).toThrow(); +}); + +test("email validations", () => { + const validEmails = [ + `email@domain.com`, + `firstname.lastname@domain.com`, + `email@subdomain.domain.com`, + `firstname+lastname@domain.com`, + `1234567890@domain.com`, + `email@domain-one.com`, + `_______@domain.com`, + `email@domain.name`, + `email@domain.co.jp`, + `firstname-lastname@domain.com`, + `very.common@example.com`, + `disposable.style.email.with+symbol@example.com`, + `other.email-with-hyphen@example.com`, + `fully-qualified-domain@example.com`, + `user.name+tag+sorting@example.com`, + `x@example.com`, + `mojojojo@asdf.example.com`, + `example-indeed@strange-example.com`, + `example@s.example`, + `user-@example.org`, + `user@my-example.com`, + `a@b.cd`, + `work+user@mail.com`, + `tom@test.te-st.com`, + `something@subdomain.domain-with-hyphens.tld`, + `common'name@domain.com`, + `francois@etu.inp-n7.fr`, + ]; + const invalidEmails = [ + // no "printable characters" + // `user%example.com@example.org`, + // `mailhost!username@example.org`, + // `test/test@test.com`, + + // double @ + `francois@@etu.inp-n7.fr`, + // do not support quotes + `"email"@domain.com`, + `"e asdf sadf ?<>ail"@domain.com`, + `" "@example.org`, + `"john..doe"@example.org`, + `"very.(),:;<>[]\".VERY.\"very@\\ \"very\".unusual"@strange.example.com`, + // do not support comma + `a,b@domain.com`, + + // do not support IPv4 + `email@123.123.123.123`, + `email@[123.123.123.123]`, + `postmaster@123.123.123.123`, + `user@[68.185.127.196]`, + `ipv4@[85.129.96.247]`, + `valid@[79.208.229.53]`, + `valid@[255.255.255.255]`, + `valid@[255.0.55.2]`, + `valid@[255.0.55.2]`, + + // do not support ipv6 + `hgrebert0@[IPv6:4dc8:ac7:ce79:8878:1290:6098:5c50:1f25]`, + `bshapiro4@[IPv6:3669:c709:e981:4884:59a3:75d1:166b:9ae]`, + `jsmith@[IPv6:2001:db8::1]`, + `postmaster@[IPv6:2001:0db8:85a3:0000:0000:8a2e:0370:7334]`, + `postmaster@[IPv6:2001:0db8:85a3:0000:0000:8a2e:0370:192.168.1.1]`, + + // microsoft test cases + `plainaddress`, + `#@%^%#$@#$@#.com`, + `@domain.com`, + `Joe Smith <email@domain.com>`, + `email.domain.com`, + `email@domain@domain.com`, + `.email@domain.com`, + `email.@domain.com`, + `email..email@domain.com`, + `あいうえお@domain.com`, + `email@domain.com (Joe Smith)`, + `email@domain`, + `email@-domain.com`, + `email@111.222.333.44444`, + `email@domain..com`, + `Abc.example.com`, + `A@b@c@example.com`, + `colin..hacks@domain.com`, + `a"b(c)d,e:f;gi[j\k]l@example.com`, + `just"not"right@example.com`, + `this is"not\allowed@example.com`, + `this\ still\"not\\allowed@example.com`, + + // random + `i_like_underscore@but_its_not_allowed_in_this_part.example.com`, + `QA[icon]CHOCOLATE[icon]@test.com`, + `invalid@-start.com`, + `invalid@end.com-`, + `a.b@c.d`, + `invalid@[1.1.1.-1]`, + `invalid@[68.185.127.196.55]`, + `temp@[192.168.1]`, + `temp@[9.18.122.]`, + `double..point@test.com`, + `asdad@test..com`, + `asdad@hghg...sd...au`, + `asdad@hghg........au`, + `invalid@[256.2.2.48]`, + `invalid@[256.2.2.48]`, + `invalid@[999.465.265.1]`, + `jkibbey4@[IPv6:82c4:19a8::70a9:2aac:557::ea69:d985:28d]`, + `mlivesay3@[9952:143f:b4df:2179:49a1:5e82:b92e:6b6]`, + `gbacher0@[IPv6:bc37:4d3f:5048:2e26:37cc:248e:df8e:2f7f:af]`, + `invalid@[IPv6:5348:4ed3:5d38:67fb:e9b:acd2:c13:192.168.256.1]`, + `test@.com`, + `aaaaaaaaaaaaaaalongemailthatcausesregexDoSvulnerability@test.c`, + ]; + const emailSchema = z.string().email(); + + expect( + validEmails.every((email) => { + return emailSchema.safeParse(email).success; + }) + ).toBe(true); + expect( + invalidEmails.every((email) => { + return emailSchema.safeParse(email).success === false; + }) + ).toBe(true); +}); + +const validBase64Strings = [ + "SGVsbG8gV29ybGQ=", // "Hello World" + "VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw==", // "This is an encoded string" + "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcms=", // "Many hands make light work" + "UGF0aWVuY2UgaXMgdGhlIGtleSB0byBzdWNjZXNz", // "Patience is the key to success" + "QmFzZTY0IGVuY29kaW5nIGlzIGZ1bg==", // "Base64 encoding is fun" + "MTIzNDU2Nzg5MA==", // "1234567890" + "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=", // "abcdefghijklmnopqrstuvwxyz" + "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=", // "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "ISIkJSMmJyonKCk=", // "!\"#$%&'()*" + "", // Empty string is technically valid base64 + "w7/Dv8O+w74K", // ÿÿþþ +]; + +for (const str of validBase64Strings) { + test(`base64 should accept ${str}`, () => { + expect(z.string().base64().safeParse(str).success).toBe(true); + }); +} + +const invalidBase64Strings = [ + "12345", // Not padded correctly, not a multiple of 4 characters + "12345===", // Not padded correctly + "SGVsbG8gV29ybGQ", // Missing padding + "VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw", // Missing padding + "!UGF0aWVuY2UgaXMgdGhlIGtleSB0byBzdWNjZXNz", // Invalid character '!' + "?QmFzZTY0IGVuY29kaW5nIGlzIGZ1bg==", // Invalid character '?' + ".MTIzND2Nzg5MC4=", // Invalid character '.' + "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo", // Missing padding + "w7_Dv8O-w74K", // Has - and _ characters (is base64url) +]; + +for (const str of invalidBase64Strings) { + test(`base64 should reject ${str}`, () => { + expect(z.string().base64().safeParse(str).success).toBe(false); + }); +} + +const validBase64URLStrings = [ + "SGVsbG8gV29ybGQ", // "Hello World" + "SGVsbG8gV29ybGQ=", // "Hello World" with padding + "VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw", // "This is an encoded string" + "VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw==", // "This is an encoded string" with padding + "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcms", // "Many hands make light work" + "TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcms=", // "Many hands make light work" with padding + "UGF0aWVuY2UgaXMgdGhlIGtleSB0byBzdWNjZXNz", // "Patience is the key to success" + "QmFzZTY0IGVuY29kaW5nIGlzIGZ1bg", // "Base64 encoding is fun" + "QmFzZTY0IGVuY29kaW5nIGlzIGZ1bg==", // "Base64 encoding is fun" with padding + "MTIzNDU2Nzg5MA", // "1234567890" + "MTIzNDU2Nzg5MA==", // "1234567890" with padding + "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo", // "abcdefghijklmnopqrstuvwxyz" + "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=", // "abcdefghijklmnopqrstuvwxyz with padding" + "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo", // "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=", // "ABCDEFGHIJKLMNOPQRSTUVWXYZ" with padding + "ISIkJSMmJyonKCk", // "!\"#$%&'()*" + "ISIkJSMmJyonKCk=", // "!\"#$%&'()*" with padding + "", // Empty string is technically valid base64url + "w7_Dv8O-w74K", // ÿÿþþ + "123456", +]; + +for (const str of validBase64URLStrings) { + test(`base64url should accept ${str}`, () => { + expect(z.string().base64url().safeParse(str).success).toBe(true); + }); +} + +const invalidBase64URLStrings = [ + "w7/Dv8O+w74K", // Has + and / characters (is base64) + "12345", // Invalid length (not a multiple of 4 characters when adding allowed number of padding characters) + "12345===", // Not padded correctly + "!UGF0aWVuY2UgaXMgdGhlIGtleSB0byBzdWNjZXNz", // Invalid character '!' + "?QmFzZTY0IGVuY29kaW5nIGlzIGZ1bg==", // Invalid character '?' + ".MTIzND2Nzg5MC4=", // Invalid character '.' +]; + +for (const str of invalidBase64URLStrings) { + test(`base64url should reject ${str}`, () => { + expect(z.string().base64url().safeParse(str).success).toBe(false); + }); +} + +function makeJwt(header: object, payload: object) { + const headerBase64 = Buffer.from(JSON.stringify(header)).toString("base64url"); + const payloadBase64 = Buffer.from(JSON.stringify(payload)).toString("base64url"); + const signature = "signature"; // Placeholder for the signature + return `${headerBase64}.${payloadBase64}.${signature}`; +} + +test("jwt validations", () => { + const jwt = z.string().jwt(); + const jwtWithAlg = z.string().jwt({ alg: "HS256" }); + + expect(() => jwt.parse("invalid")).toThrow(); + expect(() => jwt.parse("invalid.invalid")).toThrow(); + expect(() => jwt.parse("invalid.invalid.invalid")).toThrow(); + + // Valid JWTs + const d1 = makeJwt({ typ: "JWT", alg: "HS256" }, {}); + expect(() => jwt.parse(d1)).not.toThrow(); + expect(() => jwtWithAlg.parse(d1)).not.toThrow(); + + // Invalid header + const d2 = makeJwt({}, {}); + expect(() => jwt.parse(d2)).toThrow(); + + // Wrong algorithm + const d3 = makeJwt({ typ: "JWT", alg: "RS256" }, {}); + expect(() => jwtWithAlg.parse(d3)).toThrow(); + + // missing typ is fine + const d4 = makeJwt({ alg: "HS256" }, {}); + jwt.parse(d4); + + // type isn't JWT + const d5 = makeJwt({ typ: "SUP", alg: "HS256" }, { foo: "bar" }); + expect(() => jwt.parse(d5)).toThrow(); + + // Custom error message + const customMsg = "Invalid JWT token"; + const jwtWithMsg = z.string().jwt({ message: customMsg }); + try { + jwtWithMsg.parse("invalid"); + } catch (error) { + expect((error as z.ZodError).issues[0].message).toBe(customMsg); + } +}); + +test("url validations", () => { + const url = z.string().url(); + url.parse("http://google.com"); + url.parse("https://google.com/asdf?asdf=ljk3lk4&asdf=234#asdf"); + expect(() => url.parse("asdf")).toThrow(); + expect(() => url.parse("https:/")).toThrow(); + expect(() => url.parse("asdfj@lkjsdf.com")).toThrow(); +}); + +test("url error overrides", () => { + try { + z.string().url().parse("https"); + } catch (err) { + expect((err as z.ZodError).issues[0].message).toEqual("Invalid url"); + } + try { + z.string().url("badurl").parse("https"); + } catch (err) { + expect((err as z.ZodError).issues[0].message).toEqual("badurl"); + } + try { + z.string().url({ message: "badurl" }).parse("https"); + } catch (err) { + expect((err as z.ZodError).issues[0].message).toEqual("badurl"); + } +}); + +test("emoji validations", () => { + const emoji = z.string().emoji(); + + emoji.parse("👋👋👋👋"); + emoji.parse("🍺👩‍🚀🫡"); + emoji.parse("💚💙💜💛❤️"); + emoji.parse("🐛🗝🐏🍡🎦🚢🏨💫🎌☘🗡😹🔒🎬➡️🍹🗂🚨⚜🕑〽️🚦🌊🍴💍🍌💰😳🌺🍃"); + emoji.parse("🇹🇷🤽🏿‍♂️"); + emoji.parse( + "😀😁😂🤣😃😄😅😆😉😊😋😎😍😘🥰😗😙😚☺️☺🙂🤗🤩🤔🤨😐😑😶🙄😏😣😥😮🤐😯😪😫😴😌😛😜😝🤤😒😓😔😕🙃🤑😲☹️☹🙁😖😞😟😤😢😭😦😧😨😩🤯😬😰😱🥵🥶😳🤪😵😡😠🤬😷🤒🤕🤢🤮🤧😇🤠🥳🥴🥺🤥🤫🤭🧐🤓😈👿🤡👹👺💀☠️☠👻👽👾🤖💩😺😸😹😻😼😽🙀😿😾🙈🙉🙊🏻🏼🏽🏾🏿👶👶🏻👶🏼👶🏽👶🏾👶🏿🧒🧒🏻🧒🏼🧒🏽🧒🏾🧒🏿👦👦🏻👦🏼👦🏽👦🏾👦🏿👧👧🏻👧🏼👧🏽👧🏾👧🏿🧑🧑🏻🧑🏼🧑🏽🧑🏾🧑🏿👨👨🏻👨🏼👨🏽👨🏾👨🏿👩👩🏻👩🏼👩🏽👩🏾👩🏿🧓🧓🏻🧓🏼🧓🏽🧓🏾🧓🏿👴👴🏻👴🏼👴🏽👴🏾👴🏿👵👵🏻👵🏼👵🏽👵🏾👵🏿👨‍⚕️👨‍⚕👨🏻‍⚕️👨🏻‍⚕👨🏼‍⚕️👨🏼‍⚕👨🏽‍⚕️👨🏽‍⚕👨🏾‍⚕️👨🏾‍⚕👨🏿‍⚕️👨🏿‍⚕👩‍⚕️👩‍⚕👩🏻‍⚕️👩🏻‍⚕👩🏼‍⚕️👩🏼‍⚕👩🏽‍⚕️👩🏽‍⚕👩🏾‍⚕️👩🏾‍⚕👩🏿‍⚕️👩🏿‍⚕👨‍🎓👨🏻‍🎓👨🏼‍🎓👨🏽‍🎓👨🏾‍🎓👨🏿‍🎓👩‍🎓👩🏻‍🎓👩🏼‍🎓👩🏽‍🎓👩🏾‍🎓👩🏿‍🎓👨‍🏫👨🏻‍🏫👨🏼‍🏫👨🏽‍🏫👨🏾‍🏫👨🏿‍🏫👩‍🏫👩🏻‍🏫👩🏼‍🏫👩🏽‍🏫👩🏾‍🏫👩🏿‍🏫👨‍⚖️👨‍⚖👨🏻‍⚖️👨🏻‍⚖👨🏼‍⚖️👨🏼‍⚖👨🏽‍⚖️👨🏽‍⚖👨🏾‍⚖️👨🏾‍⚖👨🏿‍⚖️👨🏿‍⚖👩‍⚖️👩‍⚖👩🏻‍⚖️👩🏻‍⚖👩🏼‍⚖️👩🏼‍⚖👩🏽‍⚖️👩🏽‍⚖👩🏾‍⚖️👩🏾‍⚖👩🏿‍⚖️👩🏿‍⚖👨‍🌾👨🏻‍🌾👨🏼‍🌾👨🏽‍🌾👨🏾‍🌾👨🏿‍🌾👩‍🌾👩🏻‍🌾👩🏼‍🌾👩🏽‍🌾👩🏾‍🌾👩🏿‍🌾👨‍🍳👨🏻‍🍳👨🏼‍🍳👨🏽‍🍳👨🏾‍🍳👨🏿‍🍳👩‍🍳👩🏻‍🍳👩🏼‍🍳👩🏽‍🍳👩🏾‍🍳👩🏿‍🍳👨‍🔧👨🏻‍🔧👨🏼‍🔧👨🏽‍🔧👨🏾‍🔧👨🏿‍🔧👩‍🔧👩🏻‍🔧👩🏼‍🔧👩🏽‍🔧👩🏾‍🔧👩🏿‍🔧👨‍🏭👨🏻‍🏭👨🏼‍🏭👨🏽‍🏭👨🏾‍🏭👨🏿‍🏭👩‍🏭👩🏻‍🏭👩🏼‍🏭👩🏽‍🏭👩🏾‍🏭👩🏿‍🏭👨‍💼👨🏻‍💼👨🏼‍💼👨🏽‍💼👨🏾‍💼👨🏿‍💼👩‍💼👩🏻‍💼👩🏼‍💼👩🏽‍💼👩🏾‍💼👩🏿‍💼👨‍🔬👨🏻‍🔬👨🏼‍🔬👨🏽‍🔬👨🏾‍🔬👨🏿‍🔬👩‍🔬👩🏻‍🔬👩🏼‍🔬👩🏽‍🔬👩🏾‍🔬👩🏿‍🔬👨‍💻👨🏻‍💻👨🏼‍💻👨🏽‍💻👨🏾‍💻👨🏿‍💻👩‍💻👩🏻‍💻👩🏼‍💻👩🏽‍💻👩🏾‍💻👩🏿‍💻👨‍🎤👨🏻‍🎤👨🏼‍🎤👨🏽‍🎤👨🏾‍🎤👨🏿‍🎤👩‍🎤👩🏻‍🎤👩🏼‍🎤👩🏽‍🎤👩🏾‍🎤👩🏿‍🎤👨‍🎨👨🏻‍🎨👨🏼‍🎨👨🏽‍🎨👨🏾‍🎨👨🏿‍🎨👩‍🎨👩🏻‍🎨👩🏼‍🎨👩🏽‍🎨👩🏾‍🎨👩🏿‍🎨👨‍✈️👨‍✈👨🏻‍✈️👨🏻‍✈👨🏼‍✈️👨🏼‍✈👨🏽‍✈️👨🏽‍✈👨🏾‍✈️👨🏾‍✈👨🏿‍✈️👨🏿‍✈👩‍✈️👩‍✈👩🏻‍✈️👩🏻‍✈👩🏼‍✈️👩🏼‍✈👩🏽‍✈️👩🏽‍✈👩🏾‍✈️👩🏾‍✈👩🏿‍✈️👩🏿‍✈👨‍🚀👨🏻‍🚀👨🏼‍🚀👨🏽‍🚀👨🏾‍🚀👨🏿‍🚀👩‍🚀👩🏻‍🚀👩🏼‍🚀👩🏽‍🚀👩🏾‍🚀👩🏿‍🚀👨‍🚒👨🏻‍🚒👨🏼‍🚒👨🏽‍🚒👨🏾‍🚒👨🏿‍🚒👩‍🚒👩🏻‍🚒👩🏼‍🚒👩🏽‍🚒👩🏾‍🚒👩🏿‍🚒👮👮🏻👮🏼👮🏽👮🏾👮🏿👮‍♂️👮‍♂👮🏻‍♂️👮🏻‍♂👮🏼‍♂️👮🏼‍♂👮🏽‍♂️👮🏽‍♂👮🏾‍♂️👮🏾‍♂👮🏿‍♂️👮🏿‍♂👮‍♀️👮‍♀👮🏻‍♀️👮🏻‍♀👮🏼‍♀️👮🏼‍♀👮🏽‍♀️👮🏽‍♀👮🏾‍♀️👮🏾‍♀👮🏿‍♀️👮🏿‍♀🕵️🕵🕵🏻🕵🏼🕵🏽🕵🏾🕵🏿🕵️‍♂️🕵‍♂️🕵️‍♂🕵‍♂🕵🏻‍♂️🕵🏻‍♂🕵🏼‍♂️🕵🏼‍♂🕵🏽‍♂️🕵🏽‍♂🕵🏾‍♂️🕵🏾‍♂🕵🏿‍♂️🕵🏿‍♂🕵️‍♀️🕵‍♀️🕵️‍♀🕵‍♀🕵🏻‍♀️🕵🏻‍♀🕵🏼‍♀️🕵🏼‍♀🕵🏽‍♀️🕵🏽‍♀🕵🏾‍♀️🕵🏾‍♀🕵🏿‍♀️🕵🏿‍♀💂💂🏻💂🏼💂🏽💂🏾💂🏿💂‍♂️💂‍♂💂🏻‍♂️💂🏻‍♂💂🏼‍♂️💂🏼‍♂💂🏽‍♂️💂🏽‍♂💂🏾‍♂️💂🏾‍♂💂🏿‍♂️💂🏿‍♂💂‍♀️💂‍♀💂🏻‍♀️💂🏻‍♀💂🏼‍♀️💂🏼‍♀💂🏽‍♀️💂🏽‍♀💂🏾‍♀️💂🏾‍♀💂🏿‍♀️💂🏿‍♀👷👷🏻👷🏼👷🏽👷🏾👷🏿👷‍♂️👷‍♂👷🏻‍♂️👷🏻‍♂👷🏼‍♂️👷🏼‍♂👷🏽‍♂️👷🏽‍♂👷🏾‍♂️👷🏾‍♂👷🏿‍♂️👷🏿‍♂👷‍♀️👷‍♀👷🏻‍♀️👷🏻‍♀👷🏼‍♀️👷🏼‍♀👷🏽‍♀️👷🏽‍♀👷🏾‍♀️👷🏾‍♀👷🏿‍♀️👷🏿‍♀🤴🤴🏻🤴🏼🤴🏽🤴🏾🤴🏿👸👸🏻👸🏼👸🏽👸🏾👸🏿👳👳🏻👳🏼👳🏽👳🏾👳🏿👳‍♂️👳‍♂👳🏻‍♂️👳🏻‍♂👳🏼‍♂️👳🏼‍♂👳🏽‍♂️👳🏽‍♂👳🏾‍♂️👳🏾‍♂👳🏿‍♂️👳🏿‍♂👳‍♀️👳‍♀👳🏻‍♀️👳🏻‍♀👳🏼‍♀️👳🏼‍♀👳🏽‍♀️👳🏽‍♀👳🏾‍♀️👳🏾‍♀👳🏿‍♀️👳🏿‍♀👲👲🏻👲🏼👲🏽👲🏾👲🏿🧕🧕🏻🧕🏼🧕🏽🧕🏾🧕🏿🧔🧔🏻🧔🏼🧔🏽🧔🏾🧔🏿👱👱🏻👱🏼👱🏽👱🏾👱🏿👱‍♂️👱‍♂👱🏻‍♂️👱🏻‍♂👱🏼‍♂️👱🏼‍♂👱🏽‍♂️👱🏽‍♂👱🏾‍♂️👱🏾‍♂👱🏿‍♂️👱🏿‍♂👱‍♀️👱‍♀👱🏻‍♀️👱🏻‍♀👱🏼‍♀️👱🏼‍♀👱🏽‍♀️👱🏽‍♀👱🏾‍♀️👱🏾‍♀👱🏿‍♀️👱🏿‍♀👨‍🦰👨🏻‍🦰👨🏼‍🦰👨🏽‍🦰👨🏾‍🦰👨🏿‍🦰👩‍🦰👩🏻‍🦰👩🏼‍🦰👩🏽‍🦰👩🏾‍🦰👩🏿‍🦰👨‍🦱👨🏻‍🦱👨🏼‍🦱👨🏽‍🦱👨🏾‍🦱👨🏿‍🦱👩‍🦱👩🏻‍🦱👩🏼‍🦱👩🏽‍🦱👩🏾‍🦱👩🏿‍🦱👨‍🦲👨🏻‍🦲👨🏼‍🦲👨🏽‍🦲👨🏾‍🦲👨🏿‍🦲👩‍🦲👩🏻‍🦲👩🏼‍🦲👩🏽‍🦲👩🏾‍🦲👩🏿‍🦲👨‍🦳👨🏻‍🦳👨🏼‍🦳👨🏽‍🦳👨🏾‍🦳👨🏿‍🦳👩‍🦳👩🏻‍🦳👩🏼‍🦳👩🏽‍🦳👩🏾‍🦳👩🏿‍🦳🤵🤵🏻🤵🏼🤵🏽🤵🏾🤵🏿👰👰🏻👰🏼👰🏽👰🏾👰🏿🤰🤰🏻🤰🏼🤰🏽🤰🏾🤰🏿🤱🤱🏻🤱🏼🤱🏽🤱🏾🤱🏿👼👼🏻👼🏼👼🏽👼🏾👼🏿🎅🎅🏻🎅🏼🎅🏽🎅🏾🎅🏿🤶🤶🏻🤶🏼🤶🏽🤶🏾🤶🏿🦸🦸🏻🦸🏼🦸🏽🦸🏾🦸🏿🦸‍♀️🦸‍♀🦸🏻‍♀️🦸🏻‍♀🦸🏼‍♀️🦸🏼‍♀🦸🏽‍♀️🦸🏽‍♀🦸🏾‍♀️🦸🏾‍♀🦸🏿‍♀️🦸🏿‍♀🦸‍♂️🦸‍♂🦸🏻‍♂️🦸🏻‍♂🦸🏼‍♂️🦸🏼‍♂🦸🏽‍♂️🦸🏽‍♂🦸🏾‍♂️🦸🏾‍♂🦸🏿‍♂️🦸🏿‍♂🦹🦹🏻🦹🏼🦹🏽🦹🏾🦹🏿🦹‍♀️🦹‍♀🦹🏻‍♀️🦹🏻‍♀🦹🏼‍♀️🦹🏼‍♀🦹🏽‍♀️🦹🏽‍♀🦹🏾‍♀️🦹🏾‍♀🦹🏿‍♀️🦹🏿‍♀🦹‍♂️🦹‍♂🦹🏻‍♂️🦹🏻‍♂🦹🏼‍♂️🦹🏼‍♂🦹🏽‍♂️🦹🏽‍♂🦹🏾‍♂️🦹🏾‍♂🦹🏿‍♂️🦹🏿‍♂🧙🧙🏻🧙🏼🧙🏽🧙🏾🧙🏿🧙‍♀️🧙‍♀🧙🏻‍♀️🧙🏻‍♀🧙🏼‍♀️🧙🏼‍♀🧙🏽‍♀️🧙🏽‍♀🧙🏾‍♀️🧙🏾‍♀🧙🏿‍♀️🧙🏿‍♀🧙‍♂️🧙‍♂🧙🏻‍♂️🧙🏻‍♂🧙🏼‍♂️🧙🏼‍♂🧙🏽‍♂️🧙🏽‍♂🧙🏾‍♂️🧙🏾‍♂🧙🏿‍♂️🧙🏿‍♂🧚🧚🏻🧚🏼🧚🏽🧚🏾🧚🏿🧚‍♀️🧚‍♀🧚🏻‍♀️🧚🏻‍♀🧚🏼‍♀️🧚🏼‍♀🧚🏽‍♀️🧚🏽‍♀🧚🏾‍♀️🧚🏾‍♀🧚🏿‍♀️🧚🏿‍♀🧚‍♂️🧚‍♂🧚🏻‍♂️🧚🏻‍♂🧚🏼‍♂️🧚🏼‍♂🧚🏽‍♂️🧚🏽‍♂🧚🏾‍♂️🧚🏾‍♂🧚🏿‍♂️🧚🏿‍♂🧛🧛🏻🧛🏼🧛🏽🧛🏾🧛🏿🧛‍♀️🧛‍♀🧛🏻‍♀️🧛🏻‍♀🧛🏼‍♀️🧛🏼‍♀🧛🏽‍♀️🧛🏽‍♀🧛🏾‍♀️🧛🏾‍♀🧛🏿‍♀️🧛🏿‍♀🧛‍♂️🧛‍♂🧛🏻‍♂️🧛🏻‍♂🧛🏼‍♂️🧛🏼‍♂🧛🏽‍♂️🧛🏽‍♂🧛🏾‍♂️🧛🏾‍♂🧛🏿‍♂️🧛🏿‍♂🧜🧜🏻🧜🏼🧜🏽🧜🏾🧜🏿🧜‍♀️🧜‍♀🧜🏻‍♀️🧜🏻‍♀🧜🏼‍♀️🧜🏼‍♀🧜🏽‍♀️🧜🏽‍♀🧜🏾‍♀️🧜🏾‍♀🧜🏿‍♀️🧜🏿‍♀🧜‍♂️🧜‍♂🧜🏻‍♂️🧜🏻‍♂🧜🏼‍♂️🧜🏼‍♂🧜🏽‍♂️🧜🏽‍♂🧜🏾‍♂️🧜🏾‍♂🧜🏿‍♂️🧜🏿‍♂🧝🧝🏻🧝🏼🧝🏽🧝🏾🧝🏿🧝‍♀️🧝‍♀🧝🏻‍♀️🧝🏻‍♀🧝🏼‍♀️🧝🏼‍♀🧝🏽‍♀️🧝🏽‍♀🧝🏾‍♀️🧝🏾‍♀🧝🏿‍♀️🧝🏿‍♀🧝‍♂️🧝‍♂🧝🏻‍♂️🧝🏻‍♂🧝🏼‍♂️🧝🏼‍♂🧝🏽‍♂️🧝🏽‍♂🧝🏾‍♂️🧝🏾‍♂🧝🏿‍♂️🧝🏿‍♂🧞🧞‍♀️🧞‍♀🧞‍♂️🧞‍♂🧟🧟‍♀️🧟‍♀🧟‍♂️🧟‍♂🙍🙍🏻🙍🏼🙍🏽🙍🏾🙍🏿🙍‍♂️🙍‍♂🙍🏻‍♂️🙍🏻‍♂🙍🏼‍♂️🙍🏼‍♂🙍🏽‍♂️🙍🏽‍♂🙍🏾‍♂️🙍🏾‍♂🙍🏿‍♂️🙍🏿‍♂🙍‍♀️🙍‍♀🙍🏻‍♀️🙍🏻‍♀🙍🏼‍♀️🙍🏼‍♀🙍🏽‍♀️🙍🏽‍♀🙍🏾‍♀️🙍🏾‍♀🙍🏿‍♀️🙍🏿‍♀🙎🙎🏻🙎🏼🙎🏽🙎🏾🙎🏿🙎‍♂️🙎‍♂🙎🏻‍♂️🙎🏻‍♂🙎🏼‍♂️🙎🏼‍♂🙎🏽‍♂️🙎🏽‍♂🙎🏾‍♂️🙎🏾‍♂🙎🏿‍♂️🙎🏿‍♂🙎‍♀️🙎‍♀🙎🏻‍♀️🙎🏻‍♀🙎🏼‍♀️🙎🏼‍♀🙎🏽‍♀️🙎🏽‍♀🙎🏾‍♀️🙎🏾‍♀🙎🏿‍♀️🙎🏿‍♀🙅🙅🏻🙅🏼🙅🏽🙅🏾🙅🏿🙅‍♂️🙅‍♂🙅🏻‍♂️🙅🏻‍♂🙅🏼‍♂️🙅🏼‍♂🙅🏽‍♂️🙅🏽‍♂🙅🏾‍♂️🙅🏾‍♂🙅🏿‍♂️🙅🏿‍♂🙅‍♀️🙅‍♀🙅🏻‍♀️🙅🏻‍♀🙅🏼‍♀️🙅🏼‍♀🙅🏽‍♀️🙅🏽‍♀🙅🏾‍♀️🙅🏾‍♀🙅🏿‍♀️🙅🏿‍♀🙆🙆🏻🙆🏼🙆🏽🙆🏾🙆🏿🙆‍♂️🙆‍♂🙆🏻‍♂️🙆🏻‍♂🙆🏼‍♂️🙆🏼‍♂🙆🏽‍♂️🙆🏽‍♂🙆🏾‍♂️🙆🏾‍♂🙆🏿‍♂️🙆🏿‍♂🙆‍♀️🙆‍♀🙆🏻‍♀️🙆🏻‍♀🙆🏼‍♀️🙆🏼‍♀🙆🏽‍♀️🙆🏽‍♀🙆🏾‍♀️🙆🏾‍♀🙆🏿‍♀️🙆🏿‍♀💁💁🏻💁🏼💁🏽💁🏾💁🏿💁‍♂️💁‍♂💁🏻‍♂️💁🏻‍♂💁🏼‍♂️💁🏼‍♂💁🏽‍♂️💁🏽‍♂💁🏾‍♂️💁🏾‍♂💁🏿‍♂️💁🏿‍♂💁‍♀️💁‍♀💁🏻‍♀️💁🏻‍♀💁🏼‍♀️💁🏼‍♀💁🏽‍♀️💁🏽‍♀💁🏾‍♀️💁🏾‍♀💁🏿‍♀️💁🏿‍♀🙋🙋🏻🙋🏼🙋🏽🙋🏾🙋🏿🙋‍♂️🙋‍♂🙋🏻‍♂️🙋🏻‍♂🙋🏼‍♂️🙋🏼‍♂🙋🏽‍♂️🙋🏽‍♂🙋🏾‍♂️🙋🏾‍♂🙋🏿‍♂️🙋🏿‍♂🙋‍♀️🙋‍♀🙋🏻‍♀️🙋🏻‍♀🙋🏼‍♀️🙋🏼‍♀🙋🏽‍♀️🙋🏽‍♀🙋🏾‍♀️🙋🏾‍♀🙋🏿‍♀️🙋🏿‍♀🙇🙇🏻🙇🏼🙇🏽🙇🏾🙇🏿🙇‍♂️🙇‍♂🙇🏻‍♂️🙇🏻‍♂🙇🏼‍♂️🙇🏼‍♂🙇🏽‍♂️🙇🏽‍♂🙇🏾‍♂️🙇🏾‍♂🙇🏿‍♂️🙇🏿‍♂🙇‍♀️🙇‍♀🙇🏻‍♀️🙇🏻‍♀🙇🏼‍♀️🙇🏼‍♀🙇🏽‍♀️🙇🏽‍♀🙇🏾‍♀️🙇🏾‍♀🙇🏿‍♀️🙇🏿‍♀🤦🤦🏻🤦🏼🤦🏽🤦🏾🤦🏿🤦‍♂️🤦‍♂🤦🏻‍♂️🤦🏻‍♂🤦🏼‍♂️🤦🏼‍♂🤦🏽‍♂️🤦🏽‍♂🤦🏾‍♂️🤦🏾‍♂🤦🏿‍♂️🤦🏿‍♂🤦‍♀️🤦‍♀🤦🏻‍♀️🤦🏻‍♀🤦🏼‍♀️🤦🏼‍♀🤦🏽‍♀️🤦🏽‍♀🤦🏾‍♀️🤦🏾‍♀🤦🏿‍♀️🤦🏿‍♀🤷🤷🏻🤷🏼🤷🏽🤷🏾🤷🏿🤷‍♂️🤷‍♂🤷🏻‍♂️🤷🏻‍♂🤷🏼‍♂️🤷🏼‍♂🤷🏽‍♂️🤷🏽‍♂🤷🏾‍♂️🤷🏾‍♂🤷🏿‍♂️🤷🏿‍♂🤷‍♀️🤷‍♀🤷🏻‍♀️🤷🏻‍♀🤷🏼‍♀️🤷🏼‍♀🤷🏽‍♀️🤷🏽‍♀🤷🏾‍♀️🤷🏾‍♀🤷🏿‍♀️🤷🏿‍♀💆💆🏻💆🏼💆🏽💆🏾💆🏿💆‍♂️💆‍♂💆🏻‍♂️💆🏻‍♂💆🏼‍♂️💆🏼‍♂💆🏽‍♂️💆🏽‍♂💆🏾‍♂️💆🏾‍♂💆🏿‍♂️💆🏿‍♂💆‍♀️💆‍♀💆🏻‍♀️💆🏻‍♀💆🏼‍♀️💆🏼‍♀💆🏽‍♀️💆🏽‍♀💆🏾‍♀️💆🏾‍♀💆🏿‍♀️💆🏿‍♀💇💇🏻💇🏼💇🏽💇🏾💇🏿💇‍♂️💇‍♂💇🏻‍♂️💇🏻‍♂💇🏼‍♂️💇🏼‍♂💇🏽‍♂️💇🏽‍♂💇🏾‍♂️💇🏾‍♂💇🏿‍♂️💇🏿‍♂💇‍♀️💇‍♀💇🏻‍♀️💇🏻‍♀💇🏼‍♀️💇🏼‍♀💇🏽‍♀️💇🏽‍♀💇🏾‍♀️💇🏾‍♀💇🏿‍♀️💇🏿‍♀🚶🚶🏻🚶🏼🚶🏽🚶🏾🚶🏿🚶‍♂️🚶‍♂🚶🏻‍♂️🚶🏻‍♂🚶🏼‍♂️🚶🏼‍♂🚶🏽‍♂️🚶🏽‍♂🚶🏾‍♂️🚶🏾‍♂🚶🏿‍♂️🚶🏿‍♂🚶‍♀️🚶‍♀🚶🏻‍♀️🚶🏻‍♀🚶🏼‍♀️🚶🏼‍♀🚶🏽‍♀️🚶🏽‍♀🚶🏾‍♀️🚶🏾‍♀🚶🏿‍♀️🚶🏿‍♀🏃🏃🏻🏃🏼🏃🏽🏃🏾🏃🏿🏃‍♂️🏃‍♂🏃🏻‍♂️🏃🏻‍♂🏃🏼‍♂️🏃🏼‍♂🏃🏽‍♂️🏃🏽‍♂🏃🏾‍♂️🏃🏾‍♂🏃🏿‍♂️🏃🏿‍♂🏃‍♀️🏃‍♀🏃🏻‍♀️🏃🏻‍♀🏃🏼‍♀️🏃🏼‍♀🏃🏽‍♀️🏃🏽‍♀🏃🏾‍♀️🏃🏾‍♀🏃🏿‍♀️🏃🏿‍♀💃💃🏻💃🏼💃🏽💃🏾💃🏿🕺🕺🏻🕺🏼🕺🏽🕺🏾🕺🏿👯👯‍♂️👯‍♂👯‍♀️👯‍♀🧖🧖🏻🧖🏼🧖🏽🧖🏾🧖🏿🧖‍♀️🧖‍♀🧖🏻‍♀️🧖🏻‍♀🧖🏼‍♀️🧖🏼‍♀🧖🏽‍♀️🧖🏽‍♀🧖🏾‍♀️🧖🏾‍♀🧖🏿‍♀️🧖🏿‍♀🧖‍♂️🧖‍♂🧖🏻‍♂️🧖🏻‍♂🧖🏼‍♂️🧖🏼‍♂🧖🏽‍♂️🧖🏽‍♂🧖🏾‍♂️🧖🏾‍♂🧖🏿‍♂️🧖🏿‍♂🧗🧗🏻🧗🏼🧗🏽🧗🏾🧗🏿🧗‍♀️🧗‍♀🧗🏻‍♀️🧗🏻‍♀🧗🏼‍♀️🧗🏼‍♀🧗🏽‍♀️🧗🏽‍♀🧗🏾‍♀️🧗🏾‍♀🧗🏿‍♀️🧗🏿‍♀🧗‍♂️🧗‍♂🧗🏻‍♂️🧗🏻‍♂🧗🏼‍♂️🧗🏼‍♂🧗🏽‍♂️🧗🏽‍♂🧗🏾‍♂️🧗🏾‍♂🧗🏿‍♂️🧗🏿‍♂🧘🧘🏻🧘🏼🧘🏽🧘🏾🧘🏿🧘‍♀️🧘‍♀🧘🏻‍♀️🧘🏻‍♀🧘🏼‍♀️🧘🏼‍♀🧘🏽‍♀️🧘🏽‍♀🧘🏾‍♀️🧘🏾‍♀🧘🏿‍♀️🧘🏿‍♀🧘‍♂️🧘‍♂🧘🏻‍♂️🧘🏻‍♂🧘🏼‍♂️🧘🏼‍♂🧘🏽‍♂️🧘🏽‍♂🧘🏾‍♂️🧘🏾‍♂🧘🏿‍♂️🧘🏿‍♂🛀🛀🏻🛀🏼🛀🏽🛀🏾🛀🏿🛌🛌🏻🛌🏼🛌🏽🛌🏾🛌🏿🕴️🕴🕴🏻🕴🏼🕴🏽🕴🏾🕴🏿🗣️🗣👤👥🤺🏇🏇🏻🏇🏼🏇🏽🏇🏾🏇🏿⛷️⛷🏂🏂🏻🏂🏼🏂🏽🏂🏾🏂🏿🏌️🏌🏌🏻🏌🏼🏌🏽🏌🏾🏌🏿🏌️‍♂️🏌‍♂️🏌️‍♂🏌‍♂🏌🏻‍♂️🏌🏻‍♂🏌🏼‍♂️🏌🏼‍♂🏌🏽‍♂️🏌🏽‍♂🏌🏾‍♂️🏌🏾‍♂🏌🏿‍♂️🏌🏿‍♂🏌️‍♀️🏌‍♀️🏌️‍♀🏌‍♀🏌🏻‍♀️🏌🏻‍♀🏌🏼‍♀️🏌🏼‍♀🏌🏽‍♀️🏌🏽‍♀🏌🏾‍♀️🏌🏾‍♀🏌🏿‍♀️🏌🏿‍♀🏄🏄🏻🏄🏼🏄🏽🏄🏾🏄🏿🏄‍♂️🏄‍♂🏄🏻‍♂️🏄🏻‍♂🏄🏼‍♂️🏄🏼‍♂🏄🏽‍♂️🏄🏽‍♂🏄🏾‍♂️🏄🏾‍♂🏄🏿‍♂️🏄🏿‍♂🏄‍♀️🏄‍♀🏄🏻‍♀️🏄🏻‍♀🏄🏼‍♀️🏄🏼‍♀🏄🏽‍♀️🏄🏽‍♀🏄🏾‍♀️🏄🏾‍♀🏄🏿‍♀️🏄🏿‍♀🚣🚣🏻🚣🏼🚣🏽🚣🏾🚣🏿🚣‍♂️🚣‍♂🚣🏻‍♂️🚣🏻‍♂🚣🏼‍♂️🚣🏼‍♂🚣🏽‍♂️🚣🏽‍♂🚣🏾‍♂️🚣🏾‍♂🚣🏿‍♂️🚣🏿‍♂🚣‍♀️🚣‍♀🚣🏻‍♀️🚣🏻‍♀🚣🏼‍♀️🚣🏼‍♀🚣🏽‍♀️🚣🏽‍♀🚣🏾‍♀️🚣🏾‍♀🚣🏿‍♀️🚣🏿‍♀🏊🏊🏻🏊🏼🏊🏽🏊🏾🏊🏿🏊‍♂️🏊‍♂🏊🏻‍♂️🏊🏻‍♂🏊🏼‍♂️🏊🏼‍♂🏊🏽‍♂️🏊🏽‍♂🏊🏾‍♂️🏊🏾‍♂🏊🏿‍♂️🏊🏿‍♂🏊‍♀️🏊‍♀🏊🏻‍♀️🏊🏻‍♀🏊🏼‍♀️🏊🏼‍♀🏊🏽‍♀️🏊🏽‍♀🏊🏾‍♀️🏊🏾‍♀🏊🏿‍♀️🏊🏿‍♀⛹️⛹⛹🏻⛹🏼⛹🏽⛹🏾⛹🏿⛹️‍♂️⛹‍♂️⛹️‍♂⛹‍♂⛹🏻‍♂️⛹🏻‍♂⛹🏼‍♂️⛹🏼‍♂⛹🏽‍♂️⛹🏽‍♂⛹🏾‍♂️⛹🏾‍♂⛹🏿‍♂️⛹🏿‍♂⛹️‍♀️⛹‍♀️⛹️‍♀⛹‍♀⛹🏻‍♀️⛹🏻‍♀⛹🏼‍♀️⛹🏼‍♀⛹🏽‍♀️⛹🏽‍♀⛹🏾‍♀️⛹🏾‍♀⛹🏿‍♀️⛹🏿‍♀🏋️🏋🏋🏻🏋🏼🏋🏽🏋🏾🏋🏿🏋️‍♂️🏋‍♂️🏋️‍♂🏋‍♂🏋🏻‍♂️🏋🏻‍♂🏋🏼‍♂️🏋🏼‍♂🏋🏽‍♂️🏋🏽‍♂🏋🏾‍♂️🏋🏾‍♂🏋🏿‍♂️🏋🏿‍♂🏋️‍♀️🏋‍♀️🏋️‍♀🏋‍♀🏋🏻‍♀️🏋🏻‍♀🏋🏼‍♀️🏋🏼‍♀🏋🏽‍♀️🏋🏽‍♀🏋🏾‍♀️🏋🏾‍♀🏋🏿‍♀️🏋🏿‍♀🚴🚴🏻🚴🏼🚴🏽🚴🏾🚴🏿🚴‍♂️🚴‍♂🚴🏻‍♂️🚴🏻‍♂🚴🏼‍♂️🚴🏼‍♂🚴🏽‍♂️🚴🏽‍♂🚴🏾‍♂️🚴🏾‍♂🚴🏿‍♂️🚴🏿‍♂🚴‍♀️🚴‍♀🚴🏻‍♀️🚴🏻‍♀🚴🏼‍♀️🚴🏼‍♀🚴🏽‍♀️🚴🏽‍♀🚴🏾‍♀️🚴🏾‍♀🚴🏿‍♀️🚴🏿‍♀🚵🚵🏻🚵🏼🚵🏽🚵🏾🚵🏿🚵‍♂️🚵‍♂🚵🏻‍♂️🚵🏻‍♂🚵🏼‍♂️🚵🏼‍♂🚵🏽‍♂️🚵🏽‍♂🚵🏾‍♂️🚵🏾‍♂🚵🏿‍♂️🚵🏿‍♂🚵‍♀️🚵‍♀🚵🏻‍♀️🚵🏻‍♀🚵🏼‍♀️🚵🏼‍♀🚵🏽‍♀️🚵🏽‍♀🚵🏾‍♀️🚵🏾‍♀🚵🏿‍♀️🚵🏿‍♀🏎️🏎🏍️🏍🤸🤸🏻🤸🏼🤸🏽🤸🏾🤸🏿🤸‍♂️🤸‍♂🤸🏻‍♂️🤸🏻‍♂🤸🏼‍♂️🤸🏼‍♂🤸🏽‍♂️🤸🏽‍♂🤸🏾‍♂️🤸🏾‍♂🤸🏿‍♂️🤸🏿‍♂🤸‍♀️🤸‍♀🤸🏻‍♀️🤸🏻‍♀🤸🏼‍♀️🤸🏼‍♀🤸🏽‍♀️🤸🏽‍♀🤸🏾‍♀️🤸🏾‍♀🤸🏿‍♀️🤸🏿‍♀🤼🤼‍♂️🤼‍♂🤼‍♀️🤼‍♀🤽🤽🏻🤽🏼🤽🏽🤽🏾🤽🏿🤽‍♂️🤽‍♂🤽🏻‍♂️🤽🏻‍♂🤽🏼‍♂️🤽🏼‍♂🤽🏽‍♂️🤽🏽‍♂🤽🏾‍♂️🤽🏾‍♂🤽🏿‍♂️🤽🏿‍♂🤽‍♀️🤽‍♀🤽🏻‍♀️🤽🏻‍♀🤽🏼‍♀️🤽🏼‍♀🤽🏽‍♀️🤽🏽‍♀🤽🏾‍♀️🤽🏾‍♀🤽🏿‍♀️🤽🏿‍♀🤾🤾🏻🤾🏼🤾🏽🤾🏾🤾🏿🤾‍♂️🤾‍♂🤾🏻‍♂️🤾🏻‍♂🤾🏼‍♂️🤾🏼‍♂🤾🏽‍♂️🤾🏽‍♂🤾🏾‍♂️🤾🏾‍♂🤾🏿‍♂️🤾🏿‍♂🤾‍♀️🤾‍♀🤾🏻‍♀️🤾🏻‍♀🤾🏼‍♀️🤾🏼‍♀🤾🏽‍♀️🤾🏽‍♀🤾🏾‍♀️🤾🏾‍♀🤾🏿‍♀️🤾🏿‍♀🤹🤹🏻🤹🏼🤹🏽🤹🏾🤹🏿🤹‍♂️🤹‍♂🤹🏻‍♂️🤹🏻‍♂🤹🏼‍♂️🤹🏼‍♂🤹🏽‍♂️🤹🏽‍♂🤹🏾‍♂️🤹🏾‍♂🤹🏿‍♂️🤹🏿‍♂🤹‍♀️🤹‍♀🤹🏻‍♀️🤹🏻‍♀🤹🏼‍♀️🤹🏼‍♀🤹🏽‍♀️🤹🏽‍♀🤹🏾‍♀️🤹🏾‍♀🤹🏿‍♀️🤹🏿‍♀👫👬👭💏👩‍❤️‍💋‍👨👩‍❤‍💋‍👨👨‍❤️‍💋‍👨👨‍❤‍💋‍👨👩‍❤️‍💋‍👩👩‍❤‍💋‍👩💑👩‍❤️‍👨👩‍❤‍👨👨‍❤️‍👨👨‍❤‍👨👩‍❤️‍👩👩‍❤‍👩👪👨‍👩‍👦👨‍👩‍👧👨‍👩‍👧‍👦👨‍👩‍👦‍👦👨‍👩‍👧‍👧👨‍👨‍👦👨‍👨‍👧👨‍👨‍👧‍👦👨‍👨‍👦‍👦👨‍👨‍👧‍👧👩‍👩‍👦👩‍👩‍👧👩‍👩‍👧‍👦👩‍👩‍👦‍👦👩‍👩‍👧‍👧👨‍👦👨‍👦‍👦👨‍👧👨‍👧‍👦👨‍👧‍👧👩‍👦👩‍👦‍👦👩‍👧👩‍👧‍👦👩‍👧‍👧🤳🤳🏻🤳🏼🤳🏽🤳🏾🤳🏿💪💪🏻💪🏼💪🏽💪🏾💪🏿🦵🦵🏻🦵🏼🦵🏽🦵🏾🦵🏿🦶🦶🏻🦶🏼🦶🏽🦶🏾🦶🏿👈👈🏻👈🏼👈🏽👈🏾👈🏿👉👉🏻👉🏼👉🏽👉🏾👉🏿☝️☝☝🏻☝🏼☝🏽☝🏾☝🏿👆👆🏻👆🏼👆🏽👆🏾👆🏿🖕🖕🏻🖕🏼🖕🏽🖕🏾🖕🏿👇👇🏻👇🏼👇🏽👇🏾👇🏿✌️✌✌🏻✌🏼✌🏽✌🏾✌🏿🤞🤞🏻🤞🏼🤞🏽🤞🏾🤞🏿🖖🖖🏻🖖🏼🖖🏽🖖🏾🖖🏿🤘🤘🏻🤘🏼🤘🏽🤘🏾🤘🏿🤙🤙🏻🤙🏼🤙🏽🤙🏾🤙🏿🖐️🖐🖐🏻🖐🏼🖐🏽🖐🏾🖐🏿✋✋🏻✋🏼✋🏽✋🏾✋🏿👌👌🏻👌🏼👌🏽👌🏾👌🏿👍👍🏻👍🏼👍🏽👍🏾👍🏿👎👎🏻👎🏼👎🏽👎🏾👎🏿✊✊🏻✊🏼✊🏽✊🏾✊🏿👊👊🏻👊🏼👊🏽👊🏾👊🏿🤛🤛🏻🤛🏼🤛🏽🤛🏾🤛🏿🤜🤜🏻🤜🏼🤜🏽🤜🏾🤜🏿🤚🤚🏻🤚🏼🤚🏽🤚🏾🤚🏿👋👋🏻👋🏼👋🏽👋🏾👋🏿🤟🤟🏻🤟🏼🤟🏽🤟🏾🤟🏿✍️✍✍🏻✍🏼✍🏽✍🏾✍🏿👏👏🏻👏🏼👏🏽👏🏾👏🏿👐👐🏻👐🏼👐🏽👐🏾👐🏿🙌🙌🏻🙌🏼🙌🏽🙌🏾🙌🏿🤲🤲🏻🤲🏼🤲🏽🤲🏾🤲🏿🙏🙏🏻🙏🏼🙏🏽🙏🏾🙏🏿🤝💅💅🏻💅🏼💅🏽💅🏾💅🏿👂👂🏻👂🏼👂🏽👂🏾👂🏿👃👃🏻👃🏼👃🏽👃🏾👃🏿🦰🦱🦲🦳👣👀👁️👁👁️‍🗨️👁‍🗨️👁️‍🗨👁‍🗨🧠🦴🦷👅👄💋💘❤️❤💓💔💕💖💗💙💚💛🧡💜🖤💝💞💟❣️❣💌💤💢💣💥💦💨💫💬🗨️🗨🗯️🗯💭🕳️🕳👓🕶️🕶🥽🥼👔👕👖🧣🧤🧥🧦👗👘👙👚👛👜👝🛍️🛍🎒👞👟🥾🥿👠👡👢👑👒🎩🎓🧢⛑️⛑📿💄💍💎🐵🐒🦍🐶🐕🐩🐺🦊🦝🐱🐈🦁🐯🐅🐆🐴🐎🦄🦓🦌🐮🐂🐃🐄🐷🐖🐗🐽🐏🐑🐐🐪🐫🦙🦒🐘🦏🦛🐭🐁🐀🐹🐰🐇🐿️🐿🦔🦇🐻🐨🐼🦘🦡🐾🦃🐔🐓🐣🐤🐥🐦🐧🕊️🕊🦅🦆🦢🦉🦚🦜🐸🐊🐢🦎🐍🐲🐉🦕🦖🐳🐋🐬🐟🐠🐡🦈🐙🐚🦀🦞🦐🦑🐌🦋🐛🐜🐝🐞🦗🕷️🕷🕸️🕸🦂🦟🦠💐🌸💮🏵️🏵🌹🥀🌺🌻🌼🌷🌱🌲🌳🌴🌵🌾🌿☘️☘🍀🍁🍂🍃🍇🍈🍉🍊🍋🍌🍍🥭🍎🍏🍐🍑🍒🍓🥝🍅🥥🥑🍆🥔🥕🌽🌶️🌶🥒🥬🥦🍄🥜🌰🍞🥐🥖🥨🥯🥞🧀🍖🍗🥩🥓🍔🍟🍕🌭🥪🌮🌯🥙🥚🍳🥘🍲🥣🥗🍿🧂🥫🍱🍘🍙🍚🍛🍜🍝🍠🍢🍣🍤🍥🥮🍡🥟🥠🥡🍦🍧🍨🍩🍪🎂🍰🧁🥧🍫🍬🍭🍮🍯🍼🥛☕🍵🍶🍾🍷🍸🍹🍺🍻🥂🥃🥤🥢🍽️🍽🍴🥄🔪🏺🌍🌎🌏🌐🗺️🗺🗾🧭🏔️🏔⛰️⛰🌋🗻🏕️🏕🏖️🏖🏜️🏜🏝️🏝🏞️🏞🏟️🏟🏛️🏛🏗️🏗🧱🏘️🏘🏚️🏚🏠🏡🏢🏣🏤🏥🏦🏨🏩🏪🏫🏬🏭🏯🏰💒🗼🗽⛪🕌🕍⛩️⛩🕋⛲⛺🌁🌃🏙️🏙🌄🌅🌆🌇🌉♨️♨🌌🎠🎡🎢💈🎪🚂🚃🚄🚅🚆🚇🚈🚉🚊🚝🚞🚋🚌🚍🚎🚐🚑🚒🚓🚔🚕🚖🚗🚘🚙🚚🚛🚜🚲🛴🛹🛵🚏🛣️🛣🛤️🛤🛢️🛢⛽🚨🚥🚦🛑🚧⚓⛵🛶🚤🛳️🛳⛴️⛴🛥️🛥🚢✈️✈🛩️🛩🛫🛬💺🚁🚟🚠🚡🛰️🛰🚀🛸🛎️🛎🧳⌛⏳⌚⏰⏱️⏱⏲️⏲🕰️🕰🕛🕧🕐🕜🕑🕝🕒🕞🕓🕟🕔🕠🕕🕡🕖🕢🕗🕣🕘🕤🕙🕥🕚🕦🌑🌒🌓🌔🌕🌖🌗🌘🌙🌚🌛🌜🌡️🌡☀️☀🌝🌞⭐🌟🌠☁️☁⛅⛈️⛈🌤️🌤🌥️🌥🌦️🌦🌧️🌧🌨️🌨🌩️🌩🌪️🌪🌫️🌫🌬️🌬🌀🌈🌂☂️☂☔⛱️⛱⚡❄️❄☃️☃⛄☄️☄🔥💧🌊🎃🎄🎆🎇🧨✨🎈🎉🎊🎋🎍🎎🎏🎐🎑🧧🎀🎁🎗️🎗🎟️🎟🎫🎖️🎖🏆🏅🥇🥈🥉⚽⚾🥎🏀🏐🏈🏉🎾🥏🎳🏏🏑🏒🥍🏓🏸🥊🥋🥅⛳⛸️⛸🎣🎽🎿🛷🥌🎯🎱🔮🧿🎮🕹️🕹🎰🎲🧩🧸♠️♠♥️♥♦️♦♣️♣♟️♟🃏🀄🎴🎭🖼️🖼🎨🧵🧶🔇🔈🔉🔊📢📣📯🔔🔕🎼🎵🎶🎙️🎙🎚️🎚🎛️🎛🎤🎧📻🎷🎸🎹🎺🎻🥁📱📲☎️☎📞📟📠🔋🔌💻🖥️🖥🖨️🖨⌨️⌨🖱️🖱🖲️🖲💽💾💿📀🧮🎥🎞️🎞📽️📽🎬📺📷📸📹📼🔍🔎🕯️🕯💡🔦🏮📔📕📖📗📘📙📚📓📒📃📜📄📰🗞️🗞📑🔖🏷️🏷💰💴💵💶💷💸💳🧾💹💱💲✉️✉📧📨📩📤📥📦📫📪📬📭📮🗳️🗳✏️✏✒️✒🖋️🖋🖊️🖊🖌️🖌🖍️🖍📝💼📁📂🗂️🗂📅📆🗒️🗒🗓️🗓📇📈📉📊📋📌📍📎🖇️🖇📏📐✂️✂🗃️🗃🗄️🗄🗑️🗑🔒🔓🔏🔐🔑🗝️🗝🔨⛏️⛏⚒️⚒🛠️🛠🗡️🗡⚔️⚔🔫🏹🛡️🛡🔧🔩⚙️⚙🗜️🗜⚖️⚖🔗⛓️⛓🧰🧲⚗️⚗🧪🧫🧬🔬🔭📡💉💊🚪🛏️🛏🛋️🛋🚽🚿🛁🧴🧷🧹🧺🧻🧼🧽🧯🛒🚬⚰️⚰⚱️⚱🗿🏧🚮🚰♿🚹🚺🚻🚼🚾🛂🛃🛄🛅⚠️⚠🚸⛔🚫🚳🚭🚯🚱🚷📵🔞☢️☢☣️☣⬆️⬆↗️↗➡️➡↘️↘⬇️⬇↙️↙⬅️⬅↖️↖↕️↕↔️↔↩️↩↪️↪⤴️⤴⤵️⤵🔃🔄🔙🔚🔛🔜🔝🛐⚛️⚛🕉️🕉✡️✡☸️☸☯️☯✝️✝☦️☦☪️☪☮️☮🕎🔯♈♉♊♋♌♍♎♏♐♑♒♓⛎🔀🔁🔂▶️▶⏩⏭️⏭⏯️⏯◀️◀⏪⏮️⏮🔼⏫🔽⏬⏸️⏸⏹️⏹⏺️⏺⏏️⏏🎦🔅🔆📶📳📴♀️♀♂️♂⚕️⚕♾️♾♻️♻⚜️⚜🔱📛🔰⭕✅☑️☑✔️✔✖️✖❌❎➕➖➗➰➿〽️〽✳️✳✴️✴❇️❇‼️‼⁉️⁉❓❔❕❗〰️〰©️©®️®™️™#️⃣#⃣*️⃣*⃣0️⃣0⃣1️⃣1⃣2️⃣2⃣3️⃣3⃣4️⃣4⃣5️⃣5⃣6️⃣6⃣7️⃣7⃣8️⃣8⃣9️⃣9⃣🔟💯🔠🔡🔢🔣🔤🅰️🅰🆎🅱️🅱🆑🆒🆓ℹ️ℹ🆔Ⓜ️Ⓜ🆕🆖🅾️🅾🆗🅿️🅿🆘🆙🆚🈁🈂️🈂🈷️🈷🈶🈯🉐🈹🈚🈲🉑🈸🈴🈳㊗️㊗㊙️㊙🈺🈵▪️▪▫️▫◻️◻◼️◼◽◾⬛⬜🔶🔷🔸🔹🔺🔻💠🔘🔲🔳⚪⚫🔴🔵🏁🚩🎌🏴🏳️🏳🏳️‍🌈🏳‍🌈🏴‍☠️🏴‍☠🇦🇨🇦🇩🇦🇪🇦🇫🇦🇬🇦🇮🇦🇱🇦🇲🇦🇴🇦🇶🇦🇷🇦🇸🇦🇹🇦🇺🇦🇼🇦🇽🇦🇿🇧🇦🇧🇧🇧🇩🇧🇪🇧🇫🇧🇬🇧🇭🇧🇮🇧🇯🇧🇱🇧🇲🇧🇳🇧🇴🇧🇶🇧🇷🇧🇸🇧🇹🇧🇻🇧🇼🇧🇾🇧🇿🇨🇦🇨🇨🇨🇩🇨🇫🇨🇬🇨🇭🇨🇮🇨🇰🇨🇱🇨🇲🇨🇳🇨🇴🇨🇵🇨🇷🇨🇺🇨🇻🇨🇼🇨🇽🇨🇾🇨🇿🇩🇪🇩🇬🇩🇯🇩🇰🇩🇲🇩🇴🇩🇿🇪🇦🇪🇨🇪🇪🇪🇬🇪🇭🇪🇷🇪🇸🇪🇹🇪🇺🇫🇮🇫🇯🇫🇰🇫🇲🇫🇴🇫🇷🇬🇦🇬🇧🇬🇩🇬🇪🇬🇫🇬🇬🇬🇭🇬🇮🇬🇱🇬🇲🇬🇳🇬🇵🇬🇶🇬🇷🇬🇸🇬🇹🇬🇺🇬🇼🇬🇾🇭🇰🇭🇲🇭🇳🇭🇷🇭🇹🇭🇺🇮🇨🇮🇩🇮🇪🇮🇱🇮🇲🇮🇳🇮🇴🇮🇶🇮🇷🇮🇸🇮🇹🇯🇪🇯🇲🇯🇴🇯🇵🇰🇪🇰🇬🇰🇭🇰🇮🇰🇲🇰🇳🇰🇵🇰🇷🇰🇼🇰🇾🇰🇿🇱🇦🇱🇧🇱🇨🇱🇮🇱🇰🇱🇷🇱🇸🇱🇹🇱🇺🇱🇻🇱🇾🇲🇦🇲🇨🇲🇩🇲🇪🇲🇫🇲🇬🇲🇭🇲🇰🇲🇱🇲🇲🇲🇳🇲🇴🇲🇵🇲🇶🇲🇷🇲🇸🇲🇹🇲🇺🇲🇻🇲🇼🇲🇽🇲🇾🇲🇿🇳🇦🇳🇨🇳🇪🇳🇫🇳🇬🇳🇮🇳🇱🇳🇴🇳🇵🇳🇷🇳🇺🇳🇿🇴🇲🇵🇦🇵🇪🇵🇫🇵🇬🇵🇭🇵🇰🇵🇱🇵🇲🇵🇳🇵🇷🇵🇸🇵🇹🇵🇼🇵🇾🇶🇦🇷🇪🇷🇴🇷🇸🇷🇺🇷🇼🇸🇦🇸🇧🇸🇨🇸🇩🇸🇪🇸🇬🇸🇭🇸🇮🇸🇯🇸🇰🇸🇱🇸🇲🇸🇳🇸🇴🇸🇷🇸🇸🇸🇹🇸🇻🇸🇽🇸🇾🇸🇿🇹🇦🇹🇨🇹🇩🇹🇫🇹🇬🇹🇭🇹🇯🇹🇰🇹🇱🇹🇲🇹🇳🇹🇴🇹🇷🇹🇹🇹🇻🇹🇼🇹🇿🇺🇦🇺🇬🇺🇲🇺🇳🇺🇸🇺🇾🇺🇿🇻🇦🇻🇨🇻🇪🇻🇬🇻🇮🇻🇳🇻🇺🇼🇫🇼🇸🇽🇰🇾🇪🇾🇹🇿🇦🇿🇲🇿🇼🏴󠁧󠁢󠁥󠁮󠁧󠁿🏴󠁧󠁢󠁳󠁣󠁴󠁿🏴󠁧󠁢󠁷󠁬󠁳󠁿" + ); + expect(() => emoji.parse(":-)")).toThrow(); + expect(() => emoji.parse("😀 is an emoji")).toThrow(); + expect(() => emoji.parse("😀stuff")).toThrow(); + expect(() => emoji.parse("stuff😀")).toThrow(); +}); + +test("uuid", () => { + const uuid = z.string().uuid("custom error"); + uuid.parse("9491d710-3185-4e06-bea0-6a2f275345e0"); + uuid.parse("d89e7b01-7598-ed11-9d7a-0022489382fd"); // new sequential id + uuid.parse("00000000-0000-0000-0000-000000000000"); + uuid.parse("b3ce60f8-e8b9-40f5-1150-172ede56ff74"); // Variant 0 - RFC 9562/4122: Reserved, NCS backward compatibility + uuid.parse("92e76bf9-28b3-4730-cd7f-cb6bc51f8c09"); // Variant 2 - RFC 9562/4122: Reserved, Microsoft Corporation backward compatibility + const result = uuid.safeParse("9491d710-3185-4e06-bea0-6a2f275345e0X"); + expect(result.success).toEqual(false); + if (!result.success) { + expect(result.error.issues[0].message).toEqual("custom error"); + } +}); + +test("bad uuid", () => { + const uuid = z.string().uuid("custom error"); + uuid.parse("9491d710-3185-4e06-bea0-6a2f275345e0"); + const result = uuid.safeParse("invalid uuid"); + expect(result.success).toEqual(false); + if (!result.success) { + expect(result.error.issues[0].message).toEqual("custom error"); + } +}); + +test("nanoid", () => { + const nanoid = z.string().nanoid("custom error"); + nanoid.parse("lfNZluvAxMkf7Q8C5H-QS"); + nanoid.parse("mIU_4PJWikaU8fMbmkouz"); + nanoid.parse("Hb9ZUtUa2JDm_dD-47EGv"); + nanoid.parse("5Noocgv_8vQ9oPijj4ioQ"); + const result = nanoid.safeParse("Xq90uDyhddC53KsoASYJGX"); + expect(result.success).toEqual(false); + if (!result.success) { + expect(result.error.issues[0].message).toEqual("custom error"); + } +}); + +test("bad nanoid", () => { + const nanoid = z.string().nanoid("custom error"); + nanoid.parse("ySh_984wpDUu7IQRrLXAp"); + const result = nanoid.safeParse("invalid nanoid"); + expect(result.success).toEqual(false); + if (!result.success) { + expect(result.error.issues[0].message).toEqual("custom error"); + } +}); + +test("cuid", () => { + const cuid = z.string().cuid(); + cuid.parse("ckopqwooh000001la8mbi2im9"); + const result = cuid.safeParse("cifjhdsfhsd-invalid-cuid"); + expect(result.success).toEqual(false); + if (!result.success) { + expect(result.error.issues[0].message).toEqual("Invalid cuid"); + } +}); + +test("cuid2", () => { + const cuid2 = z.string().cuid2(); + const validStrings = [ + "a", // short string + "tz4a98xxat96iws9zmbrgj3a", // normal string + "kf5vz6ssxe4zjcb409rjgo747tc5qjazgptvotk6", // longer than require("@paralleldrive/cuid2").bigLength + ]; + for (const s of validStrings) { + cuid2.parse(s); + } + + const invalidStrings = [ + "", // empty string + "tz4a98xxat96iws9zMbrgj3a", // include uppercase + "tz4a98xxat96iws-zmbrgj3a", // involve symbols + ]; + const results = invalidStrings.map((s) => cuid2.safeParse(s)); + expect(results.every((r) => !r.success)).toEqual(true); + if (!results[0].success) { + expect(results[0].error.issues[0].message).toEqual("Invalid cuid2"); + } +}); + +test("ulid", () => { + const ulid = z.string().ulid(); + ulid.parse("01ARZ3NDEKTSV4RRFFQ69G5FAV"); + const result = ulid.safeParse("invalidulid"); + expect(result.success).toEqual(false); + const tooLong = "01ARZ3NDEKTSV4RRFFQ69G5FAVA"; + expect(ulid.safeParse(tooLong).success).toEqual(false); + if (!result.success) { + expect(result.error.issues[0].message).toEqual("Invalid ulid"); + } + const caseInsensitive = ulid.safeParse("01arZ3nDeKTsV4RRffQ69G5FAV"); + expect(caseInsensitive.success).toEqual(true); +}); + +test("regex", () => { + z.string() + .regex(/^moo+$/) + .parse("mooooo"); + expect(() => z.string().uuid().parse("purr")).toThrow(); +}); + +test("regexp error message", () => { + const result = z + .string() + .regex(/^moo+$/) + .safeParse("boooo"); + if (!result.success) { + expect(result.error.issues[0].message).toEqual("Invalid"); + } else { + throw new Error("validation should have failed"); + } + + expect(() => z.string().uuid().parse("purr")).toThrow(); +}); + +test("regex lastIndex reset", () => { + const schema = z.string().regex(/^\d+$/g); + expect(schema.safeParse("123").success).toEqual(true); + expect(schema.safeParse("123").success).toEqual(true); + expect(schema.safeParse("123").success).toEqual(true); + expect(schema.safeParse("123").success).toEqual(true); + expect(schema.safeParse("123").success).toEqual(true); +}); + +test("checks getters", () => { + expect(z.string().email().isEmail).toEqual(true); + expect(z.string().email().isURL).toEqual(false); + expect(z.string().email().isCUID).toEqual(false); + expect(z.string().email().isCUID2).toEqual(false); + expect(z.string().email().isUUID).toEqual(false); + expect(z.string().email().isNANOID).toEqual(false); + expect(z.string().email().isIP).toEqual(false); + expect(z.string().email().isCIDR).toEqual(false); + expect(z.string().email().isULID).toEqual(false); + + expect(z.string().url().isEmail).toEqual(false); + expect(z.string().url().isURL).toEqual(true); + expect(z.string().url().isCUID).toEqual(false); + expect(z.string().url().isCUID2).toEqual(false); + expect(z.string().url().isUUID).toEqual(false); + expect(z.string().url().isNANOID).toEqual(false); + expect(z.string().url().isIP).toEqual(false); + expect(z.string().url().isCIDR).toEqual(false); + expect(z.string().url().isULID).toEqual(false); + + expect(z.string().cuid().isEmail).toEqual(false); + expect(z.string().cuid().isURL).toEqual(false); + expect(z.string().cuid().isCUID).toEqual(true); + expect(z.string().cuid().isCUID2).toEqual(false); + expect(z.string().cuid().isUUID).toEqual(false); + expect(z.string().cuid().isNANOID).toEqual(false); + expect(z.string().cuid().isIP).toEqual(false); + expect(z.string().cuid().isCIDR).toEqual(false); + expect(z.string().cuid().isULID).toEqual(false); + + expect(z.string().cuid2().isEmail).toEqual(false); + expect(z.string().cuid2().isURL).toEqual(false); + expect(z.string().cuid2().isCUID).toEqual(false); + expect(z.string().cuid2().isCUID2).toEqual(true); + expect(z.string().cuid2().isUUID).toEqual(false); + expect(z.string().cuid2().isNANOID).toEqual(false); + expect(z.string().cuid2().isIP).toEqual(false); + expect(z.string().cuid2().isCIDR).toEqual(false); + expect(z.string().cuid2().isULID).toEqual(false); + + expect(z.string().uuid().isEmail).toEqual(false); + expect(z.string().uuid().isURL).toEqual(false); + expect(z.string().uuid().isCUID).toEqual(false); + expect(z.string().uuid().isCUID2).toEqual(false); + expect(z.string().uuid().isUUID).toEqual(true); + expect(z.string().uuid().isNANOID).toEqual(false); + expect(z.string().uuid().isIP).toEqual(false); + expect(z.string().uuid().isCIDR).toEqual(false); + expect(z.string().uuid().isULID).toEqual(false); + + expect(z.string().nanoid().isEmail).toEqual(false); + expect(z.string().nanoid().isURL).toEqual(false); + expect(z.string().nanoid().isCUID).toEqual(false); + expect(z.string().nanoid().isCUID2).toEqual(false); + expect(z.string().nanoid().isUUID).toEqual(false); + expect(z.string().nanoid().isNANOID).toEqual(true); + expect(z.string().nanoid().isIP).toEqual(false); + expect(z.string().nanoid().isCIDR).toEqual(false); + expect(z.string().nanoid().isULID).toEqual(false); + + expect(z.string().ip().isEmail).toEqual(false); + expect(z.string().ip().isURL).toEqual(false); + expect(z.string().ip().isCUID).toEqual(false); + expect(z.string().ip().isCUID2).toEqual(false); + expect(z.string().ip().isUUID).toEqual(false); + expect(z.string().ip().isNANOID).toEqual(false); + expect(z.string().ip().isIP).toEqual(true); + expect(z.string().ip().isCIDR).toEqual(false); + expect(z.string().ip().isULID).toEqual(false); + + expect(z.string().cidr().isEmail).toEqual(false); + expect(z.string().cidr().isURL).toEqual(false); + expect(z.string().cidr().isCUID).toEqual(false); + expect(z.string().cidr().isCUID2).toEqual(false); + expect(z.string().cidr().isUUID).toEqual(false); + expect(z.string().cidr().isNANOID).toEqual(false); + expect(z.string().cidr().isIP).toEqual(false); + expect(z.string().cidr().isCIDR).toEqual(true); + expect(z.string().cidr().isULID).toEqual(false); + + expect(z.string().ulid().isEmail).toEqual(false); + expect(z.string().ulid().isURL).toEqual(false); + expect(z.string().ulid().isCUID).toEqual(false); + expect(z.string().ulid().isCUID2).toEqual(false); + expect(z.string().ulid().isUUID).toEqual(false); + expect(z.string().ulid().isNANOID).toEqual(false); + expect(z.string().ulid().isIP).toEqual(false); + expect(z.string().ulid().isCIDR).toEqual(false); + expect(z.string().ulid().isULID).toEqual(true); +}); + +test("min max getters", () => { + expect(z.string().min(5).minLength).toEqual(5); + expect(z.string().min(5).min(10).minLength).toEqual(10); + expect(z.string().minLength).toEqual(null); + + expect(z.string().max(5).maxLength).toEqual(5); + expect(z.string().max(5).max(1).maxLength).toEqual(1); + expect(z.string().maxLength).toEqual(null); +}); + +test("trim", () => { + expect(z.string().trim().min(2).parse(" 12 ")).toEqual("12"); + + // ordering of methods is respected + expect(z.string().min(2).trim().parse(" 1 ")).toEqual("1"); + expect(() => z.string().trim().min(2).parse(" 1 ")).toThrow(); +}); + +test("lowerCase", () => { + expect(z.string().toLowerCase().parse("ASDF")).toEqual("asdf"); + expect(z.string().toUpperCase().parse("asdf")).toEqual("ASDF"); +}); + +test("datetime", () => { + const a = z.string().datetime({}); + expect(a.isDatetime).toEqual(true); + + const b = z.string().datetime({ offset: true }); + expect(b.isDatetime).toEqual(true); + + const c = z.string().datetime({ precision: 3 }); + expect(c.isDatetime).toEqual(true); + + const d = z.string().datetime({ offset: true, precision: 0 }); + expect(d.isDatetime).toEqual(true); + + const { isDatetime } = z.string().datetime(); + expect(isDatetime).toEqual(true); +}); + +test("datetime parsing", () => { + const datetime = z.string().datetime(); + datetime.parse("1970-01-01T00:00:00.000Z"); + datetime.parse("2022-10-13T09:52:31.816Z"); + datetime.parse("2022-10-13T09:52:31.8162314Z"); + datetime.parse("1970-01-01T00:00:00Z"); + datetime.parse("2022-10-13T09:52:31Z"); + datetime.parse("2022-10-13T09:52Z"); + expect(() => datetime.parse("")).toThrow(); + expect(() => datetime.parse("foo")).toThrow(); + expect(() => datetime.parse("2020-10-14")).toThrow(); + expect(() => datetime.parse("T18:45:12.123")).toThrow(); + expect(() => datetime.parse("2020-10-14T17:42:29+00:00")).toThrow(); + expect(() => datetime.parse("2020-10-14T17:42.123+00:00")).toThrow(); + + const datetimeNoMs = z.string().datetime({ precision: 0 }); + datetimeNoMs.parse("1970-01-01T00:00:00Z"); + datetimeNoMs.parse("2022-10-13T09:52:31Z"); + datetimeNoMs.parse("2022-10-13T09:52Z"); + expect(() => datetimeNoMs.parse("tuna")).toThrow(); + expect(() => datetimeNoMs.parse("1970-01-01T00:00:00.000Z")).toThrow(); + expect(() => datetimeNoMs.parse("1970-01-01T00:00:00.Z")).toThrow(); + expect(() => datetimeNoMs.parse("2022-10-13T09:52:31.816Z")).toThrow(); + + const datetime3Ms = z.string().datetime({ precision: 3 }); + datetime3Ms.parse("1970-01-01T00:00:00.000Z"); + datetime3Ms.parse("2022-10-13T09:52:31.123Z"); + expect(() => datetime3Ms.parse("tuna")).toThrow(); + expect(() => datetime3Ms.parse("1970-01-01T00:00:00.1Z")).toThrow(); + expect(() => datetime3Ms.parse("1970-01-01T00:00:00.12Z")).toThrow(); + expect(() => datetime3Ms.parse("2022-10-13T09:52:31Z")).toThrow(); + expect(() => datetime3Ms.parse("2022-10-13T09:52Z")).toThrow(); + + const datetimeOffset = z.string().datetime({ offset: true }); + datetimeOffset.parse("1970-01-01T00:00:00.000Z"); + datetimeOffset.parse("2022-10-13T09:52:31.816234134Z"); + datetimeOffset.parse("1970-01-01T00:00:00Z"); + datetimeOffset.parse("2022-10-13T09:52:31.4Z"); + datetimeOffset.parse("2020-10-14T17:42:29+00:00"); + datetimeOffset.parse("2020-10-14T17:42:29+03:15"); + datetimeOffset.parse("2020-10-14T17:42:29+0315"); + datetimeOffset.parse("2020-10-14T17:42+0315"); + expect(() => datetimeOffset.parse("2020-10-14T17:42:29+03")); + expect(() => datetimeOffset.parse("tuna")).toThrow(); + expect(() => datetimeOffset.parse("2022-10-13T09:52:31.Z")).toThrow(); + + const datetimeOffsetNoMs = z.string().datetime({ offset: true, precision: 0 }); + datetimeOffsetNoMs.parse("1970-01-01T00:00:00Z"); + datetimeOffsetNoMs.parse("2022-10-13T09:52:31Z"); + datetimeOffsetNoMs.parse("2020-10-14T17:42:29+00:00"); + datetimeOffsetNoMs.parse("2020-10-14T17:42:29+0000"); + datetimeOffsetNoMs.parse("2020-10-14T17:42+0000"); + expect(() => datetimeOffsetNoMs.parse("2020-10-14T17:42:29+00")).toThrow(); + expect(() => datetimeOffsetNoMs.parse("tuna")).toThrow(); + expect(() => datetimeOffsetNoMs.parse("1970-01-01T00:00:00.000Z")).toThrow(); + expect(() => datetimeOffsetNoMs.parse("1970-01-01T00:00:00.Z")).toThrow(); + expect(() => datetimeOffsetNoMs.parse("2022-10-13T09:52:31.816Z")).toThrow(); + expect(() => datetimeOffsetNoMs.parse("2020-10-14T17:42:29.124+00:00")).toThrow(); + + const datetimeOffset4Ms = z.string().datetime({ offset: true, precision: 4 }); + datetimeOffset4Ms.parse("1970-01-01T00:00:00.1234Z"); + datetimeOffset4Ms.parse("2020-10-14T17:42:29.1234+00:00"); + datetimeOffset4Ms.parse("2020-10-14T17:42:29.1234+0000"); + expect(() => datetimeOffset4Ms.parse("2020-10-14T17:42:29.1234+00")).toThrow(); + expect(() => datetimeOffset4Ms.parse("tuna")).toThrow(); + expect(() => datetimeOffset4Ms.parse("1970-01-01T00:00:00.123Z")).toThrow(); + expect(() => datetimeOffset4Ms.parse("2020-10-14T17:42:29.124+00:00")).toThrow(); + expect(() => datetimeOffset4Ms.parse("2020-10-14T17:42+00:00")).toThrow(); +}); + +test("date", () => { + const a = z.string().date(); + expect(a.isDate).toEqual(true); +}); + +test("date parsing", () => { + const date = z.string().date(); + date.parse("1970-01-01"); + date.parse("2022-01-31"); + date.parse("2022-03-31"); + date.parse("2022-04-30"); + date.parse("2022-05-31"); + date.parse("2022-06-30"); + date.parse("2022-07-31"); + date.parse("2022-08-31"); + date.parse("2022-09-30"); + date.parse("2022-10-31"); + date.parse("2022-11-30"); + date.parse("2022-12-31"); + + date.parse("2000-02-29"); + date.parse("2400-02-29"); + expect(() => date.parse("2022-02-29")).toThrow(); + expect(() => date.parse("2100-02-29")).toThrow(); + expect(() => date.parse("2200-02-29")).toThrow(); + expect(() => date.parse("2300-02-29")).toThrow(); + expect(() => date.parse("2500-02-29")).toThrow(); + + expect(() => date.parse("")).toThrow(); + expect(() => date.parse("foo")).toThrow(); + expect(() => date.parse("200-01-01")).toThrow(); + expect(() => date.parse("20000-01-01")).toThrow(); + expect(() => date.parse("2000-0-01")).toThrow(); + expect(() => date.parse("2000-011-01")).toThrow(); + expect(() => date.parse("2000-01-0")).toThrow(); + expect(() => date.parse("2000-01-011")).toThrow(); + expect(() => date.parse("2000/01/01")).toThrow(); + expect(() => date.parse("01-01-2022")).toThrow(); + expect(() => date.parse("01/01/2022")).toThrow(); + expect(() => date.parse("2000-01-01 00:00:00Z")).toThrow(); + expect(() => date.parse("2020-10-14T17:42:29+00:00")).toThrow(); + expect(() => date.parse("2020-10-14T17:42:29Z")).toThrow(); + expect(() => date.parse("2020-10-14T17:42:29")).toThrow(); + expect(() => date.parse("2020-10-14T17:42:29.123Z")).toThrow(); + + expect(() => date.parse("2000-00-12")).toThrow(); + expect(() => date.parse("2000-12-00")).toThrow(); + expect(() => date.parse("2000-01-32")).toThrow(); + expect(() => date.parse("2000-13-01")).toThrow(); + expect(() => date.parse("2000-21-01")).toThrow(); + + expect(() => date.parse("2000-02-30")).toThrow(); + expect(() => date.parse("2000-02-31")).toThrow(); + expect(() => date.parse("2000-04-31")).toThrow(); + expect(() => date.parse("2000-06-31")).toThrow(); + expect(() => date.parse("2000-09-31")).toThrow(); + expect(() => date.parse("2000-11-31")).toThrow(); +}); + +test("time", () => { + const a = z.string().time(); + expect(a.isTime).toEqual(true); +}); + +test("time parsing", () => { + const time = z.string().time(); + time.parse("00:00:00"); + time.parse("23:00:00"); + time.parse("00:59:00"); + time.parse("00:00:59"); + time.parse("23:59:59"); + time.parse("09:52:31"); + time.parse("23:59:59.9999999"); + time.parse("23:59"); + expect(() => time.parse("")).toThrow(); + expect(() => time.parse("foo")).toThrow(); + expect(() => time.parse("00:00:00Z")).toThrow(); + expect(() => time.parse("0:00:00")).toThrow(); + expect(() => time.parse("00:0:00")).toThrow(); + expect(() => time.parse("00:00:0")).toThrow(); + expect(() => time.parse("00:00:00.000+00:00")).toThrow(); + + expect(() => time.parse("24:00:00")).toThrow(); + expect(() => time.parse("00:60:00")).toThrow(); + expect(() => time.parse("00:00:60")).toThrow(); + expect(() => time.parse("24:60:60")).toThrow(); + expect(() => time.parse("24:60")).toThrow(); + + const time2 = z.string().time({ precision: 2 }); + time2.parse("00:00:00.00"); + time2.parse("09:52:31.12"); + time2.parse("23:59:59.99"); + expect(() => time2.parse("")).toThrow(); + expect(() => time2.parse("foo")).toThrow(); + expect(() => time2.parse("00:00:00")).toThrow(); + expect(() => time2.parse("00:00:00.00Z")).toThrow(); + expect(() => time2.parse("00:00:00.0")).toThrow(); + expect(() => time2.parse("00:00:00.000")).toThrow(); + expect(() => time2.parse("00:00:00.00+00:00")).toThrow(); + expect(() => time2.parse("23:59")).toThrow(); + + // const time3 = z.string().time({ offset: true }); + // time3.parse("00:00:00Z"); + // time3.parse("09:52:31Z"); + // time3.parse("00:00:00+00:00"); + // time3.parse("00:00:00+0000"); + // time3.parse("00:00:00.000Z"); + // time3.parse("00:00:00.000+00:00"); + // time3.parse("00:00:00.000+0000"); + // expect(() => time3.parse("")).toThrow(); + // expect(() => time3.parse("foo")).toThrow(); + // expect(() => time3.parse("00:00:00")).toThrow(); + // expect(() => time3.parse("00:00:00.000")).toThrow(); + + // const time4 = z.string().time({ offset: true, precision: 0 }); + // time4.parse("00:00:00Z"); + // time4.parse("09:52:31Z"); + // time4.parse("00:00:00+00:00"); + // time4.parse("00:00:00+0000"); + // expect(() => time4.parse("")).toThrow(); + // expect(() => time4.parse("foo")).toThrow(); + // expect(() => time4.parse("00:00:00.0")).toThrow(); + // expect(() => time4.parse("00:00:00.000")).toThrow(); + // expect(() => time4.parse("00:00:00.000+00:00")).toThrow(); +}); + +test("duration", () => { + const duration = z.string().duration(); + expect(duration.isDuration).toEqual(true); + + const validDurations = [ + "P3Y6M4DT12H30M5S", + "P2Y9M3DT12H31M8.001S", + "+P3Y6M4DT12H30M5S", + "-PT0.001S", + "+PT0.001S", + "PT0,001S", + "PT12H30M5S", + "-P2M1D", + "P-2M-1D", + "-P5DT10H", + "P-5DT-10H", + "P1Y", + "P2MT30M", + "PT6H", + "P5W", + "P0.5Y", + "P0,5Y", + "P42YT7.004M", + ]; + + const invalidDurations = ["foo bar", "", " ", "P", "T1H", "P0.5Y1D", "P0,5Y6M", "P1YT"]; + + for (const val of validDurations) { + const result = duration.safeParse(val); + if (!result.success) { + throw Error(`Valid duration could not be parsed: ${val}`); + } + } + + for (const val of invalidDurations) { + const result = duration.safeParse(val); + + if (result.success) { + throw Error(`Invalid duration was successful parsed: ${val}`); + } + + expect(result.error.issues[0].message).toEqual("Invalid duration"); + } +}); + +test("IP validation", () => { + const ip = z.string().ip(); + expect(ip.safeParse("122.122.122.122").success).toBe(true); + + const ipv4 = z.string().ip({ version: "v4" }); + expect(() => ipv4.parse("6097:adfa:6f0b:220d:db08:5021:6191:7990")).toThrow(); + + const ipv6 = z.string().ip({ version: "v6" }); + expect(() => ipv6.parse("254.164.77.1")).toThrow(); + + const validIPs = [ + "1e5e:e6c8:daac:514b:114b:e360:d8c0:682c", + "9d4:c956:420f:5788:4339:9b3b:2418:75c3", + "474f:4c83::4e40:a47:ff95:0cda", + "d329:0:25b4:db47:a9d1:0:4926:0000", + "e48:10fb:1499:3e28:e4b6:dea5:4692:912c", + "114.71.82.94", + "0.0.0.0", + "37.85.236.115", + "2001:4888:50:ff00:500:d::", + "2001:4888:50:ff00:0500:000d:000:0000", + "2001:4888:50:ff00:0500:000d:0000:0000", + ]; + + const invalidIPs = [ + "d329:1be4:25b4:db47:a9d1:dc71:4926:992c:14af", + "d5e7:7214:2b78::3906:85e6:53cc:709:32ba", + "8f69::c757:395e:976e::3441", + "54cb::473f:d516:0.255.256.22", + "54cb::473f:d516:192.168.1", + "256.0.4.4", + "-1.0.555.4", + "0.0.0.0.0", + "1.1.1", + ]; + // no parameters check IPv4 or IPv6 + const ipSchema = z.string().ip(); + expect(validIPs.every((ip) => ipSchema.safeParse(ip).success)).toBe(true); + expect(invalidIPs.every((ip) => ipSchema.safeParse(ip).success === false)).toBe(true); +}); + +test("CIDR validation", () => { + const ipv4Cidr = z.string().cidr({ version: "v4" }); + expect(() => ipv4Cidr.parse("2001:0db8:85a3::8a2e:0370:7334/64")).toThrow(); + + const ipv6Cidr = z.string().cidr({ version: "v6" }); + expect(() => ipv6Cidr.parse("192.168.0.1/24")).toThrow(); + + const validCidrs = [ + "192.168.0.0/24", + "10.0.0.0/8", + "203.0.113.0/24", + "192.0.2.0/24", + "127.0.0.0/8", + "172.16.0.0/12", + "192.168.1.0/24", + "fc00::/7", + "fd00::/8", + "2001:db8::/32", + "2607:f0d0:1002:51::4/64", + "2001:0db8:85a3:0000:0000:8a2e:0370:7334/128", + "2001:0db8:1234:0000::/64", + ]; + + const invalidCidrs = [ + "192.168.1.1/33", + "10.0.0.1/-1", + "192.168.1.1/24/24", + "192.168.1.0/abc", + "2001:db8::1/129", + "2001:db8::1/-1", + "2001:db8::1/64/64", + "2001:db8::1/abc", + ]; + + // no parameters check IPv4 or IPv6 + const cidrSchema = z.string().cidr(); + expect(validCidrs.every((ip) => cidrSchema.safeParse(ip).success)).toBe(true); + expect(invalidCidrs.every((ip) => cidrSchema.safeParse(ip).success === false)).toBe(true); +}); diff --git a/node_modules/zod/src/v3/tests/transformer.test.ts b/node_modules/zod/src/v3/tests/transformer.test.ts new file mode 100644 index 0000000..ddd9e9a --- /dev/null +++ b/node_modules/zod/src/v3/tests/transformer.test.ts @@ -0,0 +1,233 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { util } from "../helpers/util.js"; + +const stringToNumber = z.string().transform((arg) => Number.parseFloat(arg)); +// const numberToString = z +// .transformer(z.number()) +// .transform((n) => String(n)); +const asyncNumberToString = z.number().transform(async (n) => String(n)); + +test("transform ctx.addIssue with parse", () => { + const strs = ["foo", "bar"]; + + expect(() => { + z.string() + .transform((data, ctx) => { + const i = strs.indexOf(data); + if (i === -1) { + ctx.addIssue({ + code: "custom", + message: `${data} is not one of our allowed strings`, + }); + } + return data.length; + }) + .parse("asdf"); + }).toThrow( + JSON.stringify( + [ + { + code: "custom", + message: "asdf is not one of our allowed strings", + path: [], + }, + ], + null, + 2 + ) + ); +}); + +test("transform ctx.addIssue with parseAsync", async () => { + const strs = ["foo", "bar"]; + + const result = await z + .string() + .transform(async (data, ctx) => { + const i = strs.indexOf(data); + if (i === -1) { + ctx.addIssue({ + code: "custom", + message: `${data} is not one of our allowed strings`, + }); + } + return data.length; + }) + .safeParseAsync("asdf"); + + expect(JSON.parse(JSON.stringify(result))).toEqual({ + success: false, + error: { + issues: [ + { + code: "custom", + message: "asdf is not one of our allowed strings", + path: [], + }, + ], + name: "ZodError", + }, + }); +}); + +test("z.NEVER in transform", () => { + const foo = z + .number() + .optional() + .transform((val, ctx) => { + if (!val) { + ctx.addIssue({ code: z.ZodIssueCode.custom, message: "bad" }); + return z.NEVER; + } + return val; + }); + type foo = z.infer; + util.assertEqual(true); + const arg = foo.safeParse(undefined); + if (!arg.success) { + expect(arg.error.issues[0].message).toEqual("bad"); + } +}); + +test("basic transformations", () => { + const r1 = z + .string() + .transform((data) => data.length) + .parse("asdf"); + expect(r1).toEqual(4); +}); + +test("coercion", () => { + const numToString = z.number().transform((n) => String(n)); + const data = z + .object({ + id: numToString, + }) + .parse({ id: 5 }); + + expect(data).toEqual({ id: "5" }); +}); + +test("async coercion", async () => { + const numToString = z.number().transform(async (n) => String(n)); + const data = await z + .object({ + id: numToString, + }) + .parseAsync({ id: 5 }); + + expect(data).toEqual({ id: "5" }); +}); + +test("sync coercion async error", async () => { + expect(() => + z + .object({ + id: asyncNumberToString, + }) + .parse({ id: 5 }) + ).toThrow(); + // expect(data).toEqual({ id: '5' }); +}); + +test("default", () => { + const data = z.string().default("asdf").parse(undefined); // => "asdf" + expect(data).toEqual("asdf"); +}); + +test("dynamic default", () => { + const data = z + .string() + .default(() => "string") + .parse(undefined); // => "asdf" + expect(data).toEqual("string"); +}); + +test("default when property is null or undefined", () => { + const data = z + .object({ + foo: z.boolean().nullable().default(true), + bar: z.boolean().default(true), + }) + .parse({ foo: null }); + + expect(data).toEqual({ foo: null, bar: true }); +}); + +test("default with falsy values", () => { + const schema = z.object({ + emptyStr: z.string().default("def"), + zero: z.number().default(5), + falseBoolean: z.boolean().default(true), + }); + const input = { emptyStr: "", zero: 0, falseBoolean: true }; + const output = schema.parse(input); + // defaults are not supposed to be used + expect(output).toEqual(input); +}); + +test("object typing", () => { + const t1 = z.object({ + stringToNumber, + }); + + type t1 = z.input; + type t2 = z.output; + + util.assertEqual(true); + util.assertEqual(true); +}); + +test("transform method overloads", () => { + const t1 = z.string().transform((val) => val.toUpperCase()); + expect(t1.parse("asdf")).toEqual("ASDF"); + + const t2 = z.string().transform((val) => val.length); + expect(t2.parse("asdf")).toEqual(4); +}); + +test("multiple transformers", () => { + const doubler = stringToNumber.transform((val) => { + return val * 2; + }); + expect(doubler.parse("5")).toEqual(10); +}); + +test("short circuit on dirty", () => { + const schema = z + .string() + .refine(() => false) + .transform((val) => val.toUpperCase()); + const result = schema.safeParse("asdf"); + expect(result.success).toEqual(false); + if (!result.success) { + expect(result.error.issues[0].code).toEqual(z.ZodIssueCode.custom); + } + + const result2 = schema.safeParse(1234); + expect(result2.success).toEqual(false); + if (!result2.success) { + expect(result2.error.issues[0].code).toEqual(z.ZodIssueCode.invalid_type); + } +}); + +test("async short circuit on dirty", async () => { + const schema = z + .string() + .refine(() => false) + .transform((val) => val.toUpperCase()); + const result = await schema.spa("asdf"); + expect(result.success).toEqual(false); + if (!result.success) { + expect(result.error.issues[0].code).toEqual(z.ZodIssueCode.custom); + } + + const result2 = await schema.spa(1234); + expect(result2.success).toEqual(false); + if (!result2.success) { + expect(result2.error.issues[0].code).toEqual(z.ZodIssueCode.invalid_type); + } +}); diff --git a/node_modules/zod/src/v3/tests/tuple.test.ts b/node_modules/zod/src/v3/tests/tuple.test.ts new file mode 100644 index 0000000..e525d3f --- /dev/null +++ b/node_modules/zod/src/v3/tests/tuple.test.ts @@ -0,0 +1,90 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { ZodError } from "../ZodError.js"; +import { util } from "../helpers/util.js"; + +const testTuple = z.tuple([z.string(), z.object({ name: z.literal("Rudy") }), z.array(z.literal("blue"))]); +const testData = ["asdf", { name: "Rudy" }, ["blue"]]; +const badData = [123, { name: "Rudy2" }, ["blue", "red"]]; + +test("tuple inference", () => { + const args1 = z.tuple([z.string()]); + const returns1 = z.number(); + const func1 = z.function(args1, returns1); + type func1 = z.TypeOf; + util.assertEqual number>(true); +}); + +test("successful validation", () => { + const val = testTuple.parse(testData); + expect(val).toEqual(["asdf", { name: "Rudy" }, ["blue"]]); +}); + +test("successful async validation", async () => { + const val = await testTuple.parseAsync(testData); + return expect(val).toEqual(testData); +}); + +test("failed validation", () => { + const checker = () => { + testTuple.parse([123, { name: "Rudy2" }, ["blue", "red"]] as any); + }; + try { + checker(); + } catch (err) { + if (err instanceof ZodError) { + expect(err.issues.length).toEqual(3); + } + } +}); + +test("failed async validation", async () => { + const res = await testTuple.safeParse(badData); + expect(res.success).toEqual(false); + if (!res.success) { + expect(res.error.issues.length).toEqual(3); + } + // try { + // checker(); + // } catch (err) { + // if (err instanceof ZodError) { + // expect(err.issues.length).toEqual(3); + // } + // } +}); + +test("tuple with transformers", () => { + const stringToNumber = z.string().transform((val) => val.length); + const val = z.tuple([stringToNumber]); + + type t1 = z.input; + util.assertEqual(true); + type t2 = z.output; + util.assertEqual(true); + expect(val.parse(["1234"])).toEqual([4]); +}); + +test("tuple with rest schema", () => { + const myTuple = z.tuple([z.string(), z.number()]).rest(z.boolean()); + expect(myTuple.parse(["asdf", 1234, true, false, true])).toEqual(["asdf", 1234, true, false, true]); + + expect(myTuple.parse(["asdf", 1234])).toEqual(["asdf", 1234]); + + expect(() => myTuple.parse(["asdf", 1234, "asdf"])).toThrow(); + type t1 = z.output; + + util.assertEqual(true); +}); + +test("parse should fail given sparse array as tuple", () => { + expect(() => testTuple.parse(new Array(3))).toThrow(); +}); + +// test('tuple with optional elements', () => { +// const result = z +// .tuple([z.string(), z.number().optional()]) +// .safeParse(['asdf']); +// expect(result).toEqual(['asdf']); +// }); diff --git a/node_modules/zod/src/v3/tests/unions.test.ts b/node_modules/zod/src/v3/tests/unions.test.ts new file mode 100644 index 0000000..2c3dc67 --- /dev/null +++ b/node_modules/zod/src/v3/tests/unions.test.ts @@ -0,0 +1,57 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; + +test("function parsing", () => { + const schema = z.union([z.string().refine(() => false), z.number().refine(() => false)]); + const result = schema.safeParse("asdf"); + expect(result.success).toEqual(false); +}); + +test("union 2", () => { + const result = z.union([z.number(), z.string().refine(() => false)]).safeParse("a"); + expect(result.success).toEqual(false); +}); + +test("return valid over invalid", () => { + const schema = z.union([ + z.object({ + email: z.string().email(), + }), + z.string(), + ]); + expect(schema.parse("asdf")).toEqual("asdf"); + expect(schema.parse({ email: "asdlkjf@lkajsdf.com" })).toEqual({ + email: "asdlkjf@lkajsdf.com", + }); +}); + +test("return dirty result over aborted", () => { + const result = z.union([z.number(), z.string().refine(() => false)]).safeParse("a"); + expect(result.success).toEqual(false); + if (!result.success) { + expect(result.error.issues).toEqual([ + { + code: "custom", + message: "Invalid input", + path: [], + }, + ]); + } +}); + +test("options getter", async () => { + const union = z.union([z.string(), z.number()]); + union.options[0].parse("asdf"); + union.options[1].parse(1234); + await union.options[0].parseAsync("asdf"); + await union.options[1].parseAsync(1234); +}); + +test("readonly union", async () => { + const options = [z.string(), z.number()] as const; + const union = z.union(options); + union.parse("asdf"); + union.parse(12); +}); diff --git a/node_modules/zod/src/v3/tests/validations.test.ts b/node_modules/zod/src/v3/tests/validations.test.ts new file mode 100644 index 0000000..66f41da --- /dev/null +++ b/node_modules/zod/src/v3/tests/validations.test.ts @@ -0,0 +1,133 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; + +test("array min", async () => { + try { + await z.array(z.string()).min(4).parseAsync([]); + } catch (err) { + expect((err as z.ZodError).issues[0].message).toEqual("Array must contain at least 4 element(s)"); + } +}); + +test("array max", async () => { + try { + await z.array(z.string()).max(2).parseAsync(["asdf", "asdf", "asdf"]); + } catch (err) { + expect((err as z.ZodError).issues[0].message).toEqual("Array must contain at most 2 element(s)"); + } +}); + +test("array length", async () => { + try { + await z.array(z.string()).length(2).parseAsync(["asdf", "asdf", "asdf"]); + } catch (err) { + expect((err as z.ZodError).issues[0].message).toEqual("Array must contain exactly 2 element(s)"); + } + + try { + await z.array(z.string()).length(2).parseAsync(["asdf"]); + } catch (err) { + expect((err as z.ZodError).issues[0].message).toEqual("Array must contain exactly 2 element(s)"); + } +}); + +test("string length", async () => { + try { + await z.string().length(4).parseAsync("asd"); + } catch (err) { + expect((err as z.ZodError).issues[0].message).toEqual("String must contain exactly 4 character(s)"); + } + + try { + await z.string().length(4).parseAsync("asdaa"); + } catch (err) { + expect((err as z.ZodError).issues[0].message).toEqual("String must contain exactly 4 character(s)"); + } +}); + +test("string min", async () => { + try { + await z.string().min(4).parseAsync("asd"); + } catch (err) { + expect((err as z.ZodError).issues[0].message).toEqual("String must contain at least 4 character(s)"); + } +}); + +test("string max", async () => { + try { + await z.string().max(4).parseAsync("aasdfsdfsd"); + } catch (err) { + expect((err as z.ZodError).issues[0].message).toEqual("String must contain at most 4 character(s)"); + } +}); + +test("number min", async () => { + try { + await z.number().gte(3).parseAsync(2); + } catch (err) { + expect((err as z.ZodError).issues[0].message).toEqual("Number must be greater than or equal to 3"); + } +}); + +test("number max", async () => { + try { + await z.number().lte(3).parseAsync(4); + } catch (err) { + expect((err as z.ZodError).issues[0].message).toEqual("Number must be less than or equal to 3"); + } +}); + +test("number nonnegative", async () => { + try { + await z.number().nonnegative().parseAsync(-1); + } catch (err) { + expect((err as z.ZodError).issues[0].message).toEqual("Number must be greater than or equal to 0"); + } +}); + +test("number nonpositive", async () => { + try { + await z.number().nonpositive().parseAsync(1); + } catch (err) { + expect((err as z.ZodError).issues[0].message).toEqual("Number must be less than or equal to 0"); + } +}); + +test("number negative", async () => { + try { + await z.number().negative().parseAsync(1); + } catch (err) { + expect((err as z.ZodError).issues[0].message).toEqual("Number must be less than 0"); + } +}); + +test("number positive", async () => { + try { + await z.number().positive().parseAsync(-1); + } catch (err) { + expect((err as z.ZodError).issues[0].message).toEqual("Number must be greater than 0"); + } +}); + +test("instantiation", () => { + z.string().min(5); + z.string().max(5); + z.string().length(5); + z.string().email(); + z.string().url(); + z.string().uuid(); + z.string().min(5, { message: "Must be 5 or more characters long" }); + z.string().max(5, { message: "Must be 5 or fewer characters long" }); + z.string().length(5, { message: "Must be exactly 5 characters long" }); + z.string().email({ message: "Invalid email address." }); + z.string().url({ message: "Invalid url" }); + z.string().uuid({ message: "Invalid UUID" }); +}); + +test("int", async () => { + const int = z.number().int(); + int.parse(4); + expect(() => int.parse(3.5)).toThrow(); +}); diff --git a/node_modules/zod/src/v3/tests/void.test.ts b/node_modules/zod/src/v3/tests/void.test.ts new file mode 100644 index 0000000..b128f11 --- /dev/null +++ b/node_modules/zod/src/v3/tests/void.test.ts @@ -0,0 +1,15 @@ +// @ts-ignore TS6133 +import { expect, test } from "vitest"; + +import * as z from "zod/v3"; +import { util } from "../helpers/util.js"; +test("void", () => { + const v = z.void(); + v.parse(undefined); + + expect(() => v.parse(null)).toThrow(); + expect(() => v.parse("")).toThrow(); + + type v = z.infer; + util.assertEqual(true); +}); diff --git a/node_modules/zod/src/v3/types.ts b/node_modules/zod/src/v3/types.ts new file mode 100644 index 0000000..f402854 --- /dev/null +++ b/node_modules/zod/src/v3/types.ts @@ -0,0 +1,5138 @@ +import { + type IssueData, + type StringValidation, + type ZodCustomIssue, + ZodError, + type ZodErrorMap, + type ZodIssue, + ZodIssueCode, +} from "./ZodError.js"; +import { defaultErrorMap, getErrorMap } from "./errors.js"; +import type { enumUtil } from "./helpers/enumUtil.js"; +import { errorUtil } from "./helpers/errorUtil.js"; +import { + type AsyncParseReturnType, + DIRTY, + INVALID, + OK, + type ParseContext, + type ParseInput, + type ParseParams, + type ParsePath, + type ParseReturnType, + ParseStatus, + type SyncParseReturnType, + addIssueToContext, + isAborted, + isAsync, + isDirty, + isValid, + makeIssue, +} from "./helpers/parseUtil.js"; +import type { partialUtil } from "./helpers/partialUtil.js"; +import type { Primitive } from "./helpers/typeAliases.js"; +import { util, ZodParsedType, getParsedType, type objectUtil } from "./helpers/util.js"; +import type { StandardSchemaV1 } from "./standard-schema.js"; + +/////////////////////////////////////// +/////////////////////////////////////// +////////// ////////// +////////// ZodType ////////// +////////// ////////// +/////////////////////////////////////// +/////////////////////////////////////// + +export interface RefinementCtx { + addIssue: (arg: IssueData) => void; + path: (string | number)[]; +} +export type ZodRawShape = { [k: string]: ZodTypeAny }; +export type ZodTypeAny = ZodType; +export type TypeOf> = T["_output"]; +export type input> = T["_input"]; +export type output> = T["_output"]; +export type { TypeOf as infer }; + +export type CustomErrorParams = Partial>; +export interface ZodTypeDef { + errorMap?: ZodErrorMap | undefined; + description?: string | undefined; +} + +class ParseInputLazyPath implements ParseInput { + parent: ParseContext; + data: any; + _path: ParsePath; + _key: string | number | (string | number)[]; + _cachedPath: ParsePath = []; + constructor(parent: ParseContext, value: any, path: ParsePath, key: string | number | (string | number)[]) { + this.parent = parent; + this.data = value; + this._path = path; + this._key = key; + } + get path() { + if (!this._cachedPath.length) { + if (Array.isArray(this._key)) { + this._cachedPath.push(...this._path, ...this._key); + } else { + this._cachedPath.push(...this._path, this._key); + } + } + + return this._cachedPath; + } +} + +const handleResult = ( + ctx: ParseContext, + result: SyncParseReturnType +): { success: true; data: Output } | { success: false; error: ZodError } => { + if (isValid(result)) { + return { success: true, data: result.value }; + } else { + if (!ctx.common.issues.length) { + throw new Error("Validation failed but no issues detected."); + } + + return { + success: false, + get error() { + if ((this as any)._error) return (this as any)._error as Error; + const error = new ZodError(ctx.common.issues); + (this as any)._error = error; + return (this as any)._error; + }, + }; + } +}; + +export type RawCreateParams = + | { + errorMap?: ZodErrorMap | undefined; + invalid_type_error?: string | undefined; + required_error?: string | undefined; + message?: string | undefined; + description?: string | undefined; + } + | undefined; +export type ProcessedCreateParams = { + errorMap?: ZodErrorMap | undefined; + description?: string | undefined; +}; +function processCreateParams(params: RawCreateParams): ProcessedCreateParams { + if (!params) return {}; + const { errorMap, invalid_type_error, required_error, description } = params; + if (errorMap && (invalid_type_error || required_error)) { + throw new Error(`Can't use "invalid_type_error" or "required_error" in conjunction with custom error map.`); + } + if (errorMap) return { errorMap: errorMap, description }; + const customMap: ZodErrorMap = (iss, ctx) => { + const { message } = params; + + if (iss.code === "invalid_enum_value") { + return { message: message ?? ctx.defaultError }; + } + if (typeof ctx.data === "undefined") { + return { message: message ?? required_error ?? ctx.defaultError }; + } + if (iss.code !== "invalid_type") return { message: ctx.defaultError }; + return { message: message ?? invalid_type_error ?? ctx.defaultError }; + }; + return { errorMap: customMap, description }; +} + +export type SafeParseSuccess = { + success: true; + data: Output; + error?: never; +}; +export type SafeParseError = { + success: false; + error: ZodError; + data?: never; +}; + +export type SafeParseReturnType = SafeParseSuccess | SafeParseError; + +export abstract class ZodType { + readonly _type!: Output; + readonly _output!: Output; + readonly _input!: Input; + readonly _def!: Def; + + get description(): string | undefined { + return this._def.description; + } + + "~standard": StandardSchemaV1.Props; + + abstract _parse(input: ParseInput): ParseReturnType; + + _getType(input: ParseInput): string { + return getParsedType(input.data); + } + + _getOrReturnCtx(input: ParseInput, ctx?: ParseContext | undefined): ParseContext { + return ( + ctx || { + common: input.parent.common, + data: input.data, + + parsedType: getParsedType(input.data), + + schemaErrorMap: this._def.errorMap, + path: input.path, + parent: input.parent, + } + ); + } + + _processInputParams(input: ParseInput): { + status: ParseStatus; + ctx: ParseContext; + } { + return { + status: new ParseStatus(), + ctx: { + common: input.parent.common, + data: input.data, + + parsedType: getParsedType(input.data), + + schemaErrorMap: this._def.errorMap, + path: input.path, + parent: input.parent, + }, + }; + } + + _parseSync(input: ParseInput): SyncParseReturnType { + const result = this._parse(input); + if (isAsync(result)) { + throw new Error("Synchronous parse encountered promise."); + } + return result; + } + + _parseAsync(input: ParseInput): AsyncParseReturnType { + const result = this._parse(input); + return Promise.resolve(result); + } + + parse(data: unknown, params?: util.InexactPartial): Output { + const result = this.safeParse(data, params); + if (result.success) return result.data; + throw result.error; + } + + safeParse(data: unknown, params?: util.InexactPartial): SafeParseReturnType { + const ctx: ParseContext = { + common: { + issues: [], + async: params?.async ?? false, + contextualErrorMap: params?.errorMap, + }, + path: params?.path || [], + schemaErrorMap: this._def.errorMap, + parent: null, + data, + parsedType: getParsedType(data), + }; + const result = this._parseSync({ data, path: ctx.path, parent: ctx }); + + return handleResult(ctx, result); + } + + "~validate"(data: unknown): StandardSchemaV1.Result | Promise> { + const ctx: ParseContext = { + common: { + issues: [], + async: !!(this["~standard"] as any).async, + }, + path: [], + schemaErrorMap: this._def.errorMap, + parent: null, + data, + parsedType: getParsedType(data), + }; + + if (!(this["~standard"] as any).async) { + try { + const result = this._parseSync({ data, path: [], parent: ctx }); + return isValid(result) + ? { + value: result.value, + } + : { + issues: ctx.common.issues, + }; + } catch (err: any) { + if ((err as Error)?.message?.toLowerCase()?.includes("encountered")) { + (this["~standard"] as any).async = true; + } + (ctx as any).common = { + issues: [], + async: true, + }; + } + } + + return this._parseAsync({ data, path: [], parent: ctx }).then((result) => + isValid(result) + ? { + value: result.value, + } + : { + issues: ctx.common.issues, + } + ); + } + + async parseAsync(data: unknown, params?: util.InexactPartial): Promise { + const result = await this.safeParseAsync(data, params); + if (result.success) return result.data; + throw result.error; + } + + async safeParseAsync( + data: unknown, + params?: util.InexactPartial + ): Promise> { + const ctx: ParseContext = { + common: { + issues: [], + contextualErrorMap: params?.errorMap, + async: true, + }, + path: params?.path || [], + schemaErrorMap: this._def.errorMap, + parent: null, + data, + parsedType: getParsedType(data), + }; + + const maybeAsyncResult = this._parse({ data, path: ctx.path, parent: ctx }); + const result = await (isAsync(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult)); + return handleResult(ctx, result); + } + + /** Alias of safeParseAsync */ + spa = this.safeParseAsync; + + refine( + check: (arg: Output) => arg is RefinedOutput, + message?: string | CustomErrorParams | ((arg: Output) => CustomErrorParams) + ): ZodEffects; + refine( + check: (arg: Output) => unknown | Promise, + message?: string | CustomErrorParams | ((arg: Output) => CustomErrorParams) + ): ZodEffects; + refine( + check: (arg: Output) => unknown, + message?: string | CustomErrorParams | ((arg: Output) => CustomErrorParams) + ): ZodEffects { + const getIssueProperties = (val: Output) => { + if (typeof message === "string" || typeof message === "undefined") { + return { message }; + } else if (typeof message === "function") { + return message(val); + } else { + return message; + } + }; + return this._refinement((val, ctx) => { + const result = check(val); + const setError = () => + ctx.addIssue({ + code: ZodIssueCode.custom, + ...getIssueProperties(val), + }); + if (typeof Promise !== "undefined" && result instanceof Promise) { + return result.then((data) => { + if (!data) { + setError(); + return false; + } else { + return true; + } + }); + } + if (!result) { + setError(); + return false; + } else { + return true; + } + }); + } + + refinement( + check: (arg: Output) => arg is RefinedOutput, + refinementData: IssueData | ((arg: Output, ctx: RefinementCtx) => IssueData) + ): ZodEffects; + refinement( + check: (arg: Output) => boolean, + refinementData: IssueData | ((arg: Output, ctx: RefinementCtx) => IssueData) + ): ZodEffects; + refinement( + check: (arg: Output) => unknown, + refinementData: IssueData | ((arg: Output, ctx: RefinementCtx) => IssueData) + ): ZodEffects { + return this._refinement((val, ctx) => { + if (!check(val)) { + ctx.addIssue(typeof refinementData === "function" ? refinementData(val, ctx) : refinementData); + return false; + } else { + return true; + } + }); + } + + _refinement(refinement: RefinementEffect["refinement"]): ZodEffects { + return new ZodEffects({ + schema: this, + typeName: ZodFirstPartyTypeKind.ZodEffects, + effect: { type: "refinement", refinement }, + }); + } + + superRefine( + refinement: (arg: Output, ctx: RefinementCtx) => arg is RefinedOutput + ): ZodEffects; + superRefine(refinement: (arg: Output, ctx: RefinementCtx) => void): ZodEffects; + superRefine(refinement: (arg: Output, ctx: RefinementCtx) => Promise): ZodEffects; + superRefine( + refinement: (arg: Output, ctx: RefinementCtx) => unknown | Promise + ): ZodEffects { + return this._refinement(refinement); + } + + constructor(def: Def) { + this._def = def; + this.parse = this.parse.bind(this); + this.safeParse = this.safeParse.bind(this); + this.parseAsync = this.parseAsync.bind(this); + this.safeParseAsync = this.safeParseAsync.bind(this); + this.spa = this.spa.bind(this); + this.refine = this.refine.bind(this); + this.refinement = this.refinement.bind(this); + this.superRefine = this.superRefine.bind(this); + this.optional = this.optional.bind(this); + this.nullable = this.nullable.bind(this); + this.nullish = this.nullish.bind(this); + this.array = this.array.bind(this); + this.promise = this.promise.bind(this); + this.or = this.or.bind(this); + this.and = this.and.bind(this); + this.transform = this.transform.bind(this); + this.brand = this.brand.bind(this); + this.default = this.default.bind(this); + this.catch = this.catch.bind(this); + this.describe = this.describe.bind(this); + this.pipe = this.pipe.bind(this); + this.readonly = this.readonly.bind(this); + this.isNullable = this.isNullable.bind(this); + this.isOptional = this.isOptional.bind(this); + this["~standard"] = { + version: 1, + vendor: "zod", + validate: (data) => this["~validate"](data), + }; + } + + optional(): ZodOptional { + return ZodOptional.create(this, this._def) as any; + } + nullable(): ZodNullable { + return ZodNullable.create(this, this._def) as any; + } + nullish(): ZodOptional> { + return this.nullable().optional(); + } + array(): ZodArray { + return ZodArray.create(this); + } + promise(): ZodPromise { + return ZodPromise.create(this, this._def); + } + + or(option: T): ZodUnion<[this, T]> { + return ZodUnion.create([this, option], this._def) as any; + } + + and(incoming: T): ZodIntersection { + return ZodIntersection.create(this, incoming, this._def); + } + + transform( + transform: (arg: Output, ctx: RefinementCtx) => NewOut | Promise + ): ZodEffects { + return new ZodEffects({ + ...processCreateParams(this._def), + schema: this, + typeName: ZodFirstPartyTypeKind.ZodEffects, + effect: { type: "transform", transform }, + }) as any; + } + + default(def: util.noUndefined): ZodDefault; + default(def: () => util.noUndefined): ZodDefault; + default(def: any) { + const defaultValueFunc = typeof def === "function" ? def : () => def; + + return new ZodDefault({ + ...processCreateParams(this._def), + innerType: this, + defaultValue: defaultValueFunc, + typeName: ZodFirstPartyTypeKind.ZodDefault, + }) as any; + } + + brand(brand?: B): ZodBranded; + brand(): ZodBranded { + return new ZodBranded({ + typeName: ZodFirstPartyTypeKind.ZodBranded, + type: this, + ...processCreateParams(this._def), + }); + } + + catch(def: Output): ZodCatch; + catch(def: (ctx: { error: ZodError; input: Input }) => Output): ZodCatch; + catch(def: any) { + const catchValueFunc = typeof def === "function" ? def : () => def; + + return new ZodCatch({ + ...processCreateParams(this._def), + innerType: this, + catchValue: catchValueFunc, + typeName: ZodFirstPartyTypeKind.ZodCatch, + }) as any; + } + + describe(description: string): this { + const This = (this as any).constructor; + return new This({ + ...this._def, + description, + }); + } + + pipe(target: T): ZodPipeline { + return ZodPipeline.create(this, target); + } + readonly(): ZodReadonly { + return ZodReadonly.create(this); + } + + isOptional(): boolean { + return this.safeParse(undefined).success; + } + isNullable(): boolean { + return this.safeParse(null).success; + } +} + +///////////////////////////////////////// +///////////////////////////////////////// +////////// ////////// +////////// ZodString ////////// +////////// ////////// +///////////////////////////////////////// +///////////////////////////////////////// +export type IpVersion = "v4" | "v6"; +export type ZodStringCheck = + | { kind: "min"; value: number; message?: string | undefined } + | { kind: "max"; value: number; message?: string | undefined } + | { kind: "length"; value: number; message?: string | undefined } + | { kind: "email"; message?: string | undefined } + | { kind: "url"; message?: string | undefined } + | { kind: "emoji"; message?: string | undefined } + | { kind: "uuid"; message?: string | undefined } + | { kind: "nanoid"; message?: string | undefined } + | { kind: "cuid"; message?: string | undefined } + | { kind: "includes"; value: string; position?: number | undefined; message?: string | undefined } + | { kind: "cuid2"; message?: string | undefined } + | { kind: "ulid"; message?: string | undefined } + | { kind: "startsWith"; value: string; message?: string | undefined } + | { kind: "endsWith"; value: string; message?: string | undefined } + | { kind: "regex"; regex: RegExp; message?: string | undefined } + | { kind: "trim"; message?: string | undefined } + | { kind: "toLowerCase"; message?: string | undefined } + | { kind: "toUpperCase"; message?: string | undefined } + | { kind: "jwt"; alg?: string; message?: string | undefined } + | { + kind: "datetime"; + offset: boolean; + local: boolean; + precision: number | null; + message?: string | undefined; + } + | { + kind: "date"; + // withDate: true; + message?: string | undefined; + } + | { + kind: "time"; + precision: number | null; + message?: string | undefined; + } + | { kind: "duration"; message?: string | undefined } + | { kind: "ip"; version?: IpVersion | undefined; message?: string | undefined } + | { kind: "cidr"; version?: IpVersion | undefined; message?: string | undefined } + | { kind: "base64"; message?: string | undefined } + | { kind: "base64url"; message?: string | undefined }; + +export interface ZodStringDef extends ZodTypeDef { + checks: ZodStringCheck[]; + typeName: ZodFirstPartyTypeKind.ZodString; + coerce: boolean; +} + +const cuidRegex = /^c[^\s-]{8,}$/i; +const cuid2Regex = /^[0-9a-z]+$/; +const ulidRegex = /^[0-9A-HJKMNP-TV-Z]{26}$/i; +// const uuidRegex = +// /^([a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[a-f0-9]{4}-[a-f0-9]{12}|00000000-0000-0000-0000-000000000000)$/i; +const uuidRegex = /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/i; +const nanoidRegex = /^[a-z0-9_-]{21}$/i; +const jwtRegex = /^[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+\.[A-Za-z0-9-_]*$/; +const durationRegex = + /^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/; + +// from https://stackoverflow.com/a/46181/1550155 +// old version: too slow, didn't support unicode +// const emailRegex = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i; +//old email regex +// const emailRegex = /^(([^<>()[\].,;:\s@"]+(\.[^<>()[\].,;:\s@"]+)*)|(".+"))@((?!-)([^<>()[\].,;:\s@"]+\.)+[^<>()[\].,;:\s@"]{1,})[^-<>()[\].,;:\s@"]$/i; +// eslint-disable-next-line +// const emailRegex = +// /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\])|(\[IPv6:(([a-f0-9]{1,4}:){7}|::([a-f0-9]{1,4}:){0,6}|([a-f0-9]{1,4}:){1}:([a-f0-9]{1,4}:){0,5}|([a-f0-9]{1,4}:){2}:([a-f0-9]{1,4}:){0,4}|([a-f0-9]{1,4}:){3}:([a-f0-9]{1,4}:){0,3}|([a-f0-9]{1,4}:){4}:([a-f0-9]{1,4}:){0,2}|([a-f0-9]{1,4}:){5}:([a-f0-9]{1,4}:){0,1})([a-f0-9]{1,4}|(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2})))\])|([A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])*(\.[A-Za-z]{2,})+))$/; +// const emailRegex = +// /^[a-zA-Z0-9\.\!\#\$\%\&\'\*\+\/\=\?\^\_\`\{\|\}\~\-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/; +// const emailRegex = +// /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/i; +const emailRegex = /^(?!\.)(?!.*\.\.)([A-Z0-9_'+\-\.]*)[A-Z0-9_+-]@([A-Z0-9][A-Z0-9\-]*\.)+[A-Z]{2,}$/i; +// const emailRegex = +// /^[a-z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-z0-9-]+(?:\.[a-z0-9\-]+)*$/i; + +// from https://thekevinscott.com/emojis-in-javascript/#writing-a-regular-expression +const _emojiRegex = `^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`; +let emojiRegex: RegExp; + +// faster, simpler, safer +const ipv4Regex = + /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/; +const ipv4CidrRegex = + /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/(3[0-2]|[12]?[0-9])$/; + +// const ipv6Regex = +// /^(([a-f0-9]{1,4}:){7}|::([a-f0-9]{1,4}:){0,6}|([a-f0-9]{1,4}:){1}:([a-f0-9]{1,4}:){0,5}|([a-f0-9]{1,4}:){2}:([a-f0-9]{1,4}:){0,4}|([a-f0-9]{1,4}:){3}:([a-f0-9]{1,4}:){0,3}|([a-f0-9]{1,4}:){4}:([a-f0-9]{1,4}:){0,2}|([a-f0-9]{1,4}:){5}:([a-f0-9]{1,4}:){0,1})([a-f0-9]{1,4}|(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2})))$/; +const ipv6Regex = + /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/; +const ipv6CidrRegex = + /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/; + +// https://stackoverflow.com/questions/7860392/determine-if-string-is-in-base64-using-javascript +const base64Regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/; + +// https://base64.guru/standards/base64url +const base64urlRegex = /^([0-9a-zA-Z-_]{4})*(([0-9a-zA-Z-_]{2}(==)?)|([0-9a-zA-Z-_]{3}(=)?))?$/; + +// simple +// const dateRegexSource = `\\d{4}-\\d{2}-\\d{2}`; +// no leap year validation +// const dateRegexSource = `\\d{4}-((0[13578]|10|12)-31|(0[13-9]|1[0-2])-30|(0[1-9]|1[0-2])-(0[1-9]|1\\d|2\\d))`; +// with leap year validation +const dateRegexSource = `((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))`; +const dateRegex = new RegExp(`^${dateRegexSource}$`); + +function timeRegexSource(args: { precision?: number | null }) { + let secondsRegexSource = `[0-5]\\d`; + if (args.precision) { + secondsRegexSource = `${secondsRegexSource}\\.\\d{${args.precision}}`; + } else if (args.precision == null) { + secondsRegexSource = `${secondsRegexSource}(\\.\\d+)?`; + } + + const secondsQuantifier = args.precision ? "+" : "?"; // require seconds if precision is nonzero + return `([01]\\d|2[0-3]):[0-5]\\d(:${secondsRegexSource})${secondsQuantifier}`; +} + +function timeRegex(args: { + offset?: boolean; + local?: boolean; + precision?: number | null; +}) { + return new RegExp(`^${timeRegexSource(args)}$`); +} + +// Adapted from https://stackoverflow.com/a/3143231 +export function datetimeRegex(args: { + precision?: number | null; + offset?: boolean; + local?: boolean; +}) { + let regex = `${dateRegexSource}T${timeRegexSource(args)}`; + + const opts: string[] = []; + opts.push(args.local ? `Z?` : `Z`); + if (args.offset) opts.push(`([+-]\\d{2}:?\\d{2})`); + regex = `${regex}(${opts.join("|")})`; + return new RegExp(`^${regex}$`); +} + +function isValidIP(ip: string, version?: IpVersion) { + if ((version === "v4" || !version) && ipv4Regex.test(ip)) { + return true; + } + if ((version === "v6" || !version) && ipv6Regex.test(ip)) { + return true; + } + + return false; +} + +function isValidJWT(jwt: string, alg?: string): boolean { + if (!jwtRegex.test(jwt)) return false; + try { + const [header] = jwt.split("."); + if (!header) return false; + // Convert base64url to base64 + const base64 = header + .replace(/-/g, "+") + .replace(/_/g, "/") + .padEnd(header.length + ((4 - (header.length % 4)) % 4), "="); + // @ts-ignore + const decoded = JSON.parse(atob(base64)); + if (typeof decoded !== "object" || decoded === null) return false; + if ("typ" in decoded && decoded?.typ !== "JWT") return false; + if (!decoded.alg) return false; + if (alg && decoded.alg !== alg) return false; + return true; + } catch { + return false; + } +} + +function isValidCidr(ip: string, version?: IpVersion) { + if ((version === "v4" || !version) && ipv4CidrRegex.test(ip)) { + return true; + } + if ((version === "v6" || !version) && ipv6CidrRegex.test(ip)) { + return true; + } + + return false; +} + +export class ZodString extends ZodType { + _parse(input: ParseInput): ParseReturnType { + if (this._def.coerce) { + input.data = String(input.data); + } + const parsedType = this._getType(input); + + if (parsedType !== ZodParsedType.string) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.string, + received: ctx.parsedType, + }); + return INVALID; + } + + const status = new ParseStatus(); + let ctx: undefined | ParseContext = undefined; + + for (const check of this._def.checks) { + if (check.kind === "min") { + if (input.data.length < check.value) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.too_small, + minimum: check.value, + type: "string", + inclusive: true, + exact: false, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "max") { + if (input.data.length > check.value) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.too_big, + maximum: check.value, + type: "string", + inclusive: true, + exact: false, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "length") { + const tooBig = input.data.length > check.value; + const tooSmall = input.data.length < check.value; + if (tooBig || tooSmall) { + ctx = this._getOrReturnCtx(input, ctx); + if (tooBig) { + addIssueToContext(ctx, { + code: ZodIssueCode.too_big, + maximum: check.value, + type: "string", + inclusive: true, + exact: true, + message: check.message, + }); + } else if (tooSmall) { + addIssueToContext(ctx, { + code: ZodIssueCode.too_small, + minimum: check.value, + type: "string", + inclusive: true, + exact: true, + message: check.message, + }); + } + status.dirty(); + } + } else if (check.kind === "email") { + if (!emailRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "email", + code: ZodIssueCode.invalid_string, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "emoji") { + if (!emojiRegex) { + emojiRegex = new RegExp(_emojiRegex, "u"); + } + if (!emojiRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "emoji", + code: ZodIssueCode.invalid_string, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "uuid") { + if (!uuidRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "uuid", + code: ZodIssueCode.invalid_string, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "nanoid") { + if (!nanoidRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "nanoid", + code: ZodIssueCode.invalid_string, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "cuid") { + if (!cuidRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "cuid", + code: ZodIssueCode.invalid_string, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "cuid2") { + if (!cuid2Regex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "cuid2", + code: ZodIssueCode.invalid_string, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "ulid") { + if (!ulidRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "ulid", + code: ZodIssueCode.invalid_string, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "url") { + try { + // @ts-ignore + new URL(input.data); + } catch { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "url", + code: ZodIssueCode.invalid_string, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "regex") { + check.regex.lastIndex = 0; + const testResult = check.regex.test(input.data); + if (!testResult) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "regex", + code: ZodIssueCode.invalid_string, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "trim") { + input.data = input.data.trim(); + } else if (check.kind === "includes") { + if (!(input.data as string).includes(check.value, check.position)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_string, + validation: { includes: check.value, position: check.position }, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "toLowerCase") { + input.data = input.data.toLowerCase(); + } else if (check.kind === "toUpperCase") { + input.data = input.data.toUpperCase(); + } else if (check.kind === "startsWith") { + if (!(input.data as string).startsWith(check.value)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_string, + validation: { startsWith: check.value }, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "endsWith") { + if (!(input.data as string).endsWith(check.value)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_string, + validation: { endsWith: check.value }, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "datetime") { + const regex = datetimeRegex(check); + + if (!regex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_string, + validation: "datetime", + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "date") { + const regex = dateRegex; + + if (!regex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_string, + validation: "date", + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "time") { + const regex = timeRegex(check); + + if (!regex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_string, + validation: "time", + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "duration") { + if (!durationRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "duration", + code: ZodIssueCode.invalid_string, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "ip") { + if (!isValidIP(input.data, check.version)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "ip", + code: ZodIssueCode.invalid_string, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "jwt") { + if (!isValidJWT(input.data, check.alg)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "jwt", + code: ZodIssueCode.invalid_string, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "cidr") { + if (!isValidCidr(input.data, check.version)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "cidr", + code: ZodIssueCode.invalid_string, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "base64") { + if (!base64Regex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "base64", + code: ZodIssueCode.invalid_string, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "base64url") { + if (!base64urlRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + validation: "base64url", + code: ZodIssueCode.invalid_string, + message: check.message, + }); + status.dirty(); + } + } else { + util.assertNever(check); + } + } + + return { status: status.value, value: input.data }; + } + + protected _regex(regex: RegExp, validation: StringValidation, message?: errorUtil.ErrMessage) { + return this.refinement((data) => regex.test(data), { + validation, + code: ZodIssueCode.invalid_string, + ...errorUtil.errToObj(message), + }); + } + + _addCheck(check: ZodStringCheck) { + return new ZodString({ + ...this._def, + checks: [...this._def.checks, check], + }); + } + + email(message?: errorUtil.ErrMessage) { + return this._addCheck({ kind: "email", ...errorUtil.errToObj(message) }); + } + + url(message?: errorUtil.ErrMessage) { + return this._addCheck({ kind: "url", ...errorUtil.errToObj(message) }); + } + + emoji(message?: errorUtil.ErrMessage) { + return this._addCheck({ kind: "emoji", ...errorUtil.errToObj(message) }); + } + + uuid(message?: errorUtil.ErrMessage) { + return this._addCheck({ kind: "uuid", ...errorUtil.errToObj(message) }); + } + nanoid(message?: errorUtil.ErrMessage) { + return this._addCheck({ kind: "nanoid", ...errorUtil.errToObj(message) }); + } + cuid(message?: errorUtil.ErrMessage) { + return this._addCheck({ kind: "cuid", ...errorUtil.errToObj(message) }); + } + + cuid2(message?: errorUtil.ErrMessage) { + return this._addCheck({ kind: "cuid2", ...errorUtil.errToObj(message) }); + } + ulid(message?: errorUtil.ErrMessage) { + return this._addCheck({ kind: "ulid", ...errorUtil.errToObj(message) }); + } + base64(message?: errorUtil.ErrMessage) { + return this._addCheck({ kind: "base64", ...errorUtil.errToObj(message) }); + } + base64url(message?: errorUtil.ErrMessage) { + // base64url encoding is a modification of base64 that can safely be used in URLs and filenames + return this._addCheck({ + kind: "base64url", + ...errorUtil.errToObj(message), + }); + } + + jwt(options?: { alg?: string; message?: string | undefined }) { + return this._addCheck({ kind: "jwt", ...errorUtil.errToObj(options) }); + } + + ip(options?: string | { version?: IpVersion; message?: string | undefined }) { + return this._addCheck({ kind: "ip", ...errorUtil.errToObj(options) }); + } + + cidr(options?: string | { version?: IpVersion; message?: string | undefined }) { + return this._addCheck({ kind: "cidr", ...errorUtil.errToObj(options) }); + } + + datetime( + options?: + | string + | { + message?: string | undefined; + precision?: number | null; + offset?: boolean; + local?: boolean; + } + ) { + if (typeof options === "string") { + return this._addCheck({ + kind: "datetime", + precision: null, + offset: false, + local: false, + message: options, + }); + } + return this._addCheck({ + kind: "datetime", + + precision: typeof options?.precision === "undefined" ? null : options?.precision, + offset: options?.offset ?? false, + local: options?.local ?? false, + ...errorUtil.errToObj(options?.message), + }); + } + + date(message?: string) { + return this._addCheck({ kind: "date", message }); + } + + time( + options?: + | string + | { + message?: string | undefined; + precision?: number | null; + } + ) { + if (typeof options === "string") { + return this._addCheck({ + kind: "time", + precision: null, + message: options, + }); + } + return this._addCheck({ + kind: "time", + precision: typeof options?.precision === "undefined" ? null : options?.precision, + ...errorUtil.errToObj(options?.message), + }); + } + + duration(message?: errorUtil.ErrMessage) { + return this._addCheck({ kind: "duration", ...errorUtil.errToObj(message) }); + } + + regex(regex: RegExp, message?: errorUtil.ErrMessage) { + return this._addCheck({ + kind: "regex", + regex: regex, + ...errorUtil.errToObj(message), + }); + } + + includes(value: string, options?: { message?: string; position?: number }) { + return this._addCheck({ + kind: "includes", + value: value, + position: options?.position, + ...errorUtil.errToObj(options?.message), + }); + } + + startsWith(value: string, message?: errorUtil.ErrMessage) { + return this._addCheck({ + kind: "startsWith", + value: value, + ...errorUtil.errToObj(message), + }); + } + + endsWith(value: string, message?: errorUtil.ErrMessage) { + return this._addCheck({ + kind: "endsWith", + value: value, + ...errorUtil.errToObj(message), + }); + } + + min(minLength: number, message?: errorUtil.ErrMessage) { + return this._addCheck({ + kind: "min", + value: minLength, + ...errorUtil.errToObj(message), + }); + } + + max(maxLength: number, message?: errorUtil.ErrMessage) { + return this._addCheck({ + kind: "max", + value: maxLength, + ...errorUtil.errToObj(message), + }); + } + + length(len: number, message?: errorUtil.ErrMessage) { + return this._addCheck({ + kind: "length", + value: len, + ...errorUtil.errToObj(message), + }); + } + + /** + * Equivalent to `.min(1)` + */ + nonempty(message?: errorUtil.ErrMessage) { + return this.min(1, errorUtil.errToObj(message)); + } + + trim() { + return new ZodString({ + ...this._def, + checks: [...this._def.checks, { kind: "trim" }], + }); + } + + toLowerCase() { + return new ZodString({ + ...this._def, + checks: [...this._def.checks, { kind: "toLowerCase" }], + }); + } + + toUpperCase() { + return new ZodString({ + ...this._def, + checks: [...this._def.checks, { kind: "toUpperCase" }], + }); + } + + get isDatetime() { + return !!this._def.checks.find((ch) => ch.kind === "datetime"); + } + + get isDate() { + return !!this._def.checks.find((ch) => ch.kind === "date"); + } + + get isTime() { + return !!this._def.checks.find((ch) => ch.kind === "time"); + } + get isDuration() { + return !!this._def.checks.find((ch) => ch.kind === "duration"); + } + + get isEmail() { + return !!this._def.checks.find((ch) => ch.kind === "email"); + } + + get isURL() { + return !!this._def.checks.find((ch) => ch.kind === "url"); + } + + get isEmoji() { + return !!this._def.checks.find((ch) => ch.kind === "emoji"); + } + + get isUUID() { + return !!this._def.checks.find((ch) => ch.kind === "uuid"); + } + get isNANOID() { + return !!this._def.checks.find((ch) => ch.kind === "nanoid"); + } + get isCUID() { + return !!this._def.checks.find((ch) => ch.kind === "cuid"); + } + + get isCUID2() { + return !!this._def.checks.find((ch) => ch.kind === "cuid2"); + } + get isULID() { + return !!this._def.checks.find((ch) => ch.kind === "ulid"); + } + get isIP() { + return !!this._def.checks.find((ch) => ch.kind === "ip"); + } + get isCIDR() { + return !!this._def.checks.find((ch) => ch.kind === "cidr"); + } + get isBase64() { + return !!this._def.checks.find((ch) => ch.kind === "base64"); + } + get isBase64url() { + // base64url encoding is a modification of base64 that can safely be used in URLs and filenames + return !!this._def.checks.find((ch) => ch.kind === "base64url"); + } + + get minLength() { + let min: number | null = null; + for (const ch of this._def.checks) { + if (ch.kind === "min") { + if (min === null || ch.value > min) min = ch.value; + } + } + return min; + } + + get maxLength() { + let max: number | null = null; + for (const ch of this._def.checks) { + if (ch.kind === "max") { + if (max === null || ch.value < max) max = ch.value; + } + } + return max; + } + + static create = (params?: RawCreateParams & { coerce?: true }): ZodString => { + return new ZodString({ + checks: [], + typeName: ZodFirstPartyTypeKind.ZodString, + coerce: params?.coerce ?? false, + ...processCreateParams(params), + }); + }; +} + +///////////////////////////////////////// +///////////////////////////////////////// +////////// ////////// +////////// ZodNumber ////////// +////////// ////////// +///////////////////////////////////////// +///////////////////////////////////////// +export type ZodNumberCheck = + | { kind: "min"; value: number; inclusive: boolean; message?: string | undefined } + | { kind: "max"; value: number; inclusive: boolean; message?: string | undefined } + | { kind: "int"; message?: string | undefined } + | { kind: "multipleOf"; value: number; message?: string | undefined } + | { kind: "finite"; message?: string | undefined }; + +// https://stackoverflow.com/questions/3966484/why-does-modulus-operator-return-fractional-number-in-javascript/31711034#31711034 +function floatSafeRemainder(val: number, step: number) { + const valDecCount = (val.toString().split(".")[1] || "").length; + const stepDecCount = (step.toString().split(".")[1] || "").length; + const decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount; + const valInt = Number.parseInt(val.toFixed(decCount).replace(".", "")); + const stepInt = Number.parseInt(step.toFixed(decCount).replace(".", "")); + return (valInt % stepInt) / 10 ** decCount; +} + +export interface ZodNumberDef extends ZodTypeDef { + checks: ZodNumberCheck[]; + typeName: ZodFirstPartyTypeKind.ZodNumber; + coerce: boolean; +} + +export class ZodNumber extends ZodType { + _parse(input: ParseInput): ParseReturnType { + if (this._def.coerce) { + input.data = Number(input.data); + } + const parsedType = this._getType(input); + if (parsedType !== ZodParsedType.number) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.number, + received: ctx.parsedType, + }); + return INVALID; + } + + let ctx: undefined | ParseContext = undefined; + const status = new ParseStatus(); + + for (const check of this._def.checks) { + if (check.kind === "int") { + if (!util.isInteger(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: "integer", + received: "float", + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "min") { + const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value; + if (tooSmall) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.too_small, + minimum: check.value, + type: "number", + inclusive: check.inclusive, + exact: false, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "max") { + const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value; + if (tooBig) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.too_big, + maximum: check.value, + type: "number", + inclusive: check.inclusive, + exact: false, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "multipleOf") { + if (floatSafeRemainder(input.data, check.value) !== 0) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.not_multiple_of, + multipleOf: check.value, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "finite") { + if (!Number.isFinite(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.not_finite, + message: check.message, + }); + status.dirty(); + } + } else { + util.assertNever(check); + } + } + + return { status: status.value, value: input.data }; + } + + static create = (params?: RawCreateParams & { coerce?: boolean }): ZodNumber => { + return new ZodNumber({ + checks: [], + typeName: ZodFirstPartyTypeKind.ZodNumber, + coerce: params?.coerce || false, + ...processCreateParams(params), + }); + }; + + gte(value: number, message?: errorUtil.ErrMessage) { + return this.setLimit("min", value, true, errorUtil.toString(message)); + } + min = this.gte; + + gt(value: number, message?: errorUtil.ErrMessage) { + return this.setLimit("min", value, false, errorUtil.toString(message)); + } + + lte(value: number, message?: errorUtil.ErrMessage) { + return this.setLimit("max", value, true, errorUtil.toString(message)); + } + max = this.lte; + + lt(value: number, message?: errorUtil.ErrMessage) { + return this.setLimit("max", value, false, errorUtil.toString(message)); + } + + protected setLimit(kind: "min" | "max", value: number, inclusive: boolean, message?: string) { + return new ZodNumber({ + ...this._def, + checks: [ + ...this._def.checks, + { + kind, + value, + inclusive, + message: errorUtil.toString(message), + }, + ], + }); + } + + _addCheck(check: ZodNumberCheck) { + return new ZodNumber({ + ...this._def, + checks: [...this._def.checks, check], + }); + } + + int(message?: errorUtil.ErrMessage) { + return this._addCheck({ + kind: "int", + message: errorUtil.toString(message), + }); + } + + positive(message?: errorUtil.ErrMessage) { + return this._addCheck({ + kind: "min", + value: 0, + inclusive: false, + message: errorUtil.toString(message), + }); + } + + negative(message?: errorUtil.ErrMessage) { + return this._addCheck({ + kind: "max", + value: 0, + inclusive: false, + message: errorUtil.toString(message), + }); + } + + nonpositive(message?: errorUtil.ErrMessage) { + return this._addCheck({ + kind: "max", + value: 0, + inclusive: true, + message: errorUtil.toString(message), + }); + } + + nonnegative(message?: errorUtil.ErrMessage) { + return this._addCheck({ + kind: "min", + value: 0, + inclusive: true, + message: errorUtil.toString(message), + }); + } + + multipleOf(value: number, message?: errorUtil.ErrMessage) { + return this._addCheck({ + kind: "multipleOf", + value: value, + message: errorUtil.toString(message), + }); + } + step = this.multipleOf; + + finite(message?: errorUtil.ErrMessage) { + return this._addCheck({ + kind: "finite", + message: errorUtil.toString(message), + }); + } + + safe(message?: errorUtil.ErrMessage) { + return this._addCheck({ + kind: "min", + inclusive: true, + value: Number.MIN_SAFE_INTEGER, + message: errorUtil.toString(message), + })._addCheck({ + kind: "max", + inclusive: true, + value: Number.MAX_SAFE_INTEGER, + message: errorUtil.toString(message), + }); + } + + get minValue() { + let min: number | null = null; + for (const ch of this._def.checks) { + if (ch.kind === "min") { + if (min === null || ch.value > min) min = ch.value; + } + } + return min; + } + + get maxValue() { + let max: number | null = null; + for (const ch of this._def.checks) { + if (ch.kind === "max") { + if (max === null || ch.value < max) max = ch.value; + } + } + return max; + } + + get isInt() { + return !!this._def.checks.find((ch) => ch.kind === "int" || (ch.kind === "multipleOf" && util.isInteger(ch.value))); + } + + get isFinite() { + let max: number | null = null; + let min: number | null = null; + for (const ch of this._def.checks) { + if (ch.kind === "finite" || ch.kind === "int" || ch.kind === "multipleOf") { + return true; + } else if (ch.kind === "min") { + if (min === null || ch.value > min) min = ch.value; + } else if (ch.kind === "max") { + if (max === null || ch.value < max) max = ch.value; + } + } + return Number.isFinite(min) && Number.isFinite(max); + } +} + +///////////////////////////////////////// +///////////////////////////////////////// +////////// ////////// +////////// ZodBigInt ////////// +////////// ////////// +///////////////////////////////////////// +///////////////////////////////////////// +export type ZodBigIntCheck = + | { kind: "min"; value: bigint; inclusive: boolean; message?: string | undefined } + | { kind: "max"; value: bigint; inclusive: boolean; message?: string | undefined } + | { kind: "multipleOf"; value: bigint; message?: string | undefined }; + +export interface ZodBigIntDef extends ZodTypeDef { + checks: ZodBigIntCheck[]; + typeName: ZodFirstPartyTypeKind.ZodBigInt; + coerce: boolean; +} + +export class ZodBigInt extends ZodType { + _parse(input: ParseInput): ParseReturnType { + if (this._def.coerce) { + try { + input.data = BigInt(input.data); + } catch { + return this._getInvalidInput(input); + } + } + const parsedType = this._getType(input); + if (parsedType !== ZodParsedType.bigint) { + return this._getInvalidInput(input); + } + + let ctx: undefined | ParseContext = undefined; + const status = new ParseStatus(); + + for (const check of this._def.checks) { + if (check.kind === "min") { + const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value; + if (tooSmall) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.too_small, + type: "bigint", + minimum: check.value, + inclusive: check.inclusive, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "max") { + const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value; + if (tooBig) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.too_big, + type: "bigint", + maximum: check.value, + inclusive: check.inclusive, + message: check.message, + }); + status.dirty(); + } + } else if (check.kind === "multipleOf") { + if (input.data % check.value !== BigInt(0)) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.not_multiple_of, + multipleOf: check.value, + message: check.message, + }); + status.dirty(); + } + } else { + util.assertNever(check); + } + } + + return { status: status.value, value: input.data }; + } + + _getInvalidInput(input: ParseInput) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.bigint, + received: ctx.parsedType, + }); + return INVALID; + } + + static create = (params?: RawCreateParams & { coerce?: boolean }): ZodBigInt => { + return new ZodBigInt({ + checks: [], + typeName: ZodFirstPartyTypeKind.ZodBigInt, + coerce: params?.coerce ?? false, + ...processCreateParams(params), + }); + }; + + gte(value: bigint, message?: errorUtil.ErrMessage) { + return this.setLimit("min", value, true, errorUtil.toString(message)); + } + min = this.gte; + + gt(value: bigint, message?: errorUtil.ErrMessage) { + return this.setLimit("min", value, false, errorUtil.toString(message)); + } + + lte(value: bigint, message?: errorUtil.ErrMessage) { + return this.setLimit("max", value, true, errorUtil.toString(message)); + } + max = this.lte; + + lt(value: bigint, message?: errorUtil.ErrMessage) { + return this.setLimit("max", value, false, errorUtil.toString(message)); + } + + protected setLimit(kind: "min" | "max", value: bigint, inclusive: boolean, message?: string) { + return new ZodBigInt({ + ...this._def, + checks: [ + ...this._def.checks, + { + kind, + value, + inclusive, + message: errorUtil.toString(message), + }, + ], + }); + } + + _addCheck(check: ZodBigIntCheck) { + return new ZodBigInt({ + ...this._def, + checks: [...this._def.checks, check], + }); + } + + positive(message?: errorUtil.ErrMessage) { + return this._addCheck({ + kind: "min", + value: BigInt(0), + inclusive: false, + message: errorUtil.toString(message), + }); + } + + negative(message?: errorUtil.ErrMessage) { + return this._addCheck({ + kind: "max", + value: BigInt(0), + inclusive: false, + message: errorUtil.toString(message), + }); + } + + nonpositive(message?: errorUtil.ErrMessage) { + return this._addCheck({ + kind: "max", + value: BigInt(0), + inclusive: true, + message: errorUtil.toString(message), + }); + } + + nonnegative(message?: errorUtil.ErrMessage) { + return this._addCheck({ + kind: "min", + value: BigInt(0), + inclusive: true, + message: errorUtil.toString(message), + }); + } + + multipleOf(value: bigint, message?: errorUtil.ErrMessage) { + return this._addCheck({ + kind: "multipleOf", + value, + message: errorUtil.toString(message), + }); + } + + get minValue() { + let min: bigint | null = null; + for (const ch of this._def.checks) { + if (ch.kind === "min") { + if (min === null || ch.value > min) min = ch.value; + } + } + return min; + } + + get maxValue() { + let max: bigint | null = null; + for (const ch of this._def.checks) { + if (ch.kind === "max") { + if (max === null || ch.value < max) max = ch.value; + } + } + return max; + } +} + +////////////////////////////////////////// +////////////////////////////////////////// +////////// /////////// +////////// ZodBoolean ////////// +////////// /////////// +////////////////////////////////////////// +////////////////////////////////////////// +export interface ZodBooleanDef extends ZodTypeDef { + typeName: ZodFirstPartyTypeKind.ZodBoolean; + coerce: boolean; +} + +export class ZodBoolean extends ZodType { + _parse(input: ParseInput): ParseReturnType { + if (this._def.coerce) { + input.data = Boolean(input.data); + } + const parsedType = this._getType(input); + + if (parsedType !== ZodParsedType.boolean) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.boolean, + received: ctx.parsedType, + }); + return INVALID; + } + return OK(input.data); + } + + static create = (params?: RawCreateParams & { coerce?: boolean }): ZodBoolean => { + return new ZodBoolean({ + typeName: ZodFirstPartyTypeKind.ZodBoolean, + coerce: params?.coerce || false, + ...processCreateParams(params), + }); + }; +} + +/////////////////////////////////////// +/////////////////////////////////////// +////////// //////// +////////// ZodDate //////// +////////// //////// +/////////////////////////////////////// +/////////////////////////////////////// +export type ZodDateCheck = + | { kind: "min"; value: number; message?: string | undefined } + | { kind: "max"; value: number; message?: string | undefined }; +export interface ZodDateDef extends ZodTypeDef { + checks: ZodDateCheck[]; + coerce: boolean; + typeName: ZodFirstPartyTypeKind.ZodDate; +} + +export class ZodDate extends ZodType { + _parse(input: ParseInput): ParseReturnType { + if (this._def.coerce) { + input.data = new Date(input.data); + } + const parsedType = this._getType(input); + + if (parsedType !== ZodParsedType.date) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.date, + received: ctx.parsedType, + }); + return INVALID; + } + + if (Number.isNaN(input.data.getTime())) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_date, + }); + return INVALID; + } + + const status = new ParseStatus(); + let ctx: undefined | ParseContext = undefined; + + for (const check of this._def.checks) { + if (check.kind === "min") { + if (input.data.getTime() < check.value) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.too_small, + message: check.message, + inclusive: true, + exact: false, + minimum: check.value, + type: "date", + }); + status.dirty(); + } + } else if (check.kind === "max") { + if (input.data.getTime() > check.value) { + ctx = this._getOrReturnCtx(input, ctx); + addIssueToContext(ctx, { + code: ZodIssueCode.too_big, + message: check.message, + inclusive: true, + exact: false, + maximum: check.value, + type: "date", + }); + status.dirty(); + } + } else { + util.assertNever(check); + } + } + + return { + status: status.value, + value: new Date((input.data as Date).getTime()), + }; + } + + _addCheck(check: ZodDateCheck) { + return new ZodDate({ + ...this._def, + checks: [...this._def.checks, check], + }); + } + + min(minDate: Date, message?: errorUtil.ErrMessage) { + return this._addCheck({ + kind: "min", + value: minDate.getTime(), + message: errorUtil.toString(message), + }); + } + + max(maxDate: Date, message?: errorUtil.ErrMessage) { + return this._addCheck({ + kind: "max", + value: maxDate.getTime(), + message: errorUtil.toString(message), + }); + } + + get minDate() { + let min: number | null = null; + for (const ch of this._def.checks) { + if (ch.kind === "min") { + if (min === null || ch.value > min) min = ch.value; + } + } + + return min != null ? new Date(min) : null; + } + + get maxDate() { + let max: number | null = null; + for (const ch of this._def.checks) { + if (ch.kind === "max") { + if (max === null || ch.value < max) max = ch.value; + } + } + + return max != null ? new Date(max) : null; + } + + static create = (params?: RawCreateParams & { coerce?: boolean }): ZodDate => { + return new ZodDate({ + checks: [], + coerce: params?.coerce || false, + typeName: ZodFirstPartyTypeKind.ZodDate, + ...processCreateParams(params), + }); + }; +} + +//////////////////////////////////////////// +//////////////////////////////////////////// +////////// ////////// +////////// ZodSymbol ////////// +////////// ////////// +//////////////////////////////////////////// +//////////////////////////////////////////// +export interface ZodSymbolDef extends ZodTypeDef { + typeName: ZodFirstPartyTypeKind.ZodSymbol; +} + +export class ZodSymbol extends ZodType { + _parse(input: ParseInput): ParseReturnType { + const parsedType = this._getType(input); + if (parsedType !== ZodParsedType.symbol) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.symbol, + received: ctx.parsedType, + }); + return INVALID; + } + + return OK(input.data); + } + + static create = (params?: RawCreateParams): ZodSymbol => { + return new ZodSymbol({ + typeName: ZodFirstPartyTypeKind.ZodSymbol, + ...processCreateParams(params), + }); + }; +} + +//////////////////////////////////////////// +//////////////////////////////////////////// +////////// ////////// +////////// ZodUndefined ////////// +////////// ////////// +//////////////////////////////////////////// +//////////////////////////////////////////// +export interface ZodUndefinedDef extends ZodTypeDef { + typeName: ZodFirstPartyTypeKind.ZodUndefined; +} + +export class ZodUndefined extends ZodType { + _parse(input: ParseInput): ParseReturnType { + const parsedType = this._getType(input); + if (parsedType !== ZodParsedType.undefined) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.undefined, + received: ctx.parsedType, + }); + return INVALID; + } + return OK(input.data); + } + params?: RawCreateParams; + + static create = (params?: RawCreateParams): ZodUndefined => { + return new ZodUndefined({ + typeName: ZodFirstPartyTypeKind.ZodUndefined, + ...processCreateParams(params), + }); + }; +} + +/////////////////////////////////////// +/////////////////////////////////////// +////////// ////////// +////////// ZodNull ////////// +////////// ////////// +/////////////////////////////////////// +/////////////////////////////////////// +export interface ZodNullDef extends ZodTypeDef { + typeName: ZodFirstPartyTypeKind.ZodNull; +} + +export class ZodNull extends ZodType { + _parse(input: ParseInput): ParseReturnType { + const parsedType = this._getType(input); + if (parsedType !== ZodParsedType.null) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.null, + received: ctx.parsedType, + }); + return INVALID; + } + return OK(input.data); + } + static create = (params?: RawCreateParams): ZodNull => { + return new ZodNull({ + typeName: ZodFirstPartyTypeKind.ZodNull, + ...processCreateParams(params), + }); + }; +} + +////////////////////////////////////// +////////////////////////////////////// +////////// ////////// +////////// ZodAny ////////// +////////// ////////// +////////////////////////////////////// +////////////////////////////////////// +export interface ZodAnyDef extends ZodTypeDef { + typeName: ZodFirstPartyTypeKind.ZodAny; +} + +export class ZodAny extends ZodType { + // to prevent instances of other classes from extending ZodAny. this causes issues with catchall in ZodObject. + _any = true as const; + _parse(input: ParseInput): ParseReturnType { + return OK(input.data); + } + static create = (params?: RawCreateParams): ZodAny => { + return new ZodAny({ + typeName: ZodFirstPartyTypeKind.ZodAny, + ...processCreateParams(params), + }); + }; +} + +////////////////////////////////////////// +////////////////////////////////////////// +////////// ////////// +////////// ZodUnknown ////////// +////////// ////////// +////////////////////////////////////////// +////////////////////////////////////////// +export interface ZodUnknownDef extends ZodTypeDef { + typeName: ZodFirstPartyTypeKind.ZodUnknown; +} + +export class ZodUnknown extends ZodType { + // required + _unknown = true as const; + _parse(input: ParseInput): ParseReturnType { + return OK(input.data); + } + + static create = (params?: RawCreateParams): ZodUnknown => { + return new ZodUnknown({ + typeName: ZodFirstPartyTypeKind.ZodUnknown, + ...processCreateParams(params), + }); + }; +} + +//////////////////////////////////////// +//////////////////////////////////////// +////////// ////////// +////////// ZodNever ////////// +////////// ////////// +//////////////////////////////////////// +//////////////////////////////////////// +export interface ZodNeverDef extends ZodTypeDef { + typeName: ZodFirstPartyTypeKind.ZodNever; +} + +export class ZodNever extends ZodType { + _parse(input: ParseInput): ParseReturnType { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.never, + received: ctx.parsedType, + }); + return INVALID; + } + static create = (params?: RawCreateParams): ZodNever => { + return new ZodNever({ + typeName: ZodFirstPartyTypeKind.ZodNever, + ...processCreateParams(params), + }); + }; +} + +/////////////////////////////////////// +/////////////////////////////////////// +////////// ////////// +////////// ZodVoid ////////// +////////// ////////// +/////////////////////////////////////// +/////////////////////////////////////// +export interface ZodVoidDef extends ZodTypeDef { + typeName: ZodFirstPartyTypeKind.ZodVoid; +} + +export class ZodVoid extends ZodType { + _parse(input: ParseInput): ParseReturnType { + const parsedType = this._getType(input); + if (parsedType !== ZodParsedType.undefined) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.void, + received: ctx.parsedType, + }); + return INVALID; + } + return OK(input.data); + } + + static create = (params?: RawCreateParams): ZodVoid => { + return new ZodVoid({ + typeName: ZodFirstPartyTypeKind.ZodVoid, + ...processCreateParams(params), + }); + }; +} + +//////////////////////////////////////// +//////////////////////////////////////// +////////// ////////// +////////// ZodArray ////////// +////////// ////////// +//////////////////////////////////////// +//////////////////////////////////////// +export interface ZodArrayDef extends ZodTypeDef { + type: T; + typeName: ZodFirstPartyTypeKind.ZodArray; + exactLength: { value: number; message?: string | undefined } | null; + minLength: { value: number; message?: string | undefined } | null; + maxLength: { value: number; message?: string | undefined } | null; +} + +export type ArrayCardinality = "many" | "atleastone"; +export type arrayOutputType< + T extends ZodTypeAny, + Cardinality extends ArrayCardinality = "many", +> = Cardinality extends "atleastone" ? [T["_output"], ...T["_output"][]] : T["_output"][]; + +export class ZodArray extends ZodType< + arrayOutputType, + ZodArrayDef, + Cardinality extends "atleastone" ? [T["_input"], ...T["_input"][]] : T["_input"][] +> { + _parse(input: ParseInput): ParseReturnType { + const { ctx, status } = this._processInputParams(input); + + const def = this._def; + + if (ctx.parsedType !== ZodParsedType.array) { + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.array, + received: ctx.parsedType, + }); + return INVALID; + } + + if (def.exactLength !== null) { + const tooBig = ctx.data.length > def.exactLength.value; + const tooSmall = ctx.data.length < def.exactLength.value; + if (tooBig || tooSmall) { + addIssueToContext(ctx, { + code: tooBig ? ZodIssueCode.too_big : ZodIssueCode.too_small, + minimum: (tooSmall ? def.exactLength.value : undefined) as number, + maximum: (tooBig ? def.exactLength.value : undefined) as number, + type: "array", + inclusive: true, + exact: true, + message: def.exactLength.message, + }); + status.dirty(); + } + } + + if (def.minLength !== null) { + if (ctx.data.length < def.minLength.value) { + addIssueToContext(ctx, { + code: ZodIssueCode.too_small, + minimum: def.minLength.value, + type: "array", + inclusive: true, + exact: false, + message: def.minLength.message, + }); + status.dirty(); + } + } + + if (def.maxLength !== null) { + if (ctx.data.length > def.maxLength.value) { + addIssueToContext(ctx, { + code: ZodIssueCode.too_big, + maximum: def.maxLength.value, + type: "array", + inclusive: true, + exact: false, + message: def.maxLength.message, + }); + status.dirty(); + } + } + + if (ctx.common.async) { + return Promise.all( + ([...ctx.data] as any[]).map((item, i) => { + return def.type._parseAsync(new ParseInputLazyPath(ctx, item, ctx.path, i)); + }) + ).then((result) => { + return ParseStatus.mergeArray(status, result); + }); + } + + const result = ([...ctx.data] as any[]).map((item, i) => { + return def.type._parseSync(new ParseInputLazyPath(ctx, item, ctx.path, i)); + }); + + return ParseStatus.mergeArray(status, result); + } + + get element() { + return this._def.type; + } + + min(minLength: number, message?: errorUtil.ErrMessage): this { + return new ZodArray({ + ...this._def, + minLength: { value: minLength, message: errorUtil.toString(message) }, + }) as any; + } + + max(maxLength: number, message?: errorUtil.ErrMessage): this { + return new ZodArray({ + ...this._def, + maxLength: { value: maxLength, message: errorUtil.toString(message) }, + }) as any; + } + + length(len: number, message?: errorUtil.ErrMessage): this { + return new ZodArray({ + ...this._def, + exactLength: { value: len, message: errorUtil.toString(message) }, + }) as any; + } + + nonempty(message?: errorUtil.ErrMessage): ZodArray { + return this.min(1, message) as any; + } + + static create = (schema: El, params?: RawCreateParams): ZodArray => { + return new ZodArray({ + type: schema, + minLength: null, + maxLength: null, + exactLength: null, + typeName: ZodFirstPartyTypeKind.ZodArray, + ...processCreateParams(params), + }); + }; +} + +export type ZodNonEmptyArray = ZodArray; + +///////////////////////////////////////// +///////////////////////////////////////// +////////// ////////// +////////// ZodObject ////////// +////////// ////////// +///////////////////////////////////////// +///////////////////////////////////////// + +export type UnknownKeysParam = "passthrough" | "strict" | "strip"; + +export interface ZodObjectDef< + T extends ZodRawShape = ZodRawShape, + UnknownKeys extends UnknownKeysParam = UnknownKeysParam, + Catchall extends ZodTypeAny = ZodTypeAny, +> extends ZodTypeDef { + typeName: ZodFirstPartyTypeKind.ZodObject; + shape: () => T; + catchall: Catchall; + unknownKeys: UnknownKeys; +} + +export type mergeTypes = { + [k in keyof A | keyof B]: k extends keyof B ? B[k] : k extends keyof A ? A[k] : never; +}; + +export type objectOutputType< + Shape extends ZodRawShape, + Catchall extends ZodTypeAny, + UnknownKeys extends UnknownKeysParam = UnknownKeysParam, +> = objectUtil.flatten>> & + CatchallOutput & + PassthroughType; + +export type baseObjectOutputType = { + [k in keyof Shape]: Shape[k]["_output"]; +}; + +export type objectInputType< + Shape extends ZodRawShape, + Catchall extends ZodTypeAny, + UnknownKeys extends UnknownKeysParam = UnknownKeysParam, +> = objectUtil.flatten> & CatchallInput & PassthroughType; +export type baseObjectInputType = objectUtil.addQuestionMarks<{ + [k in keyof Shape]: Shape[k]["_input"]; +}>; + +export type CatchallOutput = ZodType extends T ? unknown : { [k: string]: T["_output"] }; + +export type CatchallInput = ZodType extends T ? unknown : { [k: string]: T["_input"] }; + +export type PassthroughType = T extends "passthrough" ? { [k: string]: unknown } : unknown; + +export type deoptional = T extends ZodOptional + ? deoptional + : T extends ZodNullable + ? ZodNullable> + : T; + +export type SomeZodObject = ZodObject; + +export type noUnrecognized = { + [k in keyof Obj]: k extends keyof Shape ? Obj[k] : never; +}; + +function deepPartialify(schema: ZodTypeAny): any { + if (schema instanceof ZodObject) { + const newShape: any = {}; + + for (const key in schema.shape) { + const fieldSchema = schema.shape[key]; + newShape[key] = ZodOptional.create(deepPartialify(fieldSchema)); + } + return new ZodObject({ + ...schema._def, + shape: () => newShape, + }) as any; + } else if (schema instanceof ZodArray) { + return new ZodArray({ + ...schema._def, + type: deepPartialify(schema.element), + }); + } else if (schema instanceof ZodOptional) { + return ZodOptional.create(deepPartialify(schema.unwrap())); + } else if (schema instanceof ZodNullable) { + return ZodNullable.create(deepPartialify(schema.unwrap())); + } else if (schema instanceof ZodTuple) { + return ZodTuple.create(schema.items.map((item: any) => deepPartialify(item))); + } else { + return schema; + } +} + +export class ZodObject< + T extends ZodRawShape, + UnknownKeys extends UnknownKeysParam = UnknownKeysParam, + Catchall extends ZodTypeAny = ZodTypeAny, + Output = objectOutputType, + Input = objectInputType, +> extends ZodType, Input> { + _cached: { shape: T; keys: string[] } | null = null; + + _getCached(): { shape: T; keys: string[] } { + if (this._cached !== null) return this._cached; + const shape = this._def.shape(); + const keys = util.objectKeys(shape); + this._cached = { shape, keys }; + return this._cached; + } + + _parse(input: ParseInput): ParseReturnType { + const parsedType = this._getType(input); + if (parsedType !== ZodParsedType.object) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.object, + received: ctx.parsedType, + }); + return INVALID; + } + + const { status, ctx } = this._processInputParams(input); + + const { shape, keys: shapeKeys } = this._getCached(); + const extraKeys: string[] = []; + + if (!(this._def.catchall instanceof ZodNever && this._def.unknownKeys === "strip")) { + for (const key in ctx.data) { + if (!shapeKeys.includes(key)) { + extraKeys.push(key); + } + } + } + + const pairs: { + key: ParseReturnType; + value: ParseReturnType; + alwaysSet?: boolean; + }[] = []; + for (const key of shapeKeys) { + const keyValidator = shape[key]!; + const value = ctx.data[key]; + pairs.push({ + key: { status: "valid", value: key }, + value: keyValidator._parse(new ParseInputLazyPath(ctx, value, ctx.path, key)), + alwaysSet: key in ctx.data, + }); + } + + if (this._def.catchall instanceof ZodNever) { + const unknownKeys = this._def.unknownKeys; + + if (unknownKeys === "passthrough") { + for (const key of extraKeys) { + pairs.push({ + key: { status: "valid", value: key }, + value: { status: "valid", value: ctx.data[key] }, + }); + } + } else if (unknownKeys === "strict") { + if (extraKeys.length > 0) { + addIssueToContext(ctx, { + code: ZodIssueCode.unrecognized_keys, + keys: extraKeys, + }); + status.dirty(); + } + } else if (unknownKeys === "strip") { + } else { + throw new Error(`Internal ZodObject error: invalid unknownKeys value.`); + } + } else { + // run catchall validation + const catchall = this._def.catchall; + + for (const key of extraKeys) { + const value = ctx.data[key]; + pairs.push({ + key: { status: "valid", value: key }, + value: catchall._parse( + new ParseInputLazyPath(ctx, value, ctx.path, key) //, ctx.child(key), value, getParsedType(value) + ), + alwaysSet: key in ctx.data, + }); + } + } + + if (ctx.common.async) { + return Promise.resolve() + .then(async () => { + const syncPairs: any[] = []; + for (const pair of pairs) { + const key = await pair.key; + const value = await pair.value; + syncPairs.push({ + key, + value, + alwaysSet: pair.alwaysSet, + }); + } + return syncPairs; + }) + .then((syncPairs) => { + return ParseStatus.mergeObjectSync(status, syncPairs); + }); + } else { + return ParseStatus.mergeObjectSync(status, pairs as any); + } + } + + get shape() { + return this._def.shape(); + } + + strict(message?: errorUtil.ErrMessage): ZodObject { + errorUtil.errToObj; + return new ZodObject({ + ...this._def, + unknownKeys: "strict", + ...(message !== undefined + ? { + errorMap: (issue, ctx) => { + const defaultError = this._def.errorMap?.(issue, ctx).message ?? ctx.defaultError; + if (issue.code === "unrecognized_keys") + return { + message: errorUtil.errToObj(message).message ?? defaultError, + }; + return { + message: defaultError, + }; + }, + } + : {}), + }) as any; + } + + strip(): ZodObject { + return new ZodObject({ + ...this._def, + unknownKeys: "strip", + }) as any; + } + + passthrough(): ZodObject { + return new ZodObject({ + ...this._def, + unknownKeys: "passthrough", + }) as any; + } + + /** + * @deprecated In most cases, this is no longer needed - unknown properties are now silently stripped. + * If you want to pass through unknown properties, use `.passthrough()` instead. + */ + nonstrict = this.passthrough; + + // const AugmentFactory = + // (def: Def) => + // ( + // augmentation: Augmentation + // ): ZodObject< + // extendShape, Augmentation>, + // Def["unknownKeys"], + // Def["catchall"] + // > => { + // return new ZodObject({ + // ...def, + // shape: () => ({ + // ...def.shape(), + // ...augmentation, + // }), + // }) as any; + // }; + extend( + augmentation: Augmentation + ): ZodObject, UnknownKeys, Catchall> { + return new ZodObject({ + ...this._def, + shape: () => ({ + ...this._def.shape(), + ...augmentation, + }), + }) as any; + } + // extend< + // Augmentation extends ZodRawShape, + // NewOutput extends util.flatten<{ + // [k in keyof Augmentation | keyof Output]: k extends keyof Augmentation + // ? Augmentation[k]["_output"] + // : k extends keyof Output + // ? Output[k] + // : never; + // }>, + // NewInput extends util.flatten<{ + // [k in keyof Augmentation | keyof Input]: k extends keyof Augmentation + // ? Augmentation[k]["_input"] + // : k extends keyof Input + // ? Input[k] + // : never; + // }> + // >( + // augmentation: Augmentation + // ): ZodObject< + // extendShape, + // UnknownKeys, + // Catchall, + // NewOutput, + // NewInput + // > { + // return new ZodObject({ + // ...this._def, + // shape: () => ({ + // ...this._def.shape(), + // ...augmentation, + // }), + // }) as any; + // } + /** + * @deprecated Use `.extend` instead + * */ + augment = this.extend; + + /** + * Prior to zod@1.0.12 there was a bug in the + * inferred type of merged objects. Please + * upgrade if you are experiencing issues. + */ + merge( + merging: Incoming + ): ZodObject, Incoming["_def"]["unknownKeys"], Incoming["_def"]["catchall"]> { + const merged: any = new ZodObject({ + unknownKeys: merging._def.unknownKeys, + catchall: merging._def.catchall, + shape: () => ({ + ...this._def.shape(), + ...merging._def.shape(), + }), + typeName: ZodFirstPartyTypeKind.ZodObject, + }) as any; + return merged; + } + // merge< + // Incoming extends AnyZodObject, + // Augmentation extends Incoming["shape"], + // NewOutput extends { + // [k in keyof Augmentation | keyof Output]: k extends keyof Augmentation + // ? Augmentation[k]["_output"] + // : k extends keyof Output + // ? Output[k] + // : never; + // }, + // NewInput extends { + // [k in keyof Augmentation | keyof Input]: k extends keyof Augmentation + // ? Augmentation[k]["_input"] + // : k extends keyof Input + // ? Input[k] + // : never; + // } + // >( + // merging: Incoming + // ): ZodObject< + // extendShape>, + // Incoming["_def"]["unknownKeys"], + // Incoming["_def"]["catchall"], + // NewOutput, + // NewInput + // > { + // const merged: any = new ZodObject({ + // unknownKeys: merging._def.unknownKeys, + // catchall: merging._def.catchall, + // shape: () => + // objectUtil.mergeShapes(this._def.shape(), merging._def.shape()), + // typeName: ZodFirstPartyTypeKind.ZodObject, + // }) as any; + // return merged; + // } + + setKey( + key: Key, + schema: Schema + ): ZodObject { + return this.augment({ [key]: schema }) as any; + } + // merge( + // merging: Incoming + // ): //ZodObject = (merging) => { + // ZodObject< + // extendShape>, + // Incoming["_def"]["unknownKeys"], + // Incoming["_def"]["catchall"] + // > { + // // const mergedShape = objectUtil.mergeShapes( + // // this._def.shape(), + // // merging._def.shape() + // // ); + // const merged: any = new ZodObject({ + // unknownKeys: merging._def.unknownKeys, + // catchall: merging._def.catchall, + // shape: () => + // objectUtil.mergeShapes(this._def.shape(), merging._def.shape()), + // typeName: ZodFirstPartyTypeKind.ZodObject, + // }) as any; + // return merged; + // } + + catchall(index: Index): ZodObject { + return new ZodObject({ + ...this._def, + catchall: index, + }) as any; + } + + pick>( + mask: Mask + ): ZodObject>, UnknownKeys, Catchall> { + const shape: any = {}; + + for (const key of util.objectKeys(mask)) { + if (mask[key] && this.shape[key]) { + shape[key] = this.shape[key]; + } + } + + return new ZodObject({ + ...this._def, + shape: () => shape, + }) as any; + } + + omit>( + mask: Mask + ): ZodObject, UnknownKeys, Catchall> { + const shape: any = {}; + + for (const key of util.objectKeys(this.shape)) { + if (!mask[key]) { + shape[key] = this.shape[key]; + } + } + + return new ZodObject({ + ...this._def, + shape: () => shape, + }) as any; + } + + /** + * @deprecated + */ + deepPartial(): partialUtil.DeepPartial { + return deepPartialify(this); + } + + partial(): ZodObject<{ [k in keyof T]: ZodOptional }, UnknownKeys, Catchall>; + partial>( + mask: Mask + ): ZodObject< + objectUtil.noNever<{ + [k in keyof T]: k extends keyof Mask ? ZodOptional : T[k]; + }>, + UnknownKeys, + Catchall + >; + partial(mask?: any) { + const newShape: any = {}; + + for (const key of util.objectKeys(this.shape)) { + const fieldSchema = this.shape[key]!; + + if (mask && !mask[key]) { + newShape[key] = fieldSchema; + } else { + newShape[key] = fieldSchema.optional(); + } + } + + return new ZodObject({ + ...this._def, + shape: () => newShape, + }) as any; + } + + required(): ZodObject<{ [k in keyof T]: deoptional }, UnknownKeys, Catchall>; + required>( + mask: Mask + ): ZodObject< + objectUtil.noNever<{ + [k in keyof T]: k extends keyof Mask ? deoptional : T[k]; + }>, + UnknownKeys, + Catchall + >; + required(mask?: any) { + const newShape: any = {}; + + for (const key of util.objectKeys(this.shape)) { + if (mask && !mask[key]) { + newShape[key] = this.shape[key]; + } else { + const fieldSchema = this.shape[key]; + let newField = fieldSchema; + + while (newField instanceof ZodOptional) { + newField = (newField as ZodOptional)._def.innerType; + } + + newShape[key] = newField; + } + } + + return new ZodObject({ + ...this._def, + shape: () => newShape, + }) as any; + } + + keyof(): ZodEnum> { + return createZodEnum(util.objectKeys(this.shape) as [string, ...string[]]) as any; + } + + static create = ( + shape: Shape, + params?: RawCreateParams + ): ZodObject< + Shape, + "strip", + ZodTypeAny, + objectOutputType, + objectInputType + > => { + return new ZodObject({ + shape: () => shape, + unknownKeys: "strip", + catchall: ZodNever.create(), + typeName: ZodFirstPartyTypeKind.ZodObject, + ...processCreateParams(params), + }) as any; + }; + + static strictCreate = ( + shape: Shape, + params?: RawCreateParams + ): ZodObject => { + return new ZodObject({ + shape: () => shape, + unknownKeys: "strict", + catchall: ZodNever.create(), + typeName: ZodFirstPartyTypeKind.ZodObject, + ...processCreateParams(params), + }) as any; + }; + + static lazycreate = ( + shape: () => Shape, + params?: RawCreateParams + ): ZodObject => { + return new ZodObject({ + shape, + unknownKeys: "strip", + catchall: ZodNever.create(), + typeName: ZodFirstPartyTypeKind.ZodObject, + ...processCreateParams(params), + }) as any; + }; +} + +export type AnyZodObject = ZodObject; + +//////////////////////////////////////// +//////////////////////////////////////// +////////// ////////// +////////// ZodUnion ////////// +////////// ////////// +//////////////////////////////////////// +//////////////////////////////////////// +export type ZodUnionOptions = Readonly<[ZodTypeAny, ...ZodTypeAny[]]>; +export interface ZodUnionDef> + extends ZodTypeDef { + options: T; + typeName: ZodFirstPartyTypeKind.ZodUnion; +} + +export class ZodUnion extends ZodType< + T[number]["_output"], + ZodUnionDef, + T[number]["_input"] +> { + _parse(input: ParseInput): ParseReturnType { + const { ctx } = this._processInputParams(input); + const options = this._def.options; + + function handleResults(results: { ctx: ParseContext; result: SyncParseReturnType }[]) { + // return first issue-free validation if it exists + for (const result of results) { + if (result.result.status === "valid") { + return result.result; + } + } + + for (const result of results) { + if (result.result.status === "dirty") { + // add issues from dirty option + + ctx.common.issues.push(...result.ctx.common.issues); + return result.result; + } + } + + // return invalid + const unionErrors = results.map((result) => new ZodError(result.ctx.common.issues)); + + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_union, + unionErrors, + }); + return INVALID; + } + + if (ctx.common.async) { + return Promise.all( + options.map(async (option) => { + const childCtx: ParseContext = { + ...ctx, + common: { + ...ctx.common, + issues: [], + }, + parent: null, + }; + return { + result: await option._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: childCtx, + }), + ctx: childCtx, + }; + }) + ).then(handleResults); + } else { + let dirty: undefined | { result: DIRTY; ctx: ParseContext } = undefined; + const issues: ZodIssue[][] = []; + for (const option of options) { + const childCtx: ParseContext = { + ...ctx, + common: { + ...ctx.common, + issues: [], + }, + parent: null, + }; + const result = option._parseSync({ + data: ctx.data, + path: ctx.path, + parent: childCtx, + }); + + if (result.status === "valid") { + return result; + } else if (result.status === "dirty" && !dirty) { + dirty = { result, ctx: childCtx }; + } + + if (childCtx.common.issues.length) { + issues.push(childCtx.common.issues); + } + } + + if (dirty) { + ctx.common.issues.push(...dirty.ctx.common.issues); + return dirty.result; + } + + const unionErrors = issues.map((issues) => new ZodError(issues)); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_union, + unionErrors, + }); + + return INVALID; + } + } + + get options() { + return this._def.options; + } + + static create = >( + types: Options, + params?: RawCreateParams + ): ZodUnion => { + return new ZodUnion({ + options: types, + typeName: ZodFirstPartyTypeKind.ZodUnion, + ...processCreateParams(params), + }); + }; +} + +///////////////////////////////////////////////////// +///////////////////////////////////////////////////// +////////// ////////// +////////// ZodDiscriminatedUnion ////////// +////////// ////////// +///////////////////////////////////////////////////// +///////////////////////////////////////////////////// + +const getDiscriminator = (type: T): Primitive[] => { + if (type instanceof ZodLazy) { + return getDiscriminator(type.schema); + } else if (type instanceof ZodEffects) { + return getDiscriminator(type.innerType()); + } else if (type instanceof ZodLiteral) { + return [type.value]; + } else if (type instanceof ZodEnum) { + return type.options; + } else if (type instanceof ZodNativeEnum) { + // eslint-disable-next-line ban/ban + return util.objectValues(type.enum); + } else if (type instanceof ZodDefault) { + return getDiscriminator(type._def.innerType); + } else if (type instanceof ZodUndefined) { + return [undefined]; + } else if (type instanceof ZodNull) { + return [null]; + } else if (type instanceof ZodOptional) { + return [undefined, ...getDiscriminator(type.unwrap())]; + } else if (type instanceof ZodNullable) { + return [null, ...getDiscriminator(type.unwrap())]; + } else if (type instanceof ZodBranded) { + return getDiscriminator(type.unwrap()); + } else if (type instanceof ZodReadonly) { + return getDiscriminator(type.unwrap()); + } else if (type instanceof ZodCatch) { + return getDiscriminator(type._def.innerType); + } else { + return []; + } +}; + +export type ZodDiscriminatedUnionOption = ZodObject< + { [key in Discriminator]: ZodTypeAny } & ZodRawShape, + UnknownKeysParam, + ZodTypeAny +>; + +export interface ZodDiscriminatedUnionDef< + Discriminator extends string, + Options extends readonly ZodDiscriminatedUnionOption[] = ZodDiscriminatedUnionOption[], +> extends ZodTypeDef { + discriminator: Discriminator; + options: Options; + optionsMap: Map>; + typeName: ZodFirstPartyTypeKind.ZodDiscriminatedUnion; +} + +export class ZodDiscriminatedUnion< + Discriminator extends string, + Options extends readonly ZodDiscriminatedUnionOption[], +> extends ZodType, ZodDiscriminatedUnionDef, input> { + _parse(input: ParseInput): ParseReturnType { + const { ctx } = this._processInputParams(input); + + if (ctx.parsedType !== ZodParsedType.object) { + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.object, + received: ctx.parsedType, + }); + return INVALID; + } + + const discriminator = this.discriminator; + + const discriminatorValue: string = ctx.data[discriminator]; + + const option = this.optionsMap.get(discriminatorValue); + + if (!option) { + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_union_discriminator, + options: Array.from(this.optionsMap.keys()), + path: [discriminator], + }); + return INVALID; + } + + if (ctx.common.async) { + return option._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: ctx, + }) as any; + } else { + return option._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx, + }) as any; + } + } + + get discriminator() { + return this._def.discriminator; + } + + get options() { + return this._def.options; + } + + get optionsMap() { + return this._def.optionsMap; + } + + /** + * The constructor of the discriminated union schema. Its behaviour is very similar to that of the normal z.union() constructor. + * However, it only allows a union of objects, all of which need to share a discriminator property. This property must + * have a different value for each object in the union. + * @param discriminator the name of the discriminator property + * @param types an array of object schemas + * @param params + */ + static create< + Discriminator extends string, + Types extends readonly [ + ZodDiscriminatedUnionOption, + ...ZodDiscriminatedUnionOption[], + ], + >( + discriminator: Discriminator, + options: Types, + params?: RawCreateParams + ): ZodDiscriminatedUnion { + // Get all the valid discriminator values + const optionsMap: Map = new Map(); + + // try { + for (const type of options) { + const discriminatorValues = getDiscriminator(type.shape[discriminator]); + if (!discriminatorValues.length) { + throw new Error( + `A discriminator value for key \`${discriminator}\` could not be extracted from all schema options` + ); + } + for (const value of discriminatorValues) { + if (optionsMap.has(value)) { + throw new Error(`Discriminator property ${String(discriminator)} has duplicate value ${String(value)}`); + } + + optionsMap.set(value, type); + } + } + + return new ZodDiscriminatedUnion< + Discriminator, + // DiscriminatorValue, + Types + >({ + typeName: ZodFirstPartyTypeKind.ZodDiscriminatedUnion, + discriminator, + options, + optionsMap, + ...processCreateParams(params), + }); + } +} + +/////////////////////////////////////////////// +/////////////////////////////////////////////// +////////// ////////// +////////// ZodIntersection ////////// +////////// ////////// +/////////////////////////////////////////////// +/////////////////////////////////////////////// +export interface ZodIntersectionDef + extends ZodTypeDef { + left: T; + right: U; + typeName: ZodFirstPartyTypeKind.ZodIntersection; +} + +function mergeValues(a: any, b: any): { valid: true; data: any } | { valid: false } { + const aType = getParsedType(a); + const bType = getParsedType(b); + + if (a === b) { + return { valid: true, data: a }; + } else if (aType === ZodParsedType.object && bType === ZodParsedType.object) { + const bKeys = util.objectKeys(b); + const sharedKeys = util.objectKeys(a).filter((key) => bKeys.indexOf(key) !== -1); + + const newObj: any = { ...a, ...b }; + for (const key of sharedKeys) { + const sharedValue = mergeValues(a[key], b[key]); + if (!sharedValue.valid) { + return { valid: false }; + } + newObj[key] = sharedValue.data; + } + + return { valid: true, data: newObj }; + } else if (aType === ZodParsedType.array && bType === ZodParsedType.array) { + if (a.length !== b.length) { + return { valid: false }; + } + + const newArray: unknown[] = []; + for (let index = 0; index < a.length; index++) { + const itemA = a[index]; + const itemB = b[index]; + const sharedValue = mergeValues(itemA, itemB); + + if (!sharedValue.valid) { + return { valid: false }; + } + + newArray.push(sharedValue.data); + } + + return { valid: true, data: newArray }; + } else if (aType === ZodParsedType.date && bType === ZodParsedType.date && +a === +b) { + return { valid: true, data: a }; + } else { + return { valid: false }; + } +} + +export class ZodIntersection extends ZodType< + T["_output"] & U["_output"], + ZodIntersectionDef, + T["_input"] & U["_input"] +> { + _parse(input: ParseInput): ParseReturnType { + const { status, ctx } = this._processInputParams(input); + const handleParsed = ( + parsedLeft: SyncParseReturnType, + parsedRight: SyncParseReturnType + ): SyncParseReturnType => { + if (isAborted(parsedLeft) || isAborted(parsedRight)) { + return INVALID; + } + + const merged = mergeValues(parsedLeft.value, parsedRight.value); + + if (!merged.valid) { + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_intersection_types, + }); + return INVALID; + } + + if (isDirty(parsedLeft) || isDirty(parsedRight)) { + status.dirty(); + } + + return { status: status.value, value: merged.data }; + }; + + if (ctx.common.async) { + return Promise.all([ + this._def.left._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: ctx, + }), + this._def.right._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: ctx, + }), + ]).then(([left, right]: any) => handleParsed(left, right)); + } else { + return handleParsed( + this._def.left._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx, + }), + this._def.right._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx, + }) + ); + } + } + + static create = ( + left: TSchema, + right: USchema, + params?: RawCreateParams + ): ZodIntersection => { + return new ZodIntersection({ + left: left, + right: right, + typeName: ZodFirstPartyTypeKind.ZodIntersection, + ...processCreateParams(params), + }); + }; +} + +//////////////////////////////////////// +//////////////////////////////////////// +////////// ////////// +////////// ZodTuple ////////// +////////// ////////// +//////////////////////////////////////// +//////////////////////////////////////// +export type ZodTupleItems = [ZodTypeAny, ...ZodTypeAny[]]; +export type AssertArray = T extends any[] ? T : never; +export type OutputTypeOfTuple = AssertArray<{ + [k in keyof T]: T[k] extends ZodType ? T[k]["_output"] : never; +}>; +export type OutputTypeOfTupleWithRest< + T extends ZodTupleItems | [], + Rest extends ZodTypeAny | null = null, +> = Rest extends ZodTypeAny ? [...OutputTypeOfTuple, ...Rest["_output"][]] : OutputTypeOfTuple; + +export type InputTypeOfTuple = AssertArray<{ + [k in keyof T]: T[k] extends ZodType ? T[k]["_input"] : never; +}>; +export type InputTypeOfTupleWithRest< + T extends ZodTupleItems | [], + Rest extends ZodTypeAny | null = null, +> = Rest extends ZodTypeAny ? [...InputTypeOfTuple, ...Rest["_input"][]] : InputTypeOfTuple; + +export interface ZodTupleDef + extends ZodTypeDef { + items: T; + rest: Rest; + typeName: ZodFirstPartyTypeKind.ZodTuple; +} + +export type AnyZodTuple = ZodTuple<[ZodTypeAny, ...ZodTypeAny[]] | [], ZodTypeAny | null>; +// type ZodTupleItems = [ZodTypeAny, ...ZodTypeAny[]]; +export class ZodTuple< + T extends ZodTupleItems | [] = ZodTupleItems, + Rest extends ZodTypeAny | null = null, +> extends ZodType, ZodTupleDef, InputTypeOfTupleWithRest> { + _parse(input: ParseInput): ParseReturnType { + const { status, ctx } = this._processInputParams(input); + if (ctx.parsedType !== ZodParsedType.array) { + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.array, + received: ctx.parsedType, + }); + return INVALID; + } + + if (ctx.data.length < this._def.items.length) { + addIssueToContext(ctx, { + code: ZodIssueCode.too_small, + minimum: this._def.items.length, + inclusive: true, + exact: false, + type: "array", + }); + + return INVALID; + } + + const rest = this._def.rest; + + if (!rest && ctx.data.length > this._def.items.length) { + addIssueToContext(ctx, { + code: ZodIssueCode.too_big, + maximum: this._def.items.length, + inclusive: true, + exact: false, + type: "array", + }); + status.dirty(); + } + + const items = ([...ctx.data] as any[]) + .map((item, itemIndex) => { + const schema = this._def.items[itemIndex] || this._def.rest; + if (!schema) return null as any as SyncParseReturnType; + return schema._parse(new ParseInputLazyPath(ctx, item, ctx.path, itemIndex)); + }) + .filter((x) => !!x); // filter nulls + + if (ctx.common.async) { + return Promise.all(items).then((results) => { + return ParseStatus.mergeArray(status, results); + }); + } else { + return ParseStatus.mergeArray(status, items as SyncParseReturnType[]); + } + } + + get items() { + return this._def.items; + } + + rest(rest: RestSchema): ZodTuple { + return new ZodTuple({ + ...this._def, + rest, + }); + } + + static create = ( + schemas: Items, + params?: RawCreateParams + ): ZodTuple => { + if (!Array.isArray(schemas)) { + throw new Error("You must pass an array of schemas to z.tuple([ ... ])"); + } + return new ZodTuple({ + items: schemas, + typeName: ZodFirstPartyTypeKind.ZodTuple, + rest: null, + ...processCreateParams(params), + }); + }; +} + +///////////////////////////////////////// +///////////////////////////////////////// +////////// ////////// +////////// ZodRecord ////////// +////////// ////////// +///////////////////////////////////////// +///////////////////////////////////////// +export interface ZodRecordDef + extends ZodTypeDef { + valueType: Value; + keyType: Key; + typeName: ZodFirstPartyTypeKind.ZodRecord; +} + +export type KeySchema = ZodType; +export type RecordType = [string] extends [K] + ? Record + : [number] extends [K] + ? Record + : [symbol] extends [K] + ? Record + : [BRAND] extends [K] + ? Record + : Partial>; +export class ZodRecord extends ZodType< + RecordType, + ZodRecordDef, + RecordType +> { + get keySchema() { + return this._def.keyType; + } + get valueSchema() { + return this._def.valueType; + } + _parse(input: ParseInput): ParseReturnType { + const { status, ctx } = this._processInputParams(input); + if (ctx.parsedType !== ZodParsedType.object) { + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.object, + received: ctx.parsedType, + }); + return INVALID; + } + + const pairs: { + key: ParseReturnType; + value: ParseReturnType; + alwaysSet: boolean; + }[] = []; + + const keyType = this._def.keyType; + const valueType = this._def.valueType; + + for (const key in ctx.data) { + pairs.push({ + key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, key)), + value: valueType._parse(new ParseInputLazyPath(ctx, ctx.data[key], ctx.path, key)), + alwaysSet: key in ctx.data, + }); + } + + if (ctx.common.async) { + return ParseStatus.mergeObjectAsync(status, pairs); + } else { + return ParseStatus.mergeObjectSync(status, pairs as any); + } + } + + get element() { + return this._def.valueType; + } + + static create(valueType: Value, params?: RawCreateParams): ZodRecord; + static create( + keySchema: Keys, + valueType: Value, + params?: RawCreateParams + ): ZodRecord; + static create(first: any, second?: any, third?: any): ZodRecord { + if (second instanceof ZodType) { + return new ZodRecord({ + keyType: first, + valueType: second, + typeName: ZodFirstPartyTypeKind.ZodRecord, + ...processCreateParams(third), + }); + } + + return new ZodRecord({ + keyType: ZodString.create(), + valueType: first, + typeName: ZodFirstPartyTypeKind.ZodRecord, + ...processCreateParams(second), + }); + } +} + +////////////////////////////////////// +////////////////////////////////////// +////////// ////////// +////////// ZodMap ////////// +////////// ////////// +////////////////////////////////////// +////////////////////////////////////// +export interface ZodMapDef + extends ZodTypeDef { + valueType: Value; + keyType: Key; + typeName: ZodFirstPartyTypeKind.ZodMap; +} + +export class ZodMap extends ZodType< + Map, + ZodMapDef, + Map +> { + get keySchema() { + return this._def.keyType; + } + get valueSchema() { + return this._def.valueType; + } + _parse(input: ParseInput): ParseReturnType { + const { status, ctx } = this._processInputParams(input); + if (ctx.parsedType !== ZodParsedType.map) { + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.map, + received: ctx.parsedType, + }); + return INVALID; + } + + const keyType = this._def.keyType; + const valueType = this._def.valueType; + + const pairs = [...(ctx.data as Map).entries()].map(([key, value], index) => { + return { + key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index, "key"])), + value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index, "value"])), + }; + }); + + if (ctx.common.async) { + const finalMap = new Map(); + return Promise.resolve().then(async () => { + for (const pair of pairs) { + const key = await pair.key; + const value = await pair.value; + if (key.status === "aborted" || value.status === "aborted") { + return INVALID; + } + if (key.status === "dirty" || value.status === "dirty") { + status.dirty(); + } + + finalMap.set(key.value, value.value); + } + return { status: status.value, value: finalMap }; + }); + } else { + const finalMap = new Map(); + for (const pair of pairs) { + const key = pair.key as SyncParseReturnType; + const value = pair.value as SyncParseReturnType; + if (key.status === "aborted" || value.status === "aborted") { + return INVALID; + } + if (key.status === "dirty" || value.status === "dirty") { + status.dirty(); + } + + finalMap.set(key.value, value.value); + } + return { status: status.value, value: finalMap }; + } + } + static create = ( + keyType: KeySchema, + valueType: ValueSchema, + params?: RawCreateParams + ): ZodMap => { + return new ZodMap({ + valueType, + keyType, + typeName: ZodFirstPartyTypeKind.ZodMap, + ...processCreateParams(params), + }); + }; +} + +////////////////////////////////////// +////////////////////////////////////// +////////// ////////// +////////// ZodSet ////////// +////////// ////////// +////////////////////////////////////// +////////////////////////////////////// +export interface ZodSetDef extends ZodTypeDef { + valueType: Value; + typeName: ZodFirstPartyTypeKind.ZodSet; + minSize: { value: number; message?: string | undefined } | null; + maxSize: { value: number; message?: string | undefined } | null; +} + +export class ZodSet extends ZodType< + Set, + ZodSetDef, + Set +> { + _parse(input: ParseInput): ParseReturnType { + const { status, ctx } = this._processInputParams(input); + if (ctx.parsedType !== ZodParsedType.set) { + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.set, + received: ctx.parsedType, + }); + return INVALID; + } + + const def = this._def; + + if (def.minSize !== null) { + if (ctx.data.size < def.minSize.value) { + addIssueToContext(ctx, { + code: ZodIssueCode.too_small, + minimum: def.minSize.value, + type: "set", + inclusive: true, + exact: false, + message: def.minSize.message, + }); + status.dirty(); + } + } + + if (def.maxSize !== null) { + if (ctx.data.size > def.maxSize.value) { + addIssueToContext(ctx, { + code: ZodIssueCode.too_big, + maximum: def.maxSize.value, + type: "set", + inclusive: true, + exact: false, + message: def.maxSize.message, + }); + status.dirty(); + } + } + + const valueType = this._def.valueType; + + function finalizeSet(elements: SyncParseReturnType[]) { + const parsedSet = new Set(); + for (const element of elements) { + if (element.status === "aborted") return INVALID; + if (element.status === "dirty") status.dirty(); + parsedSet.add(element.value); + } + return { status: status.value, value: parsedSet }; + } + + const elements = [...(ctx.data as Set).values()].map((item, i) => + valueType._parse(new ParseInputLazyPath(ctx, item, ctx.path, i)) + ); + + if (ctx.common.async) { + return Promise.all(elements).then((elements) => finalizeSet(elements)); + } else { + return finalizeSet(elements as SyncParseReturnType[]); + } + } + + min(minSize: number, message?: errorUtil.ErrMessage): this { + return new ZodSet({ + ...this._def, + minSize: { value: minSize, message: errorUtil.toString(message) }, + }) as any; + } + + max(maxSize: number, message?: errorUtil.ErrMessage): this { + return new ZodSet({ + ...this._def, + maxSize: { value: maxSize, message: errorUtil.toString(message) }, + }) as any; + } + + size(size: number, message?: errorUtil.ErrMessage): this { + return this.min(size, message).max(size, message) as any; + } + + nonempty(message?: errorUtil.ErrMessage): ZodSet { + return this.min(1, message) as any; + } + + static create = ( + valueType: ValueSchema, + params?: RawCreateParams + ): ZodSet => { + return new ZodSet({ + valueType, + minSize: null, + maxSize: null, + typeName: ZodFirstPartyTypeKind.ZodSet, + ...processCreateParams(params), + }); + }; +} + +/////////////////////////////////////////// +/////////////////////////////////////////// +////////// ////////// +////////// ZodFunction ////////// +////////// ////////// +/////////////////////////////////////////// +/////////////////////////////////////////// +export interface ZodFunctionDef< + Args extends ZodTuple = ZodTuple, + Returns extends ZodTypeAny = ZodTypeAny, +> extends ZodTypeDef { + args: Args; + returns: Returns; + typeName: ZodFirstPartyTypeKind.ZodFunction; +} + +export type OuterTypeOfFunction< + Args extends ZodTuple, + Returns extends ZodTypeAny, +> = Args["_input"] extends Array ? (...args: Args["_input"]) => Returns["_output"] : never; + +export type InnerTypeOfFunction< + Args extends ZodTuple, + Returns extends ZodTypeAny, +> = Args["_output"] extends Array ? (...args: Args["_output"]) => Returns["_input"] : never; + +export class ZodFunction, Returns extends ZodTypeAny> extends ZodType< + OuterTypeOfFunction, + ZodFunctionDef, + InnerTypeOfFunction +> { + _parse(input: ParseInput): ParseReturnType { + const { ctx } = this._processInputParams(input); + if (ctx.parsedType !== ZodParsedType.function) { + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.function, + received: ctx.parsedType, + }); + return INVALID; + } + + function makeArgsIssue(args: any, error: ZodError): ZodIssue { + return makeIssue({ + data: args, + path: ctx.path, + errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, getErrorMap(), defaultErrorMap].filter( + (x) => !!x + ), + issueData: { + code: ZodIssueCode.invalid_arguments, + argumentsError: error, + }, + }); + } + + function makeReturnsIssue(returns: any, error: ZodError): ZodIssue { + return makeIssue({ + data: returns, + path: ctx.path, + errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, getErrorMap(), defaultErrorMap].filter( + (x) => !!x + ), + issueData: { + code: ZodIssueCode.invalid_return_type, + returnTypeError: error, + }, + }); + } + + const params = { errorMap: ctx.common.contextualErrorMap }; + const fn = ctx.data; + + if (this._def.returns instanceof ZodPromise) { + // Would love a way to avoid disabling this rule, but we need + // an alias (using an arrow function was what caused 2651). + // eslint-disable-next-line @typescript-eslint/no-this-alias + const me = this; + return OK(async function (this: any, ...args: any[]) { + const error = new ZodError([]); + const parsedArgs = await me._def.args.parseAsync(args, params).catch((e) => { + error.addIssue(makeArgsIssue(args, e)); + throw error; + }); + const result = await Reflect.apply(fn, this, parsedArgs as any); + const parsedReturns = await (me._def.returns as unknown as ZodPromise)._def.type + .parseAsync(result, params) + .catch((e) => { + error.addIssue(makeReturnsIssue(result, e)); + throw error; + }); + return parsedReturns; + }); + } else { + // Would love a way to avoid disabling this rule, but we need + // an alias (using an arrow function was what caused 2651). + // eslint-disable-next-line @typescript-eslint/no-this-alias + const me = this; + return OK(function (this: any, ...args: any[]) { + const parsedArgs = me._def.args.safeParse(args, params); + if (!parsedArgs.success) { + throw new ZodError([makeArgsIssue(args, parsedArgs.error)]); + } + const result = Reflect.apply(fn, this, parsedArgs.data); + const parsedReturns = me._def.returns.safeParse(result, params); + if (!parsedReturns.success) { + throw new ZodError([makeReturnsIssue(result, parsedReturns.error)]); + } + return parsedReturns.data; + }) as any; + } + } + + parameters() { + return this._def.args; + } + + returnType() { + return this._def.returns; + } + + args[0]>( + ...items: Items + ): ZodFunction, Returns> { + return new ZodFunction({ + ...this._def, + args: ZodTuple.create(items).rest(ZodUnknown.create()) as any, + }); + } + + returns>(returnType: NewReturnType): ZodFunction { + return new ZodFunction({ + ...this._def, + returns: returnType, + }); + } + + implement>( + func: F + ): ReturnType extends Returns["_output"] + ? (...args: Args["_input"]) => ReturnType + : OuterTypeOfFunction { + const validatedFunc = this.parse(func); + return validatedFunc as any; + } + + strictImplement(func: InnerTypeOfFunction): InnerTypeOfFunction { + const validatedFunc = this.parse(func); + return validatedFunc as any; + } + + validate = this.implement; + + static create(): ZodFunction, ZodUnknown>; + static create>(args: T): ZodFunction; + static create(args: T, returns: U): ZodFunction; + static create, U extends ZodTypeAny = ZodUnknown>( + args: T, + returns: U, + params?: RawCreateParams + ): ZodFunction; + static create(args?: AnyZodTuple, returns?: ZodTypeAny, params?: RawCreateParams) { + return new ZodFunction({ + args: (args ? args : ZodTuple.create([]).rest(ZodUnknown.create())) as any, + returns: returns || ZodUnknown.create(), + typeName: ZodFirstPartyTypeKind.ZodFunction, + ...processCreateParams(params), + }) as any; + } +} + +/////////////////////////////////////// +/////////////////////////////////////// +////////// ////////// +////////// ZodLazy ////////// +////////// ////////// +/////////////////////////////////////// +/////////////////////////////////////// +export interface ZodLazyDef extends ZodTypeDef { + getter: () => T; + typeName: ZodFirstPartyTypeKind.ZodLazy; +} + +export class ZodLazy extends ZodType, ZodLazyDef, input> { + get schema(): T { + return this._def.getter(); + } + + _parse(input: ParseInput): ParseReturnType { + const { ctx } = this._processInputParams(input); + const lazySchema = this._def.getter(); + return lazySchema._parse({ data: ctx.data, path: ctx.path, parent: ctx }); + } + + static create = (getter: () => Inner, params?: RawCreateParams): ZodLazy => { + return new ZodLazy({ + getter: getter, + typeName: ZodFirstPartyTypeKind.ZodLazy, + ...processCreateParams(params), + }); + }; +} + +////////////////////////////////////////// +////////////////////////////////////////// +////////// ////////// +////////// ZodLiteral ////////// +////////// ////////// +////////////////////////////////////////// +////////////////////////////////////////// +export interface ZodLiteralDef extends ZodTypeDef { + value: T; + typeName: ZodFirstPartyTypeKind.ZodLiteral; +} + +export class ZodLiteral extends ZodType, T> { + _parse(input: ParseInput): ParseReturnType { + if (input.data !== this._def.value) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + received: ctx.data, + code: ZodIssueCode.invalid_literal, + expected: this._def.value, + }); + return INVALID; + } + return { status: "valid", value: input.data }; + } + + get value() { + return this._def.value; + } + + static create = (value: Value, params?: RawCreateParams): ZodLiteral => { + return new ZodLiteral({ + value: value, + typeName: ZodFirstPartyTypeKind.ZodLiteral, + ...processCreateParams(params), + }); + }; +} + +/////////////////////////////////////// +/////////////////////////////////////// +////////// ////////// +////////// ZodEnum ////////// +////////// ////////// +/////////////////////////////////////// +/////////////////////////////////////// +export type ArrayKeys = keyof any[]; +export type Indices = Exclude; + +export type EnumValues = readonly [T, ...T[]]; + +export type Values = { + [k in T[number]]: k; +}; + +export interface ZodEnumDef extends ZodTypeDef { + values: T; + typeName: ZodFirstPartyTypeKind.ZodEnum; +} + +export type Writeable = { -readonly [P in keyof T]: T[P] }; + +export type FilterEnum = Values extends [] + ? [] + : Values extends [infer Head, ...infer Rest] + ? Head extends ToExclude + ? FilterEnum + : [Head, ...FilterEnum] + : never; + +export type typecast = A extends T ? A : never; + +function createZodEnum>( + values: T, + params?: RawCreateParams +): ZodEnum>; +function createZodEnum(values: T, params?: RawCreateParams): ZodEnum; +function createZodEnum(values: [string, ...string[]], params?: RawCreateParams) { + return new ZodEnum({ + values, + typeName: ZodFirstPartyTypeKind.ZodEnum, + ...processCreateParams(params), + }); +} + +export class ZodEnum extends ZodType, T[number]> { + _cache: Set | undefined; + + _parse(input: ParseInput): ParseReturnType { + if (typeof input.data !== "string") { + const ctx = this._getOrReturnCtx(input); + const expectedValues = this._def.values; + addIssueToContext(ctx, { + expected: util.joinValues(expectedValues) as "string", + received: ctx.parsedType, + code: ZodIssueCode.invalid_type, + }); + return INVALID; + } + + if (!this._cache) { + this._cache = new Set(this._def.values); + } + + if (!this._cache.has(input.data)) { + const ctx = this._getOrReturnCtx(input); + const expectedValues = this._def.values; + + addIssueToContext(ctx, { + received: ctx.data, + code: ZodIssueCode.invalid_enum_value, + options: expectedValues, + }); + return INVALID; + } + return OK(input.data); + } + + get options() { + return this._def.values; + } + + get enum(): Values { + const enumValues: any = {}; + for (const val of this._def.values) { + enumValues[val] = val; + } + return enumValues; + } + + get Values(): Values { + const enumValues: any = {}; + for (const val of this._def.values) { + enumValues[val] = val; + } + return enumValues; + } + + get Enum(): Values { + const enumValues: any = {}; + for (const val of this._def.values) { + enumValues[val] = val; + } + return enumValues; + } + + extract( + values: ToExtract, + newDef: RawCreateParams = this._def + ): ZodEnum> { + return ZodEnum.create(values, { + ...this._def, + ...newDef, + }) as any; + } + + exclude( + values: ToExclude, + newDef: RawCreateParams = this._def + ): ZodEnum>, [string, ...string[]]>> { + return ZodEnum.create(this.options.filter((opt) => !values.includes(opt)) as FilterEnum, { + ...this._def, + ...newDef, + }) as any; + } + + static create = createZodEnum; +} + +///////////////////////////////////////////// +///////////////////////////////////////////// +////////// ////////// +////////// ZodNativeEnum ////////// +////////// ////////// +///////////////////////////////////////////// +///////////////////////////////////////////// +export interface ZodNativeEnumDef extends ZodTypeDef { + values: T; + typeName: ZodFirstPartyTypeKind.ZodNativeEnum; +} + +export type EnumLike = { [k: string]: string | number; [nu: number]: string }; + +export class ZodNativeEnum extends ZodType, T[keyof T]> { + _cache: Set | undefined; + _parse(input: ParseInput): ParseReturnType { + const nativeEnumValues = util.getValidEnumValues(this._def.values); + + const ctx = this._getOrReturnCtx(input); + if (ctx.parsedType !== ZodParsedType.string && ctx.parsedType !== ZodParsedType.number) { + const expectedValues = util.objectValues(nativeEnumValues); + addIssueToContext(ctx, { + expected: util.joinValues(expectedValues) as "string", + received: ctx.parsedType, + code: ZodIssueCode.invalid_type, + }); + return INVALID; + } + + if (!this._cache) { + this._cache = new Set(util.getValidEnumValues(this._def.values)); + } + + if (!this._cache.has(input.data)) { + const expectedValues = util.objectValues(nativeEnumValues); + + addIssueToContext(ctx, { + received: ctx.data, + code: ZodIssueCode.invalid_enum_value, + options: expectedValues, + }); + return INVALID; + } + return OK(input.data); + } + + get enum() { + return this._def.values; + } + + static create = (values: Elements, params?: RawCreateParams): ZodNativeEnum => { + return new ZodNativeEnum({ + values: values, + typeName: ZodFirstPartyTypeKind.ZodNativeEnum, + ...processCreateParams(params), + }); + }; +} + +////////////////////////////////////////// +////////////////////////////////////////// +////////// ////////// +////////// ZodPromise ////////// +////////// ////////// +////////////////////////////////////////// +////////////////////////////////////////// +export interface ZodPromiseDef extends ZodTypeDef { + type: T; + typeName: ZodFirstPartyTypeKind.ZodPromise; +} + +export class ZodPromise extends ZodType< + Promise, + ZodPromiseDef, + Promise +> { + unwrap() { + return this._def.type; + } + + _parse(input: ParseInput): ParseReturnType { + const { ctx } = this._processInputParams(input); + if (ctx.parsedType !== ZodParsedType.promise && ctx.common.async === false) { + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.promise, + received: ctx.parsedType, + }); + return INVALID; + } + + const promisified = ctx.parsedType === ZodParsedType.promise ? ctx.data : Promise.resolve(ctx.data); + + return OK( + promisified.then((data: any) => { + return this._def.type.parseAsync(data, { + path: ctx.path, + errorMap: ctx.common.contextualErrorMap, + }); + }) + ); + } + + static create = (schema: Inner, params?: RawCreateParams): ZodPromise => { + return new ZodPromise({ + type: schema, + typeName: ZodFirstPartyTypeKind.ZodPromise, + ...processCreateParams(params), + }); + }; +} + +////////////////////////////////////////////// +////////////////////////////////////////////// +////////// ////////// +////////// ZodEffects ////////// +////////// ////////// +////////////////////////////////////////////// +////////////////////////////////////////////// + +export type Refinement = (arg: T, ctx: RefinementCtx) => any; +export type SuperRefinement = (arg: T, ctx: RefinementCtx) => void | Promise; + +export type RefinementEffect = { + type: "refinement"; + refinement: (arg: T, ctx: RefinementCtx) => any; +}; +export type TransformEffect = { + type: "transform"; + transform: (arg: T, ctx: RefinementCtx) => any; +}; +export type PreprocessEffect = { + type: "preprocess"; + transform: (arg: T, ctx: RefinementCtx) => any; +}; +export type Effect = RefinementEffect | TransformEffect | PreprocessEffect; + +export interface ZodEffectsDef extends ZodTypeDef { + schema: T; + typeName: ZodFirstPartyTypeKind.ZodEffects; + effect: Effect; +} + +export class ZodEffects, Input = input> extends ZodType< + Output, + ZodEffectsDef, + Input +> { + innerType() { + return this._def.schema; + } + + sourceType(): T { + return this._def.schema._def.typeName === ZodFirstPartyTypeKind.ZodEffects + ? (this._def.schema as unknown as ZodEffects).sourceType() + : (this._def.schema as T); + } + + _parse(input: ParseInput): ParseReturnType { + const { status, ctx } = this._processInputParams(input); + + const effect = this._def.effect || null; + + const checkCtx: RefinementCtx = { + addIssue: (arg: IssueData) => { + addIssueToContext(ctx, arg); + if (arg.fatal) { + status.abort(); + } else { + status.dirty(); + } + }, + get path() { + return ctx.path; + }, + }; + + checkCtx.addIssue = checkCtx.addIssue.bind(checkCtx); + + if (effect.type === "preprocess") { + const processed = effect.transform(ctx.data, checkCtx); + + if (ctx.common.async) { + return Promise.resolve(processed).then(async (processed) => { + if (status.value === "aborted") return INVALID; + + const result = await this._def.schema._parseAsync({ + data: processed, + path: ctx.path, + parent: ctx, + }); + if (result.status === "aborted") return INVALID; + if (result.status === "dirty") return DIRTY(result.value); + if (status.value === "dirty") return DIRTY(result.value); + return result; + }); + } else { + if (status.value === "aborted") return INVALID; + const result = this._def.schema._parseSync({ + data: processed, + path: ctx.path, + parent: ctx, + }); + if (result.status === "aborted") return INVALID; + if (result.status === "dirty") return DIRTY(result.value); + if (status.value === "dirty") return DIRTY(result.value); + return result; + } + } + if (effect.type === "refinement") { + const executeRefinement = (acc: unknown): any => { + const result = effect.refinement(acc, checkCtx); + if (ctx.common.async) { + return Promise.resolve(result); + } + if (result instanceof Promise) { + throw new Error("Async refinement encountered during synchronous parse operation. Use .parseAsync instead."); + } + return acc; + }; + + if (ctx.common.async === false) { + const inner = this._def.schema._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx, + }); + if (inner.status === "aborted") return INVALID; + if (inner.status === "dirty") status.dirty(); + + // return value is ignored + executeRefinement(inner.value); + return { status: status.value, value: inner.value }; + } else { + return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((inner) => { + if (inner.status === "aborted") return INVALID; + if (inner.status === "dirty") status.dirty(); + + return executeRefinement(inner.value).then(() => { + return { status: status.value, value: inner.value }; + }); + }); + } + } + + if (effect.type === "transform") { + if (ctx.common.async === false) { + const base = this._def.schema._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx, + }); + + if (!isValid(base)) return INVALID; + + const result = effect.transform(base.value, checkCtx); + if (result instanceof Promise) { + throw new Error( + `Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.` + ); + } + + return { status: status.value, value: result }; + } else { + return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((base) => { + if (!isValid(base)) return INVALID; + + return Promise.resolve(effect.transform(base.value, checkCtx)).then((result) => ({ + status: status.value, + value: result, + })); + }); + } + } + + util.assertNever(effect); + } + + static create = ( + schema: I, + effect: Effect, + params?: RawCreateParams + ): ZodEffects => { + return new ZodEffects({ + schema, + typeName: ZodFirstPartyTypeKind.ZodEffects, + effect, + ...processCreateParams(params), + }); + }; + + static createWithPreprocess = ( + preprocess: (arg: unknown, ctx: RefinementCtx) => unknown, + schema: I, + params?: RawCreateParams + ): ZodEffects => { + return new ZodEffects({ + schema, + effect: { type: "preprocess", transform: preprocess }, + typeName: ZodFirstPartyTypeKind.ZodEffects, + ...processCreateParams(params), + }); + }; +} + +export { ZodEffects as ZodTransformer }; + +/////////////////////////////////////////// +/////////////////////////////////////////// +////////// ////////// +////////// ZodOptional ////////// +////////// ////////// +/////////////////////////////////////////// +/////////////////////////////////////////// +export interface ZodOptionalDef extends ZodTypeDef { + innerType: T; + typeName: ZodFirstPartyTypeKind.ZodOptional; +} + +export type ZodOptionalType = ZodOptional; + +export class ZodOptional extends ZodType< + T["_output"] | undefined, + ZodOptionalDef, + T["_input"] | undefined +> { + _parse(input: ParseInput): ParseReturnType { + const parsedType = this._getType(input); + if (parsedType === ZodParsedType.undefined) { + return OK(undefined); + } + return this._def.innerType._parse(input); + } + + unwrap() { + return this._def.innerType; + } + + static create = (type: Inner, params?: RawCreateParams): ZodOptional => { + return new ZodOptional({ + innerType: type, + typeName: ZodFirstPartyTypeKind.ZodOptional, + ...processCreateParams(params), + }) as any; + }; +} + +/////////////////////////////////////////// +/////////////////////////////////////////// +////////// ////////// +////////// ZodNullable ////////// +////////// ////////// +/////////////////////////////////////////// +/////////////////////////////////////////// +export interface ZodNullableDef extends ZodTypeDef { + innerType: T; + typeName: ZodFirstPartyTypeKind.ZodNullable; +} + +export type ZodNullableType = ZodNullable; + +export class ZodNullable extends ZodType< + T["_output"] | null, + ZodNullableDef, + T["_input"] | null +> { + _parse(input: ParseInput): ParseReturnType { + const parsedType = this._getType(input); + if (parsedType === ZodParsedType.null) { + return OK(null); + } + return this._def.innerType._parse(input); + } + + unwrap() { + return this._def.innerType; + } + + static create = (type: Inner, params?: RawCreateParams): ZodNullable => { + return new ZodNullable({ + innerType: type, + typeName: ZodFirstPartyTypeKind.ZodNullable, + ...processCreateParams(params), + }) as any; + }; +} + +//////////////////////////////////////////// +//////////////////////////////////////////// +////////// ////////// +////////// ZodDefault ////////// +////////// ////////// +//////////////////////////////////////////// +//////////////////////////////////////////// +export interface ZodDefaultDef extends ZodTypeDef { + innerType: T; + defaultValue: () => util.noUndefined; + typeName: ZodFirstPartyTypeKind.ZodDefault; +} + +export class ZodDefault extends ZodType< + util.noUndefined, + ZodDefaultDef, + T["_input"] | undefined +> { + _parse(input: ParseInput): ParseReturnType { + const { ctx } = this._processInputParams(input); + let data = ctx.data; + if (ctx.parsedType === ZodParsedType.undefined) { + data = this._def.defaultValue(); + } + return this._def.innerType._parse({ + data, + path: ctx.path, + parent: ctx, + }); + } + + removeDefault() { + return this._def.innerType; + } + + static create = ( + type: Inner, + params: RawCreateParams & { + default: Inner["_input"] | (() => util.noUndefined); + } + ): ZodDefault => { + return new ZodDefault({ + innerType: type, + typeName: ZodFirstPartyTypeKind.ZodDefault, + defaultValue: typeof params.default === "function" ? params.default : () => params.default as any, + ...processCreateParams(params), + }) as any; + }; +} + +////////////////////////////////////////// +////////////////////////////////////////// +////////// ////////// +////////// ZodCatch ////////// +////////// ////////// +////////////////////////////////////////// +////////////////////////////////////////// +export interface ZodCatchDef extends ZodTypeDef { + innerType: T; + catchValue: (ctx: { error: ZodError; input: unknown }) => T["_input"]; + typeName: ZodFirstPartyTypeKind.ZodCatch; +} + +export class ZodCatch extends ZodType< + T["_output"], + ZodCatchDef, + unknown // any input will pass validation // T["_input"] +> { + _parse(input: ParseInput): ParseReturnType { + const { ctx } = this._processInputParams(input); + + // newCtx is used to not collect issues from inner types in ctx + const newCtx: ParseContext = { + ...ctx, + common: { + ...ctx.common, + issues: [], + }, + }; + + const result = this._def.innerType._parse({ + data: newCtx.data, + path: newCtx.path, + parent: { + ...newCtx, + }, + }); + + if (isAsync(result)) { + return result.then((result) => { + return { + status: "valid", + value: + result.status === "valid" + ? result.value + : this._def.catchValue({ + get error() { + return new ZodError(newCtx.common.issues); + }, + input: newCtx.data, + }), + }; + }); + } else { + return { + status: "valid", + value: + result.status === "valid" + ? result.value + : this._def.catchValue({ + get error() { + return new ZodError(newCtx.common.issues); + }, + input: newCtx.data, + }), + }; + } + } + + removeCatch() { + return this._def.innerType; + } + + static create = ( + type: Inner, + params: RawCreateParams & { + catch: Inner["_output"] | (() => Inner["_output"]); + } + ): ZodCatch => { + return new ZodCatch({ + innerType: type, + typeName: ZodFirstPartyTypeKind.ZodCatch, + catchValue: typeof params.catch === "function" ? params.catch : () => params.catch, + ...processCreateParams(params), + }); + }; +} + +///////////////////////////////////////// +///////////////////////////////////////// +////////// ////////// +////////// ZodNaN ////////// +////////// ////////// +///////////////////////////////////////// +///////////////////////////////////////// + +export interface ZodNaNDef extends ZodTypeDef { + typeName: ZodFirstPartyTypeKind.ZodNaN; +} + +export class ZodNaN extends ZodType { + _parse(input: ParseInput): ParseReturnType { + const parsedType = this._getType(input); + if (parsedType !== ZodParsedType.nan) { + const ctx = this._getOrReturnCtx(input); + addIssueToContext(ctx, { + code: ZodIssueCode.invalid_type, + expected: ZodParsedType.nan, + received: ctx.parsedType, + }); + return INVALID; + } + + return { status: "valid", value: input.data }; + } + + static create = (params?: RawCreateParams): ZodNaN => { + return new ZodNaN({ + typeName: ZodFirstPartyTypeKind.ZodNaN, + ...processCreateParams(params), + }); + }; +} + +////////////////////////////////////////// +////////////////////////////////////////// +////////// ////////// +////////// ZodBranded ////////// +////////// ////////// +////////////////////////////////////////// +////////////////////////////////////////// + +export interface ZodBrandedDef extends ZodTypeDef { + type: T; + typeName: ZodFirstPartyTypeKind.ZodBranded; +} + +export const BRAND: unique symbol = Symbol("zod_brand"); +export type BRAND = { + [BRAND]: { [k in T]: true }; +}; + +export class ZodBranded extends ZodType< + T["_output"] & BRAND, + ZodBrandedDef, + T["_input"] +> { + _parse(input: ParseInput): ParseReturnType { + const { ctx } = this._processInputParams(input); + const data = ctx.data; + return this._def.type._parse({ + data, + path: ctx.path, + parent: ctx, + }); + } + + unwrap() { + return this._def.type; + } +} + +//////////////////////////////////////////// +//////////////////////////////////////////// +////////// ////////// +////////// ZodPipeline ////////// +////////// ////////// +//////////////////////////////////////////// +//////////////////////////////////////////// + +export interface ZodPipelineDef extends ZodTypeDef { + in: A; + out: B; + typeName: ZodFirstPartyTypeKind.ZodPipeline; +} + +export class ZodPipeline extends ZodType< + B["_output"], + ZodPipelineDef, + A["_input"] +> { + _parse(input: ParseInput): ParseReturnType { + const { status, ctx } = this._processInputParams(input); + if (ctx.common.async) { + const handleAsync = async () => { + const inResult = await this._def.in._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: ctx, + }); + if (inResult.status === "aborted") return INVALID; + if (inResult.status === "dirty") { + status.dirty(); + return DIRTY(inResult.value); + } else { + return this._def.out._parseAsync({ + data: inResult.value, + path: ctx.path, + parent: ctx, + }); + } + }; + return handleAsync(); + } else { + const inResult = this._def.in._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx, + }); + if (inResult.status === "aborted") return INVALID; + if (inResult.status === "dirty") { + status.dirty(); + return { + status: "dirty", + value: inResult.value, + }; + } else { + return this._def.out._parseSync({ + data: inResult.value, + path: ctx.path, + parent: ctx, + }); + } + } + } + + static create( + a: ASchema, + b: BSchema + ): ZodPipeline { + return new ZodPipeline({ + in: a, + out: b, + typeName: ZodFirstPartyTypeKind.ZodPipeline, + }); + } +} + +/////////////////////////////////////////// +/////////////////////////////////////////// +////////// ////////// +////////// ZodReadonly ////////// +////////// ////////// +/////////////////////////////////////////// +/////////////////////////////////////////// +type BuiltIn = + | (((...args: any[]) => any) | (new (...args: any[]) => any)) + | { readonly [Symbol.toStringTag]: string } + | Date + | Error + | Generator + | Promise + | RegExp; + +type MakeReadonly = T extends Map + ? ReadonlyMap + : T extends Set + ? ReadonlySet + : T extends [infer Head, ...infer Tail] + ? readonly [Head, ...Tail] + : T extends Array + ? ReadonlyArray + : T extends BuiltIn + ? T + : Readonly; + +export interface ZodReadonlyDef extends ZodTypeDef { + innerType: T; + typeName: ZodFirstPartyTypeKind.ZodReadonly; +} + +export class ZodReadonly extends ZodType< + MakeReadonly, + ZodReadonlyDef, + MakeReadonly +> { + _parse(input: ParseInput): ParseReturnType { + const result = this._def.innerType._parse(input); + const freeze = (data: ParseReturnType) => { + if (isValid(data)) { + data.value = Object.freeze(data.value); + } + return data; + }; + return isAsync(result) ? result.then((data) => freeze(data)) : freeze(result); + } + + static create = (type: Inner, params?: RawCreateParams): ZodReadonly => { + return new ZodReadonly({ + innerType: type, + typeName: ZodFirstPartyTypeKind.ZodReadonly, + ...processCreateParams(params), + }) as any; + }; + + unwrap() { + return this._def.innerType; + } +} + +//////////////////////////////////////// +//////////////////////////////////////// +////////// ////////// +////////// z.custom ////////// +////////// ////////// +//////////////////////////////////////// +//////////////////////////////////////// +function cleanParams(params: unknown, data: unknown) { + const p = typeof params === "function" ? params(data) : typeof params === "string" ? { message: params } : params; + + const p2 = typeof p === "string" ? { message: p } : p; + return p2; +} +type CustomParams = CustomErrorParams & { fatal?: boolean }; +export function custom( + check?: (data: any) => any, + _params: string | CustomParams | ((input: any) => CustomParams) = {}, + /** + * @deprecated + * + * Pass `fatal` into the params object instead: + * + * ```ts + * z.string().custom((val) => val.length > 5, { fatal: false }) + * ``` + * + */ + fatal?: boolean +): ZodType { + if (check) + return ZodAny.create().superRefine((data, ctx) => { + const r = check(data); + if (r instanceof Promise) { + return r.then((r) => { + if (!r) { + const params = cleanParams(_params, data); + const _fatal = params.fatal ?? fatal ?? true; + ctx.addIssue({ code: "custom", ...params, fatal: _fatal }); + } + }); + } + if (!r) { + const params = cleanParams(_params, data); + const _fatal = params.fatal ?? fatal ?? true; + ctx.addIssue({ code: "custom", ...params, fatal: _fatal }); + } + return; + }); + return ZodAny.create(); +} + +export { ZodType as Schema, ZodType as ZodSchema }; + +export const late = { + object: ZodObject.lazycreate, +}; + +export enum ZodFirstPartyTypeKind { + ZodString = "ZodString", + ZodNumber = "ZodNumber", + ZodNaN = "ZodNaN", + ZodBigInt = "ZodBigInt", + ZodBoolean = "ZodBoolean", + ZodDate = "ZodDate", + ZodSymbol = "ZodSymbol", + ZodUndefined = "ZodUndefined", + ZodNull = "ZodNull", + ZodAny = "ZodAny", + ZodUnknown = "ZodUnknown", + ZodNever = "ZodNever", + ZodVoid = "ZodVoid", + ZodArray = "ZodArray", + ZodObject = "ZodObject", + ZodUnion = "ZodUnion", + ZodDiscriminatedUnion = "ZodDiscriminatedUnion", + ZodIntersection = "ZodIntersection", + ZodTuple = "ZodTuple", + ZodRecord = "ZodRecord", + ZodMap = "ZodMap", + ZodSet = "ZodSet", + ZodFunction = "ZodFunction", + ZodLazy = "ZodLazy", + ZodLiteral = "ZodLiteral", + ZodEnum = "ZodEnum", + ZodEffects = "ZodEffects", + ZodNativeEnum = "ZodNativeEnum", + ZodOptional = "ZodOptional", + ZodNullable = "ZodNullable", + ZodDefault = "ZodDefault", + ZodCatch = "ZodCatch", + ZodPromise = "ZodPromise", + ZodBranded = "ZodBranded", + ZodPipeline = "ZodPipeline", + ZodReadonly = "ZodReadonly", +} +export type ZodFirstPartySchemaTypes = + | ZodString + | ZodNumber + | ZodNaN + | ZodBigInt + | ZodBoolean + | ZodDate + | ZodUndefined + | ZodNull + | ZodAny + | ZodUnknown + | ZodNever + | ZodVoid + | ZodArray + | ZodObject + | ZodUnion + | ZodDiscriminatedUnion + | ZodIntersection + | ZodTuple + | ZodRecord + | ZodMap + | ZodSet + | ZodFunction + | ZodLazy + | ZodLiteral + | ZodEnum + | ZodEffects + | ZodNativeEnum + | ZodOptional + | ZodNullable + | ZodDefault + | ZodCatch + | ZodPromise + | ZodBranded + | ZodPipeline + | ZodReadonly + | ZodSymbol; + +// requires TS 4.4+ +abstract class Class { + constructor(..._: any[]) {} +} +const instanceOfType = ( + // const instanceOfType = any>( + cls: T, + params: CustomParams = { + message: `Input not instance of ${cls.name}`, + } +) => custom>((data) => data instanceof cls, params); + +const stringType = ZodString.create; +const numberType = ZodNumber.create; +const nanType = ZodNaN.create; +const bigIntType = ZodBigInt.create; +const booleanType = ZodBoolean.create; +const dateType = ZodDate.create; +const symbolType = ZodSymbol.create; +const undefinedType = ZodUndefined.create; +const nullType = ZodNull.create; +const anyType = ZodAny.create; +const unknownType = ZodUnknown.create; +const neverType = ZodNever.create; +const voidType = ZodVoid.create; +const arrayType = ZodArray.create; +const objectType = ZodObject.create; +const strictObjectType = ZodObject.strictCreate; +const unionType = ZodUnion.create; +const discriminatedUnionType = ZodDiscriminatedUnion.create; +const intersectionType = ZodIntersection.create; +const tupleType = ZodTuple.create; +const recordType = ZodRecord.create; +const mapType = ZodMap.create; +const setType = ZodSet.create; +const functionType = ZodFunction.create; +const lazyType = ZodLazy.create; +const literalType = ZodLiteral.create; +const enumType = ZodEnum.create; +const nativeEnumType = ZodNativeEnum.create; +const promiseType = ZodPromise.create; +const effectsType = ZodEffects.create; +const optionalType = ZodOptional.create; +const nullableType = ZodNullable.create; +const preprocessType = ZodEffects.createWithPreprocess; +const pipelineType = ZodPipeline.create; +const ostring = () => stringType().optional(); +const onumber = () => numberType().optional(); +const oboolean = () => booleanType().optional(); + +export const coerce = { + string: ((arg) => ZodString.create({ ...arg, coerce: true })) as (typeof ZodString)["create"], + number: ((arg) => ZodNumber.create({ ...arg, coerce: true })) as (typeof ZodNumber)["create"], + boolean: ((arg) => + ZodBoolean.create({ + ...arg, + coerce: true, + })) as (typeof ZodBoolean)["create"], + bigint: ((arg) => ZodBigInt.create({ ...arg, coerce: true })) as (typeof ZodBigInt)["create"], + date: ((arg) => ZodDate.create({ ...arg, coerce: true })) as (typeof ZodDate)["create"], +}; + +export { + anyType as any, + arrayType as array, + bigIntType as bigint, + booleanType as boolean, + dateType as date, + discriminatedUnionType as discriminatedUnion, + effectsType as effect, + enumType as enum, + functionType as function, + instanceOfType as instanceof, + intersectionType as intersection, + lazyType as lazy, + literalType as literal, + mapType as map, + nanType as nan, + nativeEnumType as nativeEnum, + neverType as never, + nullType as null, + nullableType as nullable, + numberType as number, + objectType as object, + oboolean, + onumber, + optionalType as optional, + ostring, + pipelineType as pipeline, + preprocessType as preprocess, + promiseType as promise, + recordType as record, + setType as set, + strictObjectType as strictObject, + stringType as string, + symbolType as symbol, + effectsType as transformer, + tupleType as tuple, + undefinedType as undefined, + unionType as union, + unknownType as unknown, + voidType as void, +}; + +export const NEVER = INVALID as never; diff --git a/node_modules/zod/src/v4-mini/index.ts b/node_modules/zod/src/v4-mini/index.ts new file mode 100644 index 0000000..87b293a --- /dev/null +++ b/node_modules/zod/src/v4-mini/index.ts @@ -0,0 +1 @@ +export * from "../v4/mini/index.js"; diff --git a/node_modules/zod/src/v4/classic/checks.ts b/node_modules/zod/src/v4/classic/checks.ts new file mode 100644 index 0000000..ac2f1a2 --- /dev/null +++ b/node_modules/zod/src/v4/classic/checks.ts @@ -0,0 +1,31 @@ +export { + _lt as lt, + _lte as lte, + _gt as gt, + _gte as gte, + _positive as positive, + _negative as negative, + _nonpositive as nonpositive, + _nonnegative as nonnegative, + _multipleOf as multipleOf, + _maxSize as maxSize, + _minSize as minSize, + _size as size, + _maxLength as maxLength, + _minLength as minLength, + _length as length, + _regex as regex, + _lowercase as lowercase, + _uppercase as uppercase, + _includes as includes, + _startsWith as startsWith, + _endsWith as endsWith, + _property as property, + _mime as mime, + _overwrite as overwrite, + _normalize as normalize, + _trim as trim, + _toLowerCase as toLowerCase, + _toUpperCase as toUpperCase, + type $RefinementCtx as RefinementCtx, +} from "../core/index.js"; diff --git a/node_modules/zod/src/v4/classic/coerce.ts b/node_modules/zod/src/v4/classic/coerce.ts new file mode 100644 index 0000000..cc400e0 --- /dev/null +++ b/node_modules/zod/src/v4/classic/coerce.ts @@ -0,0 +1,27 @@ +import * as core from "../core/index.js"; +import * as schemas from "./schemas.js"; + +export interface ZodCoercedString extends schemas._ZodString> {} +export function string(params?: string | core.$ZodStringParams): ZodCoercedString { + return core._coercedString(schemas.ZodString, params) as any; +} + +export interface ZodCoercedNumber extends schemas._ZodNumber> {} +export function number(params?: string | core.$ZodNumberParams): ZodCoercedNumber { + return core._coercedNumber(schemas.ZodNumber, params) as ZodCoercedNumber; +} + +export interface ZodCoercedBoolean extends schemas._ZodBoolean> {} +export function boolean(params?: string | core.$ZodBooleanParams): ZodCoercedBoolean { + return core._coercedBoolean(schemas.ZodBoolean, params) as ZodCoercedBoolean; +} + +export interface ZodCoercedBigInt extends schemas._ZodBigInt> {} +export function bigint(params?: string | core.$ZodBigIntParams): ZodCoercedBigInt { + return core._coercedBigint(schemas.ZodBigInt, params) as ZodCoercedBigInt; +} + +export interface ZodCoercedDate extends schemas._ZodDate> {} +export function date(params?: string | core.$ZodDateParams): ZodCoercedDate { + return core._coercedDate(schemas.ZodDate, params) as ZodCoercedDate; +} diff --git a/node_modules/zod/src/v4/classic/compat.ts b/node_modules/zod/src/v4/classic/compat.ts new file mode 100644 index 0000000..86a5813 --- /dev/null +++ b/node_modules/zod/src/v4/classic/compat.ts @@ -0,0 +1,70 @@ +// Zod 3 compat layer + +import * as core from "../core/index.js"; +import type { ZodType } from "./schemas.js"; + +export type { + /** @deprecated Use `z.output` instead. */ + output as TypeOf, + /** @deprecated Use `z.output` instead. */ + output as Infer, + /** @deprecated Use `z.core.$$ZodFirstPartyTypes` instead */ + $ZodTypes as ZodFirstPartySchemaTypes, +} from "../core/index.js"; + +/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */ +export const ZodIssueCode = { + invalid_type: "invalid_type", + too_big: "too_big", + too_small: "too_small", + invalid_format: "invalid_format", + not_multiple_of: "not_multiple_of", + unrecognized_keys: "unrecognized_keys", + invalid_union: "invalid_union", + invalid_key: "invalid_key", + invalid_element: "invalid_element", + invalid_value: "invalid_value", + custom: "custom", +} as const; + +/** @deprecated Use `z.$ZodFlattenedError` */ +export type inferFlattenedErrors = core.$ZodFlattenedError, U>; + +/** @deprecated Use `z.$ZodFormattedError` */ +export type inferFormattedError, U = string> = core.$ZodFormattedError< + core.output, + U +>; + +/** Use `z.$brand` instead */ +export type BRAND = { + [core.$brand]: { [k in T]: true }; +}; +export { $brand, config } from "../core/index.js"; + +/** @deprecated Use `z.config(params)` instead. */ +export function setErrorMap(map: core.$ZodErrorMap): void { + core.config({ + customError: map, + }); +} + +/** @deprecated Use `z.config()` instead. */ +export function getErrorMap(): core.$ZodErrorMap | undefined { + return core.config().customError; +} + +export type { + /** @deprecated Use z.ZodType (without generics) instead. */ + ZodType as ZodTypeAny, + /** @deprecated Use `z.ZodType` */ + ZodType as ZodSchema, + /** @deprecated Use `z.ZodType` */ + ZodType as Schema, +}; + +/** Included for Zod 3 compatibility */ +export type ZodRawShape = core.$ZodShape; + +/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */ +export enum ZodFirstPartyTypeKind {} diff --git a/node_modules/zod/src/v4/classic/errors.ts b/node_modules/zod/src/v4/classic/errors.ts new file mode 100644 index 0000000..695a534 --- /dev/null +++ b/node_modules/zod/src/v4/classic/errors.ts @@ -0,0 +1,82 @@ +import * as core from "../core/index.js"; +import { $ZodError } from "../core/index.js"; +import * as util from "../core/util.js"; + +/** @deprecated Use `z.core.$ZodIssue` from `@zod/core` instead, especially if you are building a library on top of Zod. */ +export type ZodIssue = core.$ZodIssue; + +/** An Error-like class used to store Zod validation issues. */ +export interface ZodError extends $ZodError { + /** @deprecated Use the `z.treeifyError(err)` function instead. */ + format(): core.$ZodFormattedError; + format(mapper: (issue: core.$ZodIssue) => U): core.$ZodFormattedError; + /** @deprecated Use the `z.treeifyError(err)` function instead. */ + flatten(): core.$ZodFlattenedError; + flatten(mapper: (issue: core.$ZodIssue) => U): core.$ZodFlattenedError; + /** @deprecated Push directly to `.issues` instead. */ + addIssue(issue: core.$ZodIssue): void; + /** @deprecated Push directly to `.issues` instead. */ + addIssues(issues: core.$ZodIssue[]): void; + + /** @deprecated Check `err.issues.length === 0` instead. */ + isEmpty: boolean; +} + +const initializer = (inst: ZodError, issues: core.$ZodIssue[]) => { + $ZodError.init(inst, issues); + inst.name = "ZodError"; + Object.defineProperties(inst, { + format: { + value: (mapper: any) => core.formatError(inst, mapper), + // enumerable: false, + }, + flatten: { + value: (mapper: any) => core.flattenError(inst, mapper), + // enumerable: false, + }, + addIssue: { + value: (issue: any) => { + inst.issues.push(issue); + inst.message = JSON.stringify(inst.issues, util.jsonStringifyReplacer, 2); + }, + // enumerable: false, + }, + addIssues: { + value: (issues: any) => { + inst.issues.push(...issues); + inst.message = JSON.stringify(inst.issues, util.jsonStringifyReplacer, 2); + }, + // enumerable: false, + }, + isEmpty: { + get() { + return inst.issues.length === 0; + }, + // enumerable: false, + }, + }); + // Object.defineProperty(inst, "isEmpty", { + // get() { + // return inst.issues.length === 0; + // }, + // }); +}; +export const ZodError: core.$constructor = core.$constructor("ZodError", initializer); +export const ZodRealError: core.$constructor = core.$constructor("ZodError", initializer, { + Parent: Error, +}); + +export type { + /** @deprecated Use `z.core.$ZodFlattenedError` instead. */ + $ZodFlattenedError as ZodFlattenedError, + /** @deprecated Use `z.core.$ZodFormattedError` instead. */ + $ZodFormattedError as ZodFormattedError, + /** @deprecated Use `z.core.$ZodErrorMap` instead. */ + $ZodErrorMap as ZodErrorMap, +} from "../core/index.js"; + +/** @deprecated Use `z.core.$ZodRawIssue` instead. */ +export type IssueData = core.$ZodRawIssue; + +// /** @deprecated Use `z.core.$ZodErrorMapCtx` instead. */ +// export type ErrorMapCtx = core.$ZodErrorMapCtx; diff --git a/node_modules/zod/src/v4/classic/external.ts b/node_modules/zod/src/v4/classic/external.ts new file mode 100644 index 0000000..855f5a7 --- /dev/null +++ b/node_modules/zod/src/v4/classic/external.ts @@ -0,0 +1,50 @@ +export * as core from "../core/index.js"; +export * from "./schemas.js"; +export * from "./checks.js"; +export * from "./errors.js"; +export * from "./parse.js"; +export * from "./compat.js"; + +// zod-specified +import { config } from "../core/index.js"; +import en from "../locales/en.js"; +config(en()); + +export type { infer, output, input } from "../core/index.js"; +export { + globalRegistry, + type GlobalMeta, + registry, + config, + function, + $output, + $input, + $brand, + clone, + regexes, + treeifyError, + prettifyError, + formatError, + flattenError, + toJSONSchema, + TimePrecision, + NEVER, +} from "../core/index.js"; + +export * as locales from "../locales/index.js"; + +// iso +// must be exported from top-level +// https://github.com/colinhacks/zod/issues/4491 +export { ZodISODateTime, ZodISODate, ZodISOTime, ZodISODuration } from "./iso.js"; +export * as iso from "./iso.js"; + +// coerce +export type { + ZodCoercedString, + ZodCoercedNumber, + ZodCoercedBigInt, + ZodCoercedBoolean, + ZodCoercedDate, +} from "./coerce.js"; +export * as coerce from "./coerce.js"; diff --git a/node_modules/zod/src/v4/classic/index.ts b/node_modules/zod/src/v4/classic/index.ts new file mode 100644 index 0000000..f0f7547 --- /dev/null +++ b/node_modules/zod/src/v4/classic/index.ts @@ -0,0 +1,5 @@ +import * as z from "./external.js"; + +export { z }; +export * from "./external.js"; +export default z; diff --git a/node_modules/zod/src/v4/classic/iso.ts b/node_modules/zod/src/v4/classic/iso.ts new file mode 100644 index 0000000..b08696d --- /dev/null +++ b/node_modules/zod/src/v4/classic/iso.ts @@ -0,0 +1,90 @@ +import * as core from "../core/index.js"; +import * as schemas from "./schemas.js"; + +////////////////////////////////////////////// +////////////////////////////////////////////// +////////// ////////// +////////// ZodISODateTime ////////// +////////// ////////// +////////////////////////////////////////////// +////////////////////////////////////////////// + +export interface ZodISODateTime extends schemas.ZodStringFormat { + _zod: core.$ZodISODateTimeInternals; +} +export const ZodISODateTime: core.$constructor = /*@__PURE__*/ core.$constructor( + "ZodISODateTime", + (inst, def) => { + core.$ZodISODateTime.init(inst, def); + schemas.ZodStringFormat.init(inst, def); + } +); + +export function datetime(params?: string | core.$ZodISODateTimeParams): ZodISODateTime { + return core._isoDateTime(ZodISODateTime, params); +} + +////////////////////////////////////////// +////////////////////////////////////////// +////////// ////////// +////////// ZodISODate ////////// +////////// ////////// +////////////////////////////////////////// +////////////////////////////////////////// + +export interface ZodISODate extends schemas.ZodStringFormat { + _zod: core.$ZodISODateInternals; +} +export const ZodISODate: core.$constructor = /*@__PURE__*/ core.$constructor("ZodISODate", (inst, def) => { + core.$ZodISODate.init(inst, def); + schemas.ZodStringFormat.init(inst, def); +}); + +export function date(params?: string | core.$ZodISODateParams): ZodISODate { + return core._isoDate(ZodISODate, params); +} + +// ZodISOTime + +////////////////////////////////////////// +////////////////////////////////////////// +////////// ////////// +////////// ZodISOTime ////////// +////////// ////////// +////////////////////////////////////////// +////////////////////////////////////////// + +export interface ZodISOTime extends schemas.ZodStringFormat { + _zod: core.$ZodISOTimeInternals; +} +export const ZodISOTime: core.$constructor = /*@__PURE__*/ core.$constructor("ZodISOTime", (inst, def) => { + core.$ZodISOTime.init(inst, def); + schemas.ZodStringFormat.init(inst, def); +}); + +export function time(params?: string | core.$ZodISOTimeParams): ZodISOTime { + return core._isoTime(ZodISOTime, params); +} + +////////////////////////////////////////////// +////////////////////////////////////////////// +////////// ////////// +////////// ZodISODuration ////////// +////////// ////////// +////////////////////////////////////////////// +////////////////////////////////////////////// + +export interface ZodISODuration extends schemas.ZodStringFormat { + _zod: core.$ZodISODurationInternals; +} +export const ZodISODuration: core.$constructor = /*@__PURE__*/ core.$constructor( + "ZodISODuration", + (inst, def) => { + core.$ZodISODuration.init(inst, def); + schemas.ZodStringFormat.init(inst, def); + } +); + +export function duration(params?: string | core.$ZodISODurationParams): ZodISODuration { + return core._isoDuration(ZodISODuration, params); +} diff --git a/node_modules/zod/src/v4/classic/parse.ts b/node_modules/zod/src/v4/classic/parse.ts new file mode 100644 index 0000000..0d77e20 --- /dev/null +++ b/node_modules/zod/src/v4/classic/parse.ts @@ -0,0 +1,33 @@ +import * as core from "../core/index.js"; +import { type ZodError, ZodRealError } from "./errors.js"; + +export type ZodSafeParseResult = ZodSafeParseSuccess | ZodSafeParseError; +export type ZodSafeParseSuccess = { success: true; data: T; error?: never }; +export type ZodSafeParseError = { success: false; data?: never; error: ZodError }; + +export const parse: ( + schema: T, + value: unknown, + _ctx?: core.ParseContext, + _params?: { callee?: core.util.AnyFunc; Err?: core.$ZodErrorClass } +) => core.output = /* @__PURE__ */ core._parse(ZodRealError) as any; + +export const parseAsync: ( + schema: T, + value: unknown, + _ctx?: core.ParseContext, + _params?: { callee?: core.util.AnyFunc; Err?: core.$ZodErrorClass } +) => Promise> = /* @__PURE__ */ core._parseAsync(ZodRealError) as any; + +export const safeParse: ( + schema: T, + value: unknown, + _ctx?: core.ParseContext + // _params?: { callee?: core.util.AnyFunc; Err?: core.$ZodErrorClass } +) => ZodSafeParseResult> = /* @__PURE__ */ core._safeParse(ZodRealError) as any; + +export const safeParseAsync: ( + schema: T, + value: unknown, + _ctx?: core.ParseContext +) => Promise>> = /* @__PURE__ */ core._safeParseAsync(ZodRealError) as any; diff --git a/node_modules/zod/src/v4/classic/schemas.ts b/node_modules/zod/src/v4/classic/schemas.ts new file mode 100644 index 0000000..43e3057 --- /dev/null +++ b/node_modules/zod/src/v4/classic/schemas.ts @@ -0,0 +1,2031 @@ +import * as core from "../core/index.js"; +import { util } from "../core/index.js"; + +import * as checks from "./checks.js"; +import * as iso from "./iso.js"; +import * as parse from "./parse.js"; + +/////////////////////////////////////////// +/////////////////////////////////////////// +//////////// //////////// +//////////// ZodType //////////// +//////////// //////////// +/////////////////////////////////////////// +/////////////////////////////////////////// + +export interface ZodType< + out Output = unknown, + out Input = unknown, + out Internals extends core.$ZodTypeInternals = core.$ZodTypeInternals, +> extends core.$ZodType { + def: Internals["def"]; + type: Internals["def"]["type"]; + + /** @deprecated Use `.def` instead. */ + _def: Internals["def"]; + /** @deprecated Use `z.output` instead. */ + _output: Internals["output"]; + /** @deprecated Use `z.input` instead. */ + _input: Internals["input"]; + + // base methods + check(...checks: (core.CheckFn> | core.$ZodCheck>)[]): this; + clone(def?: Internals["def"], params?: { parent: boolean }): this; + register( + registry: R, + ...meta: this extends R["_schema"] + ? undefined extends R["_meta"] + ? [core.$replace?] + : [core.$replace] + : ["Incompatible schema"] + ): this; + + brand(value?: T): PropertyKey extends T ? this : core.$ZodBranded; + + // parsing + parse(data: unknown, params?: core.ParseContext): core.output; + safeParse(data: unknown, params?: core.ParseContext): parse.ZodSafeParseResult>; + parseAsync(data: unknown, params?: core.ParseContext): Promise>; + safeParseAsync( + data: unknown, + params?: core.ParseContext + ): Promise>>; + spa: ( + data: unknown, + params?: core.ParseContext + ) => Promise>>; + + // refinements + refine(check: (arg: core.output) => unknown | Promise, params?: string | core.$ZodCustomParams): this; + superRefine( + refinement: (arg: core.output, ctx: core.$RefinementCtx>) => void | Promise + ): this; + overwrite(fn: (x: core.output) => core.output): this; + + // wrappers + optional(): ZodOptional; + nonoptional(params?: string | core.$ZodNonOptionalParams): ZodNonOptional; + nullable(): ZodNullable; + nullish(): ZodOptional>; + default(def: core.output): ZodDefault; + default(def: () => util.NoUndefined>): ZodDefault; + prefault(def: () => core.input): ZodPrefault; + prefault(def: core.input): ZodPrefault; + array(): ZodArray; + or(option: T): ZodUnion<[this, T]>; + and(incoming: T): ZodIntersection; + transform( + transform: (arg: core.output, ctx: core.$RefinementCtx>) => NewOut | Promise + ): ZodPipe, core.output>>; + catch(def: core.output): ZodCatch; + catch(def: (ctx: core.$ZodCatchCtx) => core.output): ZodCatch; + pipe>>( + target: T | core.$ZodType> + ): ZodPipe; + readonly(): ZodReadonly; + + /** Returns a new instance that has been registered in `z.globalRegistry` with the specified description */ + describe(description: string): this; + description?: string; + /** Returns the metadata associated with this instance in `z.globalRegistry` */ + meta(): core.$replace | undefined; + /** Returns a new instance that has been registered in `z.globalRegistry` with the specified metadata */ + meta(data: core.$replace): this; + + // helpers + /** @deprecated Try safe-parsing `undefined` (this is what `isOptional` does internally): + * + * ```ts + * const schema = z.string().optional(); + * const isOptional = schema.safeParse(undefined).success; // true + * ``` + */ + isOptional(): boolean; + /** + * @deprecated Try safe-parsing `null` (this is what `isNullable` does internally): + * + * ```ts + * const schema = z.string().nullable(); + * const isNullable = schema.safeParse(null).success; // true + * ``` + */ + isNullable(): boolean; +} + +export interface _ZodType + extends ZodType {} + +export const ZodType: core.$constructor = /*@__PURE__*/ core.$constructor("ZodType", (inst, def) => { + core.$ZodType.init(inst, def); + inst.def = def; + Object.defineProperty(inst, "_def", { value: def }); + + // base methods + inst.check = (...checks) => { + return inst.clone( + { + ...def, + checks: [ + ...(def.checks ?? []), + ...checks.map((ch) => + typeof ch === "function" ? { _zod: { check: ch, def: { check: "custom" }, onattach: [] } } : ch + ), + ], + } + // { parent: true } + ); + }; + inst.clone = (def, params) => core.clone(inst, def, params); + inst.brand = () => inst as any; + inst.register = ((reg: any, meta: any) => { + reg.add(inst, meta); + return inst; + }) as any; + + // parsing + inst.parse = (data, params) => parse.parse(inst, data, params, { callee: inst.parse }); + inst.safeParse = (data, params) => parse.safeParse(inst, data, params); + inst.parseAsync = async (data, params) => parse.parseAsync(inst, data, params, { callee: inst.parseAsync }); + inst.safeParseAsync = async (data, params) => parse.safeParseAsync(inst, data, params); + inst.spa = inst.safeParseAsync; + + // refinements + inst.refine = (check, params) => inst.check(refine(check, params)); + inst.superRefine = (refinement) => inst.check(superRefine(refinement)); + inst.overwrite = (fn) => inst.check(checks.overwrite(fn)); + + // wrappers + inst.optional = () => optional(inst); + inst.nullable = () => nullable(inst); + inst.nullish = () => optional(nullable(inst)); + inst.nonoptional = (params) => nonoptional(inst, params); + inst.array = () => array(inst); + inst.or = (arg) => union([inst, arg]); + inst.and = (arg) => intersection(inst, arg); + inst.transform = (tx) => pipe(inst, transform(tx as any)) as never; + inst.default = (def) => _default(inst, def); + inst.prefault = (def) => prefault(inst, def); + // inst.coalesce = (def, params) => coalesce(inst, def, params); + inst.catch = (params) => _catch(inst, params); + inst.pipe = (target) => pipe(inst, target); + inst.readonly = () => readonly(inst); + + // meta + inst.describe = (description) => { + const cl = inst.clone(); + core.globalRegistry.add(cl, { description }); + return cl; + }; + Object.defineProperty(inst, "description", { + get() { + return core.globalRegistry.get(inst)?.description; + }, + configurable: true, + }); + inst.meta = (...args: any) => { + if (args.length === 0) { + return core.globalRegistry.get(inst); + } + const cl = inst.clone(); + core.globalRegistry.add(cl, args[0]); + return cl as any; + }; + + // helpers + inst.isOptional = () => inst.safeParse(undefined).success; + inst.isNullable = () => inst.safeParse(null).success; + return inst; +}); + +// ZodString +export interface _ZodString = core.$ZodStringInternals> + extends _ZodType { + format: string | null; + minLength: number | null; + maxLength: number | null; + + // miscellaneous checks + regex(regex: RegExp, params?: string | core.$ZodCheckRegexParams): this; + includes(value: string, params?: core.$ZodCheckIncludesParams): this; + startsWith(value: string, params?: string | core.$ZodCheckStartsWithParams): this; + endsWith(value: string, params?: string | core.$ZodCheckEndsWithParams): this; + min(minLength: number, params?: string | core.$ZodCheckMinLengthParams): this; + max(maxLength: number, params?: string | core.$ZodCheckMaxLengthParams): this; + length(len: number, params?: string | core.$ZodCheckLengthEqualsParams): this; + nonempty(params?: string | core.$ZodCheckMinLengthParams): this; + lowercase(params?: string | core.$ZodCheckLowerCaseParams): this; + uppercase(params?: string | core.$ZodCheckUpperCaseParams): this; + + // transforms + trim(): this; + normalize(form?: "NFC" | "NFD" | "NFKC" | "NFKD" | (string & {})): this; + toLowerCase(): this; + toUpperCase(): this; +} + +/** @internal */ +export const _ZodString: core.$constructor<_ZodString> = /*@__PURE__*/ core.$constructor("_ZodString", (inst, def) => { + core.$ZodString.init(inst, def); + ZodType.init(inst, def); + + const bag = inst._zod.bag; + inst.format = bag.format ?? null; + inst.minLength = bag.minimum ?? null; + inst.maxLength = bag.maximum ?? null; + + // validations + inst.regex = (...args) => inst.check(checks.regex(...args)); + inst.includes = (...args) => inst.check(checks.includes(...args)); + inst.startsWith = (...args) => inst.check(checks.startsWith(...args)); + inst.endsWith = (...args) => inst.check(checks.endsWith(...args)); + inst.min = (...args) => inst.check(checks.minLength(...args)); + inst.max = (...args) => inst.check(checks.maxLength(...args)); + inst.length = (...args) => inst.check(checks.length(...args)); + inst.nonempty = (...args) => inst.check(checks.minLength(1, ...args)); + inst.lowercase = (params) => inst.check(checks.lowercase(params)); + inst.uppercase = (params) => inst.check(checks.uppercase(params)); + + // transforms + inst.trim = () => inst.check(checks.trim()); + inst.normalize = (...args) => inst.check(checks.normalize(...args)); + inst.toLowerCase = () => inst.check(checks.toLowerCase()); + inst.toUpperCase = () => inst.check(checks.toUpperCase()); +}); + +export interface ZodString extends _ZodString> { + // string format checks + + /** @deprecated Use `z.email()` instead. */ + email(params?: string | core.$ZodCheckEmailParams): this; + /** @deprecated Use `z.url()` instead. */ + url(params?: string | core.$ZodCheckURLParams): this; + /** @deprecated Use `z.jwt()` instead. */ + jwt(params?: string | core.$ZodCheckJWTParams): this; + /** @deprecated Use `z.emoji()` instead. */ + emoji(params?: string | core.$ZodCheckEmojiParams): this; + /** @deprecated Use `z.guid()` instead. */ + guid(params?: string | core.$ZodCheckGUIDParams): this; + /** @deprecated Use `z.uuid()` instead. */ + uuid(params?: string | core.$ZodCheckUUIDParams): this; + /** @deprecated Use `z.uuid()` instead. */ + uuidv4(params?: string | core.$ZodCheckUUIDParams): this; + /** @deprecated Use `z.uuid()` instead. */ + uuidv6(params?: string | core.$ZodCheckUUIDParams): this; + /** @deprecated Use `z.uuid()` instead. */ + uuidv7(params?: string | core.$ZodCheckUUIDParams): this; + /** @deprecated Use `z.nanoid()` instead. */ + nanoid(params?: string | core.$ZodCheckNanoIDParams): this; + /** @deprecated Use `z.guid()` instead. */ + guid(params?: string | core.$ZodCheckGUIDParams): this; + /** @deprecated Use `z.cuid()` instead. */ + cuid(params?: string | core.$ZodCheckCUIDParams): this; + /** @deprecated Use `z.cuid2()` instead. */ + cuid2(params?: string | core.$ZodCheckCUID2Params): this; + /** @deprecated Use `z.ulid()` instead. */ + ulid(params?: string | core.$ZodCheckULIDParams): this; + /** @deprecated Use `z.base64()` instead. */ + base64(params?: string | core.$ZodCheckBase64Params): this; + /** @deprecated Use `z.base64url()` instead. */ + base64url(params?: string | core.$ZodCheckBase64URLParams): this; + // /** @deprecated Use `z.jsonString()` instead. */ + // jsonString(params?: string | core.$ZodCheckJSONStringParams): this; + /** @deprecated Use `z.xid()` instead. */ + xid(params?: string | core.$ZodCheckXIDParams): this; + /** @deprecated Use `z.ksuid()` instead. */ + ksuid(params?: string | core.$ZodCheckKSUIDParams): this; + // /** @deprecated Use `z.ipv4()` or `z.ipv6()` instead. */ + // ip(params?: string | (core.$ZodCheckIPv4Params & { version?: "v4" | "v6" })): ZodUnion<[this, this]>; + /** @deprecated Use `z.ipv4()` instead. */ + ipv4(params?: string | core.$ZodCheckIPv4Params): this; + /** @deprecated Use `z.ipv6()` instead. */ + ipv6(params?: string | core.$ZodCheckIPv6Params): this; + /** @deprecated Use `z.cidrv4()` instead. */ + cidrv4(params?: string | core.$ZodCheckCIDRv4Params): this; + /** @deprecated Use `z.cidrv6()` instead. */ + cidrv6(params?: string | core.$ZodCheckCIDRv6Params): this; + /** @deprecated Use `z.e164()` instead. */ + e164(params?: string | core.$ZodCheckE164Params): this; + + // ISO 8601 checks + /** @deprecated Use `z.iso.datetime()` instead. */ + datetime(params?: string | core.$ZodCheckISODateTimeParams): this; + /** @deprecated Use `z.iso.date()` instead. */ + date(params?: string | core.$ZodCheckISODateParams): this; + /** @deprecated Use `z.iso.time()` instead. */ + time( + params?: + | string + // | { + // message?: string | undefined; + // precision?: number | null; + // } + | core.$ZodCheckISOTimeParams + ): this; + /** @deprecated Use `z.iso.duration()` instead. */ + duration(params?: string | core.$ZodCheckISODurationParams): this; +} + +export const ZodString: core.$constructor = /*@__PURE__*/ core.$constructor("ZodString", (inst, def) => { + core.$ZodString.init(inst, def); + _ZodString.init(inst, def); + + inst.email = (params) => inst.check(core._email(ZodEmail, params)); + inst.url = (params) => inst.check(core._url(ZodURL, params)); + inst.jwt = (params) => inst.check(core._jwt(ZodJWT, params)); + inst.emoji = (params) => inst.check(core._emoji(ZodEmoji, params)); + inst.guid = (params) => inst.check(core._guid(ZodGUID, params)); + inst.uuid = (params) => inst.check(core._uuid(ZodUUID, params)); + inst.uuidv4 = (params) => inst.check(core._uuidv4(ZodUUID, params)); + inst.uuidv6 = (params) => inst.check(core._uuidv6(ZodUUID, params)); + inst.uuidv7 = (params) => inst.check(core._uuidv7(ZodUUID, params)); + inst.nanoid = (params) => inst.check(core._nanoid(ZodNanoID, params)); + inst.guid = (params) => inst.check(core._guid(ZodGUID, params)); + inst.cuid = (params) => inst.check(core._cuid(ZodCUID, params)); + inst.cuid2 = (params) => inst.check(core._cuid2(ZodCUID2, params)); + inst.ulid = (params) => inst.check(core._ulid(ZodULID, params)); + inst.base64 = (params) => inst.check(core._base64(ZodBase64, params)); + inst.base64url = (params) => inst.check(core._base64url(ZodBase64URL, params)); + inst.xid = (params) => inst.check(core._xid(ZodXID, params)); + inst.ksuid = (params) => inst.check(core._ksuid(ZodKSUID, params)); + inst.ipv4 = (params) => inst.check(core._ipv4(ZodIPv4, params)); + inst.ipv6 = (params) => inst.check(core._ipv6(ZodIPv6, params)); + inst.cidrv4 = (params) => inst.check(core._cidrv4(ZodCIDRv4, params)); + inst.cidrv6 = (params) => inst.check(core._cidrv6(ZodCIDRv6, params)); + inst.e164 = (params) => inst.check(core._e164(ZodE164, params)); + + // iso + inst.datetime = (params) => inst.check(iso.datetime(params as any)); + inst.date = (params) => inst.check(iso.date(params as any)); + inst.time = (params) => inst.check(iso.time(params as any)); + inst.duration = (params) => inst.check(iso.duration(params as any)); +}); + +export function string(params?: string | core.$ZodStringParams): ZodString; +export function string(params?: string | core.$ZodStringParams): core.$ZodType; +export function string(params?: string | core.$ZodStringParams): ZodString { + return core._string(ZodString, params) as any; +} + +// ZodStringFormat +export interface ZodStringFormat + extends _ZodString> {} +export const ZodStringFormat: core.$constructor = /*@__PURE__*/ core.$constructor( + "ZodStringFormat", + (inst, def) => { + core.$ZodStringFormat.init(inst, def); + _ZodString.init(inst, def); + } +); + +// ZodEmail +export interface ZodEmail extends ZodStringFormat<"email"> { + _zod: core.$ZodEmailInternals; +} +export const ZodEmail: core.$constructor = /*@__PURE__*/ core.$constructor("ZodEmail", (inst, def) => { + // ZodStringFormat.init(inst, def); + core.$ZodEmail.init(inst, def); + ZodStringFormat.init(inst, def); +}); + +export function email(params?: string | core.$ZodEmailParams): ZodEmail { + return core._email(ZodEmail, params); +} + +// ZodGUID +export interface ZodGUID extends ZodStringFormat<"guid"> { + _zod: core.$ZodGUIDInternals; +} +export const ZodGUID: core.$constructor = /*@__PURE__*/ core.$constructor("ZodGUID", (inst, def) => { + // ZodStringFormat.init(inst, def); + core.$ZodGUID.init(inst, def); + ZodStringFormat.init(inst, def); +}); + +export function guid(params?: string | core.$ZodGUIDParams): ZodGUID { + return core._guid(ZodGUID, params); +} + +// ZodUUID +export interface ZodUUID extends ZodStringFormat<"uuid"> { + _zod: core.$ZodUUIDInternals; +} +export const ZodUUID: core.$constructor = /*@__PURE__*/ core.$constructor("ZodUUID", (inst, def) => { + // ZodStringFormat.init(inst, def); + core.$ZodUUID.init(inst, def); + ZodStringFormat.init(inst, def); +}); + +export function uuid(params?: string | core.$ZodUUIDParams): ZodUUID { + return core._uuid(ZodUUID, params); +} + +export function uuidv4(params?: string | core.$ZodUUIDv4Params): ZodUUID { + return core._uuidv4(ZodUUID, params); +} + +// ZodUUIDv6 + +export function uuidv6(params?: string | core.$ZodUUIDv6Params): ZodUUID { + return core._uuidv6(ZodUUID, params); +} + +// ZodUUIDv7 + +export function uuidv7(params?: string | core.$ZodUUIDv7Params): ZodUUID { + return core._uuidv7(ZodUUID, params); +} + +// ZodURL +export interface ZodURL extends ZodStringFormat<"url"> { + _zod: core.$ZodURLInternals; +} +export const ZodURL: core.$constructor = /*@__PURE__*/ core.$constructor("ZodURL", (inst, def) => { + // ZodStringFormat.init(inst, def); + core.$ZodURL.init(inst, def); + ZodStringFormat.init(inst, def); +}); + +export function url(params?: string | core.$ZodURLParams): ZodURL { + return core._url(ZodURL, params); +} + +// ZodEmoji +export interface ZodEmoji extends ZodStringFormat<"emoji"> { + _zod: core.$ZodEmojiInternals; +} +export const ZodEmoji: core.$constructor = /*@__PURE__*/ core.$constructor("ZodEmoji", (inst, def) => { + // ZodStringFormat.init(inst, def); + core.$ZodEmoji.init(inst, def); + ZodStringFormat.init(inst, def); +}); + +export function emoji(params?: string | core.$ZodEmojiParams): ZodEmoji { + return core._emoji(ZodEmoji, params); +} + +// ZodNanoID +export interface ZodNanoID extends ZodStringFormat<"nanoid"> { + _zod: core.$ZodNanoIDInternals; +} +export const ZodNanoID: core.$constructor = /*@__PURE__*/ core.$constructor("ZodNanoID", (inst, def) => { + // ZodStringFormat.init(inst, def); + core.$ZodNanoID.init(inst, def); + ZodStringFormat.init(inst, def); +}); + +export function nanoid(params?: string | core.$ZodNanoIDParams): ZodNanoID { + return core._nanoid(ZodNanoID, params); +} + +// ZodCUID +export interface ZodCUID extends ZodStringFormat<"cuid"> { + _zod: core.$ZodCUIDInternals; +} +export const ZodCUID: core.$constructor = /*@__PURE__*/ core.$constructor("ZodCUID", (inst, def) => { + // ZodStringFormat.init(inst, def); + core.$ZodCUID.init(inst, def); + ZodStringFormat.init(inst, def); +}); + +export function cuid(params?: string | core.$ZodCUIDParams): ZodCUID { + return core._cuid(ZodCUID, params); +} + +// ZodCUID2 +export interface ZodCUID2 extends ZodStringFormat<"cuid2"> { + _zod: core.$ZodCUID2Internals; +} +export const ZodCUID2: core.$constructor = /*@__PURE__*/ core.$constructor("ZodCUID2", (inst, def) => { + // ZodStringFormat.init(inst, def); + core.$ZodCUID2.init(inst, def); + ZodStringFormat.init(inst, def); +}); + +export function cuid2(params?: string | core.$ZodCUID2Params): ZodCUID2 { + return core._cuid2(ZodCUID2, params); +} + +// ZodULID +export interface ZodULID extends ZodStringFormat<"ulid"> { + _zod: core.$ZodULIDInternals; +} +export const ZodULID: core.$constructor = /*@__PURE__*/ core.$constructor("ZodULID", (inst, def) => { + // ZodStringFormat.init(inst, def); + core.$ZodULID.init(inst, def); + ZodStringFormat.init(inst, def); +}); + +export function ulid(params?: string | core.$ZodULIDParams): ZodULID { + return core._ulid(ZodULID, params); +} + +// ZodXID +export interface ZodXID extends ZodStringFormat<"xid"> { + _zod: core.$ZodXIDInternals; +} +export const ZodXID: core.$constructor = /*@__PURE__*/ core.$constructor("ZodXID", (inst, def) => { + // ZodStringFormat.init(inst, def); + core.$ZodXID.init(inst, def); + ZodStringFormat.init(inst, def); +}); + +export function xid(params?: string | core.$ZodXIDParams): ZodXID { + return core._xid(ZodXID, params); +} + +// ZodKSUID +export interface ZodKSUID extends ZodStringFormat<"ksuid"> { + _zod: core.$ZodKSUIDInternals; +} +export const ZodKSUID: core.$constructor = /*@__PURE__*/ core.$constructor("ZodKSUID", (inst, def) => { + // ZodStringFormat.init(inst, def); + core.$ZodKSUID.init(inst, def); + ZodStringFormat.init(inst, def); +}); + +export function ksuid(params?: string | core.$ZodKSUIDParams): ZodKSUID { + return core._ksuid(ZodKSUID, params); +} + +// ZodIP +// export interface ZodIP extends ZodStringFormat<"ip"> { +// _zod: core.$ZodIPInternals; +// } +// export const ZodIP: core.$constructor = /*@__PURE__*/ core.$constructor("ZodIP", (inst, def) => { +// // ZodStringFormat.init(inst, def); +// core.$ZodIP.init(inst, def); +// ZodStringFormat.init(inst, def); +// }); + +// export function ip(params?: string | core.$ZodIPParams): ZodIP { +// return core._ip(ZodIP, params); +// } + +// ZodIPv4 +export interface ZodIPv4 extends ZodStringFormat<"ipv4"> { + _zod: core.$ZodIPv4Internals; +} +export const ZodIPv4: core.$constructor = /*@__PURE__*/ core.$constructor("ZodIPv4", (inst, def) => { + // ZodStringFormat.init(inst, def); + core.$ZodIPv4.init(inst, def); + ZodStringFormat.init(inst, def); +}); + +export function ipv4(params?: string | core.$ZodIPv4Params): ZodIPv4 { + return core._ipv4(ZodIPv4, params); +} + +// ZodIPv6 +export interface ZodIPv6 extends ZodStringFormat<"ipv6"> { + _zod: core.$ZodIPv6Internals; +} +export const ZodIPv6: core.$constructor = /*@__PURE__*/ core.$constructor("ZodIPv6", (inst, def) => { + // ZodStringFormat.init(inst, def); + core.$ZodIPv6.init(inst, def); + ZodStringFormat.init(inst, def); +}); +export function ipv6(params?: string | core.$ZodIPv6Params): ZodIPv6 { + return core._ipv6(ZodIPv6, params); +} + +// ZodCIDRv4 +export interface ZodCIDRv4 extends ZodStringFormat<"cidrv4"> { + _zod: core.$ZodCIDRv4Internals; +} +export const ZodCIDRv4: core.$constructor = /*@__PURE__*/ core.$constructor("ZodCIDRv4", (inst, def) => { + core.$ZodCIDRv4.init(inst, def); + ZodStringFormat.init(inst, def); +}); + +export function cidrv4(params?: string | core.$ZodCIDRv4Params): ZodCIDRv4 { + return core._cidrv4(ZodCIDRv4, params); +} + +// ZodCIDRv6 +export interface ZodCIDRv6 extends ZodStringFormat<"cidrv6"> { + _zod: core.$ZodCIDRv6Internals; +} +export const ZodCIDRv6: core.$constructor = /*@__PURE__*/ core.$constructor("ZodCIDRv6", (inst, def) => { + core.$ZodCIDRv6.init(inst, def); + ZodStringFormat.init(inst, def); +}); + +export function cidrv6(params?: string | core.$ZodCIDRv6Params): ZodCIDRv6 { + return core._cidrv6(ZodCIDRv6, params); +} + +// ZodBase64 +export interface ZodBase64 extends ZodStringFormat<"base64"> { + _zod: core.$ZodBase64Internals; +} +export const ZodBase64: core.$constructor = /*@__PURE__*/ core.$constructor("ZodBase64", (inst, def) => { + // ZodStringFormat.init(inst, def); + core.$ZodBase64.init(inst, def); + ZodStringFormat.init(inst, def); +}); +export function base64(params?: string | core.$ZodBase64Params): ZodBase64 { + return core._base64(ZodBase64, params); +} + +// ZodBase64URL +export interface ZodBase64URL extends ZodStringFormat<"base64url"> { + _zod: core.$ZodBase64URLInternals; +} +export const ZodBase64URL: core.$constructor = /*@__PURE__*/ core.$constructor( + "ZodBase64URL", + (inst, def) => { + // ZodStringFormat.init(inst, def); + core.$ZodBase64URL.init(inst, def); + ZodStringFormat.init(inst, def); + } +); +export function base64url(params?: string | core.$ZodBase64URLParams): ZodBase64URL { + return core._base64url(ZodBase64URL, params); +} + +// ZodE164 +export interface ZodE164 extends ZodStringFormat<"e164"> { + _zod: core.$ZodE164Internals; +} +export const ZodE164: core.$constructor = /*@__PURE__*/ core.$constructor("ZodE164", (inst, def) => { + // ZodStringFormat.init(inst, def); + core.$ZodE164.init(inst, def); + ZodStringFormat.init(inst, def); +}); + +export function e164(params?: string | core.$ZodE164Params): ZodE164 { + return core._e164(ZodE164, params); +} + +// ZodJWT +export interface ZodJWT extends ZodStringFormat<"jwt"> { + _zod: core.$ZodJWTInternals; +} +export const ZodJWT: core.$constructor = /*@__PURE__*/ core.$constructor("ZodJWT", (inst, def) => { + // ZodStringFormat.init(inst, def); + core.$ZodJWT.init(inst, def); + ZodStringFormat.init(inst, def); +}); + +export function jwt(params?: string | core.$ZodJWTParams): ZodJWT { + return core._jwt(ZodJWT, params); +} + +// ZodCustomStringFormat +export interface ZodCustomStringFormat + extends ZodStringFormat, + core.$ZodCustomStringFormat { + _zod: core.$ZodCustomStringFormatInternals; +} +export const ZodCustomStringFormat: core.$constructor = /*@__PURE__*/ core.$constructor( + "ZodCustomStringFormat", + (inst, def) => { + // ZodStringFormat.init(inst, def); + core.$ZodCustomStringFormat.init(inst, def); + ZodStringFormat.init(inst, def); + } +); +export function stringFormat( + format: Format, + fnOrRegex: ((arg: string) => util.MaybeAsync) | RegExp, + _params: string | core.$ZodStringFormatParams = {} +): ZodCustomStringFormat { + return core._stringFormat(ZodCustomStringFormat, format, fnOrRegex, _params) as any; +} + +export function hostname(_params?: string | core.$ZodStringFormatParams): ZodCustomStringFormat<"hostname"> { + return core._stringFormat(ZodCustomStringFormat, "hostname", core.regexes.hostname, _params) as any; +} + +// ZodNumber +export interface _ZodNumber + extends _ZodType { + gt(value: number, params?: string | core.$ZodCheckGreaterThanParams): this; + /** Identical to .min() */ + gte(value: number, params?: string | core.$ZodCheckGreaterThanParams): this; + min(value: number, params?: string | core.$ZodCheckGreaterThanParams): this; + lt(value: number, params?: string | core.$ZodCheckLessThanParams): this; + /** Identical to .max() */ + lte(value: number, params?: string | core.$ZodCheckLessThanParams): this; + max(value: number, params?: string | core.$ZodCheckLessThanParams): this; + /** Consider `z.int()` instead. This API is considered *legacy*; it will never be removed but a better alternative exists. */ + int(params?: string | core.$ZodCheckNumberFormatParams): this; + /** @deprecated This is now identical to `.int()`. Only numbers in the safe integer range are accepted. */ + safe(params?: string | core.$ZodCheckNumberFormatParams): this; + positive(params?: string | core.$ZodCheckGreaterThanParams): this; + nonnegative(params?: string | core.$ZodCheckGreaterThanParams): this; + negative(params?: string | core.$ZodCheckLessThanParams): this; + nonpositive(params?: string | core.$ZodCheckLessThanParams): this; + multipleOf(value: number, params?: string | core.$ZodCheckMultipleOfParams): this; + /** @deprecated Use `.multipleOf()` instead. */ + step(value: number, params?: string | core.$ZodCheckMultipleOfParams): this; + + /** @deprecated In v4 and later, z.number() does not allow infinite values by default. This is a no-op. */ + finite(params?: unknown): this; + + minValue: number | null; + maxValue: number | null; + /** @deprecated Check the `format` property instead. */ + isInt: boolean; + /** @deprecated Number schemas no longer accept infinite values, so this always returns `true`. */ + isFinite: boolean; + format: string | null; +} + +export interface ZodNumber extends _ZodNumber> {} + +export const ZodNumber: core.$constructor = /*@__PURE__*/ core.$constructor("ZodNumber", (inst, def) => { + core.$ZodNumber.init(inst, def); + ZodType.init(inst, def); + + inst.gt = (value, params) => inst.check(checks.gt(value, params)); + inst.gte = (value, params) => inst.check(checks.gte(value, params)); + inst.min = (value, params) => inst.check(checks.gte(value, params)); + inst.lt = (value, params) => inst.check(checks.lt(value, params)); + inst.lte = (value, params) => inst.check(checks.lte(value, params)); + inst.max = (value, params) => inst.check(checks.lte(value, params)); + inst.int = (params) => inst.check(int(params)); + inst.safe = (params) => inst.check(int(params)); + inst.positive = (params) => inst.check(checks.gt(0, params)); + inst.nonnegative = (params) => inst.check(checks.gte(0, params)); + inst.negative = (params) => inst.check(checks.lt(0, params)); + inst.nonpositive = (params) => inst.check(checks.lte(0, params)); + inst.multipleOf = (value, params) => inst.check(checks.multipleOf(value, params)); + inst.step = (value, params) => inst.check(checks.multipleOf(value, params)); + + // inst.finite = (params) => inst.check(core.finite(params)); + inst.finite = () => inst; + + const bag = inst._zod.bag; + inst.minValue = + Math.max(bag.minimum ?? Number.NEGATIVE_INFINITY, bag.exclusiveMinimum ?? Number.NEGATIVE_INFINITY) ?? null; + inst.maxValue = + Math.min(bag.maximum ?? Number.POSITIVE_INFINITY, bag.exclusiveMaximum ?? Number.POSITIVE_INFINITY) ?? null; + inst.isInt = (bag.format ?? "").includes("int") || Number.isSafeInteger(bag.multipleOf ?? 0.5); + inst.isFinite = true; + inst.format = bag.format ?? null; +}); + +export function number(params?: string | core.$ZodNumberParams): ZodNumber { + return core._number(ZodNumber, params) as any; +} + +// ZodNumberFormat +export interface ZodNumberFormat extends ZodNumber { + _zod: core.$ZodNumberFormatInternals; +} +export const ZodNumberFormat: core.$constructor = /*@__PURE__*/ core.$constructor( + "ZodNumberFormat", + (inst, def) => { + core.$ZodNumberFormat.init(inst, def); + ZodNumber.init(inst, def); + } +); + +// int +export interface ZodInt extends ZodNumberFormat {} +export function int(params?: string | core.$ZodCheckNumberFormatParams): ZodInt { + return core._int(ZodNumberFormat, params); +} + +// float32 +export interface ZodFloat32 extends ZodNumberFormat {} +export function float32(params?: string | core.$ZodCheckNumberFormatParams): ZodFloat32 { + return core._float32(ZodNumberFormat, params); +} + +// float64 +export interface ZodFloat64 extends ZodNumberFormat {} +export function float64(params?: string | core.$ZodCheckNumberFormatParams): ZodFloat64 { + return core._float64(ZodNumberFormat, params); +} + +// int32 +export interface ZodInt32 extends ZodNumberFormat {} +export function int32(params?: string | core.$ZodCheckNumberFormatParams): ZodInt32 { + return core._int32(ZodNumberFormat, params); +} + +// uint32 +export interface ZodUInt32 extends ZodNumberFormat {} +export function uint32(params?: string | core.$ZodCheckNumberFormatParams): ZodUInt32 { + return core._uint32(ZodNumberFormat, params); +} + +// boolean +export interface _ZodBoolean extends _ZodType {} +export interface ZodBoolean extends _ZodBoolean> {} +export const ZodBoolean: core.$constructor = /*@__PURE__*/ core.$constructor("ZodBoolean", (inst, def) => { + core.$ZodBoolean.init(inst, def); + ZodType.init(inst, def); +}); + +export function boolean(params?: string | core.$ZodBooleanParams): ZodBoolean { + return core._boolean(ZodBoolean, params) as any; +} + +// bigint +export interface _ZodBigInt extends _ZodType { + gte(value: bigint, params?: string | core.$ZodCheckGreaterThanParams): this; + /** Alias of `.gte()` */ + min(value: bigint, params?: string | core.$ZodCheckGreaterThanParams): this; + gt(value: bigint, params?: string | core.$ZodCheckGreaterThanParams): this; + /** Alias of `.lte()` */ + lte(value: bigint, params?: string | core.$ZodCheckLessThanParams): this; + max(value: bigint, params?: string | core.$ZodCheckLessThanParams): this; + lt(value: bigint, params?: string | core.$ZodCheckLessThanParams): this; + positive(params?: string | core.$ZodCheckGreaterThanParams): this; + negative(params?: string | core.$ZodCheckLessThanParams): this; + nonpositive(params?: string | core.$ZodCheckLessThanParams): this; + nonnegative(params?: string | core.$ZodCheckGreaterThanParams): this; + multipleOf(value: bigint, params?: string | core.$ZodCheckMultipleOfParams): this; + + minValue: bigint | null; + maxValue: bigint | null; + format: string | null; +} + +export interface ZodBigInt extends _ZodBigInt> {} +export const ZodBigInt: core.$constructor = /*@__PURE__*/ core.$constructor("ZodBigInt", (inst, def) => { + core.$ZodBigInt.init(inst, def); + ZodType.init(inst, def); + + inst.gte = (value, params) => inst.check(checks.gte(value, params)); + inst.min = (value, params) => inst.check(checks.gte(value, params)); + inst.gt = (value, params) => inst.check(checks.gt(value, params)); + inst.gte = (value, params) => inst.check(checks.gte(value, params)); + inst.min = (value, params) => inst.check(checks.gte(value, params)); + inst.lt = (value, params) => inst.check(checks.lt(value, params)); + inst.lte = (value, params) => inst.check(checks.lte(value, params)); + inst.max = (value, params) => inst.check(checks.lte(value, params)); + inst.positive = (params) => inst.check(checks.gt(BigInt(0), params)); + inst.negative = (params) => inst.check(checks.lt(BigInt(0), params)); + inst.nonpositive = (params) => inst.check(checks.lte(BigInt(0), params)); + inst.nonnegative = (params) => inst.check(checks.gte(BigInt(0), params)); + inst.multipleOf = (value, params) => inst.check(checks.multipleOf(value, params)); + + const bag = inst._zod.bag; + inst.minValue = bag.minimum ?? null; + inst.maxValue = bag.maximum ?? null; + inst.format = bag.format ?? null; +}); + +export function bigint(params?: string | core.$ZodBigIntParams): ZodBigInt { + return core._bigint(ZodBigInt, params) as any; +} +// bigint formats + +// ZodBigIntFormat +export interface ZodBigIntFormat extends ZodBigInt { + _zod: core.$ZodBigIntFormatInternals; +} +export const ZodBigIntFormat: core.$constructor = /*@__PURE__*/ core.$constructor( + "ZodBigIntFormat", + (inst, def) => { + core.$ZodBigIntFormat.init(inst, def); + ZodBigInt.init(inst, def); + } +); + +// int64 +export function int64(params?: string | core.$ZodBigIntFormatParams): ZodBigIntFormat { + return core._int64(ZodBigIntFormat, params); +} + +// uint64 +export function uint64(params?: string | core.$ZodBigIntFormatParams): ZodBigIntFormat { + return core._uint64(ZodBigIntFormat, params); +} + +// symbol +export interface ZodSymbol extends _ZodType {} +export const ZodSymbol: core.$constructor = /*@__PURE__*/ core.$constructor("ZodSymbol", (inst, def) => { + core.$ZodSymbol.init(inst, def); + ZodType.init(inst, def); +}); + +export function symbol(params?: string | core.$ZodSymbolParams): ZodSymbol { + return core._symbol(ZodSymbol, params); +} + +// ZodUndefined +export interface ZodUndefined extends _ZodType {} +export const ZodUndefined: core.$constructor = /*@__PURE__*/ core.$constructor( + "ZodUndefined", + (inst, def) => { + core.$ZodUndefined.init(inst, def); + ZodType.init(inst, def); + } +); + +function _undefined(params?: string | core.$ZodUndefinedParams): ZodUndefined { + return core._undefined(ZodUndefined, params); +} +export { _undefined as undefined }; + +// ZodNull +export interface ZodNull extends _ZodType {} +export const ZodNull: core.$constructor = /*@__PURE__*/ core.$constructor("ZodNull", (inst, def) => { + core.$ZodNull.init(inst, def); + ZodType.init(inst, def); +}); + +function _null(params?: string | core.$ZodNullParams): ZodNull { + return core._null(ZodNull, params); +} +export { _null as null }; + +// ZodAny +export interface ZodAny extends _ZodType {} +export const ZodAny: core.$constructor = /*@__PURE__*/ core.$constructor("ZodAny", (inst, def) => { + core.$ZodAny.init(inst, def); + ZodType.init(inst, def); +}); + +export function any(): ZodAny { + return core._any(ZodAny); +} + +// ZodUnknown +export interface ZodUnknown extends _ZodType {} +export const ZodUnknown: core.$constructor = /*@__PURE__*/ core.$constructor("ZodUnknown", (inst, def) => { + core.$ZodUnknown.init(inst, def); + ZodType.init(inst, def); +}); + +export function unknown(): ZodUnknown { + return core._unknown(ZodUnknown); +} + +// ZodNever +export interface ZodNever extends _ZodType {} +export const ZodNever: core.$constructor = /*@__PURE__*/ core.$constructor("ZodNever", (inst, def) => { + core.$ZodNever.init(inst, def); + ZodType.init(inst, def); +}); + +export function never(params?: string | core.$ZodNeverParams): ZodNever { + return core._never(ZodNever, params); +} + +// ZodVoid +export interface ZodVoid extends _ZodType {} +export const ZodVoid: core.$constructor = /*@__PURE__*/ core.$constructor("ZodVoid", (inst, def) => { + core.$ZodVoid.init(inst, def); + ZodType.init(inst, def); +}); + +function _void(params?: string | core.$ZodVoidParams): ZodVoid { + return core._void(ZodVoid, params); +} +export { _void as void }; + +// ZodDate +export interface _ZodDate extends _ZodType { + min(value: number | Date, params?: string | core.$ZodCheckGreaterThanParams): this; + max(value: number | Date, params?: string | core.$ZodCheckLessThanParams): this; + + /** @deprecated Not recommended. */ + minDate: Date | null; + /** @deprecated Not recommended. */ + maxDate: Date | null; +} + +export interface ZodDate extends _ZodDate> {} +export const ZodDate: core.$constructor = /*@__PURE__*/ core.$constructor("ZodDate", (inst, def) => { + core.$ZodDate.init(inst, def); + ZodType.init(inst, def); + + inst.min = (value, params) => inst.check(checks.gte(value, params)); + inst.max = (value, params) => inst.check(checks.lte(value, params)); + + const c = inst._zod.bag; + inst.minDate = c.minimum ? new Date(c.minimum) : null; + inst.maxDate = c.maximum ? new Date(c.maximum) : null; +}); + +export function date(params?: string | core.$ZodDateParams): ZodDate { + return core._date(ZodDate, params); +} + +// ZodArray +export interface ZodArray + extends _ZodType>, + core.$ZodArray { + element: T; + min(minLength: number, params?: string | core.$ZodCheckMinLengthParams): this; + nonempty(params?: string | core.$ZodCheckMinLengthParams): this; + max(maxLength: number, params?: string | core.$ZodCheckMaxLengthParams): this; + length(len: number, params?: string | core.$ZodCheckLengthEqualsParams): this; + + unwrap(): T; +} +export const ZodArray: core.$constructor = /*@__PURE__*/ core.$constructor("ZodArray", (inst, def) => { + core.$ZodArray.init(inst, def); + ZodType.init(inst, def); + + inst.element = def.element as any; + inst.min = (minLength, params) => inst.check(checks.minLength(minLength, params)); + inst.nonempty = (params) => inst.check(checks.minLength(1, params)); + inst.max = (maxLength, params) => inst.check(checks.maxLength(maxLength, params)); + inst.length = (len, params) => inst.check(checks.length(len, params)); + + inst.unwrap = () => inst.element; +}); + +export function array(element: T, params?: string | core.$ZodArrayParams): ZodArray { + return core._array(ZodArray, element as any, params) as any; +} + +// .keyof +export function keyof(schema: T): ZodLiteral> { + const shape = schema._zod.def.shape; + return literal(Object.keys(shape)) as any; +} + +// ZodObject + +export interface ZodObject< + /** @ts-ignore Cast variance */ + out Shape extends core.$ZodShape = core.$ZodLooseShape, + out Config extends core.$ZodObjectConfig = core.$strip, +> extends _ZodType>, + core.$ZodObject { + shape: Shape; + + keyof(): ZodEnum>; + /** Define a schema to validate all unrecognized keys. This overrides the existing strict/loose behavior. */ + catchall(schema: T): ZodObject>; + + /** @deprecated Use `z.looseObject()` or `.loose()` instead. */ + passthrough(): ZodObject; + /** Consider `z.looseObject(A.shape)` instead */ + loose(): ZodObject; + + /** Consider `z.strictObject(A.shape)` instead */ + strict(): ZodObject; + + /** This is the default behavior. This method call is likely unnecessary. */ + strip(): ZodObject; + + extend(shape: U): ZodObject, Config>; + + /** + * @deprecated Use [`A.extend(B.shape)`](https://zod.dev/api?id=extend) instead. + */ + merge(other: U): ZodObject, U["_zod"]["config"]>; + + pick>( + mask: M + ): ZodObject>>, Config>; + + omit>( + mask: M + ): ZodObject>>, Config>; + + partial(): ZodObject< + { + [k in keyof Shape]: ZodOptional; + }, + Config + >; + partial>( + mask: M + ): ZodObject< + { + [k in keyof Shape]: k extends keyof M + ? // Shape[k] extends OptionalInSchema + // ? Shape[k] + // : + ZodOptional + : Shape[k]; + }, + Config + >; + + // required + required(): ZodObject< + { + [k in keyof Shape]: ZodNonOptional; + }, + Config + >; + required>( + mask: M + ): ZodObject< + { + [k in keyof Shape]: k extends keyof M ? ZodNonOptional : Shape[k]; + }, + Config + >; +} + +export const ZodObject: core.$constructor = /*@__PURE__*/ core.$constructor("ZodObject", (inst, def) => { + core.$ZodObject.init(inst, def); + ZodType.init(inst, def); + + util.defineLazy(inst, "shape", () => def.shape); + inst.keyof = () => _enum(Object.keys(inst._zod.def.shape)) as any; + inst.catchall = (catchall) => inst.clone({ ...inst._zod.def, catchall: catchall as any as core.$ZodType }) as any; + inst.passthrough = () => inst.clone({ ...inst._zod.def, catchall: unknown() }); + inst.loose = () => inst.clone({ ...inst._zod.def, catchall: unknown() }); + inst.strict = () => inst.clone({ ...inst._zod.def, catchall: never() }); + inst.strip = () => inst.clone({ ...inst._zod.def, catchall: undefined }); + + inst.extend = (incoming: any) => { + return util.extend(inst, incoming); + }; + inst.merge = (other) => util.merge(inst, other); + inst.pick = (mask) => util.pick(inst, mask); + inst.omit = (mask) => util.omit(inst, mask); + inst.partial = (...args: any[]) => util.partial(ZodOptional, inst, args[0] as object); + inst.required = (...args: any[]) => util.required(ZodNonOptional, inst, args[0] as object); +}); + +export function object>>( + shape?: T, + params?: string | core.$ZodObjectParams +): ZodObject, core.$strip> { + const def: core.$ZodObjectDef = { + type: "object", + get shape() { + util.assignProp(this, "shape", { ...shape }); + return this.shape; + }, + ...util.normalizeParams(params), + }; + return new ZodObject(def) as any; +} + +// strictObject + +export function strictObject( + shape: T, + params?: string | core.$ZodObjectParams +): ZodObject { + return new ZodObject({ + type: "object", + get shape() { + util.assignProp(this, "shape", { ...shape }); + return this.shape; + }, + catchall: never(), + ...util.normalizeParams(params), + }) as any; +} + +// looseObject + +export function looseObject( + shape: T, + params?: string | core.$ZodObjectParams +): ZodObject { + return new ZodObject({ + type: "object", + get shape() { + util.assignProp(this, "shape", { ...shape }); + return this.shape; + }, + catchall: unknown(), + ...util.normalizeParams(params), + }) as any; +} + +// ZodUnion +export interface ZodUnion + extends _ZodType>, + core.$ZodUnion { + options: T; +} +export const ZodUnion: core.$constructor = /*@__PURE__*/ core.$constructor("ZodUnion", (inst, def) => { + core.$ZodUnion.init(inst, def); + ZodType.init(inst, def); + inst.options = def.options; +}); + +export function union( + options: T, + params?: string | core.$ZodUnionParams +): ZodUnion { + return new ZodUnion({ + type: "union", + options: options as any as core.$ZodType[], + ...util.normalizeParams(params), + }) as any; +} + +// ZodDiscriminatedUnion +export interface ZodDiscriminatedUnion + extends ZodUnion, + core.$ZodDiscriminatedUnion { + _zod: core.$ZodDiscriminatedUnionInternals; + def: core.$ZodDiscriminatedUnionDef; +} +export const ZodDiscriminatedUnion: core.$constructor = /*@__PURE__*/ core.$constructor( + "ZodDiscriminatedUnion", + (inst, def) => { + ZodUnion.init(inst, def); + core.$ZodDiscriminatedUnion.init(inst, def); + } +); + +export function discriminatedUnion< + Types extends readonly [core.$ZodTypeDiscriminable, ...core.$ZodTypeDiscriminable[]], +>( + discriminator: string, + options: Types, + params?: string | core.$ZodDiscriminatedUnionParams +): ZodDiscriminatedUnion { + // const [options, params] = args; + return new ZodDiscriminatedUnion({ + type: "union", + options, + discriminator, + ...util.normalizeParams(params), + }) as any; +} + +// ZodIntersection +export interface ZodIntersection + extends _ZodType>, + core.$ZodIntersection {} +export const ZodIntersection: core.$constructor = /*@__PURE__*/ core.$constructor( + "ZodIntersection", + (inst, def) => { + core.$ZodIntersection.init(inst, def); + ZodType.init(inst, def); + } +); + +export function intersection( + left: T, + right: U +): ZodIntersection { + return new ZodIntersection({ + type: "intersection", + left: left as any as core.$ZodType, + right: right as any as core.$ZodType, + }) as any; +} + +// ZodTuple +export interface ZodTuple< + T extends util.TupleItems = readonly core.$ZodType[], + Rest extends core.SomeType | null = core.$ZodType | null, +> extends _ZodType>, + core.$ZodTuple { + rest(rest: Rest): ZodTuple; +} +export const ZodTuple: core.$constructor = /*@__PURE__*/ core.$constructor("ZodTuple", (inst, def) => { + core.$ZodTuple.init(inst, def); + ZodType.init(inst, def); + inst.rest = (rest) => + inst.clone({ + ...inst._zod.def, + rest: rest as any as core.$ZodType, + }) as any; +}); + +export function tuple( + items: T, + params?: string | core.$ZodTupleParams +): ZodTuple; +export function tuple( + items: T, + rest: Rest, + params?: string | core.$ZodTupleParams +): ZodTuple; +export function tuple(items: [], params?: string | core.$ZodTupleParams): ZodTuple<[], null>; +export function tuple( + items: core.SomeType[], + _paramsOrRest?: string | core.$ZodTupleParams | core.SomeType, + _params?: string | core.$ZodTupleParams +) { + const hasRest = _paramsOrRest instanceof core.$ZodType; + const params = hasRest ? _params : _paramsOrRest; + const rest = hasRest ? _paramsOrRest : null; + return new ZodTuple({ + type: "tuple", + items: items as any as core.$ZodType[], + rest, + ...util.normalizeParams(params), + }); +} + +// ZodRecord +export interface ZodRecord< + Key extends core.$ZodRecordKey = core.$ZodRecordKey, + Value extends core.SomeType = core.$ZodType, +> extends _ZodType>, + core.$ZodRecord { + keyType: Key; + valueType: Value; +} +export const ZodRecord: core.$constructor = /*@__PURE__*/ core.$constructor("ZodRecord", (inst, def) => { + core.$ZodRecord.init(inst, def); + ZodType.init(inst, def); + + inst.keyType = def.keyType; + inst.valueType = def.valueType; +}); + +export function record( + keyType: Key, + valueType: Value, + params?: string | core.$ZodRecordParams +): ZodRecord { + return new ZodRecord({ + type: "record", + keyType, + valueType: valueType as any as core.$ZodType, + ...util.normalizeParams(params), + }) as any; +} +// type alksjf = core.output; +export function partialRecord( + keyType: Key, + valueType: Value, + params?: string | core.$ZodRecordParams +): ZodRecord { + const k = core.clone(keyType); + k._zod.values = undefined; + return new ZodRecord({ + type: "record", + keyType: k, + valueType: valueType as any, + ...util.normalizeParams(params), + }) as any; +} + +// ZodMap +export interface ZodMap + extends _ZodType>, + core.$ZodMap { + keyType: Key; + valueType: Value; +} +export const ZodMap: core.$constructor = /*@__PURE__*/ core.$constructor("ZodMap", (inst, def) => { + core.$ZodMap.init(inst, def); + ZodType.init(inst, def); + inst.keyType = def.keyType; + inst.valueType = def.valueType; +}); + +export function map( + keyType: Key, + valueType: Value, + params?: string | core.$ZodMapParams +): ZodMap { + return new ZodMap({ + type: "map", + keyType: keyType as any as core.$ZodType, + valueType: valueType as any as core.$ZodType, + ...util.normalizeParams(params), + }) as any; +} + +// ZodSet +export interface ZodSet + extends _ZodType>, + core.$ZodSet { + min(minSize: number, params?: string | core.$ZodCheckMinSizeParams): this; + /** */ + nonempty(params?: string | core.$ZodCheckMinSizeParams): this; + max(maxSize: number, params?: string | core.$ZodCheckMaxSizeParams): this; + size(size: number, params?: string | core.$ZodCheckSizeEqualsParams): this; +} +export const ZodSet: core.$constructor = /*@__PURE__*/ core.$constructor("ZodSet", (inst, def) => { + core.$ZodSet.init(inst, def); + ZodType.init(inst, def); + + inst.min = (...args) => inst.check(core._minSize(...args)); + inst.nonempty = (params) => inst.check(core._minSize(1, params)); + inst.max = (...args) => inst.check(core._maxSize(...args)); + inst.size = (...args) => inst.check(core._size(...args)); +}); + +export function set( + valueType: Value, + params?: string | core.$ZodSetParams +): ZodSet { + return new ZodSet({ + type: "set", + valueType: valueType as any as core.$ZodType, + ...util.normalizeParams(params), + }) as any; +} + +// ZodEnum +export interface ZodEnum< + /** @ts-ignore Cast variance */ + out T extends util.EnumLike = util.EnumLike, +> extends _ZodType>, + core.$ZodEnum { + enum: T; + options: Array; + + extract( + values: U, + params?: string | core.$ZodEnumParams + ): ZodEnum>>; + exclude( + values: U, + params?: string | core.$ZodEnumParams + ): ZodEnum>>; +} +export const ZodEnum: core.$constructor = /*@__PURE__*/ core.$constructor("ZodEnum", (inst, def) => { + core.$ZodEnum.init(inst, def); + ZodType.init(inst, def); + + inst.enum = def.entries; + inst.options = Object.values(def.entries); + + const keys = new Set(Object.keys(def.entries)); + + inst.extract = (values, params) => { + const newEntries: Record = {}; + for (const value of values) { + if (keys.has(value)) { + newEntries[value] = def.entries[value]; + } else throw new Error(`Key ${value} not found in enum`); + } + return new ZodEnum({ + ...def, + checks: [], + ...util.normalizeParams(params), + entries: newEntries, + }) as any; + }; + + inst.exclude = (values, params) => { + const newEntries: Record = { ...def.entries }; + for (const value of values) { + if (keys.has(value)) { + delete newEntries[value]; + } else throw new Error(`Key ${value} not found in enum`); + } + return new ZodEnum({ + ...def, + checks: [], + ...util.normalizeParams(params), + entries: newEntries, + }) as any; + }; +}); + +function _enum( + values: T, + params?: string | core.$ZodEnumParams +): ZodEnum>; +function _enum(entries: T, params?: string | core.$ZodEnumParams): ZodEnum; +function _enum(values: any, params?: string | core.$ZodEnumParams) { + const entries: any = Array.isArray(values) ? Object.fromEntries(values.map((v) => [v, v])) : values; + + return new ZodEnum({ + type: "enum", + entries, + ...util.normalizeParams(params), + }) as any; +} +export { _enum as enum }; + +/** @deprecated This API has been merged into `z.enum()`. Use `z.enum()` instead. + * + * ```ts + * enum Colors { red, green, blue } + * z.enum(Colors); + * ``` + */ +export function nativeEnum(entries: T, params?: string | core.$ZodEnumParams): ZodEnum { + return new ZodEnum({ + type: "enum", + entries, + ...util.normalizeParams(params), + }) as any as ZodEnum; +} + +// ZodLiteral +export interface ZodLiteral + extends _ZodType>, + core.$ZodLiteral { + values: Set; + /** @legacy Use `.values` instead. Accessing this property will throw an error if the literal accepts multiple values. */ + value: T; +} +export const ZodLiteral: core.$constructor = /*@__PURE__*/ core.$constructor("ZodLiteral", (inst, def) => { + core.$ZodLiteral.init(inst, def); + ZodType.init(inst, def); + inst.values = new Set(def.values); + Object.defineProperty(inst, "value", { + get() { + if (def.values.length > 1) { + throw new Error("This schema contains multiple valid literal values. Use `.values` instead."); + } + return def.values[0]; + }, + }); +}); + +export function literal>( + value: T, + params?: string | core.$ZodLiteralParams +): ZodLiteral; +export function literal( + value: T, + params?: string | core.$ZodLiteralParams +): ZodLiteral; +export function literal(value: any, params: any) { + return new ZodLiteral({ + type: "literal", + values: Array.isArray(value) ? value : [value], + ...util.normalizeParams(params), + }); +} + +// ZodFile +export interface ZodFile extends _ZodType, core.$ZodFile { + min(size: number, params?: string | core.$ZodCheckMinSizeParams): this; + max(size: number, params?: string | core.$ZodCheckMaxSizeParams): this; + mime(types: util.MimeTypes | Array, params?: string | core.$ZodCheckMimeTypeParams): this; +} +export const ZodFile: core.$constructor = /*@__PURE__*/ core.$constructor("ZodFile", (inst, def) => { + core.$ZodFile.init(inst, def); + ZodType.init(inst, def); + + inst.min = (size, params) => inst.check(core._minSize(size, params)); + inst.max = (size, params) => inst.check(core._maxSize(size, params)); + inst.mime = (types, params) => inst.check(core._mime(Array.isArray(types) ? types : [types], params)); +}); + +export function file(params?: string | core.$ZodFileParams): ZodFile { + return core._file(ZodFile, params) as any; +} + +// ZodTransform +export interface ZodTransform + extends _ZodType>, + core.$ZodTransform {} +export const ZodTransform: core.$constructor = /*@__PURE__*/ core.$constructor( + "ZodTransform", + (inst, def) => { + core.$ZodTransform.init(inst, def); + ZodType.init(inst, def); + + inst._zod.parse = (payload, _ctx) => { + (payload as core.$RefinementCtx).addIssue = (issue) => { + if (typeof issue === "string") { + payload.issues.push(util.issue(issue, payload.value, def)); + } else { + // for Zod 3 backwards compatibility + const _issue = issue as any; + + if (_issue.fatal) _issue.continue = false; + _issue.code ??= "custom"; + _issue.input ??= payload.value; + _issue.inst ??= inst; + // _issue.continue ??= true; + payload.issues.push(util.issue(_issue)); + } + }; + + const output = def.transform(payload.value, payload); + if (output instanceof Promise) { + return output.then((output) => { + payload.value = output; + return payload; + }); + } + payload.value = output; + return payload; + }; + } +); + +export function transform( + fn: (input: I, ctx: core.ParsePayload) => O +): ZodTransform, I> { + return new ZodTransform({ + type: "transform", + transform: fn as any, + }) as any; +} + +// ZodOptional +export interface ZodOptional + extends _ZodType>, + core.$ZodOptional { + unwrap(): T; +} +export const ZodOptional: core.$constructor = /*@__PURE__*/ core.$constructor( + "ZodOptional", + (inst, def) => { + core.$ZodOptional.init(inst, def); + ZodType.init(inst, def); + + inst.unwrap = () => inst._zod.def.innerType; + } +); + +export function optional(innerType: T): ZodOptional { + return new ZodOptional({ + type: "optional", + innerType: innerType as any as core.$ZodType, + }) as any; +} + +// ZodNullable +export interface ZodNullable + extends _ZodType>, + core.$ZodNullable { + unwrap(): T; +} +export const ZodNullable: core.$constructor = /*@__PURE__*/ core.$constructor( + "ZodNullable", + (inst, def) => { + core.$ZodNullable.init(inst, def); + ZodType.init(inst, def); + + inst.unwrap = () => inst._zod.def.innerType; + } +); + +export function nullable(innerType: T): ZodNullable { + return new ZodNullable({ + type: "nullable", + innerType: innerType as any as core.$ZodType, + }) as any; +} + +// nullish +export function nullish(innerType: T): ZodOptional> { + return optional(nullable(innerType)); +} + +// ZodDefault +export interface ZodDefault + extends _ZodType>, + core.$ZodDefault { + unwrap(): T; + /** @deprecated Use `.unwrap()` instead. */ + removeDefault(): T; +} +export const ZodDefault: core.$constructor = /*@__PURE__*/ core.$constructor("ZodDefault", (inst, def) => { + core.$ZodDefault.init(inst, def); + ZodType.init(inst, def); + + inst.unwrap = () => inst._zod.def.innerType; + inst.removeDefault = inst.unwrap; +}); + +export function _default( + innerType: T, + defaultValue: util.NoUndefined> | (() => util.NoUndefined>) +): ZodDefault { + return new ZodDefault({ + type: "default", + innerType: innerType as any as core.$ZodType, + get defaultValue() { + return typeof defaultValue === "function" ? (defaultValue as Function)() : defaultValue; + }, + }) as any; +} + +// ZodPrefault +export interface ZodPrefault + extends _ZodType>, + core.$ZodPrefault { + unwrap(): T; +} +export const ZodPrefault: core.$constructor = /*@__PURE__*/ core.$constructor( + "ZodPrefault", + (inst, def) => { + core.$ZodPrefault.init(inst, def); + ZodType.init(inst, def); + inst.unwrap = () => inst._zod.def.innerType; + } +); + +export function prefault( + innerType: T, + defaultValue: core.input | (() => core.input) +): ZodPrefault { + return new ZodPrefault({ + type: "prefault", + innerType: innerType as any as core.$ZodType, + get defaultValue() { + return typeof defaultValue === "function" ? (defaultValue as Function)() : defaultValue; + }, + }) as any; +} + +// ZodNonOptional +export interface ZodNonOptional + extends _ZodType>, + core.$ZodNonOptional { + unwrap(): T; +} +export const ZodNonOptional: core.$constructor = /*@__PURE__*/ core.$constructor( + "ZodNonOptional", + (inst, def) => { + core.$ZodNonOptional.init(inst, def); + ZodType.init(inst, def); + + inst.unwrap = () => inst._zod.def.innerType; + } +); + +export function nonoptional( + innerType: T, + params?: string | core.$ZodNonOptionalParams +): ZodNonOptional { + return new ZodNonOptional({ + type: "nonoptional", + innerType: innerType as any as core.$ZodType, + ...util.normalizeParams(params), + }) as any; +} + +// ZodSuccess +export interface ZodSuccess + extends _ZodType>, + core.$ZodSuccess { + unwrap(): T; +} +export const ZodSuccess: core.$constructor = /*@__PURE__*/ core.$constructor("ZodSuccess", (inst, def) => { + core.$ZodSuccess.init(inst, def); + ZodType.init(inst, def); + + inst.unwrap = () => inst._zod.def.innerType; +}); + +export function success(innerType: T): ZodSuccess { + return new ZodSuccess({ + type: "success", + innerType: innerType as any as core.$ZodType, + }) as any; +} + +// ZodCatch +export interface ZodCatch + extends _ZodType>, + core.$ZodCatch { + unwrap(): T; + /** @deprecated Use `.unwrap()` instead. */ + removeCatch(): T; +} +export const ZodCatch: core.$constructor = /*@__PURE__*/ core.$constructor("ZodCatch", (inst, def) => { + core.$ZodCatch.init(inst, def); + ZodType.init(inst, def); + + inst.unwrap = () => inst._zod.def.innerType; + inst.removeCatch = inst.unwrap; +}); + +function _catch( + innerType: T, + catchValue: core.output | ((ctx: core.$ZodCatchCtx) => core.output) +): ZodCatch { + return new ZodCatch({ + type: "catch", + innerType: innerType as any as core.$ZodType, + catchValue: (typeof catchValue === "function" ? catchValue : () => catchValue) as ( + ctx: core.$ZodCatchCtx + ) => core.output, + }) as any; +} +export { _catch as catch }; + +// ZodNaN +export interface ZodNaN extends _ZodType, core.$ZodNaN {} +export const ZodNaN: core.$constructor = /*@__PURE__*/ core.$constructor("ZodNaN", (inst, def) => { + core.$ZodNaN.init(inst, def); + ZodType.init(inst, def); +}); + +export function nan(params?: string | core.$ZodNaNParams): ZodNaN { + return core._nan(ZodNaN, params); +} + +// ZodPipe +export interface ZodPipe + extends _ZodType>, + core.$ZodPipe { + in: A; + out: B; +} +export const ZodPipe: core.$constructor = /*@__PURE__*/ core.$constructor("ZodPipe", (inst, def) => { + core.$ZodPipe.init(inst, def); + ZodType.init(inst, def); + + inst.in = def.in; + inst.out = def.out; +}); + +export function pipe< + const A extends core.SomeType, + B extends core.$ZodType> = core.$ZodType>, +>(in_: A, out: B | core.$ZodType>): ZodPipe; +export function pipe(in_: core.SomeType, out: core.SomeType) { + return new ZodPipe({ + type: "pipe", + in: in_ as unknown as core.$ZodType, + out: out as unknown as core.$ZodType, + // ...util.normalizeParams(params), + }); +} + +// ZodReadonly +export interface ZodReadonly + extends _ZodType>, + core.$ZodReadonly { + unwrap(): T; +} +export const ZodReadonly: core.$constructor = /*@__PURE__*/ core.$constructor( + "ZodReadonly", + (inst, def) => { + core.$ZodReadonly.init(inst, def); + ZodType.init(inst, def); + + inst.unwrap = () => inst._zod.def.innerType; + } +); + +export function readonly(innerType: T): ZodReadonly { + return new ZodReadonly({ + type: "readonly", + innerType: innerType as any as core.$ZodType, + }) as any; +} + +// ZodTemplateLiteral +export interface ZodTemplateLiteral