@zairakai/js-utils 1.0.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.
Files changed (93) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +270 -0
  3. package/dist/arrays.cjs +210 -0
  4. package/dist/arrays.d.cts +119 -0
  5. package/dist/arrays.d.ts +119 -0
  6. package/dist/arrays.js +32 -0
  7. package/dist/chunk-27YHP2CK.js +407 -0
  8. package/dist/chunk-3WNRYKPG.js +37 -0
  9. package/dist/chunk-42CHLXT7.js +214 -0
  10. package/dist/chunk-6F4PWJZI.js +0 -0
  11. package/dist/chunk-7SXRFZBB.js +173 -0
  12. package/dist/chunk-F6RSTW65.js +156 -0
  13. package/dist/chunk-G7ZJ23DW.js +253 -0
  14. package/dist/chunk-IPP7PA6H.js +136 -0
  15. package/dist/chunk-LDSWHSRX.js +96 -0
  16. package/dist/chunk-TY75OOIQ.js +700 -0
  17. package/dist/chunk-W6JEMFAF.js +54 -0
  18. package/dist/chunk-XEJLBAXE.js +164 -0
  19. package/dist/chunk-Z7G3SIQH.js +270 -0
  20. package/dist/chunk-ZJPKS2MQ.js +101 -0
  21. package/dist/collections.cjs +797 -0
  22. package/dist/collections.d.cts +353 -0
  23. package/dist/collections.d.ts +353 -0
  24. package/dist/collections.js +17 -0
  25. package/dist/datetime.cjs +80 -0
  26. package/dist/datetime.d.cts +75 -0
  27. package/dist/datetime.d.ts +75 -0
  28. package/dist/datetime.js +24 -0
  29. package/dist/equals.cjs +121 -0
  30. package/dist/equals.d.cts +24 -0
  31. package/dist/equals.d.ts +24 -0
  32. package/dist/equals.js +8 -0
  33. package/dist/formatters.cjs +201 -0
  34. package/dist/formatters.d.cts +180 -0
  35. package/dist/formatters.d.ts +180 -0
  36. package/dist/formatters.js +48 -0
  37. package/dist/index.cjs +2906 -0
  38. package/dist/index.d.cts +120 -0
  39. package/dist/index.d.ts +120 -0
  40. package/dist/index.js +348 -0
  41. package/dist/number.cjs +279 -0
  42. package/dist/number.d.cts +177 -0
  43. package/dist/number.d.ts +177 -0
  44. package/dist/number.js +10 -0
  45. package/dist/obj.cjs +427 -0
  46. package/dist/obj.d.cts +177 -0
  47. package/dist/obj.d.ts +177 -0
  48. package/dist/obj.js +12 -0
  49. package/dist/php-arrays.cjs +954 -0
  50. package/dist/php-arrays.d.cts +256 -0
  51. package/dist/php-arrays.d.ts +256 -0
  52. package/dist/php-arrays.js +70 -0
  53. package/dist/runtime.cjs +134 -0
  54. package/dist/runtime.d.cts +90 -0
  55. package/dist/runtime.d.ts +90 -0
  56. package/dist/runtime.js +24 -0
  57. package/dist/schemas.cjs +86 -0
  58. package/dist/schemas.d.cts +108 -0
  59. package/dist/schemas.d.ts +108 -0
  60. package/dist/schemas.js +22 -0
  61. package/dist/str.cjs +499 -0
  62. package/dist/str.d.cts +282 -0
  63. package/dist/str.d.ts +282 -0
  64. package/dist/str.js +11 -0
  65. package/dist/types.cjs +18 -0
  66. package/dist/types.d.cts +13 -0
  67. package/dist/types.d.ts +13 -0
  68. package/dist/types.js +1 -0
  69. package/dist/validator.cjs +251 -0
  70. package/dist/validator.d.cts +99 -0
  71. package/dist/validator.d.ts +99 -0
  72. package/dist/validator.js +11 -0
  73. package/dist/validators.cjs +217 -0
  74. package/dist/validators.d.cts +216 -0
  75. package/dist/validators.d.ts +216 -0
  76. package/dist/validators.js +64 -0
  77. package/package.json +180 -0
  78. package/src/arrays.ts +316 -0
  79. package/src/collections.ts +866 -0
  80. package/src/datetime.ts +103 -0
  81. package/src/equals.ts +134 -0
  82. package/src/formatters.ts +342 -0
  83. package/src/index.ts +36 -0
  84. package/src/number.ts +281 -0
  85. package/src/obj.ts +303 -0
  86. package/src/php-arrays.ts +445 -0
  87. package/src/pipe.ts +29 -0
  88. package/src/runtime.ts +194 -0
  89. package/src/schemas.ts +136 -0
  90. package/src/str.ts +438 -0
  91. package/src/types.ts +13 -0
  92. package/src/validator.ts +157 -0
  93. package/src/validators.ts +359 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 Stanislas Poisson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,270 @@
