utilitish 0.0.11 → 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.
package/LICENSE.txt CHANGED
@@ -1,25 +1,25 @@
1
- GNU GENERAL PUBLIC LICENSE
2
- Version 3, 29 June 2007
3
-
4
- Copyright (C) 2025 Donovan Ferreira
5
-
6
- Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
7
-
8
- Preamble
9
-
10
- The GNU General Public License is a free, copyleft license for
11
- software and other kinds of works.
12
-
13
- The licenses for most software and other practical works are designed
14
- to take away your freedom to share and change the works. By contrast,
15
- the GNU General Public License is intended to guarantee your freedom to
16
- share and change all versions of a program--to make sure it remains free
17
- software for all its users. We, the Free Software Foundation, use the
18
- GNU General Public License for most of our software; it applies also to
19
- any other work released this way by its authors. You can apply it to
20
- your programs, too.
21
-
22
- [... contenu tronqué pour l’aperçu ...]
23
-
24
- You should have received a copy of the GNU General Public License
25
- along with this program. If not, see <https://www.gnu.org/licenses/>.
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2025 Donovan Ferreira
5
+
6
+ Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
7
+
8
+ Preamble
9
+
10
+ The GNU General Public License is a free, copyleft license for
11
+ software and other kinds of works.
12
+
13
+ The licenses for most software and other practical works are designed
14
+ to take away your freedom to share and change the works. By contrast,
15
+ the GNU General Public License is intended to guarantee your freedom to
16
+ share and change all versions of a program--to make sure it remains free
17
+ software for all its users. We, the Free Software Foundation, use the
18
+ GNU General Public License for most of our software; it applies also to
19
+ any other work released this way by its authors. You can apply it to
20
+ your programs, too.
21
+
22
+ [... contenu tronqué pour l’aperçu ...]
23
+
24
+ You should have received a copy of the GNU General Public License
25
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
package/README.md CHANGED
@@ -1,68 +1,68 @@
1
- ## Licence
2
-
3
- Ce projet est distribué sous licence [GPL v3](https://www.gnu.org/licenses/gpl-3.0.html) © 2025 Donovan Ferreira.
4
-
5
- Ceci est une petite librairie qui ajoute plusieurs méthodes au prototype JavaScript.
6
-
7
- ## Configuration Slugify
8
-
9
- La méthode `slugify()` peut être personnalisée pour répondre à vos besoins spécifiques. Consultez la JSDoc dans votre IDE pour voir tous les exemples disponibles.
10
-
11
- ### Configuration globale
12
-
13
- Vous pouvez définir une configuration globale qui s'appliquera à tous les appels `slugify()` :
14
-
15
- ```typescript
16
- import { setSlugifyConfig } from 'utilitish';
17
-
18
- // Configuration pour remplacer les symboles de genre
19
- setSlugifyConfig(
20
- SlugifyConfig.builder()
21
- .withSeparator('_')
22
- .withCustomReplacements({
23
- '♀': 'feminin',
24
- '♂': 'masculin',
25
- '@': 'at',
26
- })
27
- .build(),
28
- );
29
-
30
- 'Test ♀'.slugify(); // "test_feminin"
31
- 'User♂@domain.com'.slugify(); // "usermasculinatdomain_com"
32
- ```
33
-
34
- ### Configuration par appel
35
-
36
- Vous pouvez aussi passer une configuration spécifique à chaque appel :
37
-
38
- ```typescript
39
- // Utilise la config globale
40
- 'Hello World'.slugify(); // "hello-world"
41
-
42
- // Override la config pour cet appel
43
- 'Hello World'.slugify(SlugifyConfig.builder().withSeparator('_').build()); // "hello_world"
44
- ```
45
-
46
- ### Options de configuration
47
-
48
- - **`customReplacements`**: Remplacer des caractères spécifiques (ex: "♀" → "feminin")
49
- - **`separator`**: Caractère de séparation (défaut: "-")
50
- - **`lowercase`**: Convertir en minuscules (défaut: true)
51
- - **`removeAccents`**: Supprimer les accents (défaut: true)
52
- - **`allowedChars`**: Regex des caractères autorisés (défaut: /[a-zA-Z0-9]/)
53
- - **`maxLength`**: Longueur maximale du slug
54
- - **`transformers`**: Fonctions de transformation personnalisées
55
-
56
- ### Gestion de la configuration
57
-
58
- ```typescript
59
- import { getSlugifyConfig, resetSlugifyConfig } from 'utilitish';
60
-
61
- // Obtenir la config actuelle
62
- const currentConfig = getSlugifyConfig();
63
-
64
- // Réinitialiser aux valeurs par défaut
65
- resetSlugifyConfig();
66
- ```
67
-
68
- Pour plus d'exemples et cas d'usage avancés, consultez les JSDoc intégrées dans votre IDE.
1
+ ## Licence
2
+
3
+ Ce projet est distribué sous licence [GPL v3](https://www.gnu.org/licenses/gpl-3.0.html) © 2025 Donovan Ferreira.
4
+
5
+ Ceci est une petite librairie qui ajoute plusieurs méthodes au prototype JavaScript.
6
+
7
+ ## Configuration Slugify
8
+
9
+ La méthode `slugify()` peut être personnalisée pour répondre à vos besoins spécifiques. Consultez la JSDoc dans votre IDE pour voir tous les exemples disponibles.
10
+
11
+ ### Configuration globale
12
+
13
+ Vous pouvez définir une configuration globale qui s'appliquera à tous les appels `slugify()` :
14
+
15
+ ```typescript
16
+ import { setSlugifyConfig } from 'utilitish';
17
+
18
+ // Configuration pour remplacer les symboles de genre
19
+ setSlugifyConfig(
20
+ SlugifyConfig.builder()
21
+ .withSeparator('_')
22
+ .withCustomReplacements({
23
+ '♀': 'feminin',
24
+ '♂': 'masculin',
25
+ '@': 'at',
26
+ })
27
+ .build(),
28
+ );
29
+
30
+ 'Test ♀'.slugify(); // "test_feminin"
31
+ 'User♂@domain.com'.slugify(); // "usermasculinatdomain_com"
32
+ ```
33
+
34
+ ### Configuration par appel
35
+
36
+ Vous pouvez aussi passer une configuration spécifique à chaque appel :
37
+
38
+ ```typescript
39
+ // Utilise la config globale
40
+ 'Hello World'.slugify(); // "hello-world"
41
+
42
+ // Override la config pour cet appel
43
+ 'Hello World'.slugify(SlugifyConfig.builder().withSeparator('_').build()); // "hello_world"
44
+ ```
45
+
46
+ ### Options de configuration
47
+
48
+ - **`customReplacements`**: Remplacer des caractères spécifiques (ex: "♀" → "feminin")
49
+ - **`separator`**: Caractère de séparation (défaut: "-")
50
+ - **`lowercase`**: Convertir en minuscules (défaut: true)
51
+ - **`removeAccents`**: Supprimer les accents (défaut: true)
52
+ - **`allowedChars`**: Regex des caractères autorisés (défaut: /[a-zA-Z0-9]/)
53
+ - **`maxLength`**: Longueur maximale du slug
54
+ - **`transformers`**: Fonctions de transformation personnalisées
55
+
56
+ ### Gestion de la configuration
57
+
58
+ ```typescript
59
+ import { getSlugifyConfig, resetSlugifyConfig } from 'utilitish';
60
+
61
+ // Obtenir la config actuelle
62
+ const currentConfig = getSlugifyConfig();
63
+
64
+ // Réinitialiser aux valeurs par défaut
65
+ resetSlugifyConfig();
66
+ ```
67
+
68
+ Pour plus d'exemples et cas d'usage avancés, consultez les JSDoc intégrées dans votre IDE.
@@ -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
  });