shelving 1.20.2 → 1.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/api/Resource.d.ts CHANGED
@@ -6,24 +6,22 @@ import { Validator, Validatable } from "../util/index.js";
6
6
  * @param returns The `Validator` the function's returned value must conform to (defaults to `undefined` if not specified).
7
7
  */
8
8
  export declare class Resource<P = unknown, R = void> implements Validatable<R> {
9
- static create<X, Y>(payload: Validator<X>, result: Validator<Y>): Resource<X, Y>;
10
- static create<Y>(payload: undefined, result: Y): Resource<undefined, Y>;
11
- static create<X>(payload: Validator<X>, result?: undefined): Resource<X, void>;
12
- static create(payload?: undefined, result?: undefined): Resource<undefined, void>;
13
9
  /** Payload validator. */
14
10
  readonly payload: Validator<P>;
15
11
  /** Result validator. */
16
12
  readonly result: Validator<R>;
17
- protected constructor(payload: Validator<P>, result: Validator<R>);
13
+ constructor(payload: Validator<P>, result: Validator<R>);
18
14
  /**
19
15
  * Validate a payload for this resource.
20
16
  *
17
+ * @returns The validated payload for this resource.
18
+ * @throws InvalidFeedback if the payload could not be validated.
21
19
  */
22
- validatePayload(unsafePayload: unknown): P;
20
+ prepare(unsafePayload: unknown): P;
23
21
  /**
24
22
  * Validate a result for this resource.
25
23
  *
26
- * @returns The validated payload for this resource.
24
+ * @returns The validated result for this resource.
27
25
  * @throws ValidationError if the result could not be validated.
28
26
  */
29
27
  validate(unsafeResult: unknown): R;
@@ -32,3 +30,11 @@ export declare class Resource<P = unknown, R = void> implements Validatable<R> {
32
30
  export declare type PayloadType<X extends Resource> = X extends Resource<infer Y, unknown> ? Y : never;
33
31
  /** Extract the result type from a `Resource`. */
34
32
  export declare type ResourceType<X extends Resource> = X extends Resource<unknown, infer Y> ? Y : never;
33
+ /**
34
+ * Shortcut to create a new `Resource` (consistent with `Schema` shortcuts.
35
+ * - Sets `undefined` as the default type for payload and result.
36
+ */
37
+ export declare function RESOURCE<X, Y>(payload: Validator<X>, result: Validator<Y>): Resource<X, Y>;
38
+ export declare function RESOURCE<Y>(payload: undefined, result: Y): Resource<undefined, Y>;
39
+ export declare function RESOURCE<X>(payload: Validator<X>, result?: undefined): Resource<X, void>;
40
+ export declare function RESOURCE(payload?: undefined, result?: undefined): Resource<undefined, void>;
package/api/Resource.js CHANGED
@@ -1,8 +1,6 @@
1
1
  import { UNDEFINED, validate } from "../util/index.js";
2
- import { Feedback, throwFeedback } from "../feedback/index.js";
2
+ import { Feedback } from "../feedback/index.js";
3
3
  import { ResourceValidationError } from "./errors.js";
4
- /** Validator that always returns void/undefined. */
5
- const UNDEFINED_VALIDATOR = UNDEFINED;
6
4
  /**
7
5
  * An abstract API resource definition, used to specify types for e.g. serverless functions..
8
6
  *
@@ -15,20 +13,19 @@ export class Resource {
15
13
  this.payload = payload;
16
14
  this.result = result;
17
15
  }
18
- static create(payload = UNDEFINED_VALIDATOR, result = UNDEFINED_VALIDATOR) {
19
- return new Resource(payload, result);
20
- }
21
16
  /**
22
17
  * Validate a payload for this resource.
23
18
  *
19
+ * @returns The validated payload for this resource.
20
+ * @throws InvalidFeedback if the payload could not be validated.
24
21
  */
25
- validatePayload(unsafePayload) {
26
- return throwFeedback(validate(unsafePayload, this.payload));
22
+ prepare(unsafePayload) {
23
+ return validate(unsafePayload, this.payload);
27
24
  }
28
25
  /**
29
26
  * Validate a result for this resource.
30
27
  *
31
- * @returns The validated payload for this resource.
28
+ * @returns The validated result for this resource.
32
29
  * @throws ValidationError if the result could not be validated.
33
30
  */
34
31
  validate(unsafeResult) {
@@ -40,3 +37,6 @@ export class Resource {
40
37
  }
41
38
  }
42
39
  }
40
+ export function RESOURCE(payload = UNDEFINED, result = UNDEFINED) {
41
+ return new Resource(payload, result);
42
+ }
@@ -4,4 +4,3 @@ export * from "./WarningFeedback.js";
4
4
  export * from "./ErrorFeedback.js";
5
5
  export * from "./InvalidFeedback.js";
6
6
  export * from "./hydrations.js";
7
- export * from "./util.js";
package/feedback/index.js CHANGED
@@ -4,4 +4,3 @@ export * from "./WarningFeedback.js";
4
4
  export * from "./ErrorFeedback.js";
5
5
  export * from "./InvalidFeedback.js";
6
6
  export * from "./hydrations.js";
7
- export * from "./util.js";
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "state-management",
12
12
  "query-builder"
13
13
  ],
14
- "version": "1.20.2",
14
+ "version": "1.22.1",
15
15
  "repository": "https://github.com/dhoulb/shelving",
16
16
  "author": "Dave Houlbrooke <dave@shax.com>",
17
17
  "license": "0BSD",
@@ -1,6 +1,5 @@
1
1
  import { validate, ValidateObserver, callAsync } from "../util/index.js";
2
2
  import { Transform, validateTransform } from "../transform/index.js";
3
- import { throwFeedback } from "../feedback/index.js";
4
3
  import { ThroughProvider } from "./ThroughProvider.js";
5
4
  /** Validates any values that are read from or written to a source provider. */
6
5
  export class ValidationProvider extends ThroughProvider {
@@ -11,7 +10,7 @@ export class ValidationProvider extends ThroughProvider {
11
10
  return super.subscribe(ref, new ValidateObserver(ref, observer));
12
11
  }
13
12
  add(ref, data) {
14
- return super.add(ref, throwFeedback(validate(data, ref.validator)));
13
+ return super.add(ref, validate(data, ref.validator));
15
14
  }
16
15
  write(ref, value) {
17
16
  return super.write(ref, value ? _validateWrite(value, ref.validator) : value);
@@ -28,5 +27,5 @@ export class ValidationProvider extends ThroughProvider {
28
27
  }
29
28
  /** Validate data or a transform for a path. */
30
29
  function _validateWrite(value, validator) {
31
- return throwFeedback(value instanceof Transform ? validateTransform(value, validator) : validate(value, validator));
30
+ return value instanceof Transform ? validateTransform(value, validator) : validate(value, validator);
32
31
  }
@@ -30,5 +30,5 @@ export declare function useAsyncDocument<T extends Data>(ref: DataDocument<T> |
30
30
  * @trhows `Error` if a `CacheProvider` is not part of the database's provider chain.
31
31
  * @throws `Error` if there was a problem retrieving the result.
32
32
  */
33
- export declare function useResult<T extends Data>(ref: DataDocument<T>, maxAge?: number | true): Result<T>;
34
- export declare function useResult<T extends Data>(ref: DataDocument<T> | undefined, maxAge?: number | true): Result<T> | undefined;
33
+ export declare function useDocument<T extends Data>(ref: DataDocument<T>, maxAge?: number | true): Result<T>;
34
+ export declare function useDocument<T extends Data>(ref: DataDocument<T> | undefined, maxAge?: number | true): Result<T> | undefined;
@@ -54,6 +54,6 @@ function subscribeEffect(ref, maxAge, next, error) {
54
54
  return stopCache;
55
55
  }
56
56
  }
57
- export function useResult(ref, maxAge) {
57
+ export function useDocument(ref, maxAge) {
58
58
  return throwAsync(useAsyncDocument(ref, maxAge));
59
59
  }
@@ -9,13 +9,14 @@ import { StringSchema } from "./StringSchema.js";
9
9
  * Colors 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.
10
10
  */
11
11
  export declare class ColorSchema extends StringSchema {
12
- readonly max = 7;
13
12
  readonly type = "color";
13
+ readonly min = 1;
14
+ readonly max = 7;
14
15
  readonly multiline = false;
15
16
  readonly match: RegExp;
16
17
  sanitize(uncleanString: string): string;
17
18
  }
18
19
  /** Valid color hex string, e.g. `#00CCFF` (required because empty string is invalid). */
19
- export declare const REQUIRED_COLOR: ColorSchema;
20
+ export declare const COLOR: ColorSchema;
20
21
  /** Valid color hex string, e.g. `#00CCFF`, or `null` */
21
- export declare const OPTIONAL_COLOR: import("./NullableSchema.js").NullableSchema<string>;
22
+ export declare const OPTIONAL_COLOR: import("./OptionalSchema.js").OptionalSchema<string>;
@@ -1,4 +1,4 @@
1
- import { NULLABLE } from "./NullableSchema.js";
1
+ import { OPTIONAL } from "./OptionalSchema.js";
2
2
  import { StringSchema } from "./StringSchema.js";
3
3
  const R_MATCH = /^#[0-9A-F]{6}$/;
4
4
  const R_STRIP = /[^0-9A-F]/g;
@@ -14,8 +14,9 @@ const R_STRIP = /[^0-9A-F]/g;
14
14
  export class ColorSchema extends StringSchema {
15
15
  constructor() {
16
16
  super(...arguments);
17
- this.max = 7;
18
17
  this.type = "color";
18
+ this.min = 1;
19
+ this.max = 7;
19
20
  this.multiline = false;
20
21
  this.match = R_MATCH;
21
22
  }
@@ -25,6 +26,6 @@ export class ColorSchema extends StringSchema {
25
26
  }
26
27
  }
27
28
  /** Valid color hex string, e.g. `#00CCFF` (required because empty string is invalid). */
28
- export const REQUIRED_COLOR = new ColorSchema({});
29
+ export const COLOR = new ColorSchema({});
29
30
  /** Valid color hex string, e.g. `#00CCFF`, or `null` */
30
- export const OPTIONAL_COLOR = NULLABLE(REQUIRED_COLOR);
31
+ export const OPTIONAL_COLOR = OPTIONAL(COLOR);
@@ -1,6 +1,6 @@
1
1
  import { Validators, Data } from "../util/index.js";
2
2
  import { Schema } from "./Schema.js";
3
- import { NullableSchema } from "./NullableSchema.js";
3
+ import { OptionalSchema } from "./OptionalSchema.js";
4
4
  /** Validate a data object. */
5
5
  export declare class DataSchema<T extends Data> extends Schema<T> {
6
6
  readonly props: Validators<T>;
@@ -14,4 +14,4 @@ export declare class DataSchema<T extends Data> extends Schema<T> {
14
14
  /** Valid data object with specifed properties. */
15
15
  export declare const DATA: <T extends Data>(props: Validators<T>) => DataSchema<T>;
16
16
  /** Valid data object with specifed properties, or `null` */
17
- export declare const OPTIONAL_DATA: <T extends Data>(props: Validators<T>) => NullableSchema<T>;
17
+ export declare const OPTIONAL_DATA: <T extends Data>(props: Validators<T>) => OptionalSchema<T>;
@@ -1,7 +1,7 @@
1
1
  import { isObject, validateData } from "../util/index.js";
2
2
  import { InvalidFeedback } from "../feedback/index.js";
3
3
  import { Schema } from "./Schema.js";
4
- import { NULLABLE } from "./NullableSchema.js";
4
+ import { OPTIONAL } from "./OptionalSchema.js";
5
5
  /** Validate a data object. */
6
6
  export class DataSchema extends Schema {
7
7
  constructor({ value = {}, props, ...options }) {
@@ -18,4 +18,4 @@ export class DataSchema extends Schema {
18
18
  /** Valid data object with specifed properties. */
19
19
  export const DATA = (props) => new DataSchema({ props });
20
20
  /** Valid data object with specifed properties, or `null` */
21
- export const OPTIONAL_DATA = (props) => NULLABLE(new DataSchema({ props }));
21
+ export const OPTIONAL_DATA = (props) => OPTIONAL(new DataSchema({ props }));
@@ -13,6 +13,6 @@ export declare class DateSchema extends Schema<string> {
13
13
  validate(unsafeValue?: unknown): string;
14
14
  }
15
15
  /** Valid date, e.g. `2005-09-12` (required because falsy values are invalid). */
16
- export declare const REQUIRED_DATE: DateSchema;
16
+ export declare const DATE: DateSchema;
17
17
  /** Valid date, e.g. `2005-09-12`, or `null` */
18
- export declare const OPTIONAL_DATE: import("./NullableSchema.js").NullableSchema<string>;
18
+ export declare const OPTIONAL_DATE: import("./OptionalSchema.js").OptionalSchema<string>;
@@ -1,7 +1,7 @@
1
1
  import { toDate, getYmd } from "../util/index.js";
2
2
  import { InvalidFeedback } from "../feedback/index.js";
3
3
  import { Schema } from "./Schema.js";
4
- import { NULLABLE } from "./NullableSchema.js";
4
+ import { OPTIONAL } from "./OptionalSchema.js";
5
5
  /** Define a valid date, e.g. `2005-09-12` */
6
6
  export class DateSchema extends Schema {
7
7
  constructor({ value = "now", min = null, max = null, ...options }) {
@@ -24,6 +24,6 @@ export class DateSchema extends Schema {
24
24
  }
25
25
  }
26
26
  /** Valid date, e.g. `2005-09-12` (required because falsy values are invalid). */
27
- export const REQUIRED_DATE = new DateSchema({});
27
+ export const DATE = new DateSchema({});
28
28
  /** Valid date, e.g. `2005-09-12`, or `null` */
29
- export const OPTIONAL_DATE = NULLABLE(REQUIRED_DATE);
29
+ export const OPTIONAL_DATE = OPTIONAL(DATE);
@@ -18,12 +18,13 @@ import { StringSchema } from "./StringSchema.js";
18
18
  */
19
19
  export declare class EmailSchema extends StringSchema {
20
20
  readonly type = "email";
21
+ readonly min = 1;
21
22
  readonly max = 254;
22
23
  readonly match: RegExp;
23
24
  readonly multiline = false;
24
25
  sanitize(uncleanString: string): string;
25
26
  }
26
- /** Valid email, e.g. `test@test.com` (required because empty string is invalid). */
27
- export declare const REQUIRED_EMAIL: EmailSchema;
27
+ /** Valid email, e.g. `test@test.com` */
28
+ export declare const EMAIL: EmailSchema;
28
29
  /** Valid email, e.g. `test@test.com`, or `null` */
29
- export declare const OPTIONAL_EMAIL: import("./NullableSchema.js").NullableSchema<string>;
30
+ export declare const OPTIONAL_EMAIL: import("./OptionalSchema.js").OptionalSchema<string>;
@@ -1,4 +1,4 @@
1
- import { NULLABLE } from "./NullableSchema.js";
1
+ import { OPTIONAL } from "./OptionalSchema.js";
2
2
  import { StringSchema } from "./StringSchema.js";
3
3
  const R_MATCH = /^[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])$/;
4
4
  /**
@@ -22,6 +22,7 @@ export class EmailSchema extends StringSchema {
22
22
  constructor() {
23
23
  super(...arguments);
24
24
  this.type = "email";
25
+ this.min = 1;
25
26
  this.max = 254;
26
27
  this.match = R_MATCH;
27
28
  this.multiline = false;
@@ -31,7 +32,7 @@ export class EmailSchema extends StringSchema {
31
32
  return typeof cleanString === "string" ? cleanString.toLowerCase() : cleanString;
32
33
  }
33
34
  }
34
- /** Valid email, e.g. `test@test.com` (required because empty string is invalid). */
35
- export const REQUIRED_EMAIL = new EmailSchema({});
35
+ /** Valid email, e.g. `test@test.com` */
36
+ export const EMAIL = new EmailSchema({});
36
37
  /** Valid email, e.g. `test@test.com`, or `null` */
37
- export const OPTIONAL_EMAIL = NULLABLE(REQUIRED_EMAIL);
38
+ export const OPTIONAL_EMAIL = OPTIONAL(EMAIL);
@@ -11,6 +11,6 @@ export declare class KeySchema extends StringSchema {
11
11
  readonly max = 64;
12
12
  }
13
13
  /** Valid color hex string, e.g. `#00CCFF` (required because empty string is invalid). */
14
- export declare const REQUIRED_KEY: KeySchema;
14
+ export declare const KEY: KeySchema;
15
15
  /** Valid color hex string, e.g. `#00CCFF`, or `null` */
16
- export declare const OPTIONAL_KEY: import("./NullableSchema.js").NullableSchema<string>;
16
+ export declare const OPTIONAL_KEY: import("./OptionalSchema.js").OptionalSchema<string>;
@@ -1,5 +1,5 @@
1
1
  import { StringSchema } from "./StringSchema.js";
2
- import { NULLABLE } from "./NullableSchema.js";
2
+ import { OPTIONAL } from "./OptionalSchema.js";
3
3
  /**
4
4
  * Define a valid database key.
5
5
  *
@@ -15,6 +15,6 @@ export class KeySchema extends StringSchema {
15
15
  }
16
16
  }
17
17
  /** Valid color hex string, e.g. `#00CCFF` (required because empty string is invalid). */
18
- export const REQUIRED_KEY = new KeySchema({});
18
+ export const KEY = new KeySchema({});
19
19
  /** Valid color hex string, e.g. `#00CCFF`, or `null` */
20
- export const OPTIONAL_KEY = NULLABLE(REQUIRED_KEY);
20
+ export const OPTIONAL_KEY = OPTIONAL(KEY);
@@ -5,8 +5,9 @@ import { StringSchema } from "./StringSchema.js";
5
5
  * - URLs are limited to 512 characters, but generally these won't be data: URIs so this is a reasonable limit.
6
6
  * - Falsy values are converted to `""` empty string.
7
7
  */
8
- export declare class UrlSchema extends StringSchema {
8
+ export declare class LinkSchema extends StringSchema {
9
9
  readonly type = "url";
10
+ readonly min = 1;
10
11
  readonly max = 512;
11
12
  readonly schemes: string[];
12
13
  readonly hosts: string[] | null;
@@ -16,7 +17,7 @@ export declare class UrlSchema extends StringSchema {
16
17
  });
17
18
  validate(unsafeValue: unknown): string;
18
19
  }
19
- /** Valid URL, e.g. `#00CCFF` (required because empty string won't validate). */
20
- export declare const REQUIRED_URL: UrlSchema;
21
- /** Valid URL, e.g. `#00CCFF`, or `null` */
22
- export declare const OPTIONAL_URL: import("./NullableSchema.js").NullableSchema<string>;
20
+ /** Valid link, e.g. `https://www.google.com` */
21
+ export declare const LINK: LinkSchema;
22
+ /** Valid link, e.g. `https://www.google.com`, or `null` */
23
+ export declare const OPTIONAL_LINK: import("./OptionalSchema.js").OptionalSchema<string>;
@@ -1,6 +1,6 @@
1
1
  import { InvalidFeedback } from "../feedback/index.js";
2
2
  import { toURL } from "../util/index.js";
3
- import { NULLABLE } from "./NullableSchema.js";
3
+ import { OPTIONAL } from "./OptionalSchema.js";
4
4
  import { StringSchema } from "./StringSchema.js";
5
5
  /**
6
6
  * Type of `StringSchema` that defines a valid URL.
@@ -8,10 +8,11 @@ import { StringSchema } from "./StringSchema.js";
8
8
  * - URLs are limited to 512 characters, but generally these won't be data: URIs so this is a reasonable limit.
9
9
  * - Falsy values are converted to `""` empty string.
10
10
  */
11
- export class UrlSchema extends StringSchema {
11
+ export class LinkSchema extends StringSchema {
12
12
  constructor({ schemes = ["http:", "https:"], hosts = null, ...rest }) {
13
13
  super(rest);
14
14
  this.type = "url";
15
+ this.min = 1;
15
16
  this.max = 512;
16
17
  this.schemes = ["http:", "https:"];
17
18
  this.hosts = null;
@@ -31,7 +32,7 @@ export class UrlSchema extends StringSchema {
31
32
  return url.href;
32
33
  }
33
34
  }
34
- /** Valid URL, e.g. `#00CCFF` (required because empty string won't validate). */
35
- export const REQUIRED_URL = new UrlSchema({});
36
- /** Valid URL, e.g. `#00CCFF`, or `null` */
37
- export const OPTIONAL_URL = NULLABLE(REQUIRED_URL);
35
+ /** Valid link, e.g. `https://www.google.com` */
36
+ export const LINK = new LinkSchema({});
37
+ /** Valid link, e.g. `https://www.google.com`, or `null` */
38
+ export const OPTIONAL_LINK = OPTIONAL(LINK);
@@ -2,7 +2,6 @@ import { ImmutableMap, Validator } from "../util/index.js";
2
2
  import { Schema } from "./Schema.js";
3
3
  /** Validate a `Map` instance. */
4
4
  export declare class MapSchema<T> extends Schema<ImmutableMap<T>> {
5
- static from<X>(items: Validator<X>): MapSchema<X>;
6
5
  readonly value: ImmutableMap;
7
6
  readonly items: Validator<T>;
8
7
  readonly min: number | null;
@@ -12,9 +12,6 @@ export class MapSchema extends Schema {
12
12
  this.min = min;
13
13
  this.max = max;
14
14
  }
15
- static from(items) {
16
- return new MapSchema({ items });
17
- }
18
15
  validate(unsafeValue = this.value) {
19
16
  if (!isObject(unsafeValue))
20
17
  throw new InvalidFeedback("Must be map");
@@ -16,4 +16,4 @@ export declare class NumberSchema extends Schema<number> {
16
16
  /** Valid number, e.g. `2048` or `0` zero. */
17
17
  export declare const NUMBER: NumberSchema;
18
18
  /** Valid number, e.g. `#2048` or `0` zero, or `null` */
19
- export declare const OPTIONAL_NUMBER: import("./NullableSchema.js").NullableSchema<number>;
19
+ export declare const OPTIONAL_NUMBER: import("./OptionalSchema.js").OptionalSchema<number>;
@@ -1,7 +1,7 @@
1
1
  import { toNumber, roundNumber } from "../util/index.js";
2
2
  import { InvalidFeedback } from "../feedback/index.js";
3
3
  import { Schema } from "./Schema.js";
4
- import { NULLABLE } from "./NullableSchema.js";
4
+ import { OPTIONAL } from "./OptionalSchema.js";
5
5
  /** Schema that defines a valid number. */
6
6
  export class NumberSchema extends Schema {
7
7
  constructor({ value = 0, min = null, max = null, step = null, ...rest }) {
@@ -26,4 +26,4 @@ export class NumberSchema extends Schema {
26
26
  /** Valid number, e.g. `2048` or `0` zero. */
27
27
  export const NUMBER = new NumberSchema({});
28
28
  /** Valid number, e.g. `#2048` or `0` zero, or `null` */
29
- export const OPTIONAL_NUMBER = NULLABLE(NUMBER);
29
+ export const OPTIONAL_NUMBER = OPTIONAL(NUMBER);
@@ -1,7 +1,7 @@
1
1
  import { Schema } from "./Schema.js";
2
2
  import { ThroughSchema } from "./ThroughSchema.js";
3
3
  /** Validate a value of a specific type or `null`. */
4
- export declare class NullableSchema<T> extends ThroughSchema<T | null> {
4
+ export declare class OptionalSchema<T> extends ThroughSchema<T | null> {
5
5
  readonly value: T | null;
6
6
  constructor({ value, ...rest }: ConstructorParameters<typeof Schema>[0] & {
7
7
  source: Schema<T>;
@@ -9,5 +9,5 @@ export declare class NullableSchema<T> extends ThroughSchema<T | null> {
9
9
  });
10
10
  validate(unsafeValue?: unknown): T | null;
11
11
  }
12
- /** Create a new nullable schema from a source schema. */
13
- export declare const NULLABLE: <T>(source: Schema<T>) => NullableSchema<T>;
12
+ /** Create a new optional schema from a source schema. */
13
+ export declare const OPTIONAL: <T>(source: Schema<T>) => OptionalSchema<T>;
@@ -1,16 +1,16 @@
1
1
  import { ThroughSchema } from "./ThroughSchema.js";
2
2
  /** Validate a value of a specific type or `null`. */
3
- export class NullableSchema extends ThroughSchema {
3
+ export class OptionalSchema extends ThroughSchema {
4
4
  constructor({ value = null, ...rest }) {
5
5
  super(rest);
6
6
  this.value = null;
7
7
  this.value = value;
8
8
  }
9
9
  validate(unsafeValue = this.value) {
10
- if (unsafeValue === null)
10
+ if (unsafeValue === null || unsafeValue === undefined || unsafeValue === "" || Number.isNaN(unsafeValue))
11
11
  return null;
12
12
  return super.validate(unsafeValue);
13
13
  }
14
14
  }
15
- /** Create a new nullable schema from a source schema. */
16
- export const NULLABLE = (source) => new NullableSchema({ source });
15
+ /** Create a new optional schema from a source schema. */
16
+ export const OPTIONAL = (source) => new OptionalSchema({ source });
@@ -5,12 +5,13 @@ import { StringSchema } from "./StringSchema.js";
5
5
  * - Falsy values are converted to `""` empty string.
6
6
  */
7
7
  export declare class PhoneSchema extends StringSchema {
8
- readonly type = "phone";
8
+ readonly type = "tel";
9
9
  readonly match: RegExp;
10
+ readonly min = 1;
10
11
  readonly max: number;
11
12
  sanitize(str: string): string;
12
13
  }
13
14
  /** Valid phone number, e.g. `+441234567890` */
14
- export declare const REQUIRED_PHONE: PhoneSchema;
15
+ export declare const PHONE: PhoneSchema;
15
16
  /** Valid phone number, e.g. `+441234567890`, or `null` */
16
- export declare const OPTIONAL_PHONE: import("./NullableSchema.js").NullableSchema<string>;
17
+ export declare const OPTIONAL_PHONE: import("./OptionalSchema.js").OptionalSchema<string>;
@@ -1,5 +1,5 @@
1
1
  import { StringSchema } from "./StringSchema.js";
2
- import { NULLABLE } from "./NullableSchema.js";
2
+ import { OPTIONAL } from "./OptionalSchema.js";
3
3
  // Valid phone number is max 16 digits made up of:
4
4
  // - Country code (`+` plus character and 1-3 digits, e.g. `+44` or `+1`).
5
5
  // - Subscriber number (5-12 digits — the Solomon Islands have five-digit phone numbers apparently).
@@ -12,8 +12,9 @@ const R_MATCH = /^\+[1-9][0-9]{0,2}[0-9]{5,12}$/;
12
12
  export class PhoneSchema extends StringSchema {
13
13
  constructor() {
14
14
  super(...arguments);
15
- this.type = "phone";
15
+ this.type = "tel";
16
16
  this.match = R_MATCH;
17
+ this.min = 1;
17
18
  this.max = 16; // Valid phone number is 16 digits or fewer (15 numerals with a leading `+` plus).
18
19
  }
19
20
  sanitize(str) {
@@ -24,6 +25,6 @@ export class PhoneSchema extends StringSchema {
24
25
  }
25
26
  }
26
27
  /** Valid phone number, e.g. `+441234567890` */
27
- export const REQUIRED_PHONE = new PhoneSchema({});
28
+ export const PHONE = new PhoneSchema({});
28
29
  /** Valid phone number, e.g. `+441234567890`, or `null` */
29
- export const OPTIONAL_PHONE = NULLABLE(REQUIRED_PHONE);
30
+ export const OPTIONAL_PHONE = OPTIONAL(PHONE);
@@ -0,0 +1,18 @@
1
+ import { StringSchema } from "./StringSchema.js";
2
+ /**
3
+ * Define a valid slug, e.g. `this-is-a-slug`
4
+ *
5
+ * - Useful for URL components, usernames, etc.
6
+ * - Minimum slug length is 2 characters.
7
+ * - Maximum slug length is 64 characters.
8
+ */
9
+ export declare class SlugSchema extends StringSchema {
10
+ readonly multiline = false;
11
+ readonly min = 2;
12
+ readonly max = 32;
13
+ sanitize(unsafeString: string): string;
14
+ }
15
+ /** Valid slug, e.g. `this-is-a-slug` */
16
+ export declare const SLUG: SlugSchema;
17
+ /** Valid slug, e.g. `this-is-a-slug`, or `null` */
18
+ export declare const OPTIONAL_SLUG: import("./OptionalSchema.js").OptionalSchema<string>;
@@ -0,0 +1,25 @@
1
+ import { toSlug } from "../util/index.js";
2
+ import { OPTIONAL } from "./OptionalSchema.js";
3
+ import { StringSchema } from "./StringSchema.js";
4
+ /**
5
+ * Define a valid slug, e.g. `this-is-a-slug`
6
+ *
7
+ * - Useful for URL components, usernames, etc.
8
+ * - Minimum slug length is 2 characters.
9
+ * - Maximum slug length is 64 characters.
10
+ */
11
+ export class SlugSchema extends StringSchema {
12
+ constructor() {
13
+ super(...arguments);
14
+ this.multiline = false;
15
+ this.min = 2;
16
+ this.max = 32;
17
+ }
18
+ sanitize(unsafeString) {
19
+ return toSlug(unsafeString);
20
+ }
21
+ }
22
+ /** Valid slug, e.g. `this-is-a-slug` */
23
+ export const SLUG = new SlugSchema({});
24
+ /** Valid slug, e.g. `this-is-a-slug`, or `null` */
25
+ export const OPTIONAL_SLUG = OPTIONAL(SLUG);
@@ -1,4 +1,6 @@
1
1
  import { Schema } from "./Schema.js";
2
+ /** `type=""` prop for HTML `<input />` tags that are relevant for strings. */
3
+ export declare type HtmlInputType = "text" | "password" | "color" | "date" | "email" | "number" | "tel" | "search" | "url";
2
4
  /**
3
5
  * Schema that defines a valid string.
4
6
  *
@@ -21,7 +23,7 @@ import { Schema } from "./Schema.js";
21
23
  */
22
24
  export declare class StringSchema extends Schema<string> {
23
25
  readonly value: string;
24
- readonly type: string;
26
+ readonly type: HtmlInputType;
25
27
  readonly min: number;
26
28
  readonly max: number | null;
27
29
  readonly match: RegExp | null;
@@ -29,7 +31,7 @@ export declare class StringSchema extends Schema<string> {
29
31
  readonly trim: boolean;
30
32
  constructor({ value, type, min, max, match, multiline, trim, ...rest }: ConstructorParameters<typeof Schema>[0] & {
31
33
  readonly value?: string;
32
- readonly type?: string;
34
+ readonly type?: HtmlInputType;
33
35
  readonly min?: number;
34
36
  readonly max?: number | null;
35
37
  readonly match?: RegExp | null;
@@ -2,7 +2,7 @@ import type { Class } from "../util/index.js";
2
2
  import { Schema } from "./Schema.js";
3
3
  export declare abstract class ThroughSchema<T> extends Schema<T> {
4
4
  readonly source: Schema<T>;
5
- constructor({ source, ...options }: ConstructorParameters<typeof Schema>[0] & {
5
+ constructor({ source, title, description, placeholder, }: ConstructorParameters<typeof Schema>[0] & {
6
6
  source: Schema<T>;
7
7
  });
8
8
  validate(unsafeValue: unknown): T;
@@ -1,8 +1,8 @@
1
1
  import { AssertionError } from "../error/index.js";
2
2
  import { Schema } from "./Schema.js";
3
3
  export class ThroughSchema extends Schema {
4
- constructor({ source, ...options }) {
5
- super(options);
4
+ constructor({ source, title = source.title, description = source.description, placeholder = source.placeholder, }) {
5
+ super({ title, description, placeholder });
6
6
  this.source = source;
7
7
  }
8
8
  validate(unsafeValue) {
package/schema/index.d.ts CHANGED
@@ -7,12 +7,13 @@ export * from "./DataSchema.js";
7
7
  export * from "./DateSchema.js";
8
8
  export * from "./EmailSchema.js";
9
9
  export * from "./KeySchema.js";
10
+ export * from "./LinkSchema.js";
10
11
  export * from "./MapSchema.js";
11
- export * from "./NullableSchema.js";
12
12
  export * from "./NumberSchema.js";
13
13
  export * from "./ObjectSchema.js";
14
+ export * from "./OptionalSchema.js";
14
15
  export * from "./PhoneSchema.js";
15
16
  export * from "./RequiredSchema.js";
17
+ export * from "./SlugSchema.js";
16
18
  export * from "./StringSchema.js";
17
19
  export * from "./ThroughSchema.js";
18
- export * from "./UrlSchema.js";
package/schema/index.js CHANGED
@@ -7,12 +7,13 @@ export * from "./DataSchema.js";
7
7
  export * from "./DateSchema.js";
8
8
  export * from "./EmailSchema.js";
9
9
  export * from "./KeySchema.js";
10
+ export * from "./LinkSchema.js";
10
11
  export * from "./MapSchema.js";
11
- export * from "./NullableSchema.js";
12
12
  export * from "./NumberSchema.js";
13
13
  export * from "./ObjectSchema.js";
14
+ export * from "./OptionalSchema.js";
14
15
  export * from "./PhoneSchema.js";
15
16
  export * from "./RequiredSchema.js";
17
+ export * from "./SlugSchema.js";
16
18
  export * from "./StringSchema.js";
17
19
  export * from "./ThroughSchema.js";
18
- export * from "./UrlSchema.js";
package/util/entry.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { ImmutableArray, MutableArray } from "./array.js";
1
2
  import type { PossibleOptionalDate } from "./date.js";
2
3
  /**
3
4
  * Single entry from a map-like object.
@@ -9,6 +10,10 @@ export declare type Entry<T = unknown> = readonly [string, T];
9
10
  export declare type AnyEntry = readonly [string, any];
10
11
  /** Extract the type for an entry. */
11
12
  export declare type EntryType<X extends AnyEntry> = X extends Entry<infer Y> ? Y : never;
13
+ /** Readonly list of entries with string keys. */
14
+ export declare type ImmutableEntries<T = unknown> = ImmutableArray<Entry<T>>;
15
+ /** Writable object with string keys. */
16
+ export declare type MutableEntries<T = unknown> = MutableArray<Entry<T>>;
12
17
  /** Extract the key from an object entry. */
13
18
  export declare const ENTRY_KEY: ([k]: Entry<unknown>) => string;
14
19
  /** Extract the value from an object entry. */
@@ -1,3 +0,0 @@
1
- import { Feedback } from "./Feedback.js";
2
- /** Throw the value if it's an instance of `Feedback` */
3
- export declare function throwFeedback<T>(value: T | Feedback): T;
package/feedback/util.js DELETED
@@ -1,7 +0,0 @@
1
- import { Feedback } from "./Feedback.js";
2
- /** Throw the value if it's an instance of `Feedback` */
3
- export function throwFeedback(value) {
4
- if (value instanceof Feedback)
5
- throw value;
6
- return value;
7
- }