utilitish 0.0.14 → 0.0.15

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.
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_utils_1 = require("../utils/core.utils");
4
+ const core_utils_2 = require("./../utils/core.utils");
4
5
  /**
5
6
  * @see Array.zip
6
7
  */
@@ -19,7 +20,7 @@ const core_utils_1 = require("../utils/core.utils");
19
20
  start = 0;
20
21
  }
21
22
  if (step === 0)
22
- throw new Error('step must not be 0');
23
+ (0, core_utils_2.utilitishError)('Array.range', 'step must not be 0', undefined, RangeError);
23
24
  const result = [];
24
25
  const condition = step > 0 ? (i) => i < end : (i) => i > end;
25
26
  for (let i = start; condition(i); i += step) {
@@ -31,9 +32,12 @@ const core_utils_1 = require("../utils/core.utils");
31
32
  * @see Array.repeat
32
33
  */
33
34
  (0, core_utils_1.defineStaticIfNotExists)(Array, 'repeat', function (length, value) {
34
- if (typeof length !== 'number' || !Number.isInteger(length) || length < 0) {
35
- throw new TypeError('Length must be a non-negative integer');
36
- }
35
+ if (typeof length !== 'number')
36
+ (0, core_utils_2.utilitishError)('Array.repeat', 'n must be a number', length);
37
+ if (!Number.isInteger(length))
38
+ (0, core_utils_2.utilitishError)('Array.repeat', 'n must be an integer', length);
39
+ if (length < 0)
40
+ (0, core_utils_2.utilitishError)('Array.repeat', 'n must be non-negative', length, RangeError);
37
41
  return Array.from({ length }, () => (typeof value === 'function' ? value() : value));
38
42
  });
39
43
  /**
@@ -386,5 +386,26 @@ declare global {
386
386
  * - Empty array returns empty Map
387
387
  */
388
388
  countBy<K>(this: T[], selector?: Selector<T, K>): Map<T | K, number>;
389
+ /**
390
+ * Checks if the slugified version of a value matches any slugified string in this array.
391
+ * Useful for case-insensitive and accent-insensitive array search.
392
+ *
393
+ * @this {string[]} The array of strings to search in.
394
+ * @param {string} value - The string to search for.
395
+ * @returns {boolean} `true` if any slugified item in the array equals the slugified `value`, `false` otherwise.
396
+ * @throws {TypeError} If `value` is not a string.
397
+ * @throws {TypeError} If any item in the array is not a string.
398
+ *
399
+ * @example
400
+ * ['Hello World', 'Foo Bar'].slugifyIncludes('hello-world'); // true
401
+ * ['Héllo World', 'Foo Bar'].slugifyIncludes('hello-world'); // true
402
+ * ['Hello World', 'Foo Bar'].slugifyIncludes('baz'); // false
403
+ *
404
+ * @remarks
405
+ * - All strings are slugified before comparison.
406
+ * - Since `slugify` is idempotent, passing an already-slugified value works as expected.
407
+ * - Throws on the first non-string item encountered in the array.
408
+ */
409
+ slugifyIncludes(value: string): boolean;
389
410
  }
390
411
  }
@@ -2,43 +2,67 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const core_utils_1 = require("../utils/core.utils");
4
4
  const logic_utils_1 = require("../utils/logic.utils");
5
+ /**
6
+ * @see Array.prototype.first
7
+ */
5
8
  (0, core_utils_1.defineIfNotExists)(Array.prototype, 'first', function () {
6
9
  return this[0];
7
10
  });
11
+ /**
12
+ * @see Array.prototype.last
13
+ */
8
14
  (0, core_utils_1.defineIfNotExists)(Array.prototype, 'last', function () {
9
15
  return this[this.length - 1];
10
16
  });
