@rimbu/base 2.0.3 → 2.0.5
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 +38 -63
- package/package.json +4 -11
- package/dist/bun/arr.mts +0 -477
- package/dist/bun/entry.mts +0 -21
- package/dist/bun/index.mts +0 -16
- package/dist/bun/internal.mts +0 -1
- package/dist/bun/plain-object.mts +0 -95
- package/dist/bun/rimbu-error.mts +0 -64
- package/dist/bun/token.mts +0 -9
package/README.md
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|

|
|
7
7
|

|
|
8
8
|

|
|
9
|
-

|
|
10
9
|

|
|
11
10
|

|
|
12
11
|
|
|
@@ -77,10 +76,10 @@ import { Arr } from '@rimbu/base';
|
|
|
77
76
|
const base = [1, 2, 3];
|
|
78
77
|
|
|
79
78
|
// Pure modification: only clones when the value actually changes
|
|
80
|
-
const incremented = Arr.mod(base, 1, v => v + 1); // [1, 3, 3]
|
|
79
|
+
const incremented = Arr.mod(base, 1, (v) => v + 1); // [1, 3, 3]
|
|
81
80
|
|
|
82
81
|
// Structural no-op returns original reference for efficiency
|
|
83
|
-
const same = Arr.mod(base, 5, v => v); // index out of range → original
|
|
82
|
+
const same = Arr.mod(base, 5, (v) => v); // index out of range → original
|
|
84
83
|
|
|
85
84
|
// Append without mutating
|
|
86
85
|
const appended = Arr.append(incremented, 4); // [1, 3, 3, 4]
|
|
@@ -97,22 +96,22 @@ console.log(base); // [1, 2, 3]
|
|
|
97
96
|
|
|
98
97
|
All functions accept a `readonly T[]` input and return either the original array (when unchanged) or an optimized clone.
|
|
99
98
|
|
|
100
|
-
| Function
|
|
101
|
-
|
|
|
102
|
-
| `append`
|
|
103
|
-
| `prepend`
|
|
104
|
-
| `concat`
|
|
105
|
-
| `reverse`
|
|
106
|
-
| `forEach`
|
|
107
|
-
| `map` / `reverseMap` | Indexed transformation forward or backward.
|
|
108
|
-
| `last`
|
|
109
|
-
| `update`
|
|
110
|
-
| `mod`
|
|
111
|
-
| `insert`
|
|
112
|
-
| `tail` / `init`
|
|
113
|
-
| `splice`
|
|
114
|
-
| `copySparse`
|
|
115
|
-
| `mapSparse`
|
|
99
|
+
| Function | Purpose |
|
|
100
|
+
| -------------------- | --------------------------------------------------------- |
|
|
101
|
+
| `append` | Add element at end (non-empty array optimization). |
|
|
102
|
+
| `prepend` | Add element at start efficiently. |
|
|
103
|
+
| `concat` | Smart concat – reuses original when one side empty. |
|
|
104
|
+
| `reverse` | Fast reversed copy (range slice optional). |
|
|
105
|
+
| `forEach` | Controlled traversal with optional reverse + halt state. |
|
|
106
|
+
| `map` / `reverseMap` | Indexed transformation forward or backward. |
|
|
107
|
+
| `last` | O(1) last element access (uses `.at(-1)` when available). |
|
|
108
|
+
| `update` | Apply `Update<T>` logic at index (no-op preserved). |
|
|
109
|
+
| `mod` | Lightweight element modification via `(value)=>value'`. |
|
|
110
|
+
| `insert` | Insert at index. |
|
|
111
|
+
| `tail` / `init` | Drop first / last element. |
|
|
112
|
+
| `splice` | Immutable variant of native splice. |
|
|
113
|
+
| `copySparse` | Preserve holes in sparse arrays. |
|
|
114
|
+
| `mapSparse` | Transform only present indices, keeping sparsity. |
|
|
116
115
|
|
|
117
116
|
Design details:
|
|
118
117
|
|
|
@@ -132,7 +131,9 @@ Entry.first(pair); // 'age'
|
|
|
132
131
|
Entry.second(pair); // 42
|
|
133
132
|
|
|
134
133
|
// Shared sentinel for internal tagging / identity
|
|
135
|
-
if (someValue === Token) {
|
|
134
|
+
if (someValue === Token) {
|
|
135
|
+
/* special branch */
|
|
136
|
+
}
|
|
136
137
|
```
|
|
137
138
|
|
|
138
139
|
---
|
|
@@ -141,14 +142,14 @@ if (someValue === Token) { /* special branch */ }
|
|
|
141
142
|
|
|
142
143
|
Compile-time predicates for discriminating plain data objects from complex / functional structures:
|
|
143
144
|
|
|
144
|
-
| Type
|
|
145
|
-
|
|
|
146
|
-
| `IsPlainObj<T>`
|
|
147
|
-
| `PlainObj<T>`
|
|
148
|
-
| `IsArray<T>`
|
|
149
|
-
| `IsAny<T>`
|
|
150
|
-
| `isPlainObj(obj)` | Runtime guard for plain data objects.
|
|
151
|
-
| `isIterable(obj)` | Runtime guard for `Iterable`.
|
|
145
|
+
| Type | Description |
|
|
146
|
+
| ----------------- | ---------------------------------------------------------------------------------- |
|
|
147
|
+
| `IsPlainObj<T>` | True only for non-iterable, non-function object types without function properties. |
|
|
148
|
+
| `PlainObj<T>` | Narrows to T if `IsPlainObj<T>`; otherwise `never`. |
|
|
149
|
+
| `IsArray<T>` | Resolves to `true` if T is a (readonly) array type. |
|
|
150
|
+
| `IsAny<T>` | Detects `any`. |
|
|
151
|
+
| `isPlainObj(obj)` | Runtime guard for plain data objects. |
|
|
152
|
+
| `isIterable(obj)` | Runtime guard for `Iterable`. |
|
|
152
153
|
|
|
153
154
|
Use these when building APIs that must reject iterables or functions while retaining strong type discrimination.
|
|
154
155
|
|
|
@@ -158,12 +159,12 @@ Use these when building APIs that must reject iterables or functions while retai
|
|
|
158
159
|
|
|
159
160
|
Structured error classes provide meaningful failure contexts internally and externally:
|
|
160
161
|
|
|
161
|
-
| Error Class
|
|
162
|
-
|
|
|
163
|
-
| `EmptyCollectionAssumedNonEmptyError`
|
|
164
|
-
| `ModifiedBuilderWhileLoopingOverItError` | Mutating a builder mid-iteration.
|
|
165
|
-
| `InvalidStateError`
|
|
166
|
-
| `InvalidUsageError`
|
|
162
|
+
| Error Class | Trigger Scenario |
|
|
163
|
+
| ---------------------------------------- | ---------------------------------------------- |
|
|
164
|
+
| `EmptyCollectionAssumedNonEmptyError` | An operation expected a non-empty collection. |
|
|
165
|
+
| `ModifiedBuilderWhileLoopingOverItError` | Mutating a builder mid-iteration. |
|
|
166
|
+
| `InvalidStateError` | Internal invariant breach (should not happen). |
|
|
167
|
+
| `InvalidUsageError` | Consumer used an API incorrectly. |
|
|
167
168
|
|
|
168
169
|
Helper throw functions exist for concise signaling (`throwInvalidStateError()`, etc.). Prefer them for consistency.
|
|
169
170
|
|
|
@@ -174,7 +175,6 @@ Helper throw functions exist for concise signaling (`throwInvalidStateError()`,
|
|
|
174
175
|
### Compabitity
|
|
175
176
|
|
|
176
177
|
- [`Node` ](https://nodejs.org)
|
|
177
|
-
- [`Deno` ](https://deno.com/runtime)
|
|
178
178
|
- [`Bun` ](https://bun.sh/)
|
|
179
179
|
- `Web` 
|
|
180
180
|
|
|
@@ -198,37 +198,12 @@ npm install @rimbu/base
|
|
|
198
198
|
bun add @rimbu/base
|
|
199
199
|
```
|
|
200
200
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
Create or edit `import_map.json` in your project root:
|
|
204
|
-
|
|
205
|
-
```json
|
|
206
|
-
{
|
|
207
|
-
"imports": {
|
|
208
|
-
"@rimbu/": "https://deno.land/x/rimbu@x.y.z/"
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
_Replace `x.y.z` with the desired version._
|
|
201
|
+
**Deno:**
|
|
214
202
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
```ts
|
|
218
|
-
import { List } from '@rimbu/core/mod.ts';
|
|
219
|
-
import { HashMap } from '@rimbu/hashed/mod.ts';
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
Note that for sub-packages, due to conversion limitations it is needed to import the `index.ts` instead of `mod.ts`, like so:
|
|
223
|
-
|
|
224
|
-
```ts
|
|
225
|
-
import { HashMap } from '@rimbu/hashed/map/index.ts';
|
|
203
|
+
```sh
|
|
204
|
+
deno add npm:@rimbu/base
|
|
226
205
|
```
|
|
227
206
|
|
|
228
|
-
To run your script (let's assume the entry point is in `src/main.ts`):
|
|
229
|
-
|
|
230
|
-
`deno run --import-map import_map.json src/main.ts`
|
|
231
|
-
|
|
232
207
|
## Usage
|
|
233
208
|
|
|
234
209
|
```ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rimbu/base",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.5",
|
|
4
4
|
"description": "Utilities to implement Rimbu collections",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"array",
|
|
@@ -32,7 +32,6 @@
|
|
|
32
32
|
"types": "./dist/cjs/index.d.cts",
|
|
33
33
|
"exports": {
|
|
34
34
|
".": {
|
|
35
|
-
"bun": "./dist/bun/main/index.mts",
|
|
36
35
|
"import": {
|
|
37
36
|
"types": "./dist/esm/index.d.mts",
|
|
38
37
|
"default": "./dist/esm/index.mjs"
|
|
@@ -49,17 +48,11 @@
|
|
|
49
48
|
],
|
|
50
49
|
"scripts": {
|
|
51
50
|
"build": "yarn clean && yarn bundle",
|
|
52
|
-
"
|
|
53
|
-
"bundle": "yarn bundle:cjs && yarn bundle:esm && yarn bundle:bun",
|
|
54
|
-
"bundle:bun": "node ../../config/bunnify.mjs -mode bun",
|
|
51
|
+
"bundle": "yarn bundle:cjs && yarn bundle:esm",
|
|
55
52
|
"bundle:cjs": "yarn bundle:cjs-prepare && yarn bundle:cjs-build && yarn bundle:cjs-clean",
|
|
56
53
|
"bundle:cjs-prepare": "node ../../config/bunnify.mjs -mode cjs",
|
|
57
54
|
"bundle:cjs-build": "tsc -p tsconfig.cjs.json",
|
|
58
55
|
"bundle:cjs-clean": "rimraf _cjs_prepare",
|
|
59
|
-
"bundle:deno-prepare": "node ../../config/prepare-denoify.mjs",
|
|
60
|
-
"bundle:deno-convert": "denoify --src _deno_prepare/src",
|
|
61
|
-
"bundle:deno-move": "rimraf ../../deno_dist/base && mv deno_dist ../../deno_dist/base",
|
|
62
|
-
"bundle:deno-clean": "rimraf _deno_prepare",
|
|
63
56
|
"bundle:esm": "tsc --p tsconfig.esm.json",
|
|
64
57
|
"clean": "rimraf dist",
|
|
65
58
|
"format": "yarn format:base --write",
|
|
@@ -73,10 +66,10 @@
|
|
|
73
66
|
"typecheck": "tsc"
|
|
74
67
|
},
|
|
75
68
|
"dependencies": {
|
|
76
|
-
"@rimbu/common": "^2.0.
|
|
69
|
+
"@rimbu/common": "^2.0.5"
|
|
77
70
|
},
|
|
78
71
|
"publishConfig": {
|
|
79
72
|
"access": "public"
|
|
80
73
|
},
|
|
81
|
-
"gitHead": "
|
|
74
|
+
"gitHead": "15fd7c44f369838a47d42532bcd9771d65d6f660"
|
|
82
75
|
}
|
package/dist/bun/arr.mts
DELETED
|
@@ -1,477 +0,0 @@
|
|
|
1
|
-
import { TraverseState, Update, type ArrayNonEmpty } from '@rimbu/common';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Internal helper that appends a value using the modern immutable `toSpliced` API.
|
|
5
|
-
* @internal
|
|
6
|
-
* @typeparam T - the array element type
|
|
7
|
-
* @param array - the source array (not mutated)
|
|
8
|
-
* @param value - the value to append
|
|
9
|
-
* @returns a new non-empty array with the value at the end
|
|
10
|
-
*/
|
|
11
|
-
export function _appendNew<T>(array: readonly T[], value: T): ArrayNonEmpty<T> {
|
|
12
|
-
return array.toSpliced(array.length, 0, value) as ArrayNonEmpty<T>;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Internal helper that appends a value by cloning and pushing (legacy fallback).
|
|
17
|
-
* @internal
|
|
18
|
-
* @typeparam T - the array element type
|
|
19
|
-
* @param array - the source array (not mutated)
|
|
20
|
-
* @param value - the value to append
|
|
21
|
-
* @returns a new non-empty array with the value at the end
|
|
22
|
-
*/
|
|
23
|
-
export function _appendOld<T>(array: readonly T[], value: T): ArrayNonEmpty<T> {
|
|
24
|
-
const clone = array.slice();
|
|
25
|
-
clone.push(value);
|
|
26
|
-
return clone as ArrayNonEmpty<T>;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Returns a copy of the array with the given value appended.
|
|
31
|
-
* Chooses an implementation depending on environment capabilities.
|
|
32
|
-
* @typeparam T - the array element type
|
|
33
|
-
* @param array - the source array (not mutated)
|
|
34
|
-
* @param value - the value to append
|
|
35
|
-
* @returns a new array with the value at the end
|
|
36
|
-
*/
|
|
37
|
-
export const append = `toSpliced` in Array.prototype ? _appendNew : _appendOld;
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Returns the concatenation of two arrays, reusing an input array when the other is empty.
|
|
41
|
-
* @typeparam T - the array element type
|
|
42
|
-
* @param first - the first array
|
|
43
|
-
* @param second - the second array
|
|
44
|
-
* @returns a new array containing all elements of both arrays (or one of the originals if the other is empty)
|
|
45
|
-
*/
|
|
46
|
-
export function concat<T>(
|
|
47
|
-
first: readonly T[],
|
|
48
|
-
second: readonly T[]
|
|
49
|
-
): readonly T[] {
|
|
50
|
-
if (first.length === 0) return second;
|
|
51
|
-
if (second.length === 0) return first;
|
|
52
|
-
return first.concat(second);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Internal helper to create a reversed copy using modern `toReversed` with optional slicing.
|
|
57
|
-
* @internal
|
|
58
|
-
*/
|
|
59
|
-
export function _reverseNew<T>(
|
|
60
|
-
array: readonly T[],
|
|
61
|
-
start?: number,
|
|
62
|
-
end?: number
|
|
63
|
-
): T[] {
|
|
64
|
-
const source =
|
|
65
|
-
undefined !== start || undefined !== end
|
|
66
|
-
? array.slice(start ?? 0, (end ?? array.length - 1) + 1)
|
|
67
|
-
: array;
|
|
68
|
-
|
|
69
|
-
return source.toReversed();
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Internal helper to create a reversed copy using manual iteration (legacy fallback).
|
|
74
|
-
* @internal
|
|
75
|
-
*/
|
|
76
|
-
export function _reverseOld<T>(
|
|
77
|
-
array: readonly T[],
|
|
78
|
-
start?: number,
|
|
79
|
-
end?: number
|
|
80
|
-
): T[] {
|
|
81
|
-
const _start = start ?? 0;
|
|
82
|
-
const _end = end ?? array.length - 1;
|
|
83
|
-
const length = _end - _start + 1;
|
|
84
|
-
const res = [] as T[];
|
|
85
|
-
|
|
86
|
-
let arrayIndex = _start - 1;
|
|
87
|
-
let resIndex = length - 1;
|
|
88
|
-
|
|
89
|
-
while (++arrayIndex <= _end) res[resIndex--] = array[arrayIndex];
|
|
90
|
-
|
|
91
|
-
return res;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Returns a copy of the array (or a slice) with elements in reversed order.
|
|
96
|
-
* @typeparam T - array element type
|
|
97
|
-
* @param array - the source array
|
|
98
|
-
* @param start - optional start index (inclusive)
|
|
99
|
-
* @param end - optional end index (inclusive)
|
|
100
|
-
*/
|
|
101
|
-
export const reverse =
|
|
102
|
-
'toReversed' in Array.prototype ? _reverseNew : _reverseOld;
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Performs the given function for each element of the array, optionally in reverse order.
|
|
106
|
-
* Halting is supported through the provided `TraverseState`.
|
|
107
|
-
* @typeparam T - element type
|
|
108
|
-
* @param array - the source array
|
|
109
|
-
* @param f - callback receiving (value, sequential index, halt)
|
|
110
|
-
* @param state - traversal state (created if omitted)
|
|
111
|
-
* @param reversed - whether to traverse in reverse order
|
|
112
|
-
*/
|
|
113
|
-
export function forEach<T>(
|
|
114
|
-
array: readonly T[],
|
|
115
|
-
f: (value: T, index: number, halt: () => void) => void,
|
|
116
|
-
state: TraverseState = TraverseState(),
|
|
117
|
-
reversed = false
|
|
118
|
-
): void {
|
|
119
|
-
if (state.halted) return;
|
|
120
|
-
|
|
121
|
-
const { halt } = state;
|
|
122
|
-
|
|
123
|
-
if (reversed) {
|
|
124
|
-
let i = array.length;
|
|
125
|
-
|
|
126
|
-
while (!state.halted && --i >= 0) {
|
|
127
|
-
f(array[i], state.nextIndex(), halt);
|
|
128
|
-
}
|
|
129
|
-
} else {
|
|
130
|
-
const length = array.length;
|
|
131
|
-
let i = -1;
|
|
132
|
-
|
|
133
|
-
while (!state.halted && ++i < length) {
|
|
134
|
-
f(array[i], state.nextIndex(), halt);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Returns a copy of the array where the given function is applied to each element.
|
|
141
|
-
* Supports an index offset useful for composed traversals.
|
|
142
|
-
* @typeparam T - source element type
|
|
143
|
-
* @typeparam R - result element type
|
|
144
|
-
* @param array - the source array
|
|
145
|
-
* @param f - the mapping function
|
|
146
|
-
* @param indexOffset - optional start index value passed to `f`
|
|
147
|
-
*/
|
|
148
|
-
export function map<T, R>(
|
|
149
|
-
array: readonly T[],
|
|
150
|
-
f: (value: T, index: number) => R,
|
|
151
|
-
indexOffset = 0
|
|
152
|
-
): R[] {
|
|
153
|
-
if (indexOffset === 0) {
|
|
154
|
-
// without offset, can use standard array map
|
|
155
|
-
return array.map(f);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const result: R[] = [];
|
|
159
|
-
|
|
160
|
-
let index = indexOffset;
|
|
161
|
-
let i = -1;
|
|
162
|
-
const length = array.length;
|
|
163
|
-
while (++i < length) {
|
|
164
|
-
result[i] = f(array[i], index++);
|
|
165
|
-
}
|
|
166
|
-
return result;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Returns a copy of the array where the given function is applied to each element in reverse order.
|
|
171
|
-
* @typeparam T - source element type
|
|
172
|
-
* @typeparam R - result element type
|
|
173
|
-
* @param array - the source array
|
|
174
|
-
* @param f - the mapping function
|
|
175
|
-
* @param indexOffset - optional index offset passed to `f`
|
|
176
|
-
*/
|
|
177
|
-
export function reverseMap<T, R>(
|
|
178
|
-
array: readonly T[],
|
|
179
|
-
f: (value: T, index: number) => R,
|
|
180
|
-
indexOffset = 0
|
|
181
|
-
): R[] {
|
|
182
|
-
const result: R[] = [];
|
|
183
|
-
|
|
184
|
-
let index = indexOffset;
|
|
185
|
-
let arrayIndex = array.length;
|
|
186
|
-
let resultIndex = 0;
|
|
187
|
-
while (--arrayIndex >= 0)
|
|
188
|
-
result[resultIndex++] = f(array[arrayIndex], index++);
|
|
189
|
-
|
|
190
|
-
return result;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Internal helper to prepend a value using `toSpliced`.
|
|
195
|
-
* @internal
|
|
196
|
-
*/
|
|
197
|
-
export function _prependNew<T>(
|
|
198
|
-
array: readonly T[],
|
|
199
|
-
value: T
|
|
200
|
-
): ArrayNonEmpty<T> {
|
|
201
|
-
return array.toSpliced(0, 0, value) as ArrayNonEmpty<T>;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Internal helper to prepend a value using legacy cloning.
|
|
206
|
-
* @internal
|
|
207
|
-
*/
|
|
208
|
-
export function _prependOld<T>(
|
|
209
|
-
array: readonly T[],
|
|
210
|
-
value: T
|
|
211
|
-
): ArrayNonEmpty<T> {
|
|
212
|
-
const clone = array.slice();
|
|
213
|
-
clone.unshift(value);
|
|
214
|
-
return clone as ArrayNonEmpty<T>;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Returns a copy of the array with the given value inserted at the start.
|
|
219
|
-
* @typeparam T - element type
|
|
220
|
-
* @param array - the source array
|
|
221
|
-
* @param value - value to insert at index 0
|
|
222
|
-
*/
|
|
223
|
-
export const prepend =
|
|
224
|
-
`toSpliced` in Array.prototype ? _prependNew : _prependOld;
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Internal helper to obtain the last element using modern `at`.
|
|
228
|
-
* @internal
|
|
229
|
-
*/
|
|
230
|
-
export function _lastNew<T>(arr: readonly T[]): T {
|
|
231
|
-
return arr.at(-1)!;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Internal helper to obtain the last element using index arithmetic.
|
|
236
|
-
* @internal
|
|
237
|
-
*/
|
|
238
|
-
export function _lastOld<T>(arr: readonly T[]): T {
|
|
239
|
-
return arr[arr.length - 1];
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Returns the last element of the array.
|
|
244
|
-
* @typeparam T - element type
|
|
245
|
-
* @param arr - the array
|
|
246
|
-
*/
|
|
247
|
-
export const last = `at` in Array.prototype ? _lastNew : _lastOld;
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* Internal helper implementing an immutable index update via `with`.
|
|
251
|
-
* @internal
|
|
252
|
-
*/
|
|
253
|
-
export function _updateNew<T>(
|
|
254
|
-
arr: readonly T[],
|
|
255
|
-
index: number,
|
|
256
|
-
updater: Update<T>
|
|
257
|
-
): readonly T[] {
|
|
258
|
-
if (index < 0 || index >= arr.length) {
|
|
259
|
-
return arr;
|
|
260
|
-
}
|
|
261
|
-
const curValue = arr[index];
|
|
262
|
-
|
|
263
|
-
const newValue = Update(curValue, updater);
|
|
264
|
-
if (Object.is(newValue, curValue)) {
|
|
265
|
-
return arr;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
return arr.with(index, newValue);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Internal helper implementing an immutable index update via cloning.
|
|
273
|
-
* @internal
|
|
274
|
-
*/
|
|
275
|
-
export function _updateOld<T>(
|
|
276
|
-
arr: readonly T[],
|
|
277
|
-
index: number,
|
|
278
|
-
updater: Update<T>
|
|
279
|
-
): readonly T[] {
|
|
280
|
-
if (index < 0 || index >= arr.length) {
|
|
281
|
-
return arr;
|
|
282
|
-
}
|
|
283
|
-
const curValue = arr[index];
|
|
284
|
-
|
|
285
|
-
const newValue = Update(curValue, updater);
|
|
286
|
-
if (Object.is(newValue, curValue)) {
|
|
287
|
-
return arr;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
const newArr = arr.slice();
|
|
291
|
-
newArr[index] = newValue;
|
|
292
|
-
return newArr;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
/**
|
|
296
|
-
* Returns a copy of the array where the element at the given index is replaced using the provided updater.
|
|
297
|
-
* If the result value is identical (by `Object.is`) the original array is returned.
|
|
298
|
-
* @typeparam T - element type
|
|
299
|
-
* @param arr - the source array
|
|
300
|
-
* @param index - the index to update
|
|
301
|
-
* @param updater - value or function update description
|
|
302
|
-
*/
|
|
303
|
-
export const update = `with` in Array.prototype ? _updateNew : _updateOld;
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
* Internal helper applying a modifier function via `with`.
|
|
307
|
-
* @internal
|
|
308
|
-
*/
|
|
309
|
-
export function _modNew<T>(
|
|
310
|
-
arr: readonly T[],
|
|
311
|
-
index: number,
|
|
312
|
-
f: (value: T) => T
|
|
313
|
-
): readonly T[] {
|
|
314
|
-
if (index < 0 || index >= arr.length) {
|
|
315
|
-
return arr;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
const curValue = arr[index];
|
|
319
|
-
const newValue = f(curValue);
|
|
320
|
-
|
|
321
|
-
if (Object.is(newValue, curValue)) {
|
|
322
|
-
return arr;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
return arr.with(index, newValue);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
/**
|
|
329
|
-
* Internal helper applying a modifier function via cloning.
|
|
330
|
-
* @internal
|
|
331
|
-
*/
|
|
332
|
-
export function _modOld<T>(
|
|
333
|
-
arr: readonly T[],
|
|
334
|
-
index: number,
|
|
335
|
-
f: (value: T) => T
|
|
336
|
-
): readonly T[] {
|
|
337
|
-
if (index < 0 || index >= arr.length) {
|
|
338
|
-
return arr;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
const curValue = arr[index];
|
|
342
|
-
const newValue = f(curValue);
|
|
343
|
-
|
|
344
|
-
if (Object.is(newValue, curValue)) {
|
|
345
|
-
return arr;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
const newArr = arr.slice();
|
|
349
|
-
newArr[index] = newValue;
|
|
350
|
-
return newArr;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* Returns a copy of the array where the element at the given index is transformed by a modifier function.
|
|
355
|
-
* If the result value is identical (by `Object.is`) the original array is returned.
|
|
356
|
-
* @typeparam T - element type
|
|
357
|
-
* @param arr - the source array
|
|
358
|
-
* @param index - the index to modify
|
|
359
|
-
* @param f - modifier function receiving the current value
|
|
360
|
-
*/
|
|
361
|
-
export const mod = `with` in Array.prototype ? _modNew : _modOld;
|
|
362
|
-
|
|
363
|
-
/**
|
|
364
|
-
* Internal helper for inserting a value using `toSpliced`.
|
|
365
|
-
* @internal
|
|
366
|
-
*/
|
|
367
|
-
export function _insertNew<T>(arr: readonly T[], index: number, value: T): T[] {
|
|
368
|
-
return arr.toSpliced(index, 0, value);
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
/**
|
|
372
|
-
* Internal helper for inserting a value using legacy `splice` on a clone.
|
|
373
|
-
* @internal
|
|
374
|
-
*/
|
|
375
|
-
export function _insertOld<T>(arr: readonly T[], index: number, value: T): T[] {
|
|
376
|
-
const clone = arr.slice();
|
|
377
|
-
clone.splice(index, 0, value);
|
|
378
|
-
return clone;
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
/**
|
|
382
|
-
* Returns a copy of the array where at the given index the provided value is inserted.
|
|
383
|
-
* @typeparam T - element type
|
|
384
|
-
* @param arr - the source array
|
|
385
|
-
* @param index - insertion index
|
|
386
|
-
* @param value - value to insert
|
|
387
|
-
*/
|
|
388
|
-
export const insert = `toSpliced` in Array.prototype ? _insertNew : _insertOld;
|
|
389
|
-
|
|
390
|
-
/**
|
|
391
|
-
* Returns a copy of the array without its first element.
|
|
392
|
-
* @typeparam T - element type
|
|
393
|
-
* @param arr - the source array
|
|
394
|
-
*/
|
|
395
|
-
export function tail<T>(arr: readonly T[]): T[] {
|
|
396
|
-
return arr.slice(1);
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
/**
|
|
400
|
-
* Returns a copy of the array without its last element.
|
|
401
|
-
* @typeparam T - element type
|
|
402
|
-
* @param arr - the source array
|
|
403
|
-
*/
|
|
404
|
-
export function init<T>(arr: readonly T[]): T[] {
|
|
405
|
-
return arr.slice(0, arr.length - 1);
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
/**
|
|
409
|
-
* Internal helper providing an immutable `splice` using `toSpliced`.
|
|
410
|
-
* @internal
|
|
411
|
-
*/
|
|
412
|
-
export function _spliceNew<T>(
|
|
413
|
-
arr: readonly T[],
|
|
414
|
-
start: number,
|
|
415
|
-
deleteCount: number,
|
|
416
|
-
...items: T[]
|
|
417
|
-
): T[] {
|
|
418
|
-
return arr.toSpliced(start, deleteCount, ...items);
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
/**
|
|
422
|
-
* Internal helper providing an immutable `splice` via cloning.
|
|
423
|
-
* @internal
|
|
424
|
-
*/
|
|
425
|
-
export function _spliceOld<T>(
|
|
426
|
-
arr: readonly T[],
|
|
427
|
-
start: number,
|
|
428
|
-
deleteCount: number,
|
|
429
|
-
...items: T[]
|
|
430
|
-
): T[] {
|
|
431
|
-
const clone = arr.slice();
|
|
432
|
-
clone.splice(start, deleteCount, ...items);
|
|
433
|
-
return clone;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
/**
|
|
437
|
-
* Immutable version of the array `.splice` command, always returning a new array.
|
|
438
|
-
* @typeparam T - element type
|
|
439
|
-
* @param arr - the source array
|
|
440
|
-
* @param start - start index
|
|
441
|
-
* @param deleteCount - number of elements to delete
|
|
442
|
-
* @param items - optional items to insert
|
|
443
|
-
*/
|
|
444
|
-
export const splice = `toSpliced` in Array.prototype ? _spliceNew : _spliceOld;
|
|
445
|
-
|
|
446
|
-
/**
|
|
447
|
-
* Returns a copy of a (potentially) sparse array preserving sparsity (skips holes).
|
|
448
|
-
* @typeparam T - element type
|
|
449
|
-
* @param arr - the source sparse array
|
|
450
|
-
*/
|
|
451
|
-
export function copySparse<T>(arr: readonly T[]): T[] {
|
|
452
|
-
const clone: T[] = [];
|
|
453
|
-
for (const key in arr) {
|
|
454
|
-
clone[key] = arr[key];
|
|
455
|
-
}
|
|
456
|
-
return clone;
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
/**
|
|
460
|
-
* Returns a copy of a sparse array applying the given function to each present element, preserving holes.
|
|
461
|
-
* @typeparam T - source element type
|
|
462
|
-
* @typeparam T2 - result element type
|
|
463
|
-
* @param arr - the source sparse array
|
|
464
|
-
* @param f - mapping function
|
|
465
|
-
*/
|
|
466
|
-
export function mapSparse<T, T2>(
|
|
467
|
-
arr: readonly T[],
|
|
468
|
-
f: (value: T, index: number) => T2
|
|
469
|
-
): T2[] {
|
|
470
|
-
const result: T2[] = Array(arr.length);
|
|
471
|
-
|
|
472
|
-
for (const key in arr) {
|
|
473
|
-
result[key] = f(arr[key], key as any);
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
return result;
|
|
477
|
-
}
|
package/dist/bun/entry.mts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Returns the first element of a 2-tuple.
|
|
3
|
-
* @typeparam K - the first element type
|
|
4
|
-
* @typeparam V - the second element type
|
|
5
|
-
* @param entry - the tuple
|
|
6
|
-
* @returns the first element
|
|
7
|
-
*/
|
|
8
|
-
export function first<K, V>(entry: readonly [K, V]): K {
|
|
9
|
-
return entry[0];
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Returns the second element of a 2-tuple.
|
|
14
|
-
* @typeparam K - the first element type
|
|
15
|
-
* @typeparam V - the second element type
|
|
16
|
-
* @param entry - the tuple
|
|
17
|
-
* @returns the second element
|
|
18
|
-
*/
|
|
19
|
-
export function second<K, V>(entry: readonly [K, V]): V {
|
|
20
|
-
return entry[1];
|
|
21
|
-
}
|
package/dist/bun/index.mts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @packageDocumentation
|
|
3
|
-
*
|
|
4
|
-
* The `@rimbu/base` package provides foundational immutable array utilities, tuple helpers,
|
|
5
|
-
* plain‑object type predicates and structured error types that power all other Rimbu collections.<br/>
|
|
6
|
-
* Use it directly when you need low‑level, performance‑aware primitives for persistent data
|
|
7
|
-
* structures without pulling in the higher‑level collection packages.<br/>
|
|
8
|
-
* See the Rimbu docs and API reference for more information.
|
|
9
|
-
*/
|
|
10
|
-
export * as Arr from './arr.mts';
|
|
11
|
-
export * as Entry from './entry.mts';
|
|
12
|
-
export * as RimbuError from './rimbu-error.mts';
|
|
13
|
-
export * from './plain-object.mts';
|
|
14
|
-
|
|
15
|
-
// Internal exports (may change without notice)
|
|
16
|
-
export * from './internal.mts';
|
package/dist/bun/internal.mts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './token.mts';
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Matches any type of function
|
|
3
|
-
*/
|
|
4
|
-
export type AnyFunc = (...args: any[]) => any;
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Gives true if the given type T is a function, false otherwise.
|
|
8
|
-
* @typeparam T - the input type
|
|
9
|
-
*/
|
|
10
|
-
export type IsAnyFunc<T> = AnyFunc extends T ? true : false;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* A predicate type for any record that resolves to true if any of the record
|
|
14
|
-
* properties is a function, false otherwise.
|
|
15
|
-
* This is useful to have a coarse discrimination between pure data objects and class instances.
|
|
16
|
-
* @typeparam T - the input type
|
|
17
|
-
*/
|
|
18
|
-
export type IsObjWithoutFunctions<T> = AnyFunc extends T[keyof T]
|
|
19
|
-
? false
|
|
20
|
-
: true;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* A predicate type that resolves to true if the given type satisfies:
|
|
24
|
-
* - it is an object type (not a primitive)
|
|
25
|
-
* - it is not a function
|
|
26
|
-
* - it is not iterable
|
|
27
|
-
* - it does not have any properties that are functions
|
|
28
|
-
* Otherwise, it resolves to false
|
|
29
|
-
* @typeparam T - the input type
|
|
30
|
-
*/
|
|
31
|
-
export type IsPlainObj<T> = T extends
|
|
32
|
-
| null
|
|
33
|
-
| undefined
|
|
34
|
-
| number
|
|
35
|
-
| string
|
|
36
|
-
| boolean
|
|
37
|
-
| bigint
|
|
38
|
-
| symbol
|
|
39
|
-
| AnyFunc
|
|
40
|
-
| Iterable<any>
|
|
41
|
-
| AsyncIterable<any>
|
|
42
|
-
? false
|
|
43
|
-
: IsObjWithoutFunctions<T>;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Utility type that will only accept objects that are considered 'plain objects' according
|
|
47
|
-
* to the `IsPlainObj` predicate type.
|
|
48
|
-
* @typeparam T - the value type to test
|
|
49
|
-
*/
|
|
50
|
-
export type PlainObj<T> = IsPlainObj<T> extends true ? T : never;
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Utility type that will only return true if the input type T is equal to `any`.
|
|
54
|
-
* @typeparam T - the value type to test
|
|
55
|
-
*/
|
|
56
|
-
export type IsAny<T> = 0 extends 1 & T ? true : false;
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Utility type that will only return true if the input type T is a (readonly) array.
|
|
60
|
-
* @typeparm T - the value type to test
|
|
61
|
-
*/
|
|
62
|
-
export type IsArray<T> = T extends readonly any[] ? true : false;
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Utility type to exclude any types that are iterable. Useful in cases where
|
|
66
|
-
* plain objects are required as inputs but not arrays.
|
|
67
|
-
*/
|
|
68
|
-
export type NotIterable = {
|
|
69
|
-
[Symbol.iterator]?: never;
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Companion function to the `IsRecord<T>` type that checks whether the given object is a pure
|
|
74
|
-
* data object.
|
|
75
|
-
* @param obj - the object to check
|
|
76
|
-
* @returns true if the given object is a pure data object
|
|
77
|
-
* @note does not check whether a record's properties are not functions
|
|
78
|
-
*/
|
|
79
|
-
export function isPlainObj(obj: any): obj is object {
|
|
80
|
-
return (
|
|
81
|
-
typeof obj === 'object' &&
|
|
82
|
-
null !== obj &&
|
|
83
|
-
(obj.constructor === Object || !(obj.constructor instanceof Function)) &&
|
|
84
|
-
!(Symbol.iterator in obj) &&
|
|
85
|
-
!(Symbol.asyncIterator in obj)
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Returns true if the given object is Iterable
|
|
91
|
-
* @param obj - the object to check
|
|
92
|
-
*/
|
|
93
|
-
export function isIterable(obj: any): obj is Iterable<unknown> {
|
|
94
|
-
return obj !== null && typeof obj === 'object' && Symbol.iterator in obj;
|
|
95
|
-
}
|
package/dist/bun/rimbu-error.mts
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { ErrBase } from '@rimbu/common';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Error thrown when an operation assumes a collection is non-empty but it is empty.
|
|
5
|
-
*/
|
|
6
|
-
export class EmptyCollectionAssumedNonEmptyError extends ErrBase.CustomError {
|
|
7
|
-
constructor() {
|
|
8
|
-
super('empty collection was assumbed to be non-empty');
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Error thrown when a builder is modified while it is being iterated.
|
|
14
|
-
*/
|
|
15
|
-
export class ModifiedBuilderWhileLoopingOverItError extends ErrBase.CustomError {
|
|
16
|
-
constructor() {
|
|
17
|
-
super('an attempt was made to modify a builder while looping over it');
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Error indicating an unexpected internal state. Users are encouraged to file an issue.
|
|
23
|
-
*/
|
|
24
|
-
export class InvalidStateError extends ErrBase.CustomError {
|
|
25
|
-
constructor() {
|
|
26
|
-
super(
|
|
27
|
-
"something happend that shouldn't happen, please consider creating an issue"
|
|
28
|
-
);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Error indicating incorrect usage of the API.
|
|
34
|
-
*/
|
|
35
|
-
export class InvalidUsageError extends ErrBase.CustomError {}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Throws an `EmptyCollectionAssumedNonEmptyError`.
|
|
39
|
-
*/
|
|
40
|
-
export function throwEmptyCollectionAssumedNonEmptyError(): never {
|
|
41
|
-
throw new EmptyCollectionAssumedNonEmptyError();
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Throws a `ModifiedBuilderWhileLoopingOverItError`.
|
|
46
|
-
*/
|
|
47
|
-
export function throwModifiedBuilderWhileLoopingOverItError(): never {
|
|
48
|
-
throw new ModifiedBuilderWhileLoopingOverItError();
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Throws an `InvalidStateError`.
|
|
53
|
-
*/
|
|
54
|
-
export function throwInvalidStateError(): never {
|
|
55
|
-
throw new InvalidStateError();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Throws an `InvalidUsageError` with the provided message.
|
|
60
|
-
* @param msg - context message describing the invalid usage
|
|
61
|
-
*/
|
|
62
|
-
export function throwInvalidUsageError(msg: string): never {
|
|
63
|
-
throw new InvalidUsageError(msg);
|
|
64
|
-
}
|
package/dist/bun/token.mts
DELETED