1
+ # @zairakai/js-utils
2
+
3
+ [![Main][pipeline-main-badge]][pipeline-main-link]
4
+ [![Develop][pipeline-develop-badge]][pipeline-develop-link]
5
+ [![Coverage][coverage-badge]][coverage-link]
6
+
7
+ [![npm][npm-badge]][npm-link]
8
+ [![GitLab Release][gitlab-release-badge]][gitlab-release]
9
+ [![License][license-badge]][license]
10
+
11
+ [![Node.js][node-badge]][node]
12
+ [![ESLint][eslint-badge]][eslint]
13
+ [![Prettier][prettier-badge]][prettier]
14
+
15
+ Collection of JavaScript utility functions for string manipulation, validation, and formatting. Inspired by Laravel's helpers with modern TypeScript support.
16
+
17
+ ---
18
+
19
+ ## Features
20
+
21
+ - **Fluent Strings (`str`)** — Chained string manipulation (title, slug, limit, etc.)
22
+ - **Fluent Numbers (`num`)** — Formatting (currency, filesize), abbreviating, and calculations
23
+ - **Fluent Objects (`obj`)** — Dot notation access, deep merging, and state tracking (dirty/clean)
24
+ - **Enhanced Collections** — Laravel-like collection methods for arrays and maps
25
+ - **Runtime Validation (`validator`)** — Zod-powered validation with a familiar API
26
+ - **PHP-like Arrays** — Direct API parity for PHP's array functions (`array_chunk`, `array_merge`, etc.)
27
+ - **Runtime Schemas** — Pre-defined Zod schemas for common data types (Email, Phone, URL, etc.)
28
+ - **Deep Equality** — Robust deep comparison and diffing utilities
29
+ - **Type Guards** — Reliable type checking (isRecord, isEmail, etc.)
30
+ - **DateTime** — Lightweight wrapper around dayjs with useful presets
31
+
32
+ ---
33
+
34
+ ## Install
35
+
36
+ ```bash
37
+ npm install @zairakai/js-utils
38
+ ```
39
+
40
+ To use `validator` and `schemas` features, install `zod` (optional peer dependency):
41
+
42
+ ```bash
43
+ npm install zod
44
+ ```
45
+
46
+ ---
47
+
48
+ ## Usage Examples
49
+
50
+ ### Fluent Strings
51
+
52
+ ```typescript
53
+ import { str } from '@zairakai/js-utils'
54
+
55
+ const result = str('hello world').title().append(' extra').slug().get() // "hello-world-extra"
56
+ ```
57
+
58
+ ### Fluent Numbers
59
+
60
+ ```typescript
61
+ import { num } from '@zairakai/js-utils'
62
+
63
+ num(1024).fileSize() // "1 KB"
64
+ num(1500).abbreviate() // "1.5K"
65
+ num(10).add(5).mul(2).get() // 30
66
+ ```
67
+
68
+ ### State Tracking (Dirty)
69
+
70
+ ```typescript
71
+ import { obj } from '@zairakai/js-utils'
72
+
73
+ const user = obj({ name: 'John', status: 'active' })
74
+ user.dataSet('name', 'Jane')
75
+
76
+ user.isDirty() // true
77
+ user.getDirty() // { name: 'Jane' }
78
+ user.syncOriginal() // Mark as clean
79
+ ```
80
+
81
+ ### Validation
82
+
83
+ ```typescript
84
+ import { validator } from '@zairakai/js-utils'
85
+ import { z } from 'zod'
86
+
87
+ const v = validator(data, {
88
+ email: z.string().email(),
89
+ age: z.number().min(18),
90
+ })
91
+
92
+ if (v.fails()) {
93
+ console.log(v.errors())
94
+ }
95
+ ```
96
+
97
+ ---
98
+
99
+ ## API Reference
100
+
101
+ <details>
102
+ <summary><strong>Fluent Strings (str / Stringable)</strong></summary>
103
+
104
+ | Method | Description |
105
+ | ----------------------------- | ------------------------------------------------------- |
106
+ | `append(...values)` | Append the given values to the string. |
107
+ | `camel()` | Convert the string to camelCase. |
108
+ | `capitalize()` | Capitalize the first character. |
109
+ | `contains(needles)` | Determine if the string contains any of the needles. |
110
+ | `containsAll(needles)` | Determine if the string contains all of the needles. |
111
+ | `endsWith(needles)` | Determine if the string ends with any of the needles. |
112
+ | `finish(cap)` | Cap the string with a single instance of a given value. |
113
+ | `get()` / `toString()` | Get the raw string value. |
114
+ | `kebab()` | Convert the string to kebab-case. |
115
+ | `limit(size, end)` | Limit the number of characters in a string. |
116
+ | `lower()` | Convert the string to lower case. |
117
+ | `mask(char, index, length)` | Mask a portion of the string with a character. |
118
+ | `prepend(...values)` | Prepend the given values to the string. |
119
+ | `replace(search, replace)` | Replace the first occurrence of a value. |
120
+ | `replaceAll(search, replace)` | Replace all occurrences of a value. |
121
+ | `reverse()` | Reverse the string. |
122
+ | `slug()` | Convert the string to a URL friendly slug. |
123
+ | `snake()` | Convert the string to snake_case. |
124
+ | `start(prefix)` | Begin a string with a single instance of a given value. |
125
+ | `startsWith(needles)` | Determine if the string starts with any of the needles. |
126
+ | `studly()` | Convert the string to StudlyCase. |
127
+ | `title()` | Convert the string to Title Case. |
128
+ | `trim(chars?)` | Trim the string (optional custom characters). |
129
+ | `upper()` | Convert the string to upper case. |
130
+ | `when(condition, callback)` | Conditionally execute a callback. |
131
+
132
+ </details>
133
+
134
+ <details>
135
+ <summary><strong>Fluent Numbers (num / Numberable)</strong></summary>
136
+
137
+ | Method | Description |
138
+ | -------------------------------- | -------------------------------------------------- |
139
+ | `abbreviate(precision)` | Abbreviate the number (e.g., 1K, 1.5M). |
140
+ | `add(value)` / `sub(value)` | Arithmetic operations. |
141
+ | `mul(value)` / `div(value)` | Arithmetic operations. |
142
+ | `ceil()` / `floor()` / `round()` | Rounding operations. |
143
+ | `clamp(min, max)` | Clamp the number between min and max. |
144
+ | `currency(code, locale)` | Format as currency (default: USD). |
145
+ | `fileSize(precision)` | Format as human-readable file size (KB, MB, etc.). |
146
+ | `format(decimals, locale)` | Format the number with locale-specific separators. |
147
+ | `isBetween(min, max)` | Check if number is between min and max. |
148
+ | `ordinal()` | Add an ordinal suffix (1st, 2nd, 3rd...). |
149
+ | `percentage(decimals)` | Format as a percentage. |
150
+
151
+ </details>
152
+
153
+ <details>
154
+ <summary><strong>Fluent Objects (obj / Objectable)</strong></summary>
155
+
156
+ | Method | Description |
157
+ | ----------------------- | -------------------------------------------------------------- |
158
+ | `clone()` | Deep clone the object. |
159
+ | `dataGet(key, default)` | Get a value using dot notation (e.g., `user.profile.id`). |
160
+ | `dataSet(key, value)` | Set a value using dot notation. |
161
+ | `except(keys)` | Get all properties except those specified. |
162
+ | `filter(callback)` | Filter object properties. |
163
+ | `getDirty()` | Get the properties that have been modified. |
164
+ | `isDirty(key?)` | Determine if the object (or a specific key) has been modified. |
165
+ | `map(callback)` | Map over the object properties. |
166
+ | `merge(other)` | Shallow merge with another object. |
167
+ | `mergeDeep(other)` | Recursive deep merge. |
168
+ | `only(keys)` | Get only the specified properties. |
169
+ | `syncOriginal()` | Sync current state as the "clean" state. |
170
+
171
+ </details>
172
+
173
+ <details>
174
+ <summary><strong>Enhanced Collections (collect / EnhancedArray / EnhancedMap)</strong></summary>
175
+
176
+ Extends native `Array` and `Map` with 50+ methods including:
177
+
178
+ - **Navigation**: `at(index)`, `before(item)`, `after(item)`
179
+ - **Transformation**: `pluck(key)`, `groupBy(key)`, `unique(key)`, `chunk(size)`, `chunkBy(key)`, `deepFlatten()`, `transpose()`, `filterMap(cb)`, `extract(keys)`, `rotate(n)`, `getNth(n)`
180
+ - **Statistical**: `median()`, `mode()`, `standardDeviation()`, `percentile(p)`, `frequencies()`
181
+ - **Advanced**: `cartesian(...arrays)`, `interleave(...arrays)`, `sliding(size, step)`, `paginate(perPage, page)`, `weightedRandom(weights?)`, `recursive()`
182
+ - **State**: `isDirty()`, `isClean()`, `syncOriginal()`, `isEquivalent(other)`
183
+
184
+ </details>
185
+
186
+ <details>
187
+ <summary><strong>PHP-like Arrays (php_array)</strong></summary>
188
+
189
+ Provides direct API parity for PHP's array functions (only those that add value beyond native JS):
190
+ `array_chunk`, `array_filter`, `array_map`, `array_reduce`, `array_merge`, `array_unique`, `array_reverse`, `array_slice`, `array_splice`, `array_keys`, `array_search`, `array_key_exists`, `array_pop`, `array_push`, `array_shift`, `array_unshift`, `array_sum`, `array_product`, `array_rand`, `array_flip`, `array_count_values`, `array_intersect`, `array_diff`, `array_column`, `range`, and sorting functions (`sort`, `rsort`, `usort`, `uasort`, `uksort`, `shuffle`).
191
+
192
+ </details>
193
+
194
+ <details>
195
+ <summary><strong>Runtime Schemas</strong></summary>
196
+
197
+ Pre-defined Zod schemas and TypeScript types for common primitives:
198
+
199
+ - `EmailSchema` / `Email`
200
+ - `PhoneSchema` / `Phone`
201
+ - `UrlSchema` / `Url`
202
+ - `DateSchema`
203
+ - `ApiResponseSchema<T>` / `ApiResponse<T>`
204
+ - `PaginationSchema` / `Pagination`
205
+ - `PaginatedResponseSchema<T>` / `PaginatedResponse<T>`
206
+
207
+ Utility functions: `validateSchema(schema, data)`, `safeValidateSchema(schema, data)`.
208
+
209
+ > Requires `zod` — install separately (`npm install zod`).
210
+
211
+ </details>
212
+
213
+ <details>
214
+ <summary><strong>Standard Utilities</strong></summary>
215
+
216
+ - **Validators**: `isEmail`, `isUrl`, `isUuid`, `isIp`, `isMacAddress`, `isRecord`, `isInteger`, etc.
217
+ - **Formatters**: `snakeCase`, `kebabCase`, `camelCase`, `slugify`, `numberFormat`, etc.
218
+ - **Runtime**: `tap`, `when(condition, () => R)`, `retry`, `optional`, `data_get`, `data_set`, `throw_if`, `throw_unless`.
219
+ - **Deep Equality**: `isEqual(a, b)`, `diff(original, current)`.
220
+ - **DateTime**: `now()`, `today()`, `tomorrow()`, `yesterday()`, `isBetweenDates(date, start, end)`, `fromNow(date)`, `isToday(date)`, `isPast(date)`, `isFuture(date)`.
221
+
222
+ </details>
223
+
224
+ ---
225
+
226
+ ## Development
227
+
228
+ ```bash
229
+ npm test # run vitest
230
+ npm run build # build with tsup
231
+ npm run docs # generate TypeDoc documentation
232
+ npm run typecheck # run tsc
233
+ make quality # run full quality suite
234
+ ```
235
+
236
+ ---
237
+
238
+ ## Getting Help
239
+
240
+ [![License][license-badge]][license]
241
+ [![Security Policy][security-badge]][security]
242
+ [![Issues][issues-badge]][issues]
243
+
244
+ **Made with ❤️ by [Zairakai][ecosystem]**
245
+
246
+ <!-- Reference Links -->
247
+
248
+ [pipeline-main-badge]: https://gitlab.com/zairakai/npm-packages/js-utils/badges/main/pipeline.svg?ignore_skipped=true&key_text=Main
249
+ [pipeline-main-link]: https://gitlab.com/zairakai/npm-packages/js-utils/-/commits/main
250
+ [pipeline-develop-badge]: https://gitlab.com/zairakai/npm-packages/js-utils/badges/develop/pipeline.svg?ignore_skipped=true&key_text=Develop
251
+ [pipeline-develop-link]: https://gitlab.com/zairakai/npm-packages/js-utils/-/commits/develop
252
+ [coverage-badge]: https://gitlab.com/zairakai/npm-packages/js-utils/badges/main/coverage.svg
253
+ [coverage-link]: https://gitlab.com/zairakai/npm-packages/js-utils/-/pipelines?ref=main
254
+ [npm-badge]: https://img.shields.io/npm/v/@zairakai/js-utils
255
+ [npm-link]: https://www.npmjs.com/package/@zairakai/js-utils
256
+ [gitlab-release-badge]: https://img.shields.io/gitlab/v/release/zairakai/npm-packages/js-utils?logo=gitlab
257
+ [gitlab-release]: https://gitlab.com/zairakai/npm-packages/js-utils/-/releases
258
+ [license-badge]: https://img.shields.io/badge/license-MIT-blue.svg
259
+ [license]: ./LICENSE
260
+ [security-badge]: https://img.shields.io/badge/security-scanned-green.svg
261
+ [security]: ./SECURITY.md
262
+ [issues-badge]: https://img.shields.io/gitlab/issues/open-raw/zairakai%2Fnpm-packages%2Fhelpers?logo=gitlab&label=Issues
263
+ [issues]: https://gitlab.com/zairakai/npm-packages/js-utils/-/issues
264
+ [node-badge]: https://img.shields.io/badge/node.js-%3E%3D22-green.svg?logo=node.js
265
+ [node]: https://nodejs.org
266
+ [eslint-badge]: https://img.shields.io/badge/code%20style-eslint-4B32C3.svg?logo=eslint
267
+ [eslint]: https://eslint.org
268
+ [prettier-badge]: https://img.shields.io/badge/formatter-prettier-F7B93E.svg?logo=prettier
269
+ [prettier]: https://prettier.io
270
+ [ecosystem]: https://gitlab.com/zairakai
@@ -0,0 +1,210 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/arrays.ts
21
+ var arrays_exports = {};
22
+ __export(arrays_exports, {
23
+ arrayAdd: () => arrayAdd,
24
+ arrayCollapse: () => arrayCollapse,
25
+ arrayDivide: () => arrayDivide,
26
+ arrayDot: () => arrayDot,
27
+ arrayExcept: () => arrayExcept,
28
+ arrayFirst: () => arrayFirst,
29
+ arrayFlatten: () => arrayFlatten,
30
+ arrayGet: () => arrayGet,
31
+ arrayGroupBy: () => arrayGroupBy,
32
+ arrayHas: () => arrayHas,
33
+ arrayOnly: () => arrayOnly,
34
+ arrayPluck: () => arrayPluck,
35
+ arrayUnique: () => arrayUnique,
36
+ arrayWhere: () => arrayWhere
37
+ });
38
+ module.exports = __toCommonJS(arrays_exports);
39
+ var arrayAdd = (array, key, value) => {
40
+ const result = Array.isArray(array) ? Object.fromEntries(array.map((v, i) => [i, v])) : { ...array };
41
+ result[key] = value;
42
+ return result;
43
+ };
44
+ var arrayCollapse = (array) => {
45
+ if (!Array.isArray(array)) {
46
+ return [];
47
+ }
48
+ return array.reduce((flat, item) => {
49
+ if (Array.isArray(item)) {
50
+ return flat.concat(item);
51
+ }
52
+ return flat.concat([item]);
53
+ }, []);
54
+ };
55
+ var arrayDivide = (array) => {
56
+ if (!Array.isArray(array)) {
57
+ return [[], []];
58
+ }
59
+ const keys = array.map((_, index) => index.toString());
60
+ const values = [...array];
61
+ return [keys, values];
62
+ };
63
+ var arrayDot = (array, prepend = "") => {
64
+ const result = {};
65
+ for (const [key, value] of Object.entries(array)) {
66
+ const newKey = prepend ? `${prepend}.${key}` : key;
67
+ if (value && "object" === typeof value && !Array.isArray(value)) {
68
+ Object.assign(result, arrayDot(value, newKey));
69
+ } else {
70
+ result[newKey] = value;
71
+ }
72
+ }
73
+ return result;
74
+ };
75
+ var arrayExcept = (array, keys) => {
76
+ if (!Array.isArray(array) || !Array.isArray(keys)) {
77
+ return array;
78
+ }
79
+ return array.filter((_, index) => !keys.includes(index.toString()));
80
+ };
81
+ var arrayFirst = (array, callback, defaultValue) => {
82
+ if (!Array.isArray(array)) {
83
+ return defaultValue;
84
+ }
85
+ if (!callback) {
86
+ return 0 < array.length ? array[0] : defaultValue;
87
+ }
88
+ for (let i = 0; i < array.length; i++) {
89
+ if (callback(array[i], i)) {
90
+ return array[i];
91
+ }
92
+ }
93
+ return defaultValue;
94
+ };
95
+ var arrayFlatten = (array, depth = Infinity) => {
96
+ if (!Array.isArray(array)) {
97
+ return [];
98
+ }
99
+ const flatten = (arr, currentDepth) => {
100
+ const result = [];
101
+ for (const item of arr) {
102
+ if (Array.isArray(item) && 0 < currentDepth) {
103
+ result.push(...flatten(item, currentDepth - 1));
104
+ } else {
105
+ result.push(item);
106
+ }
107
+ }
108
+ return result;
109
+ };
110
+ return flatten(array, depth);
111
+ };
112
+ var arrayGet = (array, key, defaultValue) => {
113
+ if (!array || "object" !== typeof array) {
114
+ return defaultValue;
115
+ }
116
+ const keys = key.split(".");
117
+ let current = array;
118
+ for (const k of keys) {
119
+ if (null === current || current === void 0 || "object" !== typeof current || !(k in current)) {
120
+ return defaultValue;
121
+ }
122
+ current = current[k];
123
+ }
124
+ return current;
125
+ };
126
+ var arrayHas = (array, keys) => {
127
+ if (!array || "object" !== typeof array) {
128
+ return false;
129
+ }
130
+ const keyArray = Array.isArray(keys) ? keys : [keys];
131
+ return keyArray.every((key) => {
132
+ const keyParts = key.split(".");
133
+ let current = array;
134
+ for (const part of keyParts) {
135
+ if (null === current || current === void 0 || "object" !== typeof current || !(part in current)) {
136
+ return false;
137
+ }
138
+ current = current[part];
139
+ }
140
+ return true;
141
+ });
142
+ };
143
+ var arrayOnly = (array, keys) => {
144
+ if (!Array.isArray(array) || !Array.isArray(keys)) {
145
+ return [];
146
+ }
147
+ return array.filter((_, index) => keys.includes(index.toString()));
148
+ };
149
+ var arrayWhere = (array, callback) => {
150
+ if (!Array.isArray(array)) {
151
+ return [];
152
+ }
153
+ return array.filter(callback);
154
+ };
155
+ var arrayPluck = (array, key) => {
156
+ if (!Array.isArray(array)) {
157
+ return [];
158
+ }
159
+ return array.map((item) => item && "object" === typeof item ? item[key] : void 0).filter((value) => value !== void 0);
160
+ };
161
+ var arrayGroupBy = (array, keyOrFn) => {
162
+ if (!Array.isArray(array)) {
163
+ return {};
164
+ }
165
+ return array.reduce(
166
+ (groups, item) => {
167
+ const key = "function" === typeof keyOrFn ? String(keyOrFn(item)) : String(item && "object" === typeof item ? item[keyOrFn] : item);
168
+ if (!groups[key]) {
169
+ groups[key] = [];
170
+ }
171
+ groups[key].push(item);
172
+ return groups;
173
+ },
174
+ {}
175
+ );
176
+ };
177
+ var arrayUnique = (array, key) => {
178
+ if (!Array.isArray(array)) {
179
+ return [];
180
+ }
181
+ if (!key) {
182
+ return [...new Set(array)];
183
+ }
184
+ const seen = /* @__PURE__ */ new Set();
185
+ return array.filter((item) => {
186
+ const value = item && "object" === typeof item ? item[key] : item;
187
+ if (seen.has(value)) {
188
+ return false;
189
+ }
190
+ seen.add(value);
191
+ return true;
192
+ });
193
+ };
194
+ // Annotate the CommonJS export names for ESM import in node:
195
+ 0 && (module.exports = {
196
+ arrayAdd,
197
+ arrayCollapse,
198
+ arrayDivide,
199
+ arrayDot,
200
+ arrayExcept,
201
+ arrayFirst,
202
+ arrayFlatten,
203
+ arrayGet,
204
+ arrayGroupBy,
205
+ arrayHas,
206
+ arrayOnly,
207
+ arrayPluck,
208
+ arrayUnique,
209
+ arrayWhere
210
+ });
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Array manipulation and utility functions
3
+ * Inspired by Laravel's array helpers
4
+ */
5
+ /**
6
+ * Add an element to an array or record at a specific key.
7
+ *
8
+ * @param {T[] | Record<string, T>} array The source array or record
9
+ * @param {string} key The key to add the value at
10
+ * @param {T} value The value to add
11
+ * @returns {Record<string, unknown>} The resulting record
12
+ */
13
+ declare const arrayAdd: <T>(array: T[] | Record<string, T>, key: string, value: T) => Record<string, unknown>;
14
+ /**
15
+ * Collapse an array of arrays into a single array.
16
+ *
17
+ * @param {T[][]} array The array of arrays to collapse
18
+ * @returns {T[]} The collapsed array
19
+ */
20
+ declare const arrayCollapse: <T>(array: T[][]) => T[];
21
+ /**
22
+ * Divide an array into two arrays: one with keys (indices) and one with values.
23
+ *
24
+ * @param {T[]} array The array to divide
25
+ * @returns {[string[], T[]]} A tuple containing keys and values
26
+ */
27
+ declare const arrayDivide: <T>(array: T[]) => [string[], T[]];
28
+ /**
29
+ * Flatten a multi-dimensional record into a single-level record using dot notation.
30
+ *
31
+ * @param {Record<string, unknown>} array The record to flatten
32
+ * @param {string} prepend The string to prepend to keys
33
+ * @returns {Record<string, unknown>} The flattened record
34
+ */
35
+ declare const arrayDot: (array: Record<string, unknown>, prepend?: string) => Record<string, unknown>;
36
+ /**
37
+ * Get all of the given array except for a specified array of keys (indices).
38
+ *
39
+ * @param {T[]} array The source array
40
+ * @param {string[]} keys The keys to exclude
41
+ * @returns {T[]} The filtered array
42
+ */
43
+ declare const arrayExcept: <T>(array: T[], keys: string[]) => T[];
44
+ /**
45
+ * Return the first element in an array passing a given truth test.
46
+ *
47
+ * @param {T[]} array The source array
48
+ * @param {Function} [callback] Optional callback for truth test
49
+ * @param {T} [defaultValue] Optional default value if no element found
50
+ * @returns {T | undefined} The first matching element or default value
51
+ */
52
+ declare const arrayFirst: <T>(array: T[], callback?: (item: T, index: number) => boolean, defaultValue?: T) => T | undefined;
53
+ /**
54
+ * Flatten a multi-dimensional array into a single level.
55
+ *
56
+ * @param {unknown[]} array The array to flatten
57
+ * @param {number} [depth=Infinity] The depth to flatten to
58
+ * @returns {T[]} The flattened array
59
+ */
60
+ declare const arrayFlatten: <T>(array: unknown[], depth?: number) => T[];
61
+ /**
62
+ * Get an item from a record using dot notation.
63
+ *
64
+ * @param {Record<string, unknown>} array The source record
65
+ * @param {string} key The key to retrieve
66
+ * @param {unknown} [defaultValue] The default value if key not found
67
+ * @returns {unknown} The value at the key or default value
68
+ */
69
+ declare const arrayGet: (array: Record<string, unknown>, key: string, defaultValue?: unknown) => unknown;
70
+ /**
71
+ * Check if an item or items exist in a record using "dot" notation.
72
+ *
73
+ * @param {Record<string, unknown>} array The source record
74
+ * @param {string | string[]} keys The key or keys to check
75
+ * @returns {boolean} True if all keys exist, false otherwise
76
+ */
77
+ declare const arrayHas: (array: Record<string, unknown>, keys: string | string[]) => boolean;
78
+ /**
79
+ * Get a subset of the array's elements specified by keys (indices).
80
+ *
81
+ * @param {T[]} array The source array
82
+ * @param {string[]} keys The keys to include
83
+ * @returns {T[]} The filtered array
84
+ */
85
+ declare const arrayOnly: <T>(array: T[], keys: string[]) => T[];
86
+ /**
87
+ * Filter the array using the given callback.
88
+ *
89
+ * @param {T[]} array The source array
90
+ * @param {Function} callback The callback to use for filtering
91
+ * @returns {T[]} The filtered array
92
+ */
93
+ declare const arrayWhere: <T>(array: T[], callback: (item: T, index: number) => boolean) => T[];
94
+ /**
95
+ * Pluck an array of values from an array of objects.
96
+ *
97
+ * @param {T[]} array The source array
98
+ * @param {K} key The key to pluck
99
+ * @returns {T[K][]} The plucked values
100
+ */
101
+ declare const arrayPluck: <T, K extends keyof T>(array: T[], key: K) => T[K][];
102
+ /**
103
+ * Group an array's items by a given key or callback.
104
+ *
105
+ * @param {T[]} array The source array
106
+ * @param {keyof T | Function} keyOrFn The key or callback to group by
107
+ * @returns {Record<string, T[]>} The grouped items
108
+ */
109
+ declare const arrayGroupBy: <T>(array: T[], keyOrFn: keyof T | ((item: T) => string | number)) => Record<string, T[]>;
110
+ /**
111
+ * Filter the array to only unique elements.
112
+ *
113
+ * @param {T[]} array The source array
114
+ * @param {keyof T} [key] Optional key to use for uniqueness
115
+ * @returns {T[]} The array with unique elements
116
+ */
117
+ declare const arrayUnique: <T>(array: T[], key?: keyof T) => T[];
118
+
119
+ export { arrayAdd, arrayCollapse, arrayDivide, arrayDot, arrayExcept, arrayFirst, arrayFlatten, arrayGet, arrayGroupBy, arrayHas, arrayOnly, arrayPluck, arrayUnique, arrayWhere };