@mark1russell7/collections 0.0.0-stage → 0.1.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 (68) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +78 -2
  3. package/build/dag/index.d.ts +144 -0
  4. package/build/dag/index.d.ts.map +1 -0
  5. package/build/dag/index.js +294 -0
  6. package/build/dag/index.js.map +1 -0
  7. package/build/graph/index.d.ts +20 -0
  8. package/build/graph/index.d.ts.map +1 -0
  9. package/build/graph/index.js +48 -0
  10. package/build/graph/index.js.map +1 -0
  11. package/build/index.d.ts +4952 -0
  12. package/build/index.d.ts.map +1 -0
  13. package/build/index.js +7811 -0
  14. package/build/index.js.map +1 -0
  15. package/build/testing/index.d.ts +25 -0
  16. package/build/testing/index.d.ts.map +1 -0
  17. package/build/testing/index.js +72 -0
  18. package/build/testing/index.js.map +1 -0
  19. package/package.json +77 -3
  20. package/src/async/async-queue.ts +481 -0
  21. package/src/async/channels.ts +450 -0
  22. package/src/async/settled.ts +41 -0
  23. package/src/behaviors/bounded.ts +485 -0
  24. package/src/behaviors/composite.ts +99 -0
  25. package/src/behaviors/evented.ts +464 -0
  26. package/src/behaviors/lru.ts +449 -0
  27. package/src/behaviors/readonly.ts +236 -0
  28. package/src/behaviors/safe.ts +358 -0
  29. package/src/behaviors/synchronized.ts +316 -0
  30. package/src/behaviors/ttl.ts +464 -0
  31. package/src/core/effects.ts +327 -0
  32. package/src/core/events.ts +363 -0
  33. package/src/core/middleware.ts +413 -0
  34. package/src/core/policies.ts +316 -0
  35. package/src/core/traits.ts +164 -0
  36. package/src/dag/builder.ts +124 -0
  37. package/src/dag/executor.ts +190 -0
  38. package/src/dag/index.ts +14 -0
  39. package/src/dag/traversal.ts +129 -0
  40. package/src/dag/types.ts +87 -0
  41. package/src/fx/collectors.ts +500 -0
  42. package/src/fx/iter.ts +536 -0
  43. package/src/graph/hub-order.ts +53 -0
  44. package/src/graph/index.ts +5 -0
  45. package/src/impl/array-deque.ts +463 -0
  46. package/src/impl/array-list.ts +490 -0
  47. package/src/impl/hash-map.ts +623 -0
  48. package/src/impl/hash-set.ts +342 -0
  49. package/src/impl/linked-hash-map.ts +572 -0
  50. package/src/impl/linked-list.ts +610 -0
  51. package/src/impl/priority-queue.ts +448 -0
  52. package/src/impl/summary-tree.ts +594 -0
  53. package/src/impl/tree-map.ts +913 -0
  54. package/src/impl/tree-set.ts +469 -0
  55. package/src/index.ts +237 -0
  56. package/src/interfaces/collection.ts +141 -0
  57. package/src/interfaces/list.ts +281 -0
  58. package/src/interfaces/map.ts +405 -0
  59. package/src/interfaces/queue.ts +353 -0
  60. package/src/interfaces/set.ts +158 -0
  61. package/src/order/index.ts +6 -0
  62. package/src/order/rank.ts +271 -0
  63. package/src/storage/listeners.ts +72 -0
  64. package/src/testing/check.ts +81 -0
  65. package/src/testing/index.ts +7 -0
  66. package/src/utils/defaults.ts +345 -0
  67. package/src/utils/factories.ts +357 -0
  68. package/src/utils/helpers.ts +248 -0
