shelving 1.93.0 → 1.94.0

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.
Files changed (42) hide show
  1. package/error/AssertionError.d.ts +5 -2
  2. package/error/AssertionError.js +11 -4
  3. package/feedback/Feedbacks.js +3 -1
  4. package/package.json +1 -1
  5. package/schema/AllowSchema.d.ts +1 -1
  6. package/schema/AllowSchema.js +2 -2
  7. package/schema/ArraySchema.d.ts +1 -1
  8. package/schema/ArraySchema.js +3 -3
  9. package/schema/BooleanSchema.d.ts +1 -1
  10. package/schema/BooleanSchema.js +2 -3
  11. package/schema/ColorSchema.d.ts +2 -0
  12. package/schema/ColorSchema.js +2 -2
  13. package/schema/DataSchema.d.ts +1 -1
  14. package/schema/DataSchema.js +3 -4
  15. package/schema/DateSchema.d.ts +1 -1
  16. package/schema/DateSchema.js +3 -3
  17. package/schema/DictionarySchema.d.ts +1 -1
  18. package/schema/DictionarySchema.js +3 -3
  19. package/schema/EmailSchema.d.ts +2 -0
  20. package/schema/EmailSchema.js +2 -2
  21. package/schema/LinkSchema.d.ts +1 -1
  22. package/schema/LinkSchema.js +4 -4
  23. package/schema/NumberSchema.d.ts +1 -1
  24. package/schema/NumberSchema.js +4 -4
  25. package/schema/OptionalSchema.d.ts +1 -1
  26. package/schema/OptionalSchema.js +2 -3
  27. package/schema/PhoneSchema.d.ts +2 -0
  28. package/schema/PhoneSchema.js +2 -2
  29. package/schema/Schema.d.ts +6 -6
  30. package/schema/Schema.js +1 -1
  31. package/schema/StringSchema.d.ts +11 -1
  32. package/schema/StringSchema.js +14 -3
  33. package/schema/ThroughSchema.d.ts +1 -1
  34. package/schema/ThroughSchema.js +3 -3
  35. package/schema/TimeSchema.d.ts +1 -1
  36. package/schema/TimeSchema.js +3 -3
  37. package/util/assert.d.ts +1 -1
  38. package/util/assert.js +2 -2
  39. package/util/debug.d.ts +2 -0
  40. package/util/debug.js +5 -0
  41. package/util/validate.d.ts +4 -0
  42. package/util/validate.js +16 -0
@@ -2,8 +2,11 @@
2
2
  * Thrown if the program receives a value it didn't expect.
3
3
  *
4
4
  * @param message Message that explains why the thing happened.
5
- * @param ...received One or more additional details that appears in a ` (received X, Y, Z)` part of the message.
5
+ * @param received The value that made the assertion fail.
6
+ * @param expected The value that made the assertion fail.
6
7
  */
7
8
  export declare class AssertionError extends Error {
8
- constructor(message?: string, ...received: unknown[]);
9
+ readonly received: unknown;
10
+ readonly expected: unknown;
11
+ constructor(message?: string, ...receivedExpected: readonly [received?: unknown, expected?: unknown]);
9
12
  }
@@ -1,13 +1,20 @@
1
- import { debug } from "../util/debug.js";
1
+ import { debug, indent } from "../util/debug.js";
2
2
  /**
3
3
  * Thrown if the program receives a value it didn't expect.
4
4
  *
5
5
  * @param message Message that explains why the thing happened.
6
- * @param ...received One or more additional details that appears in a ` (received X, Y, Z)` part of the message.
6
+ * @param received The value that made the assertion fail.
7
+ * @param expected The value that made the assertion fail.
7
8
  */
