@vielzeug/toolkit 1.1.2 โ†’ 1.1.3

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 (2) hide show
  1. package/README.md +546 -0
  2. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,546 @@
1
+ # @vielzeug/toolkit
2
+
3
+ <div align="center">
4
+ <img src="../../docs/public/logo-utils.svg" alt="Toolkit Logo" width="120" />
5
+
6
+ <p><strong>A comprehensive, type-safe utility library for modern JavaScript and TypeScript.</strong></p>
7
+
8
+ [![npm version](https://img.shields.io/npm/v/@vielzeug/toolkit.svg)](https://www.npmjs.com/package/@vielzeug/toolkit)
9
+ [![npm downloads](https://img.shields.io/npm/dm/@vielzeug/toolkit.svg)](https://www.npmjs.com/package/@vielzeug/toolkit)
10
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
11
+ [![TypeScript](https://img.shields.io/badge/TypeScript-100%25-blue)](https://www.typescriptlang.org/)
12
+ [![Bundle Size](https://img.shields.io/bundlephobia/minzip/@vielzeug/toolkit)](https://bundlephobia.com/package/@vielzeug/toolkit)
13
+
14
+ </div>
15
+
16
+ ## Features
17
+
18
+ - ๐ŸŽฏ **119 Type-Safe Utilities** - Covering arrays, objects, strings, async operations, and more
19
+ - ๐Ÿ“ฆ **Tree-Shakeable** - Import only what you need, minimize bundle size
20
+ - ๐Ÿ”’ **Zero Dependencies** - No supply chain risks, no version conflicts
21
+ - ๐Ÿ’ช **Full TypeScript Support** - Complete type inference and safety
22
+ - โšก **Async-First** - Built-in support for promises and async operations
23
+ - ๐Ÿงช **Battle-Tested** - >95% test coverage, production-ready
24
+ - ๐ŸŒ **Isomorphic** - Works in both browser and Node.js environments
25
+
26
+ ## Installation
27
+
28
+ ::: code-group
29
+
30
+ ```bash [pnpm]
31
+ pnpm add @vielzeug/toolkit
32
+ ```
33
+
34
+ ```bash [npm]
35
+ npm install @vielzeug/toolkit
36
+ ```
37
+
38
+ ```bash [yarn]
39
+ yarn add @vielzeug/toolkit
40
+ ```
41
+
42
+ :::
43
+
44
+ ## Quick Start
45
+
46
+ ```typescript
47
+ import { chunk, map, retry, pool } from '@vielzeug/toolkit';
48
+
49
+ // Array operations
50
+ const batches = chunk([1, 2, 3, 4, 5], 2);
51
+ // [[1, 2], [3, 4], [5]]
52
+
53
+ // Async map with automatic Promise handling
54
+ const users = await map([1, 2, 3], async (id) => fetchUser(id));
55
+
56
+ // Retry with exponential backoff
57
+ const data = await retry(() => fetch('/api/data').then((r) => r.json()), { times: 3, delay: 1000, backoff: 2 });
58
+
59
+ // Rate limiting with promise pool
60
+ const apiPool = pool(5); // Max 5 concurrent requests
61
+ const results = await Promise.all(urls.map((url) => apiPool(() => fetch(url))));
62
+ ```
63
+
64
+ ## Categories
65
+
66
+ ### ๐Ÿ“Š Array (25 utilities)
67
+
68
+ Transform, filter, group, and manipulate arrays with full type safety.
69
+
70
+ ```typescript
71
+ import { group, uniq, flatten, sort } from '@vielzeug/toolkit';
72
+
73
+ // Group by property
74
+ const grouped = group(users, (user) => user.role);
75
+
76
+ // Remove duplicates
77
+ const unique = uniq([1, 2, 2, 3, 3, 3]);
78
+
79
+ // Flatten nested arrays
80
+ const flat = flatten([
81
+ [1, 2],
82
+ [3, [4, 5]],
83
+ ]);
84
+
85
+ // Sort with custom comparator
86
+ const sorted = sort(items, (a, b) => a.price - b.price);
87
+ ```
88
+
89
+ **Available utilities:**
90
+ `aggregate`, `alternate`, `arrange`, `chunk`, `compact`, `contains`, `every`, `filter`, `find`, `findIndex`, `findLast`, `flatten`, `group`, `list`, `map`, `pick`, `reduce`, `remoteList`, `search`, `select`, `shift`, `some`, `sort`, `substitute`, `uniq`
91
+
92
+ ---
93
+
94
+ ### โšก Async (11 utilities)
95
+
96
+ Promise utilities, concurrency control, retries, and async patterns.
97
+
98
+ ```typescript
99
+ import { parallel, queue, waitFor, race, defer } from '@vielzeug/toolkit';
100
+
101
+ // Process with controlled concurrency
102
+ await parallel(3, urls, async (url) => fetch(url));
103
+
104
+ // Task queue with monitoring
105
+ const taskQueue = queue({ concurrency: 5 });
106
+ taskQueue.add(() => processTask());
107
+ await taskQueue.onIdle();
108
+
109
+ // Wait for condition
110
+ await waitFor(() => document.querySelector('#app') !== null);
111
+
112
+ // Race with minimum delay (better UX)
113
+ const data = await race(fetchData(), 500);
114
+
115
+ // Externally-controlled promise
116
+ const deferred = defer<string>();
117
+ setTimeout(() => deferred.resolve('Done!'), 1000);
118
+ ```
119
+
120
+ **Available utilities:**
121
+ `attempt`, `defer`, `delay`, `parallel`, `pool`, `predict`, `queue`, `race`, `retry`, `sleep`, `waitFor`
122
+
123
+ ---
124
+
125
+ ### ๐Ÿ“… Date (3 utilities)
126
+
127
+ Date manipulation and time calculations.
128
+
129
+ ```typescript
130
+ import { interval, timeDiff, expires } from '@vielzeug/toolkit';
131
+
132
+ // Calculate time intervals
133
+ const days = interval(new Date('2024-01-01'), new Date('2024-12-31'), 'days');
134
+
135
+ // Time difference
136
+ const diff = timeDiff(date1, date2);
137
+
138
+ // Check expiration
139
+ if (expires(expiryDate)) {
140
+ // Handle expired
141
+ }
142
+ ```
143
+
144
+ **Available utilities:**
145
+ `expires`, `interval`, `timeDiff`
146
+
147
+ ---
148
+
149
+ ### โš™๏ธ Function (14 utilities)
150
+
151
+ Function composition, memoization, and execution control.
152
+
153
+ ```typescript
154
+ import { debounce, throttle, memo, pipe, curry } from '@vielzeug/toolkit';
155
+
156
+ // Debounce user input
157
+ const search = debounce((query) => fetchResults(query), 300);
158
+
159
+ // Throttle scroll events
160
+ const onScroll = throttle(() => updateUI(), 100);
161
+
162
+ // Memoize expensive calculations
163
+ const fibonacci = memo((n) => (n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2)));
164
+
165
+ // Function composition
166
+ const transform = pipe(
167
+ (x) => x * 2,
168
+ (x) => x + 1,
169
+ (x) => x.toString(),
170
+ );
171
+
172
+ // Currying
173
+ const add = curry((a, b, c) => a + b + c);
174
+ const add5 = add(5);
175
+ ```
176
+
177
+ **Available utilities:**
178
+ `assert`, `assertParams`, `compare`, `compareBy`, `compose`, `curry`, `debounce`, `fp`, `memo`, `once`, `pipe`, `proxy`, `prune`, `throttle`, `worker`
179
+
180
+ ---
181
+
182
+ ### ๐Ÿ”ข Math (17 utilities)
183
+
184
+ Mathematical operations, statistics, and calculations.
185
+
186
+ ```typescript
187
+ import { average, median, clamp, range, distribute } from '@vielzeug/toolkit';
188
+
189
+ // Calculate average
190
+ const avg = average([1, 2, 3, 4, 5]); // 3
191
+
192
+ // Find median
193
+ const med = median([1, 2, 3, 4, 5]); // 3
194
+
195
+ // Clamp value to range
196
+ const clamped = clamp(150, 0, 100); // 100
197
+
198
+ // Generate range
199
+ const numbers = range(1, 10); // [1, 2, 3, ..., 10]
200
+
201
+ // Distribute amount
202
+ const shares = distribute(100, 3); // [33.33, 33.33, 33.34]
203
+ ```
204
+
205
+ **Available utilities:**
206
+ `abs`, `add`, `allocate`, `average`, `boil`, `clamp`, `distribute`, `divide`, `max`, `median`, `min`, `multiply`, `range`, `rate`, `round`, `subtract`, `sum`
207
+
208
+ ---
209
+
210
+ ### ๐Ÿ’ฐ Money (3 utilities)
211
+
212
+ Currency formatting and exchange calculations.
213
+
214
+ ```typescript
215
+ import { currency, exchange } from '@vielzeug/toolkit';
216
+
217
+ // Format currency
218
+ const formatted = currency(1234.56, 'USD'); // "$1,234.56"
219
+
220
+ // Currency exchange
221
+ const converted = exchange(100, 'USD', 'EUR', 0.85); // 85
222
+ ```
223
+
224
+ **Available utilities:**
225
+ `currency`, `exchange`, `types`
226
+
227
+ ---
228
+
229
+ ### ๐Ÿ“ฆ Object (10 utilities)
230
+
231
+ Deep merging, cloning, diffing, and object manipulation.
232
+
233
+ ```typescript
234
+ import { merge, clone, diff, path, seek } from '@vielzeug/toolkit';
235
+
236
+ // Deep merge
237
+ const merged = merge(obj1, obj2);
238
+
239
+ // Deep clone
240
+ const copy = clone(original);
241
+
242
+ // Diff objects
243
+ const changes = diff(oldObj, newObj);
244
+
245
+ // Get nested value
246
+ const value = path(obj, 'user.address.city');
247
+
248
+ // Search object
249
+ const results = seek(data, (val) => val > 100);
250
+ ```
251
+
252
+ **Available utilities:**
253
+ `cache`, `clone`, `diff`, `entries`, `keys`, `merge`, `parseJSON`, `path`, `seek`, `values`
254
+
255
+ ---
256
+
257
+ ### ๐ŸŽฒ Random (4 utilities)
258
+
259
+ Random values, shuffling, and UUID generation.
260
+
261
+ ```typescript
262
+ import { random, shuffle, draw, uuid } from '@vielzeug/toolkit';
263
+
264
+ // Random number
265
+ const num = random(1, 100);
266
+
267
+ // Shuffle array
268
+ const shuffled = shuffle([1, 2, 3, 4, 5]);
269
+
270
+ // Draw random items
271
+ const winners = draw(participants, 3);
272
+
273
+ // Generate UUID
274
+ const id = uuid(); // "550e8400-e29b-41d4-a716-446655440000"
275
+ ```
276
+
277
+ **Available utilities:**
278
+ `draw`, `random`, `shuffle`, `uuid`
279
+
280
+ ---
281
+
282
+ ### ๐Ÿ“ String (6 utilities)
283
+
284
+ String formatting, case conversion, and similarity.
285
+
286
+ ```typescript
287
+ import { camelCase, kebabCase, pascalCase, snakeCase, truncate, similarity } from '@vielzeug/toolkit';
288
+
289
+ // Case conversions
290
+ camelCase('hello world'); // "helloWorld"
291
+ kebabCase('hello world'); // "hello-world"
292
+ pascalCase('hello world'); // "HelloWorld"
293
+ snakeCase('hello world'); // "hello_world"
294
+
295
+ // Truncate text
296
+ truncate('Long text here', 10); // "Long text..."
297
+
298
+ // String similarity
299
+ similarity('hello', 'hallo'); // 0.8
300
+ ```
301
+
302
+ **Available utilities:**
303
+ `camelCase`, `kebabCase`, `pascalCase`, `similarity`, `snakeCase`, `truncate`
304
+
305
+ ---
306
+
307
+ ### โœ… Typed (27 utilities)
308
+
309
+ Type guards, type checking, and validation.
310
+
311
+ ```typescript
312
+ import { isString, isArray, isPromise, isEmpty, isEqual } from '@vielzeug/toolkit';
313
+
314
+ // Type guards with narrowing
315
+ if (isString(value)) {
316
+ // TypeScript knows value is string
317
+ console.log(value.toUpperCase());
318
+ }
319
+
320
+ // Check arrays
321
+ if (isArray(data)) {
322
+ data.forEach((item) => console.log(item));
323
+ }
324
+
325
+ // Promise detection
326
+ if (isPromise(result)) {
327
+ await result;
328
+ }
329
+
330
+ // Empty check
331
+ if (isEmpty(obj)) {
332
+ // Handle empty
333
+ }
334
+
335
+ // Deep equality
336
+ if (isEqual(obj1, obj2)) {
337
+ // Objects are equal
338
+ }
339
+ ```
340
+
341
+ **Available utilities:**
342
+ `ge`, `gt`, `is`, `isArray`, `isBoolean`, `isDate`, `isDefined`, `isEmpty`, `isEqual`, `isEven`, `isFunction`, `isNegative`, `isNil`, `isNumber`, `isObject`, `isOdd`, `isPositive`, `isPrimitive`, `isPromise`, `isRegex`, `isString`, `isWithin`, `isZero`, `le`, `lt`, `typeOf`
343
+
344
+ ## Real-World Examples
345
+
346
+ ### API Rate Limiting with Retry
347
+
348
+ ```typescript
349
+ import { pool, retry, predict } from '@vielzeug/toolkit';
350
+
351
+ // Create rate-limited pool
352
+ const apiPool = pool(10); // Max 10 concurrent requests
353
+
354
+ async function fetchWithRetry(url: string) {
355
+ return apiPool(() =>
356
+ retry(
357
+ () =>
358
+ predict(
359
+ async (signal) => {
360
+ const response = await fetch(url, { signal });
361
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
362
+ return response.json();
363
+ },
364
+ { timeout: 5000 },
365
+ ),
366
+ { times: 3, delay: 1000, backoff: 2 },
367
+ ),
368
+ );
369
+ }
370
+
371
+ // Process many URLs with rate limiting and retry
372
+ const results = await Promise.all(urls.map((url) => fetchWithRetry(url)));
373
+ ```
374
+
375
+ ### Batch Processing with Progress
376
+
377
+ ```typescript
378
+ import { chunk, parallel, sleep } from '@vielzeug/toolkit';
379
+
380
+ async function processBatch(items: any[], batchSize = 10) {
381
+ const batches = chunk(items, batchSize);
382
+ const results = [];
383
+
384
+ for (let i = 0; i < batches.length; i++) {
385
+ console.log(`Processing batch ${i + 1}/${batches.length}`);
386
+
387
+ const batchResults = await parallel(3, batches[i], async (item) => {
388
+ return await processItem(item);
389
+ });
390
+
391
+ results.push(...batchResults);
392
+
393
+ // Delay between batches
394
+ if (i < batches.length - 1) {
395
+ await sleep(1000);
396
+ }
397
+ }
398
+
399
+ return results;
400
+ }
401
+ ```
402
+
403
+ ### Form Validation Pipeline
404
+
405
+ ```typescript
406
+ import { pipe, curry, isEmpty, isString } from '@vielzeug/toolkit';
407
+
408
+ const required = (value: any) => {
409
+ if (isEmpty(value)) throw new Error('Required field');
410
+ return value;
411
+ };
412
+
413
+ const minLength = curry((min: number, value: string) => {
414
+ if (!isString(value) || value.length < min) {
415
+ throw new Error(`Minimum ${min} characters`);
416
+ }
417
+ return value;
418
+ });
419
+
420
+ const email = (value: string) => {
421
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
422
+ throw new Error('Invalid email');
423
+ }
424
+ return value;
425
+ };
426
+
427
+ // Create validation pipeline
428
+ const validateEmail = pipe(required, minLength(5), email);
429
+
430
+ try {
431
+ const validEmail = validateEmail(userInput);
432
+ } catch (error) {
433
+ console.error(error.message);
434
+ }
435
+ ```
436
+
437
+ ## Performance & Bundle Size
438
+
439
+ ### Tree-Shaking
440
+
441
+ Toolkit is designed for optimal tree-shaking. Import only what you use:
442
+
443
+ ```typescript
444
+ // โœ… Good - Only includes chunk function (~0.5KB gzipped)
445
+ import { chunk } from '@vielzeug/toolkit';
446
+
447
+ // โš ๏ธ Avoid - Imports entire library (~35KB gzipped)
448
+ import * as toolkit from '@vielzeug/toolkit';
449
+ ```
450
+
451
+ ### Bundle Size by Category
452
+
453
+ | Category | Utilities | Approx. Size (gzipped) |
454
+ | -------- | --------- | ---------------------- |
455
+ | Array | 25 | ~8KB |
456
+ | Async | 11 | ~3KB |
457
+ | Date | 3 | ~1KB |
458
+ | Function | 14 | ~5KB |
459
+ | Math | 17 | ~4KB |
460
+ | Money | 3 | ~1KB |
461
+ | Object | 10 | ~3KB |
462
+ | Random | 4 | ~1KB |
463
+ | String | 6 | ~2KB |
464
+ | Typed | 27 | ~3KB |
465
+
466
+ > **Note**: Individual utilities are typically **0.1-0.8 KB gzipped** each.
467
+
468
+ ## TypeScript Support
469
+
470
+ Full TypeScript support with complete type inference:
471
+
472
+ ```typescript
473
+ import { map, filter, group } from '@vielzeug/toolkit';
474
+
475
+ const numbers = [1, 2, 3, 4, 5];
476
+
477
+ // Type inferred as number[]
478
+ const doubled = map(numbers, (n) => n * 2);
479
+
480
+ // Type inferred as number[]
481
+ const evens = filter(numbers, (n) => n % 2 === 0);
482
+
483
+ // Type inferred as Record<string, User[]>
484
+ const byRole = group(users, (u) => u.role);
485
+
486
+ // Async operations automatically return Promise
487
+ const results = await map(ids, async (id) => fetchUser(id));
488
+ // Type: Promise<User[]>
489
+ ```
490
+
491
+ ## Comparison with Alternatives
492
+
493
+ | Feature | Toolkit | Lodash | Ramda | Native JS |
494
+ | ---------------------- | ---------------- | ----------------- | ----------------- | ---------- |
495
+ | TypeScript Support | โœ… First-class | โš ๏ธ Via @types | โš ๏ธ Via @types | โŒ Limited |
496
+ | Tree-shakeable | โœ… By default | โš ๏ธ lodash-es only | โœ… Yes | N/A |
497
+ | Bundle Size (min+gzip) | ~0.1-1KB/utility | ~24KB (full) | ~12KB (full) | 0KB |
498
+ | Dependencies | 0 | 0 | 0 | N/A |
499
+ | Async Support | โœ… Built-in | โŒ Limited | โŒ Limited | โš ๏ธ Manual |
500
+ | Learning Curve | Low | Low | High (FP focused) | Low |
501
+
502
+ ## Documentation
503
+
504
+ - **[Full Documentation](https://helmuthdu.github.io/vielzeug/toolkit/)**
505
+ - **[API Reference](https://helmuthdu.github.io/vielzeug/toolkit/api)**
506
+ - **[Usage Guide](https://helmuthdu.github.io/vielzeug/toolkit/usage)**
507
+ - **[Examples](https://helmuthdu.github.io/vielzeug/toolkit/examples/array)**
508
+
509
+ ## Contributing
510
+
511
+ We welcome contributions! Please see our [Contributing Guide](../../CONTRIBUTING.md) for details.
512
+
513
+ ### Development
514
+
515
+ ```bash
516
+ # Install dependencies
517
+ pnpm install
518
+
519
+ # Build the package
520
+ pnpm build
521
+
522
+ # Run tests
523
+ pnpm test
524
+
525
+ # Run tests in watch mode
526
+ pnpm test:watch
527
+
528
+ # Type check
529
+ pnpm typecheck
530
+ ```
531
+
532
+ ## License
533
+
534
+ MIT ยฉ [Helmuth Saatkamp](https://github.com/helmuthdu/vielzeug)
535
+
536
+ ## Related Packages
537
+
538
+ Part of the [@vielzeug](https://helmuthdu.github.io/vielzeug/) monorepo:
539
+
540
+ - **[@vielzeug/deposit](../deposit)** - Type-safe local storage with schemas and expiration
541
+ - **[@vielzeug/fetchit](../fetchit)** - Advanced HTTP client with caching and retries
542
+ - **[@vielzeug/formit](../formit)** - Type-safe form state and validation
543
+ - **[@vielzeug/i18nit](../i18nit)** - Internationalization with TypeScript
544
+ - **[@vielzeug/logit](../logit)** - Beautiful console logging
545
+ - **[@vielzeug/permit](../permit)** - Role-based access control
546
+ - **[@vielzeug/validit](../validit)** - Type-safe validation schemas
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vielzeug/toolkit",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"