@decs/typeschema
Advanced tools
Comparing version 0.5.2 to 0.6.0
@@ -30,3 +30,3 @@ "use strict"; | ||
let ajv = null; | ||
(0, registry_1.register)(schema => ((0, utils_1.isJSONSchema)(schema) ? schema : null), async (schema) => { | ||
(registry_1.register.Ω = [undefined], (0, registry_1.register)(schema => ((0, utils_1.isJSONSchema)(schema) ? schema : null), async (schema) => { | ||
if (ajv == null) { | ||
@@ -48,2 +48,2 @@ const Ajv = await Promise.resolve().then(() => __importStar(require('ajv'))); | ||
}; | ||
}, 'ajv'); | ||
}, 'ajv')); |
@@ -6,3 +6,3 @@ "use strict"; | ||
const utils_1 = require("../utils"); | ||
(0, registry_1.register)(schema => 'infer' in schema && !(0, utils_1.isTypeBoxSchema)(schema) && !(0, utils_1.isJSONSchema)(schema) | ||
(registry_1.register.Ω = [undefined], (0, registry_1.register)(schema => 'infer' in schema && !(0, utils_1.isTypeBoxSchema)(schema) && !(0, utils_1.isJSONSchema)(schema) | ||
? schema | ||
@@ -19,2 +19,2 @@ : null, async (schema) => ({ | ||
}, | ||
}), 'arktype'); | ||
}), 'arktype')); |
@@ -5,3 +5,3 @@ "use strict"; | ||
const schema_1 = require("../schema"); | ||
(0, registry_1.register)(schema => typeof schema === 'function' && !('assert' in schema) ? schema : null, async (schema) => ({ | ||
(registry_1.register.Ω = [undefined], (0, registry_1.register)(schema => typeof schema === 'function' && !('assert' in schema) ? schema : null, async (schema) => ({ | ||
validate: async (data) => { | ||
@@ -18,2 +18,2 @@ try { | ||
}, | ||
})); | ||
}))); |
import './ajv'; | ||
import './arktype'; | ||
import './deepkit'; | ||
import './function'; | ||
import './io-ts'; | ||
import './joi'; | ||
import './ow'; | ||
import './runtypes'; | ||
@@ -7,0 +9,0 @@ import './superstruct'; |
@@ -5,5 +5,7 @@ "use strict"; | ||
require("./arktype"); | ||
require("./deepkit"); | ||
require("./function"); | ||
require("./io-ts"); | ||
require("./joi"); | ||
require("./ow"); | ||
require("./runtypes"); | ||
@@ -10,0 +12,0 @@ require("./superstruct"); |
@@ -29,3 +29,3 @@ "use strict"; | ||
const utils_1 = require("../utils"); | ||
(0, registry_1.register)(schema => 'encode' in schema && !(0, utils_1.isTypeBoxSchema)(schema) && !(0, utils_1.isJSONSchema)(schema) | ||
(registry_1.register.Ω = [undefined], (0, registry_1.register)(schema => 'encode' in schema && !(0, utils_1.isTypeBoxSchema)(schema) && !(0, utils_1.isJSONSchema)(schema) | ||
? schema | ||
@@ -45,2 +45,2 @@ : null, async (schema) => { | ||
}; | ||
}, 'io-ts'); | ||
}, 'io-ts')); |
@@ -6,3 +6,3 @@ "use strict"; | ||
const utils_1 = require("../utils"); | ||
(0, registry_1.register)(schema => '_flags' in schema && !(0, utils_1.isTypeBoxSchema)(schema) && !(0, utils_1.isJSONSchema)(schema) | ||
(registry_1.register.Ω = [undefined], (0, registry_1.register)(schema => '_flags' in schema && !(0, utils_1.isTypeBoxSchema)(schema) && !(0, utils_1.isJSONSchema)(schema) | ||
? schema | ||
@@ -19,2 +19,2 @@ : null, async (schema) => ({ | ||
}, | ||
}), 'joi'); | ||
}), 'joi')); |
@@ -6,3 +6,3 @@ "use strict"; | ||
const utils_1 = require("../utils"); | ||
(0, registry_1.register)(schema => 'reflect' in schema && !(0, utils_1.isTypeBoxSchema)(schema) && !(0, utils_1.isJSONSchema)(schema) | ||
(registry_1.register.Ω = [undefined], (0, registry_1.register)(schema => 'reflect' in schema && !(0, utils_1.isTypeBoxSchema)(schema) && !(0, utils_1.isJSONSchema)(schema) | ||
? schema | ||
@@ -17,2 +17,2 @@ : null, async (schema) => ({ | ||
}, | ||
}), 'runtypes'); | ||
}), 'runtypes')); |
@@ -6,3 +6,3 @@ "use strict"; | ||
const utils_1 = require("../utils"); | ||
(0, registry_1.register)(schema => 'refiner' in schema && !(0, utils_1.isTypeBoxSchema)(schema) && !(0, utils_1.isJSONSchema)(schema) | ||
(registry_1.register.Ω = [undefined], (0, registry_1.register)(schema => 'refiner' in schema && !(0, utils_1.isTypeBoxSchema)(schema) && !(0, utils_1.isJSONSchema)(schema) | ||
? schema | ||
@@ -18,2 +18,2 @@ : null, async (schema) => ({ | ||
}, | ||
}), 'superstruct'); | ||
}), 'superstruct')); |
@@ -29,3 +29,3 @@ "use strict"; | ||
const utils_1 = require("../utils"); | ||
(0, registry_1.register)(schema => ((0, utils_1.isTypeBoxSchema)(schema) ? schema : null), async (schema) => { | ||
(registry_1.register.Ω = [undefined], (0, registry_1.register)(schema => ((0, utils_1.isTypeBoxSchema)(schema) ? schema : null), async (schema) => { | ||
const { TypeCompiler } = await Promise.resolve().then(() => __importStar(require('@sinclair/typebox/compiler'))); | ||
@@ -43,2 +43,2 @@ const result = TypeCompiler.Compile(schema); | ||
}; | ||
}, '@sinclair/typebox'); | ||
}, '@sinclair/typebox')); |
@@ -29,3 +29,3 @@ "use strict"; | ||
const utils_1 = require("../utils"); | ||
(0, registry_1.register)(schema => '__isYupSchema__' in schema && | ||
(registry_1.register.Ω = [undefined], (0, registry_1.register)(schema => '__isYupSchema__' in schema && | ||
!(0, utils_1.isTypeBoxSchema)(schema) && | ||
@@ -54,2 +54,2 @@ !(0, utils_1.isJSONSchema)(schema) | ||
}; | ||
}, 'yup'); | ||
}, 'yup')); |
@@ -6,3 +6,3 @@ "use strict"; | ||
const utils_1 = require("../utils"); | ||
(0, registry_1.register)(schema => '_def' in schema && !(0, utils_1.isTypeBoxSchema)(schema) && !(0, utils_1.isJSONSchema)(schema) | ||
(registry_1.register.Ω = [undefined], (0, registry_1.register)(schema => '_def' in schema && !(0, utils_1.isTypeBoxSchema)(schema) && !(0, utils_1.isJSONSchema)(schema) | ||
? schema | ||
@@ -19,2 +19,2 @@ : null, async (schema) => ({ | ||
}, | ||
}), 'zod'); | ||
}), 'zod')); |
@@ -1,2 +0,2 @@ | ||
import type { InferOutput } from './resolver'; | ||
import type { InferInput, InferOutput } from './resolver'; | ||
import type { Schema, ValidationIssue } from './schema'; | ||
@@ -8,2 +8,5 @@ import type { IfDefined } from './utils'; | ||
}[keyof TypeSchemaRegistry]; | ||
export type InferIn<TSchema extends Schema> = { | ||
[K in keyof TypeSchemaRegistry]: IfDefined<InferInput<TypeSchemaRegistry[K], TSchema>>; | ||
}[keyof TypeSchemaRegistry]; | ||
export declare function validate<TSchema extends Schema>(schema: TSchema, data: unknown): Promise<{ | ||
@@ -10,0 +13,0 @@ data: Infer<TSchema>; |
@@ -7,4 +7,4 @@ import type { Schema } from './schema'; | ||
export declare function isTypeBoxSchema(schema: Schema): schema is TypeBoxSchema; | ||
export type JSONSchema = Exclude<ActualJSONSchema, boolean | IfDefined<TKind>>; | ||
export type JSONSchema = Exclude<ActualJSONSchema, boolean>; | ||
export type FromJSONSchema<TSchema extends JSONSchema> = TSchema extends IfDefined<TKind> ? never : FromSchema<TSchema>; | ||
export declare function isJSONSchema(schema: Schema): schema is JSONSchema; |
@@ -21,4 +21,5 @@ "use strict"; | ||
!('parse' in schema) && | ||
!('kind' in schema) && | ||
!isTypeBoxSchema(schema)); | ||
} | ||
exports.isJSONSchema = isJSONSchema; |
@@ -5,3 +5,3 @@ "use strict"; | ||
const registry_1 = require("./registry"); | ||
exports.cachedWrappedSchemas = new Map(); | ||
exports.cachedWrappedSchemas = (Map.Ω = [undefined, undefined], new Map()); | ||
let lastUsedAdapter = null; | ||
@@ -8,0 +8,0 @@ function wrapCached(schema) { |
{ | ||
"name": "@decs/typeschema", | ||
"version": "0.5.2", | ||
"version": "0.6.0", | ||
"description": "Universal adapter for schema validation", | ||
@@ -9,5 +9,18 @@ "keywords": [ | ||
"schema", | ||
"adapter", | ||
"validation", | ||
"inference", | ||
"assert" | ||
"assert", | ||
"zod", | ||
"yup", | ||
"joi", | ||
"ajv", | ||
"superstruct", | ||
"io-ts", | ||
"ow", | ||
"typia", | ||
"typebox", | ||
"deepkit", | ||
"runtypes", | ||
"arktype" | ||
], | ||
@@ -39,2 +52,5 @@ "homepage": "https://typeschema.com", | ||
"devDependencies": { | ||
"@deepkit/core": "^1.0.1-alpha.97", | ||
"@deepkit/type": "^1.0.1-alpha.97", | ||
"@deepkit/type-compiler": "^1.0.1-alpha.97", | ||
"@sinclair/typebox": "^0.29.6", | ||
@@ -64,2 +80,3 @@ "@types/node": "^20.3.3", | ||
"newtype-ts": "^0.3.5", | ||
"ow": "^0.28.2", | ||
"prettier": "^2.8.8", | ||
@@ -73,2 +90,3 @@ "runtypes": "^6.7.0", | ||
"typia": "^4.1.2", | ||
"uuid": "^9.0.0", | ||
"webpack": "^5.88.1", | ||
@@ -79,2 +97,3 @@ "yup": "^1.2.0", | ||
"peerDependencies": { | ||
"@deepkit/type": "^1.0.1-alpha.97", | ||
"@sinclair/typebox": "^0.29.4", | ||
@@ -86,2 +105,3 @@ "ajv": "^8.12.0", | ||
"joi": "^17.9.2", | ||
"ow": "^0.28.2", | ||
"runtypes": "^6.7.0", | ||
@@ -93,2 +113,5 @@ "superstruct": "^1.0.3", | ||
"peerDependenciesMeta": { | ||
"@deepkit/type": { | ||
"optional": true | ||
}, | ||
"@sinclair/typebox": { | ||
@@ -112,2 +135,5 @@ "optional": true | ||
}, | ||
"ow": { | ||
"optional": true | ||
}, | ||
"runtypes": { | ||
@@ -114,0 +140,0 @@ "optional": true |
@@ -6,3 +6,5 @@ <div id="header"> | ||
<a href="https://opensource.org/licenses/MIT" rel="nofollow"><img src="https://img.shields.io/github/license/decs/typeschema" alt="License"></a> | ||
<a href="https://www.npmjs.com/package/@decs/typeschema" rel="nofollow"><img src="https://img.shields.io/npm/dw/@decs/typeschema.svg" alt="NPM Downloads"></a> | ||
<a href="https://bundlephobia.com/package/@decs/typeschema" rel="nofollow"><img src="https://img.shields.io/bundlephobia/minzip/%40decs%2Ftypeschema" alt="Bundle size"></a> | ||
<a href="https://www.npmjs.com/package/@decs/typeschema" rel="nofollow"><img src="https://img.shields.io/npm/dw/@decs/typeschema.svg" alt="NPM downloads"></a> | ||
<a href="https://github.com/decs/typeschema/stargazers" rel="nofollow"><img src="https://img.shields.io/github/stars/decs/typeschema" alt="GitHub stars"></a> | ||
</p> | ||
@@ -17,3 +19,3 @@ | ||
1. **Couple their code** with a specific validation library: which limits adoption by developers who use another | ||
1. **Support multiple** validation libraries: which is a burden to keep up-to-date ([`tRPC`](https://trpc.io/) picked this one) | ||
1. **Support multiple** validation libraries: which is a burden to keep up-to-date (e.g. [tRPC](https://trpc.io/)) | ||
@@ -24,3 +26,3 @@ 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.** | ||
- 🚀 Decouple your code from validation libraries | ||
- 🚀 Decouple from validation libraries | ||
- 🍃 Tiny client footprint | ||
@@ -51,4 +53,4 @@ - ✨ Easy-to-use, minimal API | ||
```ts | ||
import type {Infer, Schema} from '@decs/typeschema'; | ||
import {assert, validate} from '@decs/typeschema'; | ||
import type {Infer, InferIn, Schema} from '@decs/typeschema'; | ||
import {assert, createAssert, validate} from '@decs/typeschema'; | ||
@@ -61,3 +63,4 @@ // Use your favorite validation library, e.g. `zod`, `arktype`, `typia` | ||
// Extracts the schema type | ||
type Type = Infer<typeof schema>; // `string` | ||
type Output = Infer<typeof schema>; // `string` | ||
type Input = InferIn<typeof schema>; // `string` | ||
@@ -78,2 +81,42 @@ // Returns the validated data or throws a `ValidationIssue` | ||
## Coverage | ||
TypeSchema supports all major schema validation libraries: | ||
| Project | Popularity | Example schema | Support | | ||
| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | ------- | | ||
| [zod](https://zod.dev) | <a href="https://github.com/colinhacks/zod" rel="nofollow"><img src="https://img.shields.io/github/stars/colinhacks/zod?style=social" alt="GitHub stars"></a> | `z.string()` | ✅ | | ||
| [yup](https://github.com/jquense/yup) | <a href="https://github.com/jquense/yup" rel="nofollow"><img src="https://img.shields.io/github/stars/jquense/yup?style=social" alt="GitHub stars"></a> | `string()` | ✅ | | ||
| [joi](https://joi.dev) | <a href="https://github.com/hapijs/joi" rel="nofollow"><img src="https://img.shields.io/github/stars/hapijs/joi?style=social" alt="GitHub stars"></a> | `Joi.string()` | ✅[^1] | | ||
| [ajv](https://ajv.js.org) | <a href="https://github.com/ajv-validator/ajv" rel="nofollow"><img src="https://img.shields.io/github/stars/ajv-validator/ajv?style=social" alt="GitHub stars"></a> | `{type: "string"} as const` | ✅ | | ||
| [superstruct](https://docs.superstructjs.org) | <a href="https://github.com/ianstormtaylor/superstruct" rel="nofollow"><img src="https://img.shields.io/github/stars/ianstormtaylor/superstruct?style=social" alt="GitHub stars"></a> | `string()` | ✅[^2] | | ||
| [io-ts](https://gcanti.github.io/io-ts) | <a href="https://github.com/gcanti/io-ts" rel="nofollow"><img src="https://img.shields.io/github/stars/gcanti/io-ts?style=social" alt="GitHub stars"></a> | `t.string` | ✅ | | ||
| [ow](https://sindresorhus.com/ow) | <a href="https://github.com/sindresorhus/ow" rel="nofollow"><img src="https://img.shields.io/github/stars/sindresorhus/ow?style=social" alt="GitHub stars"></a> | `ow.string` | ✅[^3] | | ||
| [typia](https://typia.io) | <a href="https://github.com/samchon/typia" rel="nofollow"><img src="https://img.shields.io/github/stars/samchon/typia?style=social" alt="GitHub stars"></a> | `typia.createAssert<string>()` | ✅ | | ||
| [typebox](https://github.com/sinclairzx81/typebox) | <a href="https://github.com/sinclairzx81/typebox" rel="nofollow"><img src="https://img.shields.io/github/stars/sinclairzx81/typebox?style=social" alt="GitHub stars"></a> | `Type.String()` | ✅ | | ||
| [deepkit](https://deepkit.io) | <a href="https://github.com/deepkit/deepkit-framework" rel="nofollow"><img src="https://img.shields.io/github/stars/deepkit/deepkit-framework?style=social" alt="GitHub stars"></a> | `typeOf<string>()` | ✅[^1] | | ||
| [runtypes](https://github.com/pelotom/runtypes) | <a href="https://github.com/pelotom/runtypes" rel="nofollow"><img src="https://img.shields.io/github/stars/pelotom/runtypes?style=social" alt="GitHub stars"></a> | `String` | ✅ | | ||
| [arktype](https://arktype.io) | <a href="https://github.com/arktypeio/arktype" rel="nofollow"><img src="https://img.shields.io/github/stars/arktypeio/arktype?style=social" alt="GitHub stars"></a> | `type('string')` | ✅ | | ||
[^1]: Type inference is not yet supported for [joi](https://joi.dev) and [deepkit](https://deepkit.io) | ||
[^2]: Input type inference is not yet supported for [superstruct](https://docs.superstructjs.org) | ||
[^3]: For [ow](https://sindresorhus.com/ow), only v0.28.2 is supported (sindresorhus/ow#248) | ||
Custom validations are also supported: | ||
```ts | ||
export function assertString(data: unknown): string { | ||
if (typeof data !== 'string') { | ||
throw new Error('Expected a string, got: ' + data); | ||
} | ||
return data; | ||
} | ||
await assert(assertString, '123'); // '123' | ||
await assert(assertString, 123); // throws `ValidationIssue` | ||
await validate(assertString, '123'); // {data: '123'} | ||
await validate(assertString, 123); // {issues: [`ValidationIssue`]} | ||
``` | ||
## API | ||
@@ -95,2 +138,6 @@ | ||
- `InferIn<TSchema extends Schema>` | ||
Extracts the input type of a schema | ||
#### Functions | ||
@@ -130,41 +177,7 @@ | ||
## Coverage | ||
| Project | Popularity | Example schema | Support | | ||
| -------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------ | ------- | | ||
| [zod](https://zod.dev) |  | `z.string()` | ✅ | | ||
| [yup](https://github.com/jquense/yup) |  | `string()` | ✅ | | ||
| [joi](https://joi.dev) |  | `Joi.string()` | ✅ | | ||
| [ajv](https://ajv.js.org) |  | `{type: "string"} as const` | ✅ | | ||
| [superstruct](https://docs.superstructjs.org) |  | `string()` | ✅ | | ||
| [io-ts](https://gcanti.github.io/io-ts) |  | `t.string` | ✅ | | ||
| [ow](https://sindresorhus.com/ow) |  | `ow.string` | ❌ | | ||
| [typebox](https://github.com/sinclairzx81/typebox) |  | `Type.String()` | ✅ | | ||
| [typia](https://typia.io) |  | `typia.createAssert<string>()` | ✅ | | ||
| [deepkit](https://deepkit.io) |  | `is<string>` | ❌ | | ||
| [runtypes](https://github.com/pelotom/runtypes) |  | `String` | ✅ | | ||
| [arktype](https://arktype.io) |  | `type('string')` | ✅ | | ||
Custom validations are also supported: | ||
```ts | ||
export function assertString(data: unknown): string { | ||
if (typeof data !== 'string') { | ||
throw new Error('Expected a string, got: ' + data); | ||
} | ||
return data; | ||
} | ||
await assert(assertString, '123'); // '123' | ||
await assert(assertString, 123); // throws `ValidationIssue` | ||
await validate(assertString, '123'); // {data: '123'} | ||
await validate(assertString, 123); // {issues: [`ValidationIssue`]} | ||
``` | ||
## Acknowledgements | ||
- Inspired by [`tRPC`](https://trpc.io/)'s [input & output validators](https://trpc.io/docs/server/validators) | ||
- Inspired by [tRPC](https://trpc.io/)'s [input & output validators](https://trpc.io/docs/server/validators) | ||
- Adapter architecture inspired by [@ecyrbe](https://github.com/ecyrbe)'s [suggestions](https://github.com/decs/typeschema/issues/1) | ||
- API definition inspired by [@colinhacks](https://github.com/colinhacks)'s [proposal](https://twitter.com/colinhacks/status/1634284724796661761) | ||
- JSON Schema type inference uses [`json-schema-to-ts`](https://github.com/ThomasAribart/json-schema-to-ts) | ||
- JSON Schema type inference powered by [`json-schema-to-ts`](https://github.com/ThomasAribart/json-schema-to-ts) |
43791
41
748
176
13
40