@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.
Files changed (122) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +102 -52
  3. package/array/index.cjs +215 -74
  4. package/array/index.d.ts +345 -2
  5. package/array/index.mjs +201 -74
  6. package/async/index.cjs +116 -39
  7. package/async/index.d.ts +292 -2
  8. package/async/index.mjs +116 -40
  9. package/cache/index.cjs +2 -2
  10. package/cache/index.d.ts +156 -2
  11. package/cache/index.mjs +3 -3
  12. package/config/index.cjs +80 -66
  13. package/config/index.d.ts +65 -3
  14. package/config/index.mjs +77 -65
  15. package/context-store/index.cjs +2 -3
  16. package/context-store/index.d.ts +193 -2
  17. package/context-store/index.mjs +2 -3
  18. package/crypto/index.cjs +55 -5
  19. package/crypto/index.d.ts +225 -2
  20. package/crypto/index.mjs +52 -7
  21. package/date/index.cjs +676 -2
  22. package/date/index.d.ts +676 -2
  23. package/date/index.mjs +665 -3
  24. package/decorator/index.cjs +2172 -0
  25. package/{decorators/decorators.utils.d.ts → decorator/index.d.ts} +58 -54
  26. package/decorator/index.mjs +2131 -0
  27. package/{dir → directory}/index.cjs +5 -4
  28. package/{dir/dir.utils.d.ts → directory/index.d.ts} +24 -21
  29. package/{dir → directory}/index.mjs +5 -4
  30. package/env/index.cjs +100 -68
  31. package/env/index.d.ts +391 -2
  32. package/env/index.mjs +100 -68
  33. package/exception/index.cjs +1 -1
  34. package/exception/index.d.ts +233 -2
  35. package/exception/index.mjs +1 -1
  36. package/fs/index.cjs +71 -37
  37. package/fs/index.d.ts +206 -2
  38. package/fs/index.mjs +65 -35
  39. package/http-status-codes/index.cjs +1 -1
  40. package/http-status-codes/index.d.ts +268 -2
  41. package/http-status-codes/index.mjs +1 -1
  42. package/id/index.cjs +1 -1
  43. package/id/index.d.ts +38 -2
  44. package/id/index.mjs +1 -1
  45. package/index.cjs +13 -13
  46. package/index.d.ts +5 -5
  47. package/index.mjs +5 -5
  48. package/logger/index.cjs +13 -15
  49. package/logger/index.d.ts +190 -2
  50. package/logger/index.mjs +14 -16
  51. package/middleware/index.cjs +1 -1
  52. package/middleware/index.d.ts +104 -2
  53. package/middleware/index.mjs +1 -1
  54. package/object/index.cjs +379 -0
  55. package/{obj/obj.utils.d.ts → object/index.d.ts} +73 -33
  56. package/object/index.mjs +360 -0
  57. package/package.json +41 -23
  58. package/performance/index.cjs +4 -4
  59. package/performance/index.d.ts +139 -2
  60. package/performance/index.mjs +4 -4
  61. package/request/index.cjs +37 -25
  62. package/request/index.d.ts +242 -3
  63. package/request/index.mjs +37 -25
  64. package/response/index.cjs +1 -1
  65. package/response/index.d.ts +319 -3
  66. package/response/index.mjs +1 -1
  67. package/server/index.cjs +249 -146
  68. package/server/index.d.ts +866 -5
  69. package/server/index.mjs +248 -144
  70. package/stream/index.cjs +1 -1
  71. package/stream/index.d.ts +91 -2
  72. package/stream/index.mjs +1 -1
  73. package/string/index.cjs +34 -1
  74. package/string/index.d.ts +146 -2
  75. package/string/index.mjs +31 -2
  76. package/type/index.cjs +19 -2
  77. package/type/index.d.ts +144 -2
  78. package/type/index.mjs +17 -3
  79. package/types/index.cjs +1 -1
  80. package/types/index.d.ts +775 -5
  81. package/types/index.mjs +1 -1
  82. package/url/index.cjs +63 -5
  83. package/url/index.d.ts +200 -2
  84. package/url/index.mjs +59 -6
  85. package/{validate → validation}/index.cjs +91 -44
  86. package/{validate/validate.utils.d.ts → validation/index.d.ts} +33 -24
  87. package/{validate → validation}/index.mjs +87 -44
  88. package/array/array.utils.d.ts +0 -191
  89. package/async/async.utils.d.ts +0 -296
  90. package/cache/cache.utils.d.ts +0 -176
  91. package/config/config.d.ts +0 -57
  92. package/context-store/context-store.utils.d.ts +0 -212
  93. package/crypto/crypto.utils.d.ts +0 -183
  94. package/date/date.utils.d.ts +0 -190
  95. package/decorators/index.cjs +0 -913
  96. package/decorators/index.d.ts +0 -25
  97. package/decorators/index.mjs +0 -872
  98. package/dir/index.d.ts +0 -25
  99. package/env/env.utils.d.ts +0 -400
  100. package/exception/exception.utils.d.ts +0 -253
  101. package/fs/fs.utils.d.ts +0 -196
  102. package/http-status-codes/http-status-codes.d.ts +0 -289
  103. package/id/id.utils.d.ts +0 -59
  104. package/logger/logger.utils.d.ts +0 -210
  105. package/middleware/middleware.utils.d.ts +0 -123
  106. package/obj/index.cjs +0 -317
  107. package/obj/index.d.ts +0 -25
  108. package/obj/index.mjs +0 -301
  109. package/performance/performance.utils.d.ts +0 -159
  110. package/request/request.utils.d.ts +0 -109
  111. package/response/response.utils.d.ts +0 -186
  112. package/server/server.builder.d.ts +0 -531
  113. package/server/server.d.ts +0 -303
  114. package/stream/stream.utils.d.ts +0 -111
  115. package/string/string.utils.d.ts +0 -124
  116. package/type/type.utils.d.ts +0 -129
  117. package/types/api-response.d.ts +0 -175
  118. package/types/common.d.ts +0 -148
  119. package/types/config.d.ts +0 -88
  120. package/types/server.d.ts +0 -291
  121. package/url/url.utils.d.ts +0 -164
  122. package/validate/index.d.ts +0 -25
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License
2
2
 
