@budsbox/lib-es 2.3.0 → 3.0.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.
package/dist/object.js CHANGED
@@ -1,47 +1,86 @@
1
+ /**
2
+ * Object utility functions for selecting, omitting, filtering, reducing, and
3
+ * strongly-typing common object operations.
4
+ *
5
+ * @module
6
+ * @importTarget ./object
7
+ */
1
8
  import { isNotNil } from '#guards';
2
9
  export function pick(source, ...keys) {
3
10
  return keys.reduce((acc, key) => Object.hasOwn(source, key) ? { ...acc, [key]: source[key] } : acc, {});
4
11
  }
12
+ /**
13
+ * A strict version of {@link pick} that restricts keys to those present in `TSource`.
14
+ *
15
+ * @param source - The source object.
16
+ * @param keys - The property keys to pick.
17
+ * @returns A new object with the picked properties.
18
+ * @typeParam TSource - The type of the source object.
19
+ * @typeParam Keys - The type of the keys to pick, restricted to keys of `TSource`.
20
+ */
5
21
  export const pickStrict = pick;
6
22
  export function omit(source, ...keys) {
7
23
  const keySet = new Set(keys);
8
24
  return Object.fromEntries(Object.entries(source).filter(([key]) => !keySet.has(key)));
9
25
  }
26
+ /**
27
+ * A strict version of {@link omit} that restricts keys to those present in `TSource`.
28
+ *
29
+ * @param source - The source object.
30
+ * @param keys - The property keys to omit.
31
+ * @returns A new object without the omitted properties.
32
+ * @typeParam TSource - The type of the source object.
33
+ * @typeParam TKey - The type of the keys to omit, restricted to keys of `TSource`.
34
+ */
10
35
  export const omitStrict = omit;
