shelving 1.82.0 → 1.83.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 (91) hide show
  1. package/constraint/Constraints.js +3 -3
  2. package/constraint/FilterConstraint.d.ts +5 -5
  3. package/constraint/SortConstraint.d.ts +2 -2
  4. package/db/Change.d.ts +12 -12
  5. package/db/Collection.d.ts +4 -4
  6. package/db/Database.d.ts +29 -29
  7. package/db/Item.d.ts +4 -4
  8. package/db/Query.d.ts +4 -4
  9. package/feedback/Feedback.d.ts +2 -2
  10. package/feedback/Feedback.js +3 -2
  11. package/firestore/client/FirestoreClientProvider.js +2 -2
  12. package/firestore/lite/FirestoreLiteProvider.js +2 -2
  13. package/firestore/server/FirestoreServerProvider.js +2 -2
  14. package/package.json +1 -1
  15. package/provider/CacheProvider.d.ts +12 -12
  16. package/provider/DebugProvider.d.ts +21 -21
  17. package/provider/MemoryProvider.d.ts +16 -16
  18. package/provider/MemoryProvider.js +3 -3
  19. package/provider/Provider.d.ts +30 -30
  20. package/provider/ThroughProvider.d.ts +23 -23
  21. package/provider/ValidationProvider.d.ts +22 -22
  22. package/provider/ValidationProvider.js +2 -2
  23. package/react/useItem.d.ts +4 -4
  24. package/react/useQuery.d.ts +4 -4
  25. package/schema/AllowSchema.d.ts +25 -24
  26. package/schema/AllowSchema.js +25 -29
  27. package/schema/ArraySchema.d.ts +2 -2
  28. package/schema/BooleanSchema.d.ts +2 -2
  29. package/schema/DataSchema.d.ts +2 -2
  30. package/schema/DataSchema.js +2 -2
  31. package/schema/DateSchema.d.ts +2 -2
  32. package/schema/DictionarySchema.d.ts +19 -0
  33. package/schema/{ObjectSchema.js → DictionarySchema.js} +6 -6
  34. package/schema/LinkSchema.d.ts +2 -2
  35. package/schema/NumberSchema.d.ts +2 -2
  36. package/schema/Schema.d.ts +10 -8
  37. package/schema/Schema.js +1 -1
  38. package/schema/StringSchema.d.ts +12 -10
  39. package/schema/index.d.ts +1 -1
  40. package/schema/index.js +1 -1
  41. package/state/ArrayState.js +4 -4
  42. package/state/DataState.js +3 -3
  43. package/state/DictionaryState.d.ts +15 -0
  44. package/state/{ObjectState.js → DictionaryState.js} +6 -6
  45. package/state/index.d.ts +2 -2
  46. package/state/index.js +2 -2
  47. package/test/basics.js +1 -1
  48. package/update/ArrayUpdate.js +2 -2
  49. package/update/DataUpdate.d.ts +10 -9
  50. package/update/DataUpdate.js +6 -4
  51. package/update/DictionaryUpdate.d.ts +29 -0
  52. package/update/{ObjectUpdate.js → DictionaryUpdate.js} +14 -14
  53. package/update/hydrations.js +2 -2
  54. package/update/index.d.ts +1 -1
  55. package/update/index.js +1 -1
  56. package/util/array.d.ts +40 -111
  57. package/util/array.js +50 -114
  58. package/util/clone.d.ts +2 -2
  59. package/util/clone.js +5 -5
  60. package/util/data.d.ts +20 -53
  61. package/util/data.js +11 -1
  62. package/util/dictionary.d.ts +39 -0
  63. package/util/dictionary.js +33 -0
  64. package/util/diff.d.ts +3 -3
  65. package/util/entry.d.ts +7 -5
  66. package/util/entry.js +8 -6
  67. package/util/filter.d.ts +0 -5
  68. package/util/filter.js +0 -3
  69. package/util/hydrate.d.ts +2 -2
  70. package/util/hydrate.js +7 -8
  71. package/util/index.d.ts +1 -0
  72. package/util/index.js +1 -0
  73. package/util/map.d.ts +28 -6
  74. package/util/map.js +22 -6
  75. package/util/merge.d.ts +3 -6
  76. package/util/merge.js +4 -6
  77. package/util/object.d.ts +77 -90
  78. package/util/object.js +23 -76
  79. package/util/set.d.ts +10 -0
  80. package/util/set.js +17 -0
  81. package/util/template.d.ts +3 -3
  82. package/util/template.js +3 -3
  83. package/util/transform.d.ts +22 -45
  84. package/util/transform.js +20 -37
  85. package/util/units.d.ts +6 -12
  86. package/util/units.js +8 -4
  87. package/util/validate.d.ts +6 -5
  88. package/util/validate.js +5 -4
  89. package/schema/ObjectSchema.d.ts +0 -19
  90. package/state/ObjectState.d.ts +0 -16
  91. package/update/ObjectUpdate.d.ts +0 -29
