@web-ts-toolkit/utils 0.43.0 → 0.45.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/README.md +145 -11
- package/index.d.mts +398 -8
- package/index.d.ts +398 -8
- package/index.js +352 -82
- package/index.mjs +351 -82
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,13 +8,12 @@ Shared collection, object, async, and URL helpers used across the workspace.
|
|
|
8
8
|
pnpm add @web-ts-toolkit/utils
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Requires Node `>=22`. Import from the package root with canonical named
|
|
12
|
+
imports; there is no default export and no public subpath:
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
- URL helpers such as `normalizeUrlPath(...)`
|
|
17
|
-
- async helpers such as `mapValuesAsync(...)`
|
|
14
|
+
```ts
|
|
15
|
+
import { get, normalizeUrlPath, parseBooleanString } from '@web-ts-toolkit/utils';
|
|
16
|
+
```
|
|
18
17
|
|
|
19
18
|
## Quick Start
|
|
20
19
|
|
|
@@ -64,14 +63,149 @@ parseBooleanString('true', false);
|
|
|
64
63
|
|
|
65
64
|
## Main Exports
|
|
66
65
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
-
|
|
66
|
+
58 functions plus the `PropertyPath` type, all from the package root
|
|
67
|
+
(see `src/index.ts`):
|
|
68
|
+
|
|
69
|
+
- object/path helpers: `get`, `set`, `hasOwn`, `pick`, `pickBy`, `omit`, `omitBy`, `assign`, `keys`, `mapKeys`, `mapValues`, `toStringRecord`
|
|
70
|
+
- collection helpers: `map`, `filter`, `forEach`, `eachRight`, `join`, `reduce`, `find`, `flatten`, `flattenDeep`, `compact`, `uniq`, `uniqBy`, `difference`, `intersection`, `intersectionBy`, `groupBy`, `orderBy`, `sum`, `sumBy`
|
|
71
|
+
- guards: `isArray`, `isBoolean`, `isEmpty`, `isEqual`, `isFunction`, `isMatch`, `isNaN`, `isNil`, `isNumber`, `isObject`, `isPlainObject`, `isPromise`, `isString`, `isUndefined`
|
|
72
|
+
- string helpers: `startCase`, `upperCase`, `padEnd`
|
|
71
73
|
- URL helpers: `addLeadingSlash`, `removeConsecutiveSlashesFromUrl`, `normalizeUrlPath`
|
|
74
|
+
- async helpers: `mapValuesAsync`, `toAsyncFn`
|
|
75
|
+
- misc: `castArray`, `arrayToRecord`, `cloneDeep`, `noop`, `parseBooleanString`
|
|
76
|
+
|
|
77
|
+
## Path Grammar And Mutation Rules
|
|
78
|
+
|
|
79
|
+
`get`, `set`, `pick`, and `omit` accept a `PropertyPath`: dot segments
|
|
80
|
+
(`'a.b'`), bare brackets (`'a[0]'`), quoted brackets (`'a["b.c"]'`), or
|
|
81
|
+
segment arrays (`['a', 'b']`).
|
|
82
|
+
|
|
83
|
+
- Key identity is literal: string segments are never coerced, so `'01'`
|
|
84
|
+
and `'1'` address different properties, and digit keys beyond
|
|
85
|
+
`MAX_SAFE_INTEGER` never round. Only canonical indices (`'0'`, `'1'`,
|
|
86
|
+
… with no leading zeros) address array slots; `'a[01]'` addresses an
|
|
87
|
+
own `'01'` property. Empty quoted keys, escaped quotes, empty dot
|
|
88
|
+
segments, and malformed brackets are unspecified (no Lodash parity).
|
|
89
|
+
- Mutation segments `__proto__`, `constructor`, and `prototype` (quoted
|
|
90
|
+
or not) are rejected before any write: `set` returns its target
|
|
91
|
+
unchanged and `omit` is a no-op.
|
|
92
|
+
- In `pick`/`omit`, a flat string array is a **list** of paths
|
|
93
|
+
(`pick(o, ['a', 'b'])` picks keys `a` and `b`); pass a nested array for
|
|
94
|
+
a single segmented path (`pick(o, [['a', 'b']])` picks `a.b`).
|
|
95
|
+
- Reads follow the prototype chain; `get` returns `defaultValue` for a
|
|
96
|
+
`null`/`undefined` intermediate or an `undefined` leaf. Writes never
|
|
97
|
+
traverse inherited containers: an inherited member is shadowed with a
|
|
98
|
+
new own container (array for a following canonical index, plain object
|
|
99
|
+
otherwise) and the final write creates an own data property, bypassing
|
|
100
|
+
inherited setters. Use `hasOwn` when own-key presence matters.
|
|
101
|
+
- Dictionary builders (`groupBy`, `arrayToRecord`, `mapKeys`,
|
|
102
|
+
`mapValues`, `pickBy`, `omitBy`, `toStringRecord`) preserve arbitrary
|
|
103
|
+
string keys — including `__proto__` — as own data properties without
|
|
104
|
+
replacing the result prototype. Results keep `Object.prototype`
|
|
105
|
+
(never null-prototype).
|
|
106
|
+
|
|
107
|
+
## Mutation Versus Copying
|
|
108
|
+
|
|
109
|
+
- `set` mutates its target in place and returns it. `omit` never mutates
|
|
110
|
+
its input: it deep-clones first, then deletes from the clone.
|
|
111
|
+
- `assign` is a thin wrapper over native `Object.assign` (source getters
|
|
112
|
+
and target setters run); it is not a hardened untrusted-input copier.
|
|
113
|
+
- `orderBy`, `uniq`/`uniqBy`, `difference`, the `intersection` family,
|
|
114
|
+
and `flatten`/`flattenDeep` never mutate their inputs. Sorting and
|
|
115
|
+
deduplication are stable/first-occurrence: ties keep input order and
|
|
116
|
+
the first occurrence wins.
|
|
117
|
+
|
|
118
|
+
## Clone And Comparison Domains
|
|
119
|
+
|
|
120
|
+
`cloneDeep`, `isEqual`, and `isMatch` share one bounded domain:
|
|
121
|
+
|
|
122
|
+
- Supported: primitives (`NaN` equals itself), plain objects
|
|
123
|
+
(`null`/`Object.prototype`, plus `Object.create` graphs over plain
|
|
124
|
+
ancestors whose prototype is shared by reference), arrays (length,
|
|
125
|
+
holes, and extra own keys participate), `Date` (by time), and `RegExp`
|
|
126
|
+
(by source plus flags). Cycles and repeated references terminate and
|
|
127
|
+
stay shared within the clone.
|
|
128
|
+
- Functions and exotic values (`Map`/`Set`, class instances such as BSON
|
|
129
|
+
`ObjectId`) are opaque: nested occurrences are shared by reference,
|
|
130
|
+
never traversed, and distinct references are never equal. A top-level
|
|
131
|
+
exotic root passed to `cloneDeep` throws `TypeError` instead of
|
|
132
|
+
returning an alias, so `omit` on an uncloneable root throws before
|
|
133
|
+
deleting anything rather than deleting from your input.
|
|
134
|
+
- Comparison uses own enumerable string/symbol keys only: inherited
|
|
135
|
+
state is ignored and prototypes are not compared. `isMatch` requires
|
|
136
|
+
each own source key (including `undefined`-valued and symbol keys) to
|
|
137
|
+
exist as an own key on the target, so `isMatch({}, { a: undefined })`
|
|
138
|
+
is `false`; arrays use prefix semantics.
|
|
139
|
+
|
|
140
|
+
## Async Contracts
|
|
141
|
+
|
|
142
|
+
- `toAsyncFn` lifts sync results into a promise, but it is not a full
|
|
143
|
+
async-function boundary: a synchronous `throw` escapes synchronously
|
|
144
|
+
instead of becoming a rejection, and thenables (including foreign
|
|
145
|
+
thenables) are returned unchanged with identity preserved rather than
|
|
146
|
+
converted to native promises. When `fn` is absent, the wrapper resolves
|
|
147
|
+
`defaultValue`. `this` is forwarded.
|
|
148
|
+
- `mapValuesAsync` starts every callback eagerly with unbounded
|
|
149
|
+
parallelism (`Promise.all`): one rejection rejects the whole call, and
|
|
150
|
+
there is no concurrency limit, cancellation, or scheduler. Chunk the
|
|
151
|
+
input if downstream throttling is needed.
|
|
152
|
+
|
|
153
|
+
## Boolean Strings
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
import { parseBooleanString } from '@web-ts-toolkit/utils';
|
|
157
|
+
|
|
158
|
+
parseBooleanString('true'); // true
|
|
159
|
+
parseBooleanString('false'); // false
|
|
160
|
+
parseBooleanString('TRUE'); // false — exact match only, no case folding
|
|
161
|
+
parseBooleanString(''); // undefined — empty string falls back to the default
|
|
162
|
+
parseBooleanString('', false); // false — via the default
|
|
163
|
+
parseBooleanString(undefined, true); // true — missing input uses the default
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
`parseBooleanString(str, defaultValue)` returns `true` only for the exact
|
|
167
|
+
string `'true'`, returns `false` for any other non-empty string, and falls
|
|
168
|
+
back to `defaultValue` (which is `undefined` when omitted) when the input
|
|
169
|
+
is `undefined` **or the empty string `''`**. Note that an Express-style
|
|
170
|
+
`?flag=` query value parses to `''` and therefore yields the default, not
|
|
171
|
+
`false`.
|
|
172
|
+
|
|
173
|
+
## URL Paths Are Pathname-Only
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
import { normalizeUrlPath } from '@web-ts-toolkit/utils';
|
|
177
|
+
|
|
178
|
+
normalizeUrlPath('api//users'); // '/api/users'
|
|
179
|
+
normalizeUrlPath('api//users/42'); // '/api/users/42'
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
`normalizeUrlPath` composes route-path fragments: it collapses every run
|
|
183
|
+
of slashes and prepends a leading slash. The input must be a path
|
|
184
|
+
fragment — no scheme/host, query string, or fragment. Full URLs are out
|
|
185
|
+
of domain and are mangled rather than normalized
|
|
186
|
+
(`normalizeUrlPath('https://example.com//a')` yields
|
|
187
|
+
`'/https:/example.com/a'`; slash runs inside query/fragment values are
|
|
188
|
+
collapsed too). These helpers are route-path composition for workspace
|
|
189
|
+
routers, not WHATWG URL normalization and not a security sanitizer.
|
|
190
|
+
|
|
191
|
+
## Guards And Types
|
|
192
|
+
|
|
193
|
+
- `isBoolean`/`isNumber`/`isString` accept primitives only: boxed
|
|
194
|
+
instances such as `new Boolean(false)` return `false` and are never
|
|
195
|
+
narrowed to primitives.
|
|
196
|
+
- `flattenDeep<T>(input)` takes `unknown` (a non-array yields `[]`) and
|
|
197
|
+
`T` is an unchecked caller assertion — specify it explicitly
|
|
198
|
+
(`flattenDeep<number>(input)`) or narrow `unknown[]` yourself. Cyclic
|
|
199
|
+
arrays throw `TypeError`; shared (non-ancestor) subarrays flatten once
|
|
200
|
+
per occurrence. Wide and deeply nested inputs flatten iteratively
|
|
201
|
+
without `RangeError`.
|
|
202
|
+
- `intersectionBy`/`difference` ignore non-array value arguments, while
|
|
203
|
+
`intersection` treats a non-array secondary as empty (result `[]`).
|
|
204
|
+
`intersectionBy` evaluates each element's iteratee once per input array;
|
|
205
|
+
redundant-callback side effects are not preserved.
|
|
72
206
|
|
|
73
207
|
## Documentation
|
|
74
208
|
|
|
75
|
-
Full package documentation lives
|
|
209
|
+
Full package documentation lives on the published docs site:
|
|
76
210
|
|
|
77
211
|
- live docs: https://web-ts-toolkit.pages.dev/docs/packages/utils
|