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 +25 -25
- package/README.md +68 -68
- package/dist/array/array-constructor.js +8 -4
- package/dist/array/array-prototype.d.ts +21 -0
- package/dist/array/array-prototype.js +94 -17
- package/dist/array/array-prototype.spec.js +16 -16
- package/dist/map/map-prototype.js +18 -18
- package/dist/object/object-prototype.js +4 -3
- package/dist/set/set-prototype.d.ts +1 -1
- package/dist/set/set-prototype.js +4 -4
- package/dist/string/string-prototype.d.ts +88 -11
- package/dist/string/string-prototype.js +59 -19
- package/dist/string/string-prototype.spec.js +20 -20
- package/dist/test.html +13 -0
- package/dist/utils/core.utils.d.ts +1 -0
- package/dist/utils/core.utils.js +6 -1
- package/dist/utils/core.utils.spec.d.ts +1 -0
- package/dist/utils/core.utils.spec.js +150 -0
- package/dist/utils/logic.utils.js +4 -0
- package/dist/utils/logic.utils.spec.d.ts +1 -0
- package/dist/utils/logic.utils.spec.js +57 -0
- package/dist/utils/slugify.config.d.ts +9 -0
- package/dist/utils/slugify.config.js +15 -0
- package/dist/utils/slugify.config.spec.d.ts +1 -0
- package/dist/utils/slugify.config.spec.js +144 -0
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +15 -0
- package/package.json +4 -2
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
|
-
|
|
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'
|
|
35
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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'
|
|
25
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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'
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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(
|
|
101
|
-
expect(() => arr.chunk(-1)).toThrow(
|
|
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
|
|
17
|
-
|
|
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
|
-
|
|
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
|
|
39
|
-
|
|
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
|
-
|
|
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
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
|
|
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
|
});
|