8
9
  export class AssertionError extends Error {
9
- constructor(message = "Failed assertion", ...received) {
10
- super(received.length ? `${message} (received ${received.map(debug).join(", ")})` : message);
10
+ constructor(message = "Failed assertion", ...receivedExpected) {
11
+ super(receivedExpected.length >= 2 //
12
+ ? `${message}\nReceived:${indent(debug(receivedExpected[0]))}\nExpected:${indent(debug(receivedExpected[0]))}`
13
+ : receivedExpected.length >= 1
14
+ ? `${message}\nReceived:${indent(debug(receivedExpected[0]))}`
15
+ : message);
16
+ this.received = receivedExpected[0];
17
+ this.expected = receivedExpected[1];
11
18
  }
12
19
  }
13
20
  AssertionError.prototype.name = "AssertionError";
@@ -1,3 +1,4 @@
1
+ import { indent } from "../util/debug.js";
1
2
  import { getProp } from "../util/object.js";
2
3
  import { mapDictionary } from "../util/transform.js";
3
4
  import { Feedback } from "./Feedback.js";
@@ -8,7 +9,8 @@ export class Feedbacks extends Feedback {
8
9
  return mapDictionary(this.feedbacks, getProp, "message");
9
10
  }
10
11
  constructor(feedbacks, value) {
11
- super("Invalid format", value);
12
+ super(`${Object.entries(feedbacks).map(_mapMessages).join("\n")}`, value);
12
13
  this.feedbacks = feedbacks;
13
14
  }
14
15
  }
16
+ const _mapMessages = ([name, { message }]) => `${name}:${indent(message)}`;
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "state-management",
12
12
  "query-builder"
13
13
  ],
14
- "version": "1.93.0",
14
+ "version": "1.94.0",
15
15
  "repository": "https://github.com/dhoulb/shelving",
16
16
  "author": "Dave Houlbrooke <dave@shax.com>",
17
17
  "license": "0BSD",