3
- Copyright (c) 2025 Catbee Technologies. https://catbee.in/license
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/2025" alt="Maintenance" />
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 { chunk, sleep, getLogger, uuid, isEmail } from "@catbee/utils";
57
-
58
- // Chunk an array
59
- const result = chunk([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]
60
-
61
- // Sleep for 1 second
62
- await sleep(1000);
63
-
64
- // Log with context
65
- getLogger().info("App started");
66
-
67
- // Generate a secure UUID
68
- console.log(uuid()); // e.g. 2a563ec1-caf6-4fe2-b60c-9cf7fb1bdb7f
69
-
70
- // Basic validation
71
- console.log(isEmail("user@example.com")); // true
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 | Description |
79
- | ------ | ----------- |
80
- | [Express Server](https://catbee.in/docs/@catbee/utils/express-server) | Fast, secure, and scalable server setup |
81
- | [Array Utilities](https://catbee.in/docs/@catbee/utils/modules/array) | Advanced array manipulation |
82
- | [Async Utilities](https://catbee.in/docs/@catbee/utils/modules/async) | Promise helpers, concurrency, timing |
83
- | [Cache Utilities](https://catbee.in/docs/@catbee/utils/modules/cache) | In-memory caching with TTL |
84
- | [Context Store](https://catbee.in/docs/@catbee/utils/modules/context-store) | Per-request context via AsyncLocalStorage |
85
- | [Crypto Utilities](https://catbee.in/docs/@catbee/utils/modules/crypto) | Hashing, encryption, tokens |
86
- | [Date Utilities](https://catbee.in/docs/@catbee/utils/modules/date) | Date/time manipulation |
87
- | [Decorators Utilities](https://catbee.in/docs/@catbee/utils/modules/decorators) | TypeScript decorators for Express |
88
- | [Directory Utilities](https://catbee.in/docs/@catbee/utils/modules/directory) | Directory and file system helpers |
89
- | [Environment Utilities](https://catbee.in/docs/@catbee/utils/modules/environment) | Env variable management |
90
- | [Exception Utilities](https://catbee.in/docs/@catbee/utils/modules/exception) | HTTP and error handling |
91
- | [File System Utilities](https://catbee.in/docs/@catbee/utils/modules/file-system) | File operations |
92
- | [HTTP Status Codes](https://catbee.in/docs/@catbee/utils/modules/http-status-codes) | Typed status codes |
93
- | [ID Utilities](https://catbee.in/docs/@catbee/utils/modules/id) | UUID and ID generation |
94
- | [Logger Utilities](https://catbee.in/docs/@catbee/utils/modules/logger) | Structured logging with Pino |
95
- | [Middleware Utilities](https://catbee.in/docs/@catbee/utils/modules/middleware) | Express middleware collection |
96
- | [Object Utilities](https://catbee.in/docs/@catbee/utils/modules/object) | Deep merge, flatten, pick/omit, etc. |
97
- | [Performance Utilities](https://catbee.in/docs/@catbee/utils/modules/performance) | Timing, memoization, memory tracking |
98
- | [Request Utilities](https://catbee.in/docs/@catbee/utils/modules/request) | HTTP request parameter parsing/validation |
99
- | [Response Utilities](https://catbee.in/docs/@catbee/utils/modules/response) | Standardized API response formatting |
100
- | [Stream Utilities](https://catbee.in/docs/@catbee/utils/modules/stream) | Stream conversion, batching, throttling, line splitting |
101
- | [String Utilities](https://catbee.in/docs/@catbee/utils/modules/string) | Casing, masking, slugifying, formatting |
102
- | [Type Utilities](https://catbee.in/docs/@catbee/utils/modules/type) | Type checking, conversion, guards |
103
- | [URL Utilities](https://catbee.in/docs/@catbee/utils/modules/url) | URL parsing, query manipulation, normalization |
104
- | [Validate Utilities](https://catbee.in/docs/@catbee/utils/modules/validation) | Input validation functions |
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
- Import only what you need:
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 "@catbee/utils";
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) 2025 Catbee Technologies. https://catbee.in/license
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 obj = require('@catbee/utils/obj');
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
- return array.filter((item) => {
47
+ const result = [];
48
+ for (const item of array) {
47
49
  const key = keyFn(item);
48
- if (seen.has(key)) return false;
49
- seen.add(key);
50
- return true;
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
- for (const val of array) {
61
+ const stack = [
62
+ ...array
63
+ ];
64
+ while (stack.length) {
65
+ const val = stack.pop();
58
66
  if (Array.isArray(val)) {
59
- result.push(...flattenDeep(val));
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
- const idx = Math.floor(Math.random() * array.length);
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[keyOrFn];
76
- return array.reduce((acc, item) => {
77
- const key = keyFn(item);
78
- if (!acc[key]) acc[key] = [];
79
- acc[key].push(item);
80
- return acc;
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 = Math.floor(Math.random() * (i + 1));
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
- if (array.length <= 1) return array.slice();
117
- const keyFn = typeof key === "function" ? key : (item) => obj.getValueByPath(item, key);
118
- const compare = /* @__PURE__ */ __name((a, b) => {
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 < bVal ? -1 : 1 : aVal > bVal ? -1 : 1;
125
- }, "compare");
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
- if (compare(left[i], right[j]) <= 0) result.push(left[i++]);
131
- else result.push(right[j++]);
150
+ result.push(compare(left[i], right[j]) <= 0 ? left[i++] : right[j++]);
132
151
  }
133
- return result.concat(left.slice(i)).concat(right.slice(j));
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((arr) => {
136
- if (arr.length <= 1) return arr;
137
- const mid = Math.floor(arr.length / 2);
138
- const left = sort(arr.slice(0, mid));
139
- const right = sort(arr.slice(mid));
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(array);
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 isAscending = step > 0;
189
- if (isAscending && start >= end || !isAscending && start <= end) {
190
- return [];
191
- }
192
- const length = Math.max(Math.ceil((end - start) / step), 0);
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
- for (let i = 0; i < array.length; i++) {
209
- if (!predicate(array[i], i)) break;
210
- result.push(array[i]);
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
- return array.filter(Boolean);
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
- return array.reduce((acc, item) => {
239
+ const result = {};
240
+ for (const item of array) {
223
241
  const key = String(keyFn(item));
224
- acc[key] = (acc[key] || 0) + 1;
225
- return acc;
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;