@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 CHANGED
@@ -6,7 +6,6 @@
6
6
  ![License](https://img.shields.io/github/license/rimbu-org/rimbu)
7
7
  ![Types Included](https://img.shields.io/badge/TypeScript-ready-blue)
8
8
  ![Node](https://img.shields.io/badge/Node-18+-6DA55F?logo=node.js&logoColor=white)
9
- ![Deno](https://shield.deno.dev/x/rimbu)
10
9
  ![Bun](https://img.shields.io/badge/Bun-%23000000.svg)
11
10
  ![ESM + CJS](https://img.shields.io/badge/modules-ESM%20%2B%20CJS-informational)
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 | Purpose |
101
- | -------- | ------- |
102
- | `append` | Add element at end (non-empty array optimization). |
103
- | `prepend` | Add element at start efficiently. |
104
- | `concat` | Smart concat – reuses original when one side empty. |
105
- | `reverse` | Fast reversed copy (range slice optional). |
106
- | `forEach` | Controlled traversal with optional reverse + halt state. |
107
- | `map` / `reverseMap` | Indexed transformation forward or backward. |
108
- | `last` | O(1) last element access (uses `.at(-1)` when available). |
109
- | `update` | Apply `Update<T>` logic at index (no-op preserved). |
110
- | `mod` | Lightweight element modification via `(value)=>value'`. |
111
- | `insert` | Insert at index. |
112
- | `tail` / `init` | Drop first / last element. |
113
- | `splice` | Immutable variant of native splice. |
114
- | `copySparse` | Preserve holes in sparse arrays. |
115
- | `mapSparse` | Transform only present indices, keeping sparsity. |
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) { /* special branch */ }
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 | Description |
145
- | ---- | ----------- |
146
- | `IsPlainObj<T>` | True only for non-iterable, non-function object types without function properties. |
147
- | `PlainObj<T>` | Narrows to T if `IsPlainObj<T>`; otherwise `never`. |
148
- | `IsArray<T>` | Resolves to `true` if T is a (readonly) array type. |
149
- | `IsAny<T>` | Detects `any`. |
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 | Trigger Scenario |
162
- | ----------- | ---------------- |
163
- | `EmptyCollectionAssumedNonEmptyError` | An operation expected a non-empty collection. |
164
- | `ModifiedBuilderWhileLoopingOverItError` | Mutating a builder mid-iteration. |
165
- | `InvalidStateError` | Internal invariant breach (should not happen). |
166
- | `InvalidUsageError` | Consumer used an API incorrectly. |
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` ![NodeJS](https://img.shields.io/badge/node.js-6DA55F?logo=node.js&logoColor=white)](https://nodejs.org)
177
- - [`Deno` ![Deno JS](https://img.shields.io/badge/deno%20js-000000?logo=deno&logoColor=white)](https://deno.com/runtime)
178
178
  - [`Bun` ![Bun](https://img.shields.io/badge/Bun-%23000000.svg?logoColor=white)](https://bun.sh/)
179
179
  - `Web` ![HTML5](https://img.shields.io/badge/html5-%23E34F26.svg?logoColor=white)
180
180
 
@@ -198,37 +198,12 @@ npm install @rimbu/base
198
198
  bun add @rimbu/base
199
199
  ```
200
200
 
201
- ### Deno Setup
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
- In this way you can use relative imports from Rimbu in your code, like so:
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",
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
- "build:deno": "yarn bundle:deno-prepare && yarn bundle:deno-convert && yarn bundle:deno-move && yarn bundle:deno-clean",
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.3"
69
+ "@rimbu/common": "^2.0.5"
77
70
  },
78
71
  "publishConfig": {
79
72
  "access": "public"
80
73
  },
81
- "gitHead": "1c35dbdd9ce13aeba818b41eb20bab1e826b3e16"
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
- }
@@ -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
- }
@@ -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';
@@ -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
- }
@@ -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
- }
@@ -1,9 +0,0 @@
1
- /**
2
- * Unique symbol used as a nominal token within the base package.
3
- * Can be employed for branding or sentinel values.
4
- */
5
- export const Token = Symbol('Token');
6
- /**
7
- * Type alias representing the Token symbol.
8
- */
9
- export type Token = typeof Token;