@rtorcato/js-common 4.0.0 → 6.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 (78) hide show
  1. package/AGENTS.md +21 -20
  2. package/README.md +42 -32
  3. package/dist/abortController/index.d.ts +3 -2
  4. package/dist/abortController/index.d.ts.map +1 -1
  5. package/dist/abortController/index.js +1 -1
  6. package/dist/arrays/arrays.test-d.js +1 -1
  7. package/dist/arrays/index.d.ts +52 -0
  8. package/dist/arrays/index.d.ts.map +1 -1
  9. package/dist/arrays/index.js +1 -1
  10. package/dist/chunks/chunk-6FGK7LS2.js +1 -0
  11. package/dist/chunks/chunk-NEODDZIS.js +1 -0
  12. package/dist/chunks/chunk-U2F5TMN2.js +1 -0
  13. package/dist/chunks/chunk-VSTXGIC3.js +1 -0
  14. package/dist/cli/index.mjs +7 -10
  15. package/dist/crypto/index.d.ts +15 -10
  16. package/dist/crypto/index.d.ts.map +1 -1
  17. package/dist/crypto/index.js +1 -1
  18. package/dist/currency/currencies.d.ts.map +1 -1
  19. package/dist/currency/index.d.ts.map +1 -1
  20. package/dist/date/index.d.ts +22 -2
  21. package/dist/date/index.d.ts.map +1 -1
  22. package/dist/date/index.js +1 -1
  23. package/dist/env/index.d.ts +1 -1
  24. package/dist/env/index.d.ts.map +1 -1
  25. package/dist/env/index.js +3 -1
  26. package/dist/fetch/index.d.ts +6 -3
  27. package/dist/fetch/index.d.ts.map +1 -1
  28. package/dist/fetch/index.js +1 -1
  29. package/dist/logger/index.d.ts.map +1 -1
  30. package/dist/logger/index.js +1 -1
  31. package/dist/mime-types/db.d.ts +1839 -1839
  32. package/dist/mime-types/db.d.ts.map +1 -1
  33. package/dist/mime-types/index.d.ts +1 -1
  34. package/dist/node/index.d.ts.map +1 -1
  35. package/dist/numbers/index.d.ts +96 -3
  36. package/dist/numbers/index.d.ts.map +1 -1
  37. package/dist/numbers/index.js +1 -1
  38. package/dist/os/index.d.ts +0 -11
  39. package/dist/os/index.d.ts.map +1 -1
  40. package/dist/os/index.js +1 -1
  41. package/dist/promises/index.d.ts +51 -0
  42. package/dist/promises/index.d.ts.map +1 -1
  43. package/dist/promises/index.js +1 -1
  44. package/dist/promises/promises.test-d.js +1 -1
  45. package/dist/regex/index.d.ts +7 -0
  46. package/dist/regex/index.d.ts.map +1 -1
  47. package/dist/regex/index.js +1 -1
  48. package/dist/security/index.d.ts +0 -13
  49. package/dist/security/index.d.ts.map +1 -1
  50. package/dist/security/index.js +1 -1
  51. package/dist/sleep/index.d.ts +3 -2
  52. package/dist/sleep/index.d.ts.map +1 -1
  53. package/dist/sleep/index.js +1 -1
  54. package/dist/strings/index.d.ts +3 -2
  55. package/dist/strings/index.d.ts.map +1 -1
  56. package/dist/strings/index.js +1 -1
  57. package/dist/system/index.d.ts +22 -3
  58. package/dist/system/index.d.ts.map +1 -1
  59. package/dist/system/index.js +1 -1
  60. package/dist/try/index.d.ts +12 -0
  61. package/dist/try/index.d.ts.map +1 -1
  62. package/dist/try/index.js +1 -1
  63. package/dist/try/trycatch.test-d.js +1 -1
  64. package/dist/url/index.d.ts.map +1 -1
  65. package/dist/url/index.js +1 -1
  66. package/dist/uuid/index.d.ts.map +1 -1
  67. package/dist/validation/index.d.ts +0 -12
  68. package/dist/validation/index.d.ts.map +1 -1
  69. package/dist/validation/index.js +1 -1
  70. package/package.json +77 -44
  71. package/CHANGELOG.md +0 -258
  72. package/dist/chunks/chunk-AVPQVYSA.js +0 -1
  73. package/dist/chunks/chunk-FBDKWWIQ.js +0 -3
  74. package/dist/chunks/chunk-J4C2KNK5.js +0 -1
  75. package/dist/chunks/chunk-UQBVI52L.js +0 -1
  76. package/dist/index.d.ts +0 -2
  77. package/dist/index.d.ts.map +0 -1
  78. package/dist/index.js +0 -0
package/AGENTS.md CHANGED
@@ -2,16 +2,16 @@
2
2
 
3
3
  # Using @rtorcato/js-common
4
4
 
5
- `@rtorcato/js-common` is a tree-shakeable, ESM-only utility library for Node.js >= 22 (TypeScript-first, JSDoc on every public API). One subpath export per concern — 44 of them. The package root is intentionally empty.
5
+ `@rtorcato/js-common` is a tree-shakeable, ESM-only utility library for Node.js >= 24 (TypeScript-first, JSDoc on every public API). One subpath export per concern — 42 of them. There is no package root export.
6
6
 
7
7
  ## Rules
8
8
 
9
- 1. **Import from the subpath, never the package root.** The root export has no runtime code at all, so a root import gets you nothing.
9
+ 1. **Import from the subpath, never the package root.** The root has no `exports` entry at all, so a root import fails at resolve time (`ERR_PACKAGE_PATH_NOT_EXPORTED`) instead of silently binding nothing.
10
10
 
11
11
  ```ts
12
12
  // ✅ do
13
13
  import { slugify } from '@rtorcato/js-common/strings'
14
- // ❌ don't — the root export is empty by design
14
+ // ❌ don't — there is no root export; this throws at resolve time
15
15
  import { slugify } from '@rtorcato/js-common'
16
16
  ```
17
17
 
@@ -19,12 +19,12 @@
19
19
 
20
20
  | Looks like | Actually |
21
21
  |---|---|
22
- | `functions.once` vs `events.onceEvent` | `once(fn)` memoises a call; `onceEvent(target, type)` awaits a DOM event |
22
+ | `functions.once` vs `events.onceEvent` | `once(fn)` memoises a call; `onceEvent(target, type)` awaits an `EventTarget` event |
23
23
  | `logger` vs `logging` | `logger` is one configured pino instance; `logging` is `console` helpers with no runtime deps |