17
+ /**
18
+ * @see Array.prototype.sum
19
+ */
11
20
  (0, core_utils_1.defineIfNotExists)(Array.prototype, 'sum', function (selector) {
12
21
  if (this.length === 0)
13
22
  return 0;
14
23
  const getValue = (0, core_utils_1.resolveSelector)(selector, (item) => item);
15
- if (this.every((item) => typeof getValue(item) === 'number')) {
16
- return this.reduce((acc, item) => getValue(item) + acc, 0);
24
+ if (!this.every((item) => typeof getValue(item) === 'number')) {
25
+ (0, core_utils_1.utilitishError)('Array.prototype.sum', 'requires a selector that returns a number unless array is number[]');
17
26
  }
18
- throw new TypeError('Array.prototype.sum() requires a selector who return a number unless array is number[]');
27
+ return this.reduce((acc, item) => getValue(item) + acc, 0);
19
28
  });
29
+ /**
30
+ * @see Array.prototype.unique
31
+ */
20
32
  (0, core_utils_1.defineIfNotExists)(Array.prototype, 'unique', function () {
21
33
  return [...new Set(this)];
22
34
  });
35
+ /**
36
+ * @see Array.prototype.chunk
37
+ */
23
38
  (0, core_utils_1.defineIfNotExists)(Array.prototype, 'chunk', function (size) {
24
- if (typeof size !== 'number' || !Number.isInteger(size) || size <= 0) {
25
- throw new TypeError('Chunk size must be a positive integer');
26
- }
39
+ if (typeof size !== 'number')
40
+ (0, core_utils_1.utilitishError)('Array.prototype.chunk', 'size must be a number', size);
41
+ if (!Number.isInteger(size))
42
+ (0, core_utils_1.utilitishError)('Array.prototype.chunk', 'size must be an integer', size);
43
+ if (size <= 0)
44
+ (0, core_utils_1.utilitishError)('Array.prototype.chunk', 'size must be positive', size, RangeError);
27
45
  const result = [];
28
46
  for (let i = 0; i < this.length; i += size) {
29
47
  result.push(this.slice(i, i + size));
30
48
  }
31
49
  return result;
32
50
  });
51
+ /**
52
+ * @see Array.prototype.average
53
+ */
33
54
  (0, core_utils_1.defineIfNotExists)(Array.prototype, 'average', function (selector) {
34
55
  if (this.length === 0)
35
56
  return 0;
36
57
  const getValue = (0, core_utils_1.resolveSelector)(selector, (item) => item);
37
- if (this.every((item) => typeof getValue(item) === 'number')) {
38
- return this.reduce((acc, item) => getValue(item) + acc, 0) / this.length;
58
+ if (!this.every((item) => typeof getValue(item) === 'number')) {
59
+ (0, core_utils_1.utilitishError)('Array.prototype.average', 'requires a selector that returns a number unless array is number[]');
39
60
  }
40
- throw new TypeError('Array.prototype.average() requires a selector who return a number unless array is number[]');
61
+ return this.reduce((acc, item) => getValue(item) + acc, 0) / this.length;
41
62
  });
63
+ /**
64
+ * @see Array.prototype.groupBy
65
+ */
42
66
  (0, core_utils_1.defineIfNotExists)(Array.prototype, 'groupBy', function (selector) {
43
67
  const getKey = (0, core_utils_1.resolveSelector)(selector, (item) => item);
44
68
  const map = new Map();
@@ -51,24 +75,34 @@ const logic_utils_1 = require("../utils/logic.utils");
51
75
  }
52
76
  return map;
53
77
  });
78
+ /**
79
+ * @see Array.prototype.compact
80
+ */
54
81
  (0, core_utils_1.defineIfNotExists)(Array.prototype, 'compact', function () {
55
82
  return this.filter(Boolean);
56
83
  });
84
+ /**
85
+ * @see Array.prototype.enumerate
86
+ */
57
87
  (0, core_utils_1.defineIfNotExists)(Array.prototype, 'enumerate', function () {
58
88
  return this.map((value, index) => [value, index]);
59
89
  });
90
+ /**
91
+ * @see Array.prototype.sortAsc
92
+ * @see Array.prototype.sortDesc
93
+ */
60
94
  (0, core_utils_1.defineIfNotExists)(Array.prototype, 'sortBy', function (direction, selector) {
61
95
  if (this.length === 0)
62
96
  return this.slice();
63
97
  const getValue = (0, core_utils_1.resolveSelector)(selector, (item) => item);
64
98
  if (!selector && !this.every((item) => (0, core_utils_1.isNumberOrString)(item))) {
65
- throw new TypeError('Array elements must be number or string if no selector is provided');
99
+ (0, core_utils_1.utilitishError)('Array.prototype.sortBy', 'array elements must be number or string if no selector is provided');
66
100
  }
67
101
  return this.slice().sort((a, b) => {
68
102
  const valA = getValue(a);
69
103
  const valB = getValue(b);
70
104
  if (!(0, core_utils_1.isNumberOrString)(valA) || !(0, core_utils_1.isNumberOrString)(valB)) {
71
- throw new TypeError('Selector must return number or string');
105
+ (0, core_utils_1.utilitishError)('Array.prototype.sortBy', 'selector must return number or string');
72
106
  }
73
107
  if (valA > valB)
74
108
  return direction === 'asc' ? 1 : -1;
@@ -77,19 +111,34 @@ const logic_utils_1 = require("../utils/logic.utils");
77
111
  return 0;
78
112
  });
79
113
  });
114
+ /**
115
+ * @see Array.prototype.sortAsc
116
+ */
80
117
  (0, core_utils_1.defineIfNotExists)(Array.prototype, 'sortAsc', function (selector) {
81
118
  return (0, logic_utils_1.sortBy)(this, 'asc', selector);
82
119
  });
120
+ /**
121
+ * @see Array.prototype.sortDesc
122
+ */
83
123
  (0, core_utils_1.defineIfNotExists)(Array.prototype, 'sortDesc', function (selector) {
84
124
  return (0, logic_utils_1.sortBy)(this, 'desc', selector);
85
125
  });
126
+ /**
127
+ * @see Array.prototype.swap
128
+ */
86
129
  (0, core_utils_1.defineIfNotExists)(Array.prototype, 'swap', function (i, j) {
87
- if (typeof i !== 'number' || typeof j !== 'number' || !Number.isInteger(i) || !Number.isInteger(j)) {
88
- throw new TypeError('Indices must be integers');
89
- }
90
- if (i < 0 || i >= this.length || j < 0 || j >= this.length) {
91
- throw new RangeError('Index out of bounds');
92
- }
130
+ if (typeof i !== 'number')
131
+ (0, core_utils_1.utilitishError)('Array.prototype.swap', 'i must be a number', i);
132
+ if (typeof j !== 'number')
133
+ (0, core_utils_1.utilitishError)('Array.prototype.swap', 'j must be a number', j);
134
+ if (!Number.isInteger(i))
135
+ (0, core_utils_1.utilitishError)('Array.prototype.swap', 'i must be an integer', i);
136
+ if (!Number.isInteger(j))
137
+ (0, core_utils_1.utilitishError)('Array.prototype.swap', 'j must be an integer', j);
138
+ if (i < 0 || i >= this.length)
139
+ (0, core_utils_1.utilitishError)('Array.prototype.swap', 'i is out of bounds', i, RangeError);
140
+ if (j < 0 || j >= this.length)
141
+ (0, core_utils_1.utilitishError)('Array.prototype.swap', 'j is out of bounds', j, RangeError);
93
142
  if (i !== j) {
94
143
  const temp = this[i];
95
144
  this[i] = this[j];
@@ -97,6 +146,9 @@ const logic_utils_1 = require("../utils/logic.utils");
97
146
  }
98
147
  return this;
99
148
  });
149
+ /**
150
+ * @see Array.prototype.shuffle
151
+ */
100
152
  (0, core_utils_1.defineIfNotExists)(Array.prototype, 'shuffle', function () {
101
153
  const arr = this.slice();
102
154
  for (let i = arr.length - 1; i > 0; i--) {
@@ -105,6 +157,9 @@ const logic_utils_1 = require("../utils/logic.utils");
105
157
  }
106
158
  return arr;
107
159
  });
160
+ /**
161
+ * @see Array.prototype.toMap
162
+ */
108
163
  (0, core_utils_1.defineIfNotExists)(Array.prototype, 'toMap', function (keySelector, valueSelector) {
109
164
  if (!keySelector && this.length && this.every((item) => Array.isArray(item) && item.length === 2)) {
110
165
  return new Map(this);
@@ -120,6 +175,9 @@ const logic_utils_1 = require("../utils/logic.utils");
120
175
  }
121
176
  return map;
122
177
  });
178
+ /**
179
+ * @see Array.prototype.toObject
180
+ */
123
181
  (0, core_utils_1.defineIfNotExists)(Array.prototype, 'toObject', function (keySelector, valueSelector) {
124
182
  let entries;
125
183
  if (!keySelector && this.length && this.every((item) => Array.isArray(item) && item.length === 2)) {
@@ -142,10 +200,16 @@ const logic_utils_1 = require("../utils/logic.utils");
142
200
  }
143
201
  return Object.fromEntries(entries);
144
202
  });
203
+ /**
204
+ * @see Array.prototype.toSet
205
+ */
145
206
  (0, core_utils_1.defineIfNotExists)(Array.prototype, 'toSet', function (selector) {
146
207
  const getValue = (0, core_utils_1.resolveSelector)(selector, (item) => item);
147
208
  return new Set(this.map(getValue));
148
209
  });
210
+ /**
211
+ * @see Array.prototype.countBy
212
+ */
149
213
  (0, core_utils_1.defineIfNotExists)(Array.prototype, 'countBy', function (selector) {
150
214
  const getKey = (0, core_utils_1.resolveSelector)(selector, (item) => item);
151
215
  const map = new Map();
@@ -155,3 +219,16 @@ const logic_utils_1 = require("../utils/logic.utils");
155
219
  }
156
220
  return map;
157
221
  });
