utilitish 0.0.5 → 0.0.7
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/array/array-constructor.d.ts +19 -13
- package/dist/array/array-constructor.js +5 -5
- package/dist/array/array-constructor.spec.d.ts +2 -0
- package/dist/array/array-constructor.spec.js +130 -0
- package/dist/array/array-prototype.d.ts +341 -84
- package/dist/array/array-prototype.js +38 -53
- package/dist/array/array-prototype.spec.d.ts +1 -0
- package/dist/array/array-prototype.spec.js +536 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/map/map-prototype.d.ts +69 -9
- package/dist/map/map-prototype.js +16 -3
- package/dist/map/map-prototype.spec.d.ts +1 -0
- package/dist/map/map-prototype.spec.js +261 -0
- package/dist/object/object-prototype.d.ts +61 -8
- package/dist/object/object-prototype.js +9 -0
- package/dist/object/object-prototype.spec.d.ts +1 -0
- package/dist/object/object-prototype.spec.js +110 -0
- package/dist/set/set-prototype.d.ts +83 -5
- package/dist/set/set-prototype.js +21 -6
- package/dist/set/set-prototype.spec.d.ts +1 -0
- package/dist/set/set-prototype.spec.js +122 -0
- package/dist/string/string-prototype.d.ts +143 -24
- package/dist/string/string-prototype.js +41 -11
- package/dist/string/string-prototype.spec.d.ts +1 -0
- package/dist/string/string-prototype.spec.js +115 -0
- package/dist/utils/core.utils.d.ts +103 -0
- package/dist/utils/core.utils.js +152 -0
- package/dist/utils/logic.utils.d.ts +3 -0
- package/dist/utils/logic.utils.js +41 -0
- package/package.json +1 -1
- package/dist/utils.d.ts +0 -28
- package/dist/utils.js +0 -80
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defineStaticIfNotExists = exports.defineIfNotExists = void 0;
|
|
4
|
+
exports.resolveSelector = resolveSelector;
|
|
5
|
+
exports.assertValidSelector = assertValidSelector;
|
|
6
|
+
exports.isNumberOrString = isNumberOrString;
|
|
7
|
+
/**
|
|
8
|
+
* Defines a **non-enumerable, non-writable, non-configurable** property on a prototype
|
|
9
|
+
* if it does not already exist, or if the existing property is writable or configurable.
|
|
10
|
+
*
|
|
11
|
+
* - Intended for instance prototype methods (e.g., `Array.prototype`, `String.prototype`).
|
|
12
|
+
* - Does **not** overwrite non-configurable and non-writable properties.
|
|
13
|
+
* - Ensures immutability and hides the property from enumeration.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* defineIfNotExists(Array.prototype, 'last', function() {
|
|
17
|
+
* return this[this.length - 1];
|
|
18
|
+
* });
|
|
19
|
+
*
|
|
20
|
+
* @template T The prototype object type (e.g., `Array.prototype`).
|
|
21
|
+
* @param {T} prototype The prototype on which to define the method.
|
|
22
|
+
* @param {string} name The name of the method to define.
|
|
23
|
+
* @param {Function} fn The function to assign as the method.
|
|
24
|
+
*
|
|
25
|
+
* @remarks
|
|
26
|
+
* Use this function to safely add prototype methods without overwriting stable or built-in ones.
|
|
27
|
+
*/
|
|
28
|
+
const defineIfNotExists = (prototype, name, fn) => {
|
|
29
|
+
const descriptor = Object.getOwnPropertyDescriptor(prototype, name);
|
|
30
|
+
if (!descriptor || descriptor.writable || descriptor.configurable) {
|
|
31
|
+
Object.defineProperty(prototype, name, {
|
|
32
|
+
value: fn,
|
|
33
|
+
enumerable: false,
|
|
34
|
+
configurable: false,
|
|
35
|
+
writable: false,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
exports.defineIfNotExists = defineIfNotExists;
|
|
40
|
+
/**
|
|
41
|
+
* Defines a **static** property on a constructor if it does not already exist,
|
|
42
|
+
* or if the existing property is writable or configurable.
|
|
43
|
+
*
|
|
44
|
+
* - Only affects static properties on constructors (e.g., `Array`, `Map`).
|
|
45
|
+
* - The property is created as non-enumerable, immutable, and non-configurable.
|
|
46
|
+
* - Does **not** overwrite existing properties that are non-configurable and non-writable.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* defineStaticIfNotExists(Array, 'range', function(start: number, end?: number) {
|
|
50
|
+
* // implementation
|
|
51
|
+
* });
|
|
52
|
+
*
|
|
53
|
+
* @template T The constructor type (e.g., `typeof Array`).
|
|
54
|
+
* @param {T} constructor The constructor object on which to define the static method.
|
|
55
|
+
* @param {string} name The name of the static method to define.
|
|
56
|
+
* @param {Function} fn The function to assign as the static method.
|
|
57
|
+
*
|
|
58
|
+
* @remarks
|
|
59
|
+
* To forcefully replace an existing property, delete it first or use `Object.defineProperty` directly.
|
|
60
|
+
*/
|
|
61
|
+
const defineStaticIfNotExists = (constructor, name, fn) => {
|
|
62
|
+
const descriptor = Object.getOwnPropertyDescriptor(constructor, name);
|
|
63
|
+
if (!descriptor || descriptor.writable || descriptor.configurable) {
|
|
64
|
+
Object.defineProperty(constructor, name, {
|
|
65
|
+
value: fn,
|
|
66
|
+
enumerable: false,
|
|
67
|
+
configurable: false,
|
|
68
|
+
writable: false,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
exports.defineStaticIfNotExists = defineStaticIfNotExists;
|
|
73
|
+
/**
|
|
74
|
+
* Resolves a selector parameter into a function that extracts a value from an item.
|
|
75
|
+
*
|
|
76
|
+
* The selector can be:
|
|
77
|
+
* - a key string of the object (returns the value at that key),
|
|
78
|
+
* - a function transforming the item to the desired value,
|
|
79
|
+
* - or undefined, in which case a fallback function must be provided.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* const sel1 = resolveSelector<{name: string}, string>('name');
|
|
83
|
+
* sel1({name: 'Alice'}); // 'Alice'
|
|
84
|
+
*
|
|
85
|
+
* const sel2 = resolveSelector<{value: number}, number>(item => item.value * 2);
|
|
86
|
+
* sel2({value: 5}); // 10
|
|
87
|
+
*
|
|
88
|
+
* const sel3 = resolveSelector(undefined, (item) => item.toString());
|
|
89
|
+
* sel3(42); // '42'
|
|
90
|
+
*
|
|
91
|
+
* @template T The type of the input items.
|
|
92
|
+
* @template R The type of the selected value.
|
|
93
|
+
* @param {keyof T | ((item: T) => R) | undefined} selector The selector key or function.
|
|
94
|
+
* @param {(item: T, index?: number) => R} [fallback] A fallback function if no selector is provided.
|
|
95
|
+
* @param {string} [name='selector'] Name used in error messages.
|
|
96
|
+
* @returns {(item: T, index?: number) => R} The resolved selector function.
|
|
97
|
+
*
|
|
98
|
+
* @throws {TypeError} If the selector is not a function or string key.
|
|
99
|
+
* @throws {TypeError} If no selector is provided and no fallback is given.
|
|
100
|
+
*/
|
|
101
|
+
function resolveSelector(selector, fallback, name = 'selector') {
|
|
102
|
+
assertValidSelector(selector);
|
|
103
|
+
if (typeof selector === 'function') {
|
|
104
|
+
return selector;
|
|
105
|
+
}
|
|
106
|
+
if (typeof selector === 'string') {
|
|
107
|
+
return (item) => item[selector];
|
|
108
|
+
}
|
|
109
|
+
if (selector) {
|
|
110
|
+
throw new TypeError(`${name} must be a function or a string key`);
|
|
111
|
+
}
|
|
112
|
+
if (fallback) {
|
|
113
|
+
if (typeof fallback === 'function') {
|
|
114
|
+
return fallback;
|
|
115
|
+
}
|
|
116
|
+
throw new TypeError(`fallback must be a function`);
|
|
117
|
+
}
|
|
118
|
+
throw new TypeError(`fallback must be given if no selector`);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Asserts that a selector parameter is valid, i.e., a function or a string.
|
|
122
|
+
*
|
|
123
|
+
* @template T The type of the input items.
|
|
124
|
+
* @template R The type of the selected value.
|
|
125
|
+
* @param {any} selector The selector to validate.
|
|
126
|
+
* @param {string} [name='selector'] The name to use in error messages.
|
|
127
|
+
*
|
|
128
|
+
* @throws {TypeError} If the selector is neither a function nor a string.
|
|
129
|
+
*
|
|
130
|
+
* @remarks
|
|
131
|
+
* Used internally by `resolveSelector` to provide clearer type safety and errors.
|
|
132
|
+
*/
|
|
133
|
+
function assertValidSelector(selector, name = 'selector') {
|
|
134
|
+
const isValid = typeof selector === 'function' || typeof selector === 'string';
|
|
135
|
+
if (selector !== undefined && !isValid) {
|
|
136
|
+
throw new TypeError(`${name} must be a function or a string key`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Type guard to check if a value is a string or number.
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* isNumberOrString('hello'); // true
|
|
144
|
+
* isNumberOrString(42); // true
|
|
145
|
+
* isNumberOrString(true); // false
|
|
146
|
+
*
|
|
147
|
+
* @param {unknown} value The value to test.
|
|
148
|
+
* @returns {value is string | number} True if the value is a string or number, else false.
|
|
149
|
+
*/
|
|
150
|
+
function isNumberOrString(value) {
|
|
151
|
+
return typeof value === 'string' || typeof value === 'number';
|
|
152
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mapToObject = mapToObject;
|
|
4
|
+
exports.sortBy = sortBy;
|
|
5
|
+
const core_utils_1 = require("./core.utils");
|
|
6
|
+
function mapToObject(map) {
|
|
7
|
+
const obj = {};
|
|
8
|
+
for (const [key, value] of map) {
|
|
9
|
+
// Validate that key is not null or undefined
|
|
10
|
+
if (key === null || key === undefined) {
|
|
11
|
+
throw new TypeError(`Invalid key: key cannot be null or undefined. Key received: ${String(key)}`);
|
|
12
|
+
}
|
|
13
|
+
const keyType = typeof key;
|
|
14
|
+
// Only allow string, number, or symbol
|
|
15
|
+
if (keyType !== 'string' && keyType !== 'number' && keyType !== 'symbol') {
|
|
16
|
+
throw new TypeError(`Invalid key type: keys must be string, number, or symbol, received ${keyType}. Key value: ${String(key)}`);
|
|
17
|
+
}
|
|
18
|
+
obj[key] = value;
|
|
19
|
+
}
|
|
20
|
+
return obj;
|
|
21
|
+
}
|
|
22
|
+
function sortBy(arr, direction, selector) {
|
|
23
|
+
if (arr.length === 0)
|
|
24
|
+
return arr.slice();
|
|
25
|
+
const getValue = (0, core_utils_1.resolveSelector)(selector, (item) => item);
|
|
26
|
+
if (!selector && !arr.every((item) => (0, core_utils_1.isNumberOrString)(item))) {
|
|
27
|
+
throw new TypeError('Array elements must be number or string if no selector is provided');
|
|
28
|
+
}
|
|
29
|
+
return arr.slice().sort((a, b) => {
|
|
30
|
+
const valA = getValue(a);
|
|
31
|
+
const valB = getValue(b);
|
|
32
|
+
if (!(0, core_utils_1.isNumberOrString)(valA) || !(0, core_utils_1.isNumberOrString)(valB)) {
|
|
33
|
+
throw new TypeError('Selector must return number or string');
|
|
34
|
+
}
|
|
35
|
+
if (valA > valB)
|
|
36
|
+
return direction === 'asc' ? 1 : -1;
|
|
37
|
+
if (valA < valB)
|
|
38
|
+
return direction === 'asc' ? -1 : 1;
|
|
39
|
+
return 0;
|
|
40
|
+
});
|
|
41
|
+
}
|
package/package.json
CHANGED
package/dist/utils.d.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
export declare const defineIfNotExists: <T extends object>(prototype: T, name: string, fn: Function) => void;
|
|
2
|
-
/**
|
|
3
|
-
* Defines a **static** property on a constructor if it does not already exist
|
|
4
|
-
* (or if the existing property is writable **or** configurable).
|
|
5
|
-
*
|
|
6
|
-
* - Does **not** affect instance prototypes (use `defineIfNotExists` for `Foo.prototype`).
|
|
7
|
-
* - The property is created with: { enumerable: false, configurable: false, writable: false }
|
|
8
|
-
* making it non-enumerable and immutable after definition.
|
|
9
|
-
* - If an existing property is non-configurable AND non-writable, it will **not** be replaced.
|
|
10
|
-
*
|
|
11
|
-
* @template T
|
|
12
|
-
* @param {T} constructor The constructor object (e.g., `Array`, `String`, `Map`, ...)
|
|
13
|
-
* @param {string} name The name of the static method to define (e.g., `'create'`, `'range'`)
|
|
14
|
-
* @param {Function} fn The function to attach as a static property
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* // Define Array.range if possible
|
|
18
|
-
* defineStaticIfNotExists(Array, 'range', function(start: number, end?: number) { ... });
|
|
19
|
-
*
|
|
20
|
-
* @remarks
|
|
21
|
-
* - To force replacement, delete the property first or use Object.defineProperty directly.
|
|
22
|
-
* - This function is meant to standardize the addition of static methods in utilitish.
|
|
23
|
-
*/
|
|
24
|
-
export declare const defineStaticIfNotExists: <T extends object>(constructor: T, name: string, fn: Function) => void;
|
|
25
|
-
export declare function resolveSelector<T, R>(selector?: keyof T | ((item: T) => R), fallback?: (item: T, index?: number) => R, name?: string): (item: T, index?: number) => R;
|
|
26
|
-
export declare function assertValidSelector<T, R>(selector: any, name?: string): asserts selector is Selector<T, R>;
|
|
27
|
-
export declare function isNumberOrString(value: unknown): value is string | number;
|
|
28
|
-
export type Selector<T, K> = keyof T | ((item: T) => K);
|
package/dist/utils.js
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.defineStaticIfNotExists = exports.defineIfNotExists = void 0;
|
|
4
|
-
exports.resolveSelector = resolveSelector;
|
|
5
|
-
exports.assertValidSelector = assertValidSelector;
|
|
6
|
-
exports.isNumberOrString = isNumberOrString;
|
|
7
|
-
const defineIfNotExists = (prototype, name, fn) => {
|
|
8
|
-
const descriptor = Object.getOwnPropertyDescriptor(prototype, name);
|
|
9
|
-
if (!descriptor || descriptor.writable || descriptor.configurable) {
|
|
10
|
-
Object.defineProperty(prototype, name, {
|
|
11
|
-
value: fn,
|
|
12
|
-
enumerable: false,
|
|
13
|
-
configurable: false,
|
|
14
|
-
writable: false,
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
exports.defineIfNotExists = defineIfNotExists;
|
|
19
|
-
/**
|
|
20
|
-
* Defines a **static** property on a constructor if it does not already exist
|
|
21
|
-
* (or if the existing property is writable **or** configurable).
|
|
22
|
-
*
|
|
23
|
-
* - Does **not** affect instance prototypes (use `defineIfNotExists` for `Foo.prototype`).
|
|
24
|
-
* - The property is created with: { enumerable: false, configurable: false, writable: false }
|
|
25
|
-
* making it non-enumerable and immutable after definition.
|
|
26
|
-
* - If an existing property is non-configurable AND non-writable, it will **not** be replaced.
|
|
27
|
-
*
|
|
28
|
-
* @template T
|
|
29
|
-
* @param {T} constructor The constructor object (e.g., `Array`, `String`, `Map`, ...)
|
|
30
|
-
* @param {string} name The name of the static method to define (e.g., `'create'`, `'range'`)
|
|
31
|
-
* @param {Function} fn The function to attach as a static property
|
|
32
|
-
*
|
|
33
|
-
* @example
|
|
34
|
-
* // Define Array.range if possible
|
|
35
|
-
* defineStaticIfNotExists(Array, 'range', function(start: number, end?: number) { ... });
|
|
36
|
-
*
|
|
37
|
-
* @remarks
|
|
38
|
-
* - To force replacement, delete the property first or use Object.defineProperty directly.
|
|
39
|
-
* - This function is meant to standardize the addition of static methods in utilitish.
|
|
40
|
-
*/
|
|
41
|
-
const defineStaticIfNotExists = (constructor, name, fn) => {
|
|
42
|
-
const descriptor = Object.getOwnPropertyDescriptor(constructor, name);
|
|
43
|
-
if (!descriptor || descriptor.writable || descriptor.configurable) {
|
|
44
|
-
Object.defineProperty(constructor, name, {
|
|
45
|
-
value: fn,
|
|
46
|
-
enumerable: false,
|
|
47
|
-
configurable: false,
|
|
48
|
-
writable: false,
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
exports.defineStaticIfNotExists = defineStaticIfNotExists;
|
|
53
|
-
function resolveSelector(selector, fallback, name = 'selector') {
|
|
54
|
-
assertValidSelector(selector);
|
|
55
|
-
if (typeof selector === 'function') {
|
|
56
|
-
return selector;
|
|
57
|
-
}
|
|
58
|
-
if (typeof selector === 'string') {
|
|
59
|
-
return (item) => item[selector];
|
|
60
|
-
}
|
|
61
|
-
if (selector) {
|
|
62
|
-
throw new TypeError(`${name} must be a function or a string key`);
|
|
63
|
-
}
|
|
64
|
-
if (fallback) {
|
|
65
|
-
if (typeof fallback === 'function') {
|
|
66
|
-
return fallback;
|
|
67
|
-
}
|
|
68
|
-
throw new TypeError(`fallback must be a function`);
|
|
69
|
-
}
|
|
70
|
-
throw new TypeError(`fallback must be given if no selector`);
|
|
71
|
-
}
|
|
72
|
-
function assertValidSelector(selector, name = 'selector') {
|
|
73
|
-
const isValid = typeof selector === 'function' || typeof selector === 'string';
|
|
74
|
-
if (selector !== undefined && !isValid) {
|
|
75
|
-
throw new TypeError(`${name} must be a function or a string key`);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
function isNumberOrString(value) {
|
|
79
|
-
return typeof value === 'string' || typeof value === 'number';
|
|
80
|
-
}
|