24
24
  | `try.tryCatch` vs `errors.tryWithFallback` | Result object vs swallow-and-fall-back — see rule 3 |
25
25
  | `date.formatDate` vs `datetime.formatDateTimeLocal` | a UTC calendar day vs a local instant |
26
26
 
27
- Where two modules used to ship the same name, the loser was deleted rather than aliased — [MODULE-BOUNDARIES.md](https://github.com/rtorcato/js-common/blob/main/MODULE-BOUNDARIES.md) records which side won and why.
27
+ Where two modules used to ship the same name, the loser was deleted — use `emails.isValidEmail`, `url.isValidUrl` and `process.getProcessPlatform` (not `validation.isEmail`, `validation.isUrl` or `os.getOsPlatform`). [MODULE-BOUNDARIES.md](https://github.com/rtorcato/js-common/blob/main/MODULE-BOUNDARIES.md) records which side won and why.
28
28
 
29
29
  3. **Three different error idioms — don't mix them up.**
30
30
 
@@ -44,7 +44,7 @@
44
44
 
45
45
  `tryCatch` in `errors` was renamed to `tryWithFallback` in 2.0; `tryCatch` now means the Result helper in `try`.
46
46
 
47
- 4. **Node-only modules.** `crypto`, `security`, and `file` import `node:crypto` / `node:fs`; `logger` uses pino. Don't ship these to a browser bundle. `events` is the opposite — it wraps DOM `EventTarget` and is browser-only. `os`, `process`, `node`, and `system` probe for `process` / `window` and degrade rather than throw.
47
+ 4. **Node-only modules.** `file` imports `node:fs`; `logger` uses pino. `crypto` is Web Crypto (`globalThis.crypto`), so it runs anywhere — `hashString` and `hmacHash` return promises. Don't ship `file` or `logger` to a browser bundle. `events` wraps `EventTarget` / `CustomEvent`, which are globals in browsers and Node ≥ 22, so it runs in both. `os`, `process`, `node`, `system`, and `i18n` probe for `process` / `window` / `navigator` and degrade rather than throw. `console` and `env` read `process` unguarded, so a browser bundle needs the bundler to define it. Everything else runs anywhere. `src/runtime-boundaries.test.ts` enforces this paragraph and the `Runtime:` line on each docs module page.
48
48
 
49
49
  5. **`./types` is types-only.** It has a `types` field and no `import` field on purpose — use it for `import type { Prettify, Merge } from '@rtorcato/js-common/types'` only.
50
50
 
@@ -57,13 +57,13 @@ Import from `@rtorcato/js-common/<module>`.
57
57
  | Module | Exports |
58
58
  |---|---|
59
59
  | abortController | createAbortController, abortPromise, withAbort, abortAfter |
60
- | arrays | unique, chunk, compact, shuffle |
60
+ | arrays | unique, chunk, compact, shuffle, partition, sortBy, zip |
61
61
  | boolean | toBoolean |
62
62
  | colors | randomColor, matchingTextColor, hexToRgb, rgbToHex, isValidHex, darken, lighten |
63
63
  | console | disableConsole, clearConsole |
64
64
  | crypto | hashString, randomHex, hmacHash, base64Encode, base64Decode |
65
65
  | currency | getCurrencySymbol, getCurrencyName, getCurrencyLocale, formatPrice, formatPriceCompact, parsePrice, parseCurrencyString, convertCurrency, isValidCurrencyCode, isValidCurrency |
66
- | date | today, parseDate, formatDate, daysBetween, diffInHours, diffInMinutes, isLeapYear, addDays, subDays, addMonths, getDayOfWeek, startOfDay, endOfDay, isWeekend, isSameDay, isToday, formatRelative |
66
+ | date | today, parseDate, formatDate, daysBetween, diffInHours, diffInMinutes, isLeapYear, addDays, subDays, addMonths, getDayOfWeek, startOfDay, endOfDay, isWeekend, isWeekday, isSameDay, isToday, formatRelative |
67
67
  | datetime | nowIso, parseIsoDateTime, formatDateTimeLocal, getTimezoneOffset, toUtcDate, unixTimestamp, unixMillis, getIsoWeek, getIsoWeekInfo |
68
68
  | emails | isValidEmail, normalizeEmail, maskEmail, getEmailDomain, isFreeEmailProvider |
69
69
  | env | getENV, isDev, isProd, isTest, getNodeEnv, checkEnv, RootApiEnvSchema |
@@ -79,36 +79,37 @@ Import from `@rtorcato/js-common/<module>`.
79
79
  | logger | logger (pino instance — pretty in dev, JSON in prod) |
80
80
  | logging | logWithTimestamp, info, warn, error, captureConsole, ConsoleLevel |
81
81
  | maps | invertMap, mapValues, mergeMaps, objectToMap, mapToObject |
82
- | mime-types | lookup, types, extensions, mimeTypes |
82
+ | mime-types | lookup, types, extensions, mimeTypes, FileExtension, MimeType, MimeValue |
83
83
  | node | nodeVersionCheck, getNodeMajorVersion, isNode, requireOptional |
84
- | numbers | clamp, roundTo, formatPercent, between, sum, average, mod |
84
+ | numbers | clamp, roundTo, formatPercent, FormatPercentOptions, between, sum, average, mod, variance, stdDev, median, percentile |
85
85
  | objects | isPlainObject, deepMerge, omit, pick |
86
- | os | getOsPlatform, getOsRelease, getOsArch, getHomeDir, getTmpDir |
86
+ | os | getOsRelease, getOsArch, getHomeDir, getTmpDir |
87
87
  | process | getProcessId, getProcessUptime, getCwd, getProcessPlatform, exitProcess, isCI |
88
- | promises | to, withTimeout |
88
+ | promises | to, withTimeout, mapLimit, retry, RetryOptions |
89
89
  | random | randomInt, randomFloat, randomBool, randomElement, randomString |
90
90
  | regex | escapeRegExp, testRegex, matchAll, replaceAllRegex, splitByRegex |
91
- | security | stripScriptish, isStrongPassword, generateSecureToken |
91
+ | security | stripScriptish, isStrongPassword |
92
92
  | sleep | sleep, sleepSync, sleepRandom, sleepWithAbort |
93
93
  | strings | titleCase, capitalize, camelCase, kebabCase, snakeCase, truncate, reverse, slugify, words, wordCount, pluralize, ordinalize, isBlank, mask, template |
94
94
  | system | isMacOs, isWindows, isLinux, isIOS, isAndroid, getPlatform, isTouchDevice |
95
95
  | time | nowTime, nowTimeShort, parseTime, formatTime, secondsBetween, pad2 |
96
- | try | tryCatch, isSuccess, Result, Success, Failure |
96
+ | try | tryCatch, tryCatchSync, isSuccess, Result, Success, Failure |
97
97
  | types | Prettify, Merge (types only) |
98
98
  | url | isValidUrl, getQueryParams, setQueryParam, removeQueryParam, joinUrl, getHostname |
99
99
  | uuid | getUUIDv7, getShortUUID, toShortUUID, fromShortUUID, isUUID, isUUIDv4, isNilUUID, getUUIDVersion, getNilUUID, uuidToBytes, bytesToUUID |
100
- | validation | isDefined, isString, isNumber, isBoolean, isArray, isObject, isEmail, isUrl |
100
+ | validation | isDefined, isString, isNumber, isBoolean, isArray, isObject |
101
101
 
102
102
  ## CLI
103
103
 
104
- The package also ships a binary for shell use:
104
+ The package also ships a binary for shell use. Its UI packages are optional peers, so install them first
105
+ (`npm install -g @rtorcato/js-common @inquirer/prompts chalk chalk-animation commander figlet gradient-string`):
105
106
 
106
107
  ```bash
107
- npx @rtorcato/js-common@latest date today
108
- npx @rtorcato/js-common@latest math sum 1 2 3
109
- npx @rtorcato/js-common@latest text capitalize "hello world"
108
+ js-common date today
109
+ js-common math sum 1 2 3
110
+ js-common text capitalize "hello world"
110
111
  ```
111
112
 
112
113
  See [CLI.md](https://github.com/rtorcato/js-common/blob/main/CLI.md) for the full command list.
113
114
 
114
- For full signatures and examples, see <https://rtorcato.github.io/js-common/>.
115
+ For full signatures and examples, see <https://docs.torcato.dev/js-common/>.
package/README.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # js-common
2
2
 
3
- <p align="center">
4
- <picture>
5
- <source media="(max-width: 600px)" srcset="./brand/banner-mobile.png">
6
- <img src="./brand/banner.png" alt="js-common — Tree-shakeable TypeScript utilities: tiny bundles, full type safety, CLI included." width="100%">
7
- </picture>
8
- </p>
3
+ <!-- brand-kit:banner:start -->
4
+ <picture>
5
+ <source media="(max-width: 640px)" srcset="./brand/banner-mobile.png">
6
+ <img src="./brand/banner.png" alt="js-common banner" width="1600">
7
+ </picture>
8
+ <!-- brand-kit:banner:end -->
9
9
 
10
10
  [![CI](https://github.com/rtorcato/js-common/actions/workflows/ci.yml/badge.svg)](https://github.com/rtorcato/js-common/actions/workflows/ci.yml)
11
11
  [![npm version](https://badge.fury.io/js/%40rtorcato%2Fjs-common.svg)](https://badge.fury.io/js/%40rtorcato%2Fjs-common)
@@ -13,13 +13,14 @@
13
13
  [![Bundle size](https://img.shields.io/bundlephobia/minzip/@rtorcato/js-common)](https://bundlephobia.com/package/@rtorcato/js-common)
14
14
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
15
15
  [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
16
- [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D22.0.0-brightgreen.svg)](https://nodejs.org/)
17
- [![codecov](https://codecov.io/gh/rtorcato/js-common/branch/main/graph/badge.svg)](https://codecov.io/gh/rtorcato/js-common)
18
- [![Docs](https://img.shields.io/badge/docs-rtorcato.github.io%2Fjs--common-blue.svg)](https://rtorcato.github.io/js-common/)
16
+ [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D24.0.0-brightgreen.svg)](https://nodejs.org/)
17
+ [![Docs](https://img.shields.io/badge/docs-docs.torcato.dev%2Fjs--common-blue.svg)](https://docs.torcato.dev/js-common/)
19
18
 
20
19
  A comprehensive set of common JavaScript and TypeScript utilities for Node.js projects.
21
20
 
22
- 📘 **Documentation:** <https://rtorcato.github.io/js-common/>
21
+ > **Browser APIs live in [`@rtorcato/browser-common`](https://github.com/rtorcato/browser-common).** js-common covers runtime-agnostic JavaScript and Node.js. Wrappers around browser Web APIs, such as clipboard, storage, observers, geolocation, the DOM and user-agent detection, belong to browser-common. The two packages don't overlap.
22
+
23
+ 📘 **Documentation:** <https://docs.torcato.dev/js-common/>
23
24
 
24
25
  ## Features
25
26
 
@@ -27,7 +28,7 @@ A comprehensive set of common JavaScript and TypeScript utilities for Node.js pr
27
28
  - **TypeScript** — full type definitions, JSDoc on every public API
28
29
  - **CLI included** — optional binary for use in scripts and terminals
29
30
  - **Modular** — one module per concern, 42 subpaths
30
- - **Minimal runtime deps** — only `pino`, `uuid`, `short-uuid`, `zod`. CLI packages (`chalk`, `commander`, `figlet`, …) are `optionalDependencies` and only needed for the CLI.
31
+ - **No required runtime deps** — `zod` (`./env`), `pino` (`./logger`, plus `pino-pretty` for pretty dev logs) and `uuid` + `short-uuid` (`./uuid`) are optional peers: install one only if you import its module. The CLI packages (`chalk`, `commander`, `figlet`, …) are optional peers too, needed only to run the `js-common` binary — see [CLI.md](CLI.md).
31
32
 
32
33
  ## Installation
33
34
 
@@ -35,6 +36,14 @@ A comprehensive set of common JavaScript and TypeScript utilities for Node.js pr
35
36
  npm install @rtorcato/js-common
36
37
  ```
37
38
 
39
+ Three modules need an optional peer you install yourself:
40
+
41
+ | Module | Peer |
42
+ |---|---|
43
+ | `./env` | `npm install zod` |
44
+ | `./logger` | `npm install pino` (add `pino-pretty` for pretty dev logs) |
45
+ | `./uuid` | `npm install uuid short-uuid` |
46
+
38
47
  Pre-release builds are published to the `beta` dist-tag, so they never reach a plain `npm install`:
39
48
 
40
49
  ```bash
@@ -64,9 +73,13 @@ npx skills add https://github.com/rtorcato/js-common --skill js-common
64
73
 
65
74
  ## Migrating
66
75
 
67
- **3.x → 4.x** — everything the runtime already does was removed. `./sets` and `./interval` are gone as modules, and the pass-through wrappers inside surviving modules went with them: `promises.all`/`allSettled`/`race`/`delay`, `boolean.and`/`or`/`not`/`xor`, `strings.padStart`/`padEnd`/`replaceString`, `arrays.first`/`last`/`flatten`/`groupBy`, `numbers.isInteger`/`isFiniteNumber`/`min`/`max`, `objects.deepClone`, `json.deepCloneJson` and `uuid.getUUID`. Nothing moved to another module — the replacement is a JavaScript built-in in every case, which the Node 22 floor guarantees. Two are **not** drop-ins: `Object.groupBy` returns a null-prototype object with optional values, and `structuredClone` keeps `Date`s where the JSON round trip flattened them. The full before/after table is in the [migration guide](https://rtorcato.github.io/js-common/docs/guides/migration).
76
+ **5.x → 6.x** — the Node floor is now 24 (`engines.node >=24`). The CLI packages (`@inquirer/prompts`, `chalk`, `chalk-animation`, `commander`, `figlet`, `gradient-string`) and `pino-pretty` moved from `optionalDependencies` to optional `peerDependencies`, so a plain install no longer downloads them. To run the CLI, install them alongside the package; for pretty `./logger` output in dev, add `pino-pretty`. Details in the [migration guide](https://docs.torcato.dev/js-common/docs/guides/migration).
77
+
78
+ **4.x → 5.x** — `zod`, `pino`, `uuid` and `short-uuid` moved from `dependencies` to optional `peerDependencies`. If you import `./env`, add `zod`; `./logger`, add `pino`; `./uuid`, add `uuid` and `short-uuid`. Every other module is unaffected. Details in the [migration guide](https://docs.torcato.dev/js-common/docs/guides/migration).
68
79
 
69
- **2.x → 3.x** — every helper now has exactly one home. `./formatting` and `./math` are gone, and where two modules shipped the same name the loser was deleted rather than aliased, so you get a build error naming the fix. One helper was also renamed rather than moved: `sanitizeString` is now `stripScriptish`, because the old name promised sanitising it never did — it removes `<script>` blocks and inline `on*` handlers and nothing else. The full before/after map is in the [migration guide](https://rtorcato.github.io/js-common/docs/guides/migration); the reasoning is in [MODULE-BOUNDARIES.md](MODULE-BOUNDARIES.md).
80
+ **3.x → 4.x** — everything the runtime already does was removed. `./sets` and `./interval` are gone as modules, and the pass-through wrappers inside surviving modules went with them: `promises.all`/`allSettled`/`race`/`delay`, `boolean.and`/`or`/`not`/`xor`, `strings.padStart`/`padEnd`/`replaceString`, `arrays.first`/`last`/`flatten`/`groupBy`, `numbers.isInteger`/`isFiniteNumber`/`min`/`max`, `objects.deepClone`, `json.deepCloneJson` and `uuid.getUUID`. Nothing moved to another module — the replacement is a JavaScript built-in in every case, which the Node 22 floor guarantees. Two are **not** drop-ins: `Object.groupBy` returns a null-prototype object with optional values, and `structuredClone` keeps `Date`s where the JSON round trip flattened them. The full before/after table is in the [migration guide](https://docs.torcato.dev/js-common/docs/guides/migration).
81
+
82
+ **2.x → 3.x** — every helper now has exactly one home. `./formatting` and `./math` are gone, and where two modules shipped the same name the loser was deleted rather than aliased, so you get a build error naming the fix. One helper was also renamed rather than moved: `sanitizeString` is now `stripScriptish`, because the old name promised sanitising it never did — it removes `<script>` blocks and inline `on*` handlers and nothing else. The full before/after map is in the [migration guide](https://docs.torcato.dev/js-common/docs/guides/migration); the reasoning is in [MODULE-BOUNDARIES.md](MODULE-BOUNDARIES.md).
70
83
 
71
84
  **1.x → 2.x** — the only breaking change in 2.0 is a rename in the `errors` module:
72
85
 
@@ -93,20 +106,18 @@ Prefer the Result-style `tryCatch` for new code; reserve `tryWithFallback` for c
93
106
 
94
107
  ## CLI Usage
95
108
 
96
- This package includes a command-line interface for many utilities:
109
+ This package includes a command-line interface for many utilities. Its UI packages are optional peers, so install them alongside it:
97
110
 
98
111
  ```bash
99
112
  # Install globally to use the CLI
100
- npm install -g @rtorcato/js-common
101
-
102
- # Or use with npx
103
- npx @rtorcato/js-common@latest --help
113
+ npm install -g @rtorcato/js-common @inquirer/prompts chalk chalk-animation commander figlet gradient-string
114
+ js-common --help
104
115
 
105
116
  # Examples
106
- npx @rtorcato/js-common@latest date today
107
- npx @rtorcato/js-common@latest math sum 1 2 3 4 5
108
- npx @rtorcato/js-common@latest text capitalize "hello world"
109
- npx @rtorcato/js-common@latest system node-version
117
+ js-common date today
118
+ js-common math sum 1 2 3 4 5
119
+ js-common text capitalize "hello world"
120
+ js-common system node-version
110
121
  ```
111
122
 
112
123
  See [CLI.md](./CLI.md) for complete CLI documentation.
@@ -148,6 +159,7 @@ import { nowTime, parseTime, secondsBetween } from '@rtorcato/js-common/time'
148
159
  ### Numbers
149
160
  ```typescript
150
161
  import { sum, average, roundTo, clamp, formatPercent } from '@rtorcato/js-common/numbers'
162
+ import { variance, stdDev, median, percentile } from '@rtorcato/js-common/numbers' // dispersion
151
163
  import { randomInt, randomFloat, randomBool, randomElement } from '@rtorcato/js-common/random'
152
164
  ```
153
165
 
@@ -161,7 +173,8 @@ import { detectLanguage, formatNumber, formatDateI18n, t } from '@rtorcato/js-co
161
173
 
162
174
  ### Security & Validation
163
175
  ```typescript
164
- import { isStrongPassword, generateSecureToken } from '@rtorcato/js-common/security'
176
+ import { isStrongPassword, stripScriptish } from '@rtorcato/js-common/security'
177
+ import { randomHex, hashString, hmacHash } from '@rtorcato/js-common/crypto'
165
178
  import { isValidEmail, maskEmail } from '@rtorcato/js-common/emails'
166
179
  import { isValidUrl } from '@rtorcato/js-common/url'
167
180
  import { isString, isNumber, isBoolean, isArray, isObject } from '@rtorcato/js-common/validation'
@@ -170,7 +183,7 @@ import { toBoolean } from '@rtorcato/js-common/boolean'
170
183
 
171
184
  ### Data Structures
172
185
  ```typescript
173
- import { unique, chunk, compact, shuffle } from '@rtorcato/js-common/arrays'
186
+ import { unique, chunk, compact, shuffle, partition, sortBy, zip } from '@rtorcato/js-common/arrays'
174
187
  import { deepMerge, pick, omit, isPlainObject } from '@rtorcato/js-common/objects'
175
188
  import { safeJsonParse, safeJsonStringify } from '@rtorcato/js-common/json'
176
189
  import { invertMap, mapValues, objectToMap, mapToObject } from '@rtorcato/js-common/maps'
@@ -178,7 +191,7 @@ import { invertMap, mapValues, objectToMap, mapToObject } from '@rtorcato/js-com
178
191
 
179
192
  ### Async & Control Flow
180
193
  ```typescript
181
- import { to, withTimeout } from '@rtorcato/js-common/promises'
194
+ import { retry, to, withTimeout } from '@rtorcato/js-common/promises'
182
195
  import { debounce, throttle, once } from '@rtorcato/js-common/functions'
183
196
  import { sleep } from '@rtorcato/js-common/sleep'
184
197
  import { tryCatch } from '@rtorcato/js-common/try'
@@ -189,9 +202,9 @@ import { createCustomError, getErrorMessage, assert } from '@rtorcato/js-common/
189
202
  ### System & Process
190
203
  ```typescript
191
204
  import { getENV, isDev, isProd, getNodeEnv, checkEnv } from '@rtorcato/js-common/env'
192
- import { getOsPlatform, getOsArch, getHomeDir } from '@rtorcato/js-common/os'
205
+ import { getOsArch, getOsRelease, getHomeDir } from '@rtorcato/js-common/os'
193
206
  import { getNodeMajorVersion, isNode, requireOptional } from '@rtorcato/js-common/node'
194
- import { getProcessId, getCwd, exitProcess, isCI } from '@rtorcato/js-common/process'
207
+ import { getProcessPlatform, getCwd, exitProcess, isCI } from '@rtorcato/js-common/process'
195
208
  import { isMacOs, isWindows, isLinux, getPlatform } from '@rtorcato/js-common/system'
196
209
  import { disableConsole, clearConsole } from '@rtorcato/js-common/console'
197
210
  ```
@@ -216,7 +229,7 @@ import { info, warn, error, captureConsole } from '@rtorcato/js-common/logging'
216
229
 
217
230
  ## Requirements
218
231
 
219
- - **Node.js** >= 22.0.0 (enforced via the `engines` field)
232
+ - **Node.js** >= 24.0.0 (enforced via the `engines` field)
220
233
  - **TypeScript** >= 5.0.0 (for TypeScript projects)
221
234
 
222
235
  ## Development
@@ -242,9 +255,6 @@ pnpm run check:fix
242
255
 
243
256
  # Type checking
244
257
  pnpm run typecheck
245
-
246
- # Run micro-benchmarks (scripts/benchmark.mjs)
247
- pnpm run benchmark
248
258
  ```
249
259
 
250
260
  ## Documentation site
@@ -259,7 +269,7 @@ pnpm --filter @rtorcato/js-common-docs dev
259
269
  pnpm --filter @rtorcato/js-common-docs build
260
270
  ```
261
271
 
262
- Live site: <https://rtorcato.github.io/js-common/>
272
+ Live site: <https://docs.torcato.dev/js-common/>
263
273
 
264
274
  ## Roadmap
265
275
 
@@ -16,7 +16,7 @@ export declare function createAbortController(): {
16
16
  signal: AbortSignal;
17
17
  };
18
18
  /**
19
- * Returns a promise that rejects when the given AbortSignal is aborted.
19
+ * Returns a promise that rejects with `signal.reason` when the given AbortSignal is aborted.
20
20
  *
21
21
  * @example
22
22
  * ```typescript
@@ -31,7 +31,8 @@ export declare function createAbortController(): {
31
31
  */
32
32
  export declare function abortPromise(signal: AbortSignal): Promise<never>;
33
33
  /**
34
- * Wraps a promise and rejects it if the signal is aborted.
34
+ * Wraps a promise and rejects it with `signal.reason` if the signal is aborted.
35
+ * The abort listener is removed once the promise settles.
35
36
  *
36
37
  * @example
37
38
  * ```typescript
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/abortController/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB;;;EAGpC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,CAchE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,CAEjF;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAEjG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/abortController/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB;;;EAGpC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,CAKhE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,CAiBjF;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAEjG"}
@@ -1 +1 @@
1
- import"../chunks/chunk-ANN5UYCF.js";function n(){let r=new AbortController;return{controller:r,signal:r.signal}}function t(r){return new Promise((e,o)=>{r.aborted?o(new DOMException("Aborted","AbortError")):r.addEventListener("abort",()=>{o(new DOMException("Aborted","AbortError"))},{once:!0})})}function i(r,e){return Promise.race([r,t(e)])}function b(r,e){return setTimeout(()=>r.abort(),e)}export{b as abortAfter,t as abortPromise,n as createAbortController,i as withAbort};
1
+ import"../chunks/chunk-ANN5UYCF.js";function u(){let e=new AbortController;return{controller:e,signal:e.signal}}function s(e){return new Promise((r,o)=>{e.aborted?o(e.reason):e.addEventListener("abort",()=>o(e.reason),{once:!0})})}function a(e,r){return r.aborted?Promise.reject(r.reason):new Promise((o,n)=>{let b=()=>n(r.reason);r.addEventListener("abort",b,{once:!0});let i=()=>r.removeEventListener("abort",b);e.then(t=>{i(),o(t)},t=>{i(),n(t)})})}function c(e,r){return setTimeout(()=>e.abort(),r)}export{c as abortAfter,s as abortPromise,u as createAbortController,a as withAbort};
@@ -1 +1 @@
1
- import{a as r,b as t}from"../chunks/chunk-UQBVI52L.js";import"../chunks/chunk-ANN5UYCF.js";import{describe as a,expectTypeOf as e,it as u}from"vitest";a("arrays \u2014 types",()=>{u("unique preserves element type",()=>{e(r([1,2,3])).toEqualTypeOf(),e(r(["a"])).toEqualTypeOf()}),u("chunk returns array of arrays of the element type",()=>{e(t([1,2,3],2)).toEqualTypeOf(),e(t(["a","b"],1)).toEqualTypeOf()})});
1
+ import{a as p,b as a,e as n,f as u,g as y}from"../chunks/chunk-U2F5TMN2.js";import"../chunks/chunk-ANN5UYCF.js";import{describe as o,expectTypeOf as e,it as r}from"vitest";o("arrays \u2014 types",()=>{r("unique preserves element type",()=>{e(p([1,2,3])).toEqualTypeOf(),e(p(["a"])).toEqualTypeOf()}),r("chunk returns array of arrays of the element type",()=>{e(a([1,2,3],2)).toEqualTypeOf(),e(a(["a","b"],1)).toEqualTypeOf()})});o("arrays \u2014 grouping helper types",()=>{r("partition returns a tuple of element arrays",()=>{e(n([1,2],t=>t>1)).toEqualTypeOf()}),r("sortBy preserves the element type",()=>{e(u([1,2],t=>t)).toEqualTypeOf()}),r("zip pairs both element types",()=>{e(y([1],["a"])).toEqualTypeOf()})});
@@ -68,4 +68,56 @@ export declare function compact<T>(arr: T[]): T[];
68
68
  * @category Array Utilities
69
69
  */
70
70
  export declare function shuffle<T>(arr: T[]): T[];
71
+ /**
72
+ * Splits an array into two arrays: the elements that satisfy the predicate and
73
+ * the ones that do not. Order is preserved within each half.
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * partition([1, 2, 3, 4], (n) => n % 2 === 0) // [[2, 4], [1, 3]]
78
+ * partition(['a', 'bb'], (s) => s.length > 1) // [['bb'], ['a']]
79
+ * ```
80
+ *
81
+ * @param arr The array to split
82
+ * @param predicate Called with each element and its index; truthy sends the element to the first half
83
+ * @returns A `[pass, fail]` tuple of new arrays
84
+ * @category Array Utilities
85
+ */
86
+ export declare function partition<T>(arr: T[], predicate: (value: T, index: number) => boolean): [T[], T[]];
87
+ /**
88
+ * Sorts an array by a derived key, without mutating the input.
89
+ * Keys are compared with `<` / `>`, so strings sort lexicographically and
90
+ * numbers numerically — unlike `Array#sort`, which stringifies everything.
91
+ * The sort is stable, so equal keys keep their original order.
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * sortBy([{ n: 2 }, { n: 1 }], (o) => o.n) // [{ n: 1 }, { n: 2 }]
96
+ * sortBy([10, 9, 100], (n) => n) // [9, 10, 100] — not [10, 100, 9]
97
+ * sortBy(users, (u) => u.name, 'desc')
98
+ * ```
99
+ *
100
+ * @param arr The array to sort
101
+ * @param keyFn Maps an element to the value to sort by
102
+ * @param direction `'asc'` (default) or `'desc'`
103
+ * @returns A new sorted array
104
+ * @category Array Utilities
105
+ */
106
+ export declare function sortBy<T>(arr: T[], keyFn: (value: T) => number | string | bigint | Date, direction?: 'asc' | 'desc'): T[];
107
+ /**
108
+ * Pairs up two arrays element by element. The result is as long as the shorter
109
+ * input — surplus elements are dropped.
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * zip([1, 2, 3], ['a', 'b', 'c']) // [[1, 'a'], [2, 'b'], [3, 'c']]
114
+ * zip([1, 2, 3], ['a']) // [[1, 'a']]
115
+ * ```
116
+ *
117
+ * @param a The first array
118
+ * @param b The second array
119
+ * @returns An array of `[a[i], b[i]]` pairs
120
+ * @category Array Utilities
121
+ */
122
+ export declare function zip<A, B>(a: A[], b: B[]): [A, B][];
71
123
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/arrays/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAEvC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,EAAE,EAAE,CAOtD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAExC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAOxC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/arrays/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAEvC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,EAAE,EAAE,CAOtD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAExC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAOxC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAC1B,GAAG,EAAE,CAAC,EAAE,EACR,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,GAC7C,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAOZ;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,MAAM,CAAC,CAAC,EACvB,GAAG,EAAE,CAAC,EAAE,EACR,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,EACpD,SAAS,GAAE,KAAK,GAAG,MAAc,GAC/B,CAAC,EAAE,CAWL;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAKlD"}
@@ -1 +1 @@
1
- import{a,b,c,d}from"../chunks/chunk-UQBVI52L.js";import"../chunks/chunk-ANN5UYCF.js";export{b as chunk,c as compact,d as shuffle,a as unique};
1
+ import{a,b,c,d,e,f,g}from"../chunks/chunk-U2F5TMN2.js";import"../chunks/chunk-ANN5UYCF.js";export{b as chunk,c as compact,e as partition,d as shuffle,f as sortBy,a as unique,g as zip};
@@ -0,0 +1 @@
1
+ function e(r){return r.error===null}async function u(r){try{return{data:await r(),error:null}}catch(t){return{data:null,error:t}}}function a(r){try{return{data:r(),error:null}}catch(t){return{data:null,error:t}}}export{e as a,u as b,a as c};
@@ -0,0 +1 @@
1
+ import{d as c}from"./chunk-VSTXGIC3.js";async function h(t){try{return[null,await t]}catch(e){return[e,void 0]}}function w(t,e,a=new Error("Timeout")){return Promise.race([t,new Promise((n,i)=>setTimeout(()=>i(a),e))])}async function b(t,e={}){let{retries:a=3,minDelay:n=100,maxDelay:i=1e4,jitter:s=!0,shouldRetry:m=()=>!0,signal:o}=e;for(let r=1;;r++){o?.throwIfAborted();try{return await t(r,o)}catch(l){if(o?.aborted)throw o.reason;if(r>a||!m(l,r))throw l}let u=Math.min(i,n*2**(r-1));await c(s?Math.random()*u:u,o)}}async function f(t,e,a){if(!Number.isInteger(e)||e<1)throw new RangeError(`limit must be a positive integer, got ${e}`);let n=Array.from(t),i=new Array(n.length),s=0,m=!1;async function o(){for(;!m&&s<n.length;){let r=s++;try{i[r]=await a(n[r],r)}catch(u){throw m=!0,u}}}return await Promise.all(Array.from({length:Math.min(e,n.length)},o)),i}export{h as a,w as b,b as c,f as d};
@@ -0,0 +1 @@
1
+ function s(o){return Array.from(new Set(o))}function i(o,t){if(t<1)throw new Error("Chunk size must be at least 1");let e=[];for(let r=0;r<o.length;r+=t)e.push(o.slice(r,r+t));return e}function T(o){return o.filter(Boolean)}function c(o){let t=o.slice();for(let e=t.length-1;e>0;e--){let r=Math.floor(Math.random()*(e+1));[t[e],t[r]]=[t[r],t[e]]}return t}function a(o,t){let e=[],r=[];return o.forEach((n,u)=>{(t(n,u)?e:r).push(n)}),[e,r]}function f(o,t,e="asc"){let r=e==="desc"?-1:1;return o.map((n,u)=>({value:n,index:u,key:t(n)})).sort((n,u)=>n.key<u.key?-r:n.key>u.key?r:n.index-u.index).map(n=>n.value)}function l(o,t){let e=Math.min(o.length,t.length),r=new Array(e);for(let n=0;n<e;n++)r[n]=[o[n],t[n]];return r}export{s as a,i as b,T as c,c as d,a as e,f,l as g};
@@ -0,0 +1 @@
1
+ var m=o=>new Promise(e=>setTimeout(e,o));function s(o){let e=Date.now()+o;for(;Date.now()<e;);}function u(o,e){let r=Math.floor(Math.random()*(e-o+1))+o;return new Promise(t=>setTimeout(t,r))}function b(o,e){return new Promise((r,t)=>{if(e?.aborted){t(e.reason);return}let n=()=>{clearTimeout(i),t(e?.reason)},i=setTimeout(()=>{e?.removeEventListener("abort",n),r()},o);e?.addEventListener("abort",n,{once:!0})})}export{m as a,s as b,u as c,b as d};
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  // Entry point for the js-common CLI binary.
3
- // CLI-only npm deps (chalk, commander, figlet, …) live under
4
- // `optionalDependencies` to keep the install footprint small for
5
- // library-only consumers. If any of them is missing at runtime we
6
- // catch the resolution error and print install instructions instead
7
- // of letting Node emit an opaque ERR_MODULE_NOT_FOUND trace.
3
+ // CLI-only npm deps (chalk, commander, figlet, …) are optional
4
+ // `peerDependencies`, so library-only consumers never install them. If any
5
+ // of them is missing at runtime we catch the resolution error and print one
6
+ // install line instead of letting Node emit an opaque ERR_MODULE_NOT_FOUND
7
+ // trace. cli.test.ts fails if this list misses a package cli.ts imports.
8
+ const CLI_PEERS = '@inquirer/prompts chalk chalk-animation commander figlet gradient-string';
8
9
  try {
9
10
  await import('./cli.mjs');
10
11
  }
@@ -14,11 +15,7 @@ catch (err) {
14
15
  'code' in err &&
15
16
  err.code === 'ERR_MODULE_NOT_FOUND';
16
17
  if (isMissingModule) {
17
- process.stderr.write('The js-common CLI requires optional dependencies that are not installed.\n' +
18
- 'Install them globally to use the CLI:\n\n' +
19
- ' npm install -g @rtorcato/js-common\n\n' +
20
- 'Or run it ad-hoc with npx, which installs them on demand:\n\n' +
21
- ' npx @rtorcato/js-common@latest --help\n');
18
+ process.stderr.write(`js-common CLI: missing peer dependencies. Install them with: npm i -D ${CLI_PEERS}\n`);
22
19
  process.exit(1);
23
20
  }
24
21
  throw err;
@@ -1,25 +1,29 @@
1
1
  /**
2
2
  * Hashes a string using the specified algorithm.
3
3
  *
4
+ * Web Crypto supports SHA-1/256/384/512 only — there is no md5. An unsupported
5
+ * algorithm rejects.
6
+ *
4
7
  * @example
5
8
  * ```typescript
6
- * hashString('hello')
9
+ * await hashString('hello')
7
10
  * // '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'
8
- * hashString('hello', 'md5') // '5d41402abc4b2a76b9719d911017c592'
11
+ * await hashString('hello', 'sha1') // 'aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d'
9
12
  * ```
10
13
  *
11
14
  * @param str The string to hash.
12
15
  * @param algorithm The hash algorithm (default: 'sha256').
13
16
  * @returns The hex-encoded hash.
14
17
  */
15
- export declare function hashString(str: string, algorithm?: string): string;
18
+ export declare function hashString(str: string, algorithm?: 'sha1' | 'sha256' | 'sha384' | 'sha512'): Promise<string>;
16
19
  /**
17
- * Generates a random hex string of the specified length (in bytes).
20
+ * Generates a cryptographically secure random hex string of the specified length (in bytes).
18
21
  *
19
22
  * @example
20
23
  * ```typescript
21
24
  * randomHex(4) // '9f3c1ab7' (8 hex chars)
22
25
  * randomHex() // 32 hex chars (16 bytes)
26
+ * randomHex(32) // 64 hex chars — a password-reset token
23
27
  * ```
24
28
  *
25
29
  * @param length The number of bytes (not hex chars).
@@ -31,9 +35,9 @@ export declare function randomHex(length?: number): string;
31
35
  *
32
36
  * @example
33
37
  * ```typescript
34
- * hmacHash('payload', 's3cret')
38
+ * await hmacHash('payload', 's3cret')
35
39
  * // 'd1d0f5b6...' (64 hex chars, stable for the same input + secret)
36
- * hmacHash('payload', 's3cret', 'sha1') // 40 hex chars
40
+ * await hmacHash('payload', 's3cret', 'sha1') // 40 hex chars
37
41
  * ```
38
42
  *
39
43
  * @param str The string to hash.
@@ -41,17 +45,18 @@ export declare function randomHex(length?: number): string;
41
45
  * @param algorithm The hash algorithm (default: 'sha256').
42
46
  * @returns The hex-encoded HMAC.
43
47
  */
44
- export declare function hmacHash(str: string, secret: string, algorithm?: string): string;
48
+ export declare function hmacHash(str: string, secret: string, algorithm?: 'sha1' | 'sha256' | 'sha384' | 'sha512'): Promise<string>;
45
49
  /**
46
- * Encodes a string to base64.
50
+ * Encodes a string (as UTF-8) to base64.
47
51
  * @param str The string to encode.
48
52
  * @returns The base64-encoded string.
49
53
  */
50
54
  export declare function base64Encode(str: string): string;
51
55
  /**
52
- * Decodes a base64 string.
53
- * @param b64 The base64 string to decode.
56
+ * Decodes a base64 string to a UTF-8 string.
57
+ * @param b64 The base64 string to decode (standard alphabet; padding optional).
54
58
  * @returns The decoded string.
59
+ * @throws {DOMException} When `b64` is not valid base64 (including the URL-safe `-`/`_` alphabet).
55
60
  */
56
61
  export declare function base64Decode(b64: string): string;
57
62
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/crypto/index.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,SAAW,GAAG,MAAM,CAEpE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,MAAM,SAAK,GAAG,MAAM,CAE7C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,SAAW,GAAG,MAAM,CAElF;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/crypto/index.ts"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,UAAU,CAC/B,GAAG,EAAE,MAAM,EACX,SAAS,GAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAmB,GAC3D,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,MAAM,SAAK,GAAG,MAAM,CAE7C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,QAAQ,CAC7B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,SAAS,GAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAmB,GAC3D,OAAO,CAAC,MAAM,CAAC,CAUjB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD"}
@@ -1 +1 @@
1
- import"../chunks/chunk-ANN5UYCF.js";import{createHash as n,createHmac as i,randomBytes as s}from"node:crypto";function a(t,r="sha256"){return n(r).update(t).digest("hex")}function g(t=16){return s(t).toString("hex")}function u(t,r,e="sha256"){return i(e,r).update(t).digest("hex")}function f(t){return Buffer.from(t,"utf-8").toString("base64")}function c(t){return Buffer.from(t,"base64").toString("utf-8")}export{c as base64Decode,f as base64Encode,a as hashString,u as hmacHash,g as randomHex};
1
+ import"../chunks/chunk-ANN5UYCF.js";function e(r){return Array.from(new Uint8Array(r),n=>n.toString(16).padStart(2,"0")).join("")}function a(r){return`SHA-${r.replace(/^sha-?/i,"")}`}async function i(r,n="sha256"){let t=await crypto.subtle.digest(a(n),new TextEncoder().encode(r));return e(t)}function c(r=16){return e(crypto.getRandomValues(new Uint8Array(r)))}async function g(r,n,t="sha256"){let o=new TextEncoder,s=await crypto.subtle.importKey("raw",o.encode(n),{name:"HMAC",hash:a(t)},!1,["sign"]);return e(await crypto.subtle.sign("HMAC",s,o.encode(r)))}function d(r){return btoa(Array.from(new TextEncoder().encode(r),n=>String.fromCharCode(n)).join(""))}function h(r){return new TextDecoder().decode(Uint8Array.from(atob(r),n=>n.charCodeAt(0)))}export{h as base64Decode,d as base64Encode,i as hashString,g as hmacHash,c as randomHex};
@@ -1 +1 @@
1
- {"version":3,"file":"currencies.d.ts","sourceRoot":"","sources":["../../src/currency/currencies.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,UAAU,UA4Cf,CAAA;AAED,eAAe,UAAU,CAAA"}
1
+ {"version":3,"file":"currencies.d.ts","sourceRoot":"","sources":["../../src/currency/currencies.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,UAAU,UA4Cf,CAAA;eAEc,UAAU"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/currency/index.ts"],"names":[],"mappings":"AAgBA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,GAAI,UAAU,MAAM,KAAG,MAAM,GAAG,SAY7D,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,SAAO,GAAG,MAAM,GAAG,SAAS,CAMnF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAkC1D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,SAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAM7F;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CACjC,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,QAAQ,SAAQ,EAChB,MAAM,CAAC,EAAE,MAAM,GACb,MAAM,CAQR;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAevD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA2C9F;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,MAAM,CAElF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGxE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOrD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/currency/index.ts"],"names":[],"mappings":"AAgBA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,iBAAiB,aAAc,MAAM,KAAG,MAAM,GAAG,SAY7D,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,SAAO,GAAG,MAAM,GAAG,SAAS,CAMnF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAkC1D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,SAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAM7F;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CACjC,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,QAAQ,SAAQ,EAChB,MAAM,CAAC,EAAE,MAAM,GACb,MAAM,CAQR;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAevD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA2C9F;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAI,GAAG,MAAM,CAElF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGxE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOrD"}
@@ -27,7 +27,8 @@ export declare function parseDate(dateStr: string): Date;
27
27
  */
28
28
  export declare function formatDate(date: Date): string;
29
29
  /**
30
- * Returns the difference in days between two dates (date2 - date1).
30
+ * Returns the difference in days between two dates (date2 - date1), measured in
31
+ * local wall-clock time so a DST change doesn't cost or gain a day.
31
32
  */
32
33
  export declare function daysBetween(date1: string | Date, date2: string | Date): number;
33
34
  /**
@@ -52,6 +53,15 @@ export declare function addDays(date: string | Date, days: number): Date;
52
53
  export declare function subDays(date: string | Date, days: number): Date;
53
54
  /**
54
55
  * Adds months to a date and returns a new Date object.
56
+ *
57
+ * When the source day does not exist in the target month, the result clamps to that
58
+ * month's last day (as Temporal and date-fns do) instead of rolling into the next month.
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * addMonths('2026-01-31', 1) // Date — Feb 28, not Mar 3
63
+ * addMonths('2024-01-31', 1) // Date — Feb 29 (leap year)
64
+ * ```
55
65
  */
56
66
  export declare function addMonths(date: string | Date, months: number): Date;
57
67
  /**
@@ -67,9 +77,19 @@ export declare function startOfDay(date: string | Date): Date;
67
77
  */
68
78
  export declare function endOfDay(date: string | Date): Date;
69
79
  /**
70
- * Returns true if the date falls on Saturday or Sunday.
80
+ * Returns true if the date falls on Saturday or Sunday (local time).
71
81
  */
72
82
  export declare function isWeekend(date: string | Date): boolean;
83
+ /**
84
+ * Returns true if the date falls on Monday through Friday (local time).
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * isWeekday('2026-06-12') // true (Friday)
89
+ * isWeekday('2026-06-13') // false (Saturday)
90
+ * ```
91
+ */
92
+ export declare function isWeekday(date: string | Date): boolean;
73
93
  /**
74
94
  * Returns true if the two dates fall on the same calendar day (local time).
75
95
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/date/index.ts"],"names":[],"mappings":"AASA;;;;;;;GAOG;AACH,wBAAgB,KAAK,IAAI,MAAM,CAE9B;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE/C;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAE7C;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAE9E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAE9E;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAEhF;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAGvD;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAI/D;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAE/D;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAInE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAExD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAIpD;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAIlD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAGtD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAQ7E;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAEpD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,GAAE,IAAiB,GAAG,MAAM,CAQlF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/date/index.ts"],"names":[],"mappings":"AASA;;;;;;;GAOG;AACH,wBAAgB,KAAK,IAAI,MAAM,CAE9B;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE/C;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAE7C;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAI9E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAE9E;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAEhF;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAGvD;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAI/D;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAE/D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CASnE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAExD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAIpD;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAIlD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAGtD;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAEtD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAQ7E;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAEpD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,GAAE,IAAiB,GAAG,MAAM,CAQlF"}