222
+ /**
223
+ * @see Array.prototype.slugifyIncludes
224
+ */
225
+ (0, core_utils_1.defineIfNotExists)(Array.prototype, 'slugifyIncludes', function (value) {
226
+ if (typeof value !== 'string')
227
+ (0, core_utils_1.utilitishError)('Array.prototype.slugifyIncludes', 'must be a string', value);
228
+ const slugified = value.slugify();
229
+ return this.some((item) => {
230
+ if (typeof item !== 'string')
231
+ (0, core_utils_1.utilitishError)('Array.prototype.slugifyIncludes', 'all array items must be strings', item);
232
+ return item.slugify() === slugified;
233
+ });
234
+ });
@@ -97,8 +97,8 @@ describe('Array.prototype', () => {
97
97
  describe('error handling', () => {
98
98
  it('should throw TypeError when size is not a positive integer', () => {
99
99
  const arr = [1, 2, 3];
100
- expect(() => arr.chunk(0)).toThrow(TypeError);
101
- expect(() => arr.chunk(-1)).toThrow(TypeError);
100
+ expect(() => arr.chunk(0)).toThrow(RangeError);
101
+ expect(() => arr.chunk(-1)).toThrow(RangeError);
102
102
  expect(() => arr.chunk(1.5)).toThrow(TypeError);
103
103
  expect(() => arr.chunk('a')).toThrow(TypeError);
104
104
  });
@@ -409,7 +409,7 @@ describe('Array.prototype', () => {
409
409
  });
410
410
  });
411
411
  describe('Array.prototype.toObject', () => {
412
- it('converts array of pairs to object', () => {
412
+ it('should converts array of pairs to object', () => {
413
413
  const arr = [
414
414
  ['a', 1],
415
415
  ['b', 2],
@@ -419,7 +419,7 @@ describe('Array.prototype', () => {
419
419
  expect(obj).toEqual({ a: 1, b: 2, c: 3 });
420
420
  expect(typeof obj).toBe('object');
421
421
  });
422
- it('converts array of pairs with numeric keys to object', () => {
422
+ it('should converts array of pairs with numeric keys to object', () => {
423
423
  const arr = [
424
424
  [1, 'a'],
425
425
  [2, 'b'],
@@ -428,7 +428,7 @@ describe('Array.prototype', () => {
428
428
  const obj = arr.toObject();
429
429
  expect(obj).toEqual({ 1: 'a', 2: 'b', 3: 'c' });
430
430
  });
431
- it('converts array of objects to object using key string', () => {
431
+ it('should converts array of objects to object using key string', () => {
432
432
  const arr = [
433
433
  { id: 1, name: 'foo' },
434
434
  { id: 2, name: 'bar' },
@@ -439,7 +439,7 @@ describe('Array.prototype', () => {
439
439
  2: { id: 2, name: 'bar' },
440
440
  });
441
441
  });
442
- it('converts array of objects to object using key callback', () => {
442
+ it('should converts array of objects to object using key callback', () => {
443
443
  const arr = [
444
444
  { id: 1, name: 'foo' },
445
445
  { id: 2, name: 'bar' },
@@ -450,7 +450,7 @@ describe('Array.prototype', () => {
450
450
  2: { id: 2, name: 'bar' },
451
451
  });
452
452
  });
453
- it('converts array of objects using key callback and value callback', () => {
453
+ it('should converts array of objects using key callback and value callback', () => {
454
454
  const arr = [
455
455
  { id: 1, name: 'foo' },
456
456
  { id: 2, name: 'bar' },
@@ -461,7 +461,7 @@ describe('Array.prototype', () => {
461
461
  2: 'bar',
462
462
  });
463
463
  });
464
- it('converts array without selector (uses index as key)', () => {
464
+ it('should converts array without selector (uses index as key)', () => {
465
465
  const arr = ['a', 'b', 'c'];
466
466
  const obj = arr.toObject();
467
467
  expect(obj).toEqual({
@@ -470,12 +470,12 @@ describe('Array.prototype', () => {
470
470
  2: 'c',
471
471
  });
472
472
  });
473
- it('converts empty array to empty object', () => {
473
+ it('should converts empty array to empty object', () => {
474
474
  const arr = [];
475
475
  const obj = arr.toObject();
476
476
  expect(obj).toEqual({});
477
477
  });
478
- it('handles objects with string and numeric keys', () => {
478
+ it('should handles objects with string and numeric keys', () => {
479
479
  const arr = [
480
480
  { key: 'name', value: 'Alice' },
481
481
  { key: 'age', value: 30 },
@@ -486,19 +486,19 @@ describe('Array.prototype', () => {
486
486
  age: 30,
487
487
  });
488
488
  });
489
- it('throws error when key selector returns null', () => {
489
+ it('should throws error when key selector returns null', () => {
490
490
  const arr = [{ id: 1, name: 'foo' }];
491
491
  expect(() => arr.toObject((x) => null, (x) => x.name)).toThrow(TypeError);
492
492
  });
493
- it('throws error when key selector returns undefined', () => {
493
+ it('should throws error when key selector returns undefined', () => {
494
494
  const arr = [{ id: 1, name: 'foo' }];
495
495
  expect(() => arr.toObject((x) => undefined, (x) => x.name)).toThrow(TypeError);
496
496
  });
497
- it('throws error when key is not a string or number', () => {
497
+ it('should throws error when key is not a string or number', () => {
498
498
  const arr = [{ id: { nested: 1 }, name: 'foo' }];
499
499
  expect(() => arr.toObject((x) => x.id)).toThrow(TypeError);
500
500
  });
501
- it('overwrites duplicate keys with the last value', () => {
501
+ it('should overwrites duplicate keys with the last value', () => {
502
502
  const arr = [
503
503
  { id: 1, value: 'first' },
504
504
  { id: 1, value: 'second' },
@@ -508,7 +508,7 @@ describe('Array.prototype', () => {
508
508
  1: 'second',
509
509
  });
510
510
  });
511
- it('handles mixed types in array', () => {
511
+ it('should handles mixed types in array', () => {
512
512
  const arr = [
513
513
  { id: 'x', value: 10 },
514
514
  { id: 'y', value: 20 },
@@ -519,7 +519,7 @@ describe('Array.prototype', () => {
519
519
  y: 20,
520
520
  });
521
521
  });
522
- it('converts with string key and different value types', () => {
522
+ it('should converts with string key and different value types', () => {
523
523
  const arr = [
524
524
  { id: 1, data: 'text' },
525
525
  { id: 2, data: 42 },
@@ -13,20 +13,17 @@ const core_utils_1 = require("../utils/core.utils");
13
13
  case 'object': {
14
14
  const obj = {};
15
15
  for (const [key, value] of this) {
16
- if (typeof key === 'string' || typeof key === 'number' || typeof key === 'symbol') {
17
- // For number keys, convert to string (object keys are always strings or symbols)
18
- obj[String(key)] = value;
19
- }
20
- else {
21
- throw new TypeError(`Map.prototype.toList('object') only supports string, number, or symbol keys. Got: ${typeof key}`);
16
+ if (typeof key !== 'string' && typeof key !== 'number' && typeof key !== 'symbol') {
17
+ (0, core_utils_1.utilitishError)('Map.prototype.toList', `only supports string, number, or symbol keys`, key);
22
18
  }
19
+ obj[String(key)] = value;
23
20
  }
24
21
  return obj;
25
22
  }
26
23
  case 'entries':
27
24
  return Array.from(this.entries());
28
25
  default:
29
- throw new TypeError(`Unknown type "${type}" for Map.prototype.toList`);
26
+ return (0, core_utils_1.utilitishError)('Map.prototype.toList', `unknown type`, type);
30
27
  }
31
28
  });
32
29
  /**
@@ -35,12 +32,13 @@ const core_utils_1 = require("../utils/core.utils");
35
32
  (0, core_utils_1.defineIfNotExists)(Map.prototype, 'toObject', function () {
36
33
  const entries = Array.from(this.entries());
37
34
  for (const [key] of entries) {
38
- if (key === null || key === undefined) {
39
- throw new TypeError(`Invalid key: key cannot be null or undefined. Key received: ${String(key)}`);
40
- }
35
+ if (key === null)
36
+ (0, core_utils_1.utilitishError)('Map.prototype.toObject', 'key cannot be null');
37
+ if (key === undefined)
38
+ (0, core_utils_1.utilitishError)('Map.prototype.toObject', 'key cannot be undefined');
41
39
  const keyType = typeof key;
42
40
  if (keyType !== 'string' && keyType !== 'number' && keyType !== 'symbol') {
43
- throw new TypeError(`Invalid key type: keys must be string, number, or symbol, received ${keyType}. Key value: ${String(key)}`);
41
+ (0, core_utils_1.utilitishError)('Map.prototype.toObject', `keys must be string, number, or symbol`, key);
44
42
  }
45
43
  }
46
44
  return Object.fromEntries(entries);
@@ -49,15 +47,17 @@ const core_utils_1 = require("../utils/core.utils");
49
47
  * @see Map.prototype.ensureArray
50
48
  */
51
49
  (0, core_utils_1.defineIfNotExists)(Map.prototype, 'ensureArray', function (key) {
52
- if (key === null || key === undefined) {
53
- throw new TypeError('Key cannot be null or undefined');
54
- }
55
- if (!this.has(key)) {
56
- this.set(key, []);
50
+ if (key === null)
51
+ (0, core_utils_1.utilitishError)('Map.prototype.ensureArray', 'key cannot be null');
52
+ if (key === undefined)
53
+ (0, core_utils_1.utilitishError)('Map.prototype.ensureArray', 'key cannot be undefined');
54
+ let arr = this.get(key);
55
+ if (arr === undefined) {
56
+ arr = [];
57
+ this.set(key, arr);
57
58
  }
58
- const arr = this.get(key);
59
59
  if (!Array.isArray(arr)) {
60
- throw new TypeError('Value for the key is not an array');
60
+ (0, core_utils_1.utilitishError)('Map.prototype.ensureArray', 'value for the key is not an array', arr);
61
61
  }
62
62
  return arr;
63
63
  });
@@ -11,9 +11,10 @@ const core_utils_1 = require("../utils/core.utils");
11
11
  * @see Object.prototype.deepMerge
12
12
  */
13
13
  (0, core_utils_1.defineIfNotExists)(Object.prototype, 'deepMerge', function (source) {
14
- if (typeof source !== 'object' || source === null) {
15
- throw new TypeError('Source must be a non-null object');
16
- }
14
+ if (typeof source !== 'object')
15
+ (0, core_utils_1.utilitishError)('Object.prototype.deepMerge', 'source must be an object', source);
16
+ if (source === null)
17
+ (0, core_utils_1.utilitishError)('Object.prototype.deepMerge', 'source cannot be null', source);
17
18
  const isObject = (val) => val !== null && typeof val === 'object' && !Array.isArray(val);
18
19
  const merge = (target, source) => {
19
20
  for (const key of Object.keys(source)) {
@@ -24,13 +24,11 @@ describe('Object.prototype', () => {
24
24
  const source = { b: { d: 3 }, e: 4 };
25
25
  const merged = obj.deepMerge(source);
26
26
  expect(merged).toEqual({ a: 1, b: { c: 2, d: 3 }, e: 4 });
27
- console.log(merged);
28
27
  });
29
28
  it('should overwrite primitive values', () => {
30
29
  const obj = { a: 1, b: 2 };
31
30
  const merged = obj.deepMerge({ b: 3 });
32
31
  expect(merged).toEqual({ a: 1, b: 3 });
33
- console.log(merged);
34
32
  });
35
33
  describe('error handling', () => {
36
34
  it('should throw if source is not an object', () => {
@@ -15,7 +15,7 @@ declare global {
15
15
  * - Returns a new array instance each time; modifying it does not affect the Set
16
16
  * - Empty sets return an empty array
17
17
  */
18
- toList<T>(): T[];
18
+ toList(): T[];
19
19
  /**
20
20
  * Returns true if at least one of the given items is present in the Set.
21
21
  *
@@ -13,7 +13,7 @@ const core_utils_1 = require("../utils/core.utils");
13
13
  */
14
14
  (0, core_utils_1.defineIfNotExists)(Set.prototype, 'hasAny', function (...items) {
15
15
  if (!Array.isArray(items))
16
- throw new TypeError('Arguments must be an array');
16
+ (0, core_utils_1.utilitishError)('Set.prototype.hasAny', 'arguments must be an array', items);
17
17
  if (items.length === 0)
18
18
  return false;
19
19
  return items.some((item) => this.has(item));
@@ -32,7 +32,7 @@ const core_utils_1 = require("../utils/core.utils");
32
32
  values = args;
33
33
  }
34
34
  if (!Array.isArray(values))
35
- throw new TypeError('Arguments must be an array or a Set');
35
+ (0, core_utils_1.utilitishError)('Set.prototype.includes', 'arguments must be an array or a Set', args);
36
36
  return values.every((item) => this.has(item));
37
37
  });
38
38
  /**
@@ -42,7 +42,7 @@ const core_utils_1 = require("../utils/core.utils");
42
42
  const result = new Set(this);
43
43
  for (const other of others) {
44
44
  if (!(other instanceof Set))
45
- throw new TypeError('Arguments must be Sets');
45
+ (0, core_utils_1.utilitishError)('Set.prototype.union', 'arguments must be Sets', other);
46
46
  for (const item of other) {
47
47
  result.add(item);
48
48
  }
@@ -54,7 +54,7 @@ const core_utils_1 = require("../utils/core.utils");
54
54
  */
55
55
  (0, core_utils_1.defineIfNotExists)(Set.prototype, 'intersection', function (...others) {
56
56
  if (others.some((s) => !(s instanceof Set)))
57
- throw new TypeError('Arguments must be Sets');
57
+ (0, core_utils_1.utilitishError)('Set.prototype.intersection', 'arguments must be Sets', others);
58
58
  const result = new Set();
59
59
  for (const item of this) {
60
60
  if (others.every((set) => set.has(item))) {
@@ -194,6 +194,103 @@ declare global {
194
194
  */
195
195
  slugify(): string;
196
196
  slugify(config: SlugifyConfig): string;
197
+ /**
198
+ * Compares two strings by slugifying both and checking if they are equal.
199
+ * Useful for case-insensitive and accent-insensitive string comparison.
200
+ *
201
+ * @this {string} The first string to compare.
202
+ * @param {string} other - The second string to compare.
203
+ * @returns {boolean} `true` if both slugified strings are equal, `false` otherwise.
204
+ * @throws {TypeError} If `other` is not a string.
205
+ *
206
+ * @example
207
+ * 'Hello World'.slugifyEquals('hello-world'); // true
208
+ * 'Héllo World'.slugifyEquals('hello-world'); // true
209
+ * 'Hello World'.slugifyEquals('goodbye-world'); // false
210
+ *
211
+ * @remarks
212
+ * - Both strings are slugified before comparison.
213
+ * - Since `slugify` is idempotent, passing an already-slugified string works as expected.
214
+ * - Useful for comparing user-provided strings with stored slugs.
215
+ */
216
+ slugifyEquals(other: string): boolean;
217
+ /**
218
+ * Checks if the slugified version of this string includes the slugified version of another.
219
+ * Useful for case-insensitive and accent-insensitive substring search.
220
+ *
221
+ * @this {string} The string to search in.
222
+ * @param {string} other - The string to search for.
223
+ * @returns {boolean} `true` if the slugified string contains the slugified `other`, `false` otherwise.
224
+ * @throws {TypeError} If `other` is not a string.
225
+ *
226
+ * @example
227
+ * 'Hello World'.slugifyIncludes('hello'); // true
228
+ * 'Héllo World'.slugifyIncludes('hello'); // true
229
+ * 'Hello World'.slugifyIncludes('goodbye'); // false
230
+ *
231
+ * @remarks
232
+ * - Both strings are slugified before comparison.
233
+ * - Since `slugify` is idempotent, passing an already-slugified string works as expected.
234
+ */
235
+ slugifyIncludes(other: string): boolean;
236
+ /**
237
+ * Checks if the slugified version of this string starts with the slugified version of another.
238
+ * Useful for case-insensitive and accent-insensitive prefix matching.
239
+ *
240
+ * @this {string} The string to check.
241
+ * @param {string} other - The prefix to check against.
242
+ * @returns {boolean} `true` if the slugified string starts with the slugified `other`, `false` otherwise.
243
+ * @throws {TypeError} If `other` is not a string.
244
+ *
245
+ * @example
246
+ * 'Hello World'.slugifyStartsWith('hello'); // true
247
+ * 'Héllo World'.slugifyStartsWith('hello'); // true
248
+ * 'Hello World'.slugifyStartsWith('world'); // false
249
+ *
250
+ * @remarks
251
+ * - Both strings are slugified before comparison.
252
+ * - Since `slugify` is idempotent, passing an already-slugified string works as expected.
253
+ */
254
+ slugifyStartsWith(other: string): boolean;
255
+ /**
256
+ * Checks if the slugified version of this string ends with the slugified version of another.
257
+ * Useful for case-insensitive and accent-insensitive suffix matching.
258
+ *
259
+ * @this {string} The string to check.
260
+ * @param {string} other - The suffix to check against.
261
+ * @returns {boolean} `true` if the slugified string ends with the slugified `other`, `false` otherwise.
262
+ * @throws {TypeError} If `other` is not a string.
263
+ *
264
+ * @example
265
+ * 'Hello World'.slugifyEndsWith('world'); // true
266
+ * 'Héllo World'.slugifyEndsWith('world'); // true
267
+ * 'Hello World'.slugifyEndsWith('hello'); // false
268
+ *
269
+ * @remarks
270
+ * - Both strings are slugified before comparison.
271
+ * - Since `slugify` is idempotent, passing an already-slugified string works as expected.
272
+ */
273
+ slugifyEndsWith(other: string): boolean;
274
+ /**
275
+ * Checks if the slugified version of this string matches any slugified string in a list.
276
+ * Useful for case-insensitive and accent-insensitive list lookup.
277
+ *
278
+ * @this {string} The string to search for.
279
+ * @param {string[]} list - The array of strings to search in.
280
+ * @returns {boolean} `true` if any slugified item in the list equals the slugified string, `false` otherwise.
281
+ * @throws {TypeError} If `list` is not an array.
282
+ * @throws {TypeError} If `list` contains non-string items.
283
+ *
284
+ * @example
285
+ * 'Hello World'.slugifyIn(['hello-world', 'foo']); // true
286
+ * 'Héllo World'.slugifyIn(['hello-world', 'foo']); // true
287
+ * 'Hello World'.slugifyIn(['foo', 'bar']); // false
288
+ *
289
+ * @remarks
290
+ * - All strings are slugified before comparison.
291
+ * - Since `slugify` is idempotent, mixing raw and already-slugified strings in the list works as expected.
292
+ */
293
+ slugifyIn(list: string[]): boolean;
197
294
  /**
198
295
  * Replaces a substring between `start` and `end` indices with a given string.
199
296
  * Provides precise control over which portion of the string to replace.