@catbee/utils 2.0.0-next.0 → 2.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.
- package/LICENSE +1 -1
- package/README.md +102 -52
- package/array/index.cjs +215 -74
- package/array/index.d.ts +345 -2
- package/array/index.mjs +201 -74
- package/async/index.cjs +116 -39
- package/async/index.d.ts +292 -2
- package/async/index.mjs +116 -40
- package/cache/index.cjs +2 -2
- package/cache/index.d.ts +156 -2
- package/cache/index.mjs +3 -3
- package/config/index.cjs +80 -66
- package/config/index.d.ts +65 -3
- package/config/index.mjs +77 -65
- package/context-store/index.cjs +2 -3
- package/context-store/index.d.ts +193 -2
- package/context-store/index.mjs +2 -3
- package/crypto/index.cjs +55 -5
- package/crypto/index.d.ts +225 -2
- package/crypto/index.mjs +52 -7
- package/date/index.cjs +676 -2
- package/date/index.d.ts +676 -2
- package/date/index.mjs +665 -3
- package/decorator/index.cjs +2172 -0
- package/{decorators/decorators.utils.d.ts → decorator/index.d.ts} +58 -54
- package/decorator/index.mjs +2131 -0
- package/{dir → directory}/index.cjs +5 -4
- package/{dir/dir.utils.d.ts → directory/index.d.ts} +24 -21
- package/{dir → directory}/index.mjs +5 -4
- package/env/index.cjs +100 -68
- package/env/index.d.ts +391 -2
- package/env/index.mjs +100 -68
- package/exception/index.cjs +1 -1
- package/exception/index.d.ts +233 -2
- package/exception/index.mjs +1 -1
- package/fs/index.cjs +71 -37
- package/fs/index.d.ts +206 -2
- package/fs/index.mjs +65 -35
- package/http-status-codes/index.cjs +1 -1
- package/http-status-codes/index.d.ts +268 -2
- package/http-status-codes/index.mjs +1 -1
- package/id/index.cjs +1 -1
- package/id/index.d.ts +38 -2
- package/id/index.mjs +1 -1
- package/index.cjs +13 -13
- package/index.d.ts +5 -5
- package/index.mjs +5 -5
- package/logger/index.cjs +13 -15
- package/logger/index.d.ts +190 -2
- package/logger/index.mjs +14 -16
- package/middleware/index.cjs +1 -1
- package/middleware/index.d.ts +104 -2
- package/middleware/index.mjs +1 -1
- package/object/index.cjs +379 -0
- package/{obj/obj.utils.d.ts → object/index.d.ts} +73 -33
- package/object/index.mjs +360 -0
- package/package.json +41 -23
- package/performance/index.cjs +4 -4
- package/performance/index.d.ts +139 -2
- package/performance/index.mjs +4 -4
- package/request/index.cjs +37 -25
- package/request/index.d.ts +242 -3
- package/request/index.mjs +37 -25
- package/response/index.cjs +1 -1
- package/response/index.d.ts +319 -3
- package/response/index.mjs +1 -1
- package/server/index.cjs +249 -146
- package/server/index.d.ts +866 -5
- package/server/index.mjs +248 -144
- package/stream/index.cjs +1 -1
- package/stream/index.d.ts +91 -2
- package/stream/index.mjs +1 -1
- package/string/index.cjs +34 -1
- package/string/index.d.ts +146 -2
- package/string/index.mjs +31 -2
- package/type/index.cjs +19 -2
- package/type/index.d.ts +144 -2
- package/type/index.mjs +17 -3
- package/types/index.cjs +1 -1
- package/types/index.d.ts +775 -5
- package/types/index.mjs +1 -1
- package/url/index.cjs +63 -5
- package/url/index.d.ts +200 -2
- package/url/index.mjs +59 -6
- package/{validate → validation}/index.cjs +91 -44
- package/{validate/validate.utils.d.ts → validation/index.d.ts} +33 -24
- package/{validate → validation}/index.mjs +87 -44
- package/array/array.utils.d.ts +0 -191
- package/async/async.utils.d.ts +0 -296
- package/cache/cache.utils.d.ts +0 -176
- package/config/config.d.ts +0 -57
- package/context-store/context-store.utils.d.ts +0 -212
- package/crypto/crypto.utils.d.ts +0 -183
- package/date/date.utils.d.ts +0 -190
- package/decorators/index.cjs +0 -913
- package/decorators/index.d.ts +0 -25
- package/decorators/index.mjs +0 -872
- package/dir/index.d.ts +0 -25
- package/env/env.utils.d.ts +0 -400
- package/exception/exception.utils.d.ts +0 -253
- package/fs/fs.utils.d.ts +0 -196
- package/http-status-codes/http-status-codes.d.ts +0 -289
- package/id/id.utils.d.ts +0 -59
- package/logger/logger.utils.d.ts +0 -210
- package/middleware/middleware.utils.d.ts +0 -123
- package/obj/index.cjs +0 -317
- package/obj/index.d.ts +0 -25
- package/obj/index.mjs +0 -301
- package/performance/performance.utils.d.ts +0 -159
- package/request/request.utils.d.ts +0 -109
- package/response/response.utils.d.ts +0 -186
- package/server/server.builder.d.ts +0 -531
- package/server/server.d.ts +0 -303
- package/stream/stream.utils.d.ts +0 -111
- package/string/string.utils.d.ts +0 -124
- package/type/type.utils.d.ts +0 -129
- package/types/api-response.d.ts +0 -175
- package/types/common.d.ts +0 -148
- package/types/config.d.ts +0 -88
- package/types/server.d.ts +0 -291
- package/url/url.utils.d.ts +0 -164
- package/validate/index.d.ts +0 -25
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
The MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) 2026 Catbee Technologies. https://catbee.in/license
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
# @catbee/utils
|
|
2
2
|
|
|
3
|
-
<!-- <div style="width: 100%; display: flex; align-items: center; justify-content: space-between;">
|
|
4
|
-
<b style="font-size: 24px; text-decoration: none;">@catbee/utils</b>
|
|
5
|
-
<a href="https://sonarcloud.io/summary/new_code?id=catbee-technologies_catbee-utils">
|
|
6
|
-
<img src="https://sonarcloud.io/images/project_badges/sonarcloud-dark.svg" alt="SonarQube Cloud" width="200"/>
|
|
7
|
-
</a>
|
|
8
|
-
</div> -->
|
|
9
3
|
|
|
10
4
|
## 🧰 Utility Modules for Node.js
|
|
11
5
|
|
|
@@ -20,7 +14,7 @@ A modular, production-grade utility toolkit for Node.js and TypeScript, designed
|
|
|
20
14
|
<img src="https://img.shields.io/npm/v/@catbee/utils/next" alt="NPM Next Version" /> -->
|
|
21
15
|
<img src="https://img.shields.io/npm/dt/@catbee/utils" alt="NPM Downloads" />
|
|
22
16
|
<img src="https://img.shields.io/npm/types/@catbee/utils" alt="TypeScript Types" />
|
|
23
|
-
<img src="https://img.shields.io/maintenance/yes/
|
|
17
|
+
<img src="https://img.shields.io/maintenance/yes/2050" alt="Maintenance" />
|
|
24
18
|
<img src="https://snyk.io/test/github/catbee-technologies/catbee-utils/badge.svg" alt="Snyk Vulnerabilities" />
|
|
25
19
|
<img src="https://sonarcloud.io/api/project_badges/measure?project=catbee-technologies_catbee-utils&metric=alert_status&token=93da835f2d48d37b41fa628cc7fc764c873bd700" alt="Quality Gate Status" />
|
|
26
20
|
<img src="https://sonarcloud.io/api/project_badges/measure?project=catbee-technologies_catbee-utils&metric=ncloc&token=93da835f2d48d37b41fa628cc7fc764c873bd700" alt="Lines of Code" />
|
|
@@ -53,66 +47,122 @@ npm i @catbee/utils
|
|
|
53
47
|
## ⚡ Quick Start
|
|
54
48
|
|
|
55
49
|
```ts
|
|
56
|
-
import {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
50
|
+
import { ServerConfigBuilder, ExpressServer } from '@catbee/utils/server';
|
|
51
|
+
import { Router } from 'express';
|
|
52
|
+
|
|
53
|
+
const config = new ServerConfigBuilder()
|
|
54
|
+
.withPort(3000)
|
|
55
|
+
.withCors({ origin: '*' })
|
|
56
|
+
.enableRateLimit({ max: 50, windowMs: 60000 })
|
|
57
|
+
.enableRequestLogging({ ignorePaths: ['/healthz', '/metrics'] })
|
|
58
|
+
.withHealthCheck({ path: '/health', detailed: true })
|
|
59
|
+
.enableOpenApi('./openapi.yaml', { mountPath: '/docs' })
|
|
60
|
+
.withGlobalHeaders({ 'X-Powered-By': 'Catbee' })
|
|
61
|
+
.withGlobalPrefix('/api')
|
|
62
|
+
.withRequestId({ headerName: 'X-Request-Id', exposeHeader: true })
|
|
63
|
+
.enableResponseTime({ addHeader: true, logOnComplete: true })
|
|
64
|
+
.build();
|
|
65
|
+
|
|
66
|
+
const server = new ExpressServer(config, {
|
|
67
|
+
beforeInit: srv => console.log('Initializing server...'),
|
|
68
|
+
afterInit: srv => console.log('Server initialized'),
|
|
69
|
+
beforeStart: app => console.log('Starting server...'),
|
|
70
|
+
afterStart: srv => console.log('Server started!'),
|
|
71
|
+
beforeStop: srv => console.log('Stopping server...'),
|
|
72
|
+
afterStop: () => console.log('Server stopped.'),
|
|
73
|
+
onRequest: (req, res, next) => {
|
|
74
|
+
console.log('Processing request:', req.method, req.url);
|
|
75
|
+
next();
|
|
76
|
+
},
|
|
77
|
+
onResponse: (req, res, next) => {
|
|
78
|
+
res.setHeader('X-Processed-By', 'ExpressServer');
|
|
79
|
+
next();
|
|
80
|
+
},
|
|
81
|
+
onError: (err, req, res, next) => {
|
|
82
|
+
console.error('Custom error handler:', err);
|
|
83
|
+
res.status(500).json({ error: 'Custom error: ' + err.message });
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Register routes
|
|
88
|
+
const router = server.createRouter('/users');
|
|
89
|
+
router.get('/', (req, res) => res.json({ users: [] }));
|
|
90
|
+
router.post('/', (req, res) => res.json({ created: true }));
|
|
91
|
+
|
|
92
|
+
// Or set a base router for all routes
|
|
93
|
+
const baseRouter = Router();
|
|
94
|
+
baseRouter.use('/users', router);
|
|
95
|
+
server.setBaseRouter(baseRouter);
|
|
96
|
+
|
|
97
|
+
server.registerHealthCheck('database', async () => await checkDatabaseConnection());
|
|
98
|
+
server.useMiddleware(loggingMiddleware, errorMiddleware);
|
|
99
|
+
|
|
100
|
+
await server.start();
|
|
101
|
+
server.enableGracefulShutdown();
|
|
72
102
|
```
|
|
73
103
|
|
|
74
104
|
---
|
|
75
105
|
|
|
76
106
|
## 📚 Modules Overview
|
|
77
107
|
|
|
78
|
-
| Module
|
|
79
|
-
|
|
|
80
|
-
| [Express Server](https://catbee.in/docs/@catbee/utils/
|
|
81
|
-
| [Array Utilities](https://catbee.in/docs/@catbee/utils/
|
|
82
|
-
| [Async Utilities](https://catbee.in/docs/@catbee/utils/
|
|
83
|
-
| [Cache Utilities](https://catbee.in/docs/@catbee/utils/
|
|
84
|
-
| [Context Store](https://catbee.in/docs/@catbee/utils/
|
|
85
|
-
| [Crypto Utilities](https://catbee.in/docs/@catbee/utils/
|
|
86
|
-
| [Date Utilities](https://catbee.in/docs/@catbee/utils/
|
|
87
|
-
| [Decorators Utilities](https://catbee.in/docs/@catbee/utils/
|
|
88
|
-
| [Directory Utilities](https://catbee.in/docs/@catbee/utils/
|
|
89
|
-
| [Environment Utilities](https://catbee.in/docs/@catbee/utils/
|
|
90
|
-
| [Exception Utilities](https://catbee.in/docs/@catbee/utils/
|
|
91
|
-
| [File System Utilities](https://catbee.in/docs/@catbee/utils/
|
|
92
|
-
| [HTTP Status Codes](https://catbee.in/docs/@catbee/utils/
|
|
93
|
-
| [ID Utilities](https://catbee.in/docs/@catbee/utils/
|
|
94
|
-
| [Logger Utilities](https://catbee.in/docs/@catbee/utils/
|
|
95
|
-
| [Middleware Utilities](https://catbee.in/docs/@catbee/utils/
|
|
96
|
-
| [Object Utilities](https://catbee.in/docs/@catbee/utils/
|
|
97
|
-
| [Performance Utilities](https://catbee.in/docs/@catbee/utils/
|
|
98
|
-
| [Request Utilities](https://catbee.in/docs/@catbee/utils/
|
|
99
|
-
| [Response Utilities](https://catbee.in/docs/@catbee/utils/
|
|
100
|
-
| [Stream Utilities](https://catbee.in/docs/@catbee/utils/
|
|
101
|
-
| [String Utilities](https://catbee.in/docs/@catbee/utils/
|
|
102
|
-
| [Type Utilities](https://catbee.in/docs/@catbee/utils/
|
|
103
|
-
| [
|
|
104
|
-
| [
|
|
108
|
+
| Module | Description |
|
|
109
|
+
| --------------------------------------------------------------------------- | ------------------------------------------------------- |
|
|
110
|
+
| [Express Server](https://catbee.in/docs/@catbee/utils/server) | Fast, secure, and scalable server setup |
|
|
111
|
+
| [Array Utilities](https://catbee.in/docs/@catbee/utils/array) | Advanced array manipulation |
|
|
112
|
+
| [Async Utilities](https://catbee.in/docs/@catbee/utils/async) | Promise helpers, concurrency, timing |
|
|
113
|
+
| [Cache Utilities](https://catbee.in/docs/@catbee/utils/cache) | In-memory caching with TTL |
|
|
114
|
+
| [Context Store](https://catbee.in/docs/@catbee/utils/context-store) | Per-request context via AsyncLocalStorage |
|
|
115
|
+
| [Crypto Utilities](https://catbee.in/docs/@catbee/utils/crypto) | Hashing, encryption, tokens |
|
|
116
|
+
| [Date Utilities](https://catbee.in/docs/@catbee/utils/date) | Date/time manipulation |
|
|
117
|
+
| [Decorators Utilities](https://catbee.in/docs/@catbee/utils/decorator) | TypeScript decorators for Express |
|
|
118
|
+
| [Directory Utilities](https://catbee.in/docs/@catbee/utils/directory) | Directory and file system helpers |
|
|
119
|
+
| [Environment Utilities](https://catbee.in/docs/@catbee/utils/environment) | Env variable management |
|
|
120
|
+
| [Exception Utilities](https://catbee.in/docs/@catbee/utils/exception) | HTTP and error handling |
|
|
121
|
+
| [File System Utilities](https://catbee.in/docs/@catbee/utils/fs) | File operations |
|
|
122
|
+
| [HTTP Status Codes](https://catbee.in/docs/@catbee/utils/http-status-codes) | Typed status codes |
|
|
123
|
+
| [ID Utilities](https://catbee.in/docs/@catbee/utils/id) | UUID and ID generation |
|
|
124
|
+
| [Logger Utilities](https://catbee.in/docs/@catbee/utils/logger) | Structured logging with Pino |
|
|
125
|
+
| [Middleware Utilities](https://catbee.in/docs/@catbee/utils/middleware) | Express middleware collection |
|
|
126
|
+
| [Object Utilities](https://catbee.in/docs/@catbee/utils/object) | Deep merge, flatten, pick/omit, etc. |
|
|
127
|
+
| [Performance Utilities](https://catbee.in/docs/@catbee/utils/performance) | Timing, memoization, memory tracking |
|
|
128
|
+
| [Request Utilities](https://catbee.in/docs/@catbee/utils/request) | HTTP request parameter parsing/validation |
|
|
129
|
+
| [Response Utilities](https://catbee.in/docs/@catbee/utils/response) | Standardized API response formatting |
|
|
130
|
+
| [Stream Utilities](https://catbee.in/docs/@catbee/utils/stream) | Stream conversion, batching, throttling, line splitting |
|
|
131
|
+
| [String Utilities](https://catbee.in/docs/@catbee/utils/string) | Casing, masking, slugifying, formatting |
|
|
132
|
+
| [Type Utilities](https://catbee.in/docs/@catbee/utils/type) | Type checking, conversion, guards |
|
|
133
|
+
| [Types Utilities](https://catbee.in/docs/@catbee/utils/types) | Common TypeScript types and interfaces |
|
|
134
|
+
| [URL Utilities](https://catbee.in/docs/@catbee/utils/url) | URL parsing, query manipulation, normalization |
|
|
135
|
+
| [Validate Utilities](https://catbee.in/docs/@catbee/utils/validation) | Input validation functions |
|
|
105
136
|
|
|
106
137
|
---
|
|
107
138
|
|
|
108
139
|
## 🏁 Usage
|
|
109
140
|
|
|
110
|
-
|
|
141
|
+
This library supports flexible import patterns to suit your needs:
|
|
142
|
+
|
|
143
|
+
### Root-level imports (everything available)
|
|
144
|
+
Import any utility directly from the root package:
|
|
111
145
|
|
|
112
146
|
```ts
|
|
113
|
-
import { chunk, sleep, TTLCache, getLogger } from
|
|
147
|
+
import { chunk, sleep, TTLCache, getLogger, ServerConfigBuilder } from '@catbee/utils';
|
|
114
148
|
```
|
|
115
149
|
|
|
150
|
+
### Module-level imports (scoped imports)
|
|
151
|
+
Import only from specific modules for better organization and smaller bundles:
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
// Import only server-related exports
|
|
155
|
+
import { ServerConfigBuilder, ExpressServer } from '@catbee/utils/server';
|
|
156
|
+
|
|
157
|
+
// Import only date utilities
|
|
158
|
+
import { formatDate, addDays, DateBuilder } from '@catbee/utils/date';
|
|
159
|
+
|
|
160
|
+
// Import only crypto utilities
|
|
161
|
+
import { hashPassword, verifyPassword } from '@catbee/utils/crypto';
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Both import styles are fully supported and tree-shakable. Use whichever fits your project structure best!
|
|
165
|
+
|
|
116
166
|
---
|
|
117
167
|
|
|
118
168
|
## 📖 Documentation
|
package/array/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The MIT License
|
|
3
3
|
*
|
|
4
|
-
* Copyright (c)
|
|
4
|
+
* Copyright (c) 2026 Catbee Technologies. https://catbee.in/license
|
|
5
5
|
*
|
|
6
6
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
* of this software and associated documentation files (the "Software"), to deal
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
|
|
25
25
|
'use strict';
|
|
26
26
|
|
|
27
|
-
var
|
|
27
|
+
var object = require('@catbee/utils/object');
|
|
28
|
+
var crypto = require('crypto');
|
|
28
29
|
|
|
29
30
|
var __defProp = Object.defineProperty;
|
|
30
31
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
@@ -43,49 +44,64 @@ function unique(array, keyFn) {
|
|
|
43
44
|
if (!Array.isArray(array) || array.length === 0) return [];
|
|
44
45
|
if (!keyFn) return Array.from(new Set(array));
|
|
45
46
|
const seen = /* @__PURE__ */ new Set();
|
|
46
|
-
|
|
47
|
+
const result = [];
|
|
48
|
+
for (const item of array) {
|
|
47
49
|
const key = keyFn(item);
|
|
48
|
-
if (seen.has(key))
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
if (!seen.has(key)) {
|
|
51
|
+
seen.add(key);
|
|
52
|
+
result.push(item);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
52
56
|
}
|
|
53
57
|
__name(unique, "unique");
|
|
54
58
|
function flattenDeep(array) {
|
|
55
59
|
if (!Array.isArray(array)) return [];
|
|
56
60
|
const result = [];
|
|
57
|
-
|
|
61
|
+
const stack = [
|
|
62
|
+
...array
|
|
63
|
+
];
|
|
64
|
+
while (stack.length) {
|
|
65
|
+
const val = stack.pop();
|
|
58
66
|
if (Array.isArray(val)) {
|
|
59
|
-
|
|
67
|
+
stack.push(...val);
|
|
60
68
|
} else {
|
|
61
69
|
result.push(val);
|
|
62
70
|
}
|
|
63
71
|
}
|
|
64
|
-
return result;
|
|
72
|
+
return result.reverse();
|
|
65
73
|
}
|
|
66
74
|
__name(flattenDeep, "flattenDeep");
|
|
67
75
|
function random(array) {
|
|
68
76
|
if (!Array.isArray(array) || array.length === 0) return void 0;
|
|
69
|
-
|
|
70
|
-
return array[idx];
|
|
77
|
+
return array[secureIndex(array.length)];
|
|
71
78
|
}
|
|
72
79
|
__name(random, "random");
|
|
73
80
|
function groupBy(array, keyOrFn) {
|
|
74
81
|
if (!Array.isArray(array) || array.length === 0) return {};
|
|
75
|
-
const keyFn = typeof keyOrFn === "function" ? keyOrFn : (item) => item
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
const keyFn = typeof keyOrFn === "function" ? keyOrFn : (item) => String(object.getValueByPath(item, keyOrFn));
|
|
83
|
+
const result = {};
|
|
84
|
+
for (const item of array) {
|
|
85
|
+
const key = String(keyFn(item));
|
|
86
|
+
if (Object.hasOwn(result, key)) {
|
|
87
|
+
result[key].push(item);
|
|
88
|
+
} else {
|
|
89
|
+
result[key] = [
|
|
90
|
+
item
|
|
91
|
+
];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return Object.fromEntries(Object.entries(result).map(([k, v]) => [
|
|
95
|
+
k,
|
|
96
|
+
v
|
|
97
|
+
]));
|
|
82
98
|
}
|
|
83
99
|
__name(groupBy, "groupBy");
|
|
84
100
|
function shuffle(array) {
|
|
85
101
|
if (!Array.isArray(array)) throw new TypeError("Expected an array");
|
|
86
102
|
const copy = array.slice();
|
|
87
103
|
for (let i = copy.length - 1; i > 0; i--) {
|
|
88
|
-
const j =
|
|
104
|
+
const j = secureIndex(i + 1);
|
|
89
105
|
[copy[i], copy[j]] = [
|
|
90
106
|
copy[j],
|
|
91
107
|
copy[i]
|
|
@@ -96,7 +112,7 @@ function shuffle(array) {
|
|
|
96
112
|
__name(shuffle, "shuffle");
|
|
97
113
|
function pluck(array, key) {
|
|
98
114
|
if (!Array.isArray(array)) return [];
|
|
99
|
-
return array.map((item) => item[key]);
|
|
115
|
+
return array.map((item) => item?.[key]);
|
|
100
116
|
}
|
|
101
117
|
__name(pluck, "pluck");
|
|
102
118
|
function difference(a, b) {
|
|
@@ -111,35 +127,41 @@ function intersect(a, b) {
|
|
|
111
127
|
return a.filter((item) => setB.has(item));
|
|
112
128
|
}
|
|
113
129
|
__name(intersect, "intersect");
|
|
114
|
-
function mergeSort(array, key, direction = "asc") {
|
|
130
|
+
function mergeSort(array, key, direction = "asc", compareFn) {
|
|
115
131
|
if (!Array.isArray(array)) throw new TypeError("Expected array");
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
const
|
|
132
|
+
const arr = array.slice();
|
|
133
|
+
if (arr.length <= 1) return arr;
|
|
134
|
+
const keyFn = typeof key === "function" ? key : (item) => object.getValueByPath(item, key);
|
|
135
|
+
const collator = new Intl.Collator("en", {
|
|
136
|
+
numeric: true
|
|
137
|
+
});
|
|
138
|
+
const compare = compareFn ?? function(a, b) {
|
|
119
139
|
const aVal = keyFn(a);
|
|
120
140
|
const bVal = keyFn(b);
|
|
121
141
|
if (aVal === bVal) return 0;
|
|
122
142
|
if (aVal == null) return direction === "asc" ? 1 : -1;
|
|
123
143
|
if (bVal == null) return direction === "asc" ? -1 : 1;
|
|
124
|
-
return direction === "asc" ? aVal
|
|
125
|
-
}
|
|
144
|
+
return direction === "asc" ? collator.compare(String(aVal), String(bVal)) : collator.compare(String(bVal), String(aVal));
|
|
145
|
+
};
|
|
126
146
|
const merge = /* @__PURE__ */ __name((left, right) => {
|
|
127
147
|
const result = [];
|
|
128
148
|
let i = 0, j = 0;
|
|
129
149
|
while (i < left.length && j < right.length) {
|
|
130
|
-
|
|
131
|
-
else result.push(right[j++]);
|
|
150
|
+
result.push(compare(left[i], right[j]) <= 0 ? left[i++] : right[j++]);
|
|
132
151
|
}
|
|
133
|
-
|
|
152
|
+
while (i < left.length) result.push(left[i++]);
|
|
153
|
+
while (j < right.length) result.push(right[j++]);
|
|
154
|
+
return result;
|
|
134
155
|
}, "merge");
|
|
135
|
-
const sort = /* @__PURE__ */ __name((
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const
|
|
139
|
-
const
|
|
156
|
+
const sort = /* @__PURE__ */ __name((input) => {
|
|
157
|
+
const len = input.length;
|
|
158
|
+
if (len <= 1) return input;
|
|
159
|
+
const mid = len >> 1;
|
|
160
|
+
const left = sort(input.slice(0, mid));
|
|
161
|
+
const right = sort(input.slice(mid));
|
|
140
162
|
return merge(left, right);
|
|
141
163
|
}, "sort");
|
|
142
|
-
return sort(
|
|
164
|
+
return sort(arr);
|
|
143
165
|
}
|
|
144
166
|
__name(mergeSort, "mergeSort");
|
|
145
167
|
function zip(...arrays) {
|
|
@@ -156,28 +178,20 @@ function zip(...arrays) {
|
|
|
156
178
|
}
|
|
157
179
|
__name(zip, "zip");
|
|
158
180
|
function partition(array, predicate) {
|
|
181
|
+
const pass = [];
|
|
182
|
+
const fail = [];
|
|
159
183
|
if (!Array.isArray(array)) return [
|
|
160
|
-
|
|
161
|
-
|
|
184
|
+
pass,
|
|
185
|
+
fail
|
|
186
|
+
];
|
|
187
|
+
for (let i = 0; i < array.length; i++) {
|
|
188
|
+
const item = array[i];
|
|
189
|
+
(predicate(item, i, array) ? pass : fail).push(item);
|
|
190
|
+
}
|
|
191
|
+
return [
|
|
192
|
+
pass,
|
|
193
|
+
fail
|
|
162
194
|
];
|
|
163
|
-
return array.reduce(([pass, fail], item, index) => {
|
|
164
|
-
return predicate(item, index, array) ? [
|
|
165
|
-
[
|
|
166
|
-
...pass,
|
|
167
|
-
item
|
|
168
|
-
],
|
|
169
|
-
fail
|
|
170
|
-
] : [
|
|
171
|
-
pass,
|
|
172
|
-
[
|
|
173
|
-
...fail,
|
|
174
|
-
item
|
|
175
|
-
]
|
|
176
|
-
];
|
|
177
|
-
}, [
|
|
178
|
-
[],
|
|
179
|
-
[]
|
|
180
|
-
]);
|
|
181
195
|
}
|
|
182
196
|
__name(partition, "partition");
|
|
183
197
|
function range(start, end, step = 1) {
|
|
@@ -185,62 +199,189 @@ function range(start, end, step = 1) {
|
|
|
185
199
|
throw new TypeError("Arguments must be finite numbers");
|
|
186
200
|
}
|
|
187
201
|
if (step === 0) throw new Error("Step cannot be zero");
|
|
188
|
-
const
|
|
189
|
-
if (
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const result = new Array(length);
|
|
194
|
-
for (let i = 0, value = start; i < length; i++, value += step) {
|
|
195
|
-
result[i] = value;
|
|
202
|
+
const result = [];
|
|
203
|
+
if (step > 0) {
|
|
204
|
+
for (let i = start; i < end; i += step) result.push(i);
|
|
205
|
+
} else {
|
|
206
|
+
for (let i = start; i > end; i += step) result.push(i);
|
|
196
207
|
}
|
|
197
208
|
return result;
|
|
198
209
|
}
|
|
199
210
|
__name(range, "range");
|
|
200
211
|
function take(array, n = 1) {
|
|
201
212
|
if (!Array.isArray(array) || n <= 0) return [];
|
|
202
|
-
return array.slice(0, n);
|
|
213
|
+
return n >= array.length ? array.slice() : array.slice(0, n);
|
|
203
214
|
}
|
|
204
215
|
__name(take, "take");
|
|
205
216
|
function takeWhile(array, predicate) {
|
|
206
|
-
if (!Array.isArray(array)) return [];
|
|
207
217
|
const result = [];
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
218
|
+
if (!Array.isArray(array)) return result;
|
|
219
|
+
const len = array.length;
|
|
220
|
+
for (let i = 0; i < len; i++) {
|
|
221
|
+
const item = array[i];
|
|
222
|
+
if (!predicate(item, i)) break;
|
|
223
|
+
result.push(item);
|
|
211
224
|
}
|
|
212
225
|
return result;
|
|
213
226
|
}
|
|
214
227
|
__name(takeWhile, "takeWhile");
|
|
215
228
|
function compact(array) {
|
|
216
229
|
if (!Array.isArray(array)) return [];
|
|
217
|
-
|
|
230
|
+
const result = [];
|
|
231
|
+
for (const v of array) {
|
|
232
|
+
if (v) result.push(v);
|
|
233
|
+
}
|
|
234
|
+
return result;
|
|
218
235
|
}
|
|
219
236
|
__name(compact, "compact");
|
|
220
237
|
function countBy(array, keyFn) {
|
|
221
238
|
if (!Array.isArray(array)) return {};
|
|
222
|
-
|
|
239
|
+
const result = {};
|
|
240
|
+
for (const item of array) {
|
|
223
241
|
const key = String(keyFn(item));
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
242
|
+
result[key] = (result[key] ?? 0) + 1;
|
|
243
|
+
}
|
|
244
|
+
return result;
|
|
227
245
|
}
|
|
228
246
|
__name(countBy, "countBy");
|
|
247
|
+
function toggle(array, item) {
|
|
248
|
+
if (!Array.isArray(array)) return [
|
|
249
|
+
item
|
|
250
|
+
];
|
|
251
|
+
const exists = array.includes(item);
|
|
252
|
+
if (exists) return array.filter((x) => x !== item);
|
|
253
|
+
return [
|
|
254
|
+
...array,
|
|
255
|
+
item
|
|
256
|
+
];
|
|
257
|
+
}
|
|
258
|
+
__name(toggle, "toggle");
|
|
259
|
+
function secureIndex(max) {
|
|
260
|
+
if (!Number.isInteger(max) || max <= 0) throw new RangeError("Max must be a positive integer");
|
|
261
|
+
const limit = 4294967295 - 4294967295 % max;
|
|
262
|
+
let rand;
|
|
263
|
+
do {
|
|
264
|
+
rand = crypto.randomBytes(4).readUInt32BE(0);
|
|
265
|
+
} while (rand >= limit);
|
|
266
|
+
return rand % max;
|
|
267
|
+
}
|
|
268
|
+
__name(secureIndex, "secureIndex");
|
|
269
|
+
var secureRandom = /* @__PURE__ */ __name((array) => {
|
|
270
|
+
if (!Array.isArray(array) || array.length === 0) return void 0;
|
|
271
|
+
const idx = secureIndex(array.length);
|
|
272
|
+
return array[idx];
|
|
273
|
+
}, "secureRandom");
|
|
274
|
+
function findLast(array, predicate) {
|
|
275
|
+
if (!Array.isArray(array)) return void 0;
|
|
276
|
+
for (let i = array.length - 1; i >= 0; i--) {
|
|
277
|
+
if (predicate(array[i], i, array)) return array[i];
|
|
278
|
+
}
|
|
279
|
+
return void 0;
|
|
280
|
+
}
|
|
281
|
+
__name(findLast, "findLast");
|
|
282
|
+
function findLastIndex(array, predicate) {
|
|
283
|
+
if (!Array.isArray(array)) return -1;
|
|
284
|
+
for (let i = array.length - 1; i >= 0; i--) {
|
|
285
|
+
if (predicate(array[i], i, array)) return i;
|
|
286
|
+
}
|
|
287
|
+
return -1;
|
|
288
|
+
}
|
|
289
|
+
__name(findLastIndex, "findLastIndex");
|
|
290
|
+
function chunkBy(array, predicate) {
|
|
291
|
+
if (!Array.isArray(array) || array.length === 0) return [];
|
|
292
|
+
const result = [];
|
|
293
|
+
let chunk2 = [];
|
|
294
|
+
for (let i = 0; i < array.length; i++) {
|
|
295
|
+
if (predicate(array[i], i, array) && chunk2.length) {
|
|
296
|
+
result.push(chunk2);
|
|
297
|
+
chunk2 = [];
|
|
298
|
+
}
|
|
299
|
+
chunk2.push(array[i]);
|
|
300
|
+
}
|
|
301
|
+
if (chunk2.length) result.push(chunk2);
|
|
302
|
+
return result;
|
|
303
|
+
}
|
|
304
|
+
__name(chunkBy, "chunkBy");
|
|
305
|
+
function remove(array, value) {
|
|
306
|
+
if (!Array.isArray(array)) return [];
|
|
307
|
+
return array.filter((item) => item !== value);
|
|
308
|
+
}
|
|
309
|
+
__name(remove, "remove");
|
|
310
|
+
function isSorted(array, direction = "asc", compareFn) {
|
|
311
|
+
if (!Array.isArray(array) || array.length <= 1) return true;
|
|
312
|
+
const cmp = compareFn || ((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
313
|
+
for (let i = 1; i < array.length; i++) {
|
|
314
|
+
const res = cmp(array[i - 1], array[i]);
|
|
315
|
+
if (direction === "asc" && res > 0 || direction === "desc" && res < 0) return false;
|
|
316
|
+
}
|
|
317
|
+
return true;
|
|
318
|
+
}
|
|
319
|
+
__name(isSorted, "isSorted");
|
|
320
|
+
function headOfArr(array) {
|
|
321
|
+
return Array.isArray(array) && array.length > 0 ? array[0] : void 0;
|
|
322
|
+
}
|
|
323
|
+
__name(headOfArr, "headOfArr");
|
|
324
|
+
function lastOfArr(array) {
|
|
325
|
+
return Array.isArray(array) && array.length > 0 ? array.at(-1) : void 0;
|
|
326
|
+
}
|
|
327
|
+
__name(lastOfArr, "lastOfArr");
|
|
328
|
+
function drop(array, n) {
|
|
329
|
+
if (!Array.isArray(array) || n <= 0) return [
|
|
330
|
+
...array
|
|
331
|
+
];
|
|
332
|
+
return array.slice(n);
|
|
333
|
+
}
|
|
334
|
+
__name(drop, "drop");
|
|
335
|
+
function dropWhile(array, predicate) {
|
|
336
|
+
if (!Array.isArray(array)) return [];
|
|
337
|
+
let i = 0;
|
|
338
|
+
while (i < array.length && predicate(array[i], i)) {
|
|
339
|
+
i++;
|
|
340
|
+
}
|
|
341
|
+
return array.slice(i);
|
|
342
|
+
}
|
|
343
|
+
__name(dropWhile, "dropWhile");
|
|
344
|
+
function maxBy(array, keyOrFn) {
|
|
345
|
+
if (!Array.isArray(array) || array.length === 0) return void 0;
|
|
346
|
+
const fn = typeof keyOrFn === "function" ? keyOrFn : (item) => item[keyOrFn];
|
|
347
|
+
return array.reduce((max, item) => fn(item) > fn(max) ? item : max, array[0]);
|
|
348
|
+
}
|
|
349
|
+
__name(maxBy, "maxBy");
|
|
350
|
+
function minBy(array, keyOrFn) {
|
|
351
|
+
if (!Array.isArray(array) || array.length === 0) return void 0;
|
|
352
|
+
const fn = typeof keyOrFn === "function" ? keyOrFn : (item) => item[keyOrFn];
|
|
353
|
+
return array.reduce((min, item) => fn(item) < fn(min) ? item : min, array[0]);
|
|
354
|
+
}
|
|
355
|
+
__name(minBy, "minBy");
|
|
229
356
|
|
|
230
357
|
exports.chunk = chunk;
|
|
358
|
+
exports.chunkBy = chunkBy;
|
|
231
359
|
exports.compact = compact;
|
|
232
360
|
exports.countBy = countBy;
|
|
233
361
|
exports.difference = difference;
|
|
362
|
+
exports.drop = drop;
|
|
363
|
+
exports.dropWhile = dropWhile;
|
|
364
|
+
exports.findLast = findLast;
|
|
365
|
+
exports.findLastIndex = findLastIndex;
|
|
234
366
|
exports.flattenDeep = flattenDeep;
|
|
235
367
|
exports.groupBy = groupBy;
|
|
368
|
+
exports.headOfArr = headOfArr;
|
|
236
369
|
exports.intersect = intersect;
|
|
370
|
+
exports.isSorted = isSorted;
|
|
371
|
+
exports.lastOfArr = lastOfArr;
|
|
372
|
+
exports.maxBy = maxBy;
|
|
237
373
|
exports.mergeSort = mergeSort;
|
|
374
|
+
exports.minBy = minBy;
|
|
238
375
|
exports.partition = partition;
|
|
239
376
|
exports.pluck = pluck;
|
|
240
377
|
exports.random = random;
|
|
241
378
|
exports.range = range;
|
|
379
|
+
exports.remove = remove;
|
|
380
|
+
exports.secureIndex = secureIndex;
|
|
381
|
+
exports.secureRandom = secureRandom;
|
|
242
382
|
exports.shuffle = shuffle;
|
|
243
383
|
exports.take = take;
|
|
244
384
|
exports.takeWhile = takeWhile;
|
|
385
|
+
exports.toggle = toggle;
|
|
245
386
|
exports.unique = unique;
|
|
246
387
|
exports.zip = zip;
|