├── index.js ├── .gitignore ├── tsconfig.json ├── package.json ├── README.md ├── test.ts └── index.d.ts /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require("joi"); 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | build/ 3 | node_modules/ 4 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "lib": ["es2018"], 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "noFallthroughCasesInSwitch": true, 8 | "noImplicitReturns": true, 9 | "outDir": "./build/", 10 | "rootDir": "./", 11 | "sourceMap": true, 12 | "strict": true, 13 | "target": "es2018" 14 | }, 15 | "include": ["index.d.ts", "test.ts"] 16 | } 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "types-joi", 3 | "version": "2.1.0", 4 | "description": "TypeScript definitions for joi (Object schema description language and validator for JavaScript objects) https://joi.dev/", 5 | "keywords": [ 6 | "ts", 7 | "typescript", 8 | "types", 9 | "validation", 10 | "joi" 11 | ], 12 | "main": "index.js", 13 | "types": "index", 14 | "typeScriptVersion": "3.4.1", 15 | "files": [ 16 | "index.d.ts", 17 | "index.js" 18 | ], 19 | "scripts": { 20 | "test": "tsc" 21 | }, 22 | "author": "maghis", 23 | "license": "ISC", 24 | "devDependencies": { 25 | "@types/node": "14.14.20", 26 | "typescript": "4.1.3" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # types-joi 2 | 3 | TypeScript definitions for joi (Object schema description language and validator for JavaScript objects) https://joi.dev/ 4 | 5 | # Getting started 6 | 7 | Install `joi` and `types-joi`: 8 | 9 | ``` 10 | npm i joi types-joi 11 | ``` 12 | 13 | Use it: 14 | 15 | ```ts 16 | import * as joi from "types-joi"; 17 | import { InterfaceFrom } from "types-joi"; 18 | 19 | const messageSchema = joi.object({ 20 | status: joi.number().required(), 21 | body: joi.string() 22 | }).required(); 23 | 24 | type Message = InterfaceFrom; 25 | 26 | function processMessage(message: Message) { 27 | if (message.body) message.body.length; 28 | } 29 | 30 | const validatedMessage = joi.attempt({ some: "value" }, messageSchema); 31 | 32 | processMessage(validatedMessage); 33 | ``` 34 | -------------------------------------------------------------------------------- /test.ts: -------------------------------------------------------------------------------- 1 | import * as joi from "types-joi"; 2 | import { InterfaceFrom } from "types-joi"; 3 | 4 | const schema = joi 5 | .object({ 6 | test: joi 7 | .string() 8 | .required() 9 | .default("baz") 10 | .valid("baz" as const, "bar" as const), 11 | val: joi.number().optional(), 12 | inner: joi 13 | .object({ 14 | a: joi.string(), 15 | b: joi.number() 16 | }) 17 | .required(), 18 | values: joi 19 | .array() 20 | .required() 21 | .items(joi.string().required()), 22 | buf: joi.binary().required(), 23 | allowNullButRequired: joi.string().allow(null).required(), 24 | }) 25 | .required(); 26 | 27 | type SchemaInterface = InterfaceFrom; 28 | 29 | const stringArray = joi.array().items(joi.string()); 30 | 31 | const either = joi.alternatives([joi.string(), joi.number()]).required(); 32 | 33 | const test = joi 34 | .number() 35 | .optional() 36 | .required(); 37 | 38 | const metricsApiSchema = joi 39 | .object({ 40 | field: joi.number().required(), 41 | stringish: joi.string() 42 | }) 43 | .required(); 44 | 45 | type Matching = InterfaceFrom; 46 | 47 | const aString = joi.string().required(); 48 | const len = aString.length; 49 | 50 | function handleObj(obj: Matching) { 51 | const test: number = obj.field 52 | } 53 | type PickNot = { 54 | [P in keyof T]: P extends K ? undefined : T[P]; 55 | }; 56 | 57 | const sample = { 58 | hello: "test", 59 | bla: true 60 | }; 61 | 62 | type SampleType = typeof sample; 63 | 64 | const someObject = undefined as any as PickNot; 65 | const someOther = joi.object().pattern(/test/, joi.string().required()); 66 | const thing = joi.attempt(undefined, someOther)["test"]; 67 | 68 | (async () => { 69 | const res = await schema.validate({ test: "aaa" }); 70 | 71 | const foo = res.test; 72 | 73 | if (foo !== "bar") { 74 | const bar: "baz" = foo; 75 | } 76 | 77 | const buf: Buffer = joi.attempt(undefined, schema).buf; 78 | 79 | const result: Matching = joi.attempt(undefined, metricsApiSchema); 80 | const someNumber: number = result.field; 81 | })(); 82 | 83 | const emptyObj = joi.object(); 84 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | type PickNot = { 2 | [P in keyof T]: P extends K ? undefined : T[P]; 3 | }; 4 | 5 | type DictObj = { [key: string]: T }; 6 | 7 | declare module "types-joi" { 8 | type Callback = ((err: null, value: T) => void) | ((err: ValidationError, value: null) => void); 9 | 10 | interface JoiError { 11 | readonly message: string; 12 | readonly path: any[]; 13 | readonly type: string; 14 | readonly context: any; 15 | } 16 | 17 | interface ValidationError extends Error { 18 | readonly name: "ValidationError"; 19 | readonly isJoi: true; 20 | readonly details: JoiError[]; 21 | annotate(stripColors?: boolean): string; 22 | readonly _object: any; 23 | } 24 | 25 | type DefaultMethod = (context: any) => T; 26 | 27 | interface ValidateFail extends Promise { 28 | readonly error: ValidationError; 29 | readonly value: any; 30 | } 31 | 32 | interface ValidateSuccess extends Promise { 33 | readonly error: null; 34 | readonly value: T; 35 | } 36 | 37 | type ValidateResult = ValidateSuccess | ValidateFail; 38 | 39 | type TypeName = 40 | T extends string ? "string" : 41 | T extends number ? "number" : 42 | T extends boolean ? "boolean" : 43 | T extends undefined ? "undefined" : 44 | T extends Function ? "function" : 45 | "object"; 46 | 47 | interface BaseSchema { 48 | readonly schemaType: TypeName>; 49 | validate(value: any, options?: any, callback?: any): ValidateResult; 50 | } 51 | 52 | interface Extensions { 53 | description(desc: string): T; 54 | notes(notes: string[]): T; 55 | tags(tags: string[]): T; 56 | meta(meta: any): T; 57 | example(...values: any[]): T; 58 | unit(name: string): T; 59 | label(name: string): T; 60 | options(options: any): T; 61 | strict(isStrict: boolean): T; 62 | error(err: any, options: any): T; 63 | describe(): any; 64 | } 65 | 66 | interface AnySchema extends BaseSchema, Extensions> { 67 | allow(...values: readonly U[]): Schema; 68 | 69 | valid(...values: readonly U[]): Schema; 70 | 71 | required(): Schema; 72 | optional(): Schema; 73 | 74 | forbidden(): Schema; 75 | strip(): Schema; 76 | 77 | default(value: T, description?: string): Schema>; 78 | default(value: DefaultMethod & { description: string }): Schema; 79 | default(value: DefaultMethod, description: string): Schema; 80 | 81 | // // concat(schema: Schema): Schema; 82 | // // when(condition, options) 83 | 84 | // raw(isRaw: boolean): Schema; 85 | // empty(schema: T | Schema): Schema; 86 | // empty(): Schema>; 87 | } 88 | 89 | type ArrayComparator = (a: T, b: T) => boolean; 90 | interface ArrayUniqueOptions { 91 | ignoreUndefined: boolean; 92 | } 93 | 94 | interface ArraySchema extends AnySchema { 95 | // sparse([enabled]) 96 | // single([enabled]) 97 | items(schema: Schema): Schema[] | undefined>; 98 | // ordered(type) 99 | 100 | min(limit: number): Schema; 101 | max(limit: number): Schema; 102 | length(limit: number): Schema; 103 | unique(comparator: ArrayComparator | string, options: ArrayUniqueOptions): Schema; 104 | // has(schema) 105 | } 106 | 107 | interface BooleanSchema extends AnySchema { 108 | truthy(value: any | any[]): Schema; 109 | falsy(value: any | any[]): Schema; 110 | empty(value: any): Schema; 111 | insensitive(enabled?: boolean): Schema; 112 | } 113 | 114 | interface BinarySchema extends AnySchema { 115 | encoding(encoding: string): Schema; 116 | min(limit: number): Schema; 117 | max(limit: number): Schema; 118 | length(limit: number): Schema; 119 | } 120 | 121 | type DateType = Date | "now" | number | string; 122 | interface DateSchema extends AnySchema { 123 | min(date: DateType): Schema; 124 | max(date: DateType): Schema; 125 | greater(date: DateType): Schema; 126 | less(date: DateType): Schema; 127 | iso(): Schema; 128 | timestamp(type?: "javascript" | "unix"): Schema; 129 | } 130 | 131 | interface NumberSchema extends AnySchema { 132 | unsafe(enabled?: boolean): Schema; 133 | min(limit: number): Schema; 134 | max(limit: number): Schema; 135 | greater(limit: number): Schema; 136 | less(limit: number): Schema; 137 | integer(): Schema; 138 | precision(limit: number): Schema; 139 | multiple(base: number): Schema; 140 | positive(): Schema; 141 | negative(): Schema; 142 | port(): Schema; 143 | } 144 | 145 | interface RegexOptions { 146 | name?: string; 147 | invert?: boolean; 148 | } 149 | 150 | interface StringSchema extends AnySchema { 151 | insensitive(): Schema; 152 | min(limit: number, encoding?: string): Schema; 153 | max(limit: number, encoding?: string): Schema; 154 | truncate(enabled?: boolean): Schema; 155 | creditCard(): Schema; 156 | length(limit: number, encoding?: boolean): Schema; 157 | regex(pattern: RegExp, name?: string): Schema; 158 | regex(pattern: RegExp, options?: RegexOptions): Schema; 159 | replace(pattern: RegExp | string, replacement: string): Schema; 160 | alphanum(): Schema; 161 | token(): Schema; 162 | email(options?: any): Schema; 163 | ip(options?: any): Schema; 164 | uri(options?: any): Schema; 165 | guid(): Schema; 166 | hex(options?: any): Schema; 167 | base64(options?: any): Schema; 168 | dataUri(options?: any): Schema; 169 | hostname(): Schema; 170 | normalize(options?: any): Schema; 171 | lowercase(): Schema; 172 | uppercase(): Schema; 173 | trim(enabled?: boolean): Schema; 174 | isoDate(): Schema; 175 | } 176 | 177 | type SchemaMap = { 178 | [P in keyof T]: Schema 179 | }; 180 | 181 | interface ObjectSchema extends AnySchema { 182 | keys(schema: SchemaMap): Schema; 183 | append(schema: SchemaMap): Schema; 184 | min(limit: number): Schema; 185 | max(limit: number): Schema; 186 | length(limit: number): Schema; 187 | pattern(pattern: RegExp | Schema, schema: Schema): Schema>; 188 | // and(peers): Schema; 189 | // nand(peers): Schema; 190 | // or(peers): Schema; 191 | // xor(peers): Schema; 192 | // oxor(...peers): Schema; 193 | // with(key, peers): Schema; 194 | // without(key, peers): Schema; 195 | // rename(from: U, to: V): Schema>; 196 | // assert(ref, schema, [message]): Schema; 197 | unknown(allow: true): Schema; 198 | // type(constructor, [name]): Schema; 199 | // schema(): Schema; 200 | // requiredKeys(children): Schema; 201 | // optionalKeys(children): Schema; 202 | // forbiddenKeys(children): Schema; 203 | } 204 | 205 | type Schema = 206 | NonNullable extends any[] ? ArraySchema : 207 | NonNullable extends boolean ? BooleanSchema : 208 | NonNullable extends Buffer ? BinarySchema : 209 | NonNullable extends Date ? DateSchema : 210 | NonNullable extends number ? NumberSchema : 211 | NonNullable extends string ? StringSchema : 212 | NonNullable extends {} ? ObjectSchema : 213 | AnySchema; 214 | 215 | function attempt(value: any, schema: BaseSchema, message?: string | Error): T; 216 | type InterfaceFrom> = T extends BaseSchema ? U : never; 217 | 218 | function any(): Schema; 219 | function array(): Schema; 220 | function boolean(): Schema; 221 | function binary(): Schema; 222 | function date(): Schema; 223 | function number(): Schema; 224 | function string(): Schema; 225 | function object(): Schema<{} | undefined>; 226 | function object(map: SchemaMap): Schema; 227 | function alternatives(schemas: [Schema, Schema]): Schema; 228 | function alternatives(schemas: [Schema, Schema, Schema]): Schema; 229 | function alternatives(schemas: [Schema, Schema, Schema, Schema]): Schema; 230 | } 231 | --------------------------------------------------------------------------------