@mark1russell7/collections 0.0.0-bootstrap.0 → 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 +77 -1
  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 +71 -4
  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,413 @@
1
+ /**
2
+ * Middleware composition system for collections.
3
+ *
4
+ * This module gives the core composition mechanism. With it, behaviors go in layers
5
+ * on top of collections with the decorator pattern.
6
+ *
7
+ * The mechanism is for synchronous collection operations. The collection instance itself
8
+ * is the context, so a behavior needs no explicit context object.
9
+ *
10
+ * @example
11
+ * const list = compose(
12
+ * safeList(),
13
+ * eventedList(),
14
+ * boundedList({ capacity: 100 })
15
+ * )(arrayList<number>())
16
+ */
17
+
18
+ import type { Collection } from "../interfaces/collection.js";
19
+
20
+ /**
21
+ * A middleware is a function that takes a collection and gives
22
+ * an enhanced version of that collection.
23
+ *
24
+ * This maps to the unified middleware pattern where:
25
+ * - The "context" is the collection itself (passed directly, not in a context object)
26
+ * - Execution is synchronous (no Promises)
27
+ * - Type transformation is tracked through In -> Out
28
+ *
29
+ * Middleware can:
30
+ * - Intercept method calls
31
+ * - Add new capabilities
32
+ * - Transform inputs/outputs
33
+ * - Delegate to the next layer
34
+ *
35
+ * @template In The input collection type
36
+ * @template Out The output collection type (defaults to In if not specified)
37
+ */
38
+ export type Middleware<In = any, Out extends In = In> = (next: In) => Out;
39
+
40
+ /**
41
+ * Composes multiple middleware layers into a single enhancer function.
42
+ *
43
+ * This function uses reduceRight to make an "onion" pattern where the first middleware
44
+ * is the outermost layer (runs first when calling into the collection).
45
+ *
46
+ * The type system properly tracks capability additions through composition.
47
+ *
48
+ * @example
49
+ * // Layer order (outer to inner):
50
+ * // 1. safe - converts throws to Option/Result
51
+ * // 2. evented - emits events on mutations
52
+ * // 3. bounded - enforces capacity limits
53
+ * // 4. base - the underlying ArrayList
54
+ * const enhancer = compose(
55
+ * safeList(),
56
+ * eventedList(),
57
+ * boundedList({ capacity: 100 })
58
+ * )
59
+ * const list = enhancer(arrayList<number>())
60
+ * // Type: List<number> & SafeCollection & EventedCollection & BoundedCollection
61
+ *
62
+ * @param layers The middleware layers to compose
63
+ * @returns A function that applies all layers to a base collection
64
+ */
65
+
66
+ // Overload for 1 middleware
67
+ export function compose<C, R1 extends C>(
68
+ m1: Middleware<C, R1>
69
+ ): (base: C) => R1;
70
+
71
+ // Overload for 2 middleware
72
+ export function compose<C, R1 extends C, R2 extends R1>(
73
+ m1: Middleware<R1, R2>,
74
+ m2: Middleware<C, R1>
75
+ ): (base: C) => R2;
76
+
77
+ // Overload for 3 middleware
78
+ export function compose<C, R1 extends C, R2 extends R1, R3 extends R2>(
79
+ m1: Middleware<R2, R3>,
80
+ m2: Middleware<R1, R2>,
81
+ m3: Middleware<C, R1>
82
+ ): (base: C) => R3;
83
+
84
+ // Overload for 4 middleware
85
+ export function compose<C, R1 extends C, R2 extends R1, R3 extends R2, R4 extends R3>(
86
+ m1: Middleware<R3, R4>,
87
+ m2: Middleware<R2, R3>,
88
+ m3: Middleware<R1, R2>,
89
+ m4: Middleware<C, R1>
90
+ ): (base: C) => R4;
91
+
92
+ // Overload for 5 middleware
93
+ export function compose<C, R1 extends C, R2 extends R1, R3 extends R2, R4 extends R3, R5 extends R4>(
94
+ m1: Middleware<R4, R5>,
95
+ m2: Middleware<R3, R4>,
96
+ m3: Middleware<R2, R3>,
97
+ m4: Middleware<R1, R2>,
98
+ m5: Middleware<C, R1>
99
+ ): (base: C) => R5;
100
+
101
+ // General fallback for any number of middleware
102
+ export function compose<C>(...layers: Middleware<any, any>[]): (base: C) => any;
103
+
104
+ // Implementation
105
+ export function compose(...layers: Middleware<any, any>[]) {
106
+ return (base: any): any =>
107
+ layers.reduceRight((acc, layer) => layer(acc), base);
108
+ }
109
+
110
+ /**
111
+ * Utility to check if a collection has a specific capability.
112
+ * Useful for middleware that wants to conditionally enhance behavior.
113
+ *
114
+ * @example
115
+ * if (hasCapability(collection, 'on')) {
116
+ * // Collection supports events
117
+ * collection.on('add', handler)
118
+ * }
119
+ */
120
+ export const hasCapability = <C extends Collection<any>, K extends keyof any>(
121
+ collection: C,
122
+ capability: K
123
+ ): collection is C & Record<K, unknown> => {
124
+ return capability in collection;
125
+ };
126
+
127
+ /**
128
+ * Marker interface for collections that support events.
129
+ * Middleware can use this to detect event capability.
130
+ */
131
+ export interface Evented<E extends Record<string, any>> {
132
+ /**
133
+ * Subscribe to an event.
134
+ * @returns Unsubscribe function
135
+ */
136
+ on<K extends keyof E>(event: K, handler: (payload: E[K]) => void): () => void;
137
+
138
+ /**
139
+ * Emit an event (internal use by middleware).
140
+ * @internal
141
+ */
142
+ emit?<K extends keyof E>(event: K, payload: E[K]): void;
143
+ }
144
+
145
+ /**
146
+ * Marker interface for collections that support async operations.
147
+ */
148
+ export interface Async<T> {
149
+ /**
150
+ * Async iterator for consuming elements.
151
+ */
152
+ [Symbol.asyncIterator](): AsyncIterator<T>;
153
+ }
154
+
155
+ /**
156
+ * Marker interface for collections that are bounded.
157
+ */
158
+ export interface BoundedCollection {
159
+ /** Maximum capacity */
160
+ readonly capacity: number;
161
+ /** If collection is at capacity */
162
+ readonly isFull: boolean;
163
+ /** Remaining space */
164
+ readonly remainingCapacity: number;
165
+ }
166
+
167
+ /**
168
+ * Marker interface for collections that support safe (Option/Result) operations.
169
+ */
170
+ export interface SafeCollection {
171
+ /**
172
+ * Namespace for safe operations that return Option/Result instead of throwing.
173
+ */
174
+ readonly safe: unknown;
175
+ }
176
+
177
+ /**
178
+ * Type helper to extract the element type from a collection.
179
+ */
180
+ export type ElementType<C> = C extends {
181
+ [Symbol.iterator](): Iterator<infer T>;
182
+ }
183
+ ? T
184
+ : C extends { get(index: number): infer T }
185
+ ? T
186
+ : C extends { peek(): infer T }
187
+ ? T
188
+ : never;
189
+
190
+ /**
191
+ * Type helper to make all methods of a type return their async equivalents.
192
+ */
193
+ export type Asyncify<C> = {
194
+ [K in keyof C]: C[K] extends (...args: infer Args) => infer R
195
+ ? (...args: Args) => Promise<R>
196
+ : C[K];
197
+ };
198
+
199
+ /**
200
+ * Helper to make a proxy that intercepts method calls.
201
+ * Useful for implementing middleware that needs to wrap method invocations.
202
+ *
203
+ * @example
204
+ * const logged = interceptMethods(collection, (target, method, args) => {
205
+ * console.log(`Calling ${String(method)} with`, args)
206
+ * const result = Reflect.apply(target[method], target, args)
207
+ * console.log(`Result:`, result)
208
+ * return result
209
+ * })
210
+ */
211
+ export const interceptMethods = <C extends object>(
212
+ target: C,
213
+ interceptor: (target: C, method: keyof C, args: unknown[]) => unknown
214
+ ): C => {
215
+ return new Proxy(target, {
216
+ get(t, prop, receiver) {
217
+ const value = Reflect.get(t, prop, receiver);
218
+ if (typeof value === "function" && typeof prop === "string") {
219
+ return function (this: unknown, ...args: unknown[]) {
220
+ return interceptor(t, prop as keyof C, args);
221
+ };
222
+ }
223
+ return value;
224
+ },
225
+ });
226
+ };
227
+
228
+ /**
229
+ * Helper to make a readonly view of a collection by blocking mutating methods.
230
+ *
231
+ * @param mutatingMethods Set of method names that the middleware blocks
232
+ * @param errorMessage Custom error message to throw
233
+ */
234
+ export const blockMethods = <C extends object>(
235
+ target: C,
236
+ mutatingMethods: Set<string | symbol>,
237
+ errorMessage: string = "Operation not allowed"
238
+ ): C => {
239
+ return new Proxy(target, {
240
+ get(t, prop, receiver) {
241
+ const value = Reflect.get(t, prop, receiver);
242
+ if (typeof value === "function" && mutatingMethods.has(prop)) {
243
+ return () => {
244
+ throw new Error(errorMessage);
245
+ };
246
+ }
247
+ return value;
248
+ },
249
+ });
250
+ };
251
+
252
+ /**
253
+ * Helper to delegate method calls to a target while maintaining correct context.
254
+ * Useful when wrapping collections.
255
+ */
256
+ export const delegate = <C extends object, T extends C>(
257
+ target: T,
258
+ wrapper: Partial<C>
259
+ ): C => {
260
+ return new Proxy(target, {
261
+ get(t, prop, receiver) {
262
+ // If wrapper has the property, use it
263
+ if (prop in wrapper) {
264
+ return Reflect.get(wrapper, prop, receiver);
265
+ }
266
+ // Otherwise delegate to target
267
+ const value = Reflect.get(t, prop, receiver);
268
+ // Bind methods to maintain correct 'this' context
269
+ if (typeof value === "function") {
270
+ return value.bind(t);
271
+ }
272
+ return value;
273
+ },
274
+ }) as C;
275
+ };
276
+
277
+ /**
278
+ * Utility type to add optional capabilities to a collection type.
279
+ */
280
+ export type WithCapability<C, Cap> = C & Cap;
281
+
282
+ /**
283
+ * Builder pattern helper for fluent API construction.
284
+ *
285
+ * @example
286
+ * class ListBuilder<T> {
287
+ * private middleware: Middleware<List<T>>[] = []
288
+ *
289
+ * bounded(capacity: number) {
290
+ * this.middleware.push(boundedList({ capacity }))
291
+ * return this
292
+ * }
293
+ *
294
+ * evented() {
295
+ * this.middleware.push(eventedList())
296
+ * return this
297
+ * }
298
+ *
299
+ * build(): List<T> {
300
+ * return compose(...this.middleware)(arrayList<T>())
301
+ * }
302
+ * }
303
+ */
304
+ export abstract class CollectionBuilder<C> {
305
+ protected middleware: Middleware<C>[] = [];
306
+
307
+ /**
308
+ * Apply a custom middleware.
309
+ */
310
+ use(middleware: Middleware<C>): this {
311
+ this.middleware.push(middleware);
312
+ return this;
313
+ }
314
+
315
+ /**
316
+ * Build the final collection by composing all middleware with the base.
317
+ */
318
+ abstract build(): C;
319
+ }
320
+
321
+ /**
322
+ * Utility to make a middleware that only enhances specific methods.
323
+ *
324
+ * @example
325
+ * const logAdd = enhanceMethod('add', (original, args) => {
326
+ * console.log('Adding:', args[0])
327
+ * return original(...args)
328
+ * })
329
+ */
330
+ export const enhanceMethod = <C extends object, K extends keyof C & string>(
331
+ methodName: K,
332
+ enhancer: (
333
+ original: C[K] extends (...args: infer Args) => infer R
334
+ ? (...args: Args) => R
335
+ : never,
336
+ args: C[K] extends (...args: infer Args) => any ? Args : never
337
+ ) => C[K] extends (...args: any[]) => infer R ? R : never
338
+ ): Middleware<C> => {
339
+ return (next: C): C => {
340
+ type MethodArgs = C[K] extends (...args: infer Args) => any ? Args : never;
341
+ return new Proxy(next, {
342
+ get(target, prop, receiver) {
343
+ const value = Reflect.get(target, prop, receiver);
344
+ if (prop === methodName && typeof value === "function") {
345
+ return function (this: unknown, ...args: unknown[]) {
346
+ return enhancer(value.bind(target), args as MethodArgs);
347
+ };
348
+ }
349
+ return value;
350
+ },
351
+ });
352
+ };
353
+ };
354
+
355
+ /**
356
+ * This function combines multiple middleware into a single middleware.
357
+ * Useful for making reusable middleware bundles.
358
+ *
359
+ * Bundle has the same composition semantics as compose - the first middleware
360
+ * is the outermost layer, and types are tracked through the chain.
361
+ *
362
+ * @example
363
+ * const standardBehaviors = bundle(
364
+ * boundedList({ capacity: 1000 }),
365
+ * eventedList(),
366
+ * safeList()
367
+ * )
368
+ *
369
+ * const list = compose(standardBehaviors)(arrayList<number>())
370
+ */
371
+
372
+ // Overload for 1 middleware
373
+ export function bundle<C, R1 extends C>(
374
+ m1: Middleware<C, R1>
375
+ ): Middleware<C, R1>;
376
+
377
+ // Overload for 2 middleware
378
+ export function bundle<C, R1 extends C, R2 extends R1>(
379
+ m1: Middleware<R1, R2>,
380
+ m2: Middleware<C, R1>
381
+ ): Middleware<C, R2>;
382
+
383
+ // Overload for 3 middleware
384
+ export function bundle<C, R1 extends C, R2 extends R1, R3 extends R2>(
385
+ m1: Middleware<R2, R3>,
386
+ m2: Middleware<R1, R2>,
387
+ m3: Middleware<C, R1>
388
+ ): Middleware<C, R3>;
389
+
390
+ // Overload for 4 middleware
391
+ export function bundle<C, R1 extends C, R2 extends R1, R3 extends R2, R4 extends R3>(
392
+ m1: Middleware<R3, R4>,
393
+ m2: Middleware<R2, R3>,
394
+ m3: Middleware<R1, R2>,
395
+ m4: Middleware<C, R1>
396
+ ): Middleware<C, R4>;
397
+
398
+ // Overload for 5 middleware
399
+ export function bundle<C, R1 extends C, R2 extends R1, R3 extends R2, R4 extends R3, R5 extends R4>(
400
+ m1: Middleware<R4, R5>,
401
+ m2: Middleware<R3, R4>,
402
+ m3: Middleware<R2, R3>,
403
+ m4: Middleware<R1, R2>,
404
+ m5: Middleware<C, R1>
405
+ ): Middleware<C, R5>;
406
+
407
+ // General fallback for any number of middleware
408
+ export function bundle<C>(...middleware: Middleware<any, any>[]): Middleware<C, any>;
409
+
410
+ // Implementation
411
+ export function bundle(...middleware: Middleware<any, any>[]): Middleware<any, any> {
412
+ return (next: any): any => compose(...middleware)(next);
413
+ }