utilful 3.0.1 → 3.0.2

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/README.md CHANGED
@@ -113,12 +113,12 @@ interface CSVParseOptions {
113
113
  /** @default ',' */
114
114
  delimiter?: string
115
115
  /**
116
- * Trim whitespace from unquoted headers and values.
116
+ * Whether to trim whitespace from unquoted headers and values.
117
117
  * @default false
118
118
  */
119
119
  trim?: boolean
120
120
  /**
121
- * Throw if a row's field count does not match the header row.
121
+ * Whether to throw if a row's field count does not match the header row.
122
122
  * @default true
123
123
  */
124
124
  strict?: boolean
package/dist/array.d.mts CHANGED
@@ -1,11 +1,5 @@
1
1
  //#region src/array.d.ts
2
- /**
3
- * Represents a value that can be either a single value or an array of values.
4
- */
5
2
  type MaybeArray<T> = T | T[];
6
- /**
7
- * Converts `MaybeArray<T>` to `Array<T>`.
8
- */
9
3
  declare function toArray<T>(array?: MaybeArray<T> | null | undefined): T[];
10
4
  //#endregion
11
5
  export { MaybeArray, toArray };
package/dist/array.mjs CHANGED
@@ -1,7 +1,4 @@
1
1
  //#region src/array.ts
2
- /**
3
- * Converts `MaybeArray<T>` to `Array<T>`.
4
- */
5
2
  function toArray(array) {
6
3
  array ??= [];
7
4
  return Array.isArray(array) ? array : [array];
package/dist/csv.d.mts CHANGED
@@ -1,11 +1,5 @@
1
1
  //#region src/csv.d.ts
2
- /**
3
- * Represents a row in a CSV file with column names of type T.
4
- */
5
2
  type CSVRow<T extends string = string> = Record<T, string>;
6
- /**
7
- * Options for the CSV creation functions.
8
- */
9
3
  interface CSVCreateOptions {
10
4
  /** @default ',' */
11
5
  delimiter?: string;
@@ -16,19 +10,16 @@ interface CSVCreateOptions {
16
10
  /** @default '\n' */
17
11
  lineEnding?: string;
18
12
  }
19
- /**
20
- * Options for the CSV parsing functions.
21
- */
22
13
  interface CSVParseOptions {
23
14
  /** @default ',' */
24
15
  delimiter?: string;
25
16
  /**
26
- * Trim whitespace from unquoted headers and values.
17
+ * Whether to trim whitespace from unquoted headers and values.
27
18
  * @default false
28
19
  */
29
20
  trim?: boolean;
30
21
  /**
31
- * Throw if a row's field count does not match the header row.
22
+ * Whether to throw if a row's field count does not match the header row.
32
23
  * @default true
33
24
  */
34
25
  strict?: boolean;
@@ -132,10 +123,10 @@ declare function escapeCSVValue(value: unknown, options?: {
132
123
  * UTF-8 byte order mark is stripped.
133
124
  *
134
125
  * Parsing tolerances (lenient deviations from RFC 4180):
135
- * - LF, CR, and CRLF line endings are all accepted
136
- * - Whitespace between a closing quote and the next delimiter or line break is ignored
126
+ * - LF, CR, and CRLF line endings are all accepted.
127
+ * - Whitespace between a closing quote and the next delimiter or line break is ignored.
137
128
  * - A field is only treated as quoted if it starts with a quote; quotes inside
138
- * unquoted fields are kept as literal characters
129
+ * unquoted fields are kept as literal characters.
139
130
  *
140
131
  * @example
141
132
  * const csv = `name,age
package/dist/csv.mjs CHANGED
@@ -211,10 +211,10 @@ var CSVParserCore = class {
211
211
  * UTF-8 byte order mark is stripped.
212
212
  *
213
213
  * Parsing tolerances (lenient deviations from RFC 4180):
214
- * - LF, CR, and CRLF line endings are all accepted
215
- * - Whitespace between a closing quote and the next delimiter or line break is ignored
214
+ * - LF, CR, and CRLF line endings are all accepted.
215
+ * - Whitespace between a closing quote and the next delimiter or line break is ignored.
216
216
  * - A field is only treated as quoted if it starts with a quote; quotes inside
217
- * unquoted fields are kept as literal characters
217
+ * unquoted fields are kept as literal characters.
218
218
  *
219
219
  * @example
220
220
  * const csv = `name,age
package/dist/defu.d.mts CHANGED
@@ -1,19 +1,28 @@
1
1
  //#region src/defu.d.ts
2
2
  type PlainObject = Record<PropertyKey, any>;
3
3
  type DefuMerger<T extends PlainObject = PlainObject> = (target: T, key: PropertyKey, value: any, namespace: string) => boolean | void;
4
+ type Nullish = null | undefined | void;
5
+ /**
6
+ * Values that `isPlainObject` rejects at runtime, so the merged type keeps them
7
+ * intact rather than recursing into them. `PlainObject` cannot draw this line
8
+ * itself: its `any` value type makes every object type satisfy it, classes and
9
+ * built-ins included.
10
+ */
11
+ type NonPlainObject = ((...args: any[]) => any) | {
12
+ [Symbol.iterator]: any;
13
+ } | Date | RegExp | Promise<any> | Error | WeakMap<object, any> | WeakSet<object>;
4
14
  /**
5
15
  * Deeply merged result type of a source object over a list of defaults.
6
16
  */
7
17
  type Defu<Source, Defaults extends any[]> = Defaults extends [infer First, ...infer Rest] ? Defu<MergedObject<Source, First>, Rest> : Source;
8
- type MergedObject<Source, Defaults> = Source extends PlainObject ? Defaults extends PlainObject ? { [Key in keyof Source | keyof Defaults]: MergedValue<Key extends keyof Source ? Source[Key] : undefined, Key extends keyof Defaults ? Defaults[Key] : undefined>; } : Source : Source;
9
- type MergedValue<SourceValue, DefaultValue> = SourceValue extends null | undefined ? DefaultValue : SourceValue extends any[] ? DefaultValue extends any[] ? Array<SourceValue[number] | DefaultValue[number]> : SourceValue : SourceValue extends ((...args: any[]) => any) ? SourceValue : SourceValue extends PlainObject ? MergedObject<SourceValue, DefaultValue> : SourceValue;
10
18
  /**
11
- * Defu function type that accepts a source and multiple defaults
19
+ * Source merged over one defaults object, rebuilding only the shared keys.
20
+ * Everything else passes through `Omit`, which is what keeps optionality,
21
+ * `readonly` and the nominal identity of classes intact.
12
22
  */
23
+ type MergedObject<Source, Defaults> = Source extends PlainObject ? Defaults extends PlainObject ? Source extends Defaults ? Source : Omit<Source, keyof Source & keyof Defaults> & Omit<Defaults, keyof Source & keyof Defaults> & { -readonly [Key in keyof Source & keyof Defaults]: MergedValue<Source[Key], Defaults[Key]>; } : Source : Source;
24
+ type MergedValue<SourceValue, DefaultValue> = SourceValue extends Nullish ? DefaultValue : DefaultValue extends Nullish ? SourceValue : SourceValue extends readonly any[] ? DefaultValue extends readonly any[] ? Array<SourceValue[number] | DefaultValue[number]> : SourceValue : SourceValue extends NonPlainObject ? SourceValue : DefaultValue extends NonPlainObject ? SourceValue : MergedObject<SourceValue, DefaultValue>;
13
25
  type DefuFn = <Source extends PlainObject, Defaults extends PlainObject[]>(source: Source, ...defaults: Defaults) => Defu<Source, Defaults>;
14
- /**
15
- * Create a defu function with optional custom merger
16
- */
17
26
  declare function createDefu(merger?: DefuMerger): DefuFn;
18
27
  declare const defu: DefuFn;
19
28
  //#endregion
package/dist/defu.mjs CHANGED
@@ -1,7 +1,4 @@
1
1
  //#region src/defu.ts
2
- /**
3
- * Create a defu function with optional custom merger
4
- */
5
2
  function createDefu(merger) {
6
3
  return ((source, ...defaults) => {
7
4
  return defaults.reduce((mergedResult, currentDefaults) => _defu(mergedResult, currentDefaults ?? {}, "", merger), source ?? {});
@@ -15,7 +15,7 @@ interface Emitter<Events extends Record<EventType, unknown>> {
15
15
  emit<Key extends keyof Events>(type: undefined extends Events[Key] ? Key : never): void;
16
16
  }
17
17
  /**
18
- * Simple functional event emitter / pubsub.
18
+ * Creates a functional pubsub event emitter.
19
19
  *
20
20
  * @remarks Ported from `mitt`.
21
21
  * @see https://github.com/developit/mitt
package/dist/emitter.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  //#region src/emitter.ts
2
2
  /**
3
- * Simple functional event emitter / pubsub.
3
+ * Creates a functional pubsub event emitter.
4
4
  *
5
5
  * @remarks Ported from `mitt`.
6
6
  * @see https://github.com/developit/mitt
@@ -13,7 +13,7 @@ function createEmitter(events) {
13
13
  */
14
14
  events,
15
15
  /**
16
- * Register an event handler for the given type.
16
+ * Registers an event handler for the given type.
17
17
  *
18
18
  * @memberOf createEmitter
19
19
  */
@@ -23,7 +23,7 @@ function createEmitter(events) {
23
23
  else events.set(type, [handler]);
24
24
  },
25
25
  /**
26
- * Remove an event handler for the given type.
26
+ * Removes an event handler for the given type.
27
27
  *
28
28
  * @remarks
29
29
  * If `handler` is omitted, all handlers of the given type are removed.
@@ -36,11 +36,11 @@ function createEmitter(events) {
36
36
  else events.set(type, []);
37
37
  },
38
38
  /**
39
- * Invoke all handlers for the given type.
39
+ * Invokes all handlers for the given type.
40
40
  *
41
41
  * @remarks
42
42
  * If present, `'*'` handlers are invoked after type-matched handlers.
43
- * Manually firing '*' handlers is not supported.
43
+ * Manually firing `'*'` handlers is not supported.
44
44
  *
45
45
  * @memberOf createEmitter
46
46
  */
package/dist/json.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  //#region src/json.d.ts
2
2
  /**
3
- * Type-safe wrapper around `JSON.parse`.
3
+ * Wraps `JSON.parse` with a typed return value.
4
4
  *
5
5
  * @remarks
6
6
  * Falls back to the original value if parsing fails or the value is not a string.
package/dist/json.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  //#region src/json.ts
2
2
  /**
3
- * Type-safe wrapper around `JSON.parse`.
3
+ * Wraps `JSON.parse` with a typed return value.
4
4
  *
5
5
  * @remarks
6
6
  * Falls back to the original value if parsing fails or the value is not a string.
package/dist/module.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  //#region src/module.d.ts
2
2
  /**
3
- * Interop helper for default exports.
3
+ * Unwraps a module's `default` export, or returns the module unchanged if it has none.
4
4
  *
5
5
  * @example
6
6
  * const mod = await interopDefault(import('./module.js'))
package/dist/module.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  //#region src/module.ts
2
2
  /**
3
- * Interop helper for default exports.
3
+ * Unwraps a module's `default` export, or returns the module unchanged if it has none.
4
4
  *
5
5
  * @example
6
6
  * const mod = await interopDefault(import('./module.js'))
package/dist/object.d.mts CHANGED
@@ -1,8 +1,6 @@
1
1
  //#region src/object.d.ts
2
2
  /**
3
- * A simple general purpose memoizer utility.
4
- * - Lazily computes a value when accessed
5
- * - Auto-caches the result by overwriting the getter
3
+ * Wraps a getter so its value is computed on first access and cached from then on.
6
4
  *
7
5
  * @remarks
8
6
  * Useful for deferring initialization or expensive operations. Unlike a simple getter, there is no runtime overhead after the first invocation, since the getter itself is overwritten with the memoized value.
@@ -17,11 +15,11 @@ declare function memoize<T>(getter: () => T): {
17
15
  value: T;
18
16
  };
19
17
  /**
20
- * Strictly typed `Object.keys`.
18
+ * Wraps `Object.keys` with a stricter return type.
21
19
  */
22
20
  declare function objectKeys<T extends Record<any, any>>(obj: T): Array<`${Extract<keyof T, string | number>}`>;
23
21
  /**
24
- * Strictly typed `Object.entries`.
22
+ * Wraps `Object.entries` with a stricter return type.
25
23
  */
26
24
  declare function objectEntries<T extends Record<any, any>>(obj: T): Array<[keyof T, T[keyof T]]>;
27
25
  /**
package/dist/object.mjs CHANGED
@@ -1,8 +1,6 @@
1
1
  //#region src/object.ts
2
2
  /**
3
- * A simple general purpose memoizer utility.
4
- * - Lazily computes a value when accessed
5
- * - Auto-caches the result by overwriting the getter
3
+ * Wraps a getter so its value is computed on first access and cached from then on.
6
4
  *
7
5
  * @remarks
8
6
  * Useful for deferring initialization or expensive operations. Unlike a simple getter, there is no runtime overhead after the first invocation, since the getter itself is overwritten with the memoized value.
@@ -21,13 +19,13 @@ function memoize(getter) {
21
19
  } };
22
20
  }
23
21
  /**
24
- * Strictly typed `Object.keys`.
22
+ * Wraps `Object.keys` with a stricter return type.
25
23
  */
26
24
  function objectKeys(obj) {
27
25
  return Object.keys(obj);
28
26
  }
29
27
  /**
30
- * Strictly typed `Object.entries`.
28
+ * Wraps `Object.entries` with a stricter return type.
31
29
  */
32
30
  function objectEntries(obj) {
33
31
  return Object.entries(obj);
package/dist/path.d.mts CHANGED
@@ -40,7 +40,7 @@ declare function withoutBase(input?: string, base?: string): string;
40
40
  */
41
41
  declare function getPathname(path?: string): string;
42
42
  /**
43
- * Returns the URL with the given query parameters. If a query parameter is undefined, it is omitted.
43
+ * Returns the URL with the given query parameters. If a query parameter is `undefined`, it is omitted.
44
44
  */
45
45
  declare function withQuery(input: string, query?: QueryObject): string;
46
46
  //#endregion
package/dist/path.mjs CHANGED
@@ -101,7 +101,7 @@ function getPathname(path = "/") {
101
101
  return path.slice(0, pathEnd) || "/";
102
102
  }
103
103
  /**
104
- * Returns the URL with the given query parameters. If a query parameter is undefined, it is omitted.
104
+ * Returns the URL with the given query parameters. If a query parameter is `undefined`, it is omitted.
105
105
  */
106
106
  function withQuery(input, query) {
107
107
  if (!query || Object.keys(query).length === 0) return input;
package/dist/result.d.mts CHANGED
@@ -11,8 +11,8 @@ interface ErrData<E> {
11
11
  type ResultData<T, E> = OkData<T> | ErrData<E>;
12
12
  /**
13
13
  * Successful result variant.
14
- * @template T Success value type.
15
- * @template E Error type (phantom - for type unification).
14
+ * @template T Success value type
15
+ * @template E Error type (phantom – for type unification)
16
16
  */
17
17
  declare class Ok<T, E = never> {
18
18
  readonly value: T;
@@ -20,15 +20,15 @@ declare class Ok<T, E = never> {
20
20
  constructor(value: T);
21
21
  /** Transforms the success value. */
22
22
  map<U>(fn: (value: T) => U): Ok<U, E>;
23
- /** No-op on Ok, returns self with new error type. */
23
+ /** Returns this `Ok` unchanged, with a new error type. */
24
24
  mapError<E2>(_fn: (error: E) => E2): Ok<T, E2>;
25
- /** Chains a Result-returning function. */
25
+ /** Chains a `Result`-returning function. */
26
26
  andThen<U, E2>(fn: (value: T) => Result<U, E2>): Result<U, E | E2>;
27
27
  /** Extracts the value. */
28
28
  unwrap(_message?: string): T;
29
29
  /** Returns the value, ignoring the fallback. */
30
30
  unwrapOr<U>(_fallback: U): T;
31
- /** Pattern matches on the Result. */
31
+ /** Pattern matches on the `Result`. */
32
32
  match<R>(handlers: {
33
33
  ok: (value: T) => R;
34
34
  err: (error: E) => R;
@@ -36,24 +36,24 @@ declare class Ok<T, E = never> {
36
36
  }
37
37
  /**
38
38
  * Error result variant.
39
- * @template T Success type (phantom - for type unification).
40
- * @template E Error value type.
39
+ * @template T Success type (phantom – for type unification)
40
+ * @template E Error value type
41
41
  */
42
42
  declare class Err<T, E> {
43
43
  readonly error: E;
44
44
  readonly ok = false;
45
45
  constructor(error: E);
46
- /** No-op on Err, returns self with new value type. */
46
+ /** Returns this `Err` unchanged, with a new value type. */
47
47
  map<U>(_fn: (value: T) => U): Err<U, E>;
48
48
  /** Transforms the error value. */
49
49
  mapError<E2>(fn: (error: E) => E2): Err<T, E2>;
50
- /** No-op on Err, returns self with widened error type. */
50
+ /** Returns this `Err` unchanged, with a widened error type. */
51
51
  andThen<U, E2>(_fn: (value: T) => Result<U, E2>): Err<U, E | E2>;
52
52
  /** Throws an error with the given message. */
53
53
  unwrap(message?: string): never;
54
54
  /** Returns the fallback value. */
55
55
  unwrapOr<U>(fallback: U): T | U;
56
- /** Pattern matches on the Result. */
56
+ /** Pattern matches on the `Result`. */
57
57
  match<R>(handlers: {
58
58
  ok: (value: T) => R;
59
59
  err: (error: E) => R;
package/dist/result.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  //#region src/result.ts
2
2
  /**
3
3
  * Successful result variant.
4
- * @template T Success value type.
5
- * @template E Error type (phantom - for type unification).
4
+ * @template T Success value type
5
+ * @template E Error type (phantom – for type unification)
6
6
  */
7
7
  var Ok = class Ok {
8
8
  constructor(value) {
@@ -13,11 +13,11 @@ var Ok = class Ok {
13
13
  map(fn) {
14
14
  return new Ok(fn(this.value));
15
15
  }
16
- /** No-op on Ok, returns self with new error type. */
16
+ /** Returns this `Ok` unchanged, with a new error type. */
17
17
  mapError(_fn) {
18
18
  return this;
19
19
  }
20
- /** Chains a Result-returning function. */
20
+ /** Chains a `Result`-returning function. */
21
21
  andThen(fn) {
22
22
  return fn(this.value);
23
23
  }
@@ -29,22 +29,22 @@ var Ok = class Ok {
29
29
  unwrapOr(_fallback) {
30
30
  return this.value;
31
31
  }
32
- /** Pattern matches on the Result. */
32
+ /** Pattern matches on the `Result`. */
33
33
  match(handlers) {
34
34
  return handlers.ok(this.value);
35
35
  }
36
36
  };
37
37
  /**
38
38
  * Error result variant.
39
- * @template T Success type (phantom - for type unification).
40
- * @template E Error value type.
39
+ * @template T Success type (phantom – for type unification)
40
+ * @template E Error value type
41
41
  */
42
42
  var Err = class Err {
43
43
  constructor(error) {
44
44
  this.ok = false;
45
45
  this.error = error;
46
46
  }
47
- /** No-op on Err, returns self with new value type. */
47
+ /** Returns this `Err` unchanged, with a new value type. */
48
48
  map(_fn) {
49
49
  return this;
50
50
  }
@@ -52,7 +52,7 @@ var Err = class Err {
52
52
  mapError(fn) {
53
53
  return new Err(fn(this.error));
54
54
  }
55
- /** No-op on Err, returns self with widened error type. */
55
+ /** Returns this `Err` unchanged, with a widened error type. */
56
56
  andThen(_fn) {
57
57
  return this;
58
58
  }
@@ -64,7 +64,7 @@ var Err = class Err {
64
64
  unwrapOr(fallback) {
65
65
  return fallback;
66
66
  }
67
- /** Pattern matches on the Result. */
67
+ /** Pattern matches on the `Result`. */
68
68
  match(handlers) {
69
69
  return handlers.err(this.error);
70
70
  }
package/dist/string.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  //#region src/string.d.ts
2
2
  declare const TEMPLATE_PLACEHOLDER_RE: RegExp;
3
3
  /**
4
- * Simple template engine to replace variables in a string.
4
+ * Replaces `{name}` placeholders in a string with the matching variable.
5
5
  *
6
6
  * @remarks
7
7
  * Only own properties of `variables` are substituted, so placeholders like
package/dist/string.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  const URL_ALPHABET = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
3
3
  const TEMPLATE_PLACEHOLDER_RE = /\{(\w+)\}/g;
4
4
  /**
5
- * Simple template engine to replace variables in a string.
5
+ * Replaces `{name}` placeholders in a string with the matching variable.
6
6
  *
7
7
  * @remarks
8
8
  * Only own properties of `variables` are substituted, so placeholders like
package/dist/types.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  //#region src/types.d.ts
2
2
  type AutocompletableString = string & {};
3
3
  type LooseAutocomplete<T extends string> = T | AutocompletableString;
4
- /** Also commonly referred to as `Prettify` */
4
+ /** Also commonly referred to as `Prettify`. */
5
5
  type UnifyIntersection<T> = { [K in keyof T]: T[K]; } & {};
6
6
  declare const brand: unique symbol;
7
7
  type BrandedType<T, B> = T & {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "utilful",
3
3
  "type": "module",
4
- "version": "3.0.1",
4
+ "version": "3.0.2",
5
5
  "packageManager": "pnpm@11.15.1",
6
6
  "description": "A collection of TypeScript utilities",
7
7
  "author": "Johann Schopplich <hello@johannschopplich.com>",