package/util/object.js CHANGED
@@ -1,16 +1,13 @@
1
1
  import { AssertionError } from "../error/AssertionError.js";
2
- /**
3
- * Is a value an unknown object?
4
- * - This is a TypeScript assertion object that asserts the value extends `ImmutableObject`
5
- * - Note: Arrays and other complex objects will return true.
6
- */
2
+ import { isIterable } from "./iterate.js";
3
+ /** Is an unknown value an unknown object? */
7
4
  export const isObject = (value) => typeof value === "object" && value !== null;
8
5
  /** Assert that a value is an object */
9
6
  export function assertObject(value) {
10
7
  if (!isObject(value))
11
8
  throw new AssertionError(`Must be object`, value);
12
9
  }
13
- /** Is a value a plain object? */
10
+ /** is an unknown value an unknown plain object? */
14
11
  export function isPlainObject(value) {
15
12
  if (isObject(value)) {
16
13
  const proto = Object.getPrototypeOf(value);
@@ -18,107 +15,57 @@ export function isPlainObject(value) {
18
15
  }
19
16
  return false;
20
17
  }
21
- /** Assert that a value is a plain object */
18
+ /** Assert that a value is an object */
22
19
  export function assertPlainObject(value) {
23
20
  if (!isPlainObject(value))
24
21
  throw new AssertionError(`Must be plain object`, value);
25
22
  }
26
- /** Is an unknown string an own prop of an object. */
27
- export const isProp = (obj, key) => (typeof key === "string" || typeof key === "number" || typeof key === "symbol") && Object.prototype.hasOwnProperty.call(obj, key);
28
- export function getProps(data) {
29
- return Object.entries(data);
23
+ /** Is an unknown value the key for an own prop of an object. */
24
+ export const isProp = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
25
+ export function getProps(obj) {
26
+ return isIterable(obj) ? obj : Object.entries(obj);
30
27
  }
31
28
  export function getProp(data, k1, k2, k3, k4) {
32
29
  return k2 === undefined ? data[k1] : k3 === undefined ? data[k1][k2] : k4 === undefined ? data[k1][k2][k3] : data[k1][k2][k3][k4];
33
30
  }
34
- /**
35
- * Set a prop on an object (immutably).
36
- *
37
- * @param input The input data object.
38
- * @param key The key of the entry to add.
39
- * @param value The value of the entry to add. If set, the entry will only be added if its current value is not `value`
40
- *
41
- * @return New object without the specified prop (or same object if prop value didn't change).
42
- */
31
+ /** Set a prop on an object (immutably) and return a new object including that prop. */
43
32
  export function withProp(input, key, value) {
44
33
  return input[key] === value ? input : { ...input, [key]: value };
45
34
  }
46
- /**
47
- * Set several props on an object (immutably).
48
- *
49
- * @param input The input data object.
50
- * @param props Set of props to add to the object.
51
- * @return New object with the specified prop added (or same object if no props changed).
52
- */
35
+ /** Set several props on an object (immutably) and return a new object including those props. */
53
36
  export function withProps(input, props) {
54
- for (const [k, v] of Object.entries(props))
37
+ for (const [k, v] of getProps(props))
55
38
  if (input[k] !== v)
56
39
  return { ...input, ...props };
57
40
  return input;
58
41
  }
59
- /**
60
- * Remove several key/value entries from an object (immutably).
61
- *
62
- * @param input The input object.
63
- * @param keys Set of keys for props to remove.
64
- *
65
- * @return New object without the specified entries (or same object if none of the entries existed).
66
- */
67
- export function withoutProps(input, ...keys) {
42
+ export function omitProps(input, ...keys) {
68
43
  for (const key of keys)
69
44
  if (key in input)
70
- return Object.fromEntries(Object.entries(input).filter(_doesntHaveKey, keys));
45
+ return Object.fromEntries(Object.entries(input).filter(_hasntKey, keys));
71
46
  return input;
72
47
  }
73
- function _doesntHaveKey([key]) {
48
+ function _hasntKey([key]) {
74
49
  return !this.includes(key);
75
50
  }
76
- /**
77
- * Pick several props from an object (immutably).
78
- *
79
- * @param input The input object.
80
- * @param keys Set of keys for props to pick.
81
- *
82
- * @return New object with only the specified props.
83
- */
84
51
  export function pickProps(input, ...keys) {
85
- return Object.fromEntries(Object.entries(input).filter(_doesHaveKey, keys));
52
+ return Object.fromEntries(Object.entries(input).filter(_hasKey, keys));
86
53
  }
87
- function _doesHaveKey([key]) {
54
+ function _hasKey([key]) {
88
55
  return this.includes(key);
89
56
  }
90
- /**
91
- * Set a single named prop on an object (by reference).
92
- *
93
- * @param data The target data object to modify.
94
- * @param key The key of the prop in the object to set.
95
- * @param value The value to set the prop to.
96
- */
97
- export function setProp(data, key, value) {
98
- data[key] = value;
57
+ /** Set a single named prop on an object (by reference) and return its value. */
58
+ export function setProp(obj, key, value) {
59
+ obj[key] = value;
99
60
  return value;
100
61
  }
101
- /**
102
- * Set several named props on an object (by reference).
103
- *
104
- * @param obj The target object to modify.
105
- * @param props An object containing new props to set on the object.
106
- */
107
- export function setProps(obj, props) {
108
- for (const [k, v] of getProps(props))
62
+ /** Set several named props on an object (by reference). */
63
+ export function setProps(obj, entries) {
64
+ for (const [k, v] of getProps(entries))
109
65
  obj[k] = v;
110
66
  }
111
- /**
112
- * Remove several key/value entries from an object (by reference).
113
- *
114
- * @param obj The target object to modify.
115
- * @param keys Set of keys or keys to remove.
116
- */
67
+ /** Remove several key/value entries from an object (by reference). */
117
68
  export function deleteProps(obj, ...keys) {
118
69
  for (const key of keys)
119
70
  delete obj[key];
120
71
  }
121
- /** An empty object. */
122
- export const EMPTY_OBJECT = {};
123
- /** Function that returns an an empty object. */
124
- export const getEmptyObject = () => EMPTY_OBJECT;
package/util/set.d.ts CHANGED
@@ -4,11 +4,21 @@ export declare type ImmutableSet<T = unknown> = ReadonlySet<T>;
4
4
  export declare type MutableSet<T = unknown> = Set<T>;
5
5
  /** Things that can be converted to sets. */
6
6
  export declare type PossibleSet<T> = ImmutableSet<T> | Iterable<T>;
7
+ /** Get the type of the _items_ in a set. */
8
+ export declare type SetItem<X> = X extends ReadonlySet<infer Y> ? Y : never;
7
9
  /** Is an unknown value a set? */
8
10
  export declare const isSet: <T extends ImmutableSet<unknown>>(v: unknown) => v is T;
11
+ /** Is an unknown value an item in a set? */
12
+ export declare const isSetItem: <T>(set: ImmutableSet<T>, item: unknown) => item is T;
9
13
  /** Assert that a value is a `Set` instance. */
10
14
  export declare function assertSet<T extends ImmutableSet>(v: T | unknown): asserts v is T;
11
15
  /** Convert an iterable to a `Set` (if it's already a `Set` it passes through unchanged). */
12
16
  export declare function getSet<T>(iterable: PossibleSet<T>): ImmutableSet<T>;
17
+ /** Add an item to a set (by reference) and return the set item. */
18
+ export declare function addSetItem<T>(set: MutableSet<T>, item: T): T;
19
+ /** Add multiple items to a set (by reference). */
20
+ export declare function addSetItems<T>(set: MutableSet<T>, ...items: T[]): void;
21
+ /** Remove multiple items from a set (by reference). */
22
+ export declare function removeSetItems<T>(set: MutableSet<T>, ...items: T[]): void;
13
23
  /** Apply a limit to a set. */
14
24
  export declare function limitSet<T>(set: ImmutableSet<T>, limit: number): ImmutableSet<T>;
package/util/set.js CHANGED
@@ -2,6 +2,8 @@ import { AssertionError } from "../error/AssertionError.js";
2
2
  import { limitItems } from "./iterate.js";
3
3
  /** Is an unknown value a set? */
4
4
  export const isSet = (v) => v instanceof Set;
5
+ /** Is an unknown value an item in a set? */
6
+ export const isSetItem = (set, item) => set.has(item);
5
7
  /** Assert that a value is a `Set` instance. */
6
8
  export function assertSet(v) {
7
9
  if (!isSet(v))
@@ -11,6 +13,21 @@ export function assertSet(v) {
11
13
  export function getSet(iterable) {
12
14
  return isSet(iterable) ? iterable : new Set(iterable);
13
15
  }
16
+ /** Add an item to a set (by reference) and return the set item. */
17
+ export function addSetItem(set, item) {
18
+ set.add(item);
19
+ return item;
20
+ }
21
+ /** Add multiple items to a set (by reference). */
22
+ export function addSetItems(set, ...items) {
23
+ for (const item of items)
24
+ set.add(item);
25
+ }
26
+ /** Remove multiple items from a set (by reference). */
27
+ export function removeSetItems(set, ...items) {
28
+ for (const item of items)
29
+ set.delete(item);
30
+ }
14
31
  /** Apply a limit to a set. */
15
32
  export function limitSet(set, limit) {
16
33
  return limit > set.size ? set : new Set(limitItems(set, limit));
@@ -1,7 +1,7 @@
1
1
  import type { NotString } from "./string.js";
2
- import { ImmutableObject } from "./object.js";
2
+ import type { ImmutableDictionary } from "./dictionary.js";
3
3
  /** Template values in `{ placeholder: value }` format. */
4
- declare type TemplateValues = ImmutableObject<string>;
4
+ declare type TemplateValues = ImmutableDictionary<string>;
5
5
  /** Things that can be converted to the value for a named placeholder. */
6
6
  declare type PlaceholderValues = string | ((name: string) => string) | string[] | TemplateValues;
7
7
  /**
@@ -29,7 +29,7 @@ export declare function matchTemplates(templates: Iterable<string> & NotString,
29
29
  * Turn ":year-:month" and `{ year: "2016"... }` etc into "2016-06..." etc.
30
30
  *
31
31
  * @param template The template including template placeholders, e.g. `:name-${country}/{city}`
32
- * @param values An object containing values, e.g. `{ name: "Dave", country: "UK", city: "Manchester" }` (functions are called, everything else converted to string), or a function or string to use for all placeholders.
32
+ * @param value An object containing values, e.g. `{ name: "Dave", country: "UK", city: "Manchester" }` (functions are called, everything else converted to string), or a function or string to use for all placeholders.
33
33
  * @return The rendered string, e.g. `Dave-UK/Manchester`
34
34
  *
35
35
  * @throws {ReferenceError} If a placeholder in the template string is not specified in values.
package/util/template.js CHANGED
@@ -26,7 +26,7 @@ const _split = (template) => {
26
26
  const placeholder = matches[i];
27
27
  const post = matches[i + 1];
28
28
  if (i > 1 && !pre.length)
29
- throw new SyntaxError("shelving/template: Placeholders must be separated by at least one character");
29
+ throw new SyntaxError("Placeholders must be separated by at least one character");
30
30
  const name = placeholder === "*" ? String(asterisks++) : ((_a = R_NAME.exec(placeholder)) === null || _a === void 0 ? void 0 : _a[0]) || "";
31
31
  chunks.push({ pre, placeholder, name, post });
32
32
  }
@@ -90,7 +90,7 @@ export function matchTemplates(templates, target) {
90
90
  * Turn ":year-:month" and `{ year: "2016"... }` etc into "2016-06..." etc.
91
91
  *
92
92
  * @param template The template including template placeholders, e.g. `:name-${country}/{city}`
93
- * @param values An object containing values, e.g. `{ name: "Dave", country: "UK", city: "Manchester" }` (functions are called, everything else converted to string), or a function or string to use for all placeholders.
93
+ * @param value An object containing values, e.g. `{ name: "Dave", country: "UK", city: "Manchester" }` (functions are called, everything else converted to string), or a function or string to use for all placeholders.
94
94
  * @return The rendered string, e.g. `Dave-UK/Manchester`
95
95
  *
96
96
  * @throws {ReferenceError} If a placeholder in the template string is not specified in values.
@@ -114,5 +114,5 @@ const _replace = (name, value) => {
114
114
  if (typeof v === "string")
115
115
  return v;
116
116
  }
117
- throw new ReferenceError(`renderTemplate(): values.${name}: Must be defined`);
117
+ throw new ReferenceError(`Template "value.${name}" must be defined`);
118
118
  };
@@ -1,7 +1,7 @@
1
- import type { ArrayType, ImmutableArray } from "./array.js";
2
- import type { Data, Prop, Value } from "./data.js";
3
- import { Entry } from "./entry.js";
4
- import { ImmutableObject } from "./object.js";
1
+ import type { ArrayItem, ImmutableArray } from "./array.js";
2
+ import type { Entry } from "./entry.js";
3
+ import { ImmutableObject, ObjectValue } from "./object.js";
4
+ import { ImmutableDictionary } from "./dictionary.js";
5
5
  /** Object that transforms an input value into an output value with its `transform()` method. */
6
6
  export interface Transformable<I, O> {
7
7
  transform(input: I): O;
@@ -12,49 +12,26 @@ export declare const isTransformable: <T extends Transformable<unknown, unknown>
12
12
  export declare type Transform<I, O> = (input: I) => O;
13
13
  /** Something that can transform an input value into an output value (or a plain value). */
14
14
  export declare type Transformer<I, O> = Transformable<I, O> | Transform<I, O> | O;
15
- /** Transform a value using a transform. */
15
+ /** Transform a value using a transformer. */
16
16
  export declare function transform<I, O>(input: I, transformer: (v: I) => O): O;
17
17
  export declare function transform<I, O>(input: I, transformer: Transformer<I, O>): O;
18
+ /** Modify a set of items using a transformer. */
19
+ export declare function mapItems<I, O>(items: Iterable<I>, transformer: Transformer<I, O>): Iterable<O>;
20
+ /** Modify the items of an array using a transformer. */
21
+ export declare function mapArray<T extends ImmutableArray>(arr: T, transformer: Transformer<ArrayItem<T>, ArrayItem<T>>): T;
22
+ export declare function mapArray<I, O>(arr: Iterable<I>, transformer: Transformer<I, O>): ImmutableArray<O>;
23
+ /** Modify the values of the props of an object using a transformer. */
24
+ export declare function mapObject<T extends ImmutableObject>(obj: T, transformer: Transformer<ObjectValue<T>, ObjectValue<T>>): T;
25
+ export declare function mapObject<I extends ImmutableObject, O extends ImmutableObject>(obj: I, transformer: Transformer<ObjectValue<I>, ObjectValue<O>>): O;
26
+ /** Modify the values of a dictionary using a transformer. */
27
+ export declare const mapDictionary: <I, O>(dictionary: ImmutableDictionary<I>, transformer: Transformer<I, O>) => ImmutableDictionary<O>;
28
+ /** Modify the values of a set of entries using a transformer. */
29
+ export declare function mapEntries<K, I, O>(entries: Iterable<Entry<K, I>>, transformer: Transformer<I, O>): Iterable<Entry<K, O>>;
18
30
  /** Set of named transformers for a data object. */
19
- export declare type Transformers<T extends Data> = {
31
+ export declare type Transformers<T extends ImmutableObject> = {
20
32
  readonly [K in keyof T]?: Transformer<T[K], T[K]>;
21
33
  };
22
- /**
23
- * Transform the props of a data object using a set of named transformers.
24
- * @returns New object with changed props.
25
- */
26
- export declare function transformData<T extends Data>(data: T, transforms: Transformers<T>): T;
27
- /**
28
- * Transform the props of a data object using a set of named transformers.
29
- * @yield Transformed prop entries after calling the corresponding transformer.
30
- */
31
- export declare function transformProps<T extends Data>(obj: T, transforms: Transformers<T>): Iterable<Prop<T>>;
32
- /**
33
- * Transform the _values_ of an iterable set of entries using a transformer.
34
- * @yield Transformed entry after calling transforming the new value for each entry.
35
- */
36
- export declare function mapEntries<K, I, O>(entries: Iterable<Entry<K, I>>, transformer: Transformer<I, O>): Iterable<Entry<K, O>>;
37
- /**
38
- * Transform the _values_ of a map-like object using a transformer.
39
- * @return New object after transforming its entries.
40
- */
41
- export declare function mapObject<I, O>(obj: ImmutableObject<I>, transformer: Transformer<I, O>): ImmutableObject<O>;
42
- /**
43
- * Transform the _values_ of an data object using a transformer.
44
- * @return New object after transforming its entries.
45
- */
46
- export declare function mapData<T extends Data>(data: T, transformer: Transformer<Value<T>, Value<T>>): T;
47
- export declare function mapData<I extends Data, O extends {
48
- [K in keyof I]: unknown;
49
- }>(data: I, transformer: Transformer<Value<I>, Value<O>>): O;
50
- /**
51
- * Map an iterable set of items using a transformer.
52
- * @yield Transformed items after calling `transformer()` on each.
53
- */
54
- export declare function mapItems<I, O>(items: Iterable<I>, transformer: Transformer<I, O>): Iterable<O>;
55
- /**
56
- * Apply a transformer to each item in an array and return the transformed array.
57
- * @return The transformed array.
58
- */
59
- export declare function mapArray<T extends ImmutableArray>(arr: T, transformer: Transformer<ArrayType<T>, ArrayType<T>>): T;
60
- export declare function mapArray<I, O>(arr: Iterable<I>, transformer: Transformer<I, O>): ImmutableArray<O>;
34
+ /** Transform an object using a set of named transformers. */
35
+ export declare function transformObject<T extends ImmutableObject>(obj: T, transforms: Transformers<T>): T;
36
+ /** Transform a dictionary object using a set of named transformers. */
37
+ export declare const transformDictionary: <T>(dict: ImmutableDictionary<T>, transforms: Transformers<ImmutableDictionary<T>>) => ImmutableDictionary<T>;
package/util/transform.js CHANGED
@@ -1,52 +1,35 @@
1
1
  import { isFunction } from "./function.js";
2
- import { getEntries } from "./entry.js";
3
2
  import { getProps, isObject } from "./object.js";
4
3
  /** Is an unknown value a transformable. */
5
4
  export const isTransformable = (v) => isObject(v) && typeof v.transform === "function";
6
5
  export function transform(input, transformer) {
7
6
  return isFunction(transformer) ? transformer(input) : isTransformable(transformer) ? transformer.transform(input) : transformer;
8
7
  }
9
- /**
10
- * Transform the props of a data object using a set of named transformers.
11
- * @returns New object with changed props.
12
- */
13
- export function transformData(data, transforms) {
14
- return { ...data, ...Object.fromEntries(transformProps(data, transforms)) };
8
+ /** Modify a set of items using a transformer. */
9
+ export function* mapItems(items, transformer) {
10
+ for (const item of items)
11
+ yield transform(item, transformer);
15
12
  }
16
- /**
17
- * Transform the props of a data object using a set of named transformers.
18
- * @yield Transformed prop entries after calling the corresponding transformer.
19
- */
20
- export function* transformProps(obj, transforms) {
21
- for (const [k, v] of getProps(transforms))
22
- yield [k, transform(obj[k], v)];
13
+ export function mapArray(arr, transformer) {
14
+ return Array.from(mapItems(arr, transformer));
23
15
  }
24
- /**
25
- * Transform the _values_ of an iterable set of entries using a transformer.
26
- * @yield Transformed entry after calling transforming the new value for each entry.
27
- */
16
+ export function mapObject(obj, transformer) {
17
+ return Object.fromEntries(mapEntries(getProps(obj), transformer));
18
+ }
19
+ /** Modify the values of a dictionary using a transformer. */
20
+ export const mapDictionary = mapObject;
21
+ /** Modify the values of a set of entries using a transformer. */
28
22
  export function* mapEntries(entries, transformer) {
29
23
  for (const [k, v] of entries)
30
24
  yield [k, transform(v, transformer)];
31
25
  }
32
- /**
33
- * Transform the _values_ of a map-like object using a transformer.
34
- * @return New object after transforming its entries.
35
- */
36
- export function mapObject(obj, transformer) {
37
- return Object.fromEntries(mapEntries(getEntries(obj), transformer));
26
+ /** Transform an object using a set of named transformers. */
27
+ export function transformObject(obj, transforms) {
28
+ return { ...obj, ...Object.fromEntries(_transformObjectProps(obj, transforms)) };
38
29
  }
39
- export function mapData(data, transformer) {
40
- return mapObject(data, transformer);
41
- }
42
- /**
43
- * Map an iterable set of items using a transformer.
44
- * @yield Transformed items after calling `transformer()` on each.
45
- */
46
- export function* mapItems(items, transformer) {
47
- for (const item of items)
48
- yield transform(item, transformer);
49
- }
50
- export function mapArray(arr, transformer) {
51
- return Array.from(mapItems(arr, transformer));
30
+ function* _transformObjectProps(obj, transforms) {
31
+ for (const [k, v] of getProps(transforms))
32
+ yield [k, transform(obj[k], v)];
52
33
  }
34
+ /** Transform a dictionary object using a set of named transformers. */
35
+ export const transformDictionary = transformObject;
package/util/units.d.ts CHANGED
@@ -1,5 +1,6 @@
1
+ import { ImmutableObject } from "./object.js";
1
2
  import { PossibleDate } from "./date.js";
2
- import { MapKey, RequiredMap } from "./map.js";
3
+ import { MapKey, ImmutableRequiredMap } from "./map.js";
3
4
  /** Conversion from one unit to another (either a number to multiple by, or a function to convert). */
4
5
  declare type Conversion = number | ((num: number) => number);
5
6
  /** Set of possible conversions for a set of items. */
@@ -29,6 +30,8 @@ export declare class Unit<T extends string> {
29
30
  readonly singular: string;
30
31
  /** Plural name for this unit, e.g. `kilometers` (defaults to `singular` + "s"). */
31
32
  readonly plural: string;
33
+ /** Title for this unit (uses format `abbr (plural)`, e.g. `fl oz (US fluid ounces)`) */
34
+ get title(): string;
32
35
  constructor(
33
36
  /** `UnitList` this unit belongs to. */
34
37
  list: UnitList<T>,
@@ -50,18 +53,9 @@ export declare class Unit<T extends string> {
50
53
  formatFull(amount: number, maxPrecision?: number, minPrecision?: number): string;
51
54
  }
52
55
  /** Represent a list of units. */
53
- export declare class UnitList<T extends string> extends RequiredMap<T, Unit<T>> {
56
+ export declare class UnitList<T extends string> extends ImmutableRequiredMap<T, Unit<T>> {
54
57
  readonly base: Unit<T>;
55
- constructor(units: {
56
- [K in T]: UnitProps<T>;
57
- });
58
- }
59
- export interface UnitList<T extends string> {
60
- (units: {
61
- [K in T]: UnitProps<T>;
62
- }): UnitList<T>;
63
- set: never;
64
- delete: never;
58
+ constructor(units: ImmutableObject<T, UnitProps<T>>);
65
59
  }
66
60
  /** Percentage units. */
67
61
  export declare const PERCENTAGE_UNITS: UnitList<"percent">;
package/util/units.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { ConditionError } from "../error/ConditionError.js";
2
2
  import { DAY, HOUR, MILLION, MINUTE, MONTH, NNBSP, SECOND, WEEK, YEAR } from "./constants.js";
3
+ import { getProps } from "./object.js";
3
4
  import { getDuration } from "./date.js";
4
- import { RequiredMap } from "./map.js";
5
+ import { ImmutableRequiredMap } from "./map.js";
5
6
  import { formatFullQuantity, formatQuantity, getPercent } from "./number.js";
6
- import { getProps } from "./object.js";
7
7
  /** Convert an amount using a `Conversion. */
8
8
  const _convert = (amount, conversion) => (typeof conversion === "function" ? conversion(amount) : conversion === 1 ? amount : amount * conversion);
9
9
  /** Represent a unit. */
@@ -22,6 +22,10 @@ export class Unit {
22
22
  this.plural = plural;
23
23
  this._to = to;
24
24
  }
25
+ /** Title for this unit (uses format `abbr (plural)`, e.g. `fl oz (US fluid ounces)`) */
26
+ get title() {
27
+ return `${this.abbr} (${this.plural})`;
28
+ }
25
29
  /** Convert an amount from this unit to another unit. */
26
30
  to(amount, ref = this.list.base) {
27
31
  return this._toUnit(amount, this._unit(ref));
@@ -66,14 +70,14 @@ export class Unit {
66
70
  }
67
71
  }
68
72
  /** Represent a list of units. */
69
- export class UnitList extends RequiredMap {
73
+ export class UnitList extends ImmutableRequiredMap {
70
74
  constructor(units) {
71
75
  super();
72
76
  for (const [ref, props] of getProps(units)) {
73
77
  const unit = new Unit(this, ref, props);
74
78
  if (!this.base)
75
79
  this.base = unit;
76
- super.set(ref, unit);
80
+ Map.prototype.set.call(this, ref, unit);
77
81
  }
78
82
  }
79
83
  }
@@ -1,6 +1,6 @@
1
1
  import type { Entry } from "./entry.js";
2
- import type { Data, Prop } from "./data.js";
3
- import { ImmutableObject } from "./object.js";
2
+ import type { ImmutableDictionary } from "./dictionary.js";
3
+ import { Data, DataProp } from "./data.js";
4
4
  import { ImmutableArray } from "./array.js";
5
5
  /** Object that can validate an unknown value with its `validate()` method. */
6
6
  export interface Validatable<T> {
@@ -57,19 +57,20 @@ export declare function validateItems<T>(unsafeItems: Iterable<unknown>, validat
57
57
  */
58
58
  export declare function validateEntries<T>(unsafeValues: Iterable<Entry<string, unknown>>, validator: Validator<T>): Iterable<Entry<string, T>>;
59
59
  /**
60
- * Validate a map-like object.
60
+ * Validate the values of the entries in a dictionary object.
61
61
  *
62
62
  * @throw InvalidFeedback if one or more entry values did not validate.
63
63
  * - `feedback.details` will contain an entry for each invalid item (keyed by their count in the input iterable).
64
64
  */
65
- export declare function validateObject<T>(obj: ImmutableObject<T>, validator: Validator<T>): ImmutableObject<T>;
65
+ export declare function validateDictionary<T>(obj: ImmutableDictionary<T>, validator: Validator<T>): ImmutableDictionary<T>;
66
66
  /**
67
67
  * Validate the props of a data object with a set of validators.
68
+ *
68
69
  * @yield Valid props for the data object.
69
70
  * @throw InvalidFeedback if one or more props did not validate.
70
71
  * - `feedback.details` will contain an entry for each invalid item (keyed by their count in the input iterable).
71
72
  */
72
- export declare function validateProps<T extends Data>(unsafeData: Data, validators: Validators<T>): Iterable<Prop<T>>;
73
+ export declare function validateProps<T extends Data>(unsafeData: Data, validators: Validators<T>): Iterable<DataProp<T>>;
73
74
  /**
74
75
  * Validate a data object with a set of validators.
75
76
  * - Defined props in the object will be validated against the corresponding validator.
package/util/validate.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { isFeedback } from "../feedback/Feedback.js";
2
2
  import { InvalidFeedback } from "../feedback/InvalidFeedback.js";
3
- import { getProps } from "./object.js";
3
+ import { getDataProps } from "./data.js";
4
4
  import { getArray } from "./array.js";
5
5
  /** Validate an unknown value with a validator. */
6
6
  export function validate(unsafeValue, validator) {
@@ -63,23 +63,24 @@ export function* validateEntries(unsafeValues, validator) {
63
63
  throw new InvalidFeedback("Invalid entries", feedbacks);
64
64
  }
65
65
  /**
66
- * Validate a map-like object.
66
+ * Validate the values of the entries in a dictionary object.
67
67
  *
68
68
  * @throw InvalidFeedback if one or more entry values did not validate.
69
69
  * - `feedback.details` will contain an entry for each invalid item (keyed by their count in the input iterable).
70
70
  */
71
- export function validateObject(obj, validator) {
71
+ export function validateDictionary(obj, validator) {
72
72
  return Object.fromEntries(validateEntries(Object.entries(obj), validator));
73
73
  }
74
74
  /**
75
75
  * Validate the props of a data object with a set of validators.
76
+ *
76
77
  * @yield Valid props for the data object.
77
78
  * @throw InvalidFeedback if one or more props did not validate.
78
79
  * - `feedback.details` will contain an entry for each invalid item (keyed by their count in the input iterable).
79
80
  */
80
81
  export function* validateProps(unsafeData, validators) {
81
82
  const feedbacks = new Map();
82
- for (const [key, validator] of getProps(validators)) {
83
+ for (const [key, validator] of getDataProps(validators)) {
83
84
  try {
84
85
  yield [key, validate(unsafeData[key], validator)];
85
86
  }
@@ -1,19 +0,0 @@
1
- import { ImmutableObject } from "../util/object.js";
2
- import { Validator } from "../util/validate.js";
3
- import { Schema } from "./Schema.js";
4
- /** Validate a map-like object (whose props are all the same). */
5
- export declare class ObjectSchema<T> extends Schema<ImmutableObject<T>> {
6
- readonly value: ImmutableObject;
7
- readonly items: Validator<T>;
8
- readonly min: number | null;
9
- readonly max: number | null;
10
- constructor({ value, items, min, max, ...rest }: ConstructorParameters<typeof Schema>[0] & {
11
- readonly items: Validator<T>;
12
- readonly value?: ImmutableObject;
13
- readonly min?: number | null;
14
- readonly max?: number | null;
15
- });
16
- validate(unsafeValue?: unknown): ImmutableObject<T>;
17
- }
18
- /** Valid map-like object with specifed items. */
19
- export declare const OBJECT: <T>(items: Validator<T>) => ObjectSchema<T>;
@@ -1,16 +0,0 @@
1
- import type { Entry } from "../util/entry.js";
2
- import { ImmutableObject } from "../util/object.js";
3
- import { Transformers } from "../util/transform.js";
4
- import { State } from "./State.js";
5
- /** State that stores a map-like object and has additional methods to help with that. */
6
- export declare class ObjectState<T> extends State<ImmutableObject<T>> implements Iterable<Entry<string, T>> {
7
- constructor(initial?: ImmutableObject<T>);
8
- /** Get the length of the current value of this state. */
9
- get count(): number;
10
- /** Set a named entry in this object with a different value. */
11
- update(updates: Transformers<ImmutableObject<T>>): void;
12
- /** Remove a named entry from this object. */
13
- delete(...keys: string[]): void;
14
- /** Iterate over the entries of the object. */
15
- [Symbol.iterator](): Iterator<Entry<string, T>>;
16
- }
@@ -1,29 +0,0 @@
1
- import type { Entry } from "../util/entry.js";
2
- import { Nullish } from "../util/null.js";
3
- import { ImmutableObject } from "../util/object.js";
4
- import { Validator } from "../util/validate.js";
5
- import { Update } from "./Update.js";
6
- import { Delete } from "./Delete.js";
7
- /** Set of named transforms for the entries of a map-like object. */
8
- export declare type EntryUpdates<T> = ImmutableObject<T | Update<T> | Delete>;
9
- /** Update that can be applied to a map-like object to add/remove/update its entries. */
10
- export declare class ObjectUpdate<T> extends Update<ImmutableObject<T>> implements Iterable<Entry<string, T | Update<T> | Delete>> {
11
- /** Return an object update with a specific entry marked for update. */
12
- static with<X>(key: Nullish<string>, value: X | Update<X> | Delete): ObjectUpdate<X>;
13
- /** Return an object update with a specific entry marked for deletion. */
14
- static without<X>(key: Nullish<string>): ObjectUpdate<X>;
15
- readonly updates: EntryUpdates<T>;
16
- constructor(updates?: EntryUpdates<T>);
17
- transform(obj?: ImmutableObject<T>): ImmutableObject<T>;
18
- validate(validator: Validator<ImmutableObject<T>>): this;
19
- /** Return an object update with a specific entry marked for update. */
20
- with(key: Nullish<string>, value: T | Update<T>): this;
21
- /** Return an object update with a specific entry marked for deletion. */
22
- without(key: Nullish<string>): this;
23
- /**
24
- * Iterate over the changes in this object.
25
- * - Updates are yielded first, then deletes.
26
- * - Entries whose value is `undefined` indicate deletion.
27
- */
28
- [Symbol.iterator](): Iterator<Entry<string, T | Update<T> | Delete>, void>;
29
- }