├── .gitignore ├── LICENSE ├── README.md ├── package.json ├── src ├── index.ts ├── lib │ ├── cast.ts │ ├── functions.ts │ ├── joi.ts │ ├── schema.ts │ ├── symbols.ts │ ├── util.ts │ └── value.ts └── schema │ ├── alternative.ts │ ├── any.ts │ ├── array.ts │ ├── binary.ts │ ├── boolean.ts │ ├── date.ts │ ├── function.ts │ ├── index.ts │ ├── lazy.ts │ ├── number.ts │ ├── object.ts │ ├── string.ts │ └── symbol.ts ├── test └── util.ts ├── tsconfig.build.json ├── tsconfig.json ├── typesafe-joi.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 - Jingkun Hua 4 | 5 | All rights reserved. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # typesafe-joi 2 | 3 | typesafe-joi is a fork of [@hapi/joi](https://github.com/hapijs/joi). More precisely, this is a fork of [@types/hapi__joi](https://www.npmjs.com/package/@types/hapi__joi) because it has just redefined the essential APIs of joi. **Almost** all the APIs are the same as the original APIs, but limitations **exists**. That is why I create a new package. 4 | 5 | typesafe-joi currently matches the API of @hapi/joi 15.x. And it requires TypeScript >=3.0.0 to work. 6 | 7 | > NOTE: typesafe-joi is still WIP. Sorry but I do not have enough time to write a unit test for it. Please feel free to open an issue when you find bugs or suggestions. I am glad to help! 8 | 9 | ## What’s the difference? 10 | 11 | The JavaScript APIs of typesafe-joi and joi are **identical**. However, its type definition lacks of the type information of the “value” behind the schema. That means, JavaScript knows what the validated object look like at runtime, but TypeScript does not know it at all at compile time. typesafe-joi records more information into schemas so that TypeScript is able to know what object you are validating at compile time. 12 | 13 | Unfortunately *not all* joi APIs are able to be properly described in TypeScript. See [Reference](#Reference) for more information. 14 | 15 | ## Usage 16 | 17 | Import and use joi from `typesafe-joi`: 18 | 19 | ```typescript 20 | import * as Joi from 'typesafe-joi' 21 | ``` 22 | 23 | The TypeScript magic is shown when you call `.validate` or `.attempt`: 24 | 25 | ```typescript 26 | const data: any = dataFromAnywhere 27 | 28 | // { foo?: string } | undefined 29 | Joi.object({ foo: Joi.string() }).validate(data).value 30 | 31 | // { id: number, email?: string }[] 32 | Joi.attempt(data, Joi.array() 33 | .items({ 34 | id: Joi.number().integer().required(), 35 | email: Joi.string().email() 36 | }) 37 | .required() 38 | ) 39 | ``` 40 | 41 | You can also use `Literal` to pull the data type out of the schema: 42 | 43 | ```typescript 44 | const schema = Joi.array() 45 | .items({ 46 | id: Joi.number().integer().required(), 47 | email: Joi.string().email() 48 | }) 49 | .required() 50 | 51 | type T = Joi.Literal 52 | ``` 53 | 54 | > NOTE: I suggest to turn on `strict` option in the compiler options of TypeScript. 55 | 56 | ## Typecasting 57 | 58 | Not every API of typesafe-joi matches the original joi in types. typesafe-joi provides typecast helpers in case you have to define the resulting type manually. 59 | 60 | ```typescript 61 | // 'foo' 62 | Joi.string().required() as Joi.Cast.String<'foo'> 63 | ``` 64 | 65 | If the typecast includes `undefined` type, the key will be optional. 66 | 67 | ```typescript 68 | // { foo?: Foo } 69 | Joi.object({ foo: number().required() as Joi.Cast.Object }) 70 | ``` 71 | 72 | Typecasting means you have to define everything by yourself. Schema attributes like `allow` is discarded. 73 | 74 | ```typescript 75 | // number | 'foo' | true 76 | Joi.number().allow('foo').default(true) 77 | 78 | // 123 79 | Joi.number().allow('foo').default(true) as Joi.Cast.Number<123> 80 | ``` 81 | 82 | TypeScript may complain about type mismatch. In this case assert the expression to `any` firstly. 83 | 84 | ```typescript 85 | // Error 86 | Joi.object({ 87 | foo: Joi.object().pattern(/\d+/, 1).allow(1) as Joi.Cast.Object 88 | }) 89 | 90 | // { map: Foo | 1 } 91 | Joi.object({ 92 | foo: Joi.object().pattern(/\d+/, 1).allow(1) as any as Joi.Cast.Object 93 | }) 94 | ``` 95 | 96 | I recommend *not* to use the schema anymore after typecast. The behavior will be undefined. 97 | 98 | Supported schema types to cast: 99 | 100 | * `Cast.Alternatives` 101 | * `Cast.Any` 102 | * `Cast.Array` 103 | * `Cast.Binary` 104 | * `Cast.Boolean` 105 | * `Cast.Date` 106 | * `Cast.Function` 107 | * `Cast.Lazy` 108 | * `Cast.Number` 109 | * `Cast.Object` 110 | * `Cast.String` 111 | 112 | ## Reference 113 | 114 | Here is a list of APIs of joi. 115 | 116 | * ✅ - Fully supported 117 | * ✔️ - Supported but might be incorrect (not well tested) 118 | * ⚠️ - Partially supported (with limitations) 119 | * ❌ - Not supported (however you can use it without auto type generation) 120 | * 🔘 - Supported but *no type generation needed* 121 | 122 | | API | Status | Note | 123 | |-----|--------|------| 124 | | [Joi](https://github.com/hapijs/joi/blob/master/API.md#joi) | | | 125 | | [`version`](https://github.com/hapijs/joi/blob/master/API.md#version) | 🔘 | | 126 | | [`validate(value, schema, [options], [callback])`](https://github.com/hapijs/joi/blob/master/API.md#validatevalue-schema-options-callback) | ✅ | | 127 | | [`compile(schema)`](https://github.com/hapijs/joi/blob/master/API.md#compileschema) | ✔️ | | 128 | | [`describe(schema)`](https://github.com/hapijs/joi/blob/master/API.md#describeschema) | 🔘 | | 129 | | [`assert(value, schema, [message])`](https://github.com/hapijs/joi/blob/master/API.md#assertvalue-schema-message) | ✅ | | 130 | | [`attempt(value, schema, [message])`](https://github.com/hapijs/joi/blob/master/API.md#attemptvalue-schema-message) | ✅ | | 131 | | [`ref(key, [options])`](https://github.com/hapijs/joi/blob/master/API.md#refkey-options) | 🔘 | | 132 | | [`isRef(ref)`](https://github.com/hapijs/joi/blob/master/API.md#isrefref) | 🔘 | | 133 | | [`reach(schema, path)`](https://github.com/hapijs/joi/blob/master/API.md#reachschema-path) | ❌ | | 134 | | [`defaults(fn)`](https://github.com/hapijs/joi/blob/master/API.md#defaultsfn) | 🔘 | | 135 | | [`bind()`](https://github.com/hapijs/joi/blob/master/API.md#bind) | 🔘 | | 136 | | [`extend(extension)`](https://github.com/hapijs/joi/blob/master/API.md#extendextension) | 🔘 | Requires [module augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html) to typesafe-joi | 137 | | **[any](https://github.com/hapijs/joi/blob/master/API.md#any)** | | | 138 | | [`any.validate(value, [options], [callback])`](https://github.com/hapijs/joi/blob/master/API.md#anyvalidatevalue-options-callback) | ✅ | | 139 | | [`any.allow(value)`](https://github.com/hapijs/joi/blob/master/API.md#anyallowvalue) | ✅ | | 140 | | [`any.valid(value)`](https://github.com/hapijs/joi/blob/master/API.md#anyvalidvalue---aliases-only-equal) | ✅ | | 141 | | [`any.invalid(value)`](https://github.com/hapijs/joi/blob/master/API.md#anyinvalidvalue---aliases-disallow-not) | ✅ | | 142 | | [`any.required()`](https://github.com/hapijs/joi/blob/master/API.md#anyrequired---aliases-exist) | ✅ | | 143 | | [`any.optional()`](https://github.com/hapijs/joi/blob/master/API.md#anyoptional) | ✅ | | 144 | | [`any.forbidden()`](https://github.com/hapijs/joi/blob/master/API.md#anyforbidden) | ✅ | | 145 | | [`any.strip()`](https://github.com/hapijs/joi/blob/master/API.md#anystrip) | ⚠️ | The object key will still exist. It will have `never` type. | 146 | | [`any.description(desc)`](https://github.com/hapijs/joi/blob/master/API.md#anydescriptiondesc) | 🔘 | | 147 | | [`any.notes(notes)`](https://github.com/hapijs/joi/blob/master/API.md#anynotesnotes) | 🔘 | | 148 | | [`any.tags(tags)`](https://github.com/hapijs/joi/blob/master/API.md#anytagstags) | 🔘 | | 149 | | [`any.meta(meta)`](https://github.com/hapijs/joi/blob/master/API.md#anymetameta) | 🔘 | | 150 | | [`any.example(...values)`](https://github.com/hapijs/joi/blob/master/API.md#anyexamplevalues) | 🔘 | | 151 | | [`any.unit(name)`](https://github.com/hapijs/joi/blob/master/API.md#anyunitname) | 🔘 | | 152 | | [`any.options(options)`](https://github.com/hapijs/joi/blob/master/API.md#anyoptionsoptions) | 🔘 | To properly use typesafe-joi, do not change `convert`, `presence`, `noDefaults`. | 153 | | [`any.strict(isStrict)`](https://github.com/hapijs/joi/blob/master/API.md#anystrictisstrict) | 🔘 | | 154 | | [`any.default(value, [description])`](https://github.com/hapijs/joi/blob/master/API.md#anydefaultvalue-description) | ⚠️ | Manually define the default type when using reference as default. | 155 | | [`any.concat(schema)`](https://github.com/hapijs/joi/blob/master/API.md#anyconcatschema) | ✔️ | | 156 | | [`any.when(condition, options)`](https://github.com/hapijs/joi/blob/master/API.md#anywhencondition-options) | ✔️ | | 157 | | [`any.label(name)`](https://github.com/hapijs/joi/blob/master/API.md#anylabelname) | 🔘 | | 158 | | [`any.raw(isRaw)`](https://github.com/hapijs/joi/blob/master/API.md#anyrawisraw) | 🔘 | | 159 | | [`any.empty(schema)`](https://github.com/hapijs/joi/blob/master/API.md#anyemptyschema) | ❌ | | 160 | | [`any.error(err, [options])`](https://github.com/hapijs/joi/blob/master/API.md#anyerrorerr-options) | 🔘 | | 161 | | [`any.describe()`](https://github.com/hapijs/joi/blob/master/API.md#anydescribe) | 🔘 | | 162 | | **[array](https://github.com/hapijs/joi/blob/master/API.md#array---inherits-from-any)** | | | 163 | | [`array.sparse([enabled])`](https://github.com/hapijs/joi/blob/master/API.md#arraysparseenabled) | ✅ | | 164 | | [`array.single([enabled])`](https://github.com/hapijs/joi/blob/master/API.md#arraysingleenabled) | 🔘 | | 165 | | [`array.items(type)`](https://github.com/hapijs/joi/blob/master/API.md#arrayitemstype) | ✅ | | 166 | | [`array.ordered(type)`](https://github.com/hapijs/joi/blob/master/API.md#arrayorderedtype) | ⚠️ | No actual item order in the resulting type | 167 | | [`array.min(limit)`](https://github.com/hapijs/joi/blob/master/API.md#arrayminlimit) | 🔘 | | 168 | | [`array.max(limit)`](https://github.com/hapijs/joi/blob/master/API.md#arraymaxlimit) | 🔘 | | 169 | | [`array.length(limit)`](https://github.com/hapijs/joi/blob/master/API.md#arraylengthlimit) | 🔘 | | 170 | | [`array.unique([comparator], [options])`](https://github.com/hapijs/joi/blob/master/API.md#arrayuniquecomparator-options) | 🔘 | | 171 | | [`array.has(schema)`](https://github.com/hapijs/joi/blob/master/API.md#arrayhasschema) | 🔘 | | 172 | | **[boolean](https://github.com/hapijs/joi/blob/master/API.md#boolean---inherits-from-any)** | | | 173 | | [`boolean.truthy(value)`](https://github.com/hapijs/joi/blob/master/API.md#booleantruthyvalue) | 🔘 | | 174 | | [`boolean.falsy(value)`](https://github.com/hapijs/joi/blob/master/API.md#booleanfalsyvalue) | 🔘 | | 175 | | [`boolean.insensitive([enabled])`](https://github.com/hapijs/joi/blob/master/API.md#booleaninsensitiveenabled) | 🔘 | | 176 | | **[binary](https://github.com/hapijs/joi/blob/master/API.md#binary---inherits-from-any)** | | | 177 | | [`binary.encoding(encoding)`](https://github.com/hapijs/joi/blob/master/API.md#binaryencodingencoding) | 🔘 | | 178 | | [`binary.min(limit)`](https://github.com/hapijs/joi/blob/master/API.md#binaryminlimit) | 🔘 | | 179 | | [`binary.max(limit)`](https://github.com/hapijs/joi/blob/master/API.md#binarymaxlimit) | 🔘 | | 180 | | [`binary.length(limit)`](https://github.com/hapijs/joi/blob/master/API.md#binarylengthlimit) | 🔘 | | 181 | | **[date](https://github.com/hapijs/joi/blob/master/API.md#date---inherits-from-any)** | | | 182 | | [`date.min(date)`](https://github.com/hapijs/joi/blob/master/API.md#datemindate) | 🔘 | | 183 | | [`date.max(date)`](https://github.com/hapijs/joi/blob/master/API.md#datemaxdate) | 🔘 | | 184 | | [`date.greater(date)`](https://github.com/hapijs/joi/blob/master/API.md#dategreaterdate) | 🔘 | | 185 | | [`date.less(date)`](https://github.com/hapijs/joi/blob/master/API.md#datelessdate) | 🔘 | | 186 | | [`date.iso()`](https://github.com/hapijs/joi/blob/master/API.md#dateiso) | 🔘 | | 187 | | [`date.timestamp([type])`](https://github.com/hapijs/joi/blob/master/API.md#datetimestamptype) | 🔘 | | 188 | | **[func](https://github.com/hapijs/joi/blob/master/API.md#func---inherits-from-any)** | | | 189 | | [`func.arity(n)`](https://github.com/hapijs/joi/blob/master/API.md#funcarityn) | 🔘 | | 190 | | [`func.minArity(n)`](https://github.com/hapijs/joi/blob/master/API.md#funcminarityn) | 🔘 | | 191 | | [`func.maxArity(n)`](https://github.com/hapijs/joi/blob/master/API.md#funcmaxarityn) | 🔘 | | 192 | | [`func.class()`](https://github.com/hapijs/joi/blob/master/API.md#funcclass) | 🔘 | | 193 | | [`func.ref()`](https://github.com/hapijs/joi/blob/master/API.md#funcref) | 🔘 | | 194 | | **[number](https://github.com/hapijs/joi/blob/master/API.md#number---inherits-from-any)** | | | 195 | | [`number.unsafe([enabled])`](https://github.com/hapijs/joi/blob/master/API.md#numberunsafeenabled) | 🔘 | | 196 | | [`number.min(limit)`](https://github.com/hapijs/joi/blob/master/API.md#numberminlimit) | 🔘 | | 197 | | [`number.max(limit)`](https://github.com/hapijs/joi/blob/master/API.md#numbermaxlimit) | 🔘 | | 198 | | [`number.greater(limit)`](https://github.com/hapijs/joi/blob/master/API.md#numbergreaterlimit) | 🔘 | | 199 | | [`number.less(limit)`](https://github.com/hapijs/joi/blob/master/API.md#numberlesslimit) | 🔘 | | 200 | | [`number.integer()`](https://github.com/hapijs/joi/blob/master/API.md#numberinteger) | 🔘 | | 201 | | [`number.precision(limit)`](https://github.com/hapijs/joi/blob/master/API.md#numberprecisionlimit) | 🔘 | | 202 | | [`number.multiple(base)`](https://github.com/hapijs/joi/blob/master/API.md#numbermultiplebase) | 🔘 | | 203 | | [`number.positive()`](https://github.com/hapijs/joi/blob/master/API.md#numberpositive) | 🔘 | | 204 | | [`number.negative()`](https://github.com/hapijs/joi/blob/master/API.md#numbernegative) | 🔘 | | 205 | | [`number.port()`](https://github.com/hapijs/joi/blob/master/API.md#numberport) | 🔘 | | 206 | | **[object](https://github.com/hapijs/joi/blob/master/API.md#object---inherits-from-any)** | | | 207 | | [`object.keys([schema])`](https://github.com/hapijs/joi/blob/master/API.md#objectkeysschema) | ✅ | | 208 | | [`object.append([schema])`](https://github.com/hapijs/joi/blob/master/API.md#objectappendschema) | ✅ | | 209 | | [`object.min(limit)`](https://github.com/hapijs/joi/blob/master/API.md#objectminlimit) | ❌ | | 210 | | [`object.max(limit)`](https://github.com/hapijs/joi/blob/master/API.md#objectmaxlimit) | ❌ | | 211 | | [`object.length(limit)`](https://github.com/hapijs/joi/blob/master/API.md#objectlengthlimit) | ❌ | | 212 | | [`object.pattern(pattern, schema)`](https://github.com/hapijs/joi/blob/master/API.md#objectpatternpattern-schema) | ⚠️ | The result type of `pattern` may be useless. | 213 | | [`object.and(peers)`](https://github.com/hapijs/joi/blob/master/API.md#objectandpeers) | ❌ | | 214 | | [`object.nand(peers)`](https://github.com/hapijs/joi/blob/master/API.md#objectnandpeers) | ❌ | | 215 | | [`object.or(peers)`](https://github.com/hapijs/joi/blob/master/API.md#objectorpeers) | ❌ | | 216 | | [`object.xor(peers)`](https://github.com/hapijs/joi/blob/master/API.md#objectxorpeers) | ❌ | | 217 | | [`object.oxor(...peers)`](https://github.com/hapijs/joi/blob/master/API.md#objectoxorpeers) | ❌ | | 218 | | [`object.with(key, peers)`](https://github.com/hapijs/joi/blob/master/API.md#objectwithkey-peers) | ❌ | | 219 | | [`object.without(key, peers)`](https://github.com/hapijs/joi/blob/master/API.md#objectwithoutkey-peers) | ❌ | | 220 | | [`object.rename(from, to, [options])`](https://github.com/hapijs/joi/blob/master/API.md#objectrenamefrom-to-options) | ❌ | | 221 | | [`object.assert(ref, schema, [message])`](https://github.com/hapijs/joi/blob/master/API.md#objectassertref-schema-message) | 🔘 | | 222 | | [`object.unknown([allow])`](https://github.com/hapijs/joi/blob/master/API.md#objectunknownallow) | 🔘 | | 223 | | [`object.type(constructor, [name])`](https://github.com/hapijs/joi/blob/master/API.md#objecttypeconstructor-name) | ⚠️ | If you need to combine `keys` and `type`, make sure `type` is the last call (`.keys(...).type(...)`), or the resulting type will be incorrect. | 224 | | [`object.schema()`](https://github.com/hapijs/joi/blob/master/API.md#objectschema) | ⚠️ | Same as `type`. | 225 | | [`object.requiredKeys(children)`](https://github.com/hapijs/joi/blob/master/API.md#objectrequiredkeyschildren) | ⚠️ | Nested key is not supported (e.g. `a.b`, `a.b.c`). | 226 | | [`object.optionalKeys(children)`](https://github.com/hapijs/joi/blob/master/API.md#objectoptionalkeyschildren) | ⚠️ | Nested key is not supported (e.g. `a.b`, `a.b.c`). | 227 | | [`object.forbiddenKeys(children)`](https://github.com/hapijs/joi/blob/master/API.md#objectforbiddenkeyschildren) | ⚠️ | Nested key is not supported (e.g. `a.b`, `a.b.c`). | 228 | | **[string](https://github.com/hapijs/joi/blob/master/API.md#string---inherits-from-any)** | | | 229 | | [`string.insensitive()`](https://github.com/hapijs/joi/blob/master/API.md#stringinsensitive) | 🔘 | | 230 | | [`string.min(limit, [encoding])`](https://github.com/hapijs/joi/blob/master/API.md#stringminlimit-encoding) | 🔘 | | 231 | | [`string.max(limit, [encoding])`](https://github.com/hapijs/joi/blob/master/API.md#stringmaxlimit-encoding) | 🔘 | | 232 | | [`string.truncate([enabled])`](https://github.com/hapijs/joi/blob/master/API.md#stringtruncateenabled) | 🔘 | | 233 | | [`string.creditCard()`](https://github.com/hapijs/joi/blob/master/API.md#stringcreditcard) | 🔘 | | 234 | | [`string.length(limit, [encoding])`](https://github.com/hapijs/joi/blob/master/API.md#stringlengthlimit-encoding) | 🔘 | | 235 | | [`string.regex(pattern, [options])`](https://github.com/hapijs/joi/blob/master/API.md#stringregexpattern-name--options) | 🔘 | | 236 | | [`string.replace(pattern, replacement)`](https://github.com/hapijs/joi/blob/master/API.md#stringreplacepattern-replacement) | 🔘 | | 237 | | [`string.alphanum()`](https://github.com/hapijs/joi/blob/master/API.md#stringalphanum) | 🔘 | | 238 | | [`string.token()`](https://github.com/hapijs/joi/blob/master/API.md#stringtoken) | 🔘 | | 239 | | [`string.email([options])`](https://github.com/hapijs/joi/blob/master/API.md#stringemailoptions) | 🔘 | | 240 | | [`string.ip([options])`](https://github.com/hapijs/joi/blob/master/API.md#stringipoptions) | 🔘 | | 241 | | [`string.uri([options])`](https://github.com/hapijs/joi/blob/master/API.md#stringurioptions) | 🔘 | | 242 | | [`string.guid()` - aliases: `uuid`](https://github.com/hapijs/joi/blob/master/API.md#stringguid---aliases-uuid) | 🔘 | | 243 | | [`string.hex([options])`](https://github.com/hapijs/joi/blob/master/API.md#stringhexoptions) | 🔘 | | 244 | | [`string.base64([options])`](https://github.com/hapijs/joi/blob/master/API.md#stringbase64options) | 🔘 | | 245 | | [`string.dataUri([options])`](https://github.com/hapijs/joi/blob/master/API.md#stringdataurioptions) | 🔘 | | 246 | | [`string.hostname()`](https://github.com/hapijs/joi/blob/master/API.md#stringhostname) | 🔘 | | 247 | | [`string.normalize([form])`](https://github.com/hapijs/joi/blob/master/API.md#stringnormalizeform) | 🔘 | | 248 | | [`string.lowercase()`](https://github.com/hapijs/joi/blob/master/API.md#stringlowercase) | 🔘 | | 249 | | [`string.uppercase()`](https://github.com/hapijs/joi/blob/master/API.md#stringuppercase) | 🔘 | | 250 | | [`string.trim([enabled])`](https://github.com/hapijs/joi/blob/master/API.md#stringtrimenabled) | 🔘 | | 251 | | [`string.isoDate()`](https://github.com/hapijs/joi/blob/master/API.md#stringisodate) | 🔘 | | 252 | | **[symbol](https://github.com/hapijs/joi/blob/master/API.md#symbol---inherits-from-any)** | | | 253 | | [`symbol.map(map)`](https://github.com/hapijs/joi/blob/master/API.md#symbolmapmap) | 🔘 | | 254 | | **[alternatives](https://github.com/hapijs/joi/blob/master/API.md#alternatives---inherits-from-any)** | | Array literal alternatives schema is not supported yet. | 255 | | [`alternatives.try(schemas)`](https://github.com/hapijs/joi/blob/master/API.md#alternativestryschemas) | ✅ | | 256 | | [`alternatives.when(condition, options)`](https://github.com/hapijs/joi/blob/master/API.md#alternativeswhencondition-options) | ✔️ | | 257 | | **[lazy](https://github.com/hapijs/joi/blob/master/API.md#lazyfn-options---inherits-from-any)** | | | 258 | 259 | ## Contribution 260 | 261 | Feel free to submit an issue or PR if you have any ideas, or found any bugs. 262 | 263 | ## License 264 | 265 | MIT 266 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typesafe-joi", 3 | "description": "A fork of joi that produces typed validation results in TypeScript", 4 | "version": "2.1.0", 5 | "types": "dist/index.d.js", 6 | "main": "typesafe-joi.js", 7 | "repository": "https://github.com/hjkcai/typesafe-joi.git", 8 | "author": "Jingkun Hua", 9 | "license": "MIT", 10 | "keywords": [ 11 | "joi", 12 | "typescript", 13 | "validation" 14 | ], 15 | "files": [ 16 | "dist", 17 | "src", 18 | "typesafe-joi.js" 19 | ], 20 | "scripts": { 21 | "build": "tsc -p tsconfig.build.json", 22 | "clean": "shx rm -rf dist", 23 | "test": "tsc -p . --noEmit", 24 | "prepublishOnly": "npm-run-all -s test clean build" 25 | }, 26 | "dependencies": { 27 | "@types/hapi__joi": "^15.0.1", 28 | "@types/node": "*" 29 | }, 30 | "peerDependencies": { 31 | "@hapi/joi": "^15.0.1", 32 | "typescript": ">=3.0.0" 33 | }, 34 | "devDependencies": { 35 | "npm-run-all": "^4.1.5", 36 | "shx": "^0.3.2", 37 | "typescript": "^3.4.5" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for @hapi/joi 15.x 2 | // Project: https://github.com/hapijs/joi 3 | // Definitions by: Jingkun Hua 4 | // TypeScript Version: >=3.0 5 | // @ts-ignore 6 | /// 7 | /// 8 | 9 | import * as Cast from './lib/cast' 10 | import { Schema } from './lib/schema' 11 | 12 | export * from './lib/functions' 13 | export * from './lib/joi' 14 | export * from './lib/schema' 15 | export * from './lib/value' 16 | export * from './schema' 17 | 18 | export { Cast } 19 | export type SchemaLike = Schema.SchemaLike 20 | export type SchemaMap = Schema.SchemaMap 21 | 22 | /** Pull the data type out of a schema. */ 23 | export type Literal = Schema.literal 24 | export type SchemaValue = Schema.literal 25 | 26 | module.exports = require('@hapi/joi') 27 | -------------------------------------------------------------------------------- /src/lib/cast.ts: -------------------------------------------------------------------------------- 1 | import { Value } from './value'; 2 | import * as Schemas from '../schema' 3 | 4 | type CastValue = Value 5 | 6 | /** Cast the value type of a AlternativesSchema. */ 7 | export type Alternatives = Schemas.AlternativesSchema> 8 | 9 | /** Cast the value type of a AnySchema. */ 10 | export type Any = Schemas.AnySchema> 11 | 12 | /** Cast the value type of a ArraySchema. */ 13 | export type Array = Schemas.ArraySchema> 14 | 15 | /** Cast the value type of a BinarySchema. */ 16 | export type Binary = Schemas.BinarySchema> 17 | 18 | /** Cast the value type of a BooleanSchema. */ 19 | export type Boolean = Schemas.BooleanSchema> 20 | 21 | /** Cast the value type of a DateSchema. */ 22 | export type Date = Schemas.DateSchema> 23 | 24 | /** Cast the value type of a FunctionSchema. */ 25 | export type Function = Schemas.FunctionSchema> 26 | 27 | /** Cast the value type of a LazySchema. */ 28 | export type Lazy = Schemas.LazySchema> 29 | 30 | /** Cast the value type of a NumberSchema. */ 31 | export type Number = Schemas.NumberSchema> 32 | 33 | /** Cast the value type of a ObjectSchema. */ 34 | export type Object = Schemas.ObjectSchema> 35 | 36 | /** Cast the value type of a StringSchema. */ 37 | export type String = Schemas.StringSchema> 38 | -------------------------------------------------------------------------------- /src/lib/functions.ts: -------------------------------------------------------------------------------- 1 | import * as JoiLib from './joi' 2 | import * as Schemas from '../schema' 3 | import { Value } from './value'; 4 | import { Schema } from './schema'; 5 | import { AnyType } from './util'; 6 | 7 | /** Current version of the joi package. */ 8 | export declare const version: string 9 | 10 | /** Generates a schema object that matches any data type. */ 11 | export declare function any (): Schemas.AnySchema 12 | 13 | /** Generates a schema object that matches an array data type. */ 14 | export declare function array (): Schemas.ArraySchema 15 | 16 | /** Generates a schema object that matches a boolean data type (as well as the strings 'true', 'false', 'yes', and 'no'). Can also be called via bool(). */ 17 | export declare function bool (): Schemas.BooleanSchema 18 | 19 | /** Generates a schema object that matches a boolean data type (as well as the strings 'true', 'false', 'yes', and 'no'). Can also be called via bool(). */ 20 | export declare function boolean (): Schemas.BooleanSchema 21 | 22 | /* Generates a schema object that matches a Buffer data type (as well as the strings which will be converted to Buffers). */ 23 | export declare function binary (): Schemas.BinarySchema 24 | 25 | /** Generates a schema object that matches a date type (as well as a JavaScript date string or number of milliseconds). */ 26 | export declare function date (): Schemas.DateSchema 27 | 28 | /** Generates a schema object that matches a function type. */ 29 | export declare function func (): Schemas.FunctionSchema 30 | 31 | /** Generates a schema object that matches a number data type (as well as strings that can be converted to numbers). */ 32 | export declare function number (): Schemas.NumberSchema 33 | 34 | /** Generates a schema object that matches an object data type (as well as JSON strings that have been parsed into objects). */ 35 | export declare function object (): Schemas.ObjectSchema 36 | export declare function object (schema: TSchemaMap): Schemas.ObjectSchema> 37 | 38 | /** Generates a schema object that matches a string data type. Note that empty strings are not allowed by default and must be enabled with allow(''). */ 39 | export declare function string (): Schemas.StringSchema 40 | 41 | /** Generates a type that will match one of the provided alternative schemas */ 42 | export declare function alternatives (types: T): Schemas.AlternativesSchema> 43 | export declare function alternatives (...types: T): Schemas.AlternativesSchema> 44 | 45 | /** Generates a type that will match one of the provided alternative schemas */ 46 | export declare function alt (types: T): Schemas.AlternativesSchema> 47 | export declare function alt (...types: T): Schemas.AlternativesSchema> 48 | 49 | /** 50 | * Generates a placeholder schema for a schema that you would provide with the fn. 51 | * Supports the same methods of the any() type. 52 | * This is mostly useful for recursive schemas 53 | */ 54 | export declare function lazy (cb: () => TSchema, options?: JoiLib.LazyOptions): Schemas.LazySchema> 55 | 56 | /** Validates a value using the schema and options. */ 57 | export declare function validate (value: any, schema: TSchemaLike, options?: JoiLib.ValidationOptions): JoiLib.ValidationResult> 58 | export declare function validate (value: any, schema: TSchemaLike, callback: JoiLib.ValidationCallback>): void 59 | export declare function validate (value: any, schema: TSchemaLike, options: JoiLib.ValidationOptions, callback: JoiLib.ValidationCallback>): void 60 | 61 | /** Converts literal schema definition to joi schema object (or returns the same back if already a joi schema object). */ 62 | export declare function compile (schema: TSchemaLike): Schema.compile 63 | 64 | /** 65 | * Validates a value against a schema and throws if validation fails. 66 | * 67 | * @param value - the value to validate. 68 | * @param schema - the schema object. 69 | * @param message - optional message string prefix added in front of the error message. may also be an Error object. 70 | */ 71 | export declare function assert (value: any, schema: Schema.SchemaLike, message?: string | Error): void 72 | 73 | /** 74 | * Validates a value against a schema, returns valid object, and throws if validation fails where: 75 | * 76 | * @param value - the value to validate. 77 | * @param schema - the schema object. 78 | * @param message - optional message string prefix added in front of the error message. may also be an Error object. 79 | */ 80 | export declare function attempt (value: any, schema: TSchemaLike, message?: string | Error): Schema.literal 81 | 82 | /** Generates a reference to the value of the named key. */ 83 | export declare function ref (key: string, options?: JoiLib.ReferenceOptions): JoiLib.Reference 84 | 85 | /** Checks whether or not the provided argument is a reference. It's especially useful if you want to post-process error messages. */ 86 | export declare function isRef (ref: any): ref is JoiLib.Reference 87 | 88 | /** 89 | * Get a sub-schema of an existing schema based on a `path` that can be either a string or an array 90 | * of strings For string values path separator is a dot (`.`) 91 | */ 92 | export declare function reach (schema: Schemas.ObjectSchema, TShcemaMap>>, path: TSubSchemaKey | [TSubSchemaKey]): TShcemaMap[TSubSchemaKey] 93 | export declare function reach (schema: Schemas.AbstractSchema, path: string | string[]): Schemas.AbstractSchema | undefined 94 | 95 | /** Creates a new Joi instance customized with the extension(s) you provide included. */ 96 | export declare function extend (extension: JoiLib.Extension | JoiLib.Extension[], ...extensions: Array): any 97 | 98 | export type Root = typeof import('..') 99 | export type DefaultsFunction = (root: Schemas.AbstractSchema) => Schemas.AbstractSchema 100 | 101 | /** 102 | * Creates a new Joi instance that will apply defaults onto newly created schemas 103 | * through the use of the fn function that takes exactly one argument, the schema being created. 104 | * 105 | * @param fn - The function must always return a schema, even if untransformed. 106 | */ 107 | export declare function defaults (fn: DefaultsFunction): Root 108 | 109 | /** 110 | * By default, some Joi methods to function properly need to rely on the Joi instance they are attached to 111 | * because they use `this` internally. So `Joi.string()` works but if you extract the function from it 112 | * and call `string()` it won't. `bind()` creates a new Joi instance 113 | * where all the functions relying on `this` are bound to the Joi instance. 114 | */ 115 | export declare function bind (): Root 116 | 117 | /** Returns a plain object representing the schema's rules and properties */ 118 | export declare function describe(schema: Schemas.AbstractSchema): JoiLib.Description 119 | 120 | /** Whitelists a value */ 121 | export declare function allow (values: T): Schemas.AnySchema, T[number]>> 122 | export declare function allow (...values: T): Schemas.AnySchema, T[number]>> 123 | 124 | /** Adds the provided values into the allowed whitelist and marks them as the only valid values allowed. */ 125 | export declare function valid (values: T): Schemas.AnySchema, T[number]>> 126 | export declare function valid (...values: T): Schemas.AnySchema, T[number]>> 127 | 128 | /** Adds the provided values into the allowed whitelist and marks them as the only valid values allowed. */ 129 | export declare function only (values: T): Schemas.AnySchema, T[number]>> 130 | export declare function only (...values: T): Schemas.AnySchema, T[number]>> 131 | 132 | /** Adds the provided values into the allowed whitelist and marks them as the only valid values allowed. */ 133 | export declare function equal (values: T): Schemas.AnySchema, T[number]>> 134 | export declare function equal (...values: T): Schemas.AnySchema, T[number]>> 135 | 136 | /** Blacklists a value */ 137 | export declare function invalid (values: T): Schemas.AnySchema, T[number]>> 138 | export declare function invalid (...values: T): Schemas.AnySchema, T[number]>> 139 | 140 | /** Blacklists a value */ 141 | export declare function disallow (values: T): Schemas.AnySchema, T[number]>> 142 | export declare function disallow (...values: T): Schemas.AnySchema, T[number]>> 143 | 144 | /** Blacklists a value */ 145 | export declare function not (values: T): Schemas.AnySchema, T[number]>> 146 | export declare function not (...values: T): Schemas.AnySchema, T[number]>> 147 | 148 | /** Marks a key as required which will not allow undefined as value. All keys are optional by default. */ 149 | export declare function required (): Schemas.AnySchema>> 150 | 151 | /** Alias of `required`. */ 152 | export declare function exist(): Schemas.AnySchema>> 153 | 154 | /** Marks a key as optional which will allow undefined as values. Used to annotate the schema for readability as all keys are optional by default. */ 155 | export declare function optional(): Schemas.AnySchema>> 156 | 157 | /** Marks a key as forbidden which will not allow any value except undefined. Used to explicitly forbid keys. */ 158 | export declare function forbidden(): Schemas.AnySchema>> 159 | 160 | /** Marks a key to be removed from a resulting object or array after validation. Used to sanitize output. */ 161 | export declare function strip(): Schemas.AnySchema>> 162 | 163 | /** Annotates the key. */ 164 | export declare function description(desc: string): Schemas.AnySchema 165 | 166 | /** Annotates the key. */ 167 | export declare function notes(notes: string | string[]): Schemas.AnySchema 168 | 169 | /** Annotates the key. */ 170 | export declare function tags(notes: string | string[]): Schemas.AnySchema 171 | 172 | /** Attaches metadata to the key. */ 173 | export declare function meta(meta: object): Schemas.AnySchema 174 | 175 | /** Annotates the key with an example value, must be valid. */ 176 | export declare function example(value: any): Schemas.AnySchema 177 | 178 | /** Annotates the key with an unit name. */ 179 | export declare function unit(name: string): Schemas.AnySchema 180 | 181 | /** Overrides the global validate() options for the current key and any sub-key. */ 182 | export declare function options(options: JoiLib.ValidationOptions): Schemas.AnySchema 183 | 184 | /** Sets the options.convert options to false which prevent type casting for the current key and any child keys. */ 185 | export declare function strict(isStrict?: boolean): Schemas.AnySchema 186 | 187 | /** Returns a new type that is the result of adding the rules of one type to another. */ 188 | export declare function concat>(schema: T): T 189 | 190 | /** Converts the type into an alternatives type where the conditions are merged into the type definition. */ 191 | export declare function when (ref: string | JoiLib.Reference, options: T): Schemas.AlternativesSchema>> 192 | export declare function when (ref: Schema.SchemaLike, options: T): Schemas.AlternativesSchema>> 193 | 194 | /** Overrides the key name in error messages. */ 195 | export declare function label(name: string): Schemas.AnySchema 196 | 197 | /** Outputs the original untouched value instead of the casted value. */ 198 | export declare function raw(isRaw?: boolean): Schemas.AnySchema 199 | 200 | /** 201 | * Considers anything that matches the schema to be empty (undefined). 202 | * @param schema - any object or joi schema to match. An undefined schema unsets that rule. 203 | */ 204 | export declare function empty(schema?: Schema.SchemaLike): Schemas.AnySchema 205 | -------------------------------------------------------------------------------- /src/lib/joi.ts: -------------------------------------------------------------------------------- 1 | import * as Joi from '@hapi/joi' 2 | import { Value } from './value'; 3 | import { Schema } from './schema'; 4 | import { ObjectSchema, AbstractSchema } from '../schema'; 5 | 6 | export { 7 | LanguageOptions, 8 | LanguageRootOptions, 9 | ValidationOptions, 10 | RenameOptions, 11 | EmailOptions, 12 | ErrorOptions, 13 | HexOptions, 14 | IpOptions, 15 | GuidOptions, 16 | UriOptions, 17 | DataUriOptions, 18 | Base64Options, 19 | ReferenceOptions, 20 | IPOptions, 21 | StringRegexOptions, 22 | JoiObject, 23 | Description, 24 | Context, 25 | State, 26 | ValidationError, 27 | ValidationErrorItem, 28 | ValidationErrorFunction, 29 | Reference, 30 | Err, 31 | LazyOptions 32 | } from '@hapi/joi' 33 | 34 | export interface DefaultFunction { 35 | (context: Joi.Context): T 36 | } 37 | 38 | export interface DefaultFunctionWithDescription extends DefaultFunction { 39 | description: string 40 | } 41 | 42 | export interface ValidationResult extends Pick, 'then' | 'catch'> { 43 | error: Joi.ValidationError | null; 44 | value: T; 45 | } 46 | 47 | export type ValidationCallback = (err: Joi.ValidationError, value: T) => void 48 | 49 | export interface Extension { 50 | name: string; 51 | base?: AbstractSchema; 52 | language?: Joi.LanguageOptions; 53 | coerce?(this: ExtensionBoundSchema, value: any, state: Joi.State, options: Joi.ValidationOptions): any; 54 | pre?(this: ExtensionBoundSchema, value: any, state: Joi.State, options: Joi.ValidationOptions): any; 55 | describe?(this: Schema, description: Joi.Description): Joi.Description; 56 | rules?: Rules[]; 57 | } 58 | 59 | export interface ExtensionBoundSchema extends AbstractSchema { 60 | /** 61 | * Creates a joi error object. 62 | * Used in conjunction with custom rules. 63 | * @param type - the type of rule to create the error for. 64 | * @param context - provide properties that will be available in the `language` templates. 65 | * @param state - should the context passed into the `validate` function in a custom rule 66 | * @param options - should the context passed into the `validate` function in a custom rule 67 | */ 68 | createError (type: string, context: Joi.Context, state: Joi.State, options: Joi.ValidationOptions): Joi.Err; 69 | } 70 | 71 | export interface Rules

