├── .changeset └── config.json ├── .gitattributes ├── .github ├── actions │ └── setup │ │ └── action.yaml └── workflows │ └── ci.yaml ├── .gitignore ├── .prettierrc.json ├── CNAME ├── LICENSE ├── README.md ├── _config.yml ├── _layouts └── default.html ├── assets └── logo.png ├── eslint.config.mjs ├── examples ├── bundlers │ ├── index.html │ ├── package.json │ ├── rollup.config.js │ ├── src │ │ └── main.ts │ ├── tsconfig.json │ └── webpack.config.js ├── commonjs │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── missing-adapter │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json └── next │ ├── next-env.d.ts │ ├── next.config.mjs │ ├── package.json │ ├── src │ └── app │ │ ├── layout.tsx │ │ └── page.tsx │ ├── tsconfig.json │ └── turbopack.sh ├── package.json ├── packages ├── all │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── arktype.test.ts │ │ │ ├── class-validator.test.ts │ │ │ ├── deepkit.test.ts │ │ │ ├── effect.test.ts │ │ │ ├── fastest-validator.test.ts │ │ │ ├── function.test.ts │ │ │ ├── io-ts.test.ts │ │ │ ├── joi.test.ts │ │ │ ├── json.test.ts │ │ │ ├── ow.test.ts │ │ │ ├── runtypes.test.ts │ │ │ ├── superstruct.test.ts │ │ │ ├── suretype.test.ts │ │ │ ├── tsconfig.json │ │ │ ├── typebox.test.ts │ │ │ ├── valibot.test.ts │ │ │ ├── valita.test.ts │ │ │ ├── vine.test.ts │ │ │ ├── yup.test.ts │ │ │ └── zod.test.ts │ │ ├── index.ts │ │ ├── resolver.ts │ │ ├── serialization.ts │ │ └── validation.ts │ └── tsconfig.json ├── arktype │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── arktype.test.ts │ │ │ ├── example.ts │ │ │ └── tsconfig.json │ │ ├── index.ts │ │ ├── resolver.ts │ │ └── validation.ts │ └── tsconfig.json ├── class-validator │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── class-validator.test.ts │ │ │ ├── example.ts │ │ │ └── tsconfig.json │ │ ├── index.ts │ │ ├── resolver.ts │ │ └── validation.ts │ └── tsconfig.json ├── core │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── resolver.ts │ │ ├── serialization.ts │ │ ├── utils.ts │ │ ├── validation.ts │ │ └── wrap.ts │ └── tsconfig.json ├── deepkit │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── deepkit.test.ts │ │ │ ├── example.ts │ │ │ └── tsconfig.json │ │ ├── index.ts │ │ ├── resolver.ts │ │ └── validation.ts │ └── tsconfig.json ├── effect │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── effect.test.ts │ │ │ ├── example.ts │ │ │ └── tsconfig.json │ │ ├── index.ts │ │ ├── resolver.ts │ │ ├── serialization.ts │ │ └── validation.ts │ └── tsconfig.json ├── fastest-validator │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── example.ts │ │ │ ├── fastest-validator.test.ts │ │ │ └── tsconfig.json │ │ ├── index.ts │ │ ├── resolver.ts │ │ └── validation.ts │ └── tsconfig.json ├── function │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── example.ts │ │ │ ├── function.test.ts │ │ │ └── tsconfig.json │ │ ├── index.ts │ │ ├── resolver.ts │ │ └── validation.ts │ └── tsconfig.json ├── io-ts │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── example.ts │ │ │ ├── io-ts.test.ts │ │ │ └── tsconfig.json │ │ ├── index.ts │ │ ├── resolver.ts │ │ └── validation.ts │ └── tsconfig.json ├── joi │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── example.ts │ │ │ ├── joi.test.ts │ │ │ └── tsconfig.json │ │ ├── index.ts │ │ ├── resolver.ts │ │ ├── serialization.ts │ │ └── validation.ts │ └── tsconfig.json ├── json │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── example.ts │ │ │ ├── json.test.ts │ │ │ └── tsconfig.json │ │ ├── index.ts │ │ ├── resolver.ts │ │ ├── serialization.ts │ │ └── validation.ts │ └── tsconfig.json ├── main │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── arktype.test.ts │ │ │ ├── class-validator.test.ts │ │ │ ├── deepkit.test.ts │ │ │ ├── effect.test.ts │ │ │ ├── fastest-validator.test.ts │ │ │ ├── function.test.ts │ │ │ ├── io-ts.test.ts │ │ │ ├── joi.test.ts │ │ │ ├── json.test.ts │ │ │ ├── ow.test.ts │ │ │ ├── runtypes.test.ts │ │ │ ├── superstruct.test.ts │ │ │ ├── suretype.test.ts │ │ │ ├── tsconfig.json │ │ │ ├── typebox.test.ts │ │ │ ├── valibot.test.ts │ │ │ ├── valita.test.ts │ │ │ ├── vine.test.ts │ │ │ ├── yup.test.ts │ │ │ └── zod.test.ts │ │ ├── adapters.ts │ │ ├── index.ts │ │ ├── resolver.ts │ │ ├── selector.ts │ │ ├── serialization.ts │ │ └── validation.ts │ └── tsconfig.json ├── ow │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── example.ts │ │ │ ├── ow.test.ts │ │ │ └── tsconfig.json │ │ ├── index.ts │ │ ├── resolver.ts │ │ └── validation.ts │ └── tsconfig.json ├── runtypes │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── example.ts │ │ │ ├── runtypes.test.ts │ │ │ └── tsconfig.json │ │ ├── index.ts │ │ ├── resolver.ts │ │ └── validation.ts │ └── tsconfig.json ├── superstruct │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── example.ts │ │ │ ├── superstruct.test.ts │ │ │ └── tsconfig.json │ │ ├── index.ts │ │ ├── resolver.ts │ │ └── validation.ts │ └── tsconfig.json ├── suretype │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── example.ts │ │ │ ├── suretype.test.ts │ │ │ └── tsconfig.json │ │ ├── index.ts │ │ ├── resolver.ts │ │ ├── serialization.ts │ │ └── validation.ts │ └── tsconfig.json ├── typebox │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── example.ts │ │ │ ├── tsconfig.json │ │ │ └── typebox.test.ts │ │ ├── index.ts │ │ ├── resolver.ts │ │ ├── serialization.ts │ │ └── validation.ts │ └── tsconfig.json ├── valibot │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── example.ts │ │ │ ├── tsconfig.json │ │ │ └── valibot.test.ts │ │ ├── index.ts │ │ ├── resolver.ts │ │ ├── serialization.ts │ │ └── validation.ts │ └── tsconfig.json ├── valita │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── example.ts │ │ │ ├── tsconfig.json │ │ │ └── valita.test.ts │ │ ├── index.ts │ │ ├── resolver.ts │ │ └── validation.ts │ └── tsconfig.json ├── vine │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── example.ts │ │ │ ├── tsconfig.json │ │ │ └── vine.test.ts │ │ ├── index.ts │ │ ├── resolver.ts │ │ └── validation.ts │ └── tsconfig.json ├── yup │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── __tests__ │ │ │ ├── example.ts │ │ │ ├── tsconfig.json │ │ │ └── yup.test.ts │ │ ├── index.ts │ │ ├── resolver.ts │ │ ├── serialization.ts │ │ └── validation.ts │ └── tsconfig.json └── zod │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ ├── __tests__ │ │ ├── example.ts │ │ ├── tsconfig.json │ │ └── zod.test.ts │ ├── index.ts │ ├── resolver.ts │ ├── serialization.ts │ └── validation.ts │ └── tsconfig.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── tsconfig.json ├── tsconfig.test.json ├── tsup.config.ts ├── turbo.json ├── turbo └── generators │ ├── config.ts │ ├── libraries.ts │ └── templates │ ├── README-api.md.hbs │ ├── README.md.hbs │ ├── adapter │ ├── README.md.hbs │ ├── package.json.hbs │ ├── src │ │ ├── __tests__ │ │ │ └── tsconfig.json.hbs │ │ └── index.ts.hbs │ └── tsconfig.json.hbs │ ├── all │ └── package.json.hbs │ ├── create-adapter │ └── src │ │ ├── __tests__ │ │ ├── example.ts.hbs │ │ └── {{adapterName}}.test.ts.hbs │ │ ├── resolver.ts.hbs │ │ └── validation.ts.hbs │ ├── main │ ├── package.json.hbs │ └── src │ │ ├── adapters.ts.hbs │ │ ├── serialization.ts.hbs │ │ └── validation.ts.hbs │ └── package.json.hbs ├── vitest.config.ts └── www ├── components └── Hero.tsx ├── next-env.d.ts ├── next.config.mjs ├── package.json ├── pages ├── _app.mdx ├── _meta.json ├── docs │ ├── _meta.json │ ├── coverage.mdx │ ├── credits.mdx │ ├── index.mdx │ ├── reference.mdx │ ├── setup.mdx │ └── usage.mdx └── index.mdx ├── postcss.config.js ├── public ├── logo128.png ├── logo16.png ├── logo24.png ├── logo32.png └── logo64.png ├── styles.css ├── tailwind.config.js ├── theme.config.tsx ├── tsconfig.json └── yarn.lock /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "restricted", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "ignore": ["@examples/*"] 11 | } 12 | -------------------------------------------------------------------------------- /.github/actions/setup/action.yaml: -------------------------------------------------------------------------------- 1 | name: Setup requirements 2 | runs: 3 | using: 'composite' 4 | steps: 5 | - name: Install pnpm 6 | uses: pnpm/action-setup@v2 7 | with: 8 | version: 8 9 | - name: Install Node.js 10 | uses: actions/setup-node@v3 11 | with: 12 | node-version: 20 13 | cache: 'pnpm' 14 | - name: Install dependencies 15 | run: pnpm install 16 | shell: bash 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | 4 | .next 5 | .parcel-cache 6 | .turbo 7 | 8 | dist/ 9 | *_dist/ 10 | 11 | *.tmp 12 | 13 | /turbo/generators/stars.json -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "bracketSpacing": false, 4 | "singleQuote": true, 5 | "trailingComma": "all", 6 | "overrides": [ 7 | { 8 | "files": "*.json", 9 | "options": { 10 | "trailingComma": "none" 11 | } 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | typeschema.com -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 André Costa 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | title: TypeSchema 2 | description: Universal adapter for TypeScript schema validation 3 | logo: /assets/logo.png 4 | 5 | google_analytics: G-E24ES7NSSP 6 | -------------------------------------------------------------------------------- /_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {% seo %} 8 | 9 | {% if site.google_analytics %} 10 | 11 | 12 | 18 | {% endif %} 19 | 20 | 21 |
22 | {{ content }} 23 |
24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/decs/typeschema/a5c728db9f4f1355a1df04d73091531862084a5e/assets/logo.png -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | import javascript from '@eslint/js'; 4 | import typescript from 'typescript-eslint'; 5 | import prettier from 'eslint-plugin-prettier/recommended'; 6 | import simpleImportSort from 'eslint-plugin-simple-import-sort'; 7 | 8 | export default typescript.config( 9 | javascript.configs.recommended, 10 | ...typescript.configs.recommended, 11 | { 12 | plugins: { 13 | 'simple-import-sort': simpleImportSort, 14 | }, 15 | rules: { 16 | 'simple-import-sort/imports': [ 17 | 'error', 18 | { 19 | groups: [ 20 | ['^.*\\u0000$'], 21 | ['^\\u0000'], 22 | ['^node:'], 23 | ['^@?\\w'], 24 | ['^'], 25 | ['^\\.'], 26 | ], 27 | }, 28 | ], 29 | 'simple-import-sort/exports': 'error', 30 | }, 31 | }, 32 | { 33 | files: ['**/src/__tests__/example.ts'], 34 | rules: { 35 | '@typescript-eslint/no-unused-vars': 'off', 36 | '@typescript-eslint/no-explicit-any': 'off', 37 | }, 38 | }, 39 | { 40 | ignores: ['**/sample/'], 41 | }, 42 | prettier, 43 | ); 44 | -------------------------------------------------------------------------------- /examples/bundlers/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | TypeSchema 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/bundlers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@examples/bundlers", 3 | "version": "0.0.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "test": "pnpm test:bun && pnpm test:esbuild && pnpm test:rollup && pnpm test:swc && pnpm test:vite && pnpm test:webpack", 8 | "test:bun": "bun build src/main.ts --outdir=bun_dist && node bun_dist/main.js", 9 | "test:esbuild": "esbuild src/main.ts --bundle --outdir=esbuild_dist && node esbuild_dist/main.js", 10 | "//test:parcel": "parcel build src/main.ts --dist-dir=parcel_dist --no-cache && node parcel_dist/main.js", 11 | "test:rollup": "rollup --config && node rollup_dist/main.js", 12 | "test:swc": "swc src/main.ts --out-dir=swc_dist && node swc_dist/src/main.js", 13 | "test:vite": "vite build --outDir=vite_dist", 14 | "test:webpack": "webpack --fail-on-warnings && node webpack_dist/main.js", 15 | "upgrade:deps": "ncu -u", 16 | "sync:pnpm": "sync-dependencies-meta-injected" 17 | }, 18 | "dependencies": { 19 | "@typeschema/main": "workspace:*", 20 | "@typeschema/zod": "workspace:*", 21 | "zod": "^3.23.8" 22 | }, 23 | "devDependencies": { 24 | "@rollup/plugin-node-resolve": "^15.2.3", 25 | "@swc/cli": "^0.4.0", 26 | "@swc/core": "^1.7.18", 27 | "bun": "^1.1.26", 28 | "esbuild": "^0.23.1", 29 | "parcel": "^2.12.0", 30 | "rollup": "^4.21.0", 31 | "ts-loader": "^9.5.1", 32 | "typescript": "^5.5.4", 33 | "vite": "^5.4.2", 34 | "webpack": "^5.94.0", 35 | "webpack-cli": "^5.1.4" 36 | }, 37 | "dependenciesMeta": { 38 | "@typeschema/main": { 39 | "injected": true 40 | }, 41 | "@typeschema/zod": { 42 | "injected": true 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /examples/bundlers/rollup.config.js: -------------------------------------------------------------------------------- 1 | import nodeResolve from '@rollup/plugin-node-resolve'; 2 | 3 | export default { 4 | input: 'src/main.ts', 5 | output: {dir: 'rollup_dist'}, 6 | plugins: [nodeResolve()], 7 | }; 8 | -------------------------------------------------------------------------------- /examples/bundlers/src/main.ts: -------------------------------------------------------------------------------- 1 | import {validate} from '@typeschema/main'; 2 | import {z} from 'zod'; 3 | 4 | validate(z.string(), 'hello').then(console.log); 5 | -------------------------------------------------------------------------------- /examples/bundlers/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": false 5 | }, 6 | "include": ["src"] 7 | } 8 | -------------------------------------------------------------------------------- /examples/bundlers/webpack.config.js: -------------------------------------------------------------------------------- 1 | import {cwd} from 'node:process'; 2 | 3 | export default { 4 | mode: 'production', 5 | entry: './src/main.ts', 6 | module: { 7 | rules: [ 8 | { 9 | test: /\.ts$/, 10 | use: 'ts-loader', 11 | exclude: /node_modules/, 12 | }, 13 | ], 14 | }, 15 | resolve: { 16 | extensions: ['.ts', '.js'], 17 | }, 18 | output: { 19 | path: `${cwd()}/webpack_dist`, 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /examples/commonjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@examples/commonjs", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "//test": "tsup --config ../../tsup.config.ts --format cjs && node dist/index.js", 7 | "upgrade:deps": "ncu -u", 8 | "sync:pnpm": "sync-dependencies-meta-injected" 9 | }, 10 | "dependencies": { 11 | "@typeschema/all": "workspace:*", 12 | "ow": "^2.0.0" 13 | }, 14 | "dependenciesMeta": { 15 | "@typeschema/all": { 16 | "injected": true 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/commonjs/src/index.ts: -------------------------------------------------------------------------------- 1 | import {toJSONSchema, validate} from '@typeschema/all'; 2 | import ow from 'ow'; 3 | 4 | validate(ow.string, 'hello').then(console.log); 5 | 6 | toJSONSchema(ow.string) 7 | .then(() => { 8 | throw new Error('Unexpected success'); 9 | }) 10 | .catch(error => { 11 | if (error.message !== 'This feature is unsupported for @typeschema/ow') { 12 | throw new Error(`Unexpected error: ${error.message}`); 13 | } 14 | }); 15 | -------------------------------------------------------------------------------- /examples/commonjs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /examples/missing-adapter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@examples/missing-adapter", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "tsup --config ../../tsup.config.ts --format cjs && node dist/index.js", 7 | "upgrade:deps": "ncu -u", 8 | "sync:pnpm": "sync-dependencies-meta-injected" 9 | }, 10 | "dependencies": { 11 | "@typeschema/main": "workspace:*", 12 | "valibot": "^0.39.0" 13 | }, 14 | "dependenciesMeta": { 15 | "@typeschema/main": { 16 | "injected": true 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/missing-adapter/src/index.ts: -------------------------------------------------------------------------------- 1 | import {validate} from '@typeschema/main'; 2 | import {string} from 'valibot'; 3 | 4 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 5 | validate(string(), 'hello') 6 | .then(() => { 7 | throw new Error('Unexpected success'); 8 | }) 9 | .catch(error => { 10 | if ( 11 | !error.message.startsWith("Cannot find package '@typeschema/valibot'") 12 | ) { 13 | throw new Error(`Unexpected error: ${error.message}`); 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /examples/missing-adapter/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /examples/next/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /examples/next/next.config.mjs: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {}; 3 | 4 | export default nextConfig; 5 | -------------------------------------------------------------------------------- /examples/next/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@examples/next", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "test": "pnpm test:webpack && pnpm test:turbopack", 7 | "test:webpack": "next build", 8 | "test:turbopack": "./turbopack.sh", 9 | "upgrade:deps": "ncu -u", 10 | "sync:pnpm": "sync-dependencies-meta-injected" 11 | }, 12 | "dependencies": { 13 | "@typeschema/main": "workspace:*", 14 | "@typeschema/zod": "workspace:*", 15 | "next": "14.2.6", 16 | "react": "^18", 17 | "react-dom": "^18", 18 | "zod": "^3.23.8" 19 | }, 20 | "devDependencies": { 21 | "@types/node": "^22", 22 | "@types/react": "^18", 23 | "@types/react-dom": "^18", 24 | "typescript": "^5" 25 | }, 26 | "dependenciesMeta": { 27 | "@typeschema/main": { 28 | "injected": true 29 | }, 30 | "@typeschema/zod": { 31 | "injected": true 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /examples/next/src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type {Metadata} from 'next'; 2 | 3 | export const metadata: Metadata = { 4 | title: 'TypeSchema', 5 | }; 6 | 7 | export default function RootLayout({ 8 | children, 9 | }: Readonly<{ 10 | children: React.ReactNode; 11 | }>) { 12 | return ( 13 | 14 | {children} 15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /examples/next/src/app/page.tsx: -------------------------------------------------------------------------------- 1 | import {validate} from '@typeschema/main'; 2 | import {z} from 'zod'; 3 | 4 | export default async function Page() { 5 | console.log(await validate(z.string(), 'hello')); 6 | return null; 7 | } 8 | -------------------------------------------------------------------------------- /examples/next/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["dom", "dom.iterable", "esnext"], 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": true, 7 | "noEmit": true, 8 | "esModuleInterop": true, 9 | "module": "esnext", 10 | "moduleResolution": "bundler", 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "jsx": "preserve", 14 | "incremental": true, 15 | "plugins": [ 16 | { 17 | "name": "next" 18 | } 19 | ], 20 | "paths": { 21 | "@/*": ["./src/*"] 22 | } 23 | }, 24 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 25 | "exclude": ["node_modules"] 26 | } 27 | -------------------------------------------------------------------------------- /examples/next/turbopack.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | pnpm next dev --turbo & 4 | sleep 2 5 | curl http://127.0.0.1:3000 -f > /dev/null 6 | status="$?" 7 | kill $! 8 | exit "$status" -------------------------------------------------------------------------------- /packages/all/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | TypeSchema 4 |

@typeschema/all

5 |

6 | License 7 | Bundle size 8 | npm downloads 9 | GitHub stars 10 |

11 |

12 | Universal adapter for schema validation 13 |
14 | https://typeschema.com ✨ 15 |

16 | 17 | ## API 18 | 19 | ### Inference 20 | - `Infer`: Extracts the output type of a schema 21 | - `InferIn`: Extracts the input type of a schema 22 | 23 | ### Validation 24 | - `wrap(schema)`: Returns the wrapped schema with access to its operations 25 | - `validate(schema, data)`: Returns the validated data or a list of validation issues 26 | - `assert(schema, data)`: Returns the validated data or throws an `AggregateError` 27 | 28 | ### Serialization 29 | - `toJSONSchema(schema)`: Converts the schema into the equivalent JSON schema 30 | -------------------------------------------------------------------------------- /packages/all/src/__tests__/fastest-validator.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type {Infer, InferIn} from '..'; 6 | 7 | import {initTRPC} from '@trpc/server'; 8 | import {expectTypeOf} from 'expect-type'; 9 | import {describe, expect, test} from 'vitest'; 10 | 11 | import {assert, validate, wrap} from '..'; 12 | 13 | describe('fastest-validator', () => { 14 | const schema = { 15 | age: 'number', 16 | createdAt: 'string', 17 | email: 'string', 18 | id: 'string', 19 | name: 'string', 20 | updatedAt: 'string', 21 | }; 22 | 23 | const data = { 24 | age: 123, 25 | createdAt: '2021-01-01T00:00:00.000Z', 26 | email: 'john.doe@test.com', 27 | id: 'c4a760a8-dbcf-4e14-9f39-645a8e933d74', 28 | name: 'John Doe', 29 | updatedAt: '2021-01-01T00:00:00.000Z', 30 | }; 31 | const badData = { 32 | age: '123', 33 | createdAt: '2021-01-01T00:00:00.000Z', 34 | email: 'john.doe@test.com', 35 | id: 'c4a760a8-dbcf-4e14-9f39-645a8e933d74', 36 | name: 'John Doe', 37 | updatedAt: '2021-01-01T00:00:00.000Z', 38 | }; 39 | 40 | test('infer', () => { 41 | expectTypeOf>().toEqualTypeOf(); 42 | expectTypeOf>().toEqualTypeOf(); 43 | }); 44 | 45 | test('validate', async () => { 46 | expect(await validate(schema, data)).toStrictEqual({data, success: true}); 47 | expect(await validate(schema, badData)).toStrictEqual({ 48 | issues: [{message: "The 'age' field must be a number.", path: ['age']}], 49 | success: false, 50 | }); 51 | }); 52 | 53 | test('assert', async () => { 54 | expect(await assert(schema, data)).toStrictEqual(data); 55 | await expect(assert(schema, badData)).rejects.toThrow(); 56 | }); 57 | 58 | test('wrap', async () => { 59 | const tRPC = initTRPC.create(); 60 | const router = tRPC.router({ 61 | hello: tRPC.procedure.input(wrap(schema)).query(({input}) => { 62 | expectTypeOf().toEqualTypeOf(); 63 | return input; 64 | }), 65 | }); 66 | const createCaller = tRPC.createCallerFactory(router); 67 | const caller = createCaller({}); 68 | expect(await caller.hello(data)).toStrictEqual(data); 69 | }); 70 | }); 71 | -------------------------------------------------------------------------------- /packages/all/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../../../tsconfig.test.json", 4 | "include": ["*.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/all/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type { 6 | InputFrom, 7 | OutputFrom, 8 | SchemaFrom, 9 | UnknownIfNever, 10 | } from '@typeschema/core'; 11 | 12 | import { 13 | createAssert, 14 | createValidate, 15 | createWrap, 16 | createToJSONSchema, 17 | } from '@typeschema/core'; 18 | 19 | import {AdapterResolver} from './resolver'; 20 | import {validationAdapter} from './validation'; 21 | import {serializationAdapter} from './serialization'; 22 | 23 | export type Schema = SchemaFrom; 24 | export type Infer = UnknownIfNever< 25 | OutputFrom 26 | >; 27 | export type InferIn = UnknownIfNever< 28 | InputFrom 29 | >; 30 | 31 | export const validate = createValidate(validationAdapter); 32 | export const assert = createAssert(validate); 33 | export const wrap = createWrap(assert, validate); 34 | 35 | export const toJSONSchema = createToJSONSchema(serializationAdapter); 36 | 37 | export { 38 | AdapterResolver, 39 | validationAdapter, 40 | serializationAdapter, 41 | }; 42 | -------------------------------------------------------------------------------- /packages/all/src/resolver.ts: -------------------------------------------------------------------------------- 1 | export type {AdapterResolver} from '@typeschema/main'; 2 | -------------------------------------------------------------------------------- /packages/all/src/serialization.ts: -------------------------------------------------------------------------------- 1 | export {serializationAdapter} from '@typeschema/main'; 2 | -------------------------------------------------------------------------------- /packages/all/src/validation.ts: -------------------------------------------------------------------------------- 1 | export {validationAdapter} from '@typeschema/main'; 2 | -------------------------------------------------------------------------------- /packages/all/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/arktype/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @typeschema/arktype 2 | 3 | ## 0.14.0 4 | 5 | ### Minor Changes 6 | 7 | - 14976b2: Upgrade deps 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [2251f01] 12 | - Updated dependencies [14976b2] 13 | - @typeschema/core@0.14.0 14 | 15 | ## 0.13.2 16 | 17 | ### Patch Changes 18 | 19 | - 3087916: Improve handling missing types 20 | - Updated dependencies [3087916] 21 | - @typeschema/core@0.13.2 22 | 23 | ## 0.13.1 24 | 25 | ### Patch Changes 26 | 27 | - 6f1fc2d: Export the Schema type 28 | - Updated dependencies [6f1fc2d] 29 | - @typeschema/core@0.13.1 30 | 31 | ## 0.13.0 32 | 33 | ### Minor Changes 34 | 35 | - 05b430e: Package restructure 36 | 37 | ### Patch Changes 38 | 39 | - Updated dependencies [05b430e] 40 | - @typeschema/core@0.13.0 41 | -------------------------------------------------------------------------------- /packages/arktype/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | TypeSchema 4 |

@typeschema/arktype

5 |

6 | License 7 | Bundle size 8 | npm downloads 9 | GitHub stars 10 |

11 |

12 | Reusable adapter for ArkType schemas 13 |
14 | https://typeschema.com ✨ 15 |

16 | 17 | ```ts 18 | import {initTRPC} from '@trpc/server'; 19 | import {type} from 'arktype'; 20 | 21 | import {wrap} from '@typeschema/arktype'; 22 | 23 | const schema = type({name: 'string'}); 24 | 25 | const t = initTRPC.create(); 26 | const appRouter = t.router({ 27 | hello: t.procedure 28 | .input(wrap(schema)) 29 | .query(({input}) => `Hello, ${input.name}!`), 30 | // ^? {name: string} 31 | }); 32 | 33 | ``` 34 | 35 | Use it directly or through [`@typeschema/main`](https://github.com/decs/typeschema/tree/main/packages/main) 36 | 37 | ## Dependencies 38 | - [`arktype`](https://www.npmjs.com/package/arktype): Required for inference and validation (`^2.0.0-rc.0`) 39 | 40 | ## API 41 | 42 | ### Inference 43 | - `Infer`: Extracts the output type of a schema 44 | - `InferIn`: Extracts the input type of a schema 45 | 46 | ### Validation 47 | - `wrap(schema)`: Returns the wrapped schema with access to its operations 48 | - `validate(schema, data)`: Returns the validated data or a list of validation issues 49 | - `assert(schema, data)`: Returns the validated data or throws an `AggregateError` 50 | -------------------------------------------------------------------------------- /packages/arktype/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is partially generated. Only some fields can be modified manually!", 3 | "name": "@typeschema/arktype", 4 | "//version": "This field is manually maintained.", 5 | "version": "0.14.0", 6 | "//description": "This field is manually maintained.", 7 | "description": "Reusable adapter for ArkType schemas", 8 | "keywords": [ 9 | "typescript", 10 | "type", 11 | "schema", 12 | "adapter", 13 | "validation", 14 | "inference", 15 | "assert" 16 | ], 17 | "homepage": "https://typeschema.com", 18 | "license": "MIT", 19 | "author": { 20 | "name": "André Costa", 21 | "email": "andrefonsecacosta@gmail.com" 22 | }, 23 | "publishConfig": { 24 | "access": "public", 25 | "registry": "https://registry.npmjs.org/" 26 | }, 27 | "files": [ 28 | "/dist" 29 | ], 30 | "main": "dist/index.js", 31 | "module": "dist/index.mjs", 32 | "types": "dist/index.d.ts", 33 | "exports": { 34 | ".": { 35 | "import": { 36 | "types": "./dist/index.d.mts", 37 | "default": "./dist/index.mjs" 38 | }, 39 | "require": { 40 | "types": "./dist/index.d.ts", 41 | "default": "./dist/index.js" 42 | } 43 | } 44 | }, 45 | "sideEffects": false, 46 | "repository": { 47 | "type": "git", 48 | "url": "https://github.com/decs/typeschema.git" 49 | }, 50 | "scripts": { 51 | "build": "tsup --config ../../tsup.config.ts", 52 | "lint": "eslint src --fix", 53 | "lint:package": "publint && attw --pack", 54 | "test": "vitest --config ../../vitest.config.ts", 55 | "upgrade:deps": "ncu -u --dep=dev,peer --reject ow" 56 | }, 57 | "dependencies": { 58 | "@typeschema/core": "workspace:*" 59 | }, 60 | "//devDependencies": "This field is manually maintained.", 61 | "devDependencies": { 62 | "arktype": "^2.0.0-rc.0" 63 | }, 64 | "//peerDependencies": { 65 | "//": "This field is manually maintained.", 66 | "arktype": "Required for inference and validation" 67 | }, 68 | "peerDependencies": { 69 | "arktype": "^2.0.0-rc.0" 70 | }, 71 | "//peerDependenciesMeta": "This field is manually maintained.", 72 | "peerDependenciesMeta": { 73 | "arktype": { 74 | "optional": true 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /packages/arktype/src/__tests__/example.ts: -------------------------------------------------------------------------------- 1 | import {initTRPC} from '@trpc/server'; 2 | import {type} from 'arktype'; 3 | 4 | import {wrap} from '..'; 5 | 6 | const schema = type({name: 'string'}); 7 | 8 | const t = initTRPC.create(); 9 | const appRouter = t.router({ 10 | hello: t.procedure 11 | .input(wrap(schema)) 12 | .query(({input}) => `Hello, ${input.name}!`), 13 | // ^? {name: string} 14 | }); 15 | -------------------------------------------------------------------------------- /packages/arktype/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../../../tsconfig.test.json", 4 | "include": ["*.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/arktype/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type { 6 | InputFrom, 7 | OutputFrom, 8 | SchemaFrom, 9 | UnknownIfNever, 10 | } from '@typeschema/core'; 11 | 12 | import { 13 | createAssert, 14 | createValidate, 15 | createWrap, 16 | } from '@typeschema/core'; 17 | 18 | import {AdapterResolver} from './resolver'; 19 | import {validationAdapter} from './validation'; 20 | 21 | export type Schema = SchemaFrom; 22 | export type Infer = UnknownIfNever< 23 | OutputFrom 24 | >; 25 | export type InferIn = UnknownIfNever< 26 | InputFrom 27 | >; 28 | 29 | export const validate = createValidate(validationAdapter); 30 | export const assert = createAssert(validate); 31 | export const wrap = createWrap(assert, validate); 32 | 33 | 34 | export { 35 | AdapterResolver, 36 | validationAdapter, 37 | }; 38 | -------------------------------------------------------------------------------- /packages/arktype/src/resolver.ts: -------------------------------------------------------------------------------- 1 | import type {IfDefined, Resolver} from '@typeschema/core'; 2 | import type {Type} from 'arktype'; 3 | 4 | export interface AdapterResolver extends Resolver { 5 | base: IfDefined; 6 | input: this['schema'] extends this['base'] 7 | ? this['schema']['inferIn'] 8 | : never; 9 | output: this['schema'] extends this['base'] ? this['schema']['infer'] : never; 10 | } 11 | -------------------------------------------------------------------------------- /packages/arktype/src/validation.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {ValidationAdapter} from '@typeschema/core'; 3 | 4 | import {memoize} from '@typeschema/core'; 5 | 6 | const importValidationModule = memoize(async () => { 7 | const {ArkErrors} = await import('arktype'); 8 | return {ArkErrors}; 9 | }); 10 | 11 | export const validationAdapter: ValidationAdapter< 12 | AdapterResolver 13 | > = async schema => { 14 | const {ArkErrors} = await importValidationModule(); 15 | return async data => { 16 | const result = schema(data); 17 | if (result instanceof ArkErrors) { 18 | return { 19 | issues: Array.from(result).map(({message, path}) => ({message, path})), 20 | success: false, 21 | }; 22 | } 23 | return { 24 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 25 | data: result as any, 26 | success: true, 27 | }; 28 | }; 29 | }; 30 | -------------------------------------------------------------------------------- /packages/arktype/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/class-validator/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @typeschema/class-validator 2 | 3 | ## 0.3.0 4 | 5 | ### Minor Changes 6 | 7 | - d7e9ade: Improved error messages for class-validator 8 | 9 | ## 0.2.0 10 | 11 | ### Minor Changes 12 | 13 | - 14976b2: Upgrade deps 14 | 15 | ### Patch Changes 16 | 17 | - Updated dependencies [2251f01] 18 | - Updated dependencies [14976b2] 19 | - @typeschema/core@0.14.0 20 | 21 | ## 0.1.2 22 | 23 | ### Patch Changes 24 | 25 | - 6c178f0: Fix Vite support 26 | 27 | ## 0.1.1 28 | 29 | ### Patch Changes 30 | 31 | - Updated dependencies [3087916] 32 | - @typeschema/core@0.13.2 33 | 34 | ## 0.1.0 35 | 36 | ### Minor Changes 37 | 38 | - be86c4d: Add support for class-validator 39 | -------------------------------------------------------------------------------- /packages/class-validator/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | TypeSchema 4 |

@typeschema/class-validator

5 |

6 | License 7 | Bundle size 8 | npm downloads 9 | GitHub stars 10 |

11 |

12 | Reusable adapter for class-validator classes 13 |
14 | https://typeschema.com ✨ 15 |

16 | 17 | ```ts 18 | import {initTRPC} from '@trpc/server'; 19 | import {IsNotEmpty} from 'class-validator'; 20 | 21 | import {wrap} from '@typeschema/class-validator'; 22 | 23 | class Schema { 24 | @IsNotEmpty() 25 | name!: string; 26 | } 27 | const schema = Schema; 28 | 29 | const t = initTRPC.create(); 30 | const appRouter = t.router({ 31 | hello: t.procedure 32 | .input(wrap(schema)) 33 | .query(({input}) => `Hello, ${input.name}!`), 34 | // ^? {name: string} 35 | }); 36 | 37 | ``` 38 | 39 | Use it directly or through [`@typeschema/main`](https://github.com/decs/typeschema/tree/main/packages/main) 40 | 41 | ## Dependencies 42 | - [`class-validator`](https://www.npmjs.com/package/class-validator): Required for inference and validation (`^0.14.1`) 43 | 44 | ## API 45 | 46 | ### Inference 47 | - `Infer`: Extracts the output type of a schema 48 | - `InferIn`: Extracts the input type of a schema 49 | 50 | ### Validation 51 | - `wrap(schema)`: Returns the wrapped schema with access to its operations 52 | - `validate(schema, data)`: Returns the validated data or a list of validation issues 53 | - `assert(schema, data)`: Returns the validated data or throws an `AggregateError` 54 | -------------------------------------------------------------------------------- /packages/class-validator/src/__tests__/example.ts: -------------------------------------------------------------------------------- 1 | import {initTRPC} from '@trpc/server'; 2 | import {IsNotEmpty} from 'class-validator'; 3 | 4 | import {wrap} from '..'; 5 | 6 | class Schema { 7 | @IsNotEmpty() 8 | name!: string; 9 | } 10 | const schema = Schema; 11 | 12 | const t = initTRPC.create(); 13 | const appRouter = t.router({ 14 | hello: t.procedure 15 | .input(wrap(schema)) 16 | .query(({input}) => `Hello, ${input.name}!`), 17 | // ^? {name: string} 18 | }); 19 | -------------------------------------------------------------------------------- /packages/class-validator/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../../../tsconfig.test.json", 4 | "include": ["*.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/class-validator/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type { 6 | InputFrom, 7 | OutputFrom, 8 | SchemaFrom, 9 | UnknownIfNever, 10 | } from '@typeschema/core'; 11 | 12 | import { 13 | createAssert, 14 | createValidate, 15 | createWrap, 16 | } from '@typeschema/core'; 17 | 18 | import {AdapterResolver} from './resolver'; 19 | import {validationAdapter} from './validation'; 20 | 21 | export type Schema = SchemaFrom; 22 | export type Infer = UnknownIfNever< 23 | OutputFrom 24 | >; 25 | export type InferIn = UnknownIfNever< 26 | InputFrom 27 | >; 28 | 29 | export const validate = createValidate(validationAdapter); 30 | export const assert = createAssert(validate); 31 | export const wrap = createWrap(assert, validate); 32 | 33 | 34 | export { 35 | AdapterResolver, 36 | validationAdapter, 37 | }; 38 | -------------------------------------------------------------------------------- /packages/class-validator/src/resolver.ts: -------------------------------------------------------------------------------- 1 | import type {Resolver} from '@typeschema/core'; 2 | 3 | type Prettify = {[K in keyof T]: T[K]} & NonNullable; 4 | 5 | type Attributes = Prettify< 6 | // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type 7 | Omit 8 | >; 9 | 10 | export interface AdapterResolver extends Resolver { 11 | base: new (...args: unknown[]) => object; 12 | input: this['schema'] extends this['base'] 13 | ? this['schema'] extends {prototype: unknown} 14 | ? Attributes 15 | : never 16 | : never; 17 | output: this['schema'] extends this['base'] 18 | ? this['schema'] extends {prototype: unknown} 19 | ? Attributes 20 | : never 21 | : never; 22 | } 23 | -------------------------------------------------------------------------------- /packages/class-validator/src/validation.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {ValidationAdapter, ValidationIssue} from '@typeschema/core'; 3 | 4 | import {memoize} from '@typeschema/core'; 5 | import {ValidationError} from 'class-validator'; 6 | 7 | const importValidationModule = memoize(async () => { 8 | const {validate} = await import('class-validator'); 9 | return {validate}; 10 | }); 11 | 12 | function getIssues( 13 | error: ValidationError, 14 | parentPath: Array, 15 | ): Array { 16 | const path = [ 17 | ...parentPath, 18 | Number.isInteger(+error.property) ? +error.property : error.property, 19 | ]; 20 | return Object.values(error.constraints ?? {}) 21 | .map((message): ValidationIssue => ({message, path})) 22 | .concat( 23 | error.children?.flatMap(childError => getIssues(childError, path)) ?? [], 24 | ); 25 | } 26 | 27 | export const validationAdapter: ValidationAdapter< 28 | AdapterResolver 29 | > = async schema => { 30 | const {validate} = await importValidationModule(); 31 | return async data => { 32 | const errors = await validate(Object.assign(new schema(), data)); 33 | if (errors.length === 0) { 34 | return { 35 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 36 | data: data as any, 37 | success: true, 38 | }; 39 | } 40 | return { 41 | issues: errors.flatMap(error => getIssues(error, [])), 42 | success: false, 43 | }; 44 | }; 45 | }; 46 | -------------------------------------------------------------------------------- /packages/class-validator/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/core/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @typeschema/core 2 | 3 | ## 0.14.0 4 | 5 | ### Minor Changes 6 | 7 | - 2251f01: Fixes detection of installed adapters 8 | - 14976b2: Upgrade deps 9 | 10 | ## 0.13.2 11 | 12 | ### Patch Changes 13 | 14 | - 3087916: Improve handling missing types 15 | 16 | ## 0.13.1 17 | 18 | ### Patch Changes 19 | 20 | - 6f1fc2d: Export the Schema type 21 | 22 | ## 0.13.0 23 | 24 | ### Minor Changes 25 | 26 | - 05b430e: Package restructure 27 | -------------------------------------------------------------------------------- /packages/core/README.md: -------------------------------------------------------------------------------- 1 | TypeSchema 2 |

@typeschema/core

3 |

4 | License 5 | Bundle size 6 | npm downloads 7 | GitHub stars 8 |

9 |

10 | Universal adapter for schema validation 11 |
12 | https://typeschema.com ✨ 13 |

14 | -------------------------------------------------------------------------------- /packages/core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@typeschema/core", 3 | "version": "0.14.0", 4 | "description": "Universal adapter for schema validation", 5 | "keywords": [ 6 | "typescript", 7 | "type", 8 | "schema", 9 | "adapter", 10 | "validation", 11 | "inference", 12 | "assert" 13 | ], 14 | "homepage": "https://typeschema.com", 15 | "license": "MIT", 16 | "author": { 17 | "name": "André Costa", 18 | "email": "andrefonsecacosta@gmail.com" 19 | }, 20 | "publishConfig": { 21 | "access": "public", 22 | "registry": "https://registry.npmjs.org/" 23 | }, 24 | "files": [ 25 | "/dist" 26 | ], 27 | "main": "dist/index.js", 28 | "module": "dist/index.mjs", 29 | "types": "dist/index.d.ts", 30 | "exports": { 31 | ".": { 32 | "import": { 33 | "types": "./dist/index.d.mts", 34 | "default": "./dist/index.mjs" 35 | }, 36 | "require": { 37 | "types": "./dist/index.d.ts", 38 | "default": "./dist/index.js" 39 | } 40 | } 41 | }, 42 | "sideEffects": false, 43 | "repository": { 44 | "type": "git", 45 | "url": "https://github.com/decs/typeschema.git" 46 | }, 47 | "scripts": { 48 | "build": "tsup --config ../../tsup.config.ts", 49 | "lint": "eslint src --fix", 50 | "lint:package": "publint && attw --pack" 51 | }, 52 | "devDependencies": { 53 | "@types/json-schema": "^7.0.15" 54 | }, 55 | "peerDependencies": { 56 | "@types/json-schema": "^7.0.15" 57 | }, 58 | "peerDependenciesMeta": { 59 | "@types/json-schema": { 60 | "optional": true 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /packages/core/src/index.ts: -------------------------------------------------------------------------------- 1 | export {InputFrom, OutputFrom, Resolver, SchemaFrom} from './resolver'; 2 | export { 3 | createToJSONSchema, 4 | SerializationAdapter, 5 | ToJSONSchema, 6 | } from './serialization'; 7 | export { 8 | IfDefined, 9 | memoize, 10 | memoizeWithKey, 11 | UnknownIfNever, 12 | unsupportedAdapter, 13 | } from './utils'; 14 | export { 15 | Assert, 16 | createAssert, 17 | createValidate, 18 | Validate, 19 | ValidationAdapter, 20 | ValidationIssue, 21 | ValidationResult, 22 | } from './validation'; 23 | export {createWrap, TypeSchema, Wrap} from './wrap'; 24 | -------------------------------------------------------------------------------- /packages/core/src/resolver.ts: -------------------------------------------------------------------------------- 1 | import type {IfDefined} from './utils'; 2 | 3 | export interface Resolver { 4 | schema: TSchema; 5 | input: unknown; 6 | output: unknown; 7 | base: unknown; 8 | } 9 | 10 | export type SchemaFrom = IfDefined< 11 | TResolver['base'] 12 | >; 13 | 14 | export type InputFrom = 15 | TSchema extends SchemaFrom 16 | ? IfDefined<(TResolver & {schema: TSchema})['input']> 17 | : never; 18 | 19 | export type OutputFrom = 20 | TSchema extends SchemaFrom 21 | ? IfDefined<(TResolver & {schema: TSchema})['output']> 22 | : never; 23 | -------------------------------------------------------------------------------- /packages/core/src/serialization.ts: -------------------------------------------------------------------------------- 1 | import type {Resolver, SchemaFrom} from './resolver'; 2 | import type {JSONSchema7} from 'json-schema'; 3 | 4 | import {memoizeWithKey} from './utils'; 5 | 6 | export type SerializationAdapter = < 7 | TSchema extends SchemaFrom, 8 | >( 9 | schema: TSchema, 10 | ) => Promise; 11 | 12 | export type ToJSONSchema = < 13 | TSchema extends SchemaFrom, 14 | >( 15 | schema: TSchema, 16 | ) => Promise; 17 | 18 | /* @__NO_SIDE_EFFECTS__ */ 19 | export function createToJSONSchema( 20 | serializationAdapter: SerializationAdapter, 21 | ): ToJSONSchema { 22 | const memoizedSerializationAdapter = memoizeWithKey( 23 | (schema: SchemaFrom) => serializationAdapter(schema), 24 | ); 25 | return async schema => { 26 | const serializedSchema = await memoizedSerializationAdapter(schema); 27 | return serializedSchema; 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /packages/core/src/utils.ts: -------------------------------------------------------------------------------- 1 | import type {Resolver, SchemaFrom} from './resolver'; 2 | 3 | export type IfDefined = unknown extends TValue 4 | ? TModule extends '' 5 | ? never 6 | : `Cannot find module '${TModule}'` 7 | : TValue; 8 | 9 | export type UnknownIfNever = [T] extends [never] ? unknown : T; 10 | 11 | /* @__NO_SIDE_EFFECTS__ */ 12 | export function memoize( 13 | fn: () => Promise, 14 | ): (() => Promise) & {clear(): void} { 15 | let cache: TValue | undefined = undefined; 16 | const memoizedFn = async () => { 17 | if (cache === undefined) { 18 | cache = await fn(); 19 | } 20 | return cache; 21 | }; 22 | memoizedFn.clear = () => (cache = undefined); 23 | return memoizedFn; 24 | } 25 | 26 | /* @__NO_SIDE_EFFECTS__ */ 27 | export function memoizeWithKey( 28 | fn: (key: TKey) => Promise, 29 | ): ((key: TKey) => Promise) & {clear(): void} { 30 | const cache = new Map(); 31 | const memoizedFn = async (key: TKey) => { 32 | if (!cache.has(key)) { 33 | cache.set(key, await fn(key)); 34 | } 35 | return cache.get(key) as TValue; 36 | }; 37 | memoizedFn.clear = () => cache.clear(); 38 | return memoizedFn; 39 | } 40 | 41 | /* @__NO_SIDE_EFFECTS__ */ 42 | export function unsupportedAdapter( 43 | adapterName: string, 44 | ): (schema: SchemaFrom) => Promise { 45 | return async () => { 46 | throw new Error(`This feature is unsupported for ${adapterName}`); 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /packages/core/src/validation.ts: -------------------------------------------------------------------------------- 1 | import type {OutputFrom, Resolver, SchemaFrom} from './resolver'; 2 | import type {UnknownIfNever} from './utils'; 3 | 4 | import {memoizeWithKey} from './utils'; 5 | 6 | export type ValidationIssue = { 7 | message: string; 8 | path?: Array; 9 | }; 10 | 11 | export type ValidationResult = 12 | | {success: true; data: TOutput} 13 | | {success: false; issues: Array}; 14 | 15 | export type ValidationAdapter = < 16 | TSchema extends SchemaFrom, 17 | >( 18 | schema: TSchema, 19 | ) => Promise< 20 | ( 21 | data: unknown, 22 | ) => Promise>>> 23 | >; 24 | 25 | export type Validate = < 26 | TSchema extends SchemaFrom, 27 | >( 28 | schema: TSchema, 29 | data: unknown, 30 | ) => Promise>>>; 31 | 32 | /* @__NO_SIDE_EFFECTS__ */ 33 | export function createValidate( 34 | validationAdapter: ValidationAdapter, 35 | ): Validate { 36 | const memoizedValidationAdapter = memoizeWithKey( 37 | (schema: SchemaFrom) => validationAdapter(schema), 38 | ); 39 | return async (schema, data) => { 40 | const validateSchema = await memoizedValidationAdapter(schema); 41 | return validateSchema(data); 42 | }; 43 | } 44 | 45 | export type Assert = < 46 | TSchema extends SchemaFrom, 47 | >( 48 | schema: TSchema, 49 | data: unknown, 50 | ) => Promise>>; 51 | 52 | /* @__NO_SIDE_EFFECTS__ */ 53 | export function createAssert( 54 | validate: Validate, 55 | ): Assert { 56 | return async (schema, data) => { 57 | const result = await validate(schema, data); 58 | if (result.success) { 59 | return result.data; 60 | } 61 | throw new AggregateError(result.issues, 'Assertion failed'); 62 | }; 63 | } 64 | -------------------------------------------------------------------------------- /packages/core/src/wrap.ts: -------------------------------------------------------------------------------- 1 | import type {InputFrom, OutputFrom, Resolver, SchemaFrom} from './resolver'; 2 | import type {UnknownIfNever} from './utils'; 3 | import type {Assert, Validate, ValidationIssue} from './validation'; 4 | 5 | export type TypeSchema = { 6 | _input: TInput; 7 | _output: TOutput; 8 | assert(data: unknown): Promise; 9 | parse(data: unknown): Promise; 10 | validate( 11 | data: unknown, 12 | ): Promise<{data: TOutput} | {issues: Array}>; 13 | }; 14 | 15 | export type Wrap = < 16 | TSchema extends SchemaFrom, 17 | >( 18 | schema: TSchema, 19 | ) => TypeSchema< 20 | UnknownIfNever>, 21 | UnknownIfNever> 22 | >; 23 | 24 | /* @__NO_SIDE_EFFECTS__ */ 25 | export function createWrap( 26 | assert: Assert, 27 | validate: Validate, 28 | ): Wrap { 29 | return schema => ({ 30 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 31 | _input: undefined as any, 32 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 33 | _output: undefined as any, 34 | assert: data => assert(schema, data), 35 | parse: data => assert(schema, data), 36 | validate: data => validate(schema, data), 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /packages/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/deepkit/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @typeschema/deepkit 2 | 3 | ## 0.14.0 4 | 5 | ### Minor Changes 6 | 7 | - 14976b2: Upgrade deps 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [2251f01] 12 | - Updated dependencies [14976b2] 13 | - @typeschema/core@0.14.0 14 | 15 | ## 0.13.4 16 | 17 | ### Patch Changes 18 | 19 | - 8fa21a3: Upgrade dependencies 20 | 21 | ## 0.13.3 22 | 23 | ### Patch Changes 24 | 25 | - 6c178f0: Fix Vite support 26 | 27 | ## 0.13.2 28 | 29 | ### Patch Changes 30 | 31 | - 3087916: Improve handling missing types 32 | - Updated dependencies [3087916] 33 | - @typeschema/core@0.13.2 34 | 35 | ## 0.13.1 36 | 37 | ### Patch Changes 38 | 39 | - 6f1fc2d: Export the Schema type 40 | - Updated dependencies [6f1fc2d] 41 | - @typeschema/core@0.13.1 42 | 43 | ## 0.13.0 44 | 45 | ### Minor Changes 46 | 47 | - 05b430e: Package restructure 48 | 49 | ### Patch Changes 50 | 51 | - Updated dependencies [05b430e] 52 | - @typeschema/core@0.13.0 53 | -------------------------------------------------------------------------------- /packages/deepkit/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | TypeSchema 4 |

@typeschema/deepkit

5 |

6 | License 7 | Bundle size 8 | npm downloads 9 | GitHub stars 10 |

11 |

12 | Reusable adapter for Deepkit schemas 13 |
14 | https://typeschema.com ✨ 15 |

16 | 17 | ```ts 18 | import {typeOf} from '@deepkit/type'; 19 | import {initTRPC} from '@trpc/server'; 20 | 21 | import {wrap} from '@typeschema/deepkit'; 22 | 23 | const schema = typeOf<{name: string}>(); 24 | 25 | const t = initTRPC.create(); 26 | const appRouter = t.router({ 27 | hello: t.procedure 28 | .input(wrap(schema)) 29 | .query(({input}) => `Hello, ${(input as any).name}!`), 30 | // ^? unknown 31 | }); 32 | 33 | ``` 34 | 35 | Use it directly or through [`@typeschema/main`](https://github.com/decs/typeschema/tree/main/packages/main) 36 | 37 | ## Dependencies 38 | - [`@deepkit/type`](https://www.npmjs.com/package/@deepkit/type): Required for validation (`^1.0.1-alpha.145`) 39 | 40 | ## API 41 | 42 | ### Validation 43 | - `wrap(schema)`: Returns the wrapped schema with access to its operations 44 | - `validate(schema, data)`: Returns the validated data or a list of validation issues 45 | - `assert(schema, data)`: Returns the validated data or throws an `AggregateError` 46 | -------------------------------------------------------------------------------- /packages/deepkit/src/__tests__/deepkit.test.ts: -------------------------------------------------------------------------------- 1 | import type {Infer, InferIn} from '..'; 2 | 3 | import {typeOf} from '@deepkit/type'; 4 | import {initTRPC} from '@trpc/server'; 5 | import {expectTypeOf} from 'expect-type'; 6 | import {describe, expect, test} from 'vitest'; 7 | 8 | import {assert, validate, wrap} from '..'; 9 | 10 | describe('deepkit', () => { 11 | const schema = typeOf<{ 12 | age: number; 13 | createdAt: string; 14 | email: string; 15 | id: string; 16 | name: string; 17 | updatedAt: string; 18 | }>(); 19 | 20 | const data = { 21 | age: 123, 22 | createdAt: '2021-01-01T00:00:00.000Z', 23 | email: 'john.doe@test.com', 24 | id: 'c4a760a8-dbcf-4e14-9f39-645a8e933d74', 25 | name: 'John Doe', 26 | updatedAt: '2021-01-01T00:00:00.000Z', 27 | }; 28 | const badData = { 29 | age: '123', 30 | createdAt: '2021-01-01T00:00:00.000Z', 31 | email: 'john.doe@test.com', 32 | id: 'c4a760a8-dbcf-4e14-9f39-645a8e933d74', 33 | name: 'John Doe', 34 | updatedAt: '2021-01-01T00:00:00.000Z', 35 | }; 36 | 37 | test('infer', () => { 38 | expectTypeOf>().toEqualTypeOf(); 39 | expectTypeOf>().toEqualTypeOf(); 40 | }); 41 | 42 | test('validate', async () => { 43 | expect(await validate(schema, data)).toStrictEqual({ 44 | data, 45 | success: true, 46 | }); 47 | expect(await validate(schema, badData)).toStrictEqual({ 48 | issues: [{message: 'Not a number', path: ['age']}], 49 | success: false, 50 | }); 51 | }); 52 | 53 | test('assert', async () => { 54 | expect(await assert(schema, data)).toStrictEqual(data); 55 | await expect(assert(schema, badData)).rejects.toThrow(); 56 | }); 57 | 58 | test('wrap', async () => { 59 | const tRPC = initTRPC.create(); 60 | const router = tRPC.router({ 61 | hello: tRPC.procedure.input(wrap(schema)).query(({input}) => { 62 | expectTypeOf().toEqualTypeOf(); 63 | return input; 64 | }), 65 | }); 66 | const createCaller = tRPC.createCallerFactory(router); 67 | const caller = createCaller({}); 68 | expect(await caller.hello(data)).toStrictEqual(data); 69 | }); 70 | }); 71 | -------------------------------------------------------------------------------- /packages/deepkit/src/__tests__/example.ts: -------------------------------------------------------------------------------- 1 | import {typeOf} from '@deepkit/type'; 2 | import {initTRPC} from '@trpc/server'; 3 | 4 | import {wrap} from '..'; 5 | 6 | const schema = typeOf<{name: string}>(); 7 | 8 | const t = initTRPC.create(); 9 | const appRouter = t.router({ 10 | hello: t.procedure 11 | .input(wrap(schema)) 12 | .query(({input}) => `Hello, ${(input as any).name}!`), 13 | // ^? unknown 14 | }); 15 | -------------------------------------------------------------------------------- /packages/deepkit/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../../../tsconfig.test.json", 4 | "include": ["*.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/deepkit/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type { 6 | InputFrom, 7 | OutputFrom, 8 | SchemaFrom, 9 | UnknownIfNever, 10 | } from '@typeschema/core'; 11 | 12 | import { 13 | createAssert, 14 | createValidate, 15 | createWrap, 16 | } from '@typeschema/core'; 17 | 18 | import {AdapterResolver} from './resolver'; 19 | import {validationAdapter} from './validation'; 20 | 21 | export type Schema = SchemaFrom; 22 | export type Infer = UnknownIfNever< 23 | OutputFrom 24 | >; 25 | export type InferIn = UnknownIfNever< 26 | InputFrom 27 | >; 28 | 29 | export const validate = createValidate(validationAdapter); 30 | export const assert = createAssert(validate); 31 | export const wrap = createWrap(assert, validate); 32 | 33 | 34 | export { 35 | AdapterResolver, 36 | validationAdapter, 37 | }; 38 | -------------------------------------------------------------------------------- /packages/deepkit/src/resolver.ts: -------------------------------------------------------------------------------- 1 | import type {Type} from '@deepkit/type'; 2 | import type {IfDefined, Resolver} from '@typeschema/core'; 3 | 4 | export interface AdapterResolver extends Resolver { 5 | base: IfDefined; 6 | input: this['schema'] extends this['base'] ? unknown : never; 7 | output: this['schema'] extends this['base'] ? unknown : never; 8 | } 9 | -------------------------------------------------------------------------------- /packages/deepkit/src/validation.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {ValidationAdapter} from '@typeschema/core'; 3 | 4 | import {memoize} from '@typeschema/core'; 5 | 6 | const importValidationModule = memoize(async () => { 7 | const {validate} = await import('@deepkit/type'); 8 | return {validate}; 9 | }); 10 | 11 | export const validationAdapter: ValidationAdapter< 12 | AdapterResolver 13 | > = async schema => { 14 | const {validate} = await importValidationModule(); 15 | return async data => { 16 | const result = validate(data, schema); 17 | if (result.length === 0) { 18 | return { 19 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 20 | data: data as any, 21 | success: true, 22 | }; 23 | } 24 | return { 25 | issues: result.map(({message, path}) => ({message, path: [path]})), 26 | success: false, 27 | }; 28 | }; 29 | }; 30 | -------------------------------------------------------------------------------- /packages/deepkit/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/effect/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @typeschema/effect 2 | 3 | ## 0.14.0 4 | 5 | ### Minor Changes 6 | 7 | - 14976b2: Upgrade deps 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [2251f01] 12 | - Updated dependencies [14976b2] 13 | - @typeschema/core@0.14.0 14 | 15 | ## 0.13.4 16 | 17 | ### Patch Changes 18 | 19 | - 75dd140: Add serialization support to Effect 20 | - 8fa21a3: Upgrade dependencies 21 | 22 | ## 0.13.3 23 | 24 | ### Patch Changes 25 | 26 | - 6c178f0: Fix Vite support 27 | 28 | ## 0.13.2 29 | 30 | ### Patch Changes 31 | 32 | - 3087916: Improve handling missing types 33 | - Updated dependencies [3087916] 34 | - @typeschema/core@0.13.2 35 | 36 | ## 0.13.1 37 | 38 | ### Patch Changes 39 | 40 | - 6f1fc2d: Export the Schema type 41 | - Updated dependencies [6f1fc2d] 42 | - @typeschema/core@0.13.1 43 | 44 | ## 0.13.0 45 | 46 | ### Minor Changes 47 | 48 | - 05b430e: Package restructure 49 | 50 | ### Patch Changes 51 | 52 | - Updated dependencies [05b430e] 53 | - @typeschema/core@0.13.0 54 | -------------------------------------------------------------------------------- /packages/effect/src/__tests__/example.ts: -------------------------------------------------------------------------------- 1 | import * as S from '@effect/schema/Schema'; 2 | import {initTRPC} from '@trpc/server'; 3 | 4 | import {wrap} from '..'; 5 | 6 | const schema = S.struct({name: S.string}); 7 | 8 | const t = initTRPC.create(); 9 | const appRouter = t.router({ 10 | hello: t.procedure 11 | .input(wrap(schema)) 12 | .query(({input}) => `Hello, ${input.name}!`), 13 | // ^? {name: string} 14 | }); 15 | -------------------------------------------------------------------------------- /packages/effect/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../../../tsconfig.test.json", 4 | "include": ["*.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/effect/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type { 6 | InputFrom, 7 | OutputFrom, 8 | SchemaFrom, 9 | UnknownIfNever, 10 | } from '@typeschema/core'; 11 | 12 | import { 13 | createAssert, 14 | createValidate, 15 | createWrap, 16 | createToJSONSchema, 17 | } from '@typeschema/core'; 18 | 19 | import {AdapterResolver} from './resolver'; 20 | import {validationAdapter} from './validation'; 21 | import {serializationAdapter} from './serialization'; 22 | 23 | export type Schema = SchemaFrom; 24 | export type Infer = UnknownIfNever< 25 | OutputFrom 26 | >; 27 | export type InferIn = UnknownIfNever< 28 | InputFrom 29 | >; 30 | 31 | export const validate = createValidate(validationAdapter); 32 | export const assert = createAssert(validate); 33 | export const wrap = createWrap(assert, validate); 34 | 35 | export const toJSONSchema = createToJSONSchema(serializationAdapter); 36 | 37 | export { 38 | AdapterResolver, 39 | validationAdapter, 40 | serializationAdapter, 41 | }; 42 | -------------------------------------------------------------------------------- /packages/effect/src/resolver.ts: -------------------------------------------------------------------------------- 1 | import type {Schema} from '@effect/schema/Schema'; 2 | import type {IfDefined, Resolver} from '@typeschema/core'; 3 | 4 | export interface AdapterResolver extends Resolver { 5 | base: IfDefined; 6 | input: this['schema'] extends this['base'] 7 | ? Schema.Encoded 8 | : never; 9 | output: this['schema'] extends this['base'] 10 | ? Schema.Type 11 | : never; 12 | } 13 | -------------------------------------------------------------------------------- /packages/effect/src/serialization.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {SerializationAdapter} from '@typeschema/core'; 3 | 4 | import {memoize} from '@typeschema/core'; 5 | 6 | const importSerializationModule = memoize(async () => { 7 | const {make} = await import('@effect/schema/JSONSchema'); 8 | return {make}; 9 | }); 10 | 11 | export const serializationAdapter: SerializationAdapter< 12 | AdapterResolver 13 | > = async schema => { 14 | const {make} = await importSerializationModule(); 15 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 16 | return make(schema) as any; 17 | }; 18 | -------------------------------------------------------------------------------- /packages/effect/src/validation.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {ValidationAdapter} from '@typeschema/core'; 3 | 4 | import {memoize} from '@typeschema/core'; 5 | 6 | const importValidationModule = memoize(async () => { 7 | const { 8 | Effect: {runSync}, 9 | Either: {isRight}, 10 | } = await import('effect'); 11 | const { 12 | Schema: {decodeUnknownEither}, 13 | TreeFormatter: {formatError}, 14 | } = await import('@effect/schema'); 15 | return {decodeUnknownEither, formatError, isRight, runSync}; 16 | }); 17 | 18 | export const validationAdapter: ValidationAdapter< 19 | AdapterResolver 20 | > = async schema => { 21 | const {decodeUnknownEither, formatError, isRight, runSync} = 22 | await importValidationModule(); 23 | const parseSchema = decodeUnknownEither(schema); 24 | return async data => { 25 | const result = parseSchema(data); 26 | if (isRight(result)) { 27 | return { 28 | data: result.right, 29 | success: true, 30 | }; 31 | } 32 | return { 33 | issues: [{message: runSync(formatError(result.left))}], 34 | success: false, 35 | }; 36 | }; 37 | }; 38 | -------------------------------------------------------------------------------- /packages/effect/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/fastest-validator/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @typeschema/fastest-validator 2 | 3 | ## 0.2.0 4 | 5 | ### Minor Changes 6 | 7 | - 14976b2: Upgrade deps 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [2251f01] 12 | - Updated dependencies [14976b2] 13 | - @typeschema/core@0.14.0 14 | 15 | ## 0.1.0 16 | 17 | ### Minor Changes 18 | 19 | - a7c09b6: feat: add support to fastest-validator 20 | -------------------------------------------------------------------------------- /packages/fastest-validator/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | TypeSchema 4 |

@typeschema/fastest-validator

5 |

6 | License 7 | Bundle size 8 | npm downloads 9 | GitHub stars 10 |

11 |

12 | Reusable adapter for fastest-validator schemas 13 |
14 | https://typeschema.com ✨ 15 |

16 | 17 | ```ts 18 | import {initTRPC} from '@trpc/server'; 19 | 20 | import {wrap} from '@typeschema/fastest-validator'; 21 | 22 | const schema = {name: 'string'}; 23 | 24 | const t = initTRPC.create(); 25 | const appRouter = t.router({ 26 | hello: t.procedure 27 | .input(wrap(schema)) 28 | .query(({input}) => `Hello, ${(input as any).name}!`), 29 | // ^? unknown 30 | }); 31 | 32 | ``` 33 | 34 | Use it directly or through [`@typeschema/main`](https://github.com/decs/typeschema/tree/main/packages/main) 35 | 36 | ## Dependencies 37 | - [`fastest-validator`](https://www.npmjs.com/package/fastest-validator): (`^1.19.0`) 38 | 39 | ## API 40 | 41 | ### Validation 42 | - `wrap(schema)`: Returns the wrapped schema with access to its operations 43 | - `validate(schema, data)`: Returns the validated data or a list of validation issues 44 | - `assert(schema, data)`: Returns the validated data or throws an `AggregateError` 45 | -------------------------------------------------------------------------------- /packages/fastest-validator/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is partially generated. Only some fields can be modified manually!", 3 | "name": "@typeschema/fastest-validator", 4 | "//version": "This field is manually maintained.", 5 | "version": "0.2.0", 6 | "//description": "This field is manually maintained.", 7 | "description": "Reusable adapter for fastest-validator schemas", 8 | "keywords": [ 9 | "typescript", 10 | "type", 11 | "schema", 12 | "adapter", 13 | "validation", 14 | "inference", 15 | "assert" 16 | ], 17 | "homepage": "https://typeschema.com", 18 | "license": "MIT", 19 | "author": { 20 | "name": "André Costa", 21 | "email": "andrefonsecacosta@gmail.com" 22 | }, 23 | "publishConfig": { 24 | "access": "public", 25 | "registry": "https://registry.npmjs.org/" 26 | }, 27 | "files": [ 28 | "/dist" 29 | ], 30 | "main": "dist/index.js", 31 | "module": "dist/index.mjs", 32 | "types": "dist/index.d.ts", 33 | "exports": { 34 | ".": { 35 | "import": { 36 | "types": "./dist/index.d.mts", 37 | "default": "./dist/index.mjs" 38 | }, 39 | "require": { 40 | "types": "./dist/index.d.ts", 41 | "default": "./dist/index.js" 42 | } 43 | } 44 | }, 45 | "sideEffects": false, 46 | "repository": { 47 | "type": "git", 48 | "url": "https://github.com/decs/typeschema.git" 49 | }, 50 | "scripts": { 51 | "build": "tsup --config ../../tsup.config.ts", 52 | "lint": "eslint src --fix", 53 | "lint:package": "publint && attw --pack", 54 | "test": "vitest --config ../../vitest.config.ts", 55 | "upgrade:deps": "ncu -u --dep=dev,peer --reject ow" 56 | }, 57 | "dependencies": { 58 | "@typeschema/core": "workspace:*" 59 | }, 60 | "//devDependencies": "This field is manually maintained.", 61 | "devDependencies": { 62 | "fastest-validator": "^1.19.0" 63 | }, 64 | "//peerDependencies": "This field is manually maintained.", 65 | "peerDependencies": { 66 | "fastest-validator": "^1.19.0" 67 | }, 68 | "//peerDependenciesMeta": "This field is manually maintained.", 69 | "peerDependenciesMeta": { 70 | "fastest-validator": { 71 | "optional": true 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /packages/fastest-validator/src/__tests__/example.ts: -------------------------------------------------------------------------------- 1 | import {initTRPC} from '@trpc/server'; 2 | 3 | import {wrap} from '..'; 4 | 5 | const schema = {name: 'string'}; 6 | 7 | const t = initTRPC.create(); 8 | const appRouter = t.router({ 9 | hello: t.procedure 10 | .input(wrap(schema)) 11 | .query(({input}) => `Hello, ${(input as any).name}!`), 12 | // ^? unknown 13 | }); 14 | -------------------------------------------------------------------------------- /packages/fastest-validator/src/__tests__/fastest-validator.test.ts: -------------------------------------------------------------------------------- 1 | import type {Infer, InferIn} from '..'; 2 | 3 | import {initTRPC} from '@trpc/server'; 4 | import {expectTypeOf} from 'expect-type'; 5 | import {describe, expect, test} from 'vitest'; 6 | 7 | import {assert, validate, wrap} from '..'; 8 | 9 | describe('fastest-validator', () => { 10 | const schema = { 11 | age: 'number', 12 | createdAt: 'string', 13 | email: 'string', 14 | id: 'string', 15 | name: 'string', 16 | updatedAt: 'string', 17 | }; 18 | 19 | const data = { 20 | age: 123, 21 | createdAt: '2021-01-01T00:00:00.000Z', 22 | email: 'john.doe@test.com', 23 | id: 'c4a760a8-dbcf-4e14-9f39-645a8e933d74', 24 | name: 'John Doe', 25 | updatedAt: '2021-01-01T00:00:00.000Z', 26 | }; 27 | const badData = { 28 | age: '123', 29 | createdAt: '2021-01-01T00:00:00.000Z', 30 | email: 'john.doe@test.com', 31 | id: 'c4a760a8-dbcf-4e14-9f39-645a8e933d74', 32 | name: 'John Doe', 33 | updatedAt: '2021-01-01T00:00:00.000Z', 34 | }; 35 | 36 | test('infer', () => { 37 | expectTypeOf>().toEqualTypeOf(); 38 | expectTypeOf>().toEqualTypeOf(); 39 | }); 40 | 41 | test('validate', async () => { 42 | expect(await validate(schema, data)).toStrictEqual({data, success: true}); 43 | expect(await validate(schema, badData)).toStrictEqual({ 44 | issues: [{message: "The 'age' field must be a number.", path: ['age']}], 45 | success: false, 46 | }); 47 | }); 48 | 49 | test('assert', async () => { 50 | expect(await assert(schema, data)).toStrictEqual(data); 51 | await expect(assert(schema, badData)).rejects.toThrow(); 52 | }); 53 | 54 | test('wrap', async () => { 55 | const tRPC = initTRPC.create(); 56 | const router = tRPC.router({ 57 | hello: tRPC.procedure.input(wrap(schema)).query(({input}) => { 58 | expectTypeOf().toEqualTypeOf(); 59 | return input; 60 | }), 61 | }); 62 | const createCaller = tRPC.createCallerFactory(router); 63 | const caller = createCaller({}); 64 | expect(await caller.hello(data)).toStrictEqual(data); 65 | }); 66 | }); 67 | -------------------------------------------------------------------------------- /packages/fastest-validator/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../../../tsconfig.test.json", 4 | "include": ["*.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/fastest-validator/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type { 6 | InputFrom, 7 | OutputFrom, 8 | SchemaFrom, 9 | UnknownIfNever, 10 | } from '@typeschema/core'; 11 | 12 | import { 13 | createAssert, 14 | createValidate, 15 | createWrap, 16 | } from '@typeschema/core'; 17 | 18 | import {AdapterResolver} from './resolver'; 19 | import {validationAdapter} from './validation'; 20 | 21 | export type Schema = SchemaFrom; 22 | export type Infer = UnknownIfNever< 23 | OutputFrom 24 | >; 25 | export type InferIn = UnknownIfNever< 26 | InputFrom 27 | >; 28 | 29 | export const validate = createValidate(validationAdapter); 30 | export const assert = createAssert(validate); 31 | export const wrap = createWrap(assert, validate); 32 | 33 | 34 | export { 35 | AdapterResolver, 36 | validationAdapter, 37 | }; 38 | -------------------------------------------------------------------------------- /packages/fastest-validator/src/resolver.ts: -------------------------------------------------------------------------------- 1 | import type {IfDefined, Resolver} from '@typeschema/core'; 2 | import type {ValidationSchema} from 'fastest-validator'; 3 | 4 | export interface AdapterResolver extends Resolver { 5 | base: IfDefined; 6 | input: this['schema'] extends this['base'] ? unknown : never; 7 | output: this['schema'] extends this['base'] ? unknown : never; 8 | } 9 | -------------------------------------------------------------------------------- /packages/fastest-validator/src/validation.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {ValidationAdapter} from '@typeschema/core'; 3 | 4 | import {memoize} from '@typeschema/core'; 5 | 6 | const importValidationModule = memoize(async () => { 7 | const {default: FastestValidator} = await import('fastest-validator'); 8 | return new FastestValidator(); 9 | }); 10 | 11 | export const validationAdapter: ValidationAdapter< 12 | AdapterResolver 13 | > = async schema => { 14 | const fastestValidator = await importValidationModule(); 15 | const validateSchema = fastestValidator.compile(schema); 16 | return async data => { 17 | const result = await validateSchema(data); 18 | if (result === true) { 19 | return { 20 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 21 | data: data as any, 22 | success: true, 23 | }; 24 | } 25 | return { 26 | issues: result.map(({message, field}) => ({ 27 | message: message ?? '', 28 | path: [field], 29 | })), 30 | success: false, 31 | }; 32 | }; 33 | }; 34 | -------------------------------------------------------------------------------- /packages/fastest-validator/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/function/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @typeschema/function 2 | 3 | ## 0.14.0 4 | 5 | ### Minor Changes 6 | 7 | - 14976b2: Upgrade deps 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [2251f01] 12 | - Updated dependencies [14976b2] 13 | - @typeschema/core@0.14.0 14 | 15 | ## 0.13.2 16 | 17 | ### Patch Changes 18 | 19 | - Updated dependencies [3087916] 20 | - @typeschema/core@0.13.2 21 | 22 | ## 0.13.1 23 | 24 | ### Patch Changes 25 | 26 | - 6f1fc2d: Export the Schema type 27 | - Updated dependencies [6f1fc2d] 28 | - @typeschema/core@0.13.1 29 | 30 | ## 0.13.0 31 | 32 | ### Minor Changes 33 | 34 | - 05b430e: Package restructure 35 | 36 | ### Patch Changes 37 | 38 | - Updated dependencies [05b430e] 39 | - @typeschema/core@0.13.0 40 | -------------------------------------------------------------------------------- /packages/function/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | TypeSchema 4 |

@typeschema/function

5 |

6 | License 7 | Bundle size 8 | npm downloads 9 | GitHub stars 10 |

11 |

12 | Reusable adapter for function-based schemas 13 |
14 | https://typeschema.com ✨ 15 |

16 | 17 | ```ts 18 | import {initTRPC} from '@trpc/server'; 19 | import typia from 'typia'; 20 | 21 | import {wrap} from '@typeschema/function'; 22 | 23 | const schema = typia.createAssert<{name: string}>(); 24 | 25 | const t = initTRPC.create(); 26 | const appRouter = t.router({ 27 | hello: t.procedure 28 | .input(wrap(schema)) 29 | .query(({input}) => `Hello, ${input.name}!`), 30 | // ^? {name: string} 31 | }); 32 | 33 | ``` 34 | 35 | Use it directly or through [`@typeschema/main`](https://github.com/decs/typeschema/tree/main/packages/main) 36 | 37 | ## API 38 | 39 | ### Inference 40 | - `Infer`: Extracts the output type of a schema 41 | - `InferIn`: Extracts the input type of a schema 42 | 43 | ### Validation 44 | - `wrap(schema)`: Returns the wrapped schema with access to its operations 45 | - `validate(schema, data)`: Returns the validated data or a list of validation issues 46 | - `assert(schema, data)`: Returns the validated data or throws an `AggregateError` 47 | -------------------------------------------------------------------------------- /packages/function/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is partially generated. Only some fields can be modified manually!", 3 | "name": "@typeschema/function", 4 | "//version": "This field is manually maintained.", 5 | "version": "0.14.0", 6 | "//description": "This field is manually maintained.", 7 | "description": "Reusable adapter for function-based schemas", 8 | "keywords": [ 9 | "typescript", 10 | "type", 11 | "schema", 12 | "adapter", 13 | "validation", 14 | "inference", 15 | "assert" 16 | ], 17 | "homepage": "https://typeschema.com", 18 | "license": "MIT", 19 | "author": { 20 | "name": "André Costa", 21 | "email": "andrefonsecacosta@gmail.com" 22 | }, 23 | "publishConfig": { 24 | "access": "public", 25 | "registry": "https://registry.npmjs.org/" 26 | }, 27 | "files": [ 28 | "/dist" 29 | ], 30 | "main": "dist/index.js", 31 | "module": "dist/index.mjs", 32 | "types": "dist/index.d.ts", 33 | "exports": { 34 | ".": { 35 | "import": { 36 | "types": "./dist/index.d.mts", 37 | "default": "./dist/index.mjs" 38 | }, 39 | "require": { 40 | "types": "./dist/index.d.ts", 41 | "default": "./dist/index.js" 42 | } 43 | } 44 | }, 45 | "sideEffects": false, 46 | "repository": { 47 | "type": "git", 48 | "url": "https://github.com/decs/typeschema.git" 49 | }, 50 | "scripts": { 51 | "build": "tsup --config ../../tsup.config.ts", 52 | "lint": "eslint src --fix", 53 | "lint:package": "publint && attw --pack", 54 | "test": "vitest --config ../../vitest.config.ts", 55 | "upgrade:deps": "ncu -u --dep=dev,peer --reject ow" 56 | }, 57 | "dependencies": { 58 | "@typeschema/core": "workspace:*" 59 | }, 60 | "//devDependencies": "This field is manually maintained.", 61 | "devDependencies": { 62 | "typia": "^6.9.0" 63 | }, 64 | "//peerDependencies": "This field is manually maintained.", 65 | "peerDependencies": {}, 66 | "//peerDependenciesMeta": "This field is manually maintained.", 67 | "peerDependenciesMeta": {} 68 | } 69 | -------------------------------------------------------------------------------- /packages/function/src/__tests__/example.ts: -------------------------------------------------------------------------------- 1 | import {initTRPC} from '@trpc/server'; 2 | import typia from 'typia'; 3 | 4 | import {wrap} from '..'; 5 | 6 | const schema = typia.createAssert<{name: string}>(); 7 | 8 | const t = initTRPC.create(); 9 | const appRouter = t.router({ 10 | hello: t.procedure 11 | .input(wrap(schema)) 12 | .query(({input}) => `Hello, ${input.name}!`), 13 | // ^? {name: string} 14 | }); 15 | -------------------------------------------------------------------------------- /packages/function/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../../../tsconfig.test.json", 4 | "include": ["*.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/function/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type { 6 | InputFrom, 7 | OutputFrom, 8 | SchemaFrom, 9 | UnknownIfNever, 10 | } from '@typeschema/core'; 11 | 12 | import { 13 | createAssert, 14 | createValidate, 15 | createWrap, 16 | } from '@typeschema/core'; 17 | 18 | import {AdapterResolver} from './resolver'; 19 | import {validationAdapter} from './validation'; 20 | 21 | export type Schema = SchemaFrom; 22 | export type Infer = UnknownIfNever< 23 | OutputFrom 24 | >; 25 | export type InferIn = UnknownIfNever< 26 | InputFrom 27 | >; 28 | 29 | export const validate = createValidate(validationAdapter); 30 | export const assert = createAssert(validate); 31 | export const wrap = createWrap(assert, validate); 32 | 33 | 34 | export { 35 | AdapterResolver, 36 | validationAdapter, 37 | }; 38 | -------------------------------------------------------------------------------- /packages/function/src/resolver.ts: -------------------------------------------------------------------------------- 1 | import type {Resolver} from '@typeschema/core'; 2 | 3 | type FunctionSchema = (data: unknown) => Promise | T; 4 | 5 | export interface AdapterResolver extends Resolver { 6 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 7 | base: FunctionSchema; 8 | input: this['schema'] extends this['base'] 9 | ? keyof this['schema'] extends never 10 | ? Awaited> 11 | : never 12 | : never; 13 | output: this['schema'] extends this['base'] 14 | ? keyof this['schema'] extends never 15 | ? Awaited> 16 | : never 17 | : never; 18 | } 19 | -------------------------------------------------------------------------------- /packages/function/src/validation.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {ValidationAdapter} from '@typeschema/core'; 3 | 4 | export const validationAdapter: ValidationAdapter< 5 | AdapterResolver 6 | > = async schema => { 7 | return async data => { 8 | try { 9 | return { 10 | data: await schema(data), 11 | success: true, 12 | }; 13 | } catch (error) { 14 | if (error instanceof Error) { 15 | return { 16 | issues: [{message: error.message}], 17 | success: false, 18 | }; 19 | } 20 | throw error; 21 | } 22 | }; 23 | }; 24 | -------------------------------------------------------------------------------- /packages/function/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/io-ts/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @typeschema/io-ts 2 | 3 | ## 0.14.0 4 | 5 | ### Minor Changes 6 | 7 | - 14976b2: Upgrade deps 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [2251f01] 12 | - Updated dependencies [14976b2] 13 | - @typeschema/core@0.14.0 14 | 15 | ## 0.13.3 16 | 17 | ### Patch Changes 18 | 19 | - 6c178f0: Fix Vite support 20 | 21 | ## 0.13.2 22 | 23 | ### Patch Changes 24 | 25 | - 3087916: Improve handling missing types 26 | - Updated dependencies [3087916] 27 | - @typeschema/core@0.13.2 28 | 29 | ## 0.13.1 30 | 31 | ### Patch Changes 32 | 33 | - 6f1fc2d: Export the Schema type 34 | - Updated dependencies [6f1fc2d] 35 | - @typeschema/core@0.13.1 36 | 37 | ## 0.13.0 38 | 39 | ### Minor Changes 40 | 41 | - 05b430e: Package restructure 42 | 43 | ### Patch Changes 44 | 45 | - Updated dependencies [05b430e] 46 | - @typeschema/core@0.13.0 47 | -------------------------------------------------------------------------------- /packages/io-ts/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | TypeSchema 4 |

@typeschema/io-ts

5 |

6 | License 7 | Bundle size 8 | npm downloads 9 | GitHub stars 10 |

11 |

12 | Reusable adapter for io-ts schemas 13 |
14 | https://typeschema.com ✨ 15 |

16 | 17 | ```ts 18 | import {initTRPC} from '@trpc/server'; 19 | import * as ioTs from 'io-ts'; 20 | 21 | import {wrap} from '@typeschema/io-ts'; 22 | 23 | const schema = ioTs.type({name: ioTs.string}); 24 | 25 | const t = initTRPC.create(); 26 | const appRouter = t.router({ 27 | hello: t.procedure 28 | .input(wrap(schema)) 29 | .query(({input}) => `Hello, ${input.name}!`), 30 | // ^? {name: string} 31 | }); 32 | 33 | ``` 34 | 35 | Use it directly or through [`@typeschema/main`](https://github.com/decs/typeschema/tree/main/packages/main) 36 | 37 | ## Dependencies 38 | - [`fp-ts`](https://www.npmjs.com/package/fp-ts): Required for inference and validation (`^2.16.9`) 39 | - [`io-ts`](https://www.npmjs.com/package/io-ts): Required for inference and validation (`^2.2.21`) 40 | 41 | ## API 42 | 43 | ### Inference 44 | - `Infer`: Extracts the output type of a schema 45 | - `InferIn`: Extracts the input type of a schema 46 | 47 | ### Validation 48 | - `wrap(schema)`: Returns the wrapped schema with access to its operations 49 | - `validate(schema, data)`: Returns the validated data or a list of validation issues 50 | - `assert(schema, data)`: Returns the validated data or throws an `AggregateError` 51 | -------------------------------------------------------------------------------- /packages/io-ts/src/__tests__/example.ts: -------------------------------------------------------------------------------- 1 | import {initTRPC} from '@trpc/server'; 2 | import * as ioTs from 'io-ts'; 3 | 4 | import {wrap} from '..'; 5 | 6 | const schema = ioTs.type({name: ioTs.string}); 7 | 8 | const t = initTRPC.create(); 9 | const appRouter = t.router({ 10 | hello: t.procedure 11 | .input(wrap(schema)) 12 | .query(({input}) => `Hello, ${input.name}!`), 13 | // ^? {name: string} 14 | }); 15 | -------------------------------------------------------------------------------- /packages/io-ts/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../../../tsconfig.test.json", 4 | "include": ["*.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/io-ts/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type { 6 | InputFrom, 7 | OutputFrom, 8 | SchemaFrom, 9 | UnknownIfNever, 10 | } from '@typeschema/core'; 11 | 12 | import { 13 | createAssert, 14 | createValidate, 15 | createWrap, 16 | } from '@typeschema/core'; 17 | 18 | import {AdapterResolver} from './resolver'; 19 | import {validationAdapter} from './validation'; 20 | 21 | export type Schema = SchemaFrom; 22 | export type Infer = UnknownIfNever< 23 | OutputFrom 24 | >; 25 | export type InferIn = UnknownIfNever< 26 | InputFrom 27 | >; 28 | 29 | export const validate = createValidate(validationAdapter); 30 | export const assert = createAssert(validate); 31 | export const wrap = createWrap(assert, validate); 32 | 33 | 34 | export { 35 | AdapterResolver, 36 | validationAdapter, 37 | }; 38 | -------------------------------------------------------------------------------- /packages/io-ts/src/resolver.ts: -------------------------------------------------------------------------------- 1 | import type {IfDefined, Resolver} from '@typeschema/core'; 2 | import type {Any, OutputOf, TypeOf} from 'io-ts'; 3 | 4 | export interface AdapterResolver extends Resolver { 5 | base: IfDefined; 6 | input: this['schema'] extends this['base'] ? OutputOf : never; 7 | output: this['schema'] extends this['base'] ? TypeOf : never; 8 | } 9 | -------------------------------------------------------------------------------- /packages/io-ts/src/validation.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {ValidationAdapter} from '@typeschema/core'; 3 | 4 | import {memoize} from '@typeschema/core'; 5 | 6 | const importValidationModule = memoize(async () => { 7 | const {isRight} = await import('fp-ts/Either'); 8 | return {isRight}; 9 | }); 10 | 11 | export const validationAdapter: ValidationAdapter< 12 | AdapterResolver 13 | > = async schema => { 14 | const {isRight} = await importValidationModule(); 15 | return async data => { 16 | const result = schema.decode(data); 17 | if (isRight(result)) { 18 | return { 19 | data: result.right, 20 | success: true, 21 | }; 22 | } 23 | return { 24 | issues: result.left.map(({message, context}) => ({ 25 | message: message ?? '', 26 | path: context.map(({key}) => key), 27 | })), 28 | success: false, 29 | }; 30 | }; 31 | }; 32 | -------------------------------------------------------------------------------- /packages/io-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/joi/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @typeschema/joi 2 | 3 | ## 0.14.0 4 | 5 | ### Minor Changes 6 | 7 | - 14976b2: Upgrade deps 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [2251f01] 12 | - Updated dependencies [14976b2] 13 | - @typeschema/core@0.14.0 14 | 15 | ## 0.13.3 16 | 17 | ### Patch Changes 18 | 19 | - 2cb436f: Add serialization support to Joi 20 | - 8fa21a3: Upgrade dependencies 21 | 22 | ## 0.13.2 23 | 24 | ### Patch Changes 25 | 26 | - 3087916: Improve handling missing types 27 | - Updated dependencies [3087916] 28 | - @typeschema/core@0.13.2 29 | 30 | ## 0.13.1 31 | 32 | ### Patch Changes 33 | 34 | - 6f1fc2d: Export the Schema type 35 | - Updated dependencies [6f1fc2d] 36 | - @typeschema/core@0.13.1 37 | 38 | ## 0.13.0 39 | 40 | ### Minor Changes 41 | 42 | - 05b430e: Package restructure 43 | 44 | ### Patch Changes 45 | 46 | - Updated dependencies [05b430e] 47 | - @typeschema/core@0.13.0 48 | -------------------------------------------------------------------------------- /packages/joi/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | TypeSchema 4 |

@typeschema/joi

5 |

6 | License 7 | Bundle size 8 | npm downloads 9 | GitHub stars 10 |

11 |

12 | Reusable adapter for Joi schemas 13 |
14 | https://typeschema.com ✨ 15 |

16 | 17 | ```ts 18 | import {initTRPC} from '@trpc/server'; 19 | import Joi from 'joi'; 20 | 21 | import {wrap} from '@typeschema/joi'; 22 | 23 | const schema = Joi.object({name: Joi.string().required()}); 24 | 25 | const t = initTRPC.create(); 26 | const appRouter = t.router({ 27 | hello: t.procedure 28 | .input(wrap(schema)) 29 | .query(({input}) => `Hello, ${(input as any).name}!`), 30 | // ^? unknown 31 | }); 32 | 33 | ``` 34 | 35 | Use it directly or through [`@typeschema/main`](https://github.com/decs/typeschema/tree/main/packages/main) 36 | 37 | ## Dependencies 38 | - [`joi`](https://www.npmjs.com/package/joi): Required for validation (`^17.13.3`) 39 | - [`joi-to-json`](https://www.npmjs.com/package/joi-to-json): Required for serialization (`^4.3.0`) 40 | 41 | ## API 42 | 43 | ### Validation 44 | - `wrap(schema)`: Returns the wrapped schema with access to its operations 45 | - `validate(schema, data)`: Returns the validated data or a list of validation issues 46 | - `assert(schema, data)`: Returns the validated data or throws an `AggregateError` 47 | 48 | ### Serialization 49 | - `toJSONSchema(schema)`: Converts the schema into the equivalent JSON schema 50 | -------------------------------------------------------------------------------- /packages/joi/src/__tests__/example.ts: -------------------------------------------------------------------------------- 1 | import {initTRPC} from '@trpc/server'; 2 | import Joi from 'joi'; 3 | 4 | import {wrap} from '..'; 5 | 6 | const schema = Joi.object({name: Joi.string().required()}); 7 | 8 | const t = initTRPC.create(); 9 | const appRouter = t.router({ 10 | hello: t.procedure 11 | .input(wrap(schema)) 12 | .query(({input}) => `Hello, ${(input as any).name}!`), 13 | // ^? unknown 14 | }); 15 | -------------------------------------------------------------------------------- /packages/joi/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../../../tsconfig.test.json", 4 | "include": ["*.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/joi/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type { 6 | InputFrom, 7 | OutputFrom, 8 | SchemaFrom, 9 | UnknownIfNever, 10 | } from '@typeschema/core'; 11 | 12 | import { 13 | createAssert, 14 | createValidate, 15 | createWrap, 16 | createToJSONSchema, 17 | } from '@typeschema/core'; 18 | 19 | import {AdapterResolver} from './resolver'; 20 | import {validationAdapter} from './validation'; 21 | import {serializationAdapter} from './serialization'; 22 | 23 | export type Schema = SchemaFrom; 24 | export type Infer = UnknownIfNever< 25 | OutputFrom 26 | >; 27 | export type InferIn = UnknownIfNever< 28 | InputFrom 29 | >; 30 | 31 | export const validate = createValidate(validationAdapter); 32 | export const assert = createAssert(validate); 33 | export const wrap = createWrap(assert, validate); 34 | 35 | export const toJSONSchema = createToJSONSchema(serializationAdapter); 36 | 37 | export { 38 | AdapterResolver, 39 | validationAdapter, 40 | serializationAdapter, 41 | }; 42 | -------------------------------------------------------------------------------- /packages/joi/src/resolver.ts: -------------------------------------------------------------------------------- 1 | import type {IfDefined, Resolver} from '@typeschema/core'; 2 | import type {AnySchema} from 'joi'; 3 | 4 | export interface AdapterResolver extends Resolver { 5 | base: IfDefined; 6 | input: this['schema'] extends this['base'] ? unknown : never; 7 | output: this['schema'] extends this['base'] ? unknown : never; 8 | } 9 | -------------------------------------------------------------------------------- /packages/joi/src/serialization.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {SerializationAdapter} from '@typeschema/core'; 3 | 4 | import {memoize} from '@typeschema/core'; 5 | 6 | const importSerializationModule = memoize(async () => { 7 | const {default: parse} = await import('joi-to-json'); 8 | return {parse}; 9 | }); 10 | 11 | export const serializationAdapter: SerializationAdapter< 12 | AdapterResolver 13 | > = async schema => { 14 | const {parse} = await importSerializationModule(); 15 | return parse(schema); 16 | }; 17 | -------------------------------------------------------------------------------- /packages/joi/src/validation.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {ValidationAdapter} from '@typeschema/core'; 3 | 4 | export const validationAdapter: ValidationAdapter< 5 | AdapterResolver 6 | > = async schema => { 7 | return async data => { 8 | const result = schema.validate(data); 9 | if (result.error == null) { 10 | return { 11 | data: result.value, 12 | success: true, 13 | }; 14 | } 15 | return { 16 | issues: result.error.details.map(({message, path}) => ({ 17 | message, 18 | path, 19 | })), 20 | success: false, 21 | }; 22 | }; 23 | }; 24 | -------------------------------------------------------------------------------- /packages/joi/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/json/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @typeschema/json 2 | 3 | ## 0.14.0 4 | 5 | ### Minor Changes 6 | 7 | - 14976b2: Upgrade deps 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [2251f01] 12 | - Updated dependencies [14976b2] 13 | - @typeschema/core@0.14.0 14 | 15 | ## 0.13.3 16 | 17 | ### Patch Changes 18 | 19 | - 6c178f0: Fix Vite support 20 | 21 | ## 0.13.2 22 | 23 | ### Patch Changes 24 | 25 | - 3087916: Add support for type inference 26 | - 3087916: Improve handling missing types 27 | - Updated dependencies [3087916] 28 | - @typeschema/core@0.13.2 29 | 30 | ## 0.13.1 31 | 32 | ### Patch Changes 33 | 34 | - 6f1fc2d: Export the Schema type 35 | - Updated dependencies [6f1fc2d] 36 | - @typeschema/core@0.13.1 37 | 38 | ## 0.13.0 39 | 40 | ### Minor Changes 41 | 42 | - 05b430e: Package restructure 43 | 44 | ### Patch Changes 45 | 46 | - Updated dependencies [05b430e] 47 | - @typeschema/core@0.13.0 48 | -------------------------------------------------------------------------------- /packages/json/src/__tests__/example.ts: -------------------------------------------------------------------------------- 1 | import {initTRPC} from '@trpc/server'; 2 | 3 | import {wrap} from '..'; 4 | 5 | const schema = { 6 | additionalProperties: false, 7 | properties: {name: {type: 'string'}}, 8 | required: ['name'], 9 | type: 'object', 10 | } as const; 11 | 12 | const t = initTRPC.create(); 13 | const appRouter = t.router({ 14 | hello: t.procedure 15 | .input(wrap(schema)) 16 | .query(({input}) => `Hello, ${(input as any).name}!`), 17 | // ^? {name: string} 18 | }); 19 | -------------------------------------------------------------------------------- /packages/json/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../../../tsconfig.test.json", 4 | "include": ["*.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/json/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type { 6 | InputFrom, 7 | OutputFrom, 8 | SchemaFrom, 9 | UnknownIfNever, 10 | } from '@typeschema/core'; 11 | 12 | import { 13 | createAssert, 14 | createValidate, 15 | createWrap, 16 | createToJSONSchema, 17 | } from '@typeschema/core'; 18 | 19 | import {AdapterResolver} from './resolver'; 20 | import {validationAdapter} from './validation'; 21 | import {serializationAdapter} from './serialization'; 22 | 23 | export type Schema = SchemaFrom; 24 | export type Infer = UnknownIfNever< 25 | OutputFrom 26 | >; 27 | export type InferIn = UnknownIfNever< 28 | InputFrom 29 | >; 30 | 31 | export const validate = createValidate(validationAdapter); 32 | export const assert = createAssert(validate); 33 | export const wrap = createWrap(assert, validate); 34 | 35 | export const toJSONSchema = createToJSONSchema(serializationAdapter); 36 | 37 | export { 38 | AdapterResolver, 39 | validationAdapter, 40 | serializationAdapter, 41 | }; 42 | -------------------------------------------------------------------------------- /packages/json/src/resolver.ts: -------------------------------------------------------------------------------- 1 | import type {IfDefined, Resolver} from '@typeschema/core'; 2 | import type {SchemaObject} from 'ajv'; 3 | import type {FromSchema} from 'json-schema-to-ts'; 4 | 5 | export interface AdapterResolver extends Resolver { 6 | base: IfDefined; 7 | input: this['schema'] extends this['base'] 8 | ? IfDefined, 'json-schema-to-ts'> 9 | : never; 10 | output: this['schema'] extends this['base'] 11 | ? IfDefined, 'json-schema-to-ts'> 12 | : never; 13 | } 14 | -------------------------------------------------------------------------------- /packages/json/src/serialization.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {SerializationAdapter} from '@typeschema/core'; 3 | 4 | export const serializationAdapter: SerializationAdapter< 5 | AdapterResolver 6 | > = async schema => schema; 7 | -------------------------------------------------------------------------------- /packages/json/src/validation.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {ValidationAdapter} from '@typeschema/core'; 3 | 4 | import {memoize} from '@typeschema/core'; 5 | 6 | const importValidationModule = memoize(async () => { 7 | const {default: Ajv} = await import('ajv'); 8 | return new Ajv(); 9 | }); 10 | 11 | export const validationAdapter: ValidationAdapter< 12 | AdapterResolver 13 | > = async schema => { 14 | const ajv = await importValidationModule(); 15 | const validateSchema = ajv.compile(schema); 16 | return async data => { 17 | if (validateSchema(data)) { 18 | return { 19 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 20 | data: data as any, 21 | success: true, 22 | }; 23 | } 24 | return { 25 | issues: (validateSchema.errors ?? []).map(({message, schemaPath}) => ({ 26 | message: message ?? '', 27 | path: [schemaPath], 28 | })), 29 | success: false, 30 | }; 31 | }; 32 | }; 33 | -------------------------------------------------------------------------------- /packages/json/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/main/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | TypeSchema 4 |

@typeschema/main

5 |

6 | License 7 | Bundle size 8 | npm downloads 9 | GitHub stars 10 |

11 |

12 | Universal adapter for schema validation 13 |
14 | https://typeschema.com ✨ 15 |

16 | 17 | ## API 18 | 19 | ### Inference 20 | - `Infer`: Extracts the output type of a schema 21 | - `InferIn`: Extracts the input type of a schema 22 | 23 | ### Validation 24 | - `wrap(schema)`: Returns the wrapped schema with access to its operations 25 | - `validate(schema, data)`: Returns the validated data or a list of validation issues 26 | - `assert(schema, data)`: Returns the validated data or throws an `AggregateError` 27 | 28 | ### Serialization 29 | - `toJSONSchema(schema)`: Converts the schema into the equivalent JSON schema 30 | -------------------------------------------------------------------------------- /packages/main/src/__tests__/fastest-validator.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type {Infer, InferIn} from '..'; 6 | 7 | import {initTRPC} from '@trpc/server'; 8 | import {expectTypeOf} from 'expect-type'; 9 | import {describe, expect, test} from 'vitest'; 10 | 11 | import {assert, validate, wrap} from '..'; 12 | 13 | describe('fastest-validator', () => { 14 | const schema = { 15 | age: 'number', 16 | createdAt: 'string', 17 | email: 'string', 18 | id: 'string', 19 | name: 'string', 20 | updatedAt: 'string', 21 | }; 22 | 23 | const data = { 24 | age: 123, 25 | createdAt: '2021-01-01T00:00:00.000Z', 26 | email: 'john.doe@test.com', 27 | id: 'c4a760a8-dbcf-4e14-9f39-645a8e933d74', 28 | name: 'John Doe', 29 | updatedAt: '2021-01-01T00:00:00.000Z', 30 | }; 31 | const badData = { 32 | age: '123', 33 | createdAt: '2021-01-01T00:00:00.000Z', 34 | email: 'john.doe@test.com', 35 | id: 'c4a760a8-dbcf-4e14-9f39-645a8e933d74', 36 | name: 'John Doe', 37 | updatedAt: '2021-01-01T00:00:00.000Z', 38 | }; 39 | 40 | test('infer', () => { 41 | expectTypeOf>().toEqualTypeOf(); 42 | expectTypeOf>().toEqualTypeOf(); 43 | }); 44 | 45 | test('validate', async () => { 46 | expect(await validate(schema, data)).toStrictEqual({data, success: true}); 47 | expect(await validate(schema, badData)).toStrictEqual({ 48 | issues: [{message: "The 'age' field must be a number.", path: ['age']}], 49 | success: false, 50 | }); 51 | }); 52 | 53 | test('assert', async () => { 54 | expect(await assert(schema, data)).toStrictEqual(data); 55 | await expect(assert(schema, badData)).rejects.toThrow(); 56 | }); 57 | 58 | test('wrap', async () => { 59 | const tRPC = initTRPC.create(); 60 | const router = tRPC.router({ 61 | hello: tRPC.procedure.input(wrap(schema)).query(({input}) => { 62 | expectTypeOf().toEqualTypeOf(); 63 | return input; 64 | }), 65 | }); 66 | const createCaller = tRPC.createCallerFactory(router); 67 | const caller = createCaller({}); 68 | expect(await caller.hello(data)).toStrictEqual(data); 69 | }); 70 | }); 71 | -------------------------------------------------------------------------------- /packages/main/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../../../tsconfig.test.json", 4 | "include": ["*.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/main/src/adapters.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type {AdapterResolver as ArktypeResolver} from '@typeschema/arktype'; 6 | import type {AdapterResolver as ClassValidatorResolver} from '@typeschema/class-validator'; 7 | import type {AdapterResolver as DeepkitResolver} from '@typeschema/deepkit'; 8 | import type {AdapterResolver as EffectResolver} from '@typeschema/effect'; 9 | import type {AdapterResolver as FastestValidatorResolver} from '@typeschema/fastest-validator'; 10 | import type {AdapterResolver as FunctionResolver} from '@typeschema/function'; 11 | import type {AdapterResolver as IoTsResolver} from '@typeschema/io-ts'; 12 | import type {AdapterResolver as JoiResolver} from '@typeschema/joi'; 13 | import type {AdapterResolver as JsonResolver} from '@typeschema/json'; 14 | import type {AdapterResolver as OwResolver} from '@typeschema/ow'; 15 | import type {AdapterResolver as RuntypesResolver} from '@typeschema/runtypes'; 16 | import type {AdapterResolver as SuperstructResolver} from '@typeschema/superstruct'; 17 | import type {AdapterResolver as SuretypeResolver} from '@typeschema/suretype'; 18 | import type {AdapterResolver as TypeboxResolver} from '@typeschema/typebox'; 19 | import type {AdapterResolver as ValibotResolver} from '@typeschema/valibot'; 20 | import type {AdapterResolver as ValitaResolver} from '@typeschema/valita'; 21 | import type {AdapterResolver as VineResolver} from '@typeschema/vine'; 22 | import type {AdapterResolver as YupResolver} from '@typeschema/yup'; 23 | import type {AdapterResolver as ZodResolver} from '@typeschema/zod'; 24 | 25 | export type AdapterResolvers = { 26 | arktype: ArktypeResolver; 27 | classValidator: ClassValidatorResolver; 28 | deepkit: DeepkitResolver; 29 | effect: EffectResolver; 30 | fastestValidator: FastestValidatorResolver; 31 | function: FunctionResolver; 32 | ioTs: IoTsResolver; 33 | joi: JoiResolver; 34 | json: JsonResolver; 35 | ow: OwResolver; 36 | runtypes: RuntypesResolver; 37 | superstruct: SuperstructResolver; 38 | suretype: SuretypeResolver; 39 | typebox: TypeboxResolver; 40 | valibot: ValibotResolver; 41 | valita: ValitaResolver; 42 | vine: VineResolver; 43 | yup: YupResolver; 44 | zod: ZodResolver; 45 | }; 46 | -------------------------------------------------------------------------------- /packages/main/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type { 6 | InputFrom, 7 | OutputFrom, 8 | SchemaFrom, 9 | UnknownIfNever, 10 | } from '@typeschema/core'; 11 | 12 | import { 13 | createAssert, 14 | createValidate, 15 | createWrap, 16 | createToJSONSchema, 17 | } from '@typeschema/core'; 18 | 19 | import {AdapterResolver} from './resolver'; 20 | import {validationAdapter} from './validation'; 21 | import {serializationAdapter} from './serialization'; 22 | 23 | export type Schema = SchemaFrom; 24 | export type Infer = UnknownIfNever< 25 | OutputFrom 26 | >; 27 | export type InferIn = UnknownIfNever< 28 | InputFrom 29 | >; 30 | 31 | export const validate = createValidate(validationAdapter); 32 | export const assert = createAssert(validate); 33 | export const wrap = createWrap(assert, validate); 34 | 35 | export const toJSONSchema = createToJSONSchema(serializationAdapter); 36 | 37 | export { 38 | AdapterResolver, 39 | validationAdapter, 40 | serializationAdapter, 41 | }; 42 | -------------------------------------------------------------------------------- /packages/main/src/resolver.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolvers} from './adapters'; 2 | import type {Select} from './selector'; 3 | import type { 4 | InputFrom, 5 | OutputFrom, 6 | Resolver, 7 | SchemaFrom, 8 | } from '@typeschema/core'; 9 | 10 | export interface AdapterResolver extends Resolver { 11 | base: { 12 | [TModule in keyof AdapterResolvers]: SchemaFrom; 13 | }[keyof AdapterResolvers]; 14 | input: InputFrom], this['schema']>; 15 | output: OutputFrom], this['schema']>; 16 | } 17 | -------------------------------------------------------------------------------- /packages/main/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/ow/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @typeschema/ow 2 | 3 | ## 0.14.0 4 | 5 | ### Minor Changes 6 | 7 | - 14976b2: Upgrade deps 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [2251f01] 12 | - Updated dependencies [14976b2] 13 | - @typeschema/core@0.14.0 14 | 15 | ## 0.13.3 16 | 17 | ### Patch Changes 18 | 19 | - 6c178f0: Fix Vite support 20 | 21 | ## 0.13.2 22 | 23 | ### Patch Changes 24 | 25 | - 3087916: Improve handling missing types 26 | - Updated dependencies [3087916] 27 | - @typeschema/core@0.13.2 28 | 29 | ## 0.13.1 30 | 31 | ### Patch Changes 32 | 33 | - 6f1fc2d: Export the Schema type 34 | - Updated dependencies [6f1fc2d] 35 | - @typeschema/core@0.13.1 36 | 37 | ## 0.13.0 38 | 39 | ### Minor Changes 40 | 41 | - 05b430e: Package restructure 42 | 43 | ### Patch Changes 44 | 45 | - Updated dependencies [05b430e] 46 | - @typeschema/core@0.13.0 47 | -------------------------------------------------------------------------------- /packages/ow/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | TypeSchema 4 |

@typeschema/ow

5 |

6 | License 7 | Bundle size 8 | npm downloads 9 | GitHub stars 10 |

11 |

12 | Reusable adapter for Ow schemas 13 |
14 | https://typeschema.com ✨ 15 |

16 | 17 | ```ts 18 | import {initTRPC} from '@trpc/server'; 19 | import ow from 'ow'; 20 | 21 | import {wrap} from '@typeschema/ow'; 22 | 23 | const schema = ow.object.exactShape({name: ow.string}); 24 | 25 | const t = initTRPC.create(); 26 | const appRouter = t.router({ 27 | hello: t.procedure 28 | .input(wrap(schema)) 29 | .query(({input}) => `Hello, ${input.name}!`), 30 | // ^? {name: string} 31 | }); 32 | 33 | ``` 34 | 35 | Use it directly or through [`@typeschema/main`](https://github.com/decs/typeschema/tree/main/packages/main) 36 | 37 | ## Dependencies 38 | - [`ow`](https://www.npmjs.com/package/ow): Required for inference and validation (`^0.28.2`) 39 | 40 | ## API 41 | 42 | ### Inference 43 | - `Infer`: Extracts the output type of a schema 44 | - `InferIn`: Extracts the input type of a schema 45 | 46 | ### Validation 47 | - `wrap(schema)`: Returns the wrapped schema with access to its operations 48 | - `validate(schema, data)`: Returns the validated data or a list of validation issues 49 | - `assert(schema, data)`: Returns the validated data or throws an `AggregateError` 50 | -------------------------------------------------------------------------------- /packages/ow/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is partially generated. Only some fields can be modified manually!", 3 | "name": "@typeschema/ow", 4 | "//version": "This field is manually maintained.", 5 | "version": "0.14.0", 6 | "//description": "This field is manually maintained.", 7 | "description": "Reusable adapter for Ow schemas", 8 | "keywords": [ 9 | "typescript", 10 | "type", 11 | "schema", 12 | "adapter", 13 | "validation", 14 | "inference", 15 | "assert" 16 | ], 17 | "homepage": "https://typeschema.com", 18 | "license": "MIT", 19 | "author": { 20 | "name": "André Costa", 21 | "email": "andrefonsecacosta@gmail.com" 22 | }, 23 | "publishConfig": { 24 | "access": "public", 25 | "registry": "https://registry.npmjs.org/" 26 | }, 27 | "files": [ 28 | "/dist" 29 | ], 30 | "main": "dist/index.js", 31 | "module": "dist/index.mjs", 32 | "types": "dist/index.d.ts", 33 | "exports": { 34 | ".": { 35 | "import": { 36 | "types": "./dist/index.d.mts", 37 | "default": "./dist/index.mjs" 38 | }, 39 | "require": { 40 | "types": "./dist/index.d.ts", 41 | "default": "./dist/index.js" 42 | } 43 | } 44 | }, 45 | "sideEffects": false, 46 | "repository": { 47 | "type": "git", 48 | "url": "https://github.com/decs/typeschema.git" 49 | }, 50 | "scripts": { 51 | "build": "tsup --config ../../tsup.config.ts", 52 | "lint": "eslint src --fix", 53 | "lint:package": "publint && attw --pack", 54 | "test": "vitest --config ../../vitest.config.ts", 55 | "upgrade:deps": "ncu -u --dep=dev,peer --reject ow" 56 | }, 57 | "dependencies": { 58 | "@typeschema/core": "workspace:*" 59 | }, 60 | "//devDependencies": "This field is manually maintained.", 61 | "devDependencies": { 62 | "ow": "^0.28.2" 63 | }, 64 | "//peerDependencies": { 65 | "//": "This field is manually maintained.", 66 | "ow": "Required for inference and validation" 67 | }, 68 | "peerDependencies": { 69 | "ow": "^0.28.2" 70 | }, 71 | "//peerDependenciesMeta": "This field is manually maintained.", 72 | "peerDependenciesMeta": { 73 | "ow": { 74 | "optional": true 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /packages/ow/src/__tests__/example.ts: -------------------------------------------------------------------------------- 1 | import {initTRPC} from '@trpc/server'; 2 | import ow from 'ow'; 3 | 4 | import {wrap} from '..'; 5 | 6 | const schema = ow.object.exactShape({name: ow.string}); 7 | 8 | const t = initTRPC.create(); 9 | const appRouter = t.router({ 10 | hello: t.procedure 11 | .input(wrap(schema)) 12 | .query(({input}) => `Hello, ${input.name}!`), 13 | // ^? {name: string} 14 | }); 15 | -------------------------------------------------------------------------------- /packages/ow/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../../../tsconfig.test.json", 4 | "include": ["*.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/ow/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type { 6 | InputFrom, 7 | OutputFrom, 8 | SchemaFrom, 9 | UnknownIfNever, 10 | } from '@typeschema/core'; 11 | 12 | import { 13 | createAssert, 14 | createValidate, 15 | createWrap, 16 | } from '@typeschema/core'; 17 | 18 | import {AdapterResolver} from './resolver'; 19 | import {validationAdapter} from './validation'; 20 | 21 | export type Schema = SchemaFrom; 22 | export type Infer = UnknownIfNever< 23 | OutputFrom 24 | >; 25 | export type InferIn = UnknownIfNever< 26 | InputFrom 27 | >; 28 | 29 | export const validate = createValidate(validationAdapter); 30 | export const assert = createAssert(validate); 31 | export const wrap = createWrap(assert, validate); 32 | 33 | 34 | export { 35 | AdapterResolver, 36 | validationAdapter, 37 | }; 38 | -------------------------------------------------------------------------------- /packages/ow/src/resolver.ts: -------------------------------------------------------------------------------- 1 | import type {IfDefined, Resolver} from '@typeschema/core'; 2 | import type {Infer, Predicate} from 'ow'; 3 | 4 | export interface AdapterResolver extends Resolver { 5 | base: IfDefined; 6 | input: this['schema'] extends this['base'] ? Infer : never; 7 | output: this['schema'] extends this['base'] ? Infer : never; 8 | } 9 | -------------------------------------------------------------------------------- /packages/ow/src/validation.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {ValidationAdapter} from '@typeschema/core'; 3 | 4 | import {memoize} from '@typeschema/core'; 5 | 6 | const importValidationModule = memoize(async () => { 7 | const {default: ow, ArgumentError} = await import('ow'); 8 | return {ArgumentError, ow}; 9 | }); 10 | 11 | export const validationAdapter: ValidationAdapter< 12 | AdapterResolver 13 | > = async schema => { 14 | const {ArgumentError, ow} = await importValidationModule(); 15 | const assertSchema = ow.create(schema); 16 | return async data => { 17 | try { 18 | assertSchema(data, 'data'); 19 | return { 20 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 21 | data: data as any, 22 | success: true, 23 | }; 24 | } catch (error) { 25 | if (error instanceof ArgumentError) { 26 | return { 27 | issues: Array.from(error.validationErrors.values()).flatMap( 28 | messages => Array.from(messages).map(message => ({message})), 29 | ), 30 | success: false, 31 | }; 32 | } 33 | throw error; 34 | } 35 | }; 36 | }; 37 | -------------------------------------------------------------------------------- /packages/ow/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/runtypes/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @typeschema/runtypes 2 | 3 | ## 0.14.0 4 | 5 | ### Minor Changes 6 | 7 | - 14976b2: Upgrade deps 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [2251f01] 12 | - Updated dependencies [14976b2] 13 | - @typeschema/core@0.14.0 14 | 15 | ## 0.13.2 16 | 17 | ### Patch Changes 18 | 19 | - 3087916: Improve handling missing types 20 | - Updated dependencies [3087916] 21 | - @typeschema/core@0.13.2 22 | 23 | ## 0.13.1 24 | 25 | ### Patch Changes 26 | 27 | - 6f1fc2d: Export the Schema type 28 | - Updated dependencies [6f1fc2d] 29 | - @typeschema/core@0.13.1 30 | 31 | ## 0.13.0 32 | 33 | ### Minor Changes 34 | 35 | - 05b430e: Package restructure 36 | 37 | ### Patch Changes 38 | 39 | - Updated dependencies [05b430e] 40 | - @typeschema/core@0.13.0 41 | -------------------------------------------------------------------------------- /packages/runtypes/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | TypeSchema 4 |

@typeschema/runtypes

5 |

6 | License 7 | Bundle size 8 | npm downloads 9 | GitHub stars 10 |

11 |

12 | Reusable adapter for Runtypes schemas 13 |
14 | https://typeschema.com ✨ 15 |

16 | 17 | ```ts 18 | import {initTRPC} from '@trpc/server'; 19 | import {Record, String} from 'runtypes'; 20 | 21 | import {wrap} from '@typeschema/runtypes'; 22 | 23 | const schema = Record({name: String}); 24 | 25 | const t = initTRPC.create(); 26 | const appRouter = t.router({ 27 | hello: t.procedure 28 | .input(wrap(schema)) 29 | .query(({input}) => `Hello, ${input.name}!`), 30 | // ^? {name: string} 31 | }); 32 | 33 | ``` 34 | 35 | Use it directly or through [`@typeschema/main`](https://github.com/decs/typeschema/tree/main/packages/main) 36 | 37 | ## Dependencies 38 | - [`runtypes`](https://www.npmjs.com/package/runtypes): Required for inference and validation (`^6.7.0`) 39 | 40 | ## API 41 | 42 | ### Inference 43 | - `Infer`: Extracts the output type of a schema 44 | - `InferIn`: Extracts the input type of a schema 45 | 46 | ### Validation 47 | - `wrap(schema)`: Returns the wrapped schema with access to its operations 48 | - `validate(schema, data)`: Returns the validated data or a list of validation issues 49 | - `assert(schema, data)`: Returns the validated data or throws an `AggregateError` 50 | -------------------------------------------------------------------------------- /packages/runtypes/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is partially generated. Only some fields can be modified manually!", 3 | "name": "@typeschema/runtypes", 4 | "//version": "This field is manually maintained.", 5 | "version": "0.14.0", 6 | "//description": "This field is manually maintained.", 7 | "description": "Reusable adapter for Runtypes schemas", 8 | "keywords": [ 9 | "typescript", 10 | "type", 11 | "schema", 12 | "adapter", 13 | "validation", 14 | "inference", 15 | "assert" 16 | ], 17 | "homepage": "https://typeschema.com", 18 | "license": "MIT", 19 | "author": { 20 | "name": "André Costa", 21 | "email": "andrefonsecacosta@gmail.com" 22 | }, 23 | "publishConfig": { 24 | "access": "public", 25 | "registry": "https://registry.npmjs.org/" 26 | }, 27 | "files": [ 28 | "/dist" 29 | ], 30 | "main": "dist/index.js", 31 | "module": "dist/index.mjs", 32 | "types": "dist/index.d.ts", 33 | "exports": { 34 | ".": { 35 | "import": { 36 | "types": "./dist/index.d.mts", 37 | "default": "./dist/index.mjs" 38 | }, 39 | "require": { 40 | "types": "./dist/index.d.ts", 41 | "default": "./dist/index.js" 42 | } 43 | } 44 | }, 45 | "sideEffects": false, 46 | "repository": { 47 | "type": "git", 48 | "url": "https://github.com/decs/typeschema.git" 49 | }, 50 | "scripts": { 51 | "build": "tsup --config ../../tsup.config.ts", 52 | "lint": "eslint src --fix", 53 | "lint:package": "publint && attw --pack", 54 | "test": "vitest --config ../../vitest.config.ts", 55 | "upgrade:deps": "ncu -u --dep=dev,peer --reject ow" 56 | }, 57 | "dependencies": { 58 | "@typeschema/core": "workspace:*" 59 | }, 60 | "//devDependencies": "This field is manually maintained.", 61 | "devDependencies": { 62 | "runtypes": "^6.7.0" 63 | }, 64 | "//peerDependencies": { 65 | "//": "This field is manually maintained.", 66 | "runtypes": "Required for inference and validation" 67 | }, 68 | "peerDependencies": { 69 | "runtypes": "^6.7.0" 70 | }, 71 | "//peerDependenciesMeta": "This field is manually maintained.", 72 | "peerDependenciesMeta": { 73 | "runtypes": { 74 | "optional": true 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /packages/runtypes/src/__tests__/example.ts: -------------------------------------------------------------------------------- 1 | import {initTRPC} from '@trpc/server'; 2 | import {Record, String} from 'runtypes'; 3 | 4 | import {wrap} from '..'; 5 | 6 | const schema = Record({name: String}); 7 | 8 | const t = initTRPC.create(); 9 | const appRouter = t.router({ 10 | hello: t.procedure 11 | .input(wrap(schema)) 12 | .query(({input}) => `Hello, ${input.name}!`), 13 | // ^? {name: string} 14 | }); 15 | -------------------------------------------------------------------------------- /packages/runtypes/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../../../tsconfig.test.json", 4 | "include": ["*.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/runtypes/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type { 6 | InputFrom, 7 | OutputFrom, 8 | SchemaFrom, 9 | UnknownIfNever, 10 | } from '@typeschema/core'; 11 | 12 | import { 13 | createAssert, 14 | createValidate, 15 | createWrap, 16 | } from '@typeschema/core'; 17 | 18 | import {AdapterResolver} from './resolver'; 19 | import {validationAdapter} from './validation'; 20 | 21 | export type Schema = SchemaFrom; 22 | export type Infer = UnknownIfNever< 23 | OutputFrom 24 | >; 25 | export type InferIn = UnknownIfNever< 26 | InputFrom 27 | >; 28 | 29 | export const validate = createValidate(validationAdapter); 30 | export const assert = createAssert(validate); 31 | export const wrap = createWrap(assert, validate); 32 | 33 | 34 | export { 35 | AdapterResolver, 36 | validationAdapter, 37 | }; 38 | -------------------------------------------------------------------------------- /packages/runtypes/src/resolver.ts: -------------------------------------------------------------------------------- 1 | import type {IfDefined, Resolver} from '@typeschema/core'; 2 | import type {Runtype, Static} from 'runtypes'; 3 | 4 | export interface AdapterResolver extends Resolver { 5 | base: IfDefined; 6 | input: this['schema'] extends this['base'] ? Static : never; 7 | output: this['schema'] extends this['base'] ? Static : never; 8 | } 9 | -------------------------------------------------------------------------------- /packages/runtypes/src/validation.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {ValidationAdapter} from '@typeschema/core'; 3 | 4 | export const validationAdapter: ValidationAdapter< 5 | AdapterResolver 6 | > = async schema => { 7 | return async data => { 8 | const result = schema.validate(data); 9 | if (result.success) { 10 | return { 11 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 12 | data: result.value as any, 13 | success: true, 14 | }; 15 | } 16 | return { 17 | issues: [{message: result.message}], 18 | success: false, 19 | }; 20 | }; 21 | }; 22 | -------------------------------------------------------------------------------- /packages/runtypes/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/superstruct/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @typeschema/superstruct 2 | 3 | ## 0.14.0 4 | 5 | ### Minor Changes 6 | 7 | - 14976b2: Upgrade deps 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [2251f01] 12 | - Updated dependencies [14976b2] 13 | - @typeschema/core@0.14.0 14 | 15 | ## 0.13.2 16 | 17 | ### Patch Changes 18 | 19 | - 3087916: Improve handling missing types 20 | - Updated dependencies [3087916] 21 | - @typeschema/core@0.13.2 22 | 23 | ## 0.13.1 24 | 25 | ### Patch Changes 26 | 27 | - 6f1fc2d: Export the Schema type 28 | - Updated dependencies [6f1fc2d] 29 | - @typeschema/core@0.13.1 30 | 31 | ## 0.13.0 32 | 33 | ### Minor Changes 34 | 35 | - 05b430e: Package restructure 36 | 37 | ### Patch Changes 38 | 39 | - Updated dependencies [05b430e] 40 | - @typeschema/core@0.13.0 41 | -------------------------------------------------------------------------------- /packages/superstruct/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | TypeSchema 4 |

@typeschema/superstruct

5 |

6 | License 7 | Bundle size 8 | npm downloads 9 | GitHub stars 10 |

11 |

12 | Reusable adapter for Superstruct schemas 13 |
14 | https://typeschema.com ✨ 15 |

16 | 17 | ```ts 18 | import {initTRPC} from '@trpc/server'; 19 | import {object, string} from 'superstruct'; 20 | 21 | import {wrap} from '@typeschema/superstruct'; 22 | 23 | const schema = object({name: string()}); 24 | 25 | const t = initTRPC.create(); 26 | const appRouter = t.router({ 27 | hello: t.procedure 28 | .input(wrap(schema)) 29 | .query(({input}) => `Hello, ${input.name}!`), 30 | // ^? {name: string} 31 | }); 32 | 33 | ``` 34 | 35 | Use it directly or through [`@typeschema/main`](https://github.com/decs/typeschema/tree/main/packages/main) 36 | 37 | ## Dependencies 38 | - [`superstruct`](https://www.npmjs.com/package/superstruct): Required for inference and validation (`^2.0.2`) 39 | 40 | ## API 41 | 42 | ### Inference 43 | - `Infer`: Extracts the output type of a schema 44 | 45 | ### Validation 46 | - `wrap(schema)`: Returns the wrapped schema with access to its operations 47 | - `validate(schema, data)`: Returns the validated data or a list of validation issues 48 | - `assert(schema, data)`: Returns the validated data or throws an `AggregateError` 49 | -------------------------------------------------------------------------------- /packages/superstruct/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is partially generated. Only some fields can be modified manually!", 3 | "name": "@typeschema/superstruct", 4 | "//version": "This field is manually maintained.", 5 | "version": "0.14.0", 6 | "//description": "This field is manually maintained.", 7 | "description": "Reusable adapter for Superstruct schemas", 8 | "keywords": [ 9 | "typescript", 10 | "type", 11 | "schema", 12 | "adapter", 13 | "validation", 14 | "inference", 15 | "assert" 16 | ], 17 | "homepage": "https://typeschema.com", 18 | "license": "MIT", 19 | "author": { 20 | "name": "André Costa", 21 | "email": "andrefonsecacosta@gmail.com" 22 | }, 23 | "publishConfig": { 24 | "access": "public", 25 | "registry": "https://registry.npmjs.org/" 26 | }, 27 | "files": [ 28 | "/dist" 29 | ], 30 | "main": "dist/index.js", 31 | "module": "dist/index.mjs", 32 | "types": "dist/index.d.ts", 33 | "exports": { 34 | ".": { 35 | "import": { 36 | "types": "./dist/index.d.mts", 37 | "default": "./dist/index.mjs" 38 | }, 39 | "require": { 40 | "types": "./dist/index.d.ts", 41 | "default": "./dist/index.js" 42 | } 43 | } 44 | }, 45 | "sideEffects": false, 46 | "repository": { 47 | "type": "git", 48 | "url": "https://github.com/decs/typeschema.git" 49 | }, 50 | "scripts": { 51 | "build": "tsup --config ../../tsup.config.ts", 52 | "lint": "eslint src --fix", 53 | "lint:package": "publint && attw --pack", 54 | "test": "vitest --config ../../vitest.config.ts", 55 | "upgrade:deps": "ncu -u --dep=dev,peer --reject ow" 56 | }, 57 | "dependencies": { 58 | "@typeschema/core": "workspace:*" 59 | }, 60 | "//devDependencies": "This field is manually maintained.", 61 | "devDependencies": { 62 | "superstruct": "^2.0.2" 63 | }, 64 | "//peerDependencies": { 65 | "//": "This field is manually maintained.", 66 | "superstruct": "Required for inference and validation" 67 | }, 68 | "peerDependencies": { 69 | "superstruct": "^2.0.2" 70 | }, 71 | "//peerDependenciesMeta": "This field is manually maintained.", 72 | "peerDependenciesMeta": { 73 | "superstruct": { 74 | "optional": true 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /packages/superstruct/src/__tests__/example.ts: -------------------------------------------------------------------------------- 1 | import {initTRPC} from '@trpc/server'; 2 | import {object, string} from 'superstruct'; 3 | 4 | import {wrap} from '..'; 5 | 6 | const schema = object({name: string()}); 7 | 8 | const t = initTRPC.create(); 9 | const appRouter = t.router({ 10 | hello: t.procedure 11 | .input(wrap(schema)) 12 | .query(({input}) => `Hello, ${input.name}!`), 13 | // ^? {name: string} 14 | }); 15 | -------------------------------------------------------------------------------- /packages/superstruct/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../../../tsconfig.test.json", 4 | "include": ["*.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/superstruct/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type { 6 | InputFrom, 7 | OutputFrom, 8 | SchemaFrom, 9 | UnknownIfNever, 10 | } from '@typeschema/core'; 11 | 12 | import { 13 | createAssert, 14 | createValidate, 15 | createWrap, 16 | } from '@typeschema/core'; 17 | 18 | import {AdapterResolver} from './resolver'; 19 | import {validationAdapter} from './validation'; 20 | 21 | export type Schema = SchemaFrom; 22 | export type Infer = UnknownIfNever< 23 | OutputFrom 24 | >; 25 | export type InferIn = UnknownIfNever< 26 | InputFrom 27 | >; 28 | 29 | export const validate = createValidate(validationAdapter); 30 | export const assert = createAssert(validate); 31 | export const wrap = createWrap(assert, validate); 32 | 33 | 34 | export { 35 | AdapterResolver, 36 | validationAdapter, 37 | }; 38 | -------------------------------------------------------------------------------- /packages/superstruct/src/resolver.ts: -------------------------------------------------------------------------------- 1 | import type {IfDefined, Resolver} from '@typeschema/core'; 2 | import type {Infer, Struct} from 'superstruct'; 3 | 4 | export interface AdapterResolver extends Resolver { 5 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 6 | base: IfDefined, 'superstruct'>; 7 | input: this['schema'] extends this['base'] ? unknown : never; 8 | output: this['schema'] extends this['base'] ? Infer : never; 9 | } 10 | -------------------------------------------------------------------------------- /packages/superstruct/src/validation.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {ValidationAdapter} from '@typeschema/core'; 3 | 4 | export const validationAdapter: ValidationAdapter< 5 | AdapterResolver 6 | > = async schema => { 7 | return async data => { 8 | const result = schema.validate(data, {coerce: true}); 9 | if (result[0] == null) { 10 | return { 11 | data: result[1], 12 | success: true, 13 | }; 14 | } 15 | const {message, path} = result[0]; 16 | return { 17 | issues: [{message, path}], 18 | success: false, 19 | }; 20 | }; 21 | }; 22 | -------------------------------------------------------------------------------- /packages/superstruct/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/suretype/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @typeschema/suretype 2 | 3 | ## 0.2.0 4 | 5 | ### Minor Changes 6 | 7 | - 14976b2: Upgrade deps 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [2251f01] 12 | - Updated dependencies [14976b2] 13 | - @typeschema/core@0.14.0 14 | 15 | ## 0.1.0 16 | 17 | ### Minor Changes 18 | 19 | - 14236e6: Add support for suretype 20 | -------------------------------------------------------------------------------- /packages/suretype/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is partially generated. Only some fields can be modified manually!", 3 | "name": "@typeschema/suretype", 4 | "//version": "This field is manually maintained.", 5 | "version": "0.2.0", 6 | "//description": "This field is manually maintained.", 7 | "description": "Reusable adapter for Suretype schemas", 8 | "keywords": [ 9 | "typescript", 10 | "type", 11 | "schema", 12 | "adapter", 13 | "validation", 14 | "inference", 15 | "assert" 16 | ], 17 | "homepage": "https://typeschema.com", 18 | "license": "MIT", 19 | "author": { 20 | "name": "André Costa", 21 | "email": "andrefonsecacosta@gmail.com" 22 | }, 23 | "publishConfig": { 24 | "access": "public", 25 | "registry": "https://registry.npmjs.org/" 26 | }, 27 | "files": [ 28 | "/dist" 29 | ], 30 | "main": "dist/index.js", 31 | "module": "dist/index.mjs", 32 | "types": "dist/index.d.ts", 33 | "exports": { 34 | ".": { 35 | "import": { 36 | "types": "./dist/index.d.mts", 37 | "default": "./dist/index.mjs" 38 | }, 39 | "require": { 40 | "types": "./dist/index.d.ts", 41 | "default": "./dist/index.js" 42 | } 43 | } 44 | }, 45 | "sideEffects": false, 46 | "repository": { 47 | "type": "git", 48 | "url": "https://github.com/decs/typeschema.git" 49 | }, 50 | "scripts": { 51 | "build": "tsup --config ../../tsup.config.ts", 52 | "lint": "eslint src --fix", 53 | "lint:package": "publint && attw --pack", 54 | "test": "vitest --config ../../vitest.config.ts", 55 | "upgrade:deps": "ncu -u --dep=dev,peer --reject ow" 56 | }, 57 | "dependencies": { 58 | "@typeschema/core": "workspace:*" 59 | }, 60 | "//devDependencies": "This field is manually maintained.", 61 | "devDependencies": { 62 | "suretype": "^3.3.1" 63 | }, 64 | "//peerDependencies": { 65 | "//": "This field is manually maintained.", 66 | "suretype": "Required for inference, validation, and serialization" 67 | }, 68 | "peerDependencies": { 69 | "suretype": "^3.3.1" 70 | }, 71 | "//peerDependenciesMeta": "This field is manually maintained.", 72 | "peerDependenciesMeta": { 73 | "suretype": { 74 | "optional": true 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /packages/suretype/src/__tests__/example.ts: -------------------------------------------------------------------------------- 1 | import {initTRPC} from '@trpc/server'; 2 | import {v} from 'suretype'; 3 | 4 | import {wrap} from '..'; 5 | 6 | const schema = v.object({ 7 | name: v.string().required(), 8 | }); 9 | 10 | const t = initTRPC.create(); 11 | const appRouter = t.router({ 12 | hello: t.procedure 13 | .input(wrap(schema)) 14 | .query(({input}) => `Hello, ${input.name}!`), 15 | // ^? {name: string} 16 | }); 17 | -------------------------------------------------------------------------------- /packages/suretype/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../../../tsconfig.test.json", 4 | "include": ["*.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/suretype/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type { 6 | InputFrom, 7 | OutputFrom, 8 | SchemaFrom, 9 | UnknownIfNever, 10 | } from '@typeschema/core'; 11 | 12 | import { 13 | createAssert, 14 | createValidate, 15 | createWrap, 16 | createToJSONSchema, 17 | } from '@typeschema/core'; 18 | 19 | import {AdapterResolver} from './resolver'; 20 | import {validationAdapter} from './validation'; 21 | import {serializationAdapter} from './serialization'; 22 | 23 | export type Schema = SchemaFrom; 24 | export type Infer = UnknownIfNever< 25 | OutputFrom 26 | >; 27 | export type InferIn = UnknownIfNever< 28 | InputFrom 29 | >; 30 | 31 | export const validate = createValidate(validationAdapter); 32 | export const assert = createAssert(validate); 33 | export const wrap = createWrap(assert, validate); 34 | 35 | export const toJSONSchema = createToJSONSchema(serializationAdapter); 36 | 37 | export { 38 | AdapterResolver, 39 | validationAdapter, 40 | serializationAdapter, 41 | }; 42 | -------------------------------------------------------------------------------- /packages/suretype/src/resolver.ts: -------------------------------------------------------------------------------- 1 | import type {IfDefined, Resolver} from '@typeschema/core'; 2 | import type {CoreValidator, TypeOf} from 'suretype'; 3 | 4 | export interface AdapterResolver extends Resolver { 5 | base: IfDefined, 'suretype'>; 6 | input: this['schema'] extends this['base'] ? TypeOf : never; 7 | output: this['schema'] extends this['base'] ? TypeOf : never; 8 | } 9 | -------------------------------------------------------------------------------- /packages/suretype/src/serialization.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {SerializationAdapter} from '@typeschema/core'; 3 | 4 | import {memoize} from '@typeschema/core'; 5 | 6 | const importSerializationModule = memoize(async () => { 7 | const {extractSingleJsonSchema} = await import('suretype'); 8 | return {extractSingleJsonSchema}; 9 | }); 10 | 11 | export const serializationAdapter: SerializationAdapter< 12 | AdapterResolver 13 | > = async schema => { 14 | const {extractSingleJsonSchema} = await importSerializationModule(); 15 | return extractSingleJsonSchema(schema).schema; 16 | }; 17 | -------------------------------------------------------------------------------- /packages/suretype/src/validation.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {ValidationAdapter} from '@typeschema/core'; 3 | 4 | import {memoize} from '@typeschema/core'; 5 | 6 | const importValidationModule = memoize(async () => { 7 | const {compile} = await import('suretype'); 8 | return {compile}; 9 | }); 10 | 11 | export const validationAdapter: ValidationAdapter< 12 | AdapterResolver 13 | > = async schema => { 14 | const {compile} = await importValidationModule(); 15 | const parseSchema = compile(schema); 16 | return async data => { 17 | const result = parseSchema(data); 18 | if (result.ok) { 19 | return { 20 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 21 | data: data as any, 22 | success: true, 23 | }; 24 | } 25 | return { 26 | issues: (result.errors ?? []).map(({message, schemaPath}) => ({ 27 | message: message ?? '', 28 | path: [schemaPath], 29 | })), 30 | success: false, 31 | }; 32 | }; 33 | }; 34 | -------------------------------------------------------------------------------- /packages/suretype/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/typebox/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @typeschema/typebox 2 | 3 | ## 0.14.0 4 | 5 | ### Minor Changes 6 | 7 | - 14976b2: Upgrade deps 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [2251f01] 12 | - Updated dependencies [14976b2] 13 | - @typeschema/core@0.14.0 14 | 15 | ## 0.13.4 16 | 17 | ### Patch Changes 18 | 19 | - 8fa21a3: Upgrade dependencies 20 | - 95f9616: Add serialization support to TypeBox 21 | 22 | ## 0.13.3 23 | 24 | ### Patch Changes 25 | 26 | - 6c178f0: Fix Vite support 27 | 28 | ## 0.13.2 29 | 30 | ### Patch Changes 31 | 32 | - 3087916: Improve handling missing types 33 | - Updated dependencies [3087916] 34 | - @typeschema/core@0.13.2 35 | 36 | ## 0.13.1 37 | 38 | ### Patch Changes 39 | 40 | - 6f1fc2d: Export the Schema type 41 | - Updated dependencies [6f1fc2d] 42 | - @typeschema/core@0.13.1 43 | 44 | ## 0.13.0 45 | 46 | ### Minor Changes 47 | 48 | - 05b430e: Package restructure 49 | 50 | ### Patch Changes 51 | 52 | - Updated dependencies [05b430e] 53 | - @typeschema/core@0.13.0 54 | -------------------------------------------------------------------------------- /packages/typebox/src/__tests__/example.ts: -------------------------------------------------------------------------------- 1 | import {Type} from '@sinclair/typebox'; 2 | import {initTRPC} from '@trpc/server'; 3 | 4 | import {wrap} from '..'; 5 | 6 | const schema = Type.Object({name: Type.String()}); 7 | 8 | const t = initTRPC.create(); 9 | const appRouter = t.router({ 10 | hello: t.procedure 11 | .input(wrap(schema)) 12 | .query(({input}) => `Hello, ${input.name}!`), 13 | // ^? {name: string} 14 | }); 15 | -------------------------------------------------------------------------------- /packages/typebox/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../../../tsconfig.test.json", 4 | "include": ["*.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/typebox/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type { 6 | InputFrom, 7 | OutputFrom, 8 | SchemaFrom, 9 | UnknownIfNever, 10 | } from '@typeschema/core'; 11 | 12 | import { 13 | createAssert, 14 | createValidate, 15 | createWrap, 16 | createToJSONSchema, 17 | } from '@typeschema/core'; 18 | 19 | import {AdapterResolver} from './resolver'; 20 | import {validationAdapter} from './validation'; 21 | import {serializationAdapter} from './serialization'; 22 | 23 | export type Schema = SchemaFrom; 24 | export type Infer = UnknownIfNever< 25 | OutputFrom 26 | >; 27 | export type InferIn = UnknownIfNever< 28 | InputFrom 29 | >; 30 | 31 | export const validate = createValidate(validationAdapter); 32 | export const assert = createAssert(validate); 33 | export const wrap = createWrap(assert, validate); 34 | 35 | export const toJSONSchema = createToJSONSchema(serializationAdapter); 36 | 37 | export { 38 | AdapterResolver, 39 | validationAdapter, 40 | serializationAdapter, 41 | }; 42 | -------------------------------------------------------------------------------- /packages/typebox/src/resolver.ts: -------------------------------------------------------------------------------- 1 | import type {Static, TSchema} from '@sinclair/typebox'; 2 | import type {IfDefined, Resolver} from '@typeschema/core'; 3 | 4 | export interface AdapterResolver extends Resolver { 5 | base: IfDefined; 6 | input: this['schema'] extends this['base'] ? Static : never; 7 | output: this['schema'] extends this['base'] ? Static : never; 8 | } 9 | -------------------------------------------------------------------------------- /packages/typebox/src/serialization.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {SerializationAdapter} from '@typeschema/core'; 3 | 4 | export const serializationAdapter: SerializationAdapter< 5 | AdapterResolver 6 | > = async schema => schema; 7 | -------------------------------------------------------------------------------- /packages/typebox/src/validation.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {ValidationAdapter} from '@typeschema/core'; 3 | 4 | import {memoize} from '@typeschema/core'; 5 | 6 | const importValidationModule = memoize(async () => { 7 | const {TypeCompiler} = await import('@sinclair/typebox/compiler'); 8 | return {TypeCompiler}; 9 | }); 10 | 11 | export const validationAdapter: ValidationAdapter< 12 | AdapterResolver 13 | > = async schema => { 14 | const {TypeCompiler} = await importValidationModule(); 15 | const result = TypeCompiler.Compile(schema); 16 | return async data => { 17 | if (result.Check(data)) { 18 | return { 19 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 20 | data: data as any, 21 | success: true, 22 | }; 23 | } 24 | return { 25 | issues: [...result.Errors(data)].map(({message, path}) => ({ 26 | message, 27 | path: [path], 28 | })), 29 | success: false, 30 | }; 31 | }; 32 | }; 33 | -------------------------------------------------------------------------------- /packages/typebox/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/valibot/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @typeschema/valibot 2 | 3 | ## 0.14.0 4 | 5 | ### Minor Changes 6 | 7 | - 14976b2: Upgrade deps 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [2251f01] 12 | - Updated dependencies [14976b2] 13 | - @typeschema/core@0.14.0 14 | 15 | ## 0.13.5 16 | 17 | ### Patch Changes 18 | 19 | - ac97adb: Update to Valibot 0.31 20 | 21 | ## 0.13.4 22 | 23 | ### Patch Changes 24 | 25 | - 8fa21a3: Upgrade dependencies 26 | 27 | ## 0.13.3 28 | 29 | ### Patch Changes 30 | 31 | - 6c178f0: Fix Vite support 32 | 33 | ## 0.13.2 34 | 35 | ### Patch Changes 36 | 37 | - 3087916: Improve handling missing types 38 | - Updated dependencies [3087916] 39 | - @typeschema/core@0.13.2 40 | 41 | ## 0.13.1 42 | 43 | ### Patch Changes 44 | 45 | - 6f1fc2d: Export the Schema type 46 | - Updated dependencies [6f1fc2d] 47 | - @typeschema/core@0.13.1 48 | 49 | ## 0.13.0 50 | 51 | ### Minor Changes 52 | 53 | - 05b430e: Package restructure 54 | 55 | ### Patch Changes 56 | 57 | - Updated dependencies [05b430e] 58 | - @typeschema/core@0.13.0 59 | -------------------------------------------------------------------------------- /packages/valibot/src/__tests__/example.ts: -------------------------------------------------------------------------------- 1 | import {initTRPC} from '@trpc/server'; 2 | import {object, string} from 'valibot'; 3 | 4 | import {wrap} from '..'; 5 | 6 | const schema = object({name: string()}); 7 | 8 | const t = initTRPC.create(); 9 | const appRouter = t.router({ 10 | hello: t.procedure 11 | .input(wrap(schema)) 12 | .query(({input}) => `Hello, ${input.name}!`), 13 | // ^? {name: string} 14 | }); 15 | -------------------------------------------------------------------------------- /packages/valibot/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../../../tsconfig.test.json", 4 | "include": ["*.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/valibot/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type { 6 | InputFrom, 7 | OutputFrom, 8 | SchemaFrom, 9 | UnknownIfNever, 10 | } from '@typeschema/core'; 11 | 12 | import { 13 | createAssert, 14 | createValidate, 15 | createWrap, 16 | createToJSONSchema, 17 | } from '@typeschema/core'; 18 | 19 | import {AdapterResolver} from './resolver'; 20 | import {validationAdapter} from './validation'; 21 | import {serializationAdapter} from './serialization'; 22 | 23 | export type Schema = SchemaFrom; 24 | export type Infer = UnknownIfNever< 25 | OutputFrom 26 | >; 27 | export type InferIn = UnknownIfNever< 28 | InputFrom 29 | >; 30 | 31 | export const validate = createValidate(validationAdapter); 32 | export const assert = createAssert(validate); 33 | export const wrap = createWrap(assert, validate); 34 | 35 | export const toJSONSchema = createToJSONSchema(serializationAdapter); 36 | 37 | export { 38 | AdapterResolver, 39 | validationAdapter, 40 | serializationAdapter, 41 | }; 42 | -------------------------------------------------------------------------------- /packages/valibot/src/resolver.ts: -------------------------------------------------------------------------------- 1 | import type {IfDefined, Resolver} from '@typeschema/core'; 2 | import type { 3 | GenericSchema, 4 | GenericSchemaAsync, 5 | InferInput, 6 | InferOutput, 7 | } from 'valibot'; 8 | 9 | export interface AdapterResolver extends Resolver { 10 | base: IfDefined; 11 | input: this['schema'] extends this['base'] 12 | ? InferInput 13 | : never; 14 | output: this['schema'] extends this['base'] 15 | ? InferOutput 16 | : never; 17 | } 18 | -------------------------------------------------------------------------------- /packages/valibot/src/serialization.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {SerializationAdapter} from '@typeschema/core'; 3 | 4 | import {memoize} from '@typeschema/core'; 5 | 6 | const importSerializationModule = memoize(async () => { 7 | const {toJSONSchema} = await import('@gcornut/valibot-json-schema'); 8 | return {toJSONSchema}; 9 | }); 10 | 11 | export const serializationAdapter: SerializationAdapter< 12 | AdapterResolver 13 | > = async schema => { 14 | const {toJSONSchema} = await importSerializationModule(); 15 | return toJSONSchema({ignoreUnknownValidation: true, schema}); 16 | }; 17 | -------------------------------------------------------------------------------- /packages/valibot/src/validation.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {ValidationAdapter} from '@typeschema/core'; 3 | 4 | import {memoize} from '@typeschema/core'; 5 | 6 | const importValidationModule = memoize(async () => { 7 | const {getDotPath, safeParseAsync} = await import('valibot'); 8 | return {getDotPath, safeParseAsync}; 9 | }); 10 | 11 | export const validationAdapter: ValidationAdapter< 12 | AdapterResolver 13 | > = async schema => { 14 | const {getDotPath, safeParseAsync} = await importValidationModule(); 15 | return async data => { 16 | const result = await safeParseAsync(schema, data); 17 | if (result.success) { 18 | return { 19 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 20 | data: result.output as any, 21 | success: true, 22 | }; 23 | } 24 | return { 25 | issues: result.issues.map(issue => ({ 26 | message: issue.message, 27 | path: getDotPath(issue)?.split('.'), 28 | })), 29 | success: false, 30 | }; 31 | }; 32 | }; 33 | -------------------------------------------------------------------------------- /packages/valibot/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/valita/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @typeschema/valita 2 | 3 | ## 0.2.0 4 | 5 | ### Minor Changes 6 | 7 | - 14976b2: Upgrade deps 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [2251f01] 12 | - Updated dependencies [14976b2] 13 | - @typeschema/core@0.14.0 14 | 15 | ## 0.1.0 16 | 17 | ### Minor Changes 18 | 19 | - 85a0334: Add support for valita 20 | -------------------------------------------------------------------------------- /packages/valita/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | TypeSchema 4 |

@typeschema/valita

5 |

6 | License 7 | Bundle size 8 | npm downloads 9 | GitHub stars 10 |

11 |

12 | Reusable adapter for Valita schemas 13 |
14 | https://typeschema.com ✨ 15 |

16 | 17 | ```ts 18 | import * as v from '@badrap/valita'; 19 | import {initTRPC} from '@trpc/server'; 20 | 21 | import {wrap} from '@typeschema/valita'; 22 | 23 | const schema = v.object({name: v.string()}); 24 | 25 | const t = initTRPC.create(); 26 | const appRouter = t.router({ 27 | hello: t.procedure 28 | .input(wrap(schema)) 29 | .query(({input}) => `Hello, ${input.name}!`), 30 | // ^? {name: string} 31 | }); 32 | 33 | ``` 34 | 35 | Use it directly or through [`@typeschema/main`](https://github.com/decs/typeschema/tree/main/packages/main) 36 | 37 | ## Dependencies 38 | - [`@badrap/valita`](https://www.npmjs.com/package/@badrap/valita): Required for inference and validation (`^0.3.9`) 39 | 40 | ## API 41 | 42 | ### Inference 43 | - `Infer`: Extracts the output type of a schema 44 | - `InferIn`: Extracts the input type of a schema 45 | 46 | ### Validation 47 | - `wrap(schema)`: Returns the wrapped schema with access to its operations 48 | - `validate(schema, data)`: Returns the validated data or a list of validation issues 49 | - `assert(schema, data)`: Returns the validated data or throws an `AggregateError` 50 | -------------------------------------------------------------------------------- /packages/valita/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is partially generated. Only some fields can be modified manually!", 3 | "name": "@typeschema/valita", 4 | "//version": "This field is manually maintained.", 5 | "version": "0.2.0", 6 | "//description": "This field is manually maintained.", 7 | "description": "Reusable adapter for Valita schemas", 8 | "keywords": [ 9 | "typescript", 10 | "type", 11 | "schema", 12 | "adapter", 13 | "validation", 14 | "inference", 15 | "assert" 16 | ], 17 | "homepage": "https://typeschema.com", 18 | "license": "MIT", 19 | "author": { 20 | "name": "André Costa", 21 | "email": "andrefonsecacosta@gmail.com" 22 | }, 23 | "publishConfig": { 24 | "access": "public", 25 | "registry": "https://registry.npmjs.org/" 26 | }, 27 | "files": [ 28 | "/dist" 29 | ], 30 | "main": "dist/index.js", 31 | "module": "dist/index.mjs", 32 | "types": "dist/index.d.ts", 33 | "exports": { 34 | ".": { 35 | "import": { 36 | "types": "./dist/index.d.mts", 37 | "default": "./dist/index.mjs" 38 | }, 39 | "require": { 40 | "types": "./dist/index.d.ts", 41 | "default": "./dist/index.js" 42 | } 43 | } 44 | }, 45 | "sideEffects": false, 46 | "repository": { 47 | "type": "git", 48 | "url": "https://github.com/decs/typeschema.git" 49 | }, 50 | "scripts": { 51 | "build": "tsup --config ../../tsup.config.ts", 52 | "lint": "eslint src --fix", 53 | "lint:package": "publint && attw --pack", 54 | "test": "vitest --config ../../vitest.config.ts", 55 | "upgrade:deps": "ncu -u --dep=dev,peer --reject ow" 56 | }, 57 | "dependencies": { 58 | "@typeschema/core": "workspace:*" 59 | }, 60 | "//devDependencies": "This field is manually maintained.", 61 | "devDependencies": { 62 | "@badrap/valita": "^0.3.9" 63 | }, 64 | "//peerDependencies": { 65 | "//": "This field is manually maintained.", 66 | "@badrap/valita": "Required for inference and validation" 67 | }, 68 | "peerDependencies": { 69 | "@badrap/valita": "^0.3.9" 70 | }, 71 | "//peerDependenciesMeta": "This field is manually maintained.", 72 | "peerDependenciesMeta": { 73 | "@badrap/valita": { 74 | "optional": true 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /packages/valita/src/__tests__/example.ts: -------------------------------------------------------------------------------- 1 | import * as v from '@badrap/valita'; 2 | import {initTRPC} from '@trpc/server'; 3 | 4 | import {wrap} from '..'; 5 | 6 | const schema = v.object({name: v.string()}); 7 | 8 | const t = initTRPC.create(); 9 | const appRouter = t.router({ 10 | hello: t.procedure 11 | .input(wrap(schema)) 12 | .query(({input}) => `Hello, ${input.name}!`), 13 | // ^? {name: string} 14 | }); 15 | -------------------------------------------------------------------------------- /packages/valita/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../../../tsconfig.test.json", 4 | "include": ["*.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/valita/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type { 6 | InputFrom, 7 | OutputFrom, 8 | SchemaFrom, 9 | UnknownIfNever, 10 | } from '@typeschema/core'; 11 | 12 | import { 13 | createAssert, 14 | createValidate, 15 | createWrap, 16 | } from '@typeschema/core'; 17 | 18 | import {AdapterResolver} from './resolver'; 19 | import {validationAdapter} from './validation'; 20 | 21 | export type Schema = SchemaFrom; 22 | export type Infer = UnknownIfNever< 23 | OutputFrom 24 | >; 25 | export type InferIn = UnknownIfNever< 26 | InputFrom 27 | >; 28 | 29 | export const validate = createValidate(validationAdapter); 30 | export const assert = createAssert(validate); 31 | export const wrap = createWrap(assert, validate); 32 | 33 | 34 | export { 35 | AdapterResolver, 36 | validationAdapter, 37 | }; 38 | -------------------------------------------------------------------------------- /packages/valita/src/resolver.ts: -------------------------------------------------------------------------------- 1 | import type {Infer, Type} from '@badrap/valita'; 2 | import type {IfDefined, Resolver} from '@typeschema/core'; 3 | 4 | export interface AdapterResolver extends Resolver { 5 | base: IfDefined; 6 | input: this['schema'] extends this['base'] ? Infer : never; 7 | output: this['schema'] extends this['base'] ? Infer : never; 8 | } 9 | -------------------------------------------------------------------------------- /packages/valita/src/validation.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {ValidationAdapter} from '@typeschema/core'; 3 | 4 | export const validationAdapter: ValidationAdapter< 5 | AdapterResolver 6 | > = async schema => { 7 | return async data => { 8 | const result = schema.try(data); 9 | if (result.ok) { 10 | return { 11 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 12 | data: result.value as any, 13 | success: true, 14 | }; 15 | } 16 | return { 17 | issues: result.issues.map(({code, path}) => ({message: code, path})), 18 | success: false, 19 | }; 20 | }; 21 | }; 22 | -------------------------------------------------------------------------------- /packages/valita/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/vine/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @typeschema/vine 2 | 3 | ## 0.2.0 4 | 5 | ### Minor Changes 6 | 7 | - 14976b2: Upgrade deps 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [2251f01] 12 | - Updated dependencies [14976b2] 13 | - @typeschema/core@0.14.0 14 | 15 | ## 0.1.0 16 | 17 | ### Minor Changes 18 | 19 | - 3fef7e0: feat: add support to vine 20 | -------------------------------------------------------------------------------- /packages/vine/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | TypeSchema 4 |

@typeschema/vine

5 |

6 | License 7 | Bundle size 8 | npm downloads 9 | GitHub stars 10 |

11 |

12 | Reusable adapter for VineJS schemas 13 |
14 | https://typeschema.com ✨ 15 |

16 | 17 | ```ts 18 | import {initTRPC} from '@trpc/server'; 19 | import vine from '@vinejs/vine'; 20 | 21 | import {wrap} from '@typeschema/vine'; 22 | 23 | const schema = vine.object({name: vine.string()}); 24 | 25 | const t = initTRPC.create(); 26 | const appRouter = t.router({ 27 | hello: t.procedure 28 | .input(wrap(schema)) 29 | .query(({input}) => `Hello, ${input.name}!`), 30 | // ^? {name: string} 31 | }); 32 | 33 | ``` 34 | 35 | Use it directly or through [`@typeschema/main`](https://github.com/decs/typeschema/tree/main/packages/main) 36 | 37 | ## Dependencies 38 | - [`@vinejs/vine`](https://www.npmjs.com/package/@vinejs/vine): Required for inference and validation (`^2.1.0`) 39 | 40 | ## API 41 | 42 | ### Inference 43 | - `Infer`: Extracts the output type of a schema 44 | - `InferIn`: Extracts the input type of a schema 45 | 46 | ### Validation 47 | - `wrap(schema)`: Returns the wrapped schema with access to its operations 48 | - `validate(schema, data)`: Returns the validated data or a list of validation issues 49 | - `assert(schema, data)`: Returns the validated data or throws an `AggregateError` 50 | -------------------------------------------------------------------------------- /packages/vine/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is partially generated. Only some fields can be modified manually!", 3 | "name": "@typeschema/vine", 4 | "//version": "This field is manually maintained.", 5 | "version": "0.2.0", 6 | "//description": "This field is manually maintained.", 7 | "description": "Reusable adapter for VineJS schemas", 8 | "keywords": [ 9 | "typescript", 10 | "type", 11 | "schema", 12 | "adapter", 13 | "validation", 14 | "inference", 15 | "assert" 16 | ], 17 | "homepage": "https://typeschema.com", 18 | "license": "MIT", 19 | "author": { 20 | "name": "André Costa", 21 | "email": "andrefonsecacosta@gmail.com" 22 | }, 23 | "publishConfig": { 24 | "access": "public", 25 | "registry": "https://registry.npmjs.org/" 26 | }, 27 | "files": [ 28 | "/dist" 29 | ], 30 | "main": "dist/index.js", 31 | "module": "dist/index.mjs", 32 | "types": "dist/index.d.ts", 33 | "exports": { 34 | ".": { 35 | "import": { 36 | "types": "./dist/index.d.mts", 37 | "default": "./dist/index.mjs" 38 | }, 39 | "require": { 40 | "types": "./dist/index.d.ts", 41 | "default": "./dist/index.js" 42 | } 43 | } 44 | }, 45 | "sideEffects": false, 46 | "repository": { 47 | "type": "git", 48 | "url": "https://github.com/decs/typeschema.git" 49 | }, 50 | "scripts": { 51 | "build": "tsup --config ../../tsup.config.ts", 52 | "lint": "eslint src --fix", 53 | "lint:package": "publint && attw --pack", 54 | "test": "vitest --config ../../vitest.config.ts", 55 | "upgrade:deps": "ncu -u --dep=dev,peer --reject ow" 56 | }, 57 | "dependencies": { 58 | "@typeschema/core": "workspace:*" 59 | }, 60 | "//devDependencies": "This field is manually maintained.", 61 | "devDependencies": { 62 | "@vinejs/vine": "^2.1.0" 63 | }, 64 | "//peerDependencies": { 65 | "//": "This field is manually maintained.", 66 | "@vinejs/vine": "Required for inference and validation" 67 | }, 68 | "peerDependencies": { 69 | "@vinejs/vine": "^2.1.0" 70 | }, 71 | "//peerDependenciesMeta": "This field is manually maintained.", 72 | "peerDependenciesMeta": { 73 | "@vinejs/vine": { 74 | "optional": true 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /packages/vine/src/__tests__/example.ts: -------------------------------------------------------------------------------- 1 | import {initTRPC} from '@trpc/server'; 2 | import vine from '@vinejs/vine'; 3 | 4 | import {wrap} from '..'; 5 | 6 | const schema = vine.object({name: vine.string()}); 7 | 8 | const t = initTRPC.create(); 9 | const appRouter = t.router({ 10 | hello: t.procedure 11 | .input(wrap(schema)) 12 | .query(({input}) => `Hello, ${input.name}!`), 13 | // ^? {name: string} 14 | }); 15 | -------------------------------------------------------------------------------- /packages/vine/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../../../tsconfig.test.json", 4 | "include": ["*.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/vine/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type { 6 | InputFrom, 7 | OutputFrom, 8 | SchemaFrom, 9 | UnknownIfNever, 10 | } from '@typeschema/core'; 11 | 12 | import { 13 | createAssert, 14 | createValidate, 15 | createWrap, 16 | } from '@typeschema/core'; 17 | 18 | import {AdapterResolver} from './resolver'; 19 | import {validationAdapter} from './validation'; 20 | 21 | export type Schema = SchemaFrom; 22 | export type Infer = UnknownIfNever< 23 | OutputFrom 24 | >; 25 | export type InferIn = UnknownIfNever< 26 | InputFrom 27 | >; 28 | 29 | export const validate = createValidate(validationAdapter); 30 | export const assert = createAssert(validate); 31 | export const wrap = createWrap(assert, validate); 32 | 33 | 34 | export { 35 | AdapterResolver, 36 | validationAdapter, 37 | }; 38 | -------------------------------------------------------------------------------- /packages/vine/src/resolver.ts: -------------------------------------------------------------------------------- 1 | import type {IfDefined, Resolver} from '@typeschema/core'; 2 | import type {BaseType, symbols} from '@vinejs/vine'; 3 | 4 | export interface AdapterResolver extends Resolver { 5 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 6 | base: IfDefined, '@vinejs/vine'>; 7 | input: this['schema'] extends this['base'] 8 | ? this['schema'][typeof symbols.ITYPE] 9 | : never; 10 | output: this['schema'] extends this['base'] 11 | ? this['schema'][typeof symbols.OTYPE] 12 | : never; 13 | } 14 | -------------------------------------------------------------------------------- /packages/vine/src/validation.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {ValidationAdapter} from '@typeschema/core'; 3 | 4 | import {memoize} from '@typeschema/core'; 5 | 6 | const importValidationModule = memoize(async () => { 7 | const {errors, Vine} = await import('@vinejs/vine'); 8 | return {errors, vine: new Vine()}; 9 | }); 10 | 11 | export const validationAdapter: ValidationAdapter< 12 | AdapterResolver 13 | > = async schema => { 14 | const {errors, vine} = await importValidationModule(); 15 | const validator = vine.compile(schema); 16 | return async data => { 17 | try { 18 | return { 19 | data: await validator.validate(data), 20 | success: true, 21 | }; 22 | } catch (error) { 23 | if (error instanceof errors.E_VALIDATION_ERROR) { 24 | return { 25 | issues: error.messages.map( 26 | ({message, field}: {message: string; field: string}) => ({ 27 | message, 28 | path: field != null ? field.split('.') : undefined, 29 | }), 30 | ), 31 | success: false, 32 | }; 33 | } 34 | throw error; 35 | } 36 | }; 37 | }; 38 | -------------------------------------------------------------------------------- /packages/vine/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/yup/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @typeschema/yup 2 | 3 | ## 0.14.0 4 | 5 | ### Minor Changes 6 | 7 | - 14976b2: Upgrade deps 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [2251f01] 12 | - Updated dependencies [14976b2] 13 | - @typeschema/core@0.14.0 14 | 15 | ## 0.13.3 16 | 17 | ### Patch Changes 18 | 19 | - 6c178f0: Fix Vite support 20 | 21 | ## 0.13.2 22 | 23 | ### Patch Changes 24 | 25 | - 3087916: Improve handling missing types 26 | - Updated dependencies [3087916] 27 | - @typeschema/core@0.13.2 28 | 29 | ## 0.13.1 30 | 31 | ### Patch Changes 32 | 33 | - 6f1fc2d: Export the Schema type 34 | - Updated dependencies [6f1fc2d] 35 | - @typeschema/core@0.13.1 36 | 37 | ## 0.13.0 38 | 39 | ### Minor Changes 40 | 41 | - 05b430e: Package restructure 42 | 43 | ### Patch Changes 44 | 45 | - Updated dependencies [05b430e] 46 | - @typeschema/core@0.13.0 47 | -------------------------------------------------------------------------------- /packages/yup/src/__tests__/example.ts: -------------------------------------------------------------------------------- 1 | import {initTRPC} from '@trpc/server'; 2 | import {object, string} from 'yup'; 3 | 4 | import {wrap} from '..'; 5 | 6 | const schema = object({name: string().required()}); 7 | 8 | const t = initTRPC.create(); 9 | const appRouter = t.router({ 10 | hello: t.procedure 11 | .input(wrap(schema)) 12 | .query(({input}) => `Hello, ${input.name}!`), 13 | // ^? {name: string} 14 | }); 15 | -------------------------------------------------------------------------------- /packages/yup/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../../../tsconfig.test.json", 4 | "include": ["*.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/yup/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type { 6 | InputFrom, 7 | OutputFrom, 8 | SchemaFrom, 9 | UnknownIfNever, 10 | } from '@typeschema/core'; 11 | 12 | import { 13 | createAssert, 14 | createValidate, 15 | createWrap, 16 | createToJSONSchema, 17 | } from '@typeschema/core'; 18 | 19 | import {AdapterResolver} from './resolver'; 20 | import {validationAdapter} from './validation'; 21 | import {serializationAdapter} from './serialization'; 22 | 23 | export type Schema = SchemaFrom; 24 | export type Infer = UnknownIfNever< 25 | OutputFrom 26 | >; 27 | export type InferIn = UnknownIfNever< 28 | InputFrom 29 | >; 30 | 31 | export const validate = createValidate(validationAdapter); 32 | export const assert = createAssert(validate); 33 | export const wrap = createWrap(assert, validate); 34 | 35 | export const toJSONSchema = createToJSONSchema(serializationAdapter); 36 | 37 | export { 38 | AdapterResolver, 39 | validationAdapter, 40 | serializationAdapter, 41 | }; 42 | -------------------------------------------------------------------------------- /packages/yup/src/resolver.ts: -------------------------------------------------------------------------------- 1 | import type {IfDefined, Resolver} from '@typeschema/core'; 2 | import type {InferType, Schema} from 'yup'; 3 | 4 | export interface AdapterResolver extends Resolver { 5 | base: IfDefined; 6 | input: this['schema'] extends this['base'] 7 | ? InferType 8 | : never; 9 | output: this['schema'] extends this['base'] 10 | ? InferType 11 | : never; 12 | } 13 | -------------------------------------------------------------------------------- /packages/yup/src/serialization.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {SerializationAdapter} from '@typeschema/core'; 3 | 4 | import {memoize} from '@typeschema/core'; 5 | 6 | const importSerializationModule = memoize(async () => { 7 | const {convertSchema} = await import('@sodaru/yup-to-json-schema'); 8 | return {convertSchema}; 9 | }); 10 | 11 | export const serializationAdapter: SerializationAdapter< 12 | AdapterResolver 13 | > = async schema => { 14 | const {convertSchema} = await importSerializationModule(); 15 | return convertSchema(schema); 16 | }; 17 | -------------------------------------------------------------------------------- /packages/yup/src/validation.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {ValidationAdapter} from '@typeschema/core'; 3 | 4 | import {memoize} from '@typeschema/core'; 5 | 6 | const importValidationModule = memoize(async () => { 7 | const {ValidationError} = await import('yup'); 8 | return {ValidationError}; 9 | }); 10 | 11 | export const validationAdapter: ValidationAdapter< 12 | AdapterResolver 13 | > = async schema => { 14 | const {ValidationError} = await importValidationModule(); 15 | return async data => { 16 | try { 17 | return { 18 | data: await schema.validate(data, {strict: true}), 19 | success: true, 20 | }; 21 | } catch (error) { 22 | if (error instanceof ValidationError) { 23 | const {message, path} = error; 24 | return { 25 | issues: [ 26 | { 27 | message, 28 | path: path != null && path !== '' ? [path] : undefined, 29 | }, 30 | ], 31 | success: false, 32 | }; 33 | } 34 | throw error; 35 | } 36 | }; 37 | }; 38 | -------------------------------------------------------------------------------- /packages/yup/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/zod/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @typeschema/zod 2 | 3 | ## 0.14.0 4 | 5 | ### Minor Changes 6 | 7 | - 14976b2: Upgrade deps 8 | 9 | ### Patch Changes 10 | 11 | - Updated dependencies [2251f01] 12 | - Updated dependencies [14976b2] 13 | - @typeschema/core@0.14.0 14 | 15 | ## 0.13.3 16 | 17 | ### Patch Changes 18 | 19 | - 6c178f0: Fix Vite support 20 | 21 | ## 0.13.2 22 | 23 | ### Patch Changes 24 | 25 | - 3087916: Improve handling missing types 26 | - Updated dependencies [3087916] 27 | - @typeschema/core@0.13.2 28 | 29 | ## 0.13.1 30 | 31 | ### Patch Changes 32 | 33 | - 6f1fc2d: Export the Schema type 34 | - Updated dependencies [6f1fc2d] 35 | - @typeschema/core@0.13.1 36 | 37 | ## 0.13.0 38 | 39 | ### Minor Changes 40 | 41 | - 05b430e: Package restructure 42 | 43 | ### Patch Changes 44 | 45 | - Updated dependencies [05b430e] 46 | - @typeschema/core@0.13.0 47 | -------------------------------------------------------------------------------- /packages/zod/src/__tests__/example.ts: -------------------------------------------------------------------------------- 1 | import {initTRPC} from '@trpc/server'; 2 | import {z} from 'zod'; 3 | 4 | import {wrap} from '..'; 5 | 6 | const schema = z.object({name: z.string()}); 7 | 8 | const t = initTRPC.create(); 9 | const appRouter = t.router({ 10 | hello: t.procedure 11 | .input(wrap(schema)) 12 | .query(({input}) => `Hello, ${input.name}!`), 13 | // ^? {name: string} 14 | }); 15 | -------------------------------------------------------------------------------- /packages/zod/src/__tests__/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../../../tsconfig.test.json", 4 | "include": ["*.ts"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/zod/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is generated. Do not modify it manually! 3 | */ 4 | 5 | import type { 6 | InputFrom, 7 | OutputFrom, 8 | SchemaFrom, 9 | UnknownIfNever, 10 | } from '@typeschema/core'; 11 | 12 | import { 13 | createAssert, 14 | createValidate, 15 | createWrap, 16 | createToJSONSchema, 17 | } from '@typeschema/core'; 18 | 19 | import {AdapterResolver} from './resolver'; 20 | import {validationAdapter} from './validation'; 21 | import {serializationAdapter} from './serialization'; 22 | 23 | export type Schema = SchemaFrom; 24 | export type Infer = UnknownIfNever< 25 | OutputFrom 26 | >; 27 | export type InferIn = UnknownIfNever< 28 | InputFrom 29 | >; 30 | 31 | export const validate = createValidate(validationAdapter); 32 | export const assert = createAssert(validate); 33 | export const wrap = createWrap(assert, validate); 34 | 35 | export const toJSONSchema = createToJSONSchema(serializationAdapter); 36 | 37 | export { 38 | AdapterResolver, 39 | validationAdapter, 40 | serializationAdapter, 41 | }; 42 | -------------------------------------------------------------------------------- /packages/zod/src/resolver.ts: -------------------------------------------------------------------------------- 1 | import type {IfDefined, Resolver} from '@typeschema/core'; 2 | import type {input, output, ZodType} from 'zod'; 3 | 4 | export interface AdapterResolver extends Resolver { 5 | base: IfDefined; 6 | input: this['schema'] extends this['base'] ? input : never; 7 | output: this['schema'] extends this['base'] ? output : never; 8 | } 9 | -------------------------------------------------------------------------------- /packages/zod/src/serialization.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {SerializationAdapter} from '@typeschema/core'; 3 | 4 | import {memoize} from '@typeschema/core'; 5 | 6 | const importSerializationModule = memoize(async () => { 7 | const {zodToJsonSchema} = await import('zod-to-json-schema'); 8 | return {zodToJsonSchema}; 9 | }); 10 | 11 | export const serializationAdapter: SerializationAdapter< 12 | AdapterResolver 13 | > = async schema => { 14 | const {zodToJsonSchema} = await importSerializationModule(); 15 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 16 | return zodToJsonSchema(schema) as any; 17 | }; 18 | -------------------------------------------------------------------------------- /packages/zod/src/validation.ts: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {ValidationAdapter} from '@typeschema/core'; 3 | 4 | export const validationAdapter: ValidationAdapter< 5 | AdapterResolver 6 | > = async schema => { 7 | return async data => { 8 | const result = await schema.safeParseAsync(data); 9 | if (result.success) { 10 | return { 11 | data: result.data, 12 | success: true, 13 | }; 14 | } 15 | return { 16 | issues: result.error.issues.map(({message, path}) => ({message, path})), 17 | success: false, 18 | }; 19 | }; 20 | }; 21 | -------------------------------------------------------------------------------- /packages/zod/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "//": "This file is generated. Do not modify it manually!", 3 | "extends": "../../tsconfig.json", 4 | "include": ["src"] 5 | } 6 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'examples/*' 3 | - 'packages/*' -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": true, 4 | "skipLibCheck": true, 5 | "target": "ES2022", 6 | "strict": true, 7 | "noUncheckedIndexedAccess": true, 8 | "moduleResolution": "Bundler", 9 | "module": "ESNext", 10 | "noEmit": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tsconfig.test.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "moduleResolution": "Node", 5 | "rootDir": "..", 6 | "plugins": [{"transform": "typia/lib/transform"}], 7 | "experimentalDecorators": true, 8 | "paths": { 9 | "tslib": ["./node_modules/tslib/tslib.d.ts"] 10 | } 11 | }, 12 | "reflection": true 13 | } 14 | -------------------------------------------------------------------------------- /tsup.config.ts: -------------------------------------------------------------------------------- 1 | import type {Plugin} from 'esbuild'; 2 | 3 | import fs from 'node:fs'; 4 | 5 | import { 6 | anyOf, 7 | char, 8 | createRegExp, 9 | exactly, 10 | global, 11 | maybe, 12 | multiline, 13 | oneOrMore, 14 | whitespace, 15 | wordChar, 16 | } from 'magic-regexp'; 17 | import {defineConfig} from 'tsup'; 18 | 19 | const regex = createRegExp( 20 | maybe(oneOrMore(whitespace)).groupedAs('indentation'), 21 | anyOf('const', 'let', 'var').groupedAs('declarationType'), 22 | oneOrMore(whitespace), 23 | oneOrMore(wordChar).or('{', oneOrMore(char), '}').groupedAs('variableName'), 24 | oneOrMore(whitespace), 25 | '=', 26 | oneOrMore(whitespace), 27 | maybe('await', oneOrMore(whitespace)).groupedAs('await'), 28 | 'import(', 29 | maybe(oneOrMore(whitespace)), 30 | exactly("'", oneOrMore(char), "'") 31 | .or('"', oneOrMore(char), '"') 32 | .groupedAs('modulePath'), 33 | maybe(oneOrMore(whitespace)), 34 | ')', 35 | maybe(';').groupedAs('terminator'), 36 | [global, multiline], 37 | ); 38 | const template = ` 39 | try { 40 | var dynamicallyImportedModule = $import( 41 | /* webpackIgnore: true */ 42 | $ 43 | )$ 44 | } catch (moduleImportError) { 45 | throw moduleImportError$ 46 | } 47 | $ $ = dynamicallyImportedModule$ 48 | `.trim(); 49 | 50 | const optionalPeerDependenciesPlugin: Plugin = { 51 | name: 'optionalPeerDependencies', 52 | setup(build) { 53 | build.onLoad({filter: /\.ts$/}, async args => ({ 54 | contents: fs.readFileSync(args.path, 'utf-8').replace(regex, template), 55 | loader: 'ts', 56 | })); 57 | }, 58 | }; 59 | 60 | export default defineConfig({ 61 | clean: true, 62 | dts: true, 63 | entry: ['src/index.ts'], 64 | esbuildPlugins: [optionalPeerDependenciesPlugin], 65 | format: ['esm', 'cjs'], 66 | }); 67 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "globalDependencies": [ 4 | "tsconfig.json", 5 | "tsconfig.test.json", 6 | ".eslintrc.json", 7 | ".prettierrc.json", 8 | "tsup.config.ts", 9 | "vitest.config.ts" 10 | ], 11 | "tasks": { 12 | "build": { 13 | "dependsOn": ["sync:pnpm"], 14 | "outputs": ["dist/**"] 15 | }, 16 | "lint": {}, 17 | "lint:package": { 18 | "dependsOn": ["build"] 19 | }, 20 | "test": { 21 | "cache": false, 22 | "dependsOn": ["sync:pnpm"] 23 | }, 24 | "upgrade:deps": { 25 | "cache": false 26 | }, 27 | "sync:pnpm": { 28 | "cache": false, 29 | "dependsOn": ["^build"] 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /turbo/generators/templates/README-api.md.hbs: -------------------------------------------------------------------------------- 1 | ## API 2 | {{#if canInfer.output}} 3 | 4 | ### Inference 5 | - `Infer`: Extracts the output type of a schema 6 | {{#if canInfer.input}} 7 | - `InferIn`: Extracts the input type of a schema 8 | {{/if}} 9 | {{/if}} 10 | {{#if hasModule.validation}} 11 | 12 | ### Validation 13 | - `wrap(schema)`: Returns the wrapped schema with access to its operations 14 | - `validate(schema, data)`: Returns the validated data or a list of validation issues 15 | - `assert(schema, data)`: Returns the validated data or throws an `AggregateError` 16 | {{/if}} 17 | {{#if hasModule.serialization}} 18 | 19 | ### Serialization 20 | - `toJSONSchema(schema)`: Converts the schema into the equivalent JSON schema 21 | {{/if}} -------------------------------------------------------------------------------- /turbo/generators/templates/adapter/README.md.hbs: -------------------------------------------------------------------------------- 1 | TypeSchema 2 |

@typeschema/{{name}}

3 |

4 | License 5 | Bundle size 6 | npm downloads 7 | GitHub stars 8 |

9 |

10 | {{packageJson.description}} 11 |
12 | https://typeschema.com ✨ 13 |

14 | {{#if example}} 15 | 16 | ```ts 17 | {{{example}}} 18 | ``` 19 | {{/if}} 20 | {{#unless isMultipleAdapter}} 21 | 22 | Use it directly or through [`@typeschema/main`](https://github.com/decs/typeschema/tree/main/packages/main) 23 | {{/unless}} 24 | 25 | {{#unless isMultipleAdapter}} 26 | {{#unless (isEmpty packageJson.peerDependencies)}} 27 | ## Dependencies 28 | {{#each packageJson.peerDependencies}} 29 | - [`{{@key}}`](https://www.npmjs.com/package/{{@key}}): {{lookup @root/packageJson.[//peerDependencies] @key}} (`{{this}}`) 30 | {{/each}} 31 | 32 | {{/unless}} 33 | {{/unless}} 34 | {{> readmeAPI this}} -------------------------------------------------------------------------------- /turbo/generators/templates/adapter/package.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | {{> packageJson name=name adapters=[this]}} 3 | "dependencies": { 4 | "@typeschema/core": "workspace:*", 5 | }, 6 | "//devDependencies": "This field is manually maintained.", 7 | "devDependencies": {}, 8 | "//peerDependencies": "This field is manually maintained.", 9 | "peerDependencies": {}, 10 | "//peerDependenciesMeta": "This field is manually maintained.", 11 | "peerDependenciesMeta": {} 12 | } 13 | -------------------------------------------------------------------------------- /turbo/generators/templates/adapter/src/__tests__/tsconfig.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../../tsconfig.test.json", 3 | "include": ["*.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /turbo/generators/templates/adapter/src/index.ts.hbs: -------------------------------------------------------------------------------- 1 | import type { 2 | InputFrom, 3 | OutputFrom, 4 | SchemaFrom, 5 | UnknownIfNever, 6 | } from '@typeschema/core'; 7 | 8 | import { 9 | {{#if hasModule.validation}} 10 | createAssert, 11 | createValidate, 12 | createWrap, 13 | {{/if}} 14 | {{#if hasModule.serialization}} 15 | createToJSONSchema, 16 | {{/if}} 17 | } from '@typeschema/core'; 18 | 19 | import {AdapterResolver} from './resolver'; 20 | {{#if hasModule.validation}} 21 | import {validationAdapter} from './validation'; 22 | {{/if}} 23 | {{#if hasModule.serialization}} 24 | import {serializationAdapter} from './serialization'; 25 | {{/if}} 26 | 27 | export type Schema = SchemaFrom; 28 | export type Infer = UnknownIfNever< 29 | OutputFrom 30 | >; 31 | export type InferIn = UnknownIfNever< 32 | InputFrom 33 | >; 34 | 35 | {{#if hasModule.validation}} 36 | export const validate = createValidate(validationAdapter); 37 | export const assert = createAssert(validate); 38 | export const wrap = createWrap(assert, validate); 39 | {{/if}} 40 | 41 | {{#if hasModule.serialization}} 42 | export const toJSONSchema = createToJSONSchema(serializationAdapter); 43 | {{/if}} 44 | 45 | export { 46 | AdapterResolver, 47 | {{#if hasModule.validation}} 48 | validationAdapter, 49 | {{/if}} 50 | {{#if hasModule.serialization}} 51 | serializationAdapter, 52 | {{/if}} 53 | }; 54 | -------------------------------------------------------------------------------- /turbo/generators/templates/adapter/tsconfig.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "include": ["src"] 4 | } 5 | -------------------------------------------------------------------------------- /turbo/generators/templates/all/package.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | {{> packageJson name="all" adapters=singleAdapters}} 3 | "dependencies": { 4 | "@typeschema/core": "workspace:*", 5 | "@typeschema/main": "workspace:*", 6 | {{#each singleAdapters}} 7 | "@typeschema/{{name}}": "workspace:*", 8 | {{/each}} 9 | }, 10 | "devDependencies": { 11 | {{#each singleAdapters}} 12 | {{#each packageJson.devDependencies}} 13 | "{{@key}}": "{{this}}", 14 | {{/each}} 15 | {{/each}} 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /turbo/generators/templates/create-adapter/src/__tests__/example.ts.hbs: -------------------------------------------------------------------------------- 1 | import {initTRPC} from '@trpc/server'; 2 | 3 | import {wrap} from '..'; 4 | 5 | const schema = $FixMe; 6 | 7 | const t = initTRPC.create(); 8 | const appRouter = t.router({ 9 | hello: t.procedure 10 | .input(wrap(schema)) 11 | .query(({input}) => `Hello, ${input.name}!`), 12 | // ^? {name: string} 13 | }); 14 | -------------------------------------------------------------------------------- /turbo/generators/templates/create-adapter/src/resolver.ts.hbs: -------------------------------------------------------------------------------- 1 | import type {IfDefined, Resolver} from '@typeschema/core'; 2 | 3 | export interface AdapterResolver extends Resolver { 4 | base: IfDefined<$FixMe, '$FixMe'>; 5 | input: this['schema'] extends this['base'] ? $FixMe : never; 6 | output: this['schema'] extends this['base'] ? $FixMe : never; 7 | } 8 | -------------------------------------------------------------------------------- /turbo/generators/templates/create-adapter/src/validation.ts.hbs: -------------------------------------------------------------------------------- 1 | import type {AdapterResolver} from './resolver'; 2 | import type {ValidationAdapter} from '@typeschema/core'; 3 | 4 | import {memoize} from '@typeschema/core'; 5 | 6 | const importValidationModule = memoize(async () => { 7 | const {$FixMe} = await import('$FixMe'); 8 | return {$FixMe}; 9 | }); 10 | 11 | export const validationAdapter: ValidationAdapter< 12 | AdapterResolver 13 | > = async schema => { 14 | const {$FixMe} = await importValidationModule(); 15 | return async data => { 16 | return $FixMe; 17 | }; 18 | }; 19 | -------------------------------------------------------------------------------- /turbo/generators/templates/main/package.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | {{> packageJson name="main" adapters=singleAdapters}} 3 | "dependencies": { 4 | "@typeschema/core": "workspace:*" 5 | }, 6 | "devDependencies": { 7 | {{#each singleAdapters}} 8 | "@typeschema/{{name}}": "workspace:*", 9 | {{#each packageJson.devDependencies}} 10 | "{{@key}}": "{{this}}", 11 | {{/each}} 12 | {{/each}} 13 | }, 14 | "peerDependencies": { 15 | {{#each singleAdapters}} 16 | "@typeschema/{{name}}": "workspace:*", 17 | {{/each}} 18 | }, 19 | "peerDependenciesMeta": { 20 | {{#each singleAdapters}} 21 | "@typeschema/{{name}}": { 22 | "optional": true 23 | }, 24 | {{/each}} 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /turbo/generators/templates/main/src/adapters.ts.hbs: -------------------------------------------------------------------------------- 1 | {{#each singleAdapters}} 2 | import type {AdapterResolver as {{pascalCase name}}Resolver} from '@typeschema/{{name}}'; 3 | {{/each}} 4 | 5 | export type AdapterResolvers = { 6 | {{#each singleAdapters}} 7 | {{camelCase name}}: {{pascalCase name}}Resolver; 8 | {{/each}} 9 | }; 10 | -------------------------------------------------------------------------------- /turbo/generators/templates/main/src/serialization.ts.hbs: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 2 | import type {AdapterResolvers} from './adapters'; 3 | import type {AdapterResolver} from './resolver'; 4 | import type {SerializationAdapter} from '@typeschema/core'; 5 | 6 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 7 | import {memoize, unsupportedAdapter} from '@typeschema/core'; 8 | 9 | import {select} from './selector'; 10 | 11 | {{#each singleAdapters}} 12 | {{#if hasModule.serialization}} 13 | const import{{pascalCase name}}SerializationAdapter = memoize(async () => { 14 | const {serializationAdapter} = await import('@typeschema/{{name}}'); 15 | return serializationAdapter; 16 | }); 17 | 18 | {{/if}} 19 | {{/each}} 20 | export const serializationAdapter: SerializationAdapter = select({ 21 | {{#each singleAdapters}} 22 | {{#if hasModule.serialization}} 23 | {{camelCase name}}: async schema => (await import{{pascalCase name}}SerializationAdapter())(schema), 24 | {{else}} 25 | {{camelCase name}}: unsupportedAdapter('@typeschema/{{name}}'), 26 | {{/if}} 27 | {{/each}} 28 | }); 29 | -------------------------------------------------------------------------------- /turbo/generators/templates/main/src/validation.ts.hbs: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 2 | import type {AdapterResolvers} from './adapters'; 3 | import type {AdapterResolver} from './resolver'; 4 | import type {ValidationAdapter} from '@typeschema/core'; 5 | 6 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 7 | import {memoize, unsupportedAdapter} from '@typeschema/core'; 8 | 9 | import {select} from './selector'; 10 | 11 | {{#each singleAdapters}} 12 | {{#if hasModule.validation}} 13 | const import{{pascalCase name}}ValidationAdapter = memoize(async () => { 14 | const {validationAdapter} = await import('@typeschema/{{name}}'); 15 | return validationAdapter; 16 | }); 17 | 18 | {{/if}} 19 | {{/each}} 20 | export const validationAdapter: ValidationAdapter = select({ 21 | {{#each singleAdapters}} 22 | {{#if hasModule.validation}} 23 | {{camelCase name}}: async schema => (await import{{pascalCase name}}ValidationAdapter())(schema), 24 | {{else}} 25 | {{camelCase name}}: unsupportedAdapter('@typeschema/{{name}}'), 26 | {{/if}} 27 | {{/each}} 28 | }); 29 | -------------------------------------------------------------------------------- /turbo/generators/templates/package.json.hbs: -------------------------------------------------------------------------------- 1 | "name": "@typeschema/{{name}}", 2 | "//version": "This field is manually maintained.", 3 | "version": "0.0.0", 4 | "//description": "This field is manually maintained.", 5 | "description": "Universal adapter for schema validation", 6 | "keywords": [ 7 | "typescript", 8 | "type", 9 | "schema", 10 | "adapter", 11 | "validation", 12 | "inference", 13 | "assert", 14 | {{#each adapters}} 15 | "{{name}}", 16 | {{/each}} 17 | ], 18 | "homepage": "https://typeschema.com", 19 | "license": "MIT", 20 | "author": { 21 | "name": "André Costa", 22 | "email": "andrefonsecacosta@gmail.com" 23 | }, 24 | "publishConfig": { 25 | "access": "public", 26 | "registry": "https://registry.npmjs.org/" 27 | }, 28 | "files": [ 29 | "/dist" 30 | ], 31 | "main": "dist/index.js", 32 | "module": "dist/index.mjs", 33 | "types": "dist/index.d.ts", 34 | "exports": { 35 | ".": { 36 | "import": { 37 | "types": "./dist/index.d.mts", 38 | "default": "./dist/index.mjs" 39 | }, 40 | "require": { 41 | "types": "./dist/index.d.ts", 42 | "default": "./dist/index.js" 43 | } 44 | } 45 | }, 46 | "sideEffects": false, 47 | "repository": { 48 | "type": "git", 49 | "url": "https://github.com/decs/typeschema.git" 50 | }, 51 | "scripts": { 52 | "build": "tsup --config ../../tsup.config.ts", 53 | "lint": "eslint src --fix", 54 | "lint:package": "publint && attw --pack", 55 | "test": "vitest --config ../../vitest.config.ts", 56 | "upgrade:deps": "ncu -u --dep=dev,peer --reject ow" 57 | }, -------------------------------------------------------------------------------- /vitest.config.ts: -------------------------------------------------------------------------------- 1 | import {deepkitType} from '@deepkit/vite'; 2 | import typescript from 'rollup-plugin-typescript2'; 3 | import {defineConfig} from 'vitest/config'; 4 | 5 | export default defineConfig({ 6 | esbuild: false, 7 | plugins: [ 8 | typescript({ 9 | exclude: './**/deepkit.test.ts', 10 | tsconfig: './src/__tests__/tsconfig.json', 11 | }), 12 | deepkitType({ 13 | include: './**/deepkit.test.ts', 14 | tsConfig: './src/__tests__/tsconfig.json', 15 | }), 16 | ], 17 | test: {watch: false}, 18 | }); 19 | -------------------------------------------------------------------------------- /www/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /www/next.config.mjs: -------------------------------------------------------------------------------- 1 | import nextra from 'nextra'; 2 | 3 | const withNextra = nextra({ 4 | theme: 'nextra-theme-docs', 5 | themeConfig: './theme.config.tsx', 6 | }); 7 | 8 | /** @type {import('next').NextConfig} */ 9 | export default withNextra({}); 10 | -------------------------------------------------------------------------------- /www/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "www", 3 | "version": "1.0.0", 4 | "license": "MIT", 5 | "private": true, 6 | "main": "index.js", 7 | "scripts": { 8 | "dev": "next dev", 9 | "build": "next build", 10 | "start": "next start" 11 | }, 12 | "dependencies": { 13 | "clsx": "^2.0.0", 14 | "next": "^13.4.19", 15 | "nextra": "^2.12.2", 16 | "nextra-theme-docs": "^2.12.2", 17 | "react": "^18.2.0", 18 | "react-dom": "^18.2.0" 19 | }, 20 | "devDependencies": { 21 | "@types/node": "^20.5.7", 22 | "autoprefixer": "^10.4.15", 23 | "eslint": "^8.48.0", 24 | "postcss": "^8.4.28", 25 | "tailwindcss": "^3.3.3", 26 | "typescript": "^5.2.2" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /www/pages/_app.mdx: -------------------------------------------------------------------------------- 1 | import '../styles.css'; 2 | 3 | export default function App({Component, pageProps}) { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /www/pages/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": { 3 | "title": "Universal adapter for schema validation", 4 | "type": "page", 5 | "display": "hidden" 6 | }, 7 | "docs": { 8 | "title": "Documentation", 9 | "type": "page" 10 | }, 11 | "npm": { 12 | "title": "npm", 13 | "type": "page", 14 | "href": "https://www.npmjs.com/package/@decs/typeschema", 15 | "newWindow": true 16 | }, 17 | "deno": { 18 | "title": "Deno", 19 | "type": "page", 20 | "href": "https://deno.land/x/typeschema", 21 | "newWindow": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /www/pages/docs/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": "Quickstart", 3 | "setup": "", 4 | "usage": "", 5 | "coverage": "", 6 | "reference": "", 7 | "credits": "" 8 | } 9 | -------------------------------------------------------------------------------- /www/pages/docs/credits.mdx: -------------------------------------------------------------------------------- 1 | # Credits 2 | 3 | - Inspired by [tRPC](https://trpc.io/)'s [input & output validators](https://trpc.io/docs/server/validators) 4 | - Adapter architecture inspired by [@ecyrbe](https://github.com/ecyrbe)'s [suggestions](https://github.com/decs/typeschema/issues/1) 5 | - API definition inspired by [@colinhacks](https://github.com/colinhacks)'s [proposal](https://twitter.com/colinhacks/status/1634284724796661761) 6 | - Logo designed by [flaticon](https://www.flaticon.com/) 7 | -------------------------------------------------------------------------------- /www/pages/docs/index.mdx: -------------------------------------------------------------------------------- 1 | import {Steps} from 'nextra/components'; 2 | 3 | # Quickstart 4 | 5 | Many libraries rely on some sort of type validation. Their maintainers have the choice of either to: 6 | 7 | 1. ⁠**Implement their own** validation logic: which leads to more code to maintain, and we already have many good solutions out there (e.g. [`zod`](https://zod.dev), [`arktype`](https://arktype.io), [`typia`](https://typia.io)) 8 | 1. **Couple their code** with a specific validation library: which limits adoption by developers who use another 9 | 1. **Support multiple** validation libraries: which is a burden to keep up-to-date (e.g. [tRPC](https://trpc.io/)) 10 | 11 | There's no best validation library because there's always a tradeoff. Each developer chooses the library that makes the most sense to them. TypeSchema solves this problem by easily providing option 3: **support multiple validation libraries out-of-the-box.** 12 | 13 | 14 | 15 | ### Install it 16 | 17 | ```sh npm2yarn 18 | npm install @decs/typeschema 19 | ``` 20 | 21 | Plus some optional [setup steps](/docs/setup). 22 | 23 | ### Use it 24 | 25 | ```ts 26 | import {wrap} from '@decs/typeschema'; 27 | import {z} from 'zod'; 28 | 29 | // Use your favorite validation library, e.g. `zod` 30 | const wrapped = wrap(z.string()); 31 | 32 | await wrapped.validate('123'); // {success: true, data: '123'} 33 | await wrapped.assert('123'); // '123' 34 | ``` 35 | 36 | And check other [use cases](/docs/usage). 37 | 38 | 39 | -------------------------------------------------------------------------------- /www/pages/docs/reference.mdx: -------------------------------------------------------------------------------- 1 | # Reference 2 | 3 | ## Functions 4 | 5 | #### `wrap` 6 | 7 | ```ts 8 | function wrap( 9 | schema: TSchema, 10 | ): TypeSchema, InferIn> { ... } 11 | ``` 12 | 13 | Returns the wrapped schema with access to all its operations. 14 | 15 | #### `validate` 16 | 17 | ```ts 18 | function validate( 19 | schema: TSchema, 20 | data: unknown, 21 | ): Promise>> { ... } 22 | ``` 23 | 24 | Returns the validated data or a list of `ValidationIssue`s. 25 | 26 | #### `assert` 27 | 28 | ```ts 29 | function assert( 30 | schema: TSchema, 31 | data: unknown, 32 | ): Promise> { ... } 33 | ``` 34 | 35 | Returns the validated data or throws an `AggregateError`. 36 | 37 | ## Types 38 | 39 | #### `Schema` 40 | 41 | Generic interface for schemas. An union of the schema types of all supported libraries. 42 | 43 | #### `TypeSchema` 44 | 45 | Interface for a wrapped schema, exposing all its operations. 46 | 47 | #### `Infer` 48 | 49 | Extracts the output type of a schema. 50 | 51 | #### `InferIn` 52 | 53 | Extracts the input type of a schema. 54 | 55 | #### `ValidationIssue` 56 | 57 | Generic interface for validation issues. Includes a `message` and an optional `path`. 58 | -------------------------------------------------------------------------------- /www/pages/docs/setup.mdx: -------------------------------------------------------------------------------- 1 | # Setup 2 | 3 | Install TypeSchema with your package manager of choice: 4 | 5 | ```sh npm2yarn 6 | npm install @decs/typeschema 7 | ``` 8 | 9 | ### Deno 10 | 11 | If using [Deno](https://deno.com/), just replace the import module with `https://deno.land/x/typeschema`: 12 | 13 | ```ts 14 | import {wrap} from 'https://deno.land/x/typeschema'; 15 | ``` 16 | -------------------------------------------------------------------------------- /www/pages/docs/usage.mdx: -------------------------------------------------------------------------------- 1 | # Usage 2 | 3 | ```ts 4 | import type {Infer, InferIn, Schema} from '@decs/typeschema'; 5 | import {assert, validate, wrap} from '@decs/typeschema'; 6 | 7 | // Use your favorite validation library, e.g. `zod`, `arktype`, `typia` 8 | const schema: Schema = z.string(); 9 | const schema: Schema = type('string'); 10 | const schema: Schema = typia.createAssert(); 11 | 12 | // Extracts the schema type 13 | type Output = Infer; // `string` 14 | type Input = InferIn; // `string` 15 | 16 | // Returns the wrapped schema with access to all its operations 17 | const wrapped = wrap(schema); 18 | await wrapped.validate('123'); // {success: true, data: '123'} 19 | await wrapped.assert('123'); // '123' 20 | 21 | // Returns the validated data or a list of `ValidationIssue`s 22 | await validate(schema, '123'); // {success: true, data: '123'} 23 | await validate(schema, 123); // {success: false, issues: [`ValidationIssue`]} 24 | 25 | // Returns the validated data or throws an `AggregateError` 26 | await assert(schema, '123'); // '123' 27 | await assert(schema, 123); // throws `AggregateError` 28 | ``` 29 | 30 | ### tRPC 31 | 32 | You can use any supported schema on [tRPC](https://trpc.io/) through the [`wrap`](/docs/reference#wrap) function: 33 | 34 | ```ts 35 | import {wrap} from '@decs/typeschema'; 36 | import {initTRPC} from '@trpc/server'; 37 | import {object, string} from 'valibot'; 38 | 39 | // Use your favorite validation library, e.g. `valibot` 40 | const schema = object({name: string()}); 41 | 42 | const t = initTRPC.create(); 43 | const appRouter = t.router({ 44 | hello: t.procedure 45 | .input(wrap(schema)) // like this 46 | .query(({input}) => `Hello, ${input.name}!`), 47 | }); 48 | ``` 49 | -------------------------------------------------------------------------------- /www/pages/index.mdx: -------------------------------------------------------------------------------- 1 | import Hero from '@/components/Hero'; 2 | 3 | 4 | 5 |
6 | 🚀 Decouple from schema validation libraries
7 | 🍃 Tiny client footprint, tree-shakeable
8 | 🛋️ Easy-to-use, minimal API 9 |
-------------------------------------------------------------------------------- /www/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /www/public/logo128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/decs/typeschema/a5c728db9f4f1355a1df04d73091531862084a5e/www/public/logo128.png -------------------------------------------------------------------------------- /www/public/logo16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/decs/typeschema/a5c728db9f4f1355a1df04d73091531862084a5e/www/public/logo16.png -------------------------------------------------------------------------------- /www/public/logo24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/decs/typeschema/a5c728db9f4f1355a1df04d73091531862084a5e/www/public/logo24.png -------------------------------------------------------------------------------- /www/public/logo32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/decs/typeschema/a5c728db9f4f1355a1df04d73091531862084a5e/www/public/logo32.png -------------------------------------------------------------------------------- /www/public/logo64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/decs/typeschema/a5c728db9f4f1355a1df04d73091531862084a5e/www/public/logo64.png -------------------------------------------------------------------------------- /www/styles.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; -------------------------------------------------------------------------------- /www/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | './components/**/*.{ts,tsx}', 5 | './pages/**/*.{md,mdx}', 6 | './theme.config.tsx', 7 | ], 8 | }; 9 | -------------------------------------------------------------------------------- /www/theme.config.tsx: -------------------------------------------------------------------------------- 1 | import type {DocsThemeConfig} from 'nextra-theme-docs'; 2 | 3 | import Image from 'next/image'; 4 | 5 | const logo = ( 6 |
7 | TypeSchema 8 | TypeSchema 9 |
10 | ); 11 | 12 | const config: DocsThemeConfig = { 13 | darkMode: false, 14 | docsRepositoryBase: 'https://github.com/decs/typeschema/www', 15 | feedback: {content: null}, 16 | footer: {component: null}, 17 | gitTimestamp: null, 18 | head: ( 19 | <> 20 | 21 | 22 | 23 | 24 | 25 | 26 | ), 27 | logo, 28 | primaryHue: 211, 29 | project: {link: 'https://github.com/decs/typeschema'}, 30 | useNextSeoProps() { 31 | return { 32 | titleTemplate: '%s — TypeSchema', 33 | }; 34 | } 35 | }; 36 | 37 | export default config; 38 | -------------------------------------------------------------------------------- /www/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "lib": ["dom", "dom.iterable", "esnext"], 6 | "allowJs": true, 7 | "noEmit": true, 8 | "incremental": true, 9 | "moduleResolution": "node", 10 | "resolveJsonModule": true, 11 | "isolatedModules": true, 12 | "jsx": "preserve", 13 | "paths": {"@/*": ["./*"]} 14 | }, 15 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], 16 | "exclude": ["node_modules"] 17 | } 18 | --------------------------------------------------------------------------------