schemaglobin
Advanced tools
Comparing version 5.7.0 to 5.8.0
import type { Schema, SchemaOptions } from "../Schema"; | ||
import type { FalseIfOptional } from "../types"; | ||
import { Invalid } from "../helpers/message"; | ||
/** Coerce an unknown value to a boolean. */ | ||
export declare function coerceBoolean(value: unknown): boolean; | ||
export declare type BooleanSchemaType<R extends boolean = false> = true | FalseIfOptional<R>; | ||
export declare type BooleanSchemaType<R extends boolean = false> = true | (R extends true ? never : false); | ||
export interface BooleanSchemaOptions<R extends boolean> extends SchemaOptions { | ||
@@ -8,0 +7,0 @@ readonly value?: boolean; |
@@ -1,13 +0,4 @@ | ||
import type { NullIfOptional } from "../types"; | ||
import type { Schema, SchemaOptions } from "../Schema"; | ||
import { Invalid } from "../helpers/message"; | ||
/** Coerce an unknown value to a Color (if possible). */ | ||
export declare function coerceColor(value: unknown): string | null | Invalid; | ||
export declare type ColorSchemaType<R extends boolean = boolean> = string | NullIfOptional<R>; | ||
interface ColorOptions<R extends boolean = false> extends SchemaOptions { | ||
readonly value?: string | null; | ||
readonly required?: R; | ||
} | ||
import { StringOptions, StringSchema } from "./StringSchema"; | ||
/** | ||
* Schema that defines a valid Color. | ||
* Type of `StringSchema` that defines a valid Color. | ||
* | ||
@@ -20,20 +11,15 @@ * Ensures value is a string, enforces that the string is a valid Color. | ||
*/ | ||
export declare class ColorSchema<R extends boolean = false> implements Schema<ColorSchemaType<R>> { | ||
readonly title: string; | ||
readonly description: string; | ||
readonly placeholder: string; | ||
readonly value: string | null; | ||
readonly required: R; | ||
export declare class ColorSchema<T extends string = string, R extends boolean = false> extends StringSchema<T, R> { | ||
readonly multiline = false; | ||
readonly max = 7; | ||
constructor({ title, description, placeholder, value, required }?: ColorOptions<R>); | ||
validate(unsafeValue?: unknown): ColorSchemaType<R> | Invalid; | ||
readonly match: RegExp; | ||
clean(str: string): string; | ||
} | ||
/** Shortcuts for ColorSchema. */ | ||
export declare const color: { | ||
(options: ColorOptions<false>): ColorSchema<false>; | ||
(options: ColorOptions<true>): ColorSchema<true>; | ||
(): ColorSchema<false>; | ||
required: ColorSchema<true>; | ||
optional: ColorSchema<false>; | ||
<T extends string>(options: StringOptions<T, false>): ColorSchema<T, false>; | ||
<T extends string>(options: StringOptions<T, true>): ColorSchema<T, true>; | ||
(): ColorSchema<string, false>; | ||
required: ColorSchema<string, true>; | ||
optional: ColorSchema<string, false>; | ||
}; | ||
export {}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.color = exports.ColorSchema = exports.coerceColor = void 0; | ||
const message_1 = require("../helpers/message"); | ||
exports.color = exports.ColorSchema = void 0; | ||
const StringSchema_1 = require("./StringSchema"); | ||
const R_COLOR = /^#[0-9A-F]{6}$/; | ||
@@ -10,17 +10,8 @@ /** | ||
*/ | ||
function cleanColor(value) { | ||
const cleanColor = (value) => { | ||
const digits = value.toUpperCase().replace(/[^0-9A-F]/g, ""); | ||
return digits ? `#${digits.slice(0, 6)}` : ""; | ||
} | ||
/** Coerce an unknown value to a Color (if possible). */ | ||
function coerceColor(value) { | ||
if (!value) | ||
return null; // Convert falsy to null. | ||
if (typeof value === "string") | ||
return cleanColor(value) || null; | ||
return new message_1.Invalid("Must be string or null"); | ||
} | ||
exports.coerceColor = coerceColor; | ||
}; | ||
/** | ||
* Schema that defines a valid Color. | ||
* Type of `StringSchema` that defines a valid Color. | ||
* | ||
@@ -33,30 +24,11 @@ * Ensures value is a string, enforces that the string is a valid Color. | ||
*/ | ||
class ColorSchema { | ||
constructor({ title = "", description = "", placeholder = "", value = null, required = false } = {}) { | ||
class ColorSchema extends StringSchema_1.StringSchema { | ||
constructor() { | ||
super(...arguments); | ||
this.multiline = false; | ||
this.max = 7; | ||
this.title = title; | ||
this.description = description; | ||
this.placeholder = placeholder; | ||
this.value = value; | ||
this.required = required; | ||
this.match = R_COLOR; | ||
} | ||
validate(unsafeValue = this.value) { | ||
// Coorce. | ||
const value = coerceColor(unsafeValue); | ||
if (value instanceof message_1.Invalid) | ||
return value; | ||
// Null means 'no color' | ||
if (value === null) { | ||
// Check requiredness. | ||
if (this.required) | ||
return new message_1.Required("Required"); | ||
// Return null. | ||
// We know this type assertion is sound because `null` can never be returned if `this.required == true`. | ||
return null; | ||
} | ||
// Check format. | ||
if (!R_COLOR.test(value)) | ||
return new message_1.Invalid("Invalid color (must be a hexadecimal color)"); | ||
// Return the normalised Color. | ||
return value; | ||
clean(str) { | ||
return cleanColor(super.clean(str)); | ||
} | ||
@@ -63,0 +35,0 @@ } |
import type { Schema, SchemaOptions } from "../Schema"; | ||
import type { NullIfOptional } from "../types"; | ||
import { Invalid } from "../helpers/message"; | ||
export declare type DateSchemaType<R extends boolean = false> = string | NullIfOptional<R>; | ||
export declare type DateSchemaType<R extends boolean = false> = string | (R extends true ? never : null); | ||
/** Convert an unknown value to a date string (or return Invalid) */ | ||
@@ -16,4 +15,4 @@ export declare function coerceDate<T extends unknown>(value: T): Date | null | Invalid; | ||
* Schema that defines a valid date in string YMD format, e.g. `2019-10-04` | ||
* `Date` instances, numbers, strings, are automatically converted to YMD strings. | ||
* `null` is also a valid value if this field is not required. | ||
* - `Date` instances, numbers, strings, are automatically converted to YMD strings. | ||
* - `null` is also a valid value if this field is not required. | ||
*/ | ||
@@ -20,0 +19,0 @@ export declare class DateSchema<R extends boolean = false> implements Schema<DateSchemaType<R>> { |
@@ -25,4 +25,4 @@ "use strict"; | ||
* Schema that defines a valid date in string YMD format, e.g. `2019-10-04` | ||
* `Date` instances, numbers, strings, are automatically converted to YMD strings. | ||
* `null` is also a valid value if this field is not required. | ||
* - `Date` instances, numbers, strings, are automatically converted to YMD strings. | ||
* - `null` is also a valid value if this field is not required. | ||
*/ | ||
@@ -29,0 +29,0 @@ class DateSchema { |
import { Invalid } from "../helpers/message"; | ||
import { SchemaOptions, Schema } from "../Schema"; | ||
import { NullIfOptional } from "../types"; | ||
import { DistanceUnit } from "../helpers/distance"; | ||
export declare type DistanceSchemaType<R extends boolean = false> = number | NullIfOptional<R>; | ||
export declare type DistanceSchemaType<R extends boolean = false> = number | (R extends true ? never : null); | ||
export interface DistanceOptions<R extends boolean = false> extends SchemaOptions { | ||
@@ -31,3 +30,3 @@ readonly unit?: DistanceUnit; | ||
constructor({ title, description, placeholder, value, required, min, max, step, unit, }: DistanceOptions<R>); | ||
validate(unsafeValue?: unknown): number | NullIfOptional<R> | Invalid; | ||
validate(unsafeValue?: unknown): DistanceSchemaType<R> | Invalid; | ||
} | ||
@@ -34,0 +33,0 @@ /** Shortcuts for DistanceSchema. */ |
@@ -1,14 +0,5 @@ | ||
import type { Schema, SchemaOptions } from "../Schema"; | ||
import type { NullIfOptional } from "../types"; | ||
import { Invalid } from "../helpers/message"; | ||
/** Coerce an unknown value to an email (if possible). */ | ||
export declare function coerceEmail(value: unknown): string | null | Invalid; | ||
export declare type EmailSchemaType<R extends boolean = false> = string | NullIfOptional<R>; | ||
export interface EmailOptions<R extends boolean = false> extends SchemaOptions { | ||
readonly value?: string | null; | ||
readonly required?: R; | ||
} | ||
import { StringOptions, StringSchema } from "./StringSchema"; | ||
/** | ||
* Schema that defines a valid email address. | ||
* | ||
* Type of `StringSchema` that defines a valid email address. | ||
* - Falsy values are converted to `""` empty string. | ||
* - Total length must be 254 characters or fewer (in SMTP email is encoded with `<` and `>` to make 256 characters). | ||
@@ -26,23 +17,16 @@ * - No minimum length is enforced because the email's format is enforced instead. | ||
* - TLD is a segment of 2-63 characters, possibly in `xn--` international format. | ||
* | ||
* `null` is also a valid value if this field is not required. | ||
* Falsy values and empty strings are converted to `null` | ||
*/ | ||
export declare class EmailSchema<R extends boolean = false> implements Schema<EmailSchemaType<R>> { | ||
readonly title: string; | ||
readonly description: string; | ||
readonly placeholder: string; | ||
readonly value: string | null; | ||
readonly required: R; | ||
readonly max: number; | ||
constructor({ title, description, placeholder, value, required }?: EmailOptions<R>); | ||
validate(unsafeValue?: unknown): EmailSchemaType<R> | Invalid; | ||
export declare class EmailSchema<T extends string = string, R extends boolean = boolean> extends StringSchema<T, R> { | ||
readonly max = 254; | ||
readonly match: RegExp; | ||
readonly multiline = false; | ||
clean(str: string): string; | ||
} | ||
/** Shortcuts for EmailSchema. */ | ||
export declare const email: { | ||
(options: EmailOptions<false>): EmailSchema<false>; | ||
(options: EmailOptions<true>): EmailSchema<true>; | ||
(): EmailSchema<false>; | ||
required: EmailSchema<true>; | ||
optional: EmailSchema<false>; | ||
<T extends string>(options: StringOptions<T, false>): EmailSchema<T, false>; | ||
<T extends string>(options: StringOptions<T, true>): EmailSchema<T, true>; | ||
(): EmailSchema<string, false>; | ||
required: EmailSchema<string, true>; | ||
optional: EmailSchema<string, false>; | ||
}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.email = exports.EmailSchema = exports.coerceEmail = void 0; | ||
const message_1 = require("../helpers/message"); | ||
/** Coerce an unknown value to an email (if possible). */ | ||
function coerceEmail(value) { | ||
if (!value) | ||
return null; // Convert falsy to null. | ||
if (typeof value === "string") | ||
return value.trim().toLowerCase() || null; | ||
return new message_1.Invalid("Must be string or null"); | ||
} | ||
exports.coerceEmail = coerceEmail; | ||
exports.email = exports.EmailSchema = void 0; | ||
const StringSchema_1 = require("./StringSchema"); | ||
// RegExps. | ||
const R_EMAIL = /^[a-z0-9](?:[a-zA-Z0-9._+-]{0,62}[a-zA-Z0-9])?@(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.){1,3}(?:[a-z]{2,63}|xn--[a-z0-9-]{0,58}[a-z0-9])$/; | ||
/** | ||
* Schema that defines a valid email address. | ||
* | ||
* Type of `StringSchema` that defines a valid email address. | ||
* - Falsy values are converted to `""` empty string. | ||
* - Total length must be 254 characters or fewer (in SMTP email is encoded with `<` and `>` to make 256 characters). | ||
@@ -31,37 +22,12 @@ * - No minimum length is enforced because the email's format is enforced instead. | ||
* - TLD is a segment of 2-63 characters, possibly in `xn--` international format. | ||
* | ||
* `null` is also a valid value if this field is not required. | ||
* Falsy values and empty strings are converted to `null` | ||
*/ | ||
class EmailSchema { | ||
constructor({ title = "", description = "", placeholder = "", value = null, required = false } = {}) { | ||
this.max = 254; // Can't be changed or it wouldn't be a valid email address. | ||
this.title = title; | ||
this.description = description; | ||
this.placeholder = placeholder; | ||
this.value = value; | ||
this.required = required; | ||
class EmailSchema extends StringSchema_1.StringSchema { | ||
constructor() { | ||
super(...arguments); | ||
this.max = 254; | ||
this.match = R_EMAIL; | ||
this.multiline = false; | ||
} | ||
validate(unsafeValue = this.value) { | ||
// Coorce. | ||
const value = coerceEmail(unsafeValue); | ||
if (value instanceof message_1.Invalid) | ||
return value; | ||
// Null means 'no email' | ||
if (!value) { | ||
// Check requiredness. | ||
if (this.required) | ||
return new message_1.Required("Required"); | ||
// Return null. | ||
// We know this type assertion is sound because `null` can never be returned if `this.required == true`. | ||
return null; | ||
} | ||
// Check length. | ||
if (value.length > this.max) | ||
return new message_1.Invalid(`Maximum ${this.max} characters`); | ||
// Check format. | ||
if (!R_EMAIL.test(value)) | ||
return new message_1.Invalid("Invalid email format"); | ||
// Return email. | ||
return value; | ||
clean(str) { | ||
return super.clean(str).toLowerCase(); | ||
} | ||
@@ -68,0 +34,0 @@ } |
@@ -1,36 +0,17 @@ | ||
import type { Schema, SchemaOptions } from "../Schema"; | ||
import type { NullIfOptional } from "../types"; | ||
import { Invalid } from "../helpers/message"; | ||
/** Coerce an unknown value to a key (if possible). */ | ||
export declare function coerceKey(value: unknown): string | null | Invalid; | ||
export declare type KeySchemaType<R extends boolean = false> = string | NullIfOptional<R>; | ||
export interface KeyOptions<R extends boolean = false> extends SchemaOptions { | ||
readonly value?: string | null; | ||
readonly required?: R; | ||
readonly match?: RegExp; | ||
} | ||
import { StringOptions, StringSchema } from "./StringSchema"; | ||
/** | ||
* Schema that defines a valid database key. | ||
* Ensures value is a non-empty string key of up to `max` characters. | ||
* | ||
* `null` is also a valid value if this field is not required. | ||
* Falsy values and empty strings are converted to `null` | ||
* Type of `StringSchema` that defines a valid database key. | ||
* Ensures value is a non-empty string key matching `[a-zA-Z0-9]{1,64}` | ||
*/ | ||
export declare class KeySchema<R extends boolean = false> implements Schema<KeySchemaType<R>> { | ||
readonly title: string; | ||
readonly description: string; | ||
readonly placeholder: string; | ||
readonly value: string | null; | ||
readonly required: R; | ||
export declare class KeySchema<T extends string = string, R extends boolean = false> extends StringSchema<T, R> { | ||
readonly match: RegExp; | ||
constructor({ title, description, placeholder, value, required, match }?: KeyOptions<R>); | ||
validate(unsafeValue?: unknown): KeySchemaType<R> | Invalid; | ||
readonly multiline = false; | ||
} | ||
/** Shortcuts for KeySchema. */ | ||
export declare const key: { | ||
(options: KeyOptions<false>): KeySchema<false>; | ||
(options: KeyOptions<true>): KeySchema<true>; | ||
(): KeySchema<false>; | ||
required: KeySchema<true>; | ||
optional: KeySchema<false>; | ||
<T extends string>(options: StringOptions<T, false>): KeySchema<T, false>; | ||
<T extends string>(options: StringOptions<T, true>): KeySchema<T, true>; | ||
(): KeySchema<string, false>; | ||
required: KeySchema<string, true>; | ||
optional: KeySchema<string, false>; | ||
}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.key = exports.KeySchema = exports.coerceKey = void 0; | ||
const message_1 = require("../helpers/message"); | ||
/** Coerce an unknown value to a key (if possible). */ | ||
function coerceKey(value) { | ||
if (typeof value === "number") | ||
return value.toString(); // Zero is a valid key. | ||
if (!value) | ||
return null; // Convert falsy to null. | ||
if (typeof value === "string") | ||
return value.trim() || null; | ||
return new message_1.Invalid("Must be string or null"); | ||
} | ||
exports.coerceKey = coerceKey; | ||
exports.key = exports.KeySchema = void 0; | ||
const StringSchema_1 = require("./StringSchema"); | ||
// Default key only allows [a-zA-Z0-9] and 1-64 characters. | ||
const R_KEY = /[a-zA-Z0-9]{1,64}/; | ||
/** | ||
* Schema that defines a valid database key. | ||
* Ensures value is a non-empty string key of up to `max` characters. | ||
* | ||
* `null` is also a valid value if this field is not required. | ||
* Falsy values and empty strings are converted to `null` | ||
* Type of `StringSchema` that defines a valid database key. | ||
* Ensures value is a non-empty string key matching `[a-zA-Z0-9]{1,64}` | ||
*/ | ||
class KeySchema { | ||
constructor({ title = "", description = "", placeholder = "", value = null, required = false, match = R_KEY } = {}) { | ||
this.title = title; | ||
this.description = description; | ||
this.placeholder = placeholder; | ||
this.value = value; | ||
this.required = required; | ||
this.match = match; | ||
class KeySchema extends StringSchema_1.StringSchema { | ||
constructor() { | ||
super(...arguments); | ||
this.match = R_KEY; | ||
this.multiline = false; | ||
} | ||
validate(unsafeValue = this.value) { | ||
// Coorce. | ||
const value = coerceKey(unsafeValue); | ||
if (value instanceof message_1.Invalid) | ||
return value; | ||
// Null means 'no key' | ||
if (!value) { | ||
// Check requiredness. | ||
if (this.required) | ||
return new message_1.Required("Required"); | ||
// Return. | ||
// We know this type assertion is sound because `null` can never be returned if `this.required == true`. | ||
return null; | ||
} | ||
// Check match format RegExp. | ||
if (!this.match.test(value)) | ||
return new message_1.Invalid("Invalid key format"); | ||
// Return key. | ||
return value; | ||
} | ||
} | ||
@@ -55,0 +18,0 @@ exports.KeySchema = KeySchema; |
import type { Schema, SchemaOptions } from "../Schema"; | ||
import type { NullIfOptional } from "../types"; | ||
import { Invalid } from "../helpers/message"; | ||
/** Coerce an unknown value to a number (if possible). */ | ||
export declare function coerceNumber(value: unknown): number | null | Invalid; | ||
export declare type NumberSchemaType<T extends number = number, R extends boolean = false> = T | NullIfOptional<R>; | ||
export declare type NumberSchemaType<T extends number = number, R extends boolean = false> = T | (R extends true ? never : null); | ||
export interface NumberOptions<T extends number = number, R extends boolean = false> extends SchemaOptions { | ||
@@ -8,0 +7,0 @@ readonly value?: number | null; |
import type { Schema, Schemas, SchemasType, SchemaOptions } from "../Schema"; | ||
import type { NullIfOptional, UnknownObject } from "../types"; | ||
import type { UnknownObject } from "../types"; | ||
import { Invalid } from "../helpers/message"; | ||
/** Coerce an unknown value to an object (if possible). */ | ||
export declare function coerceObject(value: unknown): UnknownObject | null | Invalid; | ||
export declare type ObjectSchemaType<S extends Schemas = Schemas, R extends boolean = false> = Readonly<SchemasType<S>> | NullIfOptional<R>; | ||
export declare type ObjectSchemaType<S extends Schemas = Schemas, R extends boolean = false> = Readonly<SchemasType<S>> | (R extends true ? never : null); | ||
export interface ObjectSchemaOptions<S extends Schemas = Schemas, R extends boolean = false> extends SchemaOptions { | ||
readonly props: S; | ||
readonly value?: SchemasType<S> | NullIfOptional<R>; | ||
readonly value?: ObjectSchemaType<S, R>; | ||
readonly required?: R; | ||
@@ -11,0 +11,0 @@ } |
@@ -1,35 +0,19 @@ | ||
import type { Schema, SchemaOptions } from "../Schema"; | ||
import type { NullIfOptional } from "../types"; | ||
import { Invalid } from "../helpers/message"; | ||
/** Coerce an unknown value into a phone number (if possible). */ | ||
export declare function coercePhone(value: unknown): string | null | Invalid; | ||
export declare type PhoneSchemaType<R extends boolean = boolean> = string | NullIfOptional<R>; | ||
export interface PhoneOptions<R extends boolean = false> extends SchemaOptions { | ||
readonly value?: string | null; | ||
readonly required?: R; | ||
} | ||
import { StringOptions, StringSchema } from "./StringSchema"; | ||
/** | ||
* Schema that defines a valid phone number. | ||
* Multiple string formats are automatically converted to E.164 format. | ||
* | ||
* `null` is also a valid value if this field is not required. | ||
* Falsy values and empty strings are converted to `null` | ||
* Type of `StringSchema` that defines a valid phone number. | ||
* - Multiple string formats are automatically converted to E.164 format (starting with `+` plus). | ||
* - Falsy values are converted to `""` empty string. | ||
*/ | ||
export declare class PhoneSchema<R extends boolean = false> implements Schema<PhoneSchemaType<R>> { | ||
readonly title: string; | ||
readonly description: string; | ||
readonly placeholder: string; | ||
readonly value: string | null; | ||
readonly required: R; | ||
export declare class PhoneSchema<T extends string = string, R extends boolean = false> extends StringSchema<T, R> { | ||
readonly match: RegExp; | ||
readonly max: number; | ||
constructor({ title, description, placeholder, value, required }?: PhoneOptions<R>); | ||
validate(unsafeValue?: unknown): PhoneSchemaType<R> | Invalid; | ||
clean(str: string): string; | ||
} | ||
/** Shortcuts for PhoneSchema. */ | ||
export declare const phone: { | ||
(options: PhoneOptions<false>): PhoneSchema<false>; | ||
(options: PhoneOptions<true>): PhoneSchema<true>; | ||
(): PhoneSchema<false>; | ||
required: PhoneSchema<true>; | ||
optional: PhoneSchema<false>; | ||
<T extends string>(options: StringOptions<T, false>): PhoneSchema<T, false>; | ||
<T extends string>(options: StringOptions<T, true>): PhoneSchema<T, true>; | ||
(): PhoneSchema<string, false>; | ||
required: PhoneSchema<string, true>; | ||
optional: PhoneSchema<string, false>; | ||
}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.phone = exports.PhoneSchema = exports.coercePhone = void 0; | ||
const message_1 = require("../helpers/message"); | ||
exports.phone = exports.PhoneSchema = void 0; | ||
const StringSchema_1 = require("./StringSchema"); | ||
/** | ||
@@ -9,3 +9,3 @@ * Clean a phone number string by removing characters that aren't digits. | ||
*/ | ||
function cleanPhone(value) { | ||
const cleanPhone = (value) => { | ||
// Strip characters that aren't 0-9 or `+` plus (including whitespace). | ||
@@ -15,14 +15,3 @@ const digits = value.replace(/[^0-9+]/g, ""); | ||
return digits.substr(0, 1) + digits.substr(1).replace(/[^0-9]/g, ""); | ||
} | ||
/** Coerce an unknown value into a phone number (if possible). */ | ||
function coercePhone(value) { | ||
if (!value) | ||
return null; // Convert falsy to null (including empty string). | ||
if (typeof value === "number") | ||
return value.toString(); | ||
if (typeof value === "string") | ||
return cleanPhone(value) || null; // Return the clean phone number (also convert empty string to null). | ||
return new message_1.Invalid("Must be string or null"); | ||
} | ||
exports.coercePhone = coercePhone; | ||
}; | ||
// Valid phone number is max 16 digits made up of: | ||
@@ -33,39 +22,14 @@ // - Country code (`+` plus character and 1-3 digits, e.g. `+44` or `+1`). | ||
/** | ||
* Schema that defines a valid phone number. | ||
* Multiple string formats are automatically converted to E.164 format. | ||
* | ||
* `null` is also a valid value if this field is not required. | ||
* Falsy values and empty strings are converted to `null` | ||
* Type of `StringSchema` that defines a valid phone number. | ||
* - Multiple string formats are automatically converted to E.164 format (starting with `+` plus). | ||
* - Falsy values are converted to `""` empty string. | ||
*/ | ||
class PhoneSchema { | ||
constructor({ title = "", description = "", placeholder = "", value = null, required = false } = {}) { | ||
class PhoneSchema extends StringSchema_1.StringSchema { | ||
constructor() { | ||
super(...arguments); | ||
this.match = R_PHONE; | ||
this.max = 16; // Valid phone number is 16 digits or fewer (15 numerals with a leading `+` plus). | ||
this.title = title; | ||
this.description = description; | ||
this.placeholder = placeholder; | ||
this.value = value; | ||
this.required = required; | ||
} | ||
validate(unsafeValue = this.value) { | ||
// Coorce. | ||
const value = coercePhone(unsafeValue); | ||
if (value instanceof message_1.Invalid) | ||
return value; | ||
// Null means 'no phone' | ||
if (!value) { | ||
// Check requiredness. | ||
if (this.required) | ||
return new message_1.Required("Required"); | ||
// Return null. | ||
// We know this type assertion is sound because `null` can never be returned if `this.required == true`. | ||
return null; | ||
} | ||
// Check length. | ||
if (value.length > this.max) | ||
return new message_1.Invalid(`Maximum ${this.max} characters`); | ||
// Check format. | ||
if (!R_PHONE.test(value)) | ||
return new message_1.Invalid("Invalid phone number (must be an international number starting with `+` plus)"); | ||
// Return phone. | ||
return value; | ||
clean(str) { | ||
return cleanPhone(super.clean(str)); | ||
} | ||
@@ -72,0 +36,0 @@ } |
import type { Schema, SchemaOptions } from "../Schema"; | ||
import type { EmptyIfOptional } from "../types"; | ||
import { Invalid } from "../helpers/message"; | ||
/** Coerce an unknown value to a string (if possible). */ | ||
export declare function coerceString(value: unknown): string | Invalid; | ||
export declare type StringSchemaType<T extends string = string, R extends boolean = boolean> = T | EmptyIfOptional<R>; | ||
export interface StringOptions<T extends string = string, R extends boolean = false> extends SchemaOptions { | ||
export declare type StringSchemaType<T extends string = string, R extends boolean = boolean> = T | (R extends true ? never : ""); | ||
export interface StringOptions<T extends string = string, R extends boolean = boolean> extends SchemaOptions { | ||
readonly value?: string; | ||
@@ -54,6 +53,6 @@ readonly required?: R; | ||
/** | ||
* Clean a phone number string by removing characters that aren't digits. | ||
* Clean a string by removing characters that aren't digits. | ||
* Might be empty string if the string contained only invalid characters. | ||
*/ | ||
clean(value: string): string; | ||
clean(str: string): string; | ||
} | ||
@@ -60,0 +59,0 @@ /** Shortcuts for StringSchema. */ |
@@ -59,3 +59,3 @@ "use strict"; | ||
// Strip control characters. | ||
const value = uncleanValue.trim().replace(this.multiline ? R_CONTROL_CHARS_MULTILINE : R_CONTROL_CHARS, ""); | ||
const value = this.clean(uncleanValue); | ||
// Empty? | ||
@@ -67,3 +67,3 @@ if (!value.length) { | ||
// Return. | ||
return ""; | ||
return value; | ||
} | ||
@@ -95,8 +95,8 @@ // Check max. | ||
/** | ||
* Clean a phone number string by removing characters that aren't digits. | ||
* Clean a string by removing characters that aren't digits. | ||
* Might be empty string if the string contained only invalid characters. | ||
*/ | ||
clean(value) { | ||
clean(str) { | ||
// Trim and always strip `\r` — only strip `\n` if multiline is truthy. | ||
return value.trim().replace(this.multiline ? R_CONTROL_CHARS_MULTILINE : R_CONTROL_CHARS, ""); | ||
return str.trim().replace(this.multiline ? R_CONTROL_CHARS_MULTILINE : R_CONTROL_CHARS, ""); | ||
} | ||
@@ -103,0 +103,0 @@ } |
@@ -1,43 +0,27 @@ | ||
import type { NullIfOptional } from "../types"; | ||
import type { Schema, SchemaOptions } from "../Schema"; | ||
import { Invalid } from "../helpers/message"; | ||
/** Coerce an unknown value to a URL (if possible). */ | ||
export declare function coerceUrl(value: unknown): string | null | Invalid; | ||
export declare type UrlSchemaType<R extends boolean = boolean> = string | NullIfOptional<R>; | ||
interface UrlOptions<R extends boolean = false> extends SchemaOptions { | ||
readonly value?: string | null; | ||
readonly required?: R; | ||
import { StringOptions, StringSchema, StringSchemaType } from "./StringSchema"; | ||
export interface UrlOptions<T extends string = string, R extends boolean = false> extends StringOptions<T, R> { | ||
readonly schemes?: string[]; | ||
readonly hosts?: string[] | null; | ||
readonly max?: number; | ||
} | ||
/** | ||
* Schema that defines a valid URL. | ||
* | ||
* Ensures value is a string, enforces that the string is a valid URL. | ||
* Checks URL scheme against a whitelist (always), and checks URL domain against a whitelist (optional). | ||
* `null` is also a valid value if this field is not required. | ||
* | ||
* URLs are limited to 512 characters (this can be changed with `max`), but generally these won't be data: URIs so this is a reasonable limit. | ||
* Type of `StringSchema` that defines a valid URL. | ||
* - Checks URL scheme against a whitelist (always), and checks URL domain against a whitelist (optional). | ||
* - URLs are limited to 512 characters, but generally these won't be data: URIs so this is a reasonable limit. | ||
* - Falsy values are converted to `""` empty string. | ||
*/ | ||
export declare class UrlSchema<R extends boolean = false> implements Schema<UrlSchemaType<R>> { | ||
readonly title: string; | ||
readonly description: string; | ||
readonly placeholder: string; | ||
readonly value: string | null; | ||
readonly required: R; | ||
export declare class UrlSchema<T extends string, R extends boolean = false> extends StringSchema<T, R> { | ||
readonly schemes: string[]; | ||
readonly hosts: string[] | null; | ||
readonly max: number; | ||
constructor({ title, description, placeholder, value, required, schemes, hosts, max, }?: UrlOptions<R>); | ||
validate(unsafeValue?: unknown): UrlSchemaType<R> | Invalid; | ||
readonly max = 512; | ||
constructor({ schemes, hosts, ...options }?: UrlOptions<T, R>); | ||
validate(unsafeValue?: unknown): StringSchemaType<T, R> | Invalid; | ||
} | ||
/** Shortcuts for UrlSchema. */ | ||
export declare const url: { | ||
(options: UrlOptions<false>): UrlSchema<false>; | ||
(options: UrlOptions<true>): UrlSchema<true>; | ||
(): UrlSchema<false>; | ||
required: UrlSchema<true>; | ||
optional: UrlSchema<false>; | ||
<T extends string>(options: UrlOptions<T, false>): UrlSchema<T, false>; | ||
<T extends string>(options: UrlOptions<T, true>): UrlSchema<T, true>; | ||
(): UrlSchema<string, false>; | ||
required: UrlSchema<string, true>; | ||
optional: UrlSchema<string, false>; | ||
}; | ||
export {}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.url = exports.UrlSchema = exports.coerceUrl = void 0; | ||
exports.url = exports.UrlSchema = void 0; | ||
const message_1 = require("../helpers/message"); | ||
/** Coerce an unknown value to a URL (if possible). */ | ||
function coerceUrl(value) { | ||
if (!value) | ||
return null; // Convert falsy to null. | ||
if (typeof value === "string") | ||
return value.trim() || null; | ||
return new message_1.Invalid("Must be string or null"); | ||
} | ||
exports.coerceUrl = coerceUrl; | ||
const StringSchema_1 = require("./StringSchema"); | ||
/** | ||
* Schema that defines a valid URL. | ||
* | ||
* Ensures value is a string, enforces that the string is a valid URL. | ||
* Checks URL scheme against a whitelist (always), and checks URL domain against a whitelist (optional). | ||
* `null` is also a valid value if this field is not required. | ||
* | ||
* URLs are limited to 512 characters (this can be changed with `max`), but generally these won't be data: URIs so this is a reasonable limit. | ||
* Type of `StringSchema` that defines a valid URL. | ||
* - Checks URL scheme against a whitelist (always), and checks URL domain against a whitelist (optional). | ||
* - URLs are limited to 512 characters, but generally these won't be data: URIs so this is a reasonable limit. | ||
* - Falsy values are converted to `""` empty string. | ||
*/ | ||
class UrlSchema { | ||
constructor({ title = "", description = "", placeholder = "", value = null, required = false, schemes = ["http:", "https:"], hosts = null, max = 512, } = {}) { | ||
class UrlSchema extends StringSchema_1.StringSchema { | ||
constructor({ schemes = ["http:", "https:"], hosts = null, ...options } = {}) { | ||
super(options); | ||
this.max = 512; | ||
this.title = title; | ||
this.description = description; | ||
this.placeholder = placeholder; | ||
this.value = value; | ||
this.required = required; | ||
this.schemes = schemes; | ||
this.hosts = hosts; | ||
this.max = max; | ||
} | ||
validate(unsafeValue = this.value) { | ||
// Coorce. | ||
const value = coerceUrl(unsafeValue); | ||
const value = super.validate(unsafeValue); | ||
if (value instanceof message_1.Invalid) | ||
return value; | ||
// Null means 'no URL' | ||
if (value === null) { | ||
// Check requiredness. | ||
if (this.required) | ||
return new message_1.Required("Required"); | ||
// Return null. | ||
// We know this type assertion is sound because `null` can never be returned if `this.required == true`. | ||
return null; | ||
} | ||
if (!value) | ||
return value; | ||
// Parse the URL using URL class (available in Node 10 and modern browsers). | ||
@@ -57,7 +34,4 @@ let u; | ||
// Definitely not valid. | ||
return new message_1.Invalid("Invalid URL format"); | ||
return new message_1.Invalid("Invalid format"); | ||
} | ||
// Check length again. | ||
if (u.href.length > this.max) | ||
return new message_1.Invalid(`Maximum ${this.max} characters`); | ||
// Check scheme and domain exist in whitelists. | ||
@@ -72,3 +46,3 @@ if (!this.schemes.includes(u.protocol)) | ||
if (u.host.length > 253) | ||
return new message_1.Invalid(`Invalid URL format`); | ||
return new message_1.Invalid(`Invalid format`); | ||
// Each host segment is no more than 63 characters. | ||
@@ -78,3 +52,3 @@ const bits = u.host.split("."); | ||
if (bits[i].length > 63) | ||
return new message_1.Invalid(`Invalid URL format`); | ||
return new message_1.Invalid(`Invalid format`); | ||
} | ||
@@ -81,0 +55,0 @@ // Return the normalised URL. |
@@ -1,7 +0,1 @@ | ||
/** Helper type that allows `null` if `R` (required) is false. */ | ||
export declare type NullIfOptional<R extends boolean> = R extends true ? never : null; | ||
/** Helper type that allows `false` if `R` (required) is false. */ | ||
export declare type FalseIfOptional<R extends boolean> = R extends true ? never : false; | ||
/** Helper type that allows empty string if `R` (required) is false. */ | ||
export declare type EmptyIfOptional<R extends boolean> = R extends true ? never : ""; | ||
/** | ||
@@ -8,0 +2,0 @@ * Unknown object: an object whose properties are unknown. |
{ | ||
"name": "schemaglobin", | ||
"description": "Validate user-entered data.", | ||
"version": "5.7.0", | ||
"version": "5.8.0", | ||
"repository": "https://github.com/dhoulb/schemaglobin", | ||
@@ -6,0 +6,0 @@ "author": "Dave Houlbrooke <dave@shax.com>", |
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
148383
2729