{ 72 | name: string 73 | params?: ObjectSchema | { [key in keyof P]: Schema.SchemaLike; } 74 | setup? (this: ExtensionBoundSchema, params: P): AbstractSchema | void 75 | validate? (this: ExtensionBoundSchema, params: P, value: any, state: Joi.State, options: Joi.ValidationOptions): any 76 | description?: string | ((params: P) => string) 77 | } 78 | 79 | export interface When { 80 | then?: Then, 81 | otherwise?: Otherwise 82 | } 83 | 84 | export interface WhenIs extends When { 85 | is: Schema.SchemaLike 86 | } 87 | -------------------------------------------------------------------------------- /src/lib/schema.ts: -------------------------------------------------------------------------------- 1 | import * as Schemas from '../schema' 2 | import { When } from './joi'; 3 | import { Value } from "./value"; 4 | import { IsNever } from './util'; 5 | import { IS_INTERNAL_OBJECT, IS_SPARSE, IS_INTERNAL_LITERAL_SCHEMA, VALUE } from "./symbols"; 6 | 7 | /** 8 | * The abstract schema interface. 9 | * @description This interface only stores the value type of the schema for general use. 10 | * For Joi's schemas, see `schemas` folder. 11 | */ 12 | export interface Schema { 13 | /** 14 | * The value type of the schema. 15 | * @private DO NOT USE! This is not a real joi schema property but is required for typesafe-joi to work. 16 | */ 17 | [VALUE]: TValue 18 | } 19 | 20 | export namespace Schema { 21 | export type SchemaMap = { [Key in keyof any]: SchemaLike } 22 | export type SchemaLikeBase = string | number | boolean | null | Schema | SchemaMap 23 | export type SchemaLike = SchemaLikeBase | SchemaLikeBase[] 24 | 25 | export type InternalSchemaMap = InternalObjectType & { [Key in keyof any]: Schema } 26 | 27 | /** 28 | * The nominal type to mark a plain object as an *internal* schema map. 29 | * @private Internal use only. 30 | * 31 | * @description 32 | * Types intersect with `InternalObjectType` ensures all its keys have the value type `Schema`. 33 | * Equivalent to `{ [IS_INTERNAL_SCHEMA_MAP]: true } & Record`. 34 | * 35 | * @example 36 | * type A = { a: NumberSchema } & InternalObjectType 37 | */ 38 | export interface InternalObjectType { 39 | [IS_INTERNAL_OBJECT]: true 40 | } 41 | 42 | /** 43 | * The tagging type for array types. 44 | * @private Internal use only. 45 | * 46 | * @description 47 | * `InternalArrayType` stores flags for array types: 48 | * - `IS_SPRASE`: Indicates if the array is sparse, which means the array contains `undefined` items. 49 | * 50 | * @example 51 | * type A = string[] & InternalArrayType 52 | */ 53 | export interface InternalArrayType { 54 | [IS_SPARSE]: T 55 | } 56 | 57 | /** 58 | * The nominal type to mark a literal value as a schema. 59 | * @private Internal use only. 60 | * 61 | * @description 62 | * Joi allows literal values to be schemas (aka `SchemaLike`). 63 | * typesafe-joi will make an intersection type when converting literal values into formal schema objects, 64 | * in order to mark them as schemas without breaking original literal types. 65 | * 66 | * @example 67 | * type A = LiteralSchema> & (1 | "2" | true) 68 | */ 69 | export interface LiteralSchema extends Schema { 70 | [IS_INTERNAL_LITERAL_SCHEMA]: true 71 | } 72 | 73 | // -------------------------------------------------------------------------- 74 | // Schema transformations 75 | // -------------------------------------------------------------------------- 76 | 77 | /** 78 | * Construct a `Schema` from another `Schema`. 79 | * 80 | * @description 81 | * The new `Schema` has the same type to the old `Schema`, 82 | * but the new one can have different value type. 83 | */ 84 | export type from> = ( 85 | TSchema extends LiteralSchema 86 | ? LiteralSchema 87 | : TSchema extends Schemas.AbstractSchema 88 | ? Schemas.SchemaType 89 | : Schema 90 | ) 91 | 92 | /** 93 | * Construct a `Schema` type from a `SchemaLike`. 94 | * 95 | * @description 96 | * The literal type remains what it is but a `LiteralSchema` type is added onto it. 97 | * The value type of the `LiteralSchema` will be what the liter indicates. 98 | * 99 | * @example 100 | * type A = fromSchemaLike<1> = LiteralSchema> & 1; 101 | * type B = fromSchemaLike<{}> = LiteralSchema, InternalObjectType & {}>> & {} 102 | */ 103 | export type fromSchemaLike = ( 104 | [TSchemaLike] extends [Schema] 105 | ? TSchemaLike 106 | : TSchemaLike extends string | number | boolean | null 107 | ? LiteralSchema> 108 | : TSchemaLike extends any[] 109 | ? never // TODO: literal alternative schema is not supported yet 110 | : LiteralSchema, 112 | fromSchemaMap> 113 | >> 114 | ) 115 | 116 | /** 117 | * Compile `SchemaLike` into its corresponding schema type. 118 | * 119 | * @description 120 | * This is almost the same to `fromSchemaLike` but it returns the corresponding schema type. 121 | */ 122 | export type compile = ( 123 | TSchemaLike extends Schema 124 | ? TSchemaLike 125 | : TSchemaLike extends string 126 | ? Schemas.StringSchema> 127 | : TSchemaLike extends number 128 | ? Schemas.NumberSchema> 129 | : TSchemaLike extends boolean 130 | ? Schemas.BooleanSchema> 131 | : TSchemaLike extends any[] 132 | ? never // TODO: literal alternative schema is not supported yet 133 | : TSchemaLike extends SchemaMap 134 | ? Schemas.ObjectSchema, compileSchemaMap>>> 135 | : Schemas.AnySchema> 136 | ) 137 | 138 | /** 139 | * Merge two a value types by adding the rules of one type to another. 140 | * 141 | * @description 142 | * Here we only choose which schema type to return. 143 | */ 144 | export type concat, U extends Schemas.AbstractSchema> = ( 145 | Schemas.SchemaType< 146 | T['schemaType'] extends 'any' 147 | ? U['schemaType'] extends 'any' 148 | ? 'any' 149 | : U['schemaType'] 150 | : T['schemaType'], 151 | Value.concat 152 | > 153 | ) 154 | 155 | /** The `concat` but accepts `SchemaLike` types. */ 156 | export type concatSchemaLike, U extends SchemaLike> = ( 157 | concat, Schemas.AbstractSchema>> 158 | ) 159 | 160 | // -------------------------------------------------------------------------- 161 | // SchemaMap transformations 162 | // -------------------------------------------------------------------------- 163 | 164 | /** Construct an internal `InternalObjectType` from a `SchemaMap`. */ 165 | export type fromSchemaMap = InternalObjectType & { 166 | [Key in keyof TSchemaMap]: fromSchemaLike 167 | } 168 | 169 | /** Compile an internal `InternalObjectType` from a `SchemaMap`. */ 170 | export type compileSchemaMap = InternalObjectType & { 171 | [Key in keyof TSchemaMap]: compile 172 | } 173 | 174 | /** 175 | * Deeply merge two `InternalObjectType`s. 176 | * @description This actually acts like deep assign. 177 | */ 178 | export type deepMergeSchemaMap = ( 179 | InternalObjectType 180 | & { 181 | [Key in Exclude]: ( 182 | Key extends keyof U 183 | ? T[Key] extends Schema 184 | ? U[Key] extends Schema 185 | ? from>, Value.deepMerge> 186 | : U[Key] 187 | : U[Key] 188 | : T[Key] 189 | ) 190 | } 191 | & { [Key in Exclude]: U[Key] } 192 | ) 193 | 194 | /** 195 | * Deeply concat two `InternalObjectType`s. 196 | * @description This is similar to `deepMergeSchemaMap` but uses `concat` when merging. 197 | */ 198 | export type deepConcatSchemaMap = IsNever, IsNever]: ( 202 | Key extends keyof U 203 | ? concat>, Extract>> 204 | : T[Key] 205 | ) 206 | } 207 | & { [Key in Exclude]: U[Key] } 208 | )>> 209 | 210 | // -------------------------------------------------------------------------- 211 | // Helpers 212 | // -------------------------------------------------------------------------- 213 | 214 | /** Helper of `when` */ 215 | export type when, U extends When> = ( 216 | U extends When 217 | ? ( 218 | | concatSchemaLike 219 | | concatSchemaLike 220 | ) 221 | : never 222 | ) 223 | 224 | /** Get the value type of a `SchemaLike` */ 225 | export type valueType = ( 226 | fromSchemaLike[typeof VALUE] 227 | ) 228 | 229 | /** Get the literal type of a `SchemaLike` */ 230 | export type literal = ( 231 | Value.literal> 232 | ) 233 | } 234 | -------------------------------------------------------------------------------- /src/lib/symbols.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The value type of a schema. 3 | * @private DO NOT USE! This is not a real joi schema property but is required for typesafe-joi to work. 4 | */ 5 | export declare const VALUE: unique symbol 6 | 7 | /** 8 | * Indicates an object literal is a schema map. 9 | * @private DO NOT USE! This is not a real joi schema property but is required for typesafe-joi to work. 10 | */ 11 | export declare const IS_INTERNAL_OBJECT: unique symbol 12 | 13 | /** 14 | * Indicates if an internal array type is sparse. 15 | * @private DO NOT USE! This is not a real joi schema property but is required for typesafe-joi to work. 16 | */ 17 | export declare const IS_SPARSE: unique symbol 18 | 19 | /** 20 | * Defines a sort of schemas that are just literals. 21 | * @private DO NOT USE! This is not a real joi schema property but is required for typesafe-joi to work. 22 | */ 23 | export declare const IS_INTERNAL_LITERAL_SCHEMA: unique symbol 24 | -------------------------------------------------------------------------------- /src/lib/util.ts: -------------------------------------------------------------------------------- 1 | export type AnyType = string | number | boolean | symbol | object | null | undefined 2 | export type ConstructorOf = new (...args: any[]) => T 3 | export type ArrayItemType = T extends (infer U)[] ? U : never 4 | 5 | export type IsAny = 1 extends (T extends never ? 1 : 0) ? TrueType : FalseType 6 | export type IsInvariant = [T] extends [U] ? ([U] extends [T] ? TrueType : FalseType) : FalseType 7 | export type IsNever = [T] extends [never] ? TrueType : FalseType 8 | 9 | export type IsInvariantWithoutAny = IsAny>> 10 | export type IsUndefinedOrNever = IsInvariant> 11 | export type IsTrue = IsInvariantWithoutAny 12 | 13 | export type FilterUndefinedKeys = { [Key in keyof T]: undefined extends T[Key] ? Key : never }[keyof T] 14 | export type OmitUndefinedKeys = { [Key in keyof T]: undefined extends T[Key] ? never : Key }[keyof T] 15 | export type MakeOptional = Exclude<({ [Key in OmitUndefinedKeys]: T[Key] } & { [Key in FilterUndefinedKeys]?: T[Key] }) | undefined, undefined> 16 | -------------------------------------------------------------------------------- /src/lib/value.ts: -------------------------------------------------------------------------------- 1 | import { Schema } from './schema' 2 | import { IS_INTERNAL_OBJECT } from "./symbols"; 3 | import { MakeOptional, IsNever, IsTrue, IsAny, IsUndefinedOrNever, ArrayItemType, IsInvariant } from './util'; 4 | 5 | /** 6 | * A structure stores all information needed to match Joi's validation logic. 7 | * `Value` will NEVER exist in runtime. `Value` is used only for type inference. 8 | * @see Value.getType - How `Value` is assembled into literal type. 9 | */ 10 | export interface Value< 11 | TBase = never, 12 | TAugment = never, 13 | TAllowed = never, 14 | TDefault = undefined, 15 | TPresence extends Value.Presence = never 16 | > { 17 | /** 18 | * The base (initial) type of a schema. 19 | * The base type should not be modified once the value type is created. 20 | * 21 | * @description 22 | * The initial type of a schema is the type when a new schema is created. For example: 23 | * 24 | * | Schema | The initial type | 25 | * |:---------------|:-------------------| 26 | * | `Joi.any()` | `any` | 27 | * | `Joi.array()` | `any[]` | 28 | * | `Joi.object()` | `Record` | 29 | */ 30 | base: TBase, 31 | 32 | /** 33 | * The augmented type of a schema. 34 | * 35 | * @description 36 | * The augmented type of a schema is the type when specifying subtypes for an existing schema. For example: 37 | * 38 | * | Schema | The augmented type | 39 | * |:-----------------------------------------|:-------------------| 40 | * | `Joi.any().equal("0", 1)` | `"0" | 1` | 41 | * | `Joi.array().items(Joi.string())` | `string[]` | 42 | * | `Joi.object().keys({ a: Joi.number() })` | `{ a?: number }` | 43 | * 44 | * Additionally, a schema map of a object schema is stored in the augment type to simplify the process of merging two object schemas. 45 | */ 46 | augment: TAugment, 47 | 48 | /** 49 | * The extra allowed types of a schema. 50 | * 51 | * @description 52 | * The allowed type is added by `Schema.allow()`, `Schema.valid()`, `Schema.only()`, `Schema.equal()`. 53 | * This type will be the part of the final literal type. 54 | */ 55 | allowed: TAllowed, 56 | 57 | /** 58 | * The default type of a schema. 59 | * 60 | * @description 61 | * The default type is specified by `Schema.default()`. 62 | * This type will be the part of the final literal type if `presence` is `Optional` or `never`. 63 | */ 64 | default: TDefault, 65 | 66 | /** 67 | * The presence of a schema. 68 | * 69 | * @description 70 | * The presence is the same to the presence flag internally defined in joi. 71 | * It has 4 valid values: `Optional`, `Required`, `Forbidden`, `never`. 72 | * When presense is `never`, it equals to `Optional`. 73 | */ 74 | presence: TPresence 75 | } 76 | 77 | export namespace Value { 78 | export const enum Presence { 79 | Optional, 80 | Required, 81 | Forbidden 82 | } 83 | 84 | // -------------------------------------------------------------------------- 85 | // Alias 86 | // -------------------------------------------------------------------------- 87 | 88 | export type AnyValue = Value< 89 | /* base */ unknown, 90 | /* augment */ unknown, 91 | /* allowed */ unknown, 92 | /* default */ unknown, 93 | /* isRequired */ Value.Presence 94 | > 95 | 96 | export type EmptyValue = Value< 97 | /* base */ never, 98 | /* augment */ never, 99 | /* allowed */ never, 100 | /* default */ never, 101 | /* isRequired */ never 102 | > 103 | 104 | // -------------------------------------------------------------------------- 105 | // Building literal 106 | // -------------------------------------------------------------------------- 107 | 108 | /** 109 | * Transform `InternalObjectType` into object literal type. 110 | * @private 111 | */ 112 | export type transformSchemaMap = IsNever]: ( 114 | T[Key] extends Schema 115 | ? Value.literal 116 | : never 117 | ) 118 | }>> 119 | 120 | /** 121 | * Transform `InternalArrayType` into array literal type. 122 | * @private 123 | */ 124 | export type transformArrayType> = IsNever & (infer TItem)[] 126 | ? (TItem | IsTrue)[] 127 | : never 128 | )> 129 | 130 | /** Wrap `U` with the presence type. */ 131 | export type literalPresence = ( 132 | IsNever 135 | > 136 | > 137 | ) 138 | 139 | /** Get the literal type of a `Value`. */ 140 | export type literal = ( 141 | TValue extends any // force typescript to handle unions one by one 142 | ? ( 143 | literalPresence> 147 | | transformArrayType>> 148 | | Exclude, Schema.InternalArrayType> 149 | > 150 | > 151 | ) 152 | : never 153 | ) 154 | 155 | // -------------------------------------------------------------------------- 156 | // Value structure manipulation 157 | // -------------------------------------------------------------------------- 158 | 159 | /** Replace the augment type of `TValue` with `U` */ 160 | export type replace = ( 161 | TValue extends any 162 | ? Value< 163 | /* base */ TValue['base'], 164 | /* augment */ isAllowOnly, 165 | /* allowed */ TValue['allowed'], 166 | /* default */ TValue['default'], 167 | /* isRequired */ TValue['presence'] 168 | > 169 | : never 170 | ) 171 | 172 | /** Set the extra allowed type of a `Value`. */ 173 | export type allow = ( 174 | TValue extends any 175 | ? Value< 176 | /* base */ TValue['base'], 177 | /* augment */ TValue['augment'], 178 | /* allowed */ TValue['allowed'] | U, 179 | /* default */ TValue['default'], 180 | /* isRequired */ TValue['presence'] 181 | > 182 | : never 183 | ) 184 | 185 | /** 186 | * Set the only allowed type of a `Value`. 187 | * @description This removes the base type and the augment type 188 | */ 189 | export type allowOnly = ( 190 | TValue extends any 191 | ? Value< 192 | /* base */ never, 193 | /* augment */ never, 194 | /* allowed */ TValue['allowed'] | U, 195 | /* default */ TValue['default'], 196 | /* isRequired */ TValue['presence'] 197 | > 198 | : never 199 | ) 200 | 201 | /** Remove types from the allowed type. */ 202 | export type disallow = ( 203 | TValue extends any 204 | ? Value< 205 | /* base */ TValue['base'], 206 | /* augment */ TValue['augment'], 207 | /* allowed */ Exclude, 208 | /* default */ TValue['default'], 209 | /* isRequired */ TValue['presence'] 210 | > 211 | : never 212 | ) 213 | 214 | /** Set the default type of a `Value`. */ 215 | export type setDefault = ( 216 | TValue extends any 217 | ? Value< 218 | /* base */ TValue['base'], 219 | /* augment */ TValue['augment'], 220 | /* allowed */ TValue['allowed'], 221 | /* default */ U, 222 | /* isRequired */ TValue['presence'] 223 | > 224 | : never 225 | ) 226 | 227 | /** Set the presence of a `Value`. */ 228 | export type presence = ( 229 | TValue extends any 230 | ? Value< 231 | /* base */ TValue['base'], 232 | /* augment */ TValue['augment'], 233 | /* allowed */ TValue['allowed'], 234 | /* default */ TValue['default'], 235 | /* isRequired */ TIsRequired 236 | > 237 | : never 238 | ) 239 | 240 | /** Merge two a value types by adding the rules of one type to another. */ 241 | export type concat = ( 242 | T extends any 243 | ? Value< 244 | /* base */ IsAny, T['base']>, 245 | /* augment */ ( 246 | | Schema.deepConcatSchemaMap, Extract> 247 | | mergeArrayOnly>, ArrayItemType>>> 248 | | Exclude, Schema.InternalArrayType> 249 | | Exclude, Schema.InternalArrayType> 250 | ), 251 | /* allowed */ T['allowed'] | U['allowed'], 252 | /* default */ IsUndefinedOrNever, 253 | /* isRequired */ IsNever 254 | > 255 | : never 256 | ) 257 | 258 | // -------------------------------------------------------------------------- 259 | // Value manipulation 260 | // -------------------------------------------------------------------------- 261 | 262 | /** Make a `Value` required. */ 263 | export type required = presence 264 | 265 | /** Make a `Value` optional. */ 266 | export type optional = presence 267 | 268 | /** Make a `Value` forbidden. */ 269 | export type forbidden = presence 270 | 271 | /** Replace the augment type with the original augment type unioned with `U` */ 272 | export type union = replace 273 | 274 | /** 275 | * Add `TNewItem` into the array type of a `Value`. 276 | * 277 | * @description 278 | * This is similar to merge two array types and leaving other types unmodified. 279 | * e.g. `mergeArray -> (A | C)[] | B` 280 | */ 281 | export type mergeArray = replace[] & Schema.InternalArrayType, ( 283 | | mergeArrayOnly>, TNewItem> 284 | | Exclude> 285 | )> 286 | )> 287 | 288 | /** Set the sparse flag of the array type of a `Value` */ 289 | export type setArraySparse = replace, ( 291 | | (ArrayItemType>>[] & Schema.InternalArrayType) 292 | | Exclude> 293 | )> 294 | )> 295 | 296 | /** 297 | * Deeply merge two `Value`s. 298 | * 299 | * @description 300 | * - If `T` and `U` both have `InternalObjectType` type, merge them. 301 | * - Otherwise just directly use `U` as the result. 302 | */ 303 | export type deepMerge = ( 304 | IsNever extends Schema.InternalObjectType 305 | ? IsNever extends Schema.InternalObjectType 306 | ? replace, 308 | Extract 309 | >> 310 | : U 311 | : U 312 | ) 313 | 314 | /** Make intersection to the augment type of a `Value` with `InternalObjectType` and `U`. */ 315 | export type appendSchemaMap = ( 316 | replace> 317 | ) 318 | 319 | /** 320 | * Make some keys of the object optional. 321 | * If one of the key is an empty string, make the entire object optional. 322 | */ 323 | export type setOptionalKeys = ( 324 | IsInvariant>> 328 | : Value.replace> 329 | : never 330 | > 331 | ) 332 | 333 | /** 334 | * Make some keys of the object required. 335 | * If one of the key is an empty string, make the entire object required. 336 | */ 337 | export type setRequiredKeys = ( 338 | IsInvariant>> 342 | : Value.replace> 343 | : never 344 | > 345 | ) 346 | 347 | /** 348 | * Make some keys of the object forbidden. 349 | * If one of the key is an empty string, make the entire object forbidden. 350 | */ 351 | export type setForbiddenKeys = ( 352 | IsInvariant>> 356 | : Value.replace> 357 | : never 358 | > 359 | ) 360 | 361 | // -------------------------------------------------------------------------- 362 | // Helpers 363 | // -------------------------------------------------------------------------- 364 | 365 | /** 366 | * Test if the base type of a `Value` is `never`. 367 | * @private 368 | */ 369 | export type isAllowOnly = ( 370 | IsNever, FalseType> 371 | ) 372 | 373 | /** 374 | * Do the real array merge of `mergeArray`. 375 | * @private 376 | */ 377 | export type mergeArrayOnly, TNewItem> = ( 378 | TArray extends Schema.InternalArrayType & (infer TItem)[] 379 | ? Exclude[] & Schema.InternalArrayType 380 | : never 381 | ) 382 | 383 | /** 384 | * Extract object keys without forbidden keys from an internal object type 385 | * @private 386 | */ 387 | export type excludeForbiddenKeys = ( 388 | { [Key in keyof T]: IsInvariant>['presence'], Presence.Forbidden, never, Key> }[Exclude] 389 | ) 390 | 391 | /** 392 | * Make some keys of the object optional. 393 | * @private 394 | */ 395 | export type setOptionalKeysInternal = ( 396 | Schema.InternalObjectType & { 397 | [key in Exclude]: key extends TKeys 398 | ? Schema.from>> 399 | : TSchemaMap[key] 400 | } 401 | ) 402 | 403 | /** 404 | * Make some keys of the object forbidden. 405 | * @private 406 | */ 407 | export type setRequiredKeysInternal = ( 408 | Schema.InternalObjectType & { 409 | [key in Exclude]: key extends TKeys 410 | ? Schema.from>> 411 | : TSchemaMap[key] 412 | } 413 | ) 414 | 415 | /** 416 | * Make some keys of the object forbidden. 417 | * @private 418 | */ 419 | export type setForbiddenKeysInternal = ( 420 | Schema.InternalObjectType & { 421 | [key in Exclude]: key extends TKeys 422 | ? Schema.from>> 423 | : TSchemaMap[key] 424 | } 425 | ) 426 | } 427 | -------------------------------------------------------------------------------- /src/schema/alternative.ts: -------------------------------------------------------------------------------- 1 | import { Value } from "../lib/value"; 2 | import { Schema } from "../lib/schema"; 3 | import { BaseSchema } from "."; 4 | 5 | export interface AlternativesSchema extends BaseSchema<'alternatives', TValue> { 6 | try (...types: TSchemaLike): AlternativesSchema< 7 | Value.union> 8 | > 9 | } 10 | -------------------------------------------------------------------------------- /src/schema/any.ts: -------------------------------------------------------------------------------- 1 | import { Value } from "../lib/value"; 2 | import { BaseSchema } from "."; 3 | 4 | export interface AnySchema> extends BaseSchema<'any', TValue> { 5 | /* This is an empty interface */ 6 | } 7 | -------------------------------------------------------------------------------- /src/schema/array.ts: -------------------------------------------------------------------------------- 1 | import { Value } from "../lib/value"; 2 | import { Schema } from "../lib/schema"; 3 | import { Reference } from "../lib/joi"; 4 | import { ArrayItemType } from "../lib/util"; 5 | import { BaseSchema } from "."; 6 | 7 | export interface ArraySchema> extends BaseSchema<'array', TValue> { 8 | /** 9 | * List the types allowed for the array values. 10 | * type can be an array of values, or multiple values can be passed as individual arguments. 11 | * If a given type is .required() then there must be a matching item in the array. 12 | * If a type is .forbidden() then it cannot appear in the array. 13 | * Required items can be added multiple times to signify that multiple items must be found. 14 | * Errors will contain the number of items that didn't match. 15 | * Any unmatched item having a label will be mentioned explicitly. 16 | * 17 | * @param type - a joi schema object to validate each array item against. 18 | */ 19 | items (types: T): ArraySchema>> 20 | items (...types: T): ArraySchema>> 21 | 22 | /** 23 | * Lists the types in sequence order for the array values where: 24 | * @param type - a joi schema object to validate against each array item in sequence order. type can be an array of values, or multiple values can be passed as individual arguments. 25 | * If a given type is .required() then there must be a matching item with the same index position in the array. 26 | * Errors will contain the number of items that didn't match. 27 | * Any unmatched item having a label will be mentioned explicitly. 28 | */ 29 | ordered (types: T): ArraySchema>> 30 | ordered (...types: T): ArraySchema>> 31 | 32 | /** 33 | * Allow this array to be sparse. 34 | */ 35 | sparse (): ArraySchema> 36 | sparse (enabled: false): ArraySchema> 37 | sparse (enabled: true): ArraySchema> 38 | 39 | /** 40 | * Allow single values to be checked against rules as if it were provided as an array. 41 | * enabled can be used with a falsy value to go back to the default behavior. 42 | */ 43 | single (enabled?: any): this 44 | 45 | /** 46 | * Specifies the minimum number of items in the array. 47 | */ 48 | min (limit: number): this 49 | 50 | /** 51 | * Specifies the maximum number of items in the array. 52 | */ 53 | max (limit: number): this 54 | 55 | /** 56 | * Specifies the exact number of items in the array. 57 | */ 58 | length (limit: number | Reference): this 59 | 60 | /** 61 | * Requires the array values to be unique. 62 | * Be aware that a deep equality is performed on elements of the array having a type of object, 63 | * a performance penalty is to be expected for this kind of operation. 64 | */ 65 | unique (): this 66 | unique (comparator: string): this 67 | unique (comparator: (a: ArrayItemType, b: ArrayItemType) => boolean): this 68 | } 69 | -------------------------------------------------------------------------------- /src/schema/binary.ts: -------------------------------------------------------------------------------- 1 | import { Value } from "../lib/value"; 2 | import { BaseSchema } from "."; 3 | 4 | export interface BinarySchema> extends BaseSchema<'binary', TValue> { 5 | /** Sets the string encoding format if a string input is converted to a buffer. */ 6 | encoding (encoding: string): this 7 | 8 | /** Specifies the minimum length of the buffer. */ 9 | min (limit: number): this 10 | 11 | /** Specifies the maximum length of the buffer. */ 12 | max (limit: number): this 13 | 14 | /** Specifies the exact length of the buffer. */ 15 | length (limit: number): this 16 | } 17 | -------------------------------------------------------------------------------- /src/schema/boolean.ts: -------------------------------------------------------------------------------- 1 | import { Value } from "../lib/value"; 2 | import { BaseSchema } from "."; 3 | 4 | export interface BooleanSchema> extends BaseSchema<'boolean', TValue> { 5 | /** 6 | * Allows for additional values to be considered valid booleans by converting them to true during validation. 7 | * Accepts a value or an array of values. String comparisons are by default case insensitive, 8 | * see boolean.insensitive() to change this behavior. 9 | */ 10 | truthy (...values: Array): this 11 | 12 | /** 13 | * Allows for additional values to be considered valid booleans by converting them to false during validation. 14 | * Accepts a value or an array of values. String comparisons are by default case insensitive, 15 | * see boolean.insensitive() to change this behavior. 16 | */ 17 | falsy (...values: Array): this 18 | 19 | /** 20 | * Allows the values provided to truthy and falsy as well as the "true" and "false" default conversion 21 | * (when not in strict() mode) to be matched in a case insensitive manner. 22 | */ 23 | insensitive (enabled?: boolean): this 24 | } 25 | -------------------------------------------------------------------------------- /src/schema/date.ts: -------------------------------------------------------------------------------- 1 | import { Value } from "../lib/value"; 2 | import { Reference } from "../lib/joi"; 3 | import { BaseSchema } from "."; 4 | 5 | export interface DateSchema> extends BaseSchema<'date', TValue> { 6 | /** 7 | * Specifies that the value must be greater than date. 8 | * Notes: 'now' can be passed in lieu of date so as to always compare relatively to the current date, 9 | * allowing to explicitly ensure a date is either in the past or in the future. 10 | * It can also be a reference to another field. 11 | */ 12 | greater (date: 'now' | Date | number | string | Reference): this 13 | 14 | /** 15 | * Specifies that the value must be less than date. 16 | * Notes: 'now' can be passed in lieu of date so as to always compare relatively to the current date, 17 | * allowing to explicitly ensure a date is either in the past or in the future. 18 | * It can also be a reference to another field. 19 | */ 20 | less (date: 'now' | Date | number | string | Reference): this 21 | 22 | /** 23 | * Specifies the oldest date allowed. 24 | * Notes: 'now' can be passed in lieu of date so as to always compare relatively to the current date, 25 | * allowing to explicitly ensure a date is either in the past or in the future. 26 | * It can also be a reference to another field. 27 | */ 28 | min (date: 'now' | Date | number | string | Reference): this 29 | 30 | /** 31 | * Specifies the latest date allowed. 32 | * Notes: 'now' can be passed in lieu of date so as to always compare relatively to the current date, 33 | * allowing to explicitly ensure a date is either in the past or in the future. 34 | * It can also be a reference to another field. 35 | */ 36 | max (date: 'now' | Date | number | string | Reference): this 37 | 38 | /** 39 | * Specifies the allowed date format: 40 | * @param format - string or array of strings that follow the moment.js format. 41 | */ 42 | format (format: string | string[]): this 43 | 44 | /** Requires the string value to be in valid ISO 8601 date format. */ 45 | iso (): this 46 | 47 | /** 48 | * Requires the value to be a timestamp interval from Unix Time. 49 | * @param type - the type of timestamp (allowed values are unix or javascript (default)) 50 | */ 51 | timestamp (type?: 'javascript' | 'unix'): this 52 | } 53 | -------------------------------------------------------------------------------- /src/schema/function.ts: -------------------------------------------------------------------------------- 1 | import { Value } from "../lib/value"; 2 | import { Reference } from "../lib/joi"; 3 | import { BaseSchema } from "."; 4 | 5 | export interface FunctionSchema> extends BaseSchema<'boolean', TValue> { 6 | /** 7 | * Specifies the arity of the function where: 8 | * @param n - the arity expected. 9 | */ 10 | arity (n: number): this 11 | 12 | /** 13 | * Specifies the minimal arity of the function where: 14 | * @param n - the minimal arity expected. 15 | */ 16 | minArity (n: number): this 17 | 18 | /** 19 | * Specifies the minimal arity of the function where: 20 | * @param n - the minimal arity expected. 21 | */ 22 | maxArity (n: number): this 23 | 24 | /** 25 | * Requires the function to be a Joi reference. 26 | */ 27 | ref (): FunctionSchema> 28 | } 29 | -------------------------------------------------------------------------------- /src/schema/index.ts: -------------------------------------------------------------------------------- 1 | import { Value } from '../lib/value' 2 | import { Schema } from '../lib/schema' 3 | import { AnyType } from '../lib/util'; 4 | import * as JoiLib from "../lib/joi"; 5 | 6 | import { AlternativesSchema } from './alternative'; 7 | import { AnySchema } from './any'; 8 | import { ArraySchema } from './array'; 9 | import { BinarySchema } from './binary'; 10 | import { BooleanSchema } from './boolean'; 11 | import { DateSchema } from './date'; 12 | import { FunctionSchema } from './function'; 13 | import { LazySchema } from './lazy'; 14 | import { NumberSchema } from './number'; 15 | import { ObjectSchema } from './object'; 16 | import { StringSchema } from './string'; 17 | import { SymbolSchema } from './symbol'; 18 | 19 | /** The collection of all available schemas */ 20 | export interface SchemaCollection { 21 | alternatives: AlternativesSchema, 22 | any: AnySchema, 23 | array: ArraySchema, 24 | binary: BinarySchema, 25 | boolean: BooleanSchema, 26 | date: DateSchema, 27 | function: FunctionSchema, 28 | lazy: LazySchema, 29 | number: NumberSchema, 30 | object: ObjectSchema, 31 | string: StringSchema, 32 | symbol: SymbolSchema 33 | } 34 | 35 | /** 36 | * Assemble a schema type (e.g. `string`, `any`) and a value type into a schema. 37 | * This is basically a lookup in `SchemaCollection`. 38 | */ 39 | export type SchemaType = ( 40 | TSchemaType extends keyof SchemaCollection 41 | ? SchemaCollection[TSchemaType] 42 | : never 43 | ) 44 | 45 | /** 46 | * `Schema` with a `schemaType` tag. 47 | * 48 | * @description 49 | * There is no functions defined in `AbstractSchema` because these functions may make trouble to type matching. 50 | * `AbstractSchema` is being used to let TypeScript know what is the kind of a `Schema`. 51 | */ 52 | export interface AbstractSchema extends Schema { 53 | schemaType: TSchemaType 54 | } 55 | 56 | /** 57 | * The schema type with all the instance methods of `AnySchema` of joi. 58 | * 59 | * @description 60 | * Notice: do not use `BaseSchema` as the constraint pf a type variable. 61 | * The functions of `BaseSchema` will make all specific schema types fail. 62 | */ 63 | export interface BaseSchema extends AbstractSchema, JoiLib.JoiObject { 64 | /** Validates a value using the schema and options. */ 65 | validate (value: any, options?: JoiLib.ValidationOptions): JoiLib.ValidationResult> 66 | validate (value: any, callback: JoiLib.ValidationCallback>): void 67 | validate (value: any, options: JoiLib.ValidationOptions, callback: JoiLib.ValidationCallback>): void 68 | 69 | /** Whitelists a value */ 70 | allow (values: T): SchemaType> 71 | allow (...values: T): SchemaType> 72 | 73 | /** Adds the provided values into the allowed whitelist and marks them as the only valid values allowed. */ 74 | valid (values: T): SchemaType> 75 | valid (...values: T): SchemaType> 76 | 77 | /** Adds the provided values into the allowed whitelist and marks them as the only valid values allowed. */ 78 | only (values: T): SchemaType> 79 | only (...values: T): SchemaType> 80 | 81 | /** Adds the provided values into the allowed whitelist and marks them as the only valid values allowed. */ 82 | equal (values: T): SchemaType> 83 | equal (...values: T): SchemaType> 84 | 85 | /** Blacklists a value */ 86 | invalid (values: T): SchemaType> 87 | invalid (...values: T): SchemaType> 88 | 89 | /** Blacklists a value */ 90 | disallow (values: T): SchemaType> 91 | disallow (...values: T): SchemaType> 92 | 93 | /** Blacklists a value */ 94 | not (values: T): SchemaType> 95 | not (...values: T): SchemaType> 96 | 97 | /** 98 | * By default, some Joi methods to function properly need to rely on the Joi instance they are attached to because 99 | * they use `this` internally. 100 | * So `Joi.string()` works but if you extract the function from it and call `string()` it won't. 101 | * `bind()` creates a new Joi instance where all the functions relying on `this` are bound to the Joi instance. 102 | */ 103 | bind (): this 104 | 105 | /** Returns a new type that is the result of adding the rules of one type to another. */ 106 | concat> (schema: TSchema): Schema.concat 107 | 108 | /** Marks a key as required which will not allow undefined as value. All keys are optional by default. */ 109 | required (): SchemaType> 110 | 111 | /** Marks a key as required which will not allow undefined as value. All keys are optional by default. */ 112 | exist (): SchemaType> 113 | 114 | /** Marks a key as optional which will allow undefined as values. Used to annotate the schema for readability as all keys are optional by default. */ 115 | optional (): SchemaType> 116 | 117 | /** Marks a key as forbidden which will not allow any value except undefined. Used to explicitly forbid keys. */ 118 | forbidden (): SchemaType> 119 | 120 | /** Marks a key to be removed from a resulting object or array after validation. Used to sanitize output. */ 121 | strip (): SchemaType> 122 | 123 | /** Annotates the key. */ 124 | description (desc: string): this 125 | 126 | /** Annotates the key. */ 127 | notes (notes: string | string[]): this 128 | 129 | /** Annotates the key. */ 130 | tags (notes: string | string[]): this 131 | 132 | /** Attaches metadata to the key. */ 133 | meta (meta: Record): this 134 | 135 | /** Annotates the key with an example value, must be valid. */ 136 | example (...value: any[]): this 137 | 138 | /** Annotates the key with an unit name. */ 139 | unit (name: string): this 140 | 141 | /** Overrides the global validate() options for the current key and any sub-key. */ 142 | options (options: JoiLib.ValidationOptions): this 143 | 144 | /** Sets the options.convert options to false which prevent type casting for the current key and any child keys. */ 145 | strict (isStrict?: boolean): this 146 | 147 | /** 148 | * Sets a default value if the original value is undefined. 149 | * @param value - the value. 150 | * value supports references. 151 | * value may also be a function which returns the default value. 152 | * If value is specified as a function that accepts a single parameter, that parameter will be a context 153 | * object that can be used to derive the resulting value. This clones the object however, which incurs some 154 | * overhead so if you don't need access to the context define your method so that it does not accept any 155 | * parameters. 156 | * Without any value, default has no effect, except for object that will then create nested defaults 157 | * (applying inner defaults of that object). 158 | * 159 | * Note that if value is an object, any changes to the object after default() is called will change the 160 | * reference and any future assignment. 161 | * 162 | * Additionally, when specifying a method you must either have a description property on your method or the 163 | * second parameter is required. 164 | */ 165 | default (): this 166 | default (value: JoiLib.Reference, description?: string): SchemaType> 167 | default (value: JoiLib.DefaultFunction, description: string): SchemaType> 168 | default (value: JoiLib.DefaultFunctionWithDescription, description?: string): SchemaType> 169 | default (value: TDefault, description?: string): SchemaType> 170 | 171 | /** Converts the type into an alternatives type where the conditions are merged into the type definition. */ 172 | when (ref: string | JoiLib.Reference, options: T): AlternativesSchema>> 173 | when (ref: Schema.SchemaLike, options: T): AlternativesSchema>> 174 | 175 | /** Overrides the key name in error messages. */ 176 | label (name: string): this 177 | 178 | /** Outputs the original untouched value instead of the casted value. */ 179 | raw (isRaw?: boolean): this 180 | 181 | /** 182 | * Considers anything that matches the schema to be empty (undefined). 183 | * @param schema - any object or joi schema to match. An undefined schema unsets that rule. 184 | */ 185 | empty (schema?: Schema.SchemaLike): this 186 | 187 | /** 188 | * Overrides the default joi error with a custom error if the rule fails where: 189 | * @param err - can be: 190 | * an instance of `Error` - the override error. 191 | * a `function(errors)`, taking an array of errors as argument, where it must either: 192 | * return a `string` - substitutes the error message with this text 193 | * return a single ` object` or an `Array` of it, where: 194 | * `type` - optional parameter providing the type of the error (eg. `number.min`). 195 | * `message` - optional parameter if `template` is provided, containing the text of the error. 196 | * `template` - optional parameter if `message` is provided, containing a template string, using the same format as usual joi language errors. 197 | * `context` - optional parameter, to provide context to your error if you are using the `template`. 198 | * return an `Error` - same as when you directly provide an `Error`, but you can customize the error message based on the errors. 199 | * 200 | * Note that if you provide an `Error`, it will be returned as-is, unmodified and undecorated with any of the 201 | * normal joi error properties. If validation fails and another error is found before the error 202 | * override, that error will be returned and the override will be ignored (unless the `abortEarly` 203 | * option has been set to `false`). 204 | */ 205 | error (err: Error | JoiLib.ValidationErrorFunction, options?: JoiLib.ErrorOptions): this 206 | 207 | /** Returns a plain object representing the schema's rules and properties. */ 208 | describe (): JoiLib.Description 209 | } 210 | 211 | export { 212 | AlternativesSchema, 213 | AnySchema, 214 | ArraySchema, 215 | BinarySchema, 216 | BooleanSchema, 217 | DateSchema, 218 | FunctionSchema, 219 | LazySchema, 220 | NumberSchema, 221 | ObjectSchema, 222 | StringSchema, 223 | SymbolSchema 224 | } 225 | -------------------------------------------------------------------------------- /src/schema/lazy.ts: -------------------------------------------------------------------------------- 1 | import { Value } from "../lib/value"; 2 | import { BaseSchema } from "."; 3 | 4 | export interface LazySchema> extends BaseSchema<'lazy', TValue> { 5 | /* This is an empty interface */ 6 | } 7 | -------------------------------------------------------------------------------- /src/schema/number.ts: -------------------------------------------------------------------------------- 1 | import { Value } from "../lib/value"; 2 | import { Reference } from "../lib/joi"; 3 | import { BaseSchema } from "."; 4 | 5 | export interface NumberSchema> extends BaseSchema<'number', TValue> { 6 | /** 7 | * Specifies the minimum value. 8 | * It can also be a reference to another field. 9 | */ 10 | min (limit: number | Reference): this 11 | 12 | /** 13 | * Specifies the maximum value. 14 | * It can also be a reference to another field. 15 | */ 16 | max (limit: number | Reference): this 17 | 18 | /** 19 | * Specifies that the value must be greater than limit. 20 | * It can also be a reference to another field. 21 | */ 22 | greater (limit: number | Reference): this 23 | 24 | /** 25 | * Specifies that the value must be less than limit. 26 | * It can also be a reference to another field. 27 | */ 28 | less (limit: number | Reference): this 29 | 30 | /** 31 | * Requires the number to be an integer (no floating point). 32 | */ 33 | integer (): this 34 | 35 | /** 36 | * Specifies the maximum number of decimal places where: 37 | * @param limit - the maximum number of decimal places allowed. 38 | */ 39 | precision (limit: number): this 40 | 41 | /** 42 | * Specifies that the value must be a multiple of base. 43 | */ 44 | multiple (base: number): this 45 | 46 | /** 47 | * Requires the number to be positive. 48 | */ 49 | positive (): this 50 | 51 | /** 52 | * Requires the number to be negative. 53 | */ 54 | negative (): this 55 | 56 | /** 57 | * Requires the number to be a TCP port, so between 0 and 65535. 58 | */ 59 | port (): this 60 | 61 | /** 62 | * Allows the number to be outside of JavaScript's safety range (Number.MIN_SAFE_INTEGER & Number.MAX_SAFE_INTEGER). 63 | */ 64 | unsafe (enabled: boolean): this; 65 | } 66 | -------------------------------------------------------------------------------- /src/schema/object.ts: -------------------------------------------------------------------------------- 1 | import { Value } from "../lib/value"; 2 | import { Schema } from "../lib/schema"; 3 | import { BaseSchema } from "."; 4 | import { ConstructorOf } from "../lib/util"; 5 | import { RenameOptions, Reference } from "../lib/joi"; 6 | 7 | export interface ObjectSchema>> extends BaseSchema<'object', TValue> { 8 | /** 9 | * Sets or extends the allowed object keys. 10 | */ 11 | keys (schemaMap?: null): ObjectSchema> 12 | keys (schemaMap: TSchemaMap): ObjectSchema< 13 | Value.deepMerge>> 14 | > 15 | 16 | /** 17 | * Appends the allowed object keys. If schema is null, undefined, or {}, no changes will be applied. 18 | */ 19 | append (schemaMap?: null): this 20 | append (schemaMap: TSchemaMap): ObjectSchema< 21 | Value.deepMerge>> 22 | > 23 | 24 | /** 25 | * Requires the object to be an instance of a given constructor. 26 | * 27 | * @param constructor - the constructor function that the object must be an instance of. 28 | * @param name - an alternate name to use in validation errors. This is useful when the constructor function does not have a name. 29 | */ 30 | type (constructor: ConstructorOf, name?: string): ObjectSchema> 31 | 32 | /** 33 | * Requires the object to be a Joi schema instance. 34 | */ 35 | schema (): ObjectSchema>> 36 | 37 | /** 38 | * Specifies the minimum number of keys in the object. 39 | */ 40 | min (limit: number): this 41 | 42 | /** 43 | * Specifies the maximum number of keys in the object. 44 | */ 45 | max (limit: number): this 46 | 47 | /** 48 | * Specifies the exact number of keys in the object. 49 | */ 50 | length (limit: number): this 51 | 52 | /** 53 | * Specify validation rules for unknown keys matching a pattern. 54 | * 55 | * @param pattern - a pattern that can be either a regular expression or a joi schema that will be tested against the unknown key names 56 | * @param schema - the schema object matching keys must validate against 57 | */ 58 | pattern (pattern: RegExp | Schema.SchemaLike, schema: TSchemaLike): ObjectSchema< 59 | Value.appendSchemaMap>> 60 | > 61 | 62 | /** 63 | * Defines an all-or-nothing relationship between keys where if one of the peers is present, all of them are required as well. 64 | * @param peers - the key names of which if one present, all are required. peers can be a single string value, 65 | * an array of string values, or each peer provided as an argument. 66 | */ 67 | and (...peers: string[]): this 68 | and (peers: string[]): this 69 | 70 | /** 71 | * Defines a relationship between keys where not all peers can be present at the same time. 72 | * @param peers - the key names of which if one present, the others may not all be present. 73 | * peers can be a single string value, an array of string values, or each peer provided as an argument. 74 | */ 75 | nand (...peers: string[]): this 76 | nand (peers: string[]): this 77 | 78 | /** 79 | * Defines a relationship between keys where one of the peers is required (and more than one is allowed). 80 | */ 81 | or (...peers: string[]): this 82 | or (peers: string[]): this 83 | 84 | /** 85 | * Defines an exclusive relationship between a set of keys where only one is allowed but none are required where: 86 | * `peers` - the exclusive key names that must not appear together but where none are required. 87 | */ 88 | oxor (...peers: string[]): this; 89 | oxor (peers: string[]): this; 90 | 91 | /** 92 | * Defines an exclusive relationship between a set of keys. one of them is required but not at the same time where: 93 | */ 94 | xor (...peers: string[]): this 95 | xor (peers: string[]): this 96 | 97 | /** 98 | * Requires the presence of other keys whenever the specified key is present. 99 | */ 100 | with (key: string, peers: string | string[]): this 101 | 102 | /** 103 | * Forbids the presence of other keys whenever the specified is present. 104 | */ 105 | without (key: string, peers: string | string[]): this 106 | 107 | /** 108 | * Renames a key to another name (deletes the renamed key). 109 | */ 110 | rename (from: string, to: string, options?: RenameOptions): this 111 | 112 | /** 113 | * Verifies an assertion where. 114 | */ 115 | assert (ref: string | Reference, schema: Schema.SchemaLike, message?: string): this 116 | 117 | /** 118 | * Overrides the handling of unknown keys for the scope of the current object only (does not apply to children). 119 | */ 120 | unknown (allow?: boolean): this 121 | 122 | /** 123 | * Sets the specified children to required. 124 | * 125 | * @param children - can be a single string value, an array of string values, or each child provided as an argument. 126 | * @example 127 | * var schema = Joi.object().keys({ a: { b: Joi.number() }, c: { d: Joi.string() } }); 128 | * var requiredSchema = schema.requiredKeys('', 'a.b', 'c', 'c.d'); 129 | * 130 | * @description 131 | * Note that in this example '' means the current object, a is not required but b is, as well as c and d. 132 | */ 133 | requiredKeys (children: TKeys): ObjectSchema> 134 | requiredKeys (...children: TKeys): ObjectSchema> 135 | 136 | /** 137 | * Sets the specified children to optional. 138 | * 139 | * @param children - can be a single string value, an array of string values, or each child provided as an argument. 140 | * 141 | * The behavior is exactly the same as requiredKeys. 142 | */ 143 | optionalKeys (children: TKeys): ObjectSchema> 144 | optionalKeys (...children: TKeys): ObjectSchema> 145 | 146 | /** 147 | * Sets the specified children to forbidden. 148 | * 149 | * @param children - can be a single string value, an array of string values, or each child provided as an argument. 150 | * @example 151 | * const schema = Joi.object().keys({ a: { b: Joi.number().required() }, c: { d: Joi.string().required() } }); 152 | * const optionalSchema = schema.forbiddenKeys('a.b', 'c.d'); 153 | * 154 | * @description 155 | * The behavior is exactly the same as requiredKeys. 156 | */ 157 | forbiddenKeys (children: TKeys): ObjectSchema> 158 | forbiddenKeys (...children: TKeys): ObjectSchema> 159 | } 160 | -------------------------------------------------------------------------------- /src/schema/string.ts: -------------------------------------------------------------------------------- 1 | import { Value } from "../lib/value"; 2 | import { BaseSchema } from "."; 3 | import * as JoiLib from "../lib/joi"; 4 | 5 | export interface StringSchema> extends BaseSchema<'string', TValue> { 6 | /** 7 | * Allows the value to match any whitelist of blacklist item in a case insensitive comparison. 8 | */ 9 | insensitive (): this 10 | 11 | /** 12 | * Specifies the minimum number string characters. 13 | * @param limit - the minimum number of string characters required. It can also be a reference to another field. 14 | * @param encoding - if specified, the string length is calculated in bytes using the provided encoding. 15 | */ 16 | min (limit: number | JoiLib.Reference, encoding?: string): this 17 | 18 | /** 19 | * Specifies the maximum number of string characters. 20 | * @param limit - the maximum number of string characters allowed. It can also be a reference to another field. 21 | * @param encoding - if specified, the string length is calculated in bytes using the provided encoding. 22 | */ 23 | max (limit: number | JoiLib.Reference, encoding?: string): this 24 | 25 | /** 26 | * Specifies whether the string.max() limit should be used as a truncation. 27 | * @param enabled - optional parameter defaulting to true which allows you to reset the behavior of truncate by providing a falsy value. 28 | */ 29 | truncate (enabled?: boolean): this 30 | 31 | /** 32 | * Requires the string value to be in a unicode normalized form. If the validation convert option is on (enabled by default), the string will be normalized. 33 | * @param form - The unicode normalization form to use. Valid values: NFC [default], NFD, NFKC, NFKD 34 | */ 35 | normalize (form?: 'NFC' | 'NFD' | 'NFKC' | 'NFKD'): this 36 | 37 | /** 38 | * Requires the string value to be a valid base64 string; does not check the decoded value. 39 | * @param options - optional settings: The unicode normalization options to use. Valid values: NFC [default], NFD, NFKC, NFKD 40 | */ 41 | base64 (options?: JoiLib.Base64Options): this 42 | 43 | /** 44 | * Requires the number to be a credit card number (Using Lunh Algorithm). 45 | */ 46 | creditCard (): this 47 | 48 | /** 49 | * Specifies the exact string length required 50 | * @param limit - the required string length. It can also be a reference to another field. 51 | * @param encoding - if specified, the string length is calculated in bytes using the provided encoding. 52 | */ 53 | length (limit: number | JoiLib.Reference, encoding?: string): this 54 | 55 | /** 56 | * Defines a regular expression rule. 57 | * @param pattern - a regular expression object the string value must match against. 58 | * @param options - optional, can be: 59 | * Name for patterns (useful with multiple patterns). Defaults to 'required'. 60 | * An optional configuration object with the following supported properties: 61 | * name - optional pattern name. 62 | * invert - optional boolean flag. Defaults to false behavior. If specified as true, the provided pattern will be disallowed instead of required. 63 | */ 64 | regex (pattern: RegExp, options?: string | JoiLib.StringRegexOptions): this 65 | 66 | /** 67 | * Replace characters matching the given pattern with the specified replacement string where: 68 | * @param pattern - a regular expression object to match against, or a string of which all occurrences will be replaced. 69 | * @param replacement - the string that will replace the pattern. 70 | */ 71 | replace (pattern: RegExp | string, replacement: string): this 72 | 73 | /** 74 | * Requires the string value to only contain a-z, A-Z, and 0-9. 75 | */ 76 | alphanum (): this 77 | 78 | /** 79 | * Requires the string value to only contain a-z, A-Z, 0-9, and underscore _. 80 | */ 81 | token (): this 82 | 83 | /** 84 | * Requires the string value to be a valid email address. 85 | */ 86 | email (options?: JoiLib.EmailOptions): this 87 | 88 | /** 89 | * Requires the string value to be a valid ip address. 90 | */ 91 | ip (options?: JoiLib.IpOptions): this 92 | 93 | /** 94 | * Requires the string value to be a valid RFC 3986 URI. 95 | */ 96 | uri (options?: JoiLib.UriOptions): this 97 | 98 | /** 99 | * Requires the string value to be a valid data URI string. 100 | */ 101 | dataUri (options?: JoiLib.DataUriOptions): this 102 | 103 | /** 104 | * Requires the string value to be a valid GUID. 105 | */ 106 | guid (options?: JoiLib.GuidOptions): this 107 | 108 | /** 109 | * Alias for `guid` -- Requires the string value to be a valid GUID 110 | */ 111 | uuid (options?: JoiLib.GuidOptions): this 112 | 113 | /** 114 | * Requires the string value to be a valid hexadecimal string. 115 | */ 116 | hex (options?: JoiLib.HexOptions): this 117 | 118 | /** 119 | * Requires the string value to be a valid hostname as per RFC1123. 120 | */ 121 | hostname (): this 122 | 123 | /** 124 | * Requires the string value to be in valid ISO 8601 date format. 125 | */ 126 | isoDate (): this 127 | 128 | /** 129 | * Requires the string value to be all lowercase. If the validation convert option is on (enabled by default), the string will be forced to lowercase. 130 | */ 131 | lowercase (): this 132 | 133 | /** 134 | * Requires the string value to be all uppercase. If the validation convert option is on (enabled by default), the string will be forced to uppercase. 135 | */ 136 | uppercase (): this 137 | 138 | /** 139 | * Requires the string value to contain no whitespace before or after. If the validation convert option is on (enabled by default), the string will be trimmed. 140 | */ 141 | trim (): this 142 | } 143 | -------------------------------------------------------------------------------- /src/schema/symbol.ts: -------------------------------------------------------------------------------- 1 | import { Value } from "../lib/value"; 2 | import { BaseSchema } from "."; 3 | 4 | export interface SymbolSchema> extends BaseSchema<'symbol', TValue> { 5 | map (iterable: Iterable<[string | number | boolean | symbol, symbol]> | Record): this 6 | } 7 | -------------------------------------------------------------------------------- /test/util.ts: -------------------------------------------------------------------------------- 1 | import { IsAny, IsInvariant, IsInvariantWithoutAny } from '../src/lib/util'; 2 | 3 | export declare function testInvariant (matches: IsInvariantWithoutAny): void 4 | export declare function testInvariant (t: T, u: U, matches: IsInvariantWithoutAny): void 5 | export declare function testAny (matches: IsAny): void 6 | export declare function testNever (matches: IsInvariant): void 7 | 8 | export declare function type (): T 9 | 10 | export declare interface StubObject { a?: string, b: number } 11 | export declare type StubObjectIntersection = { a?: string } & { b: number } 12 | export declare class StubClass { private a: string } 13 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["src"], 4 | "compilerOptions": { 5 | "outDir": "dist", 6 | "declaration": true, 7 | "emitDeclarationOnly": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["es2015"], 4 | "strict": true, 5 | "types": [ 6 | "node" 7 | ] 8 | }, 9 | "include": [ 10 | "src", 11 | "test" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /typesafe-joi.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@hapi/joi') 2 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@types/hapi__joi@*", "@types/hapi__joi@^15.0.1": 6 | version "15.0.1" 7 | resolved "https://registry.yarnpkg.com/@types/hapi__joi/-/hapi__joi-15.0.1.tgz#6038375074af792b765e34dc799c83d30a406fbe" 8 | integrity sha512-uqH3kTO1nrhe+Pbq+dQKrulrfscRPjFZNv9UWA3FupJZBHw+miT7yiV6C8A80YLnn0o6zbgTProncBb3d7QohA== 9 | dependencies: 10 | "@types/hapi__joi" "*" 11 | 12 | "@types/node@*": 13 | version "11.13.9" 14 | resolved "https://registry.yarnpkg.com/@types/node/-/node-11.13.9.tgz#f80697caca7f7fb2526527a5c5a2743487f05ccc" 15 | integrity sha512-NJ4yuEVw5podZbINp3tEqUIImMSAEHaCXRiWCf3KC32l6hIKf0iPJEh2uZdT0fELfRYk310yLmMXqy2leZQUbg== 16 | 17 | ansi-styles@^3.2.1: 18 | version "3.2.1" 19 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 20 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 21 | dependencies: 22 | color-convert "^1.9.0" 23 | 24 | array-filter@~0.0.0: 25 | version "0.0.1" 26 | resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" 27 | integrity sha1-fajPLiZijtcygDWB/SH2fKzS7uw= 28 | 29 | array-map@~0.0.0: 30 | version "0.0.0" 31 | resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662" 32 | integrity sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI= 33 | 34 | array-reduce@~0.0.0: 35 | version "0.0.0" 36 | resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" 37 | integrity sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys= 38 | 39 | balanced-match@^1.0.0: 40 | version "1.0.0" 41 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 42 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 43 | 44 | brace-expansion@^1.1.7: 45 | version "1.1.11" 46 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 47 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 48 | dependencies: 49 | balanced-match "^1.0.0" 50 | concat-map "0.0.1" 51 | 52 | chalk@^2.4.1: 53 | version "2.4.2" 54 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 55 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 56 | dependencies: 57 | ansi-styles "^3.2.1" 58 | escape-string-regexp "^1.0.5" 59 | supports-color "^5.3.0" 60 | 61 | color-convert@^1.9.0: 62 | version "1.9.3" 63 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 64 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 65 | dependencies: 66 | color-name "1.1.3" 67 | 68 | color-name@1.1.3: 69 | version "1.1.3" 70 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 71 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 72 | 73 | concat-map@0.0.1: 74 | version "0.0.1" 75 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 76 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 77 | 78 | cross-spawn@^6.0.5: 79 | version "6.0.5" 80 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" 81 | integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== 82 | dependencies: 83 | nice-try "^1.0.4" 84 | path-key "^2.0.1" 85 | semver "^5.5.0" 86 | shebang-command "^1.2.0" 87 | which "^1.2.9" 88 | 89 | define-properties@^1.1.2: 90 | version "1.1.3" 91 | resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" 92 | integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== 93 | dependencies: 94 | object-keys "^1.0.12" 95 | 96 | error-ex@^1.3.1: 97 | version "1.3.2" 98 | resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" 99 | integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== 100 | dependencies: 101 | is-arrayish "^0.2.1" 102 | 103 | es-abstract@^1.4.3: 104 | version "1.13.0" 105 | resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" 106 | integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== 107 | dependencies: 108 | es-to-primitive "^1.2.0" 109 | function-bind "^1.1.1" 110 | has "^1.0.3" 111 | is-callable "^1.1.4" 112 | is-regex "^1.0.4" 113 | object-keys "^1.0.12" 114 | 115 | es-to-primitive@^1.2.0: 116 | version "1.2.0" 117 | resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" 118 | integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== 119 | dependencies: 120 | is-callable "^1.1.4" 121 | is-date-object "^1.0.1" 122 | is-symbol "^1.0.2" 123 | 124 | es6-object-assign@^1.0.3: 125 | version "1.1.0" 126 | resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c" 127 | integrity sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw= 128 | 129 | escape-string-regexp@^1.0.5: 130 | version "1.0.5" 131 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 132 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 133 | 134 | fs.realpath@^1.0.0: 135 | version "1.0.0" 136 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 137 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 138 | 139 | function-bind@^1.0.2, function-bind@^1.1.1: 140 | version "1.1.1" 141 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 142 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 143 | 144 | glob@^7.0.0: 145 | version "7.1.3" 146 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" 147 | integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== 148 | dependencies: 149 | fs.realpath "^1.0.0" 150 | inflight "^1.0.4" 151 | inherits "2" 152 | minimatch "^3.0.4" 153 | once "^1.3.0" 154 | path-is-absolute "^1.0.0" 155 | 156 | graceful-fs@^4.1.2: 157 | version "4.1.15" 158 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" 159 | integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== 160 | 161 | has-flag@^3.0.0: 162 | version "3.0.0" 163 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 164 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 165 | 166 | has-symbols@^1.0.0: 167 | version "1.0.0" 168 | resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" 169 | integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= 170 | 171 | has@^1.0.1, has@^1.0.3: 172 | version "1.0.3" 173 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 174 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 175 | dependencies: 176 | function-bind "^1.1.1" 177 | 178 | hosted-git-info@^2.1.4: 179 | version "2.7.1" 180 | resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" 181 | integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w== 182 | 183 | inflight@^1.0.4: 184 | version "1.0.6" 185 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 186 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 187 | dependencies: 188 | once "^1.3.0" 189 | wrappy "1" 190 | 191 | inherits@2: 192 | version "2.0.3" 193 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 194 | integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= 195 | 196 | interpret@^1.0.0: 197 | version "1.2.0" 198 | resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" 199 | integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== 200 | 201 | is-arrayish@^0.2.1: 202 | version "0.2.1" 203 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" 204 | integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= 205 | 206 | is-callable@^1.1.4: 207 | version "1.1.4" 208 | resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" 209 | integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== 210 | 211 | is-date-object@^1.0.1: 212 | version "1.0.1" 213 | resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" 214 | integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= 215 | 216 | is-regex@^1.0.4: 217 | version "1.0.4" 218 | resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" 219 | integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= 220 | dependencies: 221 | has "^1.0.1" 222 | 223 | is-symbol@^1.0.2: 224 | version "1.0.2" 225 | resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" 226 | integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== 227 | dependencies: 228 | has-symbols "^1.0.0" 229 | 230 | isexe@^2.0.0: 231 | version "2.0.0" 232 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 233 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= 234 | 235 | json-parse-better-errors@^1.0.1: 236 | version "1.0.2" 237 | resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" 238 | integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== 239 | 240 | jsonify@~0.0.0: 241 | version "0.0.0" 242 | resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" 243 | integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= 244 | 245 | load-json-file@^4.0.0: 246 | version "4.0.0" 247 | resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" 248 | integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= 249 | dependencies: 250 | graceful-fs "^4.1.2" 251 | parse-json "^4.0.0" 252 | pify "^3.0.0" 253 | strip-bom "^3.0.0" 254 | 255 | memorystream@^0.3.1: 256 | version "0.3.1" 257 | resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" 258 | integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= 259 | 260 | minimatch@^3.0.4: 261 | version "3.0.4" 262 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 263 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 264 | dependencies: 265 | brace-expansion "^1.1.7" 266 | 267 | minimist@^1.2.0: 268 | version "1.2.5" 269 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" 270 | integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== 271 | 272 | nice-try@^1.0.4: 273 | version "1.0.5" 274 | resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" 275 | integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== 276 | 277 | normalize-package-data@^2.3.2: 278 | version "2.5.0" 279 | resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" 280 | integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== 281 | dependencies: 282 | hosted-git-info "^2.1.4" 283 | resolve "^1.10.0" 284 | semver "2 || 3 || 4 || 5" 285 | validate-npm-package-license "^3.0.1" 286 | 287 | npm-run-all@^4.1.5: 288 | version "4.1.5" 289 | resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba" 290 | integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ== 291 | dependencies: 292 | ansi-styles "^3.2.1" 293 | chalk "^2.4.1" 294 | cross-spawn "^6.0.5" 295 | memorystream "^0.3.1" 296 | minimatch "^3.0.4" 297 | pidtree "^0.3.0" 298 | read-pkg "^3.0.0" 299 | shell-quote "^1.6.1" 300 | string.prototype.padend "^3.0.0" 301 | 302 | object-keys@^1.0.12: 303 | version "1.1.1" 304 | resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" 305 | integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== 306 | 307 | once@^1.3.0: 308 | version "1.4.0" 309 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 310 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 311 | dependencies: 312 | wrappy "1" 313 | 314 | parse-json@^4.0.0: 315 | version "4.0.0" 316 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" 317 | integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= 318 | dependencies: 319 | error-ex "^1.3.1" 320 | json-parse-better-errors "^1.0.1" 321 | 322 | path-is-absolute@^1.0.0: 323 | version "1.0.1" 324 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 325 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 326 | 327 | path-key@^2.0.1: 328 | version "2.0.1" 329 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" 330 | integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= 331 | 332 | path-parse@^1.0.6: 333 | version "1.0.6" 334 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" 335 | integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== 336 | 337 | path-type@^3.0.0: 338 | version "3.0.0" 339 | resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" 340 | integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== 341 | dependencies: 342 | pify "^3.0.0" 343 | 344 | pidtree@^0.3.0: 345 | version "0.3.0" 346 | resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.0.tgz#f6fada10fccc9f99bf50e90d0b23d72c9ebc2e6b" 347 | integrity sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg== 348 | 349 | pify@^3.0.0: 350 | version "3.0.0" 351 | resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" 352 | integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= 353 | 354 | read-pkg@^3.0.0: 355 | version "3.0.0" 356 | resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" 357 | integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= 358 | dependencies: 359 | load-json-file "^4.0.0" 360 | normalize-package-data "^2.3.2" 361 | path-type "^3.0.0" 362 | 363 | rechoir@^0.6.2: 364 | version "0.6.2" 365 | resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" 366 | integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= 367 | dependencies: 368 | resolve "^1.1.6" 369 | 370 | resolve@^1.1.6, resolve@^1.10.0: 371 | version "1.10.1" 372 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.1.tgz#664842ac960795bbe758221cdccda61fb64b5f18" 373 | integrity sha512-KuIe4mf++td/eFb6wkaPbMDnP6kObCaEtIDuHOUED6MNUo4K670KZUHuuvYPZDxNF0WVLw49n06M2m2dXphEzA== 374 | dependencies: 375 | path-parse "^1.0.6" 376 | 377 | "semver@2 || 3 || 4 || 5", semver@^5.5.0: 378 | version "5.7.0" 379 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" 380 | integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== 381 | 382 | shebang-command@^1.2.0: 383 | version "1.2.0" 384 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" 385 | integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= 386 | dependencies: 387 | shebang-regex "^1.0.0" 388 | 389 | shebang-regex@^1.0.0: 390 | version "1.0.0" 391 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" 392 | integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= 393 | 394 | shell-quote@^1.6.1: 395 | version "1.6.1" 396 | resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" 397 | integrity sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c= 398 | dependencies: 399 | array-filter "~0.0.0" 400 | array-map "~0.0.0" 401 | array-reduce "~0.0.0" 402 | jsonify "~0.0.0" 403 | 404 | shelljs@^0.8.1: 405 | version "0.8.3" 406 | resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.3.tgz#a7f3319520ebf09ee81275b2368adb286659b097" 407 | integrity sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A== 408 | dependencies: 409 | glob "^7.0.0" 410 | interpret "^1.0.0" 411 | rechoir "^0.6.2" 412 | 413 | shx@^0.3.2: 414 | version "0.3.2" 415 | resolved "https://registry.yarnpkg.com/shx/-/shx-0.3.2.tgz#40501ce14eb5e0cbcac7ddbd4b325563aad8c123" 416 | integrity sha512-aS0mWtW3T2sHAenrSrip2XGv39O9dXIFUqxAEWHEOS1ePtGIBavdPJY1kE2IHl14V/4iCbUiNDPGdyYTtmhSoA== 417 | dependencies: 418 | es6-object-assign "^1.0.3" 419 | minimist "^1.2.0" 420 | shelljs "^0.8.1" 421 | 422 | spdx-correct@^3.0.0: 423 | version "3.1.0" 424 | resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" 425 | integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== 426 | dependencies: 427 | spdx-expression-parse "^3.0.0" 428 | spdx-license-ids "^3.0.0" 429 | 430 | spdx-exceptions@^2.1.0: 431 | version "2.2.0" 432 | resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" 433 | integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== 434 | 435 | spdx-expression-parse@^3.0.0: 436 | version "3.0.0" 437 | resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" 438 | integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== 439 | dependencies: 440 | spdx-exceptions "^2.1.0" 441 | spdx-license-ids "^3.0.0" 442 | 443 | spdx-license-ids@^3.0.0: 444 | version "3.0.4" 445 | resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz#75ecd1a88de8c184ef015eafb51b5b48bfd11bb1" 446 | integrity sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA== 447 | 448 | string.prototype.padend@^3.0.0: 449 | version "3.0.0" 450 | resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz#f3aaef7c1719f170c5eab1c32bf780d96e21f2f0" 451 | integrity sha1-86rvfBcZ8XDF6rHDK/eA2W4h8vA= 452 | dependencies: 453 | define-properties "^1.1.2" 454 | es-abstract "^1.4.3" 455 | function-bind "^1.0.2" 456 | 457 | strip-bom@^3.0.0: 458 | version "3.0.0" 459 | resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" 460 | integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= 461 | 462 | supports-color@^5.3.0: 463 | version "5.5.0" 464 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 465 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 466 | dependencies: 467 | has-flag "^3.0.0" 468 | 469 | typescript@^3.4.5: 470 | version "3.4.5" 471 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.5.tgz#2d2618d10bb566572b8d7aad5180d84257d70a99" 472 | integrity sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw== 473 | 474 | validate-npm-package-license@^3.0.1: 475 | version "3.0.4" 476 | resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" 477 | integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== 478 | dependencies: 479 | spdx-correct "^3.0.0" 480 | spdx-expression-parse "^3.0.0" 481 | 482 | which@^1.2.9: 483 | version "1.3.1" 484 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 485 | integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== 486 | dependencies: 487 | isexe "^2.0.0" 488 | 489 | wrappy@1: 490 | version "1.0.2" 491 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 492 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 493 | --------------------------------------------------------------------------------