@@ -10,7 +10,7 @@ export type AllowSchemaOptions<K, T> = Omit<SchemaOptions, "value"> & {
10
10
  export declare class AllowSchema<K, T> extends Schema<K> implements Iterable<Entry<K, T>> {
11
11
  readonly value: K;
12
12
  readonly allow: ImmutableMap<K, T>;
13
- constructor({ allow, ...options }: AllowSchemaOptions<K, T>);
13
+ constructor(options: AllowSchemaOptions<K, T>);
14
14
  validate(unsafeValue?: unknown): K;
15
15
  /** Iterate over the the allowed options in `[key, value]` format. */
16
16
  [Symbol.iterator](): Iterator<Entry<K, T>>;
@@ -5,9 +5,9 @@ import { getString } from "../util/string.js";
5
5
  import { Schema } from "./Schema.js";
6
6
  /** Define a valid value from an allowed set of values. */
7
7
  export class AllowSchema extends Schema {
8
- constructor({ allow, ...options }) {
8
+ constructor(options) {
9
9
  super(options);
10
- this.allow = getMap(allow);
10
+ this.allow = getMap(options.allow);
11
11
  this.value = getFirstItem(this.allow.keys());
12
12
  }
13
13
  validate(unsafeValue = this.value) {
@@ -43,7 +43,7 @@ export declare class ArraySchema<T> extends Schema<ImmutableArray<T>> {
43
43
  readonly unique: boolean;
44
44
  readonly min: number;
45
45
  readonly max: number;
46
- constructor({ value, items, unique, min, max, ...options }: ArraySchemaOptions<T>);
46
+ constructor(options: ArraySchemaOptions<T>);
47
47
  validate(unsafeValue?: unknown): ImmutableArray<T>;
48
48
  }
49
49
  /** Valid array with specifed items. */
@@ -30,9 +30,9 @@ import { Schema } from "./Schema.js";
30
30
  * schema.validate(["a", null], schema); // Throws Invalids({ "1": Invalid('Must be a string') });
31
31
  */
32
32
  export class ArraySchema extends Schema {
33
- constructor({ value = [], items, unique = false, min = 0, max = Infinity, ...options }) {
34
- super(options);
35
- this.value = value;
33
+ constructor(options) {
34
+ super({ value: [], ...options });
35
+ const { items, unique = false, min = 0, max = Infinity } = options;
36
36
  this.items = items;
37
37
  this.unique = unique;
38
38
  this.min = min;
@@ -7,7 +7,7 @@ export type BooleanSchemaOptions = SchemaOptions & {
7
7
  /** Define a valid boolean. */
8
8
  export declare class BooleanSchema extends Schema<boolean> {
9
9
  readonly value: boolean;
10
- constructor({ value, ...options }: BooleanSchemaOptions);
10
+ constructor(options: BooleanSchemaOptions);
11
11
  validate(unsafeValue?: unknown): boolean;
12
12
  }
13
13
  /** Valid boolean. */
@@ -1,9 +1,8 @@
1
1
  import { Schema } from "./Schema.js";
2
2
  /** Define a valid boolean. */
3
3
  export class BooleanSchema extends Schema {
4
- constructor({ value = false, ...options }) {
5
- super(options);
6
- this.value = value;
4
+ constructor(options) {
5
+ super({ value: false, ...options });
7
6
  }
8
7
  validate(unsafeValue = this.value) {
9
8
  return !!unsafeValue;
@@ -1,3 +1,4 @@
1
+ import type { StringSchemaOptions } from "./StringSchema.js";
1
2
  import { StringSchema } from "./StringSchema.js";
2
3
  /**
3
4
  * Define a valid color hex string, e.g `#00CCFF`
@@ -14,6 +15,7 @@ export declare class ColorSchema extends StringSchema {
14
15
  readonly max = 7;
15
16
  readonly multiline = false;
16
17
  readonly match: RegExp;
18
+ constructor(options: StringSchemaOptions);
17
19
  sanitize(insaneString: string): string;
18
20
  }
19
21
  /** Valid color hex string, e.g. `#00CCFF` (required because empty string is invalid). */
@@ -12,8 +12,8 @@ const R_STRIP = /[^0-9A-F]/g;
12
12
  * 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.
13
13
  */
14
14
  export class ColorSchema extends StringSchema {
15
- constructor() {
16
- super(...arguments);
15
+ constructor(options) {
16
+ super({ title: "Color", ...options });
17
17
  this.type = "color";
18
18
  this.min = 1;
19
19
  this.max = 7;
@@ -12,7 +12,7 @@ export type DataSchemaOptions<T extends Data> = SchemaOptions & {
12
12
  export declare class DataSchema<T extends Data> extends Schema<T> {
13
13
  readonly value: Partial<T>;
14
14
  readonly props: Validators<T>;
15
- constructor({ value, props, ...options }: DataSchemaOptions<T>);
15
+ constructor(options: DataSchemaOptions<T>);
16
16
  validate(unsafeValue?: unknown): T;
17
17
  }
18
18
  /** Set of named data schemas. */
@@ -5,10 +5,9 @@ import { OPTIONAL } from "./OptionalSchema.js";
5
5
  import { Schema } from "./Schema.js";
6
6
  /** Validate a data object. */
7
7
  export class DataSchema extends Schema {
8
- constructor({ value = {}, props, ...options }) {
9
- super(options);
10
- this.props = props;
11
- this.value = value;
8
+ constructor(options) {
9
+ super({ value: {}, ...options });
10
+ this.props = options.props;
12
11
  }
13
12
  validate(unsafeValue = this.value) {
14
13
  if (!isData(unsafeValue))
@@ -12,7 +12,7 @@ export declare class DateSchema extends Schema<string> {
12
12
  readonly value: PossibleDate;
13
13
  readonly min: Date | null;
14
14
  readonly max: Date | null;
15
- constructor({ value, min, max, ...options }: DateSchemaOptions);
15
+ constructor(options: DateSchemaOptions);
16
16
  validate(unsafeValue?: unknown): string;
17
17
  }
18
18
  /** Valid date, e.g. `2005-09-12` (required because falsy values are invalid). */
@@ -4,9 +4,9 @@ import { OPTIONAL } from "./OptionalSchema.js";
4
4
  import { Schema } from "./Schema.js";
5
5
  /** Define a valid date in YMD format, e.g. `2005-09-12` */
6
6
  export class DateSchema extends Schema {
7
- constructor({ value = "now", min = null, max = null, ...options }) {
8
- super(options);
9
- this.value = value;
7
+ constructor(options) {
8
+ super({ title: "Date", value: "now", ...options });
9
+ const { min = null, max = null } = options;
10
10
  this.min = getOptionalDate(min);
11
11
  this.max = getOptionalDate(max);
12
12
  }
@@ -15,7 +15,7 @@ export declare class DictionarySchema<T> extends Schema<ImmutableDictionary<T>>
15
15
  readonly items: Validator<T>;
16
16
  readonly min: number;
17
17
  readonly max: number;
18
- constructor({ value, items, min, max, ...rest }: DictionarySchemaOptions<T>);
18
+ constructor(options: DictionarySchemaOptions<T>);
19
19
  validate(unsafeValue?: unknown): ImmutableDictionary<T>;
20
20
  }
21
21
  /** Valid dictionary object with specifed items. */
@@ -4,10 +4,10 @@ import { validateDictionary } from "../util/validate.js";
4
4
  import { Schema } from "./Schema.js";
5
5
  /** Validate a dictionary object (whose props are all the same with string keys). */
6
6
  export class DictionarySchema extends Schema {
7
- constructor({ value = {}, items, min = 0, max = Infinity, ...rest }) {
8
- super(rest);
7
+ constructor(options) {
8
+ super({ value: {}, ...options });
9
+ const { items, min = 0, max = Infinity } = options;
9
10
  this.items = items;
10
- this.value = value;
11
11
  this.min = min;
12
12
  this.max = max;
13
13
  }
@@ -1,3 +1,4 @@
1
+ import type { StringSchemaOptions } from "./StringSchema.js";
1
2
  import { StringSchema } from "./StringSchema.js";
2
3
  /**
3
4
  * Define a valid email address.
@@ -22,6 +23,7 @@ export declare class EmailSchema extends StringSchema {
22
23
  readonly max = 254;
23
24
  readonly match: RegExp;
24
25
  readonly multiline = false;
26
+ constructor(options: StringSchemaOptions);
25
27
  sanitize(uncleanString: string): string;
26
28
  }
27
29
  /** Valid email, e.g. `test@test.com` */
@@ -19,8 +19,8 @@ const R_MATCH = /^[a-z0-9](?:[a-zA-Z0-9._+-]{0,62}[a-zA-Z0-9])?@(?:[a-z0-9](?:[a
19
19
  * - TLD is a segment of 2-63 characters, possibly in `xn--` international format.
20
20
  */
21
21
  export class EmailSchema extends StringSchema {
22
- constructor() {
23
- super(...arguments);
22
+ constructor(options) {
23
+ super({ title: "Email", ...options });
24
24
  this.type = "email";
25
25
  this.min = 1;
26
26
  this.max = 254;
@@ -17,7 +17,7 @@ export declare class LinkSchema extends StringSchema {
17
17
  readonly max = 512;
18
18
  readonly schemes: string[];
19
19
  readonly hosts: string[] | undefined;
20
- constructor({ schemes, hosts, ...rest }: LinkSchemaOptions);
20
+ constructor(options: LinkSchemaOptions);
21
21
  validate(unsafeValue: unknown): string;
22
22
  }
23
23
  /** Valid link, e.g. `https://www.google.com` */
@@ -9,13 +9,13 @@ import { StringSchema } from "./StringSchema.js";
9
9
  * - Falsy values are converted to `""` empty string.
10
10
  */
11
11
  export class LinkSchema extends StringSchema {
12
- constructor({ schemes = ["http:", "https:"], hosts, ...rest }) {
13
- super(rest);
12
+ constructor(options) {
13
+ super({ title: "Link", ...options });
14
14
  this.type = "url";
15
15
  this.min = 1;
16
16
  this.max = 512;
17
- this.schemes = schemes;
18
- this.hosts = hosts;
17
+ this.schemes = options.schemes || ["http:", "https:"];
18
+ this.hosts = options.hosts;
19
19
  }
20
20
  // Override to clean the URL using the builtin `URL` class and check the schemes and hosts against the whitelists.
21
21
  validate(unsafeValue) {
@@ -13,7 +13,7 @@ export declare class NumberSchema extends Schema<number> {
13
13
  readonly min: number;
14
14
  readonly max: number;
15
15
  readonly step: number | null;
16
- constructor({ value, min, max, step, ...rest }: NumberSchemaOptions);
16
+ constructor(options: NumberSchemaOptions);
17
17
  validate(unsafeValue?: unknown): number;
18
18
  }
19
19
  /** Valid number, e.g. `2048.12345` or `0` zero. */
@@ -4,9 +4,9 @@ import { OPTIONAL } from "./OptionalSchema.js";
4
4
  import { Schema } from "./Schema.js";
5
5
  /** Schema that defines a valid number. */
6
6
  export class NumberSchema extends Schema {
7
- constructor({ value = 0, min = -Infinity, max = Infinity, step = null, ...rest }) {
8
- super(rest);
9
- this.value = value;
7
+ constructor(options) {
8
+ super({ title: "Number", value: 0, ...options });
9
+ const { min = -Infinity, max = Infinity, step = null } = options;
10
10
  this.min = min;
11
11
  this.max = max;
12
12
  this.step = step;
@@ -40,6 +40,6 @@ export const NON_POSITIVE_INTEGER = new NumberSchema({ step: 1, min: Number.MIN_
40
40
  /** Valid optional integer number, e.g. `2048` or `0` zero, or `null` */
41
41
  export const OPTIONAL_INTEGER = OPTIONAL(INTEGER);
42
42
  /** Valid Unix timestamp (including milliseconds). */
43
- export const TIMESTAMP = INTEGER;
43
+ export const TIMESTAMP = new NumberSchema({ title: "Timestamp", step: 1, min: Number.MIN_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER, value: 0 });
44
44
  /** Valid Unix timestamp (including milliseconds). */
45
45
  export const OPTIONAL_TIMESTAMP = OPTIONAL_INTEGER;
@@ -3,7 +3,7 @@ import { ThroughSchema } from "./ThroughSchema.js";
3
3
  /** Validate a value of a specific type or `null`. */
4
4
  export declare class OptionalSchema<T> extends ThroughSchema<T | null> {
5
5
  readonly value: T | null;
6
- constructor({ value, ...rest }: ConstructorParameters<typeof Schema>[0] & {
6
+ constructor(options: ConstructorParameters<typeof Schema>[0] & {
7
7
  source: Schema<T>;
8
8
  value?: T | null;
9
9
  });
@@ -1,10 +1,9 @@
1
1
  import { ThroughSchema } from "./ThroughSchema.js";
2
2
  /** Validate a value of a specific type or `null`. */
3
3
  export class OptionalSchema extends ThroughSchema {
4
- constructor({ value = null, ...rest }) {
5
- super(rest);
4
+ constructor(options) {
5
+ super({ value: null, ...options });
6
6
  this.value = null;
7
- this.value = value;
8
7
  }
9
8
  validate(unsafeValue = this.value) {
10
9
  if (unsafeValue === null || unsafeValue === undefined || unsafeValue === "" || Number.isNaN(unsafeValue))
@@ -1,3 +1,4 @@
1
+ import type { StringSchemaOptions } from "./StringSchema.js";
1
2
  import { StringSchema } from "./StringSchema.js";
2
3
  /**
3
4
  * Type of `StringSchema` that defines a valid phone number.
@@ -9,6 +10,7 @@ export declare class PhoneSchema extends StringSchema {
9
10
  readonly match: RegExp;
10
11
  readonly min = 1;
11
12
  readonly max: number;
13
+ constructor(options: StringSchemaOptions);
12
14
  sanitize(insaneString: string): string;
13
15
  }
14
16
  /** Valid phone number, e.g. `+441234567890` */
@@ -10,8 +10,8 @@ const R_MATCH = /^\+[1-9][0-9]{0,2}[0-9]{5,12}$/;
10
10
  * - Falsy values are converted to `""` empty string.
11
11
  */
12
12
  export class PhoneSchema extends StringSchema {
13
- constructor() {
14
- super(...arguments);
13
+ constructor(options) {
14
+ super({ title: "Phone", ...options });
15
15
  this.type = "tel";
16
16
  this.match = R_MATCH;
17
17
  this.min = 1;
@@ -2,11 +2,11 @@ import type { Validatable } from "../util/validate.js";
2
2
  /** Options allowed by a `Schema` instance. */
3
3
  export type SchemaOptions = {
4
4
  /** Title of the schema, e.g. for using as the title of a corresponding field. */
5
- readonly title?: string | undefined;
5
+ readonly title?: string;
6
6
  /** Description of the schema, e.g. for using as a description in a corresponding field. */
7
- readonly description?: string | undefined;
7
+ readonly description?: string;
8
8
  /** Placeholder of the schema, e.g. for using as a placeholder in a corresponding field. */
9
- readonly placeholder?: string | undefined;
9
+ readonly placeholder?: string;
10
10
  /** Default value for the schema if `validate()` is called with an `undefined` value. */
11
11
  readonly value?: unknown;
12
12
  };
@@ -17,11 +17,11 @@ export type SchemaOptions = {
17
17
  */
18
18
  export declare abstract class Schema<T extends unknown = unknown> implements Validatable<T> {
19
19
  /** Title of the schema, e.g. for using as the title of a corresponding field. */
20
- readonly title: string | undefined;
20
+ readonly title: string;
21
21
  /** Description of the schema, e.g. for using as a description in a corresponding field. */
22
- readonly description: string | undefined;
22
+ readonly description: string;
23
23
  /** Placeholder of the schema, e.g. for using as a placeholder in a corresponding field. */
24
- readonly placeholder: string | undefined;
24
+ readonly placeholder: string;
25
25
  /** Default value for the schema if `validate()` is called with an `undefined` value. */
26
26
  readonly value: unknown;
27
27
  constructor({ title, description, placeholder, value }: SchemaOptions);
package/schema/Schema.js CHANGED
@@ -4,7 +4,7 @@
4
4
  * - `validate()` returns `Invalid` if value was not valid.
5
5
  */
6
6
  export class Schema {
7
- constructor({ title, description, placeholder, value }) {
7
+ constructor({ title = "", description = "", placeholder = "", value }) {
8
8
  this.title = title;
9
9
  this.description = description;
10
10
  this.placeholder = placeholder;
@@ -42,7 +42,7 @@ export declare class StringSchema extends Schema<string> {
42
42
  readonly match: RegExp | undefined;
43
43
  readonly sanitizer: Sanitizer | undefined;
44
44
  readonly multiline: boolean;
45
- constructor({ value, type, min, max, match, sanitizer, multiline, ...rest }: StringSchemaOptions);
45
+ constructor(options: StringSchemaOptions);
46
46
  validate(unsafeValue?: unknown): string;
47
47
  /**
48
48
  * Clean a string by removing characters that aren't digits.
@@ -55,3 +55,13 @@ export declare class StringSchema extends Schema<string> {
55
55
  export declare const STRING: StringSchema;
56
56
  /** Valid string, `Hello there!`, with more than one character. */
57
57
  export declare const REQUIRED_STRING: StringSchema;
58
+ /** Title string, e.g. `Title of something` */
59
+ export declare const TITLE: StringSchema;
60
+ /** Optional name string, e.g. `Title of something` or `null` */
61
+ export declare const OPTIONAL_TITLE: import("./OptionalSchema.js").OptionalSchema<string>;
62
+ /** Name string, e.g. `Name of Something` */
63
+ export declare const NAME: StringSchema;
64
+ /** Optional name string, e.g. `Name of Something` or `null` */
65
+ export declare const OPTIONAL_NAME: import("./OptionalSchema.js").OptionalSchema<string>;
66
+ /** Password string. */
67
+ export declare const PASSWORD: StringSchema;
@@ -1,5 +1,6 @@
1
1
  import { Feedback } from "../feedback/Feedback.js";
2
2
  import { sanitizeLines, sanitizeString } from "../util/string.js";
3
+ import { OPTIONAL } from "./OptionalSchema.js";
3
4
  import { Schema } from "./Schema.js";
4
5
  /**
5
6
  * Schema that defines a valid string.
@@ -22,10 +23,10 @@ import { Schema } from "./Schema.js";
22
23
  * schema.validate('j'); // Throws 'Minimum 3 chaacters'
23
24
  */
24
25
  export class StringSchema extends Schema {
25
- constructor({ value = "", type = "text", min = 0, max = Infinity, match, sanitizer, multiline = false, ...rest }) {
26
- super(rest);
26
+ constructor(options) {
27
+ super({ value: "", ...options });
28
+ const { type = "text", min = 0, max = Infinity, match, sanitizer, multiline = false } = options;
27
29
  this.type = type;
28
- this.value = value;
29
30
  this.min = min;
30
31
  this.max = max;
31
32
  this.match = match;
@@ -58,3 +59,13 @@ export class StringSchema extends Schema {
58
59
  export const STRING = new StringSchema({});
59
60
  /** Valid string, `Hello there!`, with more than one character. */
60
61
  export const REQUIRED_STRING = new StringSchema({ min: 1 });
62
+ /** Title string, e.g. `Title of something` */
63
+ export const TITLE = new StringSchema({});
64
+ /** Optional name string, e.g. `Title of something` or `null` */
65
+ export const OPTIONAL_TITLE = OPTIONAL(TITLE);
66
+ /** Name string, e.g. `Name of Something` */
67
+ export const NAME = new StringSchema({ title: "Name" });
68
+ /** Optional name string, e.g. `Name of Something` or `null` */
69
+ export const OPTIONAL_NAME = OPTIONAL(NAME);
70
+ /** Password string. */
71
+ export const PASSWORD = new StringSchema({ title: "Password", min: 6, type: "password" });
@@ -8,6 +8,6 @@ export type ThroughSchemaOptions<T> = SchemaOptions & {
8
8
  /** Schema that passes through to a source schema. */
9
9
  export declare abstract class ThroughSchema<T> extends Schema<T> implements Sourceable<Schema<T>> {
10
10
  readonly source: Schema<T>;
11
- constructor({ source, ...props }: ThroughSchemaOptions<T>);
11
+ constructor(options: ThroughSchemaOptions<T>);
12
12
  validate(unsafeValue: unknown): T;
13
13
  }
@@ -1,9 +1,9 @@
1
1
  import { Schema } from "./Schema.js";
2
2
  /** Schema that passes through to a source schema. */
3
3
  export class ThroughSchema extends Schema {
4
- constructor({ source, ...props }) {
5
- super({ ...source, ...props });
6
- this.source = source;
4
+ constructor(options) {
5
+ super(options);
6
+ this.source = options.source;
7
7
  }
8
8
  validate(unsafeValue) {
9
9
  return this.source.validate(unsafeValue);
@@ -19,7 +19,7 @@ export declare class TimeSchema extends Schema<string> {
19
19
  * - Note: `<input type="time">` elements expect `step=""` to be in _seconds_ so you need to multiply this by `1000`
20
20
  */
21
21
  readonly step: number | null;
22
- constructor({ value, min, max, step, ...options }: TimeSchemaOptions);
22
+ constructor(options: TimeSchemaOptions);
23
23
  validate(unsafeValue?: unknown): string;
24
24
  }
25
25
  /** Valid time, e.g. `2005-09-12` (required because falsy values are invalid). */
@@ -5,9 +5,9 @@ import { OPTIONAL } from "./OptionalSchema.js";
5
5
  import { Schema } from "./Schema.js";
6
6
  /** Define a valid time in 24h hh:mm:ss.fff format, e.g. `23:59` or `24:00 */
7
7
  export class TimeSchema extends Schema {
8
- constructor({ value = "now", min = null, max = null, step = 60, ...options }) {
9
- super(options);
10
- this.value = value;
8
+ constructor(options) {
9
+ super({ title: "Time", value: "now", ...options });
10
+ const { min = null, max = null, step = 60 } = options;
11
11
  this.min = getOptionalTime(min);
12
12
  this.max = getOptionalTime(max);
13
13
  this.step = step;
package/util/assert.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /** Assert a boolean condition is true. */
2
- export declare function assert(condition: unknown, ...received: unknown[]): asserts condition;
2
+ export declare function assert(condition: unknown, ...receivedExpected: [received?: unknown, expected?: unknown]): asserts condition;
3
3
  /** Assert two values are equal. */
4
4
  export declare function assertEqual<T>(left: T | unknown, right: T): asserts left is T;
5
5
  /** Assert two values are equal. */
package/util/assert.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { AssertionError } from "../error/AssertionError.js";
2
2
  /** Assert a boolean condition is true. */
3
- export function assert(condition, ...received) {
3
+ export function assert(condition, ...receivedExpected) {
4
4
  if (!condition)
5
- throw new AssertionError(`Must assert`, ...received);
5
+ throw new AssertionError(`Must assert`, ...receivedExpected);
6
6
  }
7
7
  /** Assert two values are equal. */
8
8
  export function assertEqual(left, right) {
package/util/debug.d.ts CHANGED
@@ -14,3 +14,5 @@ export declare function debugSet(value: ImmutableSet, depth?: number): string;
14
14
  export declare function debugMap(value: ImmutableMap, depth?: number): string;
15
15
  /** Debug an object. */
16
16
  export declare function debugObject(value: object, depth?: number): string;
17
+ /** If a string is multiline, push it onto the next line and prepend a tab to each line.. */
18
+ export declare function indent(str: string): string;
package/util/debug.js CHANGED
@@ -75,3 +75,8 @@ export function debugObject(value, depth = 1) {
75
75
  : "";
76
76
  return `${name ? `${name} ` : ""}${entries ? `{\n\t${entries}\n}` : "{}"}`;
77
77
  }
78
+ /** If a string is multiline, push it onto the next line and prepend a tab to each line.. */
79
+ export function indent(str) {
80
+ const lines = str.split("\n");
81
+ return lines.length > 1 ? `\n${lines.join("\n\t")}` : ` ${str}`;
82
+ }
@@ -31,6 +31,10 @@ export type ValidatorsType<T> = {
31
31
  };
32
32
  /** Validate an unknown value with a validator. */
33
33
  export declare function validate<T>(unsafeValue: unknown, validator: Validator<T>): T;
34
+ /** Get value that validates against a given `Validator`, or throw `ValidationError` */
35
+ export declare function getValid<T>(unsafeValue: unknown, validator: Validator<T>): T;
36
+ /** Assert that a value validates against a given `Validator`, or throw `ValidationError` */
37
+ export declare function assertValid<T>(unsafeValue: unknown, validator: Validator<T>): asserts unsafeValue is T;
34
38
  /**
35
39
  * Validate an iterable set of items with a validator.
36
40
  *
package/util/validate.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { ValidationError } from "../error/ValidationError.js";
1
2
  import { Feedback } from "../feedback/Feedback.js";
2
3
  import { Feedbacks } from "../feedback/Feedbacks.js";
3
4
  import { getLastItem, isArray } from "./array.js";
@@ -8,6 +9,21 @@ import { isIterable } from "./iterate.js";
8
9
  export function validate(unsafeValue, validator) {
9
10
  return typeof validator === "function" ? validator(unsafeValue) : validator.validate(unsafeValue);
10
11
  }
12
+ /** Get value that validates against a given `Validator`, or throw `ValidationError` */
13
+ export function getValid(unsafeValue, validator) {
14
+ try {
15
+ return validate(unsafeValue, validator);
16
+ }
17
+ catch (thrown) {
18
+ if (thrown instanceof Feedback)
19
+ throw new ValidationError("Must validate", thrown);
20
+ throw thrown;
21
+ }
22
+ }
23
+ /** Assert that a value validates against a given `Validator`, or throw `ValidationError` */
24
+ export function assertValid(unsafeValue, validator) {
25
+ getValid(unsafeValue, validator);
26
+ }
11
27
  /**
12
28
  * Validate an iterable set of items with a validator.
13
29
  *