11
- export function filterBy(obj, filter) {
36
+ export function filter(obj, test) {
12
37
  const newObj = {};
13
38
  for (const key in obj) {
14
39
  if (!Object.hasOwn(obj, key)) {
15
40
  break;
16
41
  }
17
42
  const value = obj[key];
18
- if (filter(value, key, obj)) {
43
+ if (test(value, key, obj)) {
19
44
  newObj[key] = value;
20
45
  }
21
46
  }
22
47
  return newObj;
23
48
  }
49
+ /**
50
+ * Returns a new object with all `null` or `undefined` properties removed using {@link filter} and {@link isNotNil}.
51
+ *
52
+ * @param object - The object to strip of nils.
53
+ * @returns A new object without nil properties.
54
+ * @typeParam T - The type of the source object.
55
+ */
24
56
  export function omitNils(object) {
25
- return filterBy(object, isNotNil);
57
+ return filter(object, isNotNil);
26
58
  }
27
- export function reduce(obj, callback, initialValue) {
28
- return Object.entries(obj).reduce((acc, [key, value]) => callback(acc, value, key, obj), initialValue);
29
- }
30
- export function getKey(value) {
31
- for (const key in value) {
32
- if (Object.hasOwn(value, key)) {
33
- return key;
34
- }
35
- else {
36
- /*
37
- Modern JS interpreters in the for..in loop
38
- first traverse the object's own properties,
39
- and then the inherited ones. Therefore, you can end the loop
40
- if the own property has never been encountered
41
- */
42
- break;
43
- }
44
- }
45
- return undefined;
59
+ /**
60
+ * Transforms the values of an object using the provided callback function.
61
+ *
62
+ * @param object - The source object whose values are to be transformed.
63
+ * @param callback - A function that is called for each key-value pair in the source object.
64
+ * It receives the value, key, and the original object as arguments and returns the transformed value.
65
+ * @returns A new object with the same keys as the source object but with values transformed by the callback function.
66
+ * @typeParam TSource - The type of the source object.
67
+ * @typeParam TValue - The type of the transformed values in the resulting object.
68
+ */
69
+ export const map = (object, callback) => {
70
+ return reduce(object, (acc, value, key, obj) => {
71
+ acc[key] = callback(value, key, obj);
72
+ return acc;
73
+ }, {});
74
+ };
75
+ export function reduce(source, callback, initialValue) {
76
+ return Object.entries(source).reduce((acc, [key, value]) => callback(acc, value, key, source), initialValue);
46
77
  }
78
+ /**
79
+ * Returns an array of a given object's own enumerable string-keyed property [key, value] pairs, typed as {@link EntryUnion}.
80
+ *
81
+ * @param source - The object whose entries are to be returned.
82
+ * @returns An array of entry tuples.
83
+ * @typeParam T - The type of the source object.
84
+ */
85
+ export const entries = (source) => Object.entries(source);
47
86
  //# sourceMappingURL=object.js.map
package/dist/set.d.ts ADDED
@@ -0,0 +1,70 @@
1
+ /**
2
+ * This module provides set utility functions for common operations like union, intersection, difference, etc.
3
+ *
4
+ * @module
5
+ * @importTarget ./set
6
+ */
7
+ import type { IterableElement } from 'type-fest';
8
+ import type { AnyReadableSet, AnySet, ArrayItemsIntersection, Nil } from '@budsbox/lib-types';
9
+ /**
10
+ * Computes the union of multiple sets and returns a new set containing all unique elements.
11
+ *
12
+ * @param sets - A collection of sets to be unified.
13
+ * @returns A new set containing all unique elements present in any of the input sets.
14
+ * @typeParam TSets - An array of sets whose elements extend the type `UnknownSet`.
15
+ */
16
+ export declare const union: <TSets extends readonly AnyReadableSet[]>(...sets: TSets) => Set<IterableElement<IterableElement<TSets>>>;
17
+ /**
18
+ * Computes the intersection of multiple sets, returning a new set containing only the elements
19
+ * that are present in all the provided sets.
20
+ *
21
+ * @param sets - A variable number of sets to compute the intersection from.
22
+ * @returns A new set containing the elements that are common to all provided sets.
23
+ * @typeParam TSets - A tuple of sets, where each set contains elements of any type.
24
+ * The resulting set contains elements that are a union of all possible intersections
25
+ * of the provided sets' elements.
26
+ */
27
+ export declare const intersection: <TSets extends readonly AnyReadableSet[]>(...sets: TSets) => Set<ArrayItemsIntersection<ItemsOfSetsArray<TSets>>>;
28
+ /**
29
+ * A read-only implementation of the `Set` interface. This class allows for creating immutable sets,
30
+ * providing the same methods as a standard `Set`, but without mutation capabilities.
31
+ *
32
+ * @typeParam T - The type of elements stored in the set.
33
+ */
34
+ export declare class ROSet<T> extends Set<T> implements ReadonlySet<T> {
35
+ /**
36
+ * Constructs a new instance of the class.
37
+ *
38
+ * @param input - An iterable object that contains elements of type `T` to initialize the set,
39
+ * or `Nil` to create an empty set.
40
+ * @typeParam T - The type of the elements in the set.
41
+ */
42
+ constructor(input?: Iterable<T> | Nil);
43
+ /**
44
+ * Throws a `TypeError` exception because set is read-only.
45
+ *
46
+ * @param value - The value to add to set.
47
+ * @returns This method does not return a value.
48
+ * @throws {@link !TypeError} Indeed: set is read-only.
49
+ */
50
+ add(value: T): never;
51
+ /**
52
+ * Throws a `TypeError` exception because set is read-only.
53
+ *
54
+ * @param value - The value to remove from set.
55
+ * @throws {@link !TypeError} Indeed: set is read-only.
56
+ */
57
+ delete(value: T): never;
58
+ /**
59
+ * Throws a `TypeError` exception because set is read-only.
60
+ *
61
+ * @throws {@link !TypeError} Indeed: set is read-only.
62
+ */
63
+ clear(): never;
64
+ }
65
+ type ItemsOfSetsArray<TSets extends readonly AnyReadableSet[]> = TSets extends readonly [infer TSet, ...infer TRest] ? [
66
+ TSet extends Set<infer T> ? T : never,
67
+ ...(TRest extends readonly AnySet[] ? ItemsOfSetsArray<TRest> : [])
68
+ ] : TSets extends readonly [] ? [] : TSets extends ReadonlyArray<Set<infer T>> ? T[] : never;
69
+ export {};
70
+ //# sourceMappingURL=set.d.ts.map
package/dist/set.js ADDED
@@ -0,0 +1,116 @@
1
+ /**
2
+ * This module provides set utility functions for common operations like union, intersection, difference, etc.
3
+ *
4
+ * @module
5
+ * @importTarget ./set
6
+ */
7
+ /**
8
+ * Computes the union of multiple sets and returns a new set containing all unique elements.
9
+ *
10
+ * @param sets - A collection of sets to be unified.
11
+ * @returns A new set containing all unique elements present in any of the input sets.
12
+ * @typeParam TSets - An array of sets whose elements extend the type `UnknownSet`.
13
+ */
14
+ export const union = (...sets) => {
15
+ const unionSet = new Set();
16
+ for (const set of sets) {
17
+ for (const element of set) {
18
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
19
+ unionSet.add(element);
20
+ }
21
+ }
22
+ return unionSet;
23
+ };
24
+ /**
25
+ * Computes the intersection of multiple sets, returning a new set containing only the elements
26
+ * that are present in all the provided sets.
27
+ *
28
+ * @param sets - A variable number of sets to compute the intersection from.
29
+ * @returns A new set containing the elements that are common to all provided sets.
30
+ * @typeParam TSets - A tuple of sets, where each set contains elements of any type.
31
+ * The resulting set contains elements that are a union of all possible intersections
32
+ * of the provided sets' elements.
33
+ */
34
+ export const intersection = (...sets) => {
35
+ const { length } = sets;
36
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
+ const counters = new Map();
38
+ for (const set of sets) {
39
+ for (const element of set) {
40
+ const count = counters.get(element) ?? 0;
41
+ counters.set(element, count + 1);
42
+ }
43
+ }
44
+ const intersectionSet = new Set();
45
+ for (const [element, count] of counters) {
46
+ if (count === length) {
47
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
48
+ intersectionSet.add(element);
49
+ }
50
+ }
51
+ return intersectionSet;
52
+ };
53
+ /**
54
+ * A read-only implementation of the `Set` interface. This class allows for creating immutable sets,
55
+ * providing the same methods as a standard `Set`, but without mutation capabilities.
56
+ *
57
+ * @typeParam T - The type of elements stored in the set.
58
+ */
59
+ export class ROSet extends Set {
60
+ /**
61
+ * Constructs a new instance of the class.
62
+ *
63
+ * @param input - An iterable object that contains elements of type `T` to initialize the set,
64
+ * or `Nil` to create an empty set.
65
+ * @typeParam T - The type of the elements in the set.
66
+ */
67
+ constructor(input) {
68
+ super(input);
69
+ createdSets.add(this);
70
+ }
71
+ /**
72
+ * Throws a `TypeError` exception because set is read-only.
73
+ *
74
+ * @param value - The value to add to set.
75
+ * @returns This method does not return a value.
76
+ * @throws {@link !TypeError} Indeed: set is read-only.
77
+ */
78
+ add(value) {
79
+ if (createdSets.has(this)) {
80
+ throw new TypeError(`Cannot add value ${String(value)}: set is read-only`);
81
+ }
82
+ return super.add(value);
83
+ }
84
+ /**
85
+ * Throws a `TypeError` exception because set is read-only.
86
+ *
87
+ * @param value - The value to remove from set.
88
+ * @throws {@link !TypeError} Indeed: set is read-only.
89
+ */
90
+ delete(value) {
91
+ throw new TypeError(`Cannot delete value ${String(value)}: set is read-only`);
92
+ }
93
+ /**
94
+ * Throws a `TypeError` exception because set is read-only.
95
+ *
96
+ * @throws {@link !TypeError} Indeed: set is read-only.
97
+ */
98
+ clear() {
99
+ throw new TypeError('Cannot clear set: set is read-only');
100
+ }
101
+ }
102
+ const createdSets = new WeakSet();
103
+ /*
104
+ * It seems a bit hacky, but I plan to use it as an actual implementation for the `ReadonlySet` type,
105
+ * so I guess it's reasonable.
106
+ */
107
+ [
108
+ [ROSet, 'name'],
109
+ [ROSet.prototype, Symbol.toStringTag],
110
+ ].forEach(([obj, prop]) => {
111
+ Object.defineProperty(obj, prop, {
112
+ value: 'ReadonlySet',
113
+ configurable: true,
114
+ });
115
+ });
116
+ //# sourceMappingURL=set.js.map
package/dist/string.d.ts CHANGED
@@ -1,13 +1,27 @@
1
+ /**
2
+ * This module provides string utility functions for common operations like case conversion, trimming, splitting, etc.
3
+ *
4
+ * @module
5
+ * @importTarget ./string
6
+ * @showCategories
7
+ * @categoryDescription Package Name
8
+ * This category contains functions for manipulating and formatting names of packages.
9
+ * @categoryDescription Casing
10
+ * This category contains functions for converting strings to different casing formats.
11
+ * @categoryDescription Paths
12
+ * This category contains functions for manipulating and formatting paths.
13
+ */
1
14
  import type { CamelCase, DelimiterCase, KebabCase, PascalCase, SnakeCase } from 'type-fest';
2
- import type { Maybe, Nil, Undef } from '@budsbox/lib-types';
3
- import type { ParsedPackageName } from './types.js';
4
- export type { ParsedPackageName };
15
+ import type { Nil, Undef } from '@budsbox/lib-types';
16
+ import type { PackageNameFormatOptions, ParsedPackageName } from './types.js';
17
+ export type { PackageNameFormatOptions, ParsedPackageName };
5
18
  /**
6
19
  * Parses a package name string to extract its scope and name.
7
20
  *
8
21
  * @param packageName - The full name of the package, potentially including a scope.
9
22
  * @param clean - A flag indicating whether to return a cleaned version (i.e., without a leading `@` and trailing `/`) of the scope. Defaults to false.
10
23
  * @returns An object containing the parsed scope and name of the package. The scope will be `null` if no scope is present.
24
+ * @category Package Name
11
25
  */
12
26
  export declare function parsePackageName(packageName: string, clean?: boolean): Required<ParsedPackageName>;
13
27
  /**
@@ -15,6 +29,7 @@ export declare function parsePackageName(packageName: string, clean?: boolean):
15
29
  *
16
30
  * @param parsedPackageName - An object representing the parsed package name with fields such as `scope` and `name`.
17
31
  * @returns The string representation of the package name, including the scope if it exists.
32
+ * @category Package Name
18
33
  */
19
34
  export declare function serializePackageName(parsedPackageName: Readonly<ParsedPackageName>): string;
20
35
  /**
@@ -23,8 +38,9 @@ export declare function serializePackageName(parsedPackageName: Readonly<ParsedP
23
38
  * @param parsedPackageName - A parsed package name object of type `ParsedPackageName` or a Nil value.
24
39
  * @param allowNil - A boolean flag specifying whether Nil values are allowed for conversion.
25
40
  * @returns The string representation of the package name if valid, or an empty string if `allowNil` is true and the input is Nil.
41
+ * @category Package Name
26
42
  */
27
- export declare function serializePackageName(parsedPackageName: Readonly<ParsedPackageName> | Nil, allowNil: true): string;
43
+ export declare function serializePackageName(parsedPackageName: Nil | Readonly<ParsedPackageName>, allowNil: true): string;
28
44
  /**
29
45
  * Resolves the package name based on the provided identifier and options.
30
46
  * Can return either a string representing the package name or a parsed package name object.
@@ -35,40 +51,13 @@ export declare function serializePackageName(parsedPackageName: Readonly<ParsedP
35
51
  * to indicate whether the result should be returned as a parsed package name object.
36
52
  * @returns The resolved package name as a string if `parsed` is false or not specified,
37
53
  * or as a `ParsedPackageName` object if `parsed` is true.
54
+ * @typeParam TParsed - Controls the return type: when `true`, returns `ParsedPackageName`; when `false` (default), returns `string`.
55
+ * @category Package Name
38
56
  */
39
57
  export declare function resolvePackageName<TParsed extends boolean = false>(ident: string | Readonly<ParsedPackageName>, options?: Readonly<{
40
58
  baseScope?: Undef<string>;
41
59
  parsed?: TParsed;
42
60
  }>): TParsed extends true ? ParsedPackageName : string;
43
- /**
44
- * Options for formatting the package name
45
- */
46
- export interface PackageNameFormatOptions {
47
- /**
48
- * The root identifier for the package.
49
- */
50
- root?: Maybe<string>;
51
- /**
52
- * The parent package name.
53
- */
54
- parent?: Maybe<string>;
55
- /**
56
- * The path to the package, relative to its parent.
57
- */
58
- relCwd?: Undef<string>;
59
- /**
60
- * The delimiter used to separate path chunks.
61
- */
62
- pathDelimiter?: Undef<string>;
63
- /**
64
- * The delimiter used to separate parents name from the base name of the package.
65
- */
66
- nameDelimiter?: Undef<string>;
67
- /**
68
- * Array of path chunks to be excluded when constructing the path.
69
- */
70
- excludePathChunks?: Undef<readonly string[]>;
71
- }
72
61
  /**
73
62
  * Formats a package name by combining the base name with processed parent and directory path details.
74
63
  *
@@ -81,14 +70,16 @@ export interface PackageNameFormatOptions {
81
70
  * @param options.nameDelimiter - The delimiter used to separate parents name from the base name of the package. Defaults to `'_'`.
82
71
  * @param options.excludePathChunks - Array of path chunks to be excluded when constructing the path. Defaults to `['packages']`.
83
72
  * @returns The formatted package name as a string.
73
+ * @category Package Name
84
74
  */
85
- export declare function formatPackageName(base: string, { root, parent, relCwd, pathDelimiter, nameDelimiter, excludePathChunks, }?: Readonly<PackageNameFormatOptions>): string;
75
+ export declare function formatPackageName(base: string, options?: Readonly<PackageNameFormatOptions>): string;
86
76
  /**
87
77
  * Converts the provided value to a string representation suitable for debugging purposes.
88
78
  *
89
79
  * @param value - The value to be converted to its string representation. Can be of any type.
90
80
  * @returns A string representation of the input value.
91
81
  * If the value cannot be serialized using JSON.stringify, it falls back to using String conversion.
82
+ * @deprecated Use `formatDebugValue` from `@budsbox/lib-es/guards` instead.
92
83
  */
93
84
  export declare function debugString(value: unknown): string;
94
85
  /**
@@ -107,8 +98,9 @@ export declare function clampWS(str: string): string;
107
98
  * @param parts - An array of path parts to join. Each part can be a string, number, boolean, null, or undefined.
108
99
  * Non-string values will be serialized, and null/undefined values are ignored.
109
100
  * @returns The combined path as a single string, with proper slash formatting.
101
+ * @category Paths
110
102
  */
111
- export declare function joinPath(...parts: ReadonlyArray<string | number | boolean | null | undefined>): string;
103
+ export declare function joinPath(...parts: ReadonlyArray<boolean | number | string | null | undefined>): string;
112
104
  /**
113
105
  * Splits a given Unix-like path into an array of its components based on the "/" delimiter.
114
106
  * Optionally keeps empty chunks in the result.
@@ -117,6 +109,7 @@ export declare function joinPath(...parts: ReadonlyArray<string | number | boole
117
109
  * @param keepEmptyChunks - A boolean indicating whether empty strings (resulting from consecutive delimiters)
118
110
  * should be preserved in the output array. Defaults to `false`.
119
111
  * @returns An array of strings representing the components of the path.
112
+ * @category Paths
120
113
  */
121
114
  export declare function splitPath(path: string, keepEmptyChunks?: boolean): string[];
122
115
  /**
@@ -124,6 +117,8 @@ export declare function splitPath(path: string, keepEmptyChunks?: boolean): stri
124
117
  *
125
118
  * @param str - The string to be converted to camelCase.
126
119
  * @returns The input string transformed into camelCase.
120
+ * @typeParam T - The input string type; used to derive the resulting `CamelCase<T>` type.
121
+ * @category Casing
127
122
  */
128
123
  export declare function camelCase<T extends string>(str: T): CamelCase<T>;
129
124
  /**
@@ -131,6 +126,8 @@ export declare function camelCase<T extends string>(str: T): CamelCase<T>;
131
126
  *
132
127
  * @param str - The string to be transformed into PascalCase.
133
128
  * @returns The transformed string in PascalCase format.
129
+ * @typeParam T - The input string type; used to derive the resulting `PascalCase<T>` type.
130
+ * @category Casing
134
131
  */
135
132
  export declare function pascalCase<T extends string>(str: T): PascalCase<T>;
136
133
  /**
@@ -139,6 +136,9 @@ export declare function pascalCase<T extends string>(str: T): PascalCase<T>;
139
136
  * @param name - The input string that will be converted to the delimited case.
140
137
  * @param delimiter - The character or string to use as a delimiter in the transformed output.
141
138
  * @returns The input string transformed into the delimited case format using the given delimiter.
139
+ * @typeParam T - The input string type; used to derive the resulting `DelimiterCase<T, D>` type.
140
+ * @typeParam D - The delimiter string type used to separate words in the result.
141
+ * @category Casing
142
142
  */
143
143
  export declare function delimCase<T extends string, D extends string>(name: T, delimiter: D): DelimiterCase<T, D>;
144
144
  /**
@@ -146,6 +146,8 @@ export declare function delimCase<T extends string, D extends string>(name: T, d
146
146
  *
147
147
  * @param name - The string input to be converted to kebab-case. The input should be a string type.
148
148
  * @returns The transformed string in kebab-case format.
149
+ * @typeParam T - The input string type; used to derive the resulting `KebabCase<T>` type.
150
+ * @category Casing
149
151
  */
150
152
  export declare function kebabCase<T extends string>(name: T): KebabCase<T>;
151
153
  /**
@@ -153,6 +155,30 @@ export declare function kebabCase<T extends string>(name: T): KebabCase<T>;
153
155
  *
154
156
  * @param name - The string to be converted to snake_case.
155
157
  * @returns The converted string in snake_case format.
158
+ * @typeParam T - The input string type; used to derive the resulting `SnakeCase<T>` type.
159
+ * @category Casing
156
160
  */
157
161
  export declare function snakeCase<T extends string>(name: T): SnakeCase<T>;
162
+ /**
163
+ * Joins an array of strings into a single formatted string using the specified conjunction.
164
+ *
165
+ * @param items - An array of strings to be joined. If the array is empty, an empty string is returned.
166
+ * @param conjunction - A word or phrase (`and` or `or`) to be used as the conjunction between the last two items.
167
+ * @returns A formatted string where the items are separated by commas and the conjunction is added before the final item.
168
+ */
169
+ export declare function joinWithConjunction(items: readonly string[], conjunction: string): string;
170
+ /**
171
+ * Constructs a dot-notation or bracket-notation string representation
172
+ * for accessing nested properties of an object based on the provided keys.
173
+ *
174
+ * @internal
175
+ * @param sourceName - The base name of the object or source from which properties are being accessed.
176
+ * @param keys - A variadic list of property keys representing the nested path.
177
+ * Each key will be used to generate the accessor string.
178
+ * @returns A string representing the accessor path in dot-notation for valid identifiers
179
+ * or bracket-notation for non-identifier keys.
180
+ * @remarks This function considers "valid" for identifiers only alphanumeric characters,
181
+ * underscores, and dollar signs.
182
+ */
183
+ export declare function formatPropAccessor(sourceName: string, ...keys: readonly PropertyKey[]): string;
158
184
  //# sourceMappingURL=string.d.ts.map