Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

schemaglobin

Package Overview
Dependencies
Maintainers
1
Versions
64
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

schemaglobin - npm Package Compare versions

Comparing version 3.3.7 to 4.0.0

dist/helpers.d.ts

4

dist/index.d.ts

@@ -1,2 +0,3 @@

export * from "./types";
export { NullIfOptional, FalseIfOptional, EmptyIfOptional, DeepPartial, UnknownObject } from "./types";
export { SchemaOptions, ValidateFlags, Schema, SchemaType, Schemas, SchemasType } from "./Schema";
export * from "./schemas/ArraySchema";

@@ -14,1 +15,2 @@ export * from "./schemas/BooleanSchema";

export * from "./Invalid";
export * from "./helpers";

@@ -20,1 +20,3 @@ "use strict";

__export(require("./Invalid"));
// Export helpers.
__export(require("./helpers"));

@@ -1,2 +0,2 @@

import { Schema, SchemaWithSchemas, SchemaOptions, SchemaType } from "../types";
import { Schema, SchemaOptions, SchemaType, ValidateFlags } from "../Schema";
import { Invalid } from "../Invalid";

@@ -37,3 +37,3 @@ interface ArrayOptions<S extends Schema = Schema, R extends boolean = false> extends SchemaOptions {

*/
export declare class ArraySchema<S extends Schema = Schema, R extends boolean = false> implements SchemaWithSchemas<ReadonlyArray<SchemaType<S>>> {
export declare class ArraySchema<S extends Schema = Schema, R extends boolean = false> implements Schema<ReadonlyArray<SchemaType<S>>> {
readonly title: string;

@@ -44,15 +44,10 @@ readonly description: string;

readonly required: R;
/**
* Describe the minimum and maximum numbers of items.
*/
/** Describe the minimum and maximum numbers of items. */
readonly min: number | null;
readonly max: number | null;
/**
* Describe the format for _all_ items in the array.
*/
/** Describe the format for _all_ items in the array. */
readonly items: S;
constructor({ title, description, placeholder, value, required, min, max, items, }: ArrayOptions<S, R>);
schema(): S;
private coerce;
validate(unsafeValue?: unknown): ReadonlyArray<SchemaType<S>> | Invalid;
validate(unsafeValue?: unknown, flags?: ValidateFlags): ReadonlyArray<SchemaType<S>> | Invalid;
}

@@ -59,0 +54,0 @@ /** Shortcuts for ArraySchema. */

@@ -33,5 +33,3 @@ "use strict";

constructor({ title = "", description = "", placeholder = "", value = [], required = false, min = 0, max = null, items, }) {
/**
* Describe the minimum and maximum numbers of items.
*/
/** Describe the minimum and maximum numbers of items. */
this.min = null;

@@ -48,6 +46,2 @@ this.max = null;

}
// Implement SchemasSchema
schema() {
return this.items;
}
coerce(value) {

@@ -60,3 +54,3 @@ if (!value)

}
validate(unsafeValue = this.value) {
validate(unsafeValue = this.value, flags = {}) {
// Coorce.

@@ -89,3 +83,3 @@ const unsafeArray = this.coerce(unsafeValue);

const current = unsafeArray[i];
const value = items.validate(current);
const value = items.validate(current, flags);
if (value instanceof Invalid_1.Invalid) {

@@ -92,0 +86,0 @@ invalid = true;

@@ -1,2 +0,3 @@

import { Schema, SchemaOptions, FalseIfOptional } from "../types";
import type { Schema, SchemaOptions } from "../Schema";
import type { FalseIfOptional } from "../types";
import { Invalid } from "../Invalid";

@@ -3,0 +4,0 @@ interface BooleanOptions<R extends boolean> extends SchemaOptions {

@@ -1,2 +0,3 @@

import { Schema, SchemaOptions, NullIfOptional } from "../types";
import type { Schema, SchemaOptions } from "../Schema";
import type { NullIfOptional } from "../types";
import { Invalid } from "../Invalid";

@@ -3,0 +4,0 @@ /** Convert an unknown value to a date string (or return Invalid) */

@@ -1,2 +0,3 @@

import { Schema, SchemaOptions, NullIfOptional } from "../types";
import type { Schema, SchemaOptions } from "../Schema";
import type { NullIfOptional } from "../types";
import { Invalid } from "../Invalid";

@@ -3,0 +4,0 @@ interface EmailOptions<R extends boolean = false> extends SchemaOptions {

@@ -1,2 +0,3 @@

import { Schema, SchemaOptions, NullIfOptional } from "../types";
import type { Schema, SchemaOptions } from "../Schema";
import type { NullIfOptional } from "../types";
import { Invalid } from "../Invalid";

@@ -3,0 +4,0 @@ interface KeyOptions<R extends boolean = false> extends SchemaOptions {

@@ -1,2 +0,2 @@

import { Schema, SchemaWithSchemas, SchemaOptions, SchemaType } from "../types";
import type { Schema, SchemaOptions, SchemaType, ValidateFlags } from "../Schema";
import { Invalid } from "../Invalid";

@@ -14,3 +14,3 @@ interface MapOptions<S extends Schema = Schema, R extends boolean = false> extends SchemaOptions {

*/
export declare class MapSchema<S extends Schema = Schema, R extends boolean = false> implements SchemaWithSchemas<Readonly<Record<string, SchemaType<S>>>> {
export declare class MapSchema<S extends Schema = Schema, R extends boolean = false> implements Schema<Readonly<Record<string, SchemaType<S>>>> {
readonly title: string;

@@ -33,5 +33,4 @@ readonly description: string;

constructor({ title, description, placeholder, value, required, items, min, max, }: MapOptions<S, R>);
schema(): S;
private coerce;
validate(unsafeValue?: unknown): Readonly<Record<string, SchemaType<S>>> | Invalid;
validate(unsafeValue?: unknown, flags?: ValidateFlags): Readonly<Record<string, SchemaType<S>>> | Invalid;
}

@@ -38,0 +37,0 @@ /** Shortcuts for MapSchema. */

@@ -25,6 +25,2 @@ "use strict";

}
// Implement SchemasSchema
schema() {
return this.items;
}
coerce(value) {

@@ -37,3 +33,3 @@ if (!value)

}
validate(unsafeValue = this.value) {
validate(unsafeValue = this.value, flags = {}) {
// Coorce.

@@ -66,3 +62,3 @@ const unsafeObject = this.coerce(unsafeValue);

// Validate the value.
const value = this.items.validate(current);
const value = this.items.validate(current, flags);
if (value instanceof Invalid_1.Invalid) {

@@ -69,0 +65,0 @@ invalid = true;

@@ -1,2 +0,3 @@

import { Schema, SchemaOptions, NullIfOptional } from "../types";
import type { Schema, SchemaOptions } from "../Schema";
import type { NullIfOptional } from "../types";
import { Invalid } from "../Invalid";

@@ -3,0 +4,0 @@ interface NumberOptions<T extends number = number, R extends boolean = false> extends SchemaOptions {

@@ -1,6 +0,5 @@

import { Schema, SchemaWithSchemas, SchemaOptions, SchemaType, NullIfOptional } from "../types";
import type { Schema, SchemaType, Schemas, SchemasType, SchemaOptions, ValidateFlags } from "../Schema";
import type { NullIfOptional, DeepPartial } from "../types";
import { Invalid } from "../Invalid";
interface ObjectOptions<S extends {
[prop: string]: Schema;
} = {}, R extends boolean = false> extends SchemaOptions {
interface ObjectOptions<S extends Schemas = Schemas, R extends boolean = false> extends SchemaOptions {
readonly props: S;

@@ -12,2 +11,5 @@ readonly value?: Partial<{

}
interface ObjectFlags extends ValidateFlags {
partial?: boolean;
}
/**

@@ -19,7 +21,3 @@ * Schema that defines a valid object.

*/
export declare class ObjectSchema<S extends {
[prop: string]: Schema;
} = {}, R extends boolean = false> implements SchemaWithSchemas<Readonly<{
[K in keyof S]: SchemaType<S[K]>;
}> | NullIfOptional<R>> {
export declare class ObjectSchema<S extends Schemas = Schemas, R extends boolean = false> implements Schema<SchemasType<S> | NullIfOptional<R>> {
readonly title: string;

@@ -39,18 +37,6 @@ readonly description: string;

private coerce;
validate(unsafeValue?: unknown): Readonly<{
[K in keyof S]: SchemaType<S[K]>;
}> | NullIfOptional<R> | Invalid;
/**
* Like `validate()` method but works on a Partial value.
* e.g. Missing properties in the object don't cause Invalid to be thrown.
*
* - Recursive! Nested ObjectSchema instances are also partially validated.
* - Props that don't appear in `options.props` are silently removed.
*
* @returns The valid partial value, or an Invalid summarising the issues.
*/
partialValidate(unsafeValue: unknown): Readonly<Partial<{
[K in keyof S]: Partial<SchemaType<S[K]>>;
}>> | NullIfOptional<R> | Invalid;
schema<K extends keyof S & string>(key: K): S[K];
validate(unsafeValue: unknown, flags: {
partial: true;
} & ObjectFlags): DeepPartial<SchemasType<S>> | NullIfOptional<R> | Invalid;
validate(unsafeValue?: unknown, flags?: ObjectFlags): SchemasType<S> | NullIfOptional<R> | Invalid;
}

@@ -57,0 +43,0 @@ /** Shortcuts for ObjectSchema. */

"use strict";
/* eslint-disable no-dupe-class-members */
Object.defineProperty(exports, "__esModule", { value: true });
const Invalid_1 = require("../Invalid");
// Whether we're in 'partial' mode or not.
let partial = false;
/**

@@ -28,3 +27,3 @@ * Schema that defines a valid object.

}
validate(unsafeValue = this.value) {
validate(unsafeValue = this.value, flags = {}) {
// Coorce.

@@ -48,3 +47,3 @@ const unsafeObj = this.coerce(unsafeValue);

const invalids = {};
if (partial) {
if (flags.partial) {
Object.entries(unsafeObj).forEach(([key, unsafeProp]) => {

@@ -54,3 +53,3 @@ if (key in this.props) {

const schema = this.props[key];
const safeProp = schema.validate(unsafeProp);
const safeProp = schema.validate(unsafeProp, flags);
if (safeProp instanceof Invalid_1.Invalid) {

@@ -76,3 +75,3 @@ invalid = true;

const unsafeProp = unsafeObj[key];
const safeProp = schema.validate(unsafeProp);
const safeProp = schema.validate(unsafeProp, flags);
if (safeProp instanceof Invalid_1.Invalid) {

@@ -98,27 +97,2 @@ invalid = true;

}
/**
* Like `validate()` method but works on a Partial value.
* e.g. Missing properties in the object don't cause Invalid to be thrown.
*
* - Recursive! Nested ObjectSchema instances are also partially validated.
* - Props that don't appear in `options.props` are silently removed.
*
* @returns The valid partial value, or an Invalid summarising the issues.
*/
partialValidate(unsafeValue) {
try {
partial = true;
const value = this.validate(unsafeValue);
partial = false;
return value;
}
catch (err) {
partial = false;
throw err;
}
}
// Implement SchemasSchema
schema(key) {
return this.props[key];
}
}

@@ -125,0 +99,0 @@ exports.ObjectSchema = ObjectSchema;

@@ -1,2 +0,3 @@

import { Schema, SchemaOptions, NullIfOptional } from "../types";
import type { Schema, SchemaOptions } from "../Schema";
import type { NullIfOptional } from "../types";
import { Invalid } from "../Invalid";

@@ -3,0 +4,0 @@ interface PhoneOptions<R extends boolean = false> extends SchemaOptions {

@@ -1,2 +0,3 @@

import { Schema, SchemaOptions, EmptyIfOptional } from "../types";
import type { Schema, SchemaOptions } from "../Schema";
import type { EmptyIfOptional } from "../types";
import { Invalid } from "../Invalid";

@@ -3,0 +4,0 @@ interface StringOptions<T extends string = string, R extends boolean = false> extends SchemaOptions {

@@ -1,2 +0,3 @@

import { Schema, SchemaOptions, NullIfOptional } from "../types";
import type { NullIfOptional } from "../types";
import type { Schema, SchemaOptions } from "../Schema";
import { Invalid } from "../Invalid";

@@ -3,0 +4,0 @@ interface UrlOptions<R extends boolean = false> extends SchemaOptions {

{
"name": "schemaglobin",
"description": "Validate user-entered data.",
"version": "3.3.7",
"version": "4.0.0",
"repository": "https://github.com/dhoulb/schemaglobin",

@@ -17,7 +17,7 @@ "author": "Dave Houlbrooke <dave@shax.com>",

"fix": "npm run fix:prettier && npm run fix:eslint",
"fix:prettier": "prettier --write \"./**/*\"",
"fix:eslint": "eslint --fix \"./**/*\"",
"fix:prettier": "prettier --write './**/*.{md,json}'",
"fix:eslint": "eslint --fix './**/*.{ts,tsx}'",
"test": "npm run test:prettier && npm run test:eslint && npm run test:typescript && npm run test:jest",
"test:prettier": "prettier --check \"./**/*\"",
"test:eslint": "eslint \"./**/*\"",
"test:prettier": "prettier --check './**/*.{md,json}'",
"test:eslint": "eslint './**/*.{ts,tsx}'",
"test:typescript": "tsc --noEmit",

@@ -30,13 +30,13 @@ "test:jest": "jest",

"@types/jest": "^25.1.1",
"@typescript-eslint/eslint-plugin": "^2.22.0",
"@typescript-eslint/parser": "^2.22.0",
"eslint": "^6.7.1",
"eslint-config-prettier": "^6.10.0",
"@typescript-eslint/eslint-plugin": "^2.32.0",
"@typescript-eslint/parser": "^2.32.0",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-import": "^2.20.1",
"eslint-plugin-prettier": "^3.1.1",
"jest": "^25.1.0",
"prettier": "^1.19.1",
"ts-jest": "^25.0.0",
"jest": "^25.5.4",
"prettier": "^2.0.5",
"ts-jest": "^25.5.1",
"typescript": "^3.8.3"
}
}

@@ -233,4 +233,3 @@ # Schemaglobin: Validate unknown user input against schemas

- `ObjectSchema.validate()`
- Normally returns `{}`
- If `options.props` is set it can return a more specific type, e.g.`{ a: string, b: number }`
- If `flags.partial` is set it returns a deep partial of the object (i.e. all props become optional).

@@ -289,2 +288,25 @@ ```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

@@ -456,6 +478,5 @@

`ObjectSchema` instances also provide the following methods:
`validate()` on `ObjectSchema` instances supports the following flags:
- `partialValidate(value: Partial<T>)` - Validate a _partial_ object where some properties are missing (normal `validate()` would return `Invalid` if required properties were missing).
- `schema(key: string)` - Get the subschema from `options.props` that corresponds to `key`
- `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).

@@ -462,0 +483,0 @@ ### `array()`

// Export all types.
export * from "./types";
export { NullIfOptional, FalseIfOptional, EmptyIfOptional, DeepPartial, UnknownObject } from "./types";
export { SchemaOptions, ValidateFlags, Schema, SchemaType, Schemas, SchemasType } from "./Schema";

@@ -19,1 +20,4 @@ // Export all schemas.

export * from "./Invalid";
// Export helpers.
export * from "./helpers";

@@ -1,2 +0,2 @@

import { Schema, SchemaWithSchemas, SchemaOptions, SchemaType } from "../types";
import { Schema, SchemaOptions, SchemaType, ValidateFlags } from "../Schema";
import { Invalid } from "../Invalid";

@@ -41,3 +41,3 @@

export class ArraySchema<S extends Schema = Schema, R extends boolean = false>
implements SchemaWithSchemas<ReadonlyArray<SchemaType<S>>> {
implements Schema<ReadonlyArray<SchemaType<S>>> {
readonly title: string;

@@ -49,11 +49,7 @@ readonly description: string;

/**
* Describe the minimum and maximum numbers of items.
*/
/** Describe the minimum and maximum numbers of items. */
readonly min: number | null = null;
readonly max: number | null = null;
/**
* Describe the format for _all_ items in the array.
*/
/** Describe the format for _all_ items in the array. */
readonly items: S;

@@ -81,7 +77,2 @@

// Implement SchemasSchema
schema(): S {
return this.items;
}
private coerce(value: unknown): unknown[] | Invalid {

@@ -93,3 +84,3 @@ if (!value) return []; // Convert falsy to empty array.

validate(unsafeValue: unknown = this.value): ReadonlyArray<SchemaType<S>> | Invalid {
validate(unsafeValue: unknown = this.value, flags: ValidateFlags = {}): ReadonlyArray<SchemaType<S>> | Invalid {
// Coorce.

@@ -125,3 +116,3 @@ const unsafeArray = this.coerce(unsafeValue);

const current = unsafeArray[i];
const value = items.validate(current);
const value = items.validate(current, flags);
if (value instanceof Invalid) {

@@ -128,0 +119,0 @@ invalid = true;

@@ -1,2 +0,3 @@

import { Schema, SchemaOptions, FalseIfOptional } from "../types";
import type { Schema, SchemaOptions } from "../Schema";
import type { FalseIfOptional } from "../types";
import { Invalid } from "../Invalid";

@@ -3,0 +4,0 @@

@@ -1,2 +0,3 @@

import { Schema, SchemaOptions, NullIfOptional } from "../types";
import type { Schema, SchemaOptions } from "../Schema";
import type { NullIfOptional } from "../types";
import { Invalid } from "../Invalid";

@@ -3,0 +4,0 @@

@@ -1,2 +0,3 @@

import { Schema, SchemaOptions, NullIfOptional } from "../types";
import type { Schema, SchemaOptions } from "../Schema";
import type { NullIfOptional } from "../types";
import { Invalid } from "../Invalid";

@@ -3,0 +4,0 @@

@@ -1,2 +0,3 @@

import { Schema, SchemaOptions, NullIfOptional } from "../types";
import type { Schema, SchemaOptions } from "../Schema";
import type { NullIfOptional } from "../types";
import { Invalid } from "../Invalid";

@@ -3,0 +4,0 @@

@@ -1,2 +0,2 @@

import { Schema, SchemaWithSchemas, SchemaOptions, SchemaType } from "../types";
import type { Schema, SchemaOptions, SchemaType, ValidateFlags } from "../Schema";
import { Invalid } from "../Invalid";

@@ -18,3 +18,3 @@

export class MapSchema<S extends Schema = Schema, R extends boolean = false>
implements SchemaWithSchemas<Readonly<Record<string, SchemaType<S>>>> {
implements Schema<Readonly<Record<string, SchemaType<S>>>> {
readonly title: string;

@@ -59,7 +59,2 @@ readonly description: string;

// Implement SchemasSchema
schema(): S {
return this.items;
}
private coerce(value: unknown): Record<string, unknown> | Invalid {

@@ -71,3 +66,6 @@ if (!value) return {}; // Convert falsy to empty object.

validate(unsafeValue: unknown = this.value): Readonly<Record<string, SchemaType<S>>> | Invalid {
validate(
unsafeValue: unknown = this.value,
flags: ValidateFlags = {},
): Readonly<Record<string, SchemaType<S>>> | Invalid {
// Coorce.

@@ -101,3 +99,3 @@ const unsafeObject = this.coerce(unsafeValue);

// Validate the value.
const value = this.items.validate(current);
const value = this.items.validate(current, flags);
if (value instanceof Invalid) {

@@ -104,0 +102,0 @@ invalid = true;

@@ -1,2 +0,3 @@

import { Schema, SchemaOptions, NullIfOptional } from "../types";
import type { Schema, SchemaOptions } from "../Schema";
import type { NullIfOptional } from "../types";
import { Invalid } from "../Invalid";

@@ -3,0 +4,0 @@

@@ -1,9 +0,9 @@

import { Schema, SchemaWithSchemas, SchemaOptions, SchemaType, NullIfOptional } from "../types";
/* eslint-disable no-dupe-class-members */
import type { Schema, SchemaType, Schemas, SchemasType, SchemaOptions, ValidateFlags } from "../Schema";
import type { NullIfOptional, DeepPartial, UnknownObject } from "../types";
import { Invalid } from "../Invalid";
// Object with only string keys and unknown values.
type UnknownObject = { [key: string]: unknown };
// Options.
interface ObjectOptions<S extends { [prop: string]: Schema } = {}, R extends boolean = false> extends SchemaOptions {
interface ObjectOptions<S extends Schemas = Schemas, R extends boolean = false> extends SchemaOptions {
readonly props: S;

@@ -14,4 +14,6 @@ readonly value?: Partial<{ [K in keyof S]: SchemaType<S[K]> }> | NullIfOptional<R>;

// Whether we're in 'partial' mode or not.
let partial = false;
// Flags.
interface ObjectFlags extends ValidateFlags {
partial?: boolean;
}

@@ -24,4 +26,4 @@ /**

*/
export class ObjectSchema<S extends { [prop: string]: Schema } = {}, R extends boolean = false>
implements SchemaWithSchemas<Readonly<{ [K in keyof S]: SchemaType<S[K]> }> | NullIfOptional<R>> {
export class ObjectSchema<S extends Schemas = Schemas, R extends boolean = false>
implements Schema<SchemasType<S> | NullIfOptional<R>> {
readonly title: string;

@@ -62,4 +64,10 @@ readonly description: string;

validate(
unsafeValue: unknown,
flags: { partial: true } & ObjectFlags,
): DeepPartial<SchemasType<S>> | NullIfOptional<R> | Invalid;
validate(unsafeValue?: unknown, flags?: ObjectFlags): SchemasType<S> | NullIfOptional<R> | Invalid;
validate(
unsafeValue: unknown = this.value,
): Readonly<{ [K in keyof S]: SchemaType<S[K]> }> | NullIfOptional<R> | Invalid {
flags: ObjectFlags = {},
): DeepPartial<SchemasType<S>> | SchemasType<S> | NullIfOptional<R> | Invalid {
// Coorce.

@@ -84,3 +92,3 @@ const unsafeObj = this.coerce(unsafeValue);

const invalids: { [key: string]: string } = {};
if (partial) {
if (flags.partial) {
Object.entries(unsafeObj).forEach(([key, unsafeProp]) => {

@@ -90,3 +98,3 @@ if (key in this.props) {

const schema = this.props[key];
const safeProp = schema.validate(unsafeProp);
const safeProp = schema.validate(unsafeProp, flags);
if (safeProp instanceof Invalid) {

@@ -108,3 +116,3 @@ invalid = true;

const unsafeProp = unsafeObj[key];
const safeProp = schema.validate(unsafeProp);
const safeProp = schema.validate(unsafeProp, flags);
if (safeProp instanceof Invalid) {

@@ -127,32 +135,4 @@ invalid = true;

// Return immuatably (return output if changes were made, or exact input otherwise).
return (changed ? safeObj : unsafeObj) as { [K in keyof S]: SchemaType<S[K]> };
return (changed ? safeObj : unsafeObj) as DeepPartial<SchemasType<S>> | SchemasType<S>;
}
/**
* Like `validate()` method but works on a Partial value.
* e.g. Missing properties in the object don't cause Invalid to be thrown.
*
* - Recursive! Nested ObjectSchema instances are also partially validated.
* - Props that don't appear in `options.props` are silently removed.
*
* @returns The valid partial value, or an Invalid summarising the issues.
*/
partialValidate(
unsafeValue: unknown,
): Readonly<Partial<{ [K in keyof S]: Partial<SchemaType<S[K]>> }>> | NullIfOptional<R> | Invalid {
try {
partial = true;
const value = this.validate(unsafeValue);
partial = false;
return value;
} catch (err) {
partial = false;
throw err;
}
}
// Implement SchemasSchema
schema<K extends keyof S & string>(key: K): S[K] {
return this.props[key];
}
}

@@ -159,0 +139,0 @@

@@ -1,2 +0,3 @@

import { Schema, SchemaOptions, NullIfOptional } from "../types";
import type { Schema, SchemaOptions } from "../Schema";
import type { NullIfOptional } from "../types";
import { Invalid } from "../Invalid";

@@ -3,0 +4,0 @@

/* eslint-disable no-control-regex */
import { Schema, SchemaOptions, EmptyIfOptional } from "../types";
import type { Schema, SchemaOptions } from "../Schema";
import type { EmptyIfOptional } from "../types";
import { Invalid } from "../Invalid";

@@ -5,0 +6,0 @@

@@ -1,2 +0,3 @@

import { Schema, SchemaOptions, NullIfOptional } from "../types";
import type { NullIfOptional } from "../types";
import type { Schema, SchemaOptions } from "../Schema";
import { Invalid } from "../Invalid";

@@ -3,0 +4,0 @@

@@ -8,5 +8,4 @@ import {

ObjectSchema,
NullIfOptional,
Invalid,
SchemaType,
DeepPartial,
} from "../../src";

@@ -16,3 +15,5 @@

describe("ObjectSchema", () => {
test("TypeScript", () => {
const PARTIAL = { partial: true } as const;
test("TypeScript (no partial flag)", () => {
const s1: ObjectSchema<{ num: NumberSchema<number, false> }, false> = object.optional({

@@ -23,6 +24,4 @@ num: new NumberSchema({ required: false }),

const r1: { num: number | null } | null | Invalid = s1.validate();
const ss1a: NumberSchema<number, false> = s1.schema("num");
const sr1a: number | null | Invalid = ss1a.validate();
const ss1b: NumberSchema<number, false> = s1.props.num;
const sr1b: number | null | Invalid = ss1b.validate();
const ss1: NumberSchema<number, false> = s1.props.num;
const sr1: number | null | Invalid = ss1.validate();
const s2: ObjectSchema<{ num: NumberSchema<number, true> }, true> = object.required({

@@ -33,6 +32,4 @@ num: new NumberSchema({ required: true }),

const r2: { num: number } | Invalid = s2.validate();
const ss2a: NumberSchema<number, true> = s2.schema("num");
const sr2a: number | Invalid = ss2a.validate();
const ss2b: NumberSchema<number, true> = s2.props.num;
const sr2b: number | Invalid = ss2b.validate();
const ss2: NumberSchema<number, true> = s2.props.num;
const sr2: number | Invalid = ss2.validate();
const s3: ObjectSchema<{ num: NumberSchema<number, true> }, true> = object({

@@ -42,3 +39,3 @@ props: { num: number.required },

});
const v3: Record<string, number> | Invalid = s3.validate();
const v3: { num: number } | Invalid = s3.validate();
const s4: ObjectSchema<{ num: NumberSchema<number, true> }, false> = object({

@@ -48,11 +45,11 @@ props: { num: number.required },

});
const v4: Record<string, number> | null | Invalid = s4.validate();
const v4: { num: number } | null | Invalid = s4.validate();
const s5: ObjectSchema<{ num: NumberSchema<number, true> }, false> = object({
props: { num: number.required },
});
const v5: Record<string, number> | null | Invalid = s5.validate();
const v5: { num: number } | null | Invalid = s5.validate();
const s6: ObjectSchema<{ num: NumberSchema<number, true> }, false> = new ObjectSchema({
props: { num: number.required },
});
const v6: Record<string, number> | null | Invalid = s6.validate();
const v6: { num: number } | null | Invalid = s6.validate();
const s7: ObjectSchema<{ num: NumberSchema<number, true> }, false> = new ObjectSchema({

@@ -62,3 +59,3 @@ props: { num: number.required },

});
const v7: Record<string, number> | null | Invalid = s7.validate();
const v7: { num: number } | null | Invalid = s7.validate();
const s8: ObjectSchema<{ num: NumberSchema<number, true> }, true> = new ObjectSchema({

@@ -68,4 +65,42 @@ props: { num: number.required },

});
const v8: Record<string, number> | null | Invalid = s8.validate();
const v8: { num: number } | null | Invalid = s8.validate();
});
test("TypeScript (partial flag)", () => {
const s1: ObjectSchema<{ num: NumberSchema<number, false> }, false> = object.optional({
num: new NumberSchema({ required: false }),
});
const r1: { num?: number | null } | null | Invalid = s1.validate({}, PARTIAL);
const s2: ObjectSchema<{ num: NumberSchema<number, true> }, true> = object.required({
num: new NumberSchema({ required: true }),
});
const r2: { num?: number } | Invalid = s2.validate({}, PARTIAL);
const s3: ObjectSchema<{ num: NumberSchema<number, true> }, true> = object({
props: { num: number.required },
required: true,
});
const v3: { num?: number } | Invalid = s3.validate({}, PARTIAL);
const s4: ObjectSchema<{ num: NumberSchema<number, true> }, false> = object({
props: { num: number.required },
required: false,
});
const v4: { num?: number } | null | Invalid = s4.validate({}, PARTIAL);
const s5: ObjectSchema<{ num: NumberSchema<number, true> }, false> = object({
props: { num: number.required },
});
const v5: { num?: number } | null | Invalid = s5.validate({}, PARTIAL);
const s6: ObjectSchema<{ num: NumberSchema<number, true> }, false> = new ObjectSchema({
props: { num: number.required },
});
const v6: { num?: number } | null | Invalid = s6.validate({}, PARTIAL);
const s7: ObjectSchema<{ num: NumberSchema<number, true> }, false> = new ObjectSchema({
props: { num: number.required },
required: false,
});
const v7: DeepPartial<{ num: number }> | null | Invalid = s7.validate({}, PARTIAL);
const s8: ObjectSchema<{ num: NumberSchema<number, true> }, true> = new ObjectSchema({
props: { num: number.required },
required: true,
});
const v8: { num?: number } | null | Invalid = s8.validate({}, PARTIAL);
});
test("Constructs correctly", () => {

@@ -86,3 +121,3 @@ const props = {};

});
describe("validate()", () => {
describe("validate() (no partial flag)", () => {
test("Non-objects throw error", () => {

@@ -215,34 +250,33 @@ const schema = object({ props: {} });

});
describe("partialValidate()", () => {
test("Non-objects throw error", () => {
describe("validate() (partial flag)", () => {
test("Partial non-objects throw error", () => {
const schema = object({ props: {} });
expect(schema.partialValidate("abc")).toEqual(new Invalid("Must be object"));
expect(schema.partialValidate(123)).toEqual(new Invalid("Must be object"));
expect(schema.partialValidate(true)).toEqual(new Invalid("Must be object"));
expect(schema.validate("abc", PARTIAL)).toEqual(new Invalid("Must be object"));
expect(schema.validate(123, PARTIAL)).toEqual(new Invalid("Must be object"));
expect(schema.validate(true, PARTIAL)).toEqual(new Invalid("Must be object"));
});
test("Falsy values return null", () => {
test("Partial falsy values return null", () => {
const schema = object({ props: {} });
expect(schema.partialValidate(0)).toBe(null);
expect(schema.partialValidate(null)).toBe(null);
expect(schema.partialValidate(false)).toBe(null);
expect(schema.validate(0, PARTIAL)).toBe(null);
expect(schema.validate(null, PARTIAL)).toBe(null);
expect(schema.validate(false, PARTIAL)).toBe(null);
});
describe("options.required", () => {
test("Required null objects return Required", () => {
test("Partial required null objects return Required", () => {
const schema = object({ props: {}, required: true });
expect(schema.partialValidate(null)).toEqual(new Invalid("Required"));
expect(schema.validate(null, PARTIAL)).toEqual(new Invalid("Required"));
});
test("Required non-null objects are not invalid", () => {
test("Partial required non-null objects are not invalid", () => {
const schema = object({ props: {}, required: true });
const obj = {};
expect(schema.partialValidate(obj)).toBe(obj);
expect(schema.validate(obj, PARTIAL)).toBe(obj);
});
test("Non-required empty objects do not return Required", () => {
test("Partial non-required empty objects do not return Required", () => {
const schema = object({ props: {}, required: false });
const obj = {};
expect(schema.partialValidate(obj)).toBe(obj);
expect(schema.validate(obj, PARTIAL)).toBe(obj);
});
});
describe("options.props", () => {
test("Object with no missing props that validates is returned unchanged", () => {
test("Partial object with no missing props that validates is returned unchanged", () => {
const a = { num: 123, str: "abc", bool: true };

@@ -256,5 +290,5 @@ const schema = object({

});
expect(schema.partialValidate(a)).toBe(a);
expect(schema.validate(a, PARTIAL)).toBe(a);
});
test("Object with missing props that validates is returned unchanged", () => {
test("Partial object with missing props that validates is returned unchanged", () => {
const a = { num: 123 };

@@ -268,5 +302,5 @@ const schema = object({

});
expect(schema.partialValidate(a)).toBe(a);
expect(schema.validate(a, PARTIAL)).toBe(a);
});
test("Object with props and fixable schema is fixed", () => {
test("Partial object with props and fixable schema is fixed", () => {
const schema = object({

@@ -279,5 +313,5 @@ props: {

});
expect(schema.partialValidate({ num: "123", str: 123 })).toEqual({ num: 123, str: "123" });
expect(schema.validate({ num: "123", str: 123 }, PARTIAL)).toEqual({ num: 123, str: "123" });
});
test("Object with props has unknown fields stripped", () => {
test("Partial object with props has unknown fields stripped", () => {
const schema = object({

@@ -291,7 +325,10 @@ props: {

expect(
schema.partialValidate({
num: 123,
str: "abcdef",
excess: "should be removed",
}),
schema.validate(
{
num: 123,
str: "abcdef",
excess: "should be removed",
},
PARTIAL,
),
).toEqual({

@@ -303,3 +340,3 @@ num: 123,

});
test("Deeply nested objects are also partially validated", () => {
test("Partial deeply nested objects are also partially validated", () => {
const schema = object({

@@ -320,10 +357,13 @@ props: {

expect(
schema.partialValidate({
num: 123,
str: "abcdef",
obj: {
schema.validate(
{
num: 123,
str: "abcdef",
obj: {
num: 123,
str: "abcdef",
},
},
}),
PARTIAL,
),
).toEqual({

@@ -340,3 +380,3 @@ num: 123,

});
test("Objects with unfixable errors in subschemas returns Invalids", () => {
test("Partial objects with unfixable errors in subschemas returns Invalids", () => {
const schema = object({

@@ -349,3 +389,3 @@ props: {

});
const invalid = schema.partialValidate({ dogs: "abc", cats: false });
const invalid = schema.validate({ dogs: "abc", cats: false }, PARTIAL);
expect(invalid).toBeInstanceOf(Object);

@@ -352,0 +392,0 @@ if (invalid instanceof Invalid && invalid.messages) {

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc