schemaglobin
Advanced tools
Comparing version 4.7.0 to 5.0.0
@@ -7,2 +7,2 @@ import type { Schema } from "../Schema"; | ||
/** Schema that always returns null. */ | ||
export declare const nullSchema: Schema<undefined>; | ||
export declare const alwaysNull: Schema<undefined>; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.nullSchema = exports.isNotNull = exports.isNull = void 0; | ||
exports.alwaysNull = exports.isNotNull = exports.isNull = void 0; | ||
/** Is a value null? */ | ||
@@ -9,4 +9,4 @@ exports.isNull = (v) => v === null; | ||
/** Schema that always returns null. */ | ||
exports.nullSchema = { | ||
exports.alwaysNull = { | ||
validate: () => undefined, | ||
}; |
import type { Schema } from "../Schema"; | ||
import type { PartialObject } from "../types"; | ||
/** Is a value undefined? */ | ||
@@ -7,2 +8,11 @@ export declare const isUndefined: (v: unknown) => v is undefined; | ||
/** Schema that always returns undefined. */ | ||
export declare const undefinedSchema: Schema<undefined>; | ||
export declare const alwaysUndefined: Schema<undefined>; | ||
/** Modify an input schema to make it allow undefined (in addition to its normally valid value). */ | ||
export declare const withUndefined: <T>(schema: Schema<T>) => Schema<T | undefined>; | ||
/** | ||
* Modify an input MapSchema or ObjectSchema schema to make it allow partial object props. | ||
* - i.e. if schema validates an object, all props of that object can be their normal value _or_ `undefined`. | ||
* - If schema does not validate an object (i.e. it's not an `ObjectSchema` or `MapSchema`) then it won't be modified. | ||
* - Works deeply, so nested `ObjectSchema` or `MapSchemas` under the input schema will also allow partial object props. | ||
*/ | ||
export declare const withPartial: <T>(schema: Schema<T>) => Schema<T | PartialObject<T>>; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.undefinedSchema = exports.isDefined = exports.isUndefined = void 0; | ||
exports.withPartial = exports.withUndefined = exports.alwaysUndefined = exports.isDefined = exports.isUndefined = void 0; | ||
const MapSchema_1 = require("../schemas/MapSchema"); | ||
const ObjectSchema_1 = require("../schemas/ObjectSchema"); | ||
const object_1 = require("./object"); | ||
/** Is a value undefined? */ | ||
@@ -9,4 +12,23 @@ exports.isUndefined = (v) => v === undefined; | ||
/** Schema that always returns undefined. */ | ||
exports.undefinedSchema = { | ||
exports.alwaysUndefined = { | ||
validate: () => undefined, | ||
}; | ||
/** Modify an input schema to make it allow undefined (in addition to its normally valid value). */ | ||
exports.withUndefined = (schema) => ({ | ||
validate(unsafeValue) { | ||
return unsafeValue === undefined ? unsafeValue : schema.validate(unsafeValue); | ||
}, | ||
}); | ||
/** | ||
* Modify an input MapSchema or ObjectSchema schema to make it allow partial object props. | ||
* - i.e. if schema validates an object, all props of that object can be their normal value _or_ `undefined`. | ||
* - If schema does not validate an object (i.e. it's not an `ObjectSchema` or `MapSchema`) then it won't be modified. | ||
* - Works deeply, so nested `ObjectSchema` or `MapSchemas` under the input schema will also allow partial object props. | ||
*/ | ||
exports.withPartial = (schema) => (schema instanceof ObjectSchema_1.ObjectSchema | ||
? new ObjectSchema_1.ObjectSchema({ props: object_1.mapObject(schema.props, withPartialDeep) }) // If schema is an ObjectSchema, modify its props option so each of them is partial and undefined. | ||
: schema instanceof MapSchema_1.MapSchema | ||
? new MapSchema_1.MapSchema({ items: withPartialDeep(schema.items) }) // If schema is an MapSchema, modify its items option so it is partial and undefined. | ||
: schema); // Else return the unmodified schema. | ||
/** Modify an input schema to make it allow to be undefined and allow partial object props. */ | ||
const withPartialDeep = (schema) => exports.withUndefined(exports.withPartial(schema)); |
@@ -15,10 +15,2 @@ import type { Invalid } from "./helpers/invalid"; | ||
/** | ||
* ValidateFlags enforces the type of the options bag that is passed into `validate()` on runtime. | ||
* - Can be passed into `validate()` as the second argument to configure the validation in some way. | ||
* - Will be passed down to subschemas (if the validation uses subschemas at all). | ||
*/ | ||
export declare type ValidateFlags = { | ||
readonly [flag: string]: unknown; | ||
}; | ||
/** | ||
* Schema is an object instance with a `validate()` method. | ||
@@ -43,3 +35,3 @@ * - Type `T` represents the type of value `validate()` returns. | ||
* @param unsafeValue A potentially invalid value. | ||
* @param flags A set of flags to configure the validation attempt. | ||
* @param partial Whether or not to to allow `undefined` values (i.e. call any functions and strip any undefined values). | ||
* | ||
@@ -49,3 +41,3 @@ * @returns Valid value. | ||
*/ | ||
validate(unsafeValue?: unknown, flags?: ValidateFlags): T | Invalid; | ||
validate(unsafeValue?: unknown): T | Invalid; | ||
} | ||
@@ -52,0 +44,0 @@ /** |
@@ -1,2 +0,2 @@ | ||
import { Schema, SchemaOptions, SchemaType, ValidateFlags } from "../Schema"; | ||
import { Schema, SchemaOptions, SchemaType } from "../Schema"; | ||
import { Invalid } from "../helpers/invalid"; | ||
@@ -52,3 +52,3 @@ /** Coerce an unknown value to an array (if possible). */ | ||
constructor({ title, description, placeholder, value, required, min, max, items }: ArraySchemaOptions<S, R>); | ||
validate(unsafeValue?: unknown, flags?: ValidateFlags): ArraySchemaType<S> | Invalid; | ||
validate(unsafeValue?: unknown): ArraySchemaType<S> | Invalid; | ||
} | ||
@@ -55,0 +55,0 @@ /** Shortcuts for ArraySchema. */ |
@@ -55,3 +55,3 @@ "use strict"; | ||
} | ||
validate(unsafeValue = this.value, flags = {}) { | ||
validate(unsafeValue = this.value) { | ||
// Coorce. | ||
@@ -84,3 +84,3 @@ const unsafeArray = coerceArray(unsafeValue); | ||
const current = unsafeArray[i]; | ||
const value = items.validate(current, flags); | ||
const value = items.validate(current); | ||
if (value instanceof invalid_1.Invalid) { | ||
@@ -87,0 +87,0 @@ invalid = true; |
@@ -1,2 +0,2 @@ | ||
import type { Schema, SchemaOptions, SchemaType, ValidateFlags } from "../Schema"; | ||
import type { Schema, SchemaOptions, SchemaType } from "../Schema"; | ||
import { Invalid } from "../helpers/invalid"; | ||
@@ -35,3 +35,3 @@ /** Coerce an unknown value to a map (if possible). */ | ||
constructor({ title, description, placeholder, value, required, items, min, max }: MapSchemaOptions<S, R>); | ||
validate(unsafeValue?: unknown, flags?: ValidateFlags): MapSchemaType<S> | Invalid; | ||
validate(unsafeValue?: unknown): MapSchemaType<S> | Invalid; | ||
} | ||
@@ -38,0 +38,0 @@ /** Shortcuts for MapSchema. */ |
@@ -35,3 +35,3 @@ "use strict"; | ||
} | ||
validate(unsafeValue = this.value, flags = {}) { | ||
validate(unsafeValue = this.value) { | ||
// Coorce. | ||
@@ -62,15 +62,14 @@ const unsafeObject = coerceMap(unsafeValue); | ||
const invalids = {}; | ||
Object.entries(unsafeObject).forEach(([key, current]) => { | ||
// Validate the value. | ||
const value = this.items.validate(current, flags); | ||
if (value instanceof invalid_1.Invalid) { | ||
for (const [key, unsafeProp] of Object.entries(unsafeObject)) { | ||
const safeProp = this.items.validate(unsafeProp); | ||
if (safeProp instanceof invalid_1.Invalid) { | ||
invalid = true; | ||
invalids[key] = value.message; | ||
invalids[key] = safeProp.message; | ||
} | ||
else { | ||
if (value !== current) | ||
if (safeProp !== unsafeProp) | ||
changed = true; | ||
output[key] = value; | ||
output[key] = safeProp; | ||
} | ||
}); | ||
} | ||
// If any Schema threw Invalid, return an Invalids. | ||
@@ -77,0 +76,0 @@ if (invalid) |
@@ -1,3 +0,3 @@ | ||
import type { Schema, Schemas, SchemasType, SchemaOptions, ValidateFlags } from "../Schema"; | ||
import type { NullIfOptional, DeepPartial, UnknownObject } from "../types"; | ||
import type { Schema, Schemas, SchemasType, SchemaOptions } from "../Schema"; | ||
import type { NullIfOptional, UnknownObject } from "../types"; | ||
import { Invalid } from "../helpers/invalid"; | ||
@@ -7,3 +7,2 @@ /** Coerce an unknown value to an object (if possible). */ | ||
export declare type ObjectSchemaType<S extends Schemas = Schemas, R extends boolean = false> = Readonly<SchemasType<S>> | NullIfOptional<R>; | ||
export declare type PartialObjectSchemaType<S extends Schemas = Schemas, R extends boolean = false> = Readonly<DeepPartial<SchemasType<S>>> | NullIfOptional<R>; | ||
export interface ObjectSchemaOptions<S extends Schemas = Schemas, R extends boolean = false> extends SchemaOptions { | ||
@@ -14,5 +13,2 @@ readonly props: S; | ||
} | ||
export interface ObjectSchemaFlags extends ValidateFlags { | ||
partial?: boolean; | ||
} | ||
/** | ||
@@ -36,6 +32,3 @@ * Schema that defines a valid object. | ||
constructor({ title, description, placeholder, value, required, props }: ObjectSchemaOptions<S, R>); | ||
validate(unsafeValue: unknown, flags: { | ||
partial: true; | ||
} & ObjectSchemaFlags): PartialObjectSchemaType<S, R> | Invalid; | ||
validate(unsafeValue?: unknown, flags?: ObjectSchemaFlags): ObjectSchemaType<S, R> | Invalid; | ||
validate(unsafeValue?: unknown): ObjectSchemaType<S, R> | Invalid; | ||
} | ||
@@ -42,0 +35,0 @@ /** Shortcuts for ObjectSchema. */ |
@@ -30,3 +30,3 @@ "use strict"; | ||
} | ||
validate(unsafeValue = this.value, flags = {}) { | ||
validate(unsafeValue = this.value) { | ||
// Coorce. | ||
@@ -42,3 +42,2 @@ const unsafeObj = coerceObject(unsafeValue); | ||
// Return. | ||
// We know this type assertion is sound because `null` can never be returned if `this.required == true`. | ||
return null; | ||
@@ -51,43 +50,19 @@ } | ||
const invalids = {}; | ||
if (flags.partial) { | ||
Object.entries(unsafeObj).forEach(([key, unsafeProp]) => { | ||
if (key in this.props) { | ||
// Known props: validate against schema. | ||
const schema = this.props[key]; | ||
const safeProp = schema.validate(unsafeProp, flags); | ||
if (safeProp instanceof invalid_1.Invalid) { | ||
invalid = true; | ||
invalids[key] = safeProp.message; | ||
} | ||
else { | ||
if (safeProp !== unsafeProp) | ||
changed = true; | ||
safeObj[key] = safeProp; | ||
} | ||
} | ||
else { | ||
// Unknown prop: needs to be stripped from the return. | ||
const propSchemas = Object.entries(this.props); | ||
for (const [key, schema] of propSchemas) { | ||
const unsafeProp = unsafeObj[key]; | ||
const safeProp = schema.validate(unsafeProp); | ||
if (safeProp instanceof invalid_1.Invalid) { | ||
invalid = true; | ||
invalids[key] = safeProp.message; | ||
} | ||
else { | ||
if (safeProp !== unsafeProp) | ||
changed = true; | ||
} | ||
}); | ||
safeObj[key] = safeProp; | ||
} | ||
} | ||
else { | ||
const entries = Object.entries(this.props); | ||
entries.forEach(([key, schema]) => { | ||
const unsafeProp = unsafeObj[key]; | ||
const safeProp = schema.validate(unsafeProp, flags); | ||
if (safeProp instanceof invalid_1.Invalid) { | ||
invalid = true; | ||
invalids[key] = safeProp.message; | ||
} | ||
else { | ||
if (safeProp !== unsafeProp) | ||
changed = true; | ||
safeObj[key] = safeProp; | ||
} | ||
}); | ||
// If input has keys that aren't in props, then these keys are _excess_ and we need to return output. | ||
if (Object.keys(unsafeObj).length > entries.length) | ||
changed = true; | ||
} | ||
// If input has keys that aren't in props, then these keys are _excess_ and we need to return output. | ||
if (Object.keys(unsafeObj).length > propSchemas.length) | ||
changed = true; | ||
// If any Schema threw Invalid, return an Invalids. | ||
@@ -94,0 +69,0 @@ if (invalid) |
@@ -7,9 +7,23 @@ /** Helper type that allows `null` if `R` (required) is false. */ | ||
export declare type EmptyIfOptional<R extends boolean> = R extends true ? never : ""; | ||
/** An object whose properties are unknown. */ | ||
/** | ||
* Unknown object: an object whose properties are unknown. | ||
* - Use this to represent POJO plain objects with string keys. | ||
* - Very useful as a generic type to allow more-specific extension. | ||
* - Never use `{}` to represent empty objects because all objects and arrays and functions can extend it. | ||
*/ | ||
export declare type UnknownObject = Record<string, unknown>; | ||
/** An object with no properties. */ | ||
/** | ||
* Empty object: an object with no properties. | ||
* - Use this as a type when you want to represent an empty object. | ||
* - Never use `{}` to represent empty objects because all objects and arrays and functions can extend it. | ||
*/ | ||
export declare type EmptyObject = Record<never, never>; | ||
/** Deep partial: Like `Partial` but works recursively on objects. */ | ||
export declare type DeepPartial<T extends UnknownObject = UnknownObject> = T | { | ||
[K in keyof T]?: T[K] extends UnknownObject ? DeepPartial<T[K]> : T[K]; | ||
}; | ||
/** | ||
* Partial object: a convert an object to its partial version. | ||
* - Any value that extends `UnknownObject`has its props made partial. | ||
* - Works deeply on nested objects too. | ||
* - Only makes plain objects changed (i.e. objects that extend `UnknownObject`), not arrays and functions. | ||
*/ | ||
export declare type PartialObject<T> = T extends UnknownObject ? { | ||
[K in keyof T]?: PartialObject<T[K]>; | ||
} : T; |
{ | ||
"name": "schemaglobin", | ||
"description": "Validate user-entered data.", | ||
"version": "4.7.0", | ||
"version": "5.0.0", | ||
"repository": "https://github.com/dhoulb/schemaglobin", | ||
@@ -6,0 +6,0 @@ "author": "Dave Houlbrooke <dave@shax.com>", |
@@ -238,4 +238,2 @@ # Schemaglobin: Validate unknown user input against schemas | ||
- If `options.options` is set it can return a more specific type, e.g. `"a" | "b" | "" | Invalid` | ||
- `ObjectSchema.validate()` | ||
- If `flags.partial` is set it returns a deep partial of the object (i.e. all props become optional). | ||
@@ -294,25 +292,2 @@ ```ts | ||
### Validation flags | ||
The second argument passed to `validate()` is an options bag of flags which can modify the validation behaviour. For example the `flags.partial` flag makes `ObjectSchema` validation _partial_ (i.e. missing properties are not invalid). | ||
```ts | ||
import { object, string, number } from "schemaglobin"; | ||
const schema = object.required({{ | ||
name: string.required, | ||
age: number.required, | ||
job: string.required, | ||
}); | ||
// Normally a partial value is invalid... | ||
const invalid = schema.validate({ name: "Dave", age: "35" }); | ||
console.log(invalid.message); // "Invalid format" | ||
console.log(invalid.messages); // { job: "Must be string" } | ||
// But with the partial flag the value is valid. | ||
const valid = schema.validate({ name: "Dave", age: "35" }); | ||
console.log(valid); // { name: "Dave", age: 35 } | ||
``` | ||
## Reference | ||
@@ -511,6 +486,2 @@ | ||
`validate()` on `ObjectSchema` instances supports the following flags: | ||
- `flags.partial` - Validate a partial object, i.e. everything in `options.props` becomes optional, and missing props are not added to the returned value (works deeply/recursively too because `flags` is passed down to subschemas). | ||
### `string()` | ||
@@ -517,0 +488,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2537
137273
578