@@ -0,0 +1,469 @@
1
+ /**
2
+ * TreeSet - Red-black tree based sorted set implementation.
3
+ *
4
+ * This module implements a sorted set using TreeMap as the backing structure.
5
+ * Mirrors java.util.TreeSet.
6
+ *
7
+ * Key features:
8
+ * - O(log n) add, remove, contains
9
+ * - Elements maintained in sorted order (natural or custom comparator)
10
+ * - Navigation methods (floor, ceiling, lower, higher)
11
+ * - Range view operations (subSet, headSet, tailSet)
12
+ *
13
+ * @example
14
+ * const set = treeSet<string>()
15
+ * set.add('c')
16
+ * set.add('a')
17
+ * set.add('b')
18
+ * // Iteration order: a, b, c (sorted)
19
+ *
20
+ * @example
21
+ * // Custom comparator for descending order
22
+ * const set = treeSet<number>({
23
+ * compare: (a, b) => b - a
24
+ * })
25
+ */
26
+
27
+ import type { SortedSet, NavigableSet } from "../interfaces/set.js";
28
+ import type { Eq, Compare } from "../core/traits.js";
29
+ import { TreeMap } from "./tree-map.js";
30
+ import { defaultEq, defaultCompare } from "../utils/defaults.js";
31
+
32
+ /**
33
+ * Dummy value used for TreeMap backing.
34
+ */
35
+ const PRESENT = true;
36
+
37
+ /**
38
+ * Options for making a TreeSet.
39
+ */
40
+ export interface TreeSetOptions<T> {
41
+ /**
42
+ * Comparison function for elements.
43
+ * @default defaultCompare
44
+ */
45
+ compare?: Compare<T>;
46
+
47
+ /**
48
+ * Equality function for elements.
49
+ * @default defaultEq
50
+ */
51
+ eq?: Eq<T>;
52
+ }
53
+
54
+ /**
55
+ * TreeSet<T> - Red-black tree based sorted set.
56
+ *
57
+ * Maintains elements in sorted order using a TreeMap as backing structure.
58
+ * This class gives O(log n) operations and navigation methods.
59
+ */
60
+ export class TreeSet<T> implements NavigableSet<T> {
61
+ private readonly _map: TreeMap<T, boolean>;
62
+ private readonly _compare: Compare<T>;
63
+ private readonly _eq: Eq<T>;
64
+
65
+ constructor(options: TreeSetOptions<T> = {}) {
66
+ const {
67
+ compare = defaultCompare,
68
+ eq = defaultEq,
69
+ } = options;
70
+
71
+ this._compare = compare;
72
+ this._eq = eq;
73
+ this._map = new TreeMap<T, boolean>({
74
+ compare,
75
+ eq,
76
+ });
77
+ }
78
+
79
+ // ========================================================================
80
+ // Size and state
81
+ // ========================================================================
82
+
83
+ get size(): number {
84
+ return this._map.size;
85
+ }
86
+
87
+ get isEmpty(): boolean {
88
+ return this._map.isEmpty;
89
+ }
90
+
91
+ get comparator(): Compare<T> {
92
+ return this._compare;
93
+ }
94
+
95
+ get eq(): Eq<T> {
96
+ return this._eq;
97
+ }
98
+
99
+ // ========================================================================
100
+ // Membership operations
101
+ // ========================================================================
102
+
103
+ has(element: T): boolean {
104
+ return this._map.has(element);
105
+ }
106
+
107
+ contains(element: T): boolean {
108
+ return this.has(element);
109
+ }
110
+
111
+ containsAll(other: Iterable<T>): boolean {
112
+ for (const element of other) {
113
+ if (!this.has(element)) {
114
+ return false;
115
+ }
116
+ }
117
+ return true;
118
+ }
119
+
120
+ // ========================================================================
121
+ // Modification operations
122
+ // ========================================================================
123
+
124
+ add(element: T): boolean {
125
+ const oldValue = this._map.set(element, PRESENT);
126
+ return oldValue === undefined; // Returns true if element was added (not already present)
127
+ }
128
+
129
+ remove(element: T): boolean {
130
+ const removed = this._map.delete(element);
131
+ return removed !== undefined;
132
+ }
133
+
134
+ clear(): void {
135
+ this._map.clear();
136
+ }
137
+
138
+ // ========================================================================
139
+ // Bulk operations
140
+ // ========================================================================
141
+
142
+ addAll(elements: Iterable<T>): boolean {
143
+ let modified = false;
144
+ for (const element of elements) {
145
+ if (this.add(element)) {
146
+ modified = true;
147
+ }
148
+ }
149
+ return modified;
150
+ }
151
+
152
+ removeAll(elements: Iterable<T>): boolean {
153
+ let modified = false;
154
+ for (const element of elements) {
155
+ if (this.remove(element)) {
156
+ modified = true;
157
+ }
158
+ }
159
+ return modified;
160
+ }
161
+
162
+ retainAll(elements: Iterable<T>): boolean {
163
+ const toRetain = new Set<T>();
164
+ for (const element of elements) {
165
+ toRetain.add(element);
166
+ }
167
+
168
+ let modified = false;
169
+ for (const element of Array.from(this)) {
170
+ if (!toRetain.has(element)) {
171
+ this.remove(element);
172
+ modified = true;
173
+ }
174
+ }
175
+ return modified;
176
+ }
177
+
178
+ // ========================================================================
179
+ // Set operations
180
+ // ========================================================================
181
+
182
+ union(other: Iterable<T>): TreeSet<T> {
183
+ const result = new TreeSet<T>({
184
+ compare: this._compare,
185
+ eq: this._eq,
186
+ });
187
+
188
+ for (const element of this) {
189
+ result.add(element);
190
+ }
191
+ for (const element of other) {
192
+ result.add(element);
193
+ }
194
+
195
+ return result;
196
+ }
197
+
198
+ intersection(other: Iterable<T>): TreeSet<T> {
199
+ const result = new TreeSet<T>({
200
+ compare: this._compare,
201
+ eq: this._eq,
202
+ });
203
+
204
+ const otherSet = new Set<T>();
205
+ for (const element of other) {
206
+ otherSet.add(element);
207
+ }
208
+
209
+ for (const element of this) {
210
+ if (otherSet.has(element)) {
211
+ result.add(element);
212
+ }
213
+ }
214
+
215
+ return result;
216
+ }
217
+
218
+ difference(other: Iterable<T>): TreeSet<T> {
219
+ const result = new TreeSet<T>({
220
+ compare: this._compare,
221
+ eq: this._eq,
222
+ });
223
+
224
+ const otherSet = new Set<T>();
225
+ for (const element of other) {
226
+ otherSet.add(element);
227
+ }
228
+
229
+ for (const element of this) {
230
+ if (!otherSet.has(element)) {
231
+ result.add(element);
232
+ }
233
+ }
234
+
235
+ return result;
236
+ }
237
+
238
+ symmetricDifference(other: Iterable<T>): TreeSet<T> {
239
+ const result = new TreeSet<T>({
240
+ compare: this._compare,
241
+ eq: this._eq,
242
+ });
243
+
244
+ // Add all elements from this set
245
+ for (const element of this) {
246
+ result.add(element);
247
+ }
248
+
249
+ // Toggle elements from other set
250
+ for (const element of other) {
251
+ if (result.has(element)) {
252
+ result.remove(element);
253
+ } else {
254
+ result.add(element);
255
+ }
256
+ }
257
+
258
+ return result;
259
+ }
260
+
261
+ isSubsetOf(other: Iterable<T>): boolean {
262
+ const otherSet = new Set<T>();
263
+ for (const element of other) {
264
+ otherSet.add(element);
265
+ }
266
+
267
+ for (const element of this) {
268
+ if (!otherSet.has(element)) {
269
+ return false;
270
+ }
271
+ }
272
+ return true;
273
+ }
274
+
275
+ isSupersetOf(other: Iterable<T>): boolean {
276
+ for (const element of other) {
277
+ if (!this.has(element)) {
278
+ return false;
279
+ }
280
+ }
281
+ return true;
282
+ }
283
+
284
+ isDisjointFrom(other: Iterable<T>): boolean {
285
+ for (const element of other) {
286
+ if (this.has(element)) {
287
+ return false;
288
+ }
289
+ }
290
+ return true;
291
+ }
292
+
293
+ // ========================================================================
294
+ // SortedSet operations
295
+ // ========================================================================
296
+
297
+ first(): T {
298
+ const key = this._map.firstKey();
299
+ return key;
300
+ }
301
+
302
+ last(): T {
303
+ const key = this._map.lastKey();
304
+ return key;
305
+ }
306
+
307
+ headSet(toElement: T): SortedSet<T> {
308
+ const result = new TreeSet<T>({
309
+ compare: this._compare,
310
+ eq: this._eq,
311
+ });
312
+
313
+ for (const element of this) {
314
+ if (this._compare(element, toElement) < 0) {
315
+ result.add(element);
316
+ } else {
317
+ break; // Elements are sorted
318
+ }
319
+ }
320
+
321
+ return result;
322
+ }
323
+
324
+ tailSet(fromElement: T): SortedSet<T> {
325
+ const result = new TreeSet<T>({
326
+ compare: this._compare,
327
+ eq: this._eq,
328
+ });
329
+
330
+ let started = false;
331
+ for (const element of this) {
332
+ if (!started && this._compare(element, fromElement) < 0) {
333
+ continue;
334
+ }
335
+ started = true;
336
+ result.add(element);
337
+ }
338
+
339
+ return result;
340
+ }
341
+
342
+ subSet(fromElement: T, toElement: T): SortedSet<T> {
343
+ const result = new TreeSet<T>({
344
+ compare: this._compare,
345
+ eq: this._eq,
346
+ });
347
+
348
+ for (const element of this) {
349
+ const cmpFrom = this._compare(element, fromElement);
350
+ const cmpTo = this._compare(element, toElement);
351
+
352
+ if (cmpFrom >= 0 && cmpTo < 0) {
353
+ result.add(element);
354
+ } else if (cmpTo >= 0) {
355
+ break; // Past the range
356
+ }
357
+ }
358
+
359
+ return result;
360
+ }
361
+
362
+ // ========================================================================
363
+ // NavigableSet operations
364
+ // ========================================================================
365
+
366
+ floor(element: T): T | undefined {
367
+ return this._map.floorKey(element);
368
+ }
369
+
370
+ ceiling(element: T): T | undefined {
371
+ return this._map.ceilingKey(element);
372
+ }
373
+
374
+ lower(element: T): T | undefined {
375
+ return this._map.lowerKey(element);
376
+ }
377
+
378
+ higher(element: T): T | undefined {
379
+ return this._map.higherKey(element);
380
+ }
381
+
382
+ pollFirst(): T | undefined {
383
+ const entry = this._map.pollFirstEntry();
384
+ return entry?.key;
385
+ }
386
+
387
+ pollLast(): T | undefined {
388
+ const entry = this._map.pollLastEntry();
389
+ return entry?.key;
390
+ }
391
+
392
+ descendingSet(): NavigableSet<T> {
393
+ const reversed = new TreeSet<T>({
394
+ compare: (a, b) => this._compare(b, a),
395
+ eq: this._eq,
396
+ });
397
+
398
+ for (const element of this) {
399
+ reversed.add(element);
400
+ }
401
+
402
+ return reversed;
403
+ }
404
+
405
+ *descendingIterator(): IterableIterator<T> {
406
+ yield* this._map.descendingKeys();
407
+ }
408
+
409
+ // ========================================================================
410
+ // View operations
411
+ // ========================================================================
412
+
413
+ *[Symbol.iterator](): Iterator<T> {
414
+ yield* this._map.keys();
415
+ }
416
+
417
+ forEach(action: (element: T, index: number) => void): void {
418
+ let index = 0;
419
+ for (const element of this) {
420
+ action(element, index++);
421
+ }
422
+ }
423
+
424
+ toArray(): T[] {
425
+ return Array.from(this);
426
+ }
427
+
428
+ // ========================================================================
429
+ // Utility methods
430
+ // ========================================================================
431
+
432
+ toString(): string {
433
+ const elements = Array.from(this).join(', ');
434
+ return `TreeSet{${elements}}`;
435
+ }
436
+ }
437
+
438
+ /**
439
+ * Factory function to make a TreeSet.
440
+ *
441
+ * @example
442
+ * const set = treeSet<string>()
443
+ * set.add('c')
444
+ * set.add('a')
445
+ * set.add('b')
446
+ * // Iteration order: a, b, c
447
+ *
448
+ * @example
449
+ * // With initial elements
450
+ * const set = treeSet(['c', 'a', 'b'])
451
+ * // Iteration order: a, b, c
452
+ *
453
+ * @example
454
+ * // Custom comparator for descending order
455
+ * const set = treeSet<number>({ compare: (a, b) => b - a })
456
+ */
457
+ export function treeSet<T>(
458
+ optionsOrElements?: TreeSetOptions<T> | Iterable<T>
459
+ ): TreeSet<T> {
460
+ if (optionsOrElements && Symbol.iterator in optionsOrElements) {
461
+ const set = new TreeSet<T>();
462
+ for (const element of optionsOrElements as Iterable<T>) {
463
+ set.add(element);
464
+ }
465
+ return set;
466
+ }
467
+
468
+ return new TreeSet<T>(optionsOrElements as TreeSetOptions<T>);
469
+ }
package/src/index.ts ADDED
@@ -0,0 +1,237 @@
1
+ /**
2
+ * `@mark1russell7/collections`: collections with no dependencies.
3
+ *
4
+ * This entry gives the lists, sets, maps, queues, the summary tree, the behaviors, the channels and the lazy
5
+ * operations. The entries `./dag` and `./graph` give the graph code. The entry `./testing` gives the checks.
6
+ */
7
+
8
+ // ============================================================================
9
+ // Core types and utilities
10
+ // ============================================================================
11
+
12
+ export * from "./core/traits.js";
13
+ export * from "./core/effects.js";
14
+ export * from "./core/policies.js";
15
+ export * from "./core/middleware.js";
16
+ export * from "./core/events.js";
17
+ // ============================================================================
18
+ // Interfaces
19
+ // ============================================================================
20
+
21
+ export * from "./interfaces/collection.js";
22
+ export * from "./interfaces/list.js";
23
+ export * from "./interfaces/map.js";
24
+ export * from "./interfaces/set.js";
25
+
26
+ // The listeners of a storage
27
+ export { StorageListeners, reportListenerError, type ListenerErrorHandler } from "./storage/listeners.js";
28
+
29
+ // The order of a list as data: a rank between two neighbors, and the index of a drop
30
+ export * from "./order/index.js";
31
+
32
+ // Export queue interfaces with disambiguation for PriorityQueue
33
+ export type {
34
+ ReadonlyQueue,
35
+ Queue,
36
+ Deque,
37
+ BlockingQueue,
38
+ PriorityQueue as IPriorityQueue,
39
+ AsyncQueue as IAsyncQueue,
40
+ TransferQueue,
41
+ DelayQueue,
42
+ } from "./interfaces/queue.js";
43
+
44
+ // ============================================================================
45
+ // Implementations
46
+ // ============================================================================
47
+
48
+ export * from "./impl/array-list.js";
49
+ export * from "./impl/array-deque.js";
50
+ export * from "./impl/hash-map.js";
51
+ export * from "./impl/linked-hash-map.js";
52
+ export * from "./impl/tree-map.js";
53
+ export * from "./impl/tree-set.js";
54
+ export * from "./impl/linked-list.js";
55
+ export * from "./impl/hash-set.js";
56
+ export * from "./impl/priority-queue.js";
57
+ export { SummaryTree, summaryTree, type SummaryLocation, type SummaryMonoid, type SummarySearch, type SummarySpec } from "./impl/summary-tree.js";
58
+
59
+ // ============================================================================
60
+ // Behaviors
61
+ // ============================================================================
62
+
63
+ // Export bounded behaviors (excluding duplicate BoundedCollection interface)
64
+ export {
65
+ type BoundedOptions,
66
+ boundedList,
67
+ boundedQueue,
68
+ boundedDeque,
69
+ boundedMap,
70
+ bounded,
71
+ } from "./behaviors/bounded.js";
72
+
73
+ export * from "./behaviors/readonly.js";
74
+ export * from "./behaviors/safe.js";
75
+ export * from "./behaviors/evented.js";
76
+ export * from "./behaviors/synchronized.js";
77
+ export * from "./behaviors/lru.js";
78
+ export * from "./behaviors/ttl.js";
79
+
80
+ // ============================================================================
81
+ // Async/Concurrent
82
+ // ============================================================================
83
+
84
+ export * from "./async/async-queue.js";
85
+ export * from "./async/channels.js";
86
+ export * from "./async/settled.js";
87
+
88
+ // ============================================================================
89
+ // Functional Operations
90
+ // ============================================================================
91
+
92
+ export * from "./fx/iter.js";
93
+ export * from "./fx/collectors.js";
94
+
95
+ // ============================================================================
96
+ // Utilities
97
+ // ============================================================================
98
+
99
+ export * from "./utils/defaults.js";
100
+ export * from "./utils/factories.js";
101
+ export * from "./utils/helpers.js";
102
+
103
+ // ============================================================================
104
+ // Re-exports for convenience
105
+ // ============================================================================
106
+
107
+ // Most commonly used exports
108
+ export { compose, bundle } from "./core/middleware.js";
109
+ export { arrayList } from "./impl/array-list.js";
110
+ export { arrayDeque } from "./impl/array-deque.js";
111
+ export { hashMap } from "./impl/hash-map.js";
112
+ export { linkedHashMap } from "./impl/linked-hash-map.js";
113
+ export { treeMap } from "./impl/tree-map.js";
114
+ export { treeSet } from "./impl/tree-set.js";
115
+ export { linkedList } from "./impl/linked-list.js";
116
+ export { hashSet } from "./impl/hash-set.js";
117
+ export { priorityQueue } from "./impl/priority-queue.js";
118
+ // Common behaviors
119
+ export { readonly, readonlyList, readonlyMap } from "./behaviors/readonly.js";
120
+ export { safeList, safeQueue, safeMap } from "./behaviors/safe.js";
121
+ export { eventedList, eventedQueue, eventedMap } from "./behaviors/evented.js";
122
+ export { synchronized } from "./behaviors/synchronized.js";
123
+ export { lruMap, lruCache, LRUCache } from "./behaviors/lru.js";
124
+ export { ttlMap, ttlCache, TTLCache, ttlCollection } from "./behaviors/ttl.js";
125
+
126
+ // Async/Concurrent
127
+ export { asyncQueue, AsyncQueue } from "./async/async-queue.js";
128
+ export { asSettled, type Settled } from "./async/settled.js";
129
+ export {
130
+ channel,
131
+ Channel,
132
+ select,
133
+ timeout,
134
+ ticker,
135
+ pipeline,
136
+ fanOut,
137
+ fanIn,
138
+ merge,
139
+ workerPool,
140
+ } from "./async/channels.js";
141
+
142
+ // Functional operations
143
+ export {
144
+ map,
145
+ filter,
146
+ flatMap,
147
+ flatten,
148
+ take,
149
+ skip,
150
+ takeWhile,
151
+ skipWhile,
152
+ concat,
153
+ zip,
154
+ enumerate,
155
+ chunk,
156
+ window,
157
+ partition,
158
+ reduce,
159
+ scan,
160
+ sort,
161
+ reverse,
162
+ distinct,
163
+ distinctConsecutive,
164
+ tap,
165
+ some,
166
+ every,
167
+ none,
168
+ find,
169
+ count,
170
+ min,
171
+ max,
172
+ sum,
173
+ average,
174
+ toArray,
175
+ toSet,
176
+ toMap as iterToMap,
177
+ pipe,
178
+ } from "./fx/iter.js";
179
+
180
+ export {
181
+ collect,
182
+ toList as collectToList,
183
+ toArray as collectToArray,
184
+ toSet as collectToSet,
185
+ toMap as collectToMap,
186
+ groupingBy,
187
+ groupingByWith,
188
+ partitioningBy,
189
+ counting,
190
+ summingNumber,
191
+ averagingNumber,
192
+ minBy,
193
+ maxBy,
194
+ joining,
195
+ mapping,
196
+ filtering,
197
+ flatMapping,
198
+ reducing,
199
+ reducingWith,
200
+ teeing,
201
+ first,
202
+ last,
203
+ summarizingNumber,
204
+ } from "./fx/collectors.js";
205
+
206
+ // Common factories
207
+ export {
208
+ emptyList,
209
+ emptyMap,
210
+ emptyQueue,
211
+ singletonList,
212
+ singletonMap,
213
+ nCopies,
214
+ listOf,
215
+ mapOf,
216
+ range,
217
+ rangeTo,
218
+ toList,
219
+ toMap,
220
+ groupBy,
221
+ } from "./utils/factories.js";
222
+
223
+ // Effects
224
+ export {
225
+ None,
226
+ Some,
227
+ type Option,
228
+ Ok,
229
+ Err,
230
+ type Result,
231
+ isSome,
232
+ isNone,
233
+ isOk,
234
+ isErr,
235
+ getOrElse,
236
+ unwrap,
237
+ } from "./core/effects.js";