@salespark/toolkit 2.0.0 β†’ 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,556 +1,783 @@
1
- # SalesPark Toolkit v2 - Documentation
2
-
3
- ## @salespark/toolkit
4
-
5
- Shared toolkit of helpers and utilities for **Node.js**, **React**, and browser environments.
6
- Tree-shakeable, TypeScript-first, ESM + CJS outputs.
7
-
8
- [![Coverage](https://codecov.io/gh/FBlade/salespark-toolkit/branch/main/graph/badge.svg)](https://codecov.io/gh/FBlade/salespark-toolkit)
9
- [![npm version](https://img.shields.io/npm/v/%40salespark%2Ftoolkit.svg)](https://www.npmjs.com/package/@salespark/toolkit)
10
- ![types](https://img.shields.io/npm/types/%40salespark%2Ftoolkit)
11
- ![modules](https://img.shields.io/badge/modules-ESM%20%2B%20CJS-1f6feb)
12
- ![tree-shakeable](https://img.shields.io/badge/tree--shakeable-yes-success)
13
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](#-license)
14
-
15
- ---
16
-
17
- ## πŸ“¦ Install
18
-
19
- ```bash
20
- yarn add @salespark/toolkit
21
- # or
22
- npm i @salespark/toolkit
23
- ```
24
-
25
- ## ✨ Features
26
-
27
- - **Array utilities**: chunk, uniqBy, deep equality, flatten, etc.
28
- - **Object utilities**: pick, omit, clean objects, etc.
29
- - **String utilities**: slugify, template fill, deburr, sanitize, etc.
30
- - **Number utilities**: clamp, round, safe parse, random digits, etc.
31
- - **Boolean utilities**: safe boolean conversion with common representations.
32
- - **Function utilities**: debounce, throttle, nil/empty checks, formatBytes, string similarity, etc.
33
- - **Environment detection**: `isBrowser`, `isNode`.
34
-
35
- ---
36
-
37
- ## πŸš€ Usage
38
-
39
- Get started in seconds with a few common utilities:
40
-
41
- ### Named Imports (Tree-shakeable)
42
-
43
- ```typescript
44
- import {
45
- debounce,
46
- chunk,
47
- slugify,
48
- clamp,
49
- isBrowser,
50
- toBool,
51
- } from "@salespark/toolkit";
52
-
53
- // Debounce a function
54
- const debouncedFn = debounce(() => {
55
- /* ... */
56
- }, 200);
57
-
58
- // Chunk an array
59
- const chunks = chunk([1, 2, 3, 4, 5], 2); // [[1,2],[3,4],[5]]
60
-
61
- // Slugify a string
62
- const slug = slugify("OlΓ‘ mundo!"); // "ola-mundo"
63
-
64
- // Clamp a number
65
- const safe = clamp(15, 0, 10); // 10
66
-
67
- // Convert to boolean
68
- const bool = toBool("yes"); // true
69
-
70
- // Check environment
71
- if (isBrowser) {
72
- /* browser-specific code */
73
- }
74
- ```
75
-
76
- ### Lodash-style Import (Alternative)
77
-
78
- ```typescript
79
- import * as _ from "@salespark/toolkit";
80
-
81
- // Debounce a function
82
- const debouncedFn = _.debounce(() => {
83
- /* ... */
84
- }, 200);
85
-
86
- // Chunk an array
87
- const chunks = _.chunk([1, 2, 3, 4, 5], 2); // [[1,2],[3,4],[5]]
88
-
89
- // Slugify a string
90
- const slug = _.slugify("OlΓ‘ mundo!"); // "ola-mundo"
91
-
92
- // Clamp a number
93
- const safe = _.clamp(15, 0, 10); // 10
94
-
95
- // Convert to boolean
96
- const bool = _.toBool("yes"); // true
97
-
98
- // Check environment
99
- if (_.isBrowser) {
100
- /* browser-specific code */
101
- }
102
- ```
103
-
104
- ## πŸ“š API Reference
105
-
106
- ### πŸ“‹ Array Utilities
107
-
108
- **`chunk<T>(arr: T[], size: number): T[][]`** β€” Splits an array into equally sized pieces.
109
-
110
- ```javascript
111
- chunk([1, 2, 3, 4, 5], 2);
112
- // Result: [[1, 2], [3, 4], [5]]
113
- ```
114
-
115
- **`uniq<T>(arr: T[]): T[]`** β€” Removes duplicate values from an array.
116
-
117
- ```javascript
118
- uniq([1, 2, 2, 3, 3, 3]);
119
- // Result: [1, 2, 3]
120
- ```
121
-
122
- **`uniqBy<T, K>(arr: T[], key: (v: T) => K): T[]`** β€” Returns unique items based on a computed key.
123
-
124
- ```javascript
125
- uniqBy(
126
- [
127
- { id: 1, name: "John" },
128
- { id: 2, name: "Jane" },
129
- { id: 1, name: "John" },
130
- ],
131
- (x) => x.id
132
- );
133
- // Result: [{id: 1, name: 'John'}, {id: 2, name: 'Jane'}]
134
- ```
135
-
136
- **`areArraysEqual<T>(arr1: T[], arr2: T[]): boolean`** β€” Deeply compares two arrays for equality.
137
-
138
- ```javascript
139
- areArraysEqual([1, 2, 3], [1, 2, 3]);
140
- // Result: true
141
- ```
142
-
143
- **`flatten<T>(arr: any[]): T[]`** β€” Flattens nested arrays into a single array (1 level deep).
144
-
145
- ```javascript
146
- flatten([1, [2, 3], [4, [5]]]);
147
- // Result: [1, 2, 3, 4, [5]]
148
- ```
149
-
150
- **`flattenOnce<T>(array): T[]`** β€” Flattens array a single level deep.
151
-
152
- ```javascript
153
- flattenOnce([1, [2, 3], [4, 5]]);
154
- // Result: [1, 2, 3, 4, 5]
155
- ```
156
-
157
- **`flattenDepth<T>(array, depth?, options?): T[]`** β€” Flattens array up to specified depth.
158
-
159
- ```javascript
160
- flattenDepth([1, [2, [3, [4]]]], 2);
161
- // Result: [1, 2, 3, [4]]
162
- ```
163
-
164
- **`groupBy<T, K>(arr: T[], key: ((item: T) => K) | K): Record<string, T[]>`** β€” Groups array items by a key or function.
165
-
166
- ```javascript
167
- groupBy(
168
- [
169
- { type: "fruit", name: "apple" },
170
- { type: "fruit", name: "banana" },
171
- { type: "veggie", name: "carrot" },
172
- ],
173
- "type"
174
- );
175
- // Result: {fruit: [{type: 'fruit', name: 'apple'}, {type: 'fruit', name: 'banana'}], veggie: [{type: 'veggie', name: 'carrot'}]}
176
- ```
177
-
178
- **`sortBy<T>(arr: T[], key: ((item: T) => any) | keyof T): T[]`** β€” Sorts array by a key or function.
179
-
180
- ```javascript
181
- sortBy([{ age: 30 }, { age: 20 }, { age: 25 }], "age");
182
- // Result: [{age: 20}, {age: 25}, {age: 30}]
183
- ```
184
-
185
- **`difference<T>(arr1: T[], arr2: T[]): T[]`** β€” Returns elements in arr1 not present in arr2.
186
-
187
- ```javascript
188
- difference([1, 2, 3, 4], [2, 4, 6]);
189
- // Result: [1, 3]
190
- ```
191
-
192
- **`intersection<T>(arr1: T[], arr2: T[]): T[]`** β€” Returns elements common to both arrays.
193
-
194
- ```javascript
195
- intersection([1, 2, 3], [2, 3, 4]);
196
- // Result: [2, 3]
197
- ```
198
-
199
- **`compact<T>(arr: T[]): T[]`** β€” Removes falsy values from array.
200
-
201
- ```javascript
202
- compact([0, 1, false, 2, "", 3, null, undefined, 4]);
203
- // Result: [1, 2, 3, 4]
204
- ```
205
-
206
- **`pluck<T, K>(arr: T[], key: K): Array<T[K]>`** β€” Extracts a property from each object in array.
207
-
208
- ```javascript
209
- pluck(
210
- [
211
- { name: "John", age: 30 },
212
- { name: "Jane", age: 25 },
213
- ],
214
- "name"
215
- );
216
- // Result: ['John', 'Jane']
217
- ```
218
-
219
- **`shuffle<T>(arr: T[]): T[]`** β€” Shuffles array elements randomly.
220
-
221
- ```javascript
222
- shuffle([1, 2, 3, 4, 5]);
223
- // Result: [3, 1, 5, 2, 4] (random order)
224
- ```
225
-
226
- **`isFlattenable(value: unknown): boolean`** β€” Checks if a value can be flattened.
227
-
228
- ```javascript
229
- isFlattenable([1, 2, 3]);
230
- // Result: true
231
- ```
232
-
233
- **`pushAll<T>(array: T[], values: readonly T[]): T[]`** β€” Appends all values into array in-place.
234
-
235
- ```javascript
236
- const arr = [1, 2];
237
- pushAll(arr, [3, 4, 5]);
238
- // Result: arr is now [1, 2, 3, 4, 5]
239
- ```
240
-
241
- ### πŸ“¦ Object Utilities
242
-
243
- **`pick<T, K>(obj: T, keys: K[]): Pick<T, K>`** β€” Picks specified properties from an object.
244
-
245
- ```javascript
246
- pick({ name: "John", age: 30, city: "NYC" }, ["name", "age"]);
247
- // Result: {name: 'John', age: 30}
248
- ```
249
-
250
- **`omit<T, K>(obj: T, keys: K[]): Omit<T, K>`** β€” Omits specified properties from an object.
251
-
252
- ```javascript
253
- omit({ name: "John", age: 30, city: "NYC" }, ["age"]);
254
- // Result: {name: 'John', city: 'NYC'}
255
- ```
256
-
257
- **`objectToString(obj: unknown): string`** β€” Converts an object to a clean string without JSON braces.
258
-
259
- ```javascript
260
- objectToString({ name: "John", age: 30 });
261
- // Result: "name=John_age=30"
262
- ```
263
-
264
- **`cleanObject<T>(obj: T): any`** β€” Deep-cleans an object by removing null/undefined values.
265
-
266
- ```javascript
267
- cleanObject({
268
- name: "John",
269
- age: null,
270
- city: undefined,
271
- data: { valid: true, invalid: null },
272
- });
273
- // Result: {name: 'John', data: {valid: true}}
274
- ```
275
-
276
- ### πŸ”€ String Utilities
277
-
278
- **`slugify(input: string): string`** β€” Converts a string to a URL-friendly slug.
279
-
280
- ```javascript
281
- slugify("OlΓ‘ Mundo! Como estΓ‘?");
282
- // Result: "ola-mundo-como-esta"
283
- ```
284
-
285
- **`fill(template: string, values: Record<string, string|number>): string`** β€” Fills a template string with values.
286
-
287
- ```javascript
288
- fill("Hello {name}, you are {age} years old!", { name: "John", age: 30 });
289
- // Result: "Hello John, you are 30 years old!"
290
- ```
291
-
292
- **`deburr(str: string): string`** β€” Removes diacritic marks from a string.
293
-
294
- ```javascript
295
- deburr("cafΓ© rΓ©sumΓ© naΓ―ve");
296
- // Result: "cafe resume naive"
297
- ```
298
-
299
- **`sanitize(input: unknown, maxLength?: number): string`** β€” Sanitizes input by removing dangerous content.
300
-
301
- ```javascript
302
- sanitize("<script>alert('hack')</script>Hello World!", 20);
303
- // Result: "Hello World!"
304
- ```
305
-
306
- ### πŸ”’ Number Utilities
307
-
308
- **`clamp(n: number, min: number, max: number): number`** β€” Restricts a number within min and max bounds.
309
-
310
- ```javascript
311
- clamp(15, 0, 10);
312
- // Result: 10
313
- ```
314
-
315
- **`round(n: number, decimals?: number): number`** β€” Rounds a number to fixed decimal places.
316
-
317
- ```javascript
318
- round(3.14159, 2);
319
- // Result: 3.14
320
- ```
321
-
322
- **`toInteger(value: unknown, defaultValue?: number): number`** β€” Safely converts a value to an integer.
323
-
324
- ```javascript
325
- toInteger("42.7");
326
- // Result: 42
327
- ```
328
-
329
- **`safeParseInt(value: unknown, defaultValue?: number): number`** β€” Alias for safe integer conversion.
330
-
331
- ```javascript
332
- safeParseInt("abc", 0);
333
- // Result: 0
334
- ```
335
-
336
- **`toNumber(value: unknown, decimals?: number): number`** β€” Safely parses a value into a number with optional decimal precision.
337
-
338
- ```javascript
339
- toNumber("123,45", 2);
340
- // Result: 123.45
341
- ```
342
-
343
- **`randomDigits(length?: number, options?: { charset?: string; noLeadingZero?: boolean }): string`** β€” Generates a random string of digits with secure randomness when available.
344
-
345
- ```javascript
346
- randomDigits(6);
347
- // Result: "482751" (random)
348
- ```
349
-
350
- ### βœ… Boolean Utilities
351
-
352
- **`toBool(value: unknown, def?: boolean): boolean`** β€” Converts a value to boolean, supporting common string/number representations.
353
-
354
- ```javascript
355
- toBool("yes");
356
- // Result: true
357
-
358
- toBool("0");
359
- // Result: false
360
- ```
361
-
362
- ### ⚑ Function Utilities
363
-
364
- **`debounce<T>(fn: T, wait?: number): T`** β€” Returns a debounced version of a function.
365
-
366
- ```javascript
367
- const debouncedFn = debounce(() => console.log("Called!"), 300);
368
- debouncedFn(); // Will only execute after 300ms of no further calls
369
- ```
370
-
371
- **`throttle<T>(fn: T, wait?: number): T`** β€” Returns a throttled version of a function.
372
-
373
- ```javascript
374
- const throttledFn = throttle(() => console.log("Called!"), 1000);
375
- throttledFn(); // Will execute at most once per 1000ms
376
- ```
377
-
378
- **`isNil(value: unknown): boolean`** β€” Checks if a value is null or undefined.
379
-
380
- ```javascript
381
- isNil(null);
382
- // Result: true
383
-
384
- isNil(undefined);
385
- // Result: true
386
-
387
- isNil(0);
388
- // Result: false
389
- ```
390
-
391
- **`isNilText(value: unknown): boolean`** β€” Checks if value is null/undefined or the text "null"/"undefined".
392
-
393
- ```javascript
394
- isNilText("null");
395
- // Result: true
396
-
397
- isNilText("undefined");
398
- // Result: true
399
- ```
400
-
401
- **`isNilOrEmpty(value: unknown): boolean`** β€” Checks if value is null/undefined or an empty string.
402
-
403
- ```javascript
404
- isNilOrEmpty("");
405
- // Result: true
406
-
407
- isNilOrEmpty(null);
408
- // Result: true
409
- ```
410
-
411
- **`hasNilOrEmpty(array: unknown): boolean`** β€” Checks if any element in array is nil or empty.
412
-
413
- ```javascript
414
- hasNilOrEmpty([1, "", 3]);
415
- // Result: true
416
-
417
- hasNilOrEmpty([1, 2, 3]);
418
- // Result: false
419
- ```
420
-
421
- **`isNilEmptyOrZeroLen(value: unknown): boolean`** β€” Checks if value is nil, empty string, or has zero length.
422
-
423
- ```javascript
424
- isNilEmptyOrZeroLen([]);
425
- // Result: true
426
-
427
- isNilEmptyOrZeroLen("");
428
- // Result: true
429
- ```
430
-
431
- **`isNilOrZeroLen(value: unknown): boolean`** β€” Checks if value is nil or has zero length.
432
-
433
- ```javascript
434
- isNilOrZeroLen([]);
435
- // Result: true
436
-
437
- isNilOrZeroLen(null);
438
- // Result: true
439
- ```
440
-
441
- **`isNilOrNaN(value: unknown): boolean`** β€” Checks if value is nil or NaN.
442
-
443
- ```javascript
444
- isNilOrNaN(NaN);
445
- // Result: true
446
-
447
- isNilOrNaN("abc");
448
- // Result: true (coerced to NaN)
449
- ```
450
-
451
- **`formatBytes(bytes: number, si?: boolean, dp?: number): string`** β€” Formats bytes as human-readable text.
452
-
453
- ```javascript
454
- formatBytes(1024);
455
- // Result: "1.0 KiB"
456
-
457
- formatBytes(1000, true);
458
- // Result: "1.0 kB"
459
- ```
460
-
461
- **`stringSimilarity(s1: string, s2: string): number`** β€” Returns the similarity between two strings (0..1).
462
-
463
- ```javascript
464
- stringSimilarity("hello", "hallo");
465
- // Result: 0.8
466
- ```
467
-
468
- **`addThousandsSpace(value: number | string): string`** β€” Adds spaces between thousands in a number.
469
-
470
- ```javascript
471
- addThousandsSpace(1234567);
472
- // Result: "1 234 567"
473
- ```
474
-
475
- ### 🌐 Environment Detection
476
-
477
- **`isBrowser: boolean`** β€” True if running in browser.
478
-
479
- ```javascript
480
- if (isBrowser) {
481
- console.log("Running in browser");
482
- }
483
- ```
484
-
485
- **`isNode: boolean`** β€” True if running in Node.js.
486
-
487
- ```javascript
488
- if (isNode) {
489
- console.log("Running in Node.js");
490
- }
491
- ```
492
-
493
- ## ⚠️ Deprecated Functions
494
-
495
- The following functions are deprecated but maintained for backward compatibility:
496
-
497
- ### πŸ“‹ Array Utilities (Deprecated)
498
-
499
- - `areArraysDeepEqualUnordered` β€” Use `areArraysEqual` instead.
500
-
501
- ### βœ… Boolean Utilities (Deprecated)
502
-
503
- - `parseToBool` β€” Use `toBool` instead.
504
-
505
- ### ⚑ Function Utilities (Deprecated)
506
-
507
- - `isNullOrUndefined` β€” Use `isNil` instead.
508
- - `isNullOrUndefinedTextInc` β€” Use `isNilText` instead.
509
- - `isNullUndefinedOrEmpty` β€” Use `isNilOrEmpty` instead.
510
- - `isNullOrUndefinedInArray` β€” Use `hasNilOrEmpty` instead.
511
- - `isNullOrUndefinedEmptyOrZero` β€” Use `isNilEmptyOrZeroLen` instead.
512
- - `isNullUndefinedOrZero` β€” Use `isNilOrZeroLen` instead.
513
- - `isNullOrUndefinedOrNaN` β€” Use `isNilOrNaN` instead.
514
- - `humanFileSize` β€” Use `formatBytes` instead.
515
- - `getStringSimilarity` β€” Use `stringSimilarity` instead.
516
- - `addSpaceBetweenNumbers` β€” Use `addThousandsSpace` instead.
517
-
518
- ### πŸ”’ Number Utilities (Deprecated)
519
-
520
- - `parseToNumber` β€” Use `toNumber` instead.
521
- - `otp` β€” Use `randomDigits` instead.
522
-
523
- ### πŸ”€ String Utilities (Deprecated)
524
-
525
- - `removeDiacritics` β€” Use `deburr` instead.
526
- - `basicSanitize` β€” Use `sanitize` instead.
527
-
528
- ## 🏷️ TypeScript
529
-
530
- All functions are fully typed for best developer experience.
531
-
532
- ---
533
-
534
- ### πŸ”’ Internal Usage Notice
535
-
536
- This package is primarily designed and maintained for internal use within the SalesPark ecosystem.
537
- While it can technically be used in other Node.js/Mongoose projects, no official support or guarantees are provided outside of SalesPark-managed projects.
538
-
539
- All code follows the same engineering standards applied across the SalesPark platform, ensuring consistency, reliability, and long-term maintainability of our internal systems.
540
-
541
- ⚑ Note: This package is most efficient and works best when used together with other official SalesPark packages, where interoperability and optimizations are fully leveraged.
542
-
543
- Disclaimer: This software is provided "as is", without warranties of any kind, express or implied. SalesPark shall not be held liable for any issues, damages, or losses arising from its use outside the intended SalesPark environment.
544
-
545
- Organization packages: https://www.npmjs.com/org/salespark
546
-
547
- ---
548
-
549
- ## πŸ“„ License
550
-
551
- MIT Β© [SalesPark](https://salespark.io)
552
-
553
- ---
554
-
555
- _Document version: 2_
556
- _Last update: 22-08-2025_
1
+ # SalesPark Toolkit v2 - Documentation
2
+
3
+ ## @salespark/toolkit
4
+
5
+ Shared toolkit of helpers and utilities for **Node.js**, **React**, and browser environments.
6
+ Tree-shakeable, TypeScript-first, ESM + CJS outputs.
7
+
8
+ [![Coverage](https://codecov.io/gh/FBlade/salespark-toolkit/branch/main/graph/badge.svg)](https://codecov.io/gh/FBlade/salespark-toolkit)
9
+ [![npm version](https://img.shields.io/npm/v/%40salespark%2Ftoolkit.svg)](https://www.npmjs.com/package/@salespark/toolkit)
10
+ ![types](https://img.shields.io/npm/types/%40salespark%2Ftoolkit)
11
+ ![modules](https://img.shields.io/badge/modules-ESM%20%2B%20CJS-1f6feb)
12
+ ![tree-shakeable](https://img.shields.io/badge/tree--shakeable-yes-success)
13
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](#-license)
14
+
15
+ ---
16
+
17
+ ## πŸ“¦ Installation
18
+
19
+ ```bash
20
+ yarn add @salespark/toolkit
21
+ # or
22
+ npm i @salespark/toolkit
23
+ ```
24
+
25
+ ## ✨ Features
26
+
27
+ - **Array utilities**: chunk, uniqBy, deep equality, flatten, groupBy, etc.
28
+ - **Object utilities**: pick, omit, clean objects, deep merge, etc.
29
+ - **String utilities**: slugify, template fill, deburr, sanitize, etc.
30
+ - **Number utilities**: clamp, round, safe parse, random digits, etc.
31
+ - **Function utilities**: debounce, throttle, formatCurrency, parseName, currency conversions, etc.
32
+ - **Boolean utilities**: safe boolean conversion with common representations
33
+ - **Validation utilities**: IBAN validator (ISO 13616), Portuguese tax ID validator
34
+ - **Security utilities**: Markdown XSS protection, content sanitization, risk assessment
35
+ - **Environment detection**: `isBrowser`, `isNode` runtime checks
36
+
37
+ ---
38
+
39
+ ## πŸš€ Usage
40
+
41
+ Get started in seconds with a few common utilities:
42
+
43
+ ### Named Imports (Tree-shakeable)
44
+
45
+ ```typescript
46
+ import {
47
+ debounce,
48
+ delay,
49
+ chunk,
50
+ slugify,
51
+ clamp,
52
+ isBrowser,
53
+ toBool,
54
+ } from "@salespark/toolkit";
55
+
56
+ // Debounce a function
57
+ const debouncedFn = debounce(() => {
58
+ /* ... */
59
+ }, 200);
60
+
61
+ // Delay execution
62
+ await delay(1000); // Wait 1 second
63
+
64
+ // Chunk an array
65
+ const chunks = chunk([1, 2, 3, 4, 5], 2); // [[1,2],[3,4],[5]]
66
+
67
+ // Slugify a string
68
+ const slug = slugify("OlΓ‘ mundo!"); // "ola-mundo"
69
+
70
+ // Clamp a number
71
+ const safe = clamp(15, 0, 10); // 10
72
+
73
+ // Convert to boolean
74
+ const bool = toBool("yes"); // true
75
+
76
+ // Check environment
77
+ if (isBrowser) {
78
+ /* browser-specific code */
79
+ }
80
+ ```
81
+
82
+ ### Lodash-style Import (Alternative)
83
+
84
+ ```typescript
85
+ import * as _ from "@salespark/toolkit";
86
+
87
+ // Debounce a function
88
+ const debouncedFn = _.debounce(() => {
89
+ /* ... */
90
+ }, 200);
91
+
92
+ // Chunk an array
93
+ const chunks = _.chunk([1, 2, 3, 4, 5], 2); // [[1,2],[3,4],[5]]
94
+
95
+ // Slugify a string
96
+ const slug = _.slugify("OlΓ‘ mundo!"); // "ola-mundo"
97
+
98
+ // Clamp a number
99
+ const safe = _.clamp(15, 0, 10); // 10
100
+
101
+ // Convert to boolean
102
+ const bool = _.toBool("yes"); // true
103
+
104
+ // Check environment
105
+ if (_.isBrowser) {
106
+ /* browser-specific code */
107
+ }
108
+ ```
109
+
110
+ ## πŸ“š API Reference
111
+
112
+ ### πŸ“‹ Array Utilities
113
+
114
+ **`chunk<T>(arr: T[], size: number): T[][]`** β€” Splits an array into equally sized pieces.
115
+
116
+ ```javascript
117
+ chunk([1, 2, 3, 4, 5], 2);
118
+ // Result: [[1, 2], [3, 4], [5]]
119
+ ```
120
+
121
+ **`uniq<T>(arr: T[]): T[]`** β€” Removes duplicate values from an array.
122
+
123
+ ```javascript
124
+ uniq([1, 2, 2, 3, 3, 3]);
125
+ // Result: [1, 2, 3]
126
+ ```
127
+
128
+ **`uniqBy<T, K>(arr: T[], key: (v: T) => K): T[]`** β€” Returns unique items based on a computed key.
129
+
130
+ ```javascript
131
+ uniqBy(
132
+ [
133
+ { id: 1, name: "John" },
134
+ { id: 2, name: "Jane" },
135
+ { id: 1, name: "John" },
136
+ ],
137
+ (x) => x.id
138
+ );
139
+ // Result: [{id: 1, name: 'John'}, {id: 2, name: 'Jane'}]
140
+ ```
141
+
142
+ **`areArraysEqual<T>(arr1: T[], arr2: T[]): boolean`** β€” Deeply compares two arrays for equality.
143
+
144
+ ```javascript
145
+ areArraysEqual([1, 2, 3], [1, 2, 3]);
146
+ // Result: true
147
+ ```
148
+
149
+ **`flatten<T>(arr: any[]): T[]`** β€” Flattens nested arrays into a single array (1 level deep).
150
+
151
+ ```javascript
152
+ flatten([1, [2, 3], [4, [5]]]);
153
+ // Result: [1, 2, 3, 4, [5]]
154
+ ```
155
+
156
+ **`flattenOnce<T>(array): T[]`** β€” Flattens array a single level deep.
157
+
158
+ ```javascript
159
+ flattenOnce([1, [2, 3], [4, 5]]);
160
+ // Result: [1, 2, 3, 4, 5]
161
+ ```
162
+
163
+ **`flattenDepth<T>(array, depth?, options?): T[]`** β€” Flattens array up to specified depth.
164
+
165
+ ```javascript
166
+ flattenDepth([1, [2, [3, [4]]]], 2);
167
+ // Result: [1, 2, 3, [4]]
168
+ ```
169
+
170
+ **`groupBy<T, K>(arr: T[], key: ((item: T) => K) | K): Record<string, T[]>`** β€” Groups array items by a key or function.
171
+
172
+ ```javascript
173
+ groupBy(
174
+ [
175
+ { type: "fruit", name: "apple" },
176
+ { type: "fruit", name: "banana" },
177
+ { type: "veggie", name: "carrot" },
178
+ ],
179
+ "type"
180
+ );
181
+ // Result: {fruit: [{type: 'fruit', name: 'apple'}, {type: 'fruit', name: 'banana'}], veggie: [{type: 'veggie', name: 'carrot'}]}
182
+ ```
183
+
184
+ **`sortBy<T>(arr: T[], key: ((item: T) => any) | keyof T): T[]`** β€” Sorts array by a key or function.
185
+
186
+ ```javascript
187
+ sortBy([{ age: 30 }, { age: 20 }, { age: 25 }], "age");
188
+ // Result: [{age: 20}, {age: 25}, {age: 30}]
189
+ ```
190
+
191
+ **`difference<T>(arr1: T[], arr2: T[]): T[]`** β€” Returns elements in arr1 not present in arr2.
192
+
193
+ ```javascript
194
+ difference([1, 2, 3, 4], [2, 4, 6]);
195
+ // Result: [1, 3]
196
+ ```
197
+
198
+ **`intersection<T>(arr1: T[], arr2: T[]): T[]`** β€” Returns elements common to both arrays.
199
+
200
+ ```javascript
201
+ intersection([1, 2, 3], [2, 3, 4]);
202
+ // Result: [2, 3]
203
+ ```
204
+
205
+ **`compact<T>(arr: T[]): T[]`** β€” Removes falsy values from array.
206
+
207
+ ```javascript
208
+ compact([0, 1, false, 2, "", 3, null, undefined, 4]);
209
+ // Result: [1, 2, 3, 4]
210
+ ```
211
+
212
+ **`pluck<T, K>(arr: T[], key: K): Array<T[K]>`** β€” Extracts a property from each object in array.
213
+
214
+ ```javascript
215
+ pluck(
216
+ [
217
+ { name: "John", age: 30 },
218
+ { name: "Jane", age: 25 },
219
+ ],
220
+ "name"
221
+ );
222
+ // Result: ['John', 'Jane']
223
+ ```
224
+
225
+ **`shuffle<T>(arr: T[]): T[]`** β€” Shuffles array elements randomly.
226
+
227
+ ```javascript
228
+ shuffle([1, 2, 3, 4, 5]);
229
+ // Result: [3, 1, 5, 2, 4] (random order)
230
+ ```
231
+
232
+ **`isFlattenable(value: unknown): boolean`** β€” Checks if a value can be flattened.
233
+
234
+ ```javascript
235
+ isFlattenable([1, 2, 3]);
236
+ // Result: true
237
+ ```
238
+
239
+ **`pushAll<T>(array: T[], values: readonly T[]): T[]`** β€” Appends all values into array in-place.
240
+
241
+ ```javascript
242
+ const arr = [1, 2];
243
+ pushAll(arr, [3, 4, 5]);
244
+ // Result: arr is now [1, 2, 3, 4, 5]
245
+ ```
246
+
247
+ ### πŸ“¦ Object Utilities
248
+
249
+ **`pick<T, K>(obj: T, keys: K[]): Pick<T, K>`** β€” Picks specified properties from an object.
250
+
251
+ ```javascript
252
+ pick({ name: "John", age: 30, city: "NYC" }, ["name", "age"]);
253
+ // Result: {name: 'John', age: 30}
254
+ ```
255
+
256
+ **`omit<T, K>(obj: T, keys: K[]): Omit<T, K>`** β€” Omits specified properties from an object.
257
+
258
+ ```javascript
259
+ omit({ name: "John", age: 30, city: "NYC" }, ["age"]);
260
+ // Result: {name: 'John', city: 'NYC'}
261
+ ```
262
+
263
+ **`objectToString(obj: unknown): string`** β€” Converts an object to a clean string without JSON braces.
264
+
265
+ ```javascript
266
+ objectToString({ name: "John", age: 30 });
267
+ // Result: "name=John_age=30"
268
+ ```
269
+
270
+ **`cleanObject<T>(obj: T): any`** β€” Deep-cleans an object by removing null/undefined values.
271
+
272
+ ```javascript
273
+ cleanObject({
274
+ name: "John",
275
+ age: null,
276
+ city: undefined,
277
+ data: { valid: true, invalid: null },
278
+ });
279
+ // Result: {name: 'John', data: {valid: true}}
280
+ ```
281
+
282
+ ### πŸ”€ String Utilities
283
+
284
+ **`slugify(input: string): string`** β€” Converts a string to a URL-friendly slug.
285
+
286
+ ```javascript
287
+ slugify("OlΓ‘ Mundo! Como estΓ‘?");
288
+ // Result: "ola-mundo-como-esta"
289
+ ```
290
+
291
+ **`fill(template: string, values: Record<string, string|number>): string`** β€” Fills a template string with values.
292
+
293
+ ```javascript
294
+ fill("Hello {name}, you are {age} years old!", { name: "John", age: 30 });
295
+ // Result: "Hello John, you are 30 years old!"
296
+ ```
297
+
298
+ **`deburr(str: string): string`** β€” Removes diacritic marks from a string.
299
+
300
+ ```javascript
301
+ deburr("cafΓ© rΓ©sumΓ© naΓ―ve");
302
+ // Result: "cafe resume naive"
303
+ ```
304
+
305
+ **`sanitize(input: unknown, maxLength?: number): string`** β€” Sanitizes input by removing dangerous content.
306
+
307
+ ```javascript
308
+ sanitize("<script>alert('hack')</script>Hello World!", 20);
309
+ // Result: "Hello World!"
310
+ ```
311
+
312
+ ### πŸ”’ Number Utilities
313
+
314
+ **`clamp(n: number, min: number, max: number): number`** β€” Restricts a number within min and max bounds.
315
+
316
+ ```javascript
317
+ clamp(15, 0, 10);
318
+ // Result: 10
319
+ ```
320
+
321
+ **`round(n: number, decimals?: number): number`** β€” Rounds a number to fixed decimal places.
322
+
323
+ ```javascript
324
+ round(3.14159, 2);
325
+ // Result: 3.14
326
+ ```
327
+
328
+ **`toInteger(value: unknown, defaultValue?: number): number`** β€” Safely converts a value to an integer.
329
+
330
+ ```javascript
331
+ toInteger("42.7");
332
+ // Result: 42
333
+ ```
334
+
335
+ **`safeParseInt(value: unknown, defaultValue?: number): number`** β€” Alias for safe integer conversion.
336
+
337
+ ```javascript
338
+ safeParseInt("abc", 0);
339
+ // Result: 0
340
+ ```
341
+
342
+ **`toNumber(value: unknown, decimals?: number): number`** β€” Safely parses a value into a number with optional decimal precision.
343
+
344
+ ```javascript
345
+ toNumber("123,45", 2);
346
+ // Result: 123.45
347
+ ```
348
+
349
+ **`randomDigits(length?: number, options?: { charset?: string; noLeadingZero?: boolean }): string`** β€” Generates a random string of digits with secure randomness when available.
350
+
351
+ ```javascript
352
+ randomDigits(6);
353
+ // Result: "482751" (random)
354
+ ```
355
+
356
+ ### βœ… Boolean Utilities
357
+
358
+ **`toBool(value: unknown, def?: boolean): boolean`** β€” Converts a value to boolean, supporting common string/number representations.
359
+
360
+ ```javascript
361
+ toBool("yes");
362
+ // Result: true
363
+
364
+ toBool("0");
365
+ // Result: false
366
+ ```
367
+
368
+ ### ⚑ Function Utilities
369
+
370
+ **`debounce<T>(fn: T, wait?: number): T`** β€” Returns a debounced version of a function.
371
+
372
+ ```javascript
373
+ const debouncedFn = debounce(() => console.log("Called!"), 300);
374
+ debouncedFn(); // Will only execute after 300ms of no further calls
375
+ ```
376
+
377
+ **`throttle<T>(fn: T, wait?: number): T`** β€” Returns a throttled version of a function.
378
+
379
+ ```javascript
380
+ const throttledFn = throttle(() => console.log("Called!"), 1000);
381
+ throttledFn(); // Will execute at most once per 1000ms
382
+ ```
383
+
384
+ **`delay(ms: number): Promise<void>`** β€” Creates a promise that resolves after specified milliseconds.
385
+
386
+ ```javascript
387
+ await delay(1000); // Wait 1 second
388
+ await delay(500); // Wait 500ms
389
+ ```
390
+
391
+ **`isNil(value: unknown): boolean`** β€” Checks if a value is null or undefined.
392
+
393
+ **`isNilTextOrEmpty(value: unknown): boolean`** β€” Strict check for `null`, `undefined`, empty string `""`, or textual values `"null"` / `"undefined"` (case-insensitive, trims spaces). Returns `true` in those cases, otherwise `false`.
394
+
395
+ ```javascript
396
+ isNilTextOrEmpty(null); // true
397
+ isNilTextOrEmpty("undefined"); // true
398
+ isNilTextOrEmpty(" UNDEFINED "); // true
399
+ isNilTextOrEmpty("null"); // true
400
+ isNilTextOrEmpty(""); // true
401
+ isNilTextOrEmpty("abc"); // false
402
+ isNilTextOrEmpty(0); // false
403
+ ```
404
+
405
+ > Deprecated: `isNullUndefinedOrEmptyEnforced` (use `isNilTextOrEmpty`).
406
+
407
+ ```javascript
408
+ isNil(null);
409
+ // Result: true
410
+
411
+ isNil(undefined);
412
+ // Result: true
413
+
414
+ isNil(0);
415
+ // Result: false
416
+ ```
417
+
418
+ **`isNilText(value: unknown): boolean`** β€” Checks if value is null/undefined or the text "null"/"undefined".
419
+
420
+ ```javascript
421
+ isNilText("null");
422
+ // Result: true
423
+
424
+ isNilText("undefined");
425
+ // Result: true
426
+ ```
427
+
428
+ **`isNilOrEmpty(value: unknown): boolean`** β€” Checks if value is null/undefined or an empty string.
429
+
430
+ ```javascript
431
+ isNilOrEmpty("");
432
+ // Result: true
433
+
434
+ isNilOrEmpty(null);
435
+ // Result: true
436
+ ```
437
+
438
+ **`hasNilOrEmpty(array: unknown): boolean`** β€” Checks if any element in array is nil or empty.
439
+
440
+ ```javascript
441
+ hasNilOrEmpty([1, "", 3]);
442
+ // Result: true
443
+
444
+ hasNilOrEmpty([1, 2, 3]);
445
+ // Result: false
446
+ ```
447
+
448
+ **`isNilEmptyOrZeroLen(value: unknown): boolean`** β€” Checks if value is nil, empty string, or has zero length.
449
+
450
+ ```javascript
451
+ isNilEmptyOrZeroLen([]);
452
+ // Result: true
453
+
454
+ isNilEmptyOrZeroLen("");
455
+ // Result: true
456
+ ```
457
+
458
+ **`isNilOrZeroLen(value: unknown): boolean`** β€” Checks if value is nil or has zero length.
459
+
460
+ ```javascript
461
+ isNilOrZeroLen([]);
462
+ // Result: true
463
+
464
+ isNilOrZeroLen(null);
465
+ // Result: true
466
+ ```
467
+
468
+ **`isNilOrNaN(value: unknown): boolean`** β€” Checks if value is nil or NaN.
469
+
470
+ ```javascript
471
+ isNilOrNaN(NaN);
472
+ // Result: true
473
+
474
+ isNilOrNaN("abc");
475
+ // Result: true (coerced to NaN)
476
+ ```
477
+
478
+ **`formatBytes(bytes: number, si?: boolean, dp?: number): string`** β€” Formats bytes as human-readable text.
479
+
480
+ ```javascript
481
+ formatBytes(1024);
482
+ // Result: "1.0 KiB"
483
+
484
+ formatBytes(1000, true);
485
+ // Result: "1.0 kB"
486
+ ```
487
+
488
+ **`stringSimilarity(s1: string, s2: string): number`** β€” Returns the similarity between two strings (0..1).
489
+
490
+ ```javascript
491
+ stringSimilarity("hello", "hallo");
492
+ // Result: 0.8
493
+ ```
494
+
495
+ **`addThousandsSpace(value: number | string): string`** β€” Adds spaces between thousands in a number.
496
+
497
+ ```javascript
498
+ addThousandsSpace(1234567);
499
+ // Result: "1 234 567"
500
+ ```
501
+
502
+ **`formatCurrency(value: number | string | null | undefined, withoutCurrencySymbol?: boolean, currency?: string, locale?: string): string`** β€” Formats currency values with configurable currency and locale. Uses modern Intl.NumberFormat with automatic thousands separators, proper decimal handling, and graceful fallback for errors.
503
+
504
+ ```javascript
505
+ // Default: EUR currency with Portuguese locale
506
+ formatCurrency(1234.56);
507
+ // Result: "1234,56 €"
508
+
509
+ formatCurrency(1000000.123);
510
+ // Result: "1 000 000,12 €"
511
+
512
+ formatCurrency(999.9, true);
513
+ // Result: "999,90" (without symbol)
514
+
515
+ // Different currencies
516
+ formatCurrency(1234.56, false, "USD", "en-US");
517
+ // Result: "$1,234.56"
518
+
519
+ formatCurrency(1234.56, false, "GBP", "en-GB");
520
+ // Result: "Β£1,234.56"
521
+
522
+ formatCurrency(1234.56, false, "USD", "pt-PT");
523
+ // Result: "1234,56 US$"
524
+
525
+ formatCurrency(null);
526
+ // Result: "0,00 €"
527
+ ```
528
+
529
+ **`parseName(name: string | null | undefined): {firstName: string, lastName: string}`** β€” Extracts first and last name from a full name string. Handles single names, empty inputs, and multi-word names intelligently.
530
+
531
+ ```javascript
532
+ parseName("JoΓ£o Silva");
533
+ // Result: { firstName: "JoΓ£o", lastName: "Silva" }
534
+
535
+ parseName("Maria JosΓ© Santos Costa");
536
+ // Result: { firstName: "Maria", lastName: "Costa" }
537
+
538
+ parseName("Ana");
539
+ // Result: { firstName: "Ana", lastName: "" }
540
+
541
+ parseName(" JosΓ© MarΓ­a GarcΓ­a ");
542
+ // Result: { firstName: "JosΓ©", lastName: "GarcΓ­a" }
543
+
544
+ parseName(null);
545
+ // Result: { firstName: "", lastName: "" }
546
+ ```
547
+
548
+ **`symbolToCurrency(symbol: string | null | undefined): string`** β€” Converts currency symbols to ISO 4217 currency codes. Supports 50+ currency symbols including €, Β£, $, Β₯, β‚Ή, β‚½, β‚©, β‚ͺ, and many others.
549
+
550
+ ```javascript
551
+ symbolToCurrency("€");
552
+ // Result: "EUR"
553
+
554
+ symbolToCurrency("$");
555
+ // Result: "USD"
556
+
557
+ symbolToCurrency("β‚©");
558
+ // Result: "KRW"
559
+
560
+ symbolToCurrency("R$");
561
+ // Result: "BRL"
562
+
563
+ symbolToCurrency("unknown");
564
+ // Result: "EUR" (fallback)
565
+ ```
566
+
567
+ **`currencyToSymbol(currency: string | null | undefined): string`** β€” Converts ISO 4217 currency codes to their corresponding symbols. Supports 50+ currencies with intelligent fallbacks.
568
+
569
+ ```javascript
570
+ currencyToSymbol("EUR");
571
+ // Result: "€"
572
+
573
+ currencyToSymbol("USD");
574
+ // Result: "$"
575
+
576
+ currencyToSymbol("KRW");
577
+ // Result: "β‚©"
578
+
579
+ currencyToSymbol("BRL");
580
+ // Result: "R$"
581
+
582
+ currencyToSymbol("UNKNOWN");
583
+ // Result: "€" (fallback)
584
+ ```
585
+
586
+ ### πŸ”’ Security Utilities
587
+
588
+ **`checkMarkdownSecurity(text: string | null | undefined): SecurityCheckResult`** β€” Comprehensive markdown security validation with XSS protection, threat detection, and automatic sanitization.
589
+
590
+ ```typescript
591
+ import { checkMarkdownSecurity } from "@salespark/toolkit";
592
+
593
+ // Safe content
594
+ checkMarkdownSecurity("# Hello World\n\nThis is **bold** text.");
595
+ // Result: { isValid: true, text: "...", risks: [], sanitized: false }
596
+
597
+ // Dangerous content with script
598
+ checkMarkdownSecurity('<script>alert("xss")</script>');
599
+ // Result: {
600
+ // isValid: false,
601
+ // text: "",
602
+ // risks: [{ type: "scriptTags", severity: "critical", description: "..." }],
603
+ // sanitized: true
604
+ // }
605
+
606
+ // Content with multiple threats
607
+ checkMarkdownSecurity('<iframe src="evil.com"></iframe><div onclick="bad()">test</div>');
608
+ // Result: Multiple risks detected, sorted by severity
609
+ ```
610
+
611
+ **`sanitizeMarkdown(text: string | null | undefined): string`** β€” Aggressive markdown sanitization removing all HTML tags, scripts, and suspicious content.
612
+
613
+ ```typescript
614
+ import { sanitizeMarkdown } from "@salespark/toolkit";
615
+
616
+ sanitizeMarkdown('<p>Hello <strong>World</strong></p>');
617
+ // Result: "Hello World"
618
+
619
+ sanitizeMarkdown('javascript:alert("xss")');
620
+ // Result: "alert(\"xss\")"
621
+
622
+ sanitizeMarkdown('<script>alert(1)</script>Safe text');
623
+ // Result: "Safe text"
624
+ ```
625
+
626
+ **`assessSecurityRisks(risks: SecurityRisk[]): SecurityAssessment`** β€” Risk assessment and scoring system with actionable recommendations.
627
+
628
+ ```typescript
629
+ import { assessSecurityRisks } from "@salespark/toolkit";
630
+
631
+ const risks = [
632
+ { type: "scriptTags", severity: "critical", description: "Script injection detected" }
633
+ ];
634
+
635
+ assessSecurityRisks(risks);
636
+ // Result: {
637
+ // score: 100,
638
+ // level: "critical",
639
+ // recommendations: [
640
+ // "URGENT: Critical security risks detected - do not render this content",
641
+ // "Always validate content from untrusted sources",
642
+ // "Consider implementing Content Security Policy (CSP)"
643
+ // ]
644
+ // }
645
+
646
+ // Safe content
647
+ assessSecurityRisks([]);
648
+ // Result: { score: 0, level: "safe", recommendations: ["Content appears safe to use"] }
649
+ ```
650
+
651
+ ### βœ… Validation Utilities
652
+
653
+ **`isPTTaxId(value: string | number): boolean`** β€” Validates Portuguese Tax ID (NIF) with MOD-11 algorithm and format checking.
654
+
655
+ ```typescript
656
+ import { isPTTaxId } from "@salespark/toolkit";
657
+
658
+ isPTTaxId("123456789"); // false (invalid check digit)
659
+ isPTTaxId("123 456 789"); // false (spaces stripped automatically)
660
+ isPTTaxId("513183504"); // true (valid NIF)
661
+ isPTTaxId("423456789"); // false (invalid prefix - 4 not allowed)
662
+
663
+ // Deprecated alias (use isPTTaxId instead)
664
+ // isValidPTTaxId("513183504"); // true
665
+ ```
666
+
667
+ **`isValidIBAN(value: string): boolean`** β€” Validates International Bank Account Numbers (IBAN) according to ISO 13616 standard with country-specific rules.
668
+
669
+ ```typescript
670
+ import { isValidIBAN } from "@salespark/toolkit";
671
+
672
+ isValidIBAN("NL91ABNA0417164300"); // true (valid Dutch IBAN)
673
+ isValidIBAN("NL91 ABNA 0417 1643 00"); // true (spaces stripped automatically)
674
+ isValidIBAN("GB29NWBK60161331926819"); // true (valid UK IBAN)
675
+ isValidIBAN("DE89370400440532013000"); // true (valid German IBAN)
676
+ isValidIBAN("NL91ABNA0417164301"); // false (invalid checksum)
677
+ isValidIBAN("XX1234567890"); // false (invalid country code)
678
+ ```
679
+
680
+ ### 🌐 Environment Detection
681
+
682
+ **`isBrowser: boolean`** β€” True if running in browser.
683
+
684
+ ```javascript
685
+ if (isBrowser) {
686
+ console.log("Running in browser");
687
+ }
688
+ ```
689
+
690
+ **`isNode: boolean`** β€” True if running in Node.js.
691
+
692
+ ```javascript
693
+ if (isNode) {
694
+ console.log("Running in Node.js");
695
+ }
696
+ ```
697
+
698
+ ## ⚠️ Deprecated Functions
699
+
700
+ The following functions are deprecated but maintained for backward compatibility:
701
+
702
+ ### πŸ“‹ Array Utilities (Deprecated)
703
+
704
+ - `areArraysDeepEqualUnordered` β€” Use `areArraysEqual` instead.
705
+
706
+ ### βœ… Boolean Utilities (Deprecated)
707
+
708
+ - `parseToBool` β€” Use `toBool` instead.
709
+
710
+ ### ⚑ Function Utilities (Deprecated)
711
+
712
+ - `isNullOrUndefined` β€” Use `isNil` instead.
713
+ - `isNullOrUndefinedTextInc` β€” Use `isNilText` instead.
714
+ - `isNullUndefinedOrEmpty` β€” Use `isNilOrEmpty` instead.
715
+ - `isNullOrUndefinedInArray` β€” Use `hasNilOrEmpty` instead.
716
+ - `isNullOrUndefinedEmptyOrZero` β€” Use `isNilEmptyOrZeroLen` instead.
717
+ - `isNullUndefinedOrZero` β€” Use `isNilOrZeroLen` instead.
718
+ - `isNullOrUndefinedOrNaN` β€” Use `isNilOrNaN` instead.
719
+ - `humanFileSize` β€” Use `formatBytes` instead.
720
+ - `getStringSimilarity` β€” Use `stringSimilarity` instead.
721
+ - `addSpaceBetweenNumbers` β€” Use `addThousandsSpace` instead.
722
+
723
+ ### βœ… Validation Utilities (Deprecated)
724
+
725
+ > These functions are now in the main API but their legacy aliases are deprecated:
726
+
727
+ - `isValidPTTaxId` β€” Use `isPTTaxId` instead.
728
+
729
+ ### πŸ”’ Number Utilities (Deprecated)
730
+
731
+ - `parseToNumber` β€” Use `toNumber` instead.
732
+ - `otp` β€” Use `randomDigits` instead.
733
+
734
+ ### πŸ”€ String Utilities (Deprecated)
735
+
736
+ - `removeDiacritics` β€” Use `deburr` instead.
737
+ - `basicSanitize` β€” Use `sanitize` instead.
738
+
739
+ ## 🏷️ TypeScript
740
+
741
+ All functions are fully typed for best developer experience.
742
+
743
+ ---
744
+
745
+ ## πŸ› οΈ Support
746
+
747
+ Got stuck? Don’t panic β€” we’ve got you covered.
748
+
749
+ ### πŸ€– AI Assistant
750
+
751
+ We built a custom **AI Assistant** trained _only_ on `@salespark/toolkit`.
752
+ It answers implementation and troubleshooting questions in real time:
753
+
754
+ πŸ‘‰ Ask the Toolkit GPT:
755
+ https://chatgpt.com/g/g-68a9bf25537081918c3b76ae8f353e70-salespark-toolkit-v2
756
+
757
+ _(Free to use with a ChatGPT account)_
758
+
759
+ ---
760
+
761
+ ### πŸ”’ Internal Usage Notice
762
+
763
+ This package is primarily designed and maintained for internal use within the SalesPark ecosystem.
764
+ While it can technically be used in other Node.js/Mongoose projects, no official support or guarantees are provided outside of SalesPark-managed projects.
765
+
766
+ All code follows the same engineering standards applied across the SalesPark platform, ensuring consistency, reliability, and long-term maintainability of our internal systems.
767
+
768
+ ⚑ Note: This package is most efficient and works best when used together with other official SalesPark packages, where interoperability and optimizations are fully leveraged.
769
+
770
+ Disclaimer: This software is provided "as is", without warranties of any kind, express or implied. SalesPark shall not be held liable for any issues, damages, or losses arising from its use outside the intended SalesPark environment.
771
+
772
+ Organization packages: https://www.npmjs.com/org/salespark
773
+
774
+ ---
775
+
776
+ ## πŸ“„ License
777
+
778
+ MIT Β© [SalesPark](https://salespark.io)
779
+
780
+ ---
781
+
782
+ _Document version: 5_
783
+ _Last update: 25-09-2025_