@soffinal/stream 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.
- package/LICENSE +21 -0
- package/README.md +776 -0
- package/dist/benchmark.d.ts +16 -0
- package/dist/benchmark.d.ts.map +1 -0
- package/dist/benchmark.js +151 -0
- package/dist/benchmark.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/list.d.ts +153 -0
- package/dist/list.d.ts.map +1 -0
- package/dist/list.js +200 -0
- package/dist/list.js.map +1 -0
- package/dist/map.d.ts +97 -0
- package/dist/map.d.ts.map +1 -0
- package/dist/map.js +99 -0
- package/dist/map.js.map +1 -0
- package/dist/set.d.ts +92 -0
- package/dist/set.d.ts.map +1 -0
- package/dist/set.js +94 -0
- package/dist/set.js.map +1 -0
- package/dist/state.d.ts +79 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +90 -0
- package/dist/state.js.map +1 -0
- package/dist/stream.d.ts +480 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/stream.js +558 -0
- package/dist/stream.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
interface BenchmarkResult {
|
|
2
|
+
name: string;
|
|
3
|
+
operations: number;
|
|
4
|
+
duration: number;
|
|
5
|
+
opsPerSecond: number;
|
|
6
|
+
memoryUsage?: number;
|
|
7
|
+
}
|
|
8
|
+
declare class Benchmark {
|
|
9
|
+
private results;
|
|
10
|
+
run(name: string, operations: number, fn: () => Promise<void> | void): Promise<BenchmarkResult>;
|
|
11
|
+
getResults(): BenchmarkResult[];
|
|
12
|
+
printSummary(): void;
|
|
13
|
+
}
|
|
14
|
+
declare function runBenchmarks(): Promise<void>;
|
|
15
|
+
export { runBenchmarks, Benchmark };
|
|
16
|
+
//# sourceMappingURL=benchmark.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"benchmark.d.ts","sourceRoot":"","sources":["../src/benchmark.ts"],"names":[],"mappings":"AAEA,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,cAAM,SAAS;IACb,OAAO,CAAC,OAAO,CAAyB;IAElC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,eAAe,CAAC;IAgCrG,UAAU,IAAI,eAAe,EAAE;IAI/B,YAAY;CAMb;AAED,iBAAe,aAAa,kBAwI3B;AAOD,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,CAAC"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { Stream, State, map, filter } from ".";
|
|
2
|
+
class Benchmark {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.results = [];
|
|
5
|
+
}
|
|
6
|
+
async run(name, operations, fn) {
|
|
7
|
+
// Force garbage collection if available
|
|
8
|
+
if (global.gc)
|
|
9
|
+
global.gc();
|
|
10
|
+
const memBefore = process.memoryUsage().heapUsed;
|
|
11
|
+
const start = performance.now();
|
|
12
|
+
await fn();
|
|
13
|
+
const end = performance.now();
|
|
14
|
+
const memAfter = process.memoryUsage().heapUsed;
|
|
15
|
+
const duration = end - start;
|
|
16
|
+
const opsPerSecond = Math.round((operations / duration) * 1000);
|
|
17
|
+
const memoryUsage = memAfter - memBefore;
|
|
18
|
+
const result = {
|
|
19
|
+
name,
|
|
20
|
+
operations,
|
|
21
|
+
duration: Math.round(duration * 100) / 100,
|
|
22
|
+
opsPerSecond,
|
|
23
|
+
memoryUsage,
|
|
24
|
+
};
|
|
25
|
+
this.results.push(result);
|
|
26
|
+
console.log(`${name}: ${opsPerSecond.toLocaleString()} ops/sec (${duration}ms, ${Math.round(memoryUsage / 1024)}KB)`);
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
getResults() {
|
|
30
|
+
return [...this.results];
|
|
31
|
+
}
|
|
32
|
+
printSummary() {
|
|
33
|
+
console.log("\n=== BENCHMARK SUMMARY ===");
|
|
34
|
+
this.results.forEach((result) => {
|
|
35
|
+
console.log(`${result.name.padEnd(40)} ${result.opsPerSecond.toLocaleString().padStart(10)} ops/sec`);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function runBenchmarks() {
|
|
40
|
+
const bench = new Benchmark();
|
|
41
|
+
const OPERATIONS = 100000;
|
|
42
|
+
const LISTENERS = 10;
|
|
43
|
+
console.log("🚀 Starting Stream Library Benchmarks...\n");
|
|
44
|
+
// Basic Stream Operations
|
|
45
|
+
await bench.run("Basic Push/Listen", OPERATIONS, async () => {
|
|
46
|
+
const stream = new Stream();
|
|
47
|
+
let received = 0;
|
|
48
|
+
for (let i = 0; i < LISTENERS; i++) {
|
|
49
|
+
stream.listen(() => received++);
|
|
50
|
+
}
|
|
51
|
+
for (let i = 0; i < OPERATIONS; i++) {
|
|
52
|
+
stream.push(i);
|
|
53
|
+
}
|
|
54
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
55
|
+
});
|
|
56
|
+
// Multiple Listeners Performance
|
|
57
|
+
await bench.run("100 Listeners", OPERATIONS, async () => {
|
|
58
|
+
const stream = new Stream();
|
|
59
|
+
let received = 0;
|
|
60
|
+
for (let i = 0; i < 100; i++) {
|
|
61
|
+
stream.listen(() => received++);
|
|
62
|
+
}
|
|
63
|
+
for (let i = 0; i < OPERATIONS; i++) {
|
|
64
|
+
stream.push(i);
|
|
65
|
+
}
|
|
66
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
67
|
+
});
|
|
68
|
+
// Extreme Scalability Test
|
|
69
|
+
await bench.run("100,000 Listeners", OPERATIONS / 10, async () => {
|
|
70
|
+
const stream = new Stream();
|
|
71
|
+
let received = 0;
|
|
72
|
+
for (let i = 0; i < 100000; i++) {
|
|
73
|
+
stream.listen(() => received++);
|
|
74
|
+
}
|
|
75
|
+
for (let i = 0; i < OPERATIONS / 10; i++) {
|
|
76
|
+
stream.push(i);
|
|
77
|
+
}
|
|
78
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
79
|
+
});
|
|
80
|
+
// Complex Pipeline Performance
|
|
81
|
+
await bench.run("Complex Pipeline", OPERATIONS, async () => {
|
|
82
|
+
const stream = new Stream();
|
|
83
|
+
const result = stream
|
|
84
|
+
.filter((x) => x > 0)
|
|
85
|
+
.map((x) => x * 2)
|
|
86
|
+
.filter((x) => x < 1000)
|
|
87
|
+
.map((x) => x.toString())
|
|
88
|
+
.filter((x) => x.length < 4);
|
|
89
|
+
let received = 0;
|
|
90
|
+
for (let i = 0; i < LISTENERS; i++) {
|
|
91
|
+
result.listen(() => received++);
|
|
92
|
+
}
|
|
93
|
+
for (let i = 0; i < OPERATIONS; i++) {
|
|
94
|
+
stream.push(i);
|
|
95
|
+
}
|
|
96
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
97
|
+
});
|
|
98
|
+
// Functional Style Performance
|
|
99
|
+
await bench.run("Functional Pipeline", OPERATIONS, async () => {
|
|
100
|
+
const stream = new Stream();
|
|
101
|
+
const result = stream
|
|
102
|
+
.pipe(filter((x) => x > 0))
|
|
103
|
+
.pipe(map((x) => x * 2))
|
|
104
|
+
.pipe(filter((x) => x < 1000))
|
|
105
|
+
.pipe(map((x) => x.toString()));
|
|
106
|
+
let received = 0;
|
|
107
|
+
for (let i = 0; i < LISTENERS; i++) {
|
|
108
|
+
result.listen(() => received++);
|
|
109
|
+
}
|
|
110
|
+
for (let i = 0; i < OPERATIONS; i++) {
|
|
111
|
+
stream.push(i);
|
|
112
|
+
}
|
|
113
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
114
|
+
});
|
|
115
|
+
// State Performance
|
|
116
|
+
await bench.run("State Updates", OPERATIONS, async () => {
|
|
117
|
+
const state = new State(0);
|
|
118
|
+
let received = 0;
|
|
119
|
+
for (let i = 0; i < LISTENERS; i++) {
|
|
120
|
+
state.listen(() => received++);
|
|
121
|
+
}
|
|
122
|
+
for (let i = 0; i < OPERATIONS; i++) {
|
|
123
|
+
state.value = i;
|
|
124
|
+
}
|
|
125
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
126
|
+
});
|
|
127
|
+
// Memory Stress Test
|
|
128
|
+
await bench.run("Memory Stress Test", OPERATIONS * 10, async () => {
|
|
129
|
+
const streams = [];
|
|
130
|
+
// Create many streams with listeners
|
|
131
|
+
for (let i = 0; i < 100; i++) {
|
|
132
|
+
const stream = new Stream();
|
|
133
|
+
stream.listen(() => { });
|
|
134
|
+
streams.push(stream);
|
|
135
|
+
}
|
|
136
|
+
// Push lots of data
|
|
137
|
+
for (let i = 0; i < OPERATIONS * 10; i++) {
|
|
138
|
+
const stream = streams[i % streams.length];
|
|
139
|
+
stream.push(i);
|
|
140
|
+
}
|
|
141
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
142
|
+
});
|
|
143
|
+
bench.printSummary();
|
|
144
|
+
console.log("\n🎯 Benchmark Complete!");
|
|
145
|
+
}
|
|
146
|
+
// Run: bun run src/benchmark.ts
|
|
147
|
+
if (require.main === module) {
|
|
148
|
+
runBenchmarks().catch(console.error);
|
|
149
|
+
}
|
|
150
|
+
export { runBenchmarks, Benchmark };
|
|
151
|
+
//# sourceMappingURL=benchmark.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"benchmark.js","sourceRoot":"","sources":["../src/benchmark.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,OAAO,CAAC;AACtB,cAAc,OAAO,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,OAAO,CAAC;AACtB,cAAc,OAAO,CAAC"}
|
package/dist/list.d.ts
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { Stream } from "./stream";
|
|
2
|
+
/**
|
|
3
|
+
* A reactive List that provides array-like functionality with stream-based mutation events.
|
|
4
|
+
* Emits events when items are inserted, deleted, or the list is cleared.
|
|
5
|
+
* Supports negative indexing with modulo wrapping.
|
|
6
|
+
* @template VALUE - The type of values stored in the list
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const todos = new List<string>();
|
|
11
|
+
*
|
|
12
|
+
* // Listen to insertions
|
|
13
|
+
* todos.insert.listen(([index, item]) => {
|
|
14
|
+
* console.log(`Added "${item}" at index ${index}`);
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* // Listen to deletions
|
|
18
|
+
* todos.delete.listen(([index, item]) => {
|
|
19
|
+
* console.log(`Removed "${item}" from index ${index}`);
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* todos.insert(0, "Buy milk"); //Added "Buy milk" at index 0
|
|
23
|
+
* todos.insert(1, "Walk dog"); //Added "Walk dog" at index 1
|
|
24
|
+
* todos.insert(-1, "kechma haja"); //Added "kechma haja" at index 2
|
|
25
|
+
* todos[0] = "Buy organic milk"; // Added "Buy organic milk" at index 0
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare class List<VALUE> implements Iterable<VALUE> {
|
|
29
|
+
private _items;
|
|
30
|
+
private _insertStream?;
|
|
31
|
+
private _deleteStream?;
|
|
32
|
+
private _clearStream?;
|
|
33
|
+
[index: number]: VALUE | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Inserts a value at the specified index and emits the insertion event.
|
|
36
|
+
* Negative indices are handled specially for insertion positioning.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const list = new List([1, 2, 3]);
|
|
41
|
+
* list.insert.listen(([index, value]) => console.log(`Inserted ${value} at ${index}`));
|
|
42
|
+
*
|
|
43
|
+
* list.insert(1, 99); // Inserted 99 at 1 → [1, 99, 2, 3]
|
|
44
|
+
* list.insert(-1, 88); // Insert at end → [1, 99, 2, 3, 88]
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
insert: ((index: number, value: VALUE) => this) & Stream<[number, VALUE]>;
|
|
48
|
+
/**
|
|
49
|
+
* Deletes a value at the specified index and emits the deletion event.
|
|
50
|
+
* Returns the deleted value or undefined if index is invalid.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* const list = new List(['a', 'b', 'c']);
|
|
55
|
+
* list.delete.listen(([index, value]) => console.log(`Deleted ${value} from ${index}`));
|
|
56
|
+
*
|
|
57
|
+
* const deleted = list.delete(1); // Deleted b from 1
|
|
58
|
+
* console.log(deleted); // 'b'
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
delete: ((index: number) => VALUE | undefined) & Stream<[number, VALUE]>;
|
|
62
|
+
/**
|
|
63
|
+
* Clears all items from the list and emits the clear event.
|
|
64
|
+
* Only emits if the list was not already empty.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* const list = new List([1, 2, 3]);
|
|
69
|
+
* list.clear.listen(() => console.log('List cleared'));
|
|
70
|
+
*
|
|
71
|
+
* list.clear(); // List cleared
|
|
72
|
+
* list.clear(); // No emission (already empty)
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
clear: (() => void) & Stream<void>;
|
|
76
|
+
/**
|
|
77
|
+
* Creates a new reactive List.
|
|
78
|
+
*
|
|
79
|
+
* @param items - Optional iterable of initial items
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* // Empty list
|
|
84
|
+
* const list = new List<number>();
|
|
85
|
+
*
|
|
86
|
+
* // With initial items
|
|
87
|
+
* const todos = new List(['Buy milk', 'Walk dog']);
|
|
88
|
+
*
|
|
89
|
+
* // Listen to changes
|
|
90
|
+
* todos.insert.listen(([index, item]) => updateUI(index, item));
|
|
91
|
+
* todos.delete.listen(([index, item]) => removeFromUI(index));
|
|
92
|
+
*
|
|
93
|
+
* // Index access with modulo wrapping
|
|
94
|
+
* console.log(todos[0]); // 'Buy milk'
|
|
95
|
+
* console.log(todos[-1]); // 'Walk dog' (last item)
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
constructor(items?: Iterable<VALUE>);
|
|
99
|
+
/**
|
|
100
|
+
* Gets the value at the specified index without modulo wrapping.
|
|
101
|
+
*
|
|
102
|
+
* @param index - The index to access
|
|
103
|
+
* @returns The value at the index or undefined
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```typescript
|
|
107
|
+
* const list = new List([10, 20, 30]);
|
|
108
|
+
* console.log(list.get(1)); // 20
|
|
109
|
+
* console.log(list.get(5)); // undefined
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
get(index: number): VALUE | undefined;
|
|
113
|
+
/**
|
|
114
|
+
* Gets the current length of the list.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```typescript
|
|
118
|
+
* const list = new List([1, 2, 3]);
|
|
119
|
+
* console.log(list.length); // 3
|
|
120
|
+
*
|
|
121
|
+
* list.insert(0, 0);
|
|
122
|
+
* console.log(list.length); // 4
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
get length(): number;
|
|
126
|
+
/**
|
|
127
|
+
* Returns an iterator for the list values.
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* ```typescript
|
|
131
|
+
* const list = new List([1, 2, 3]);
|
|
132
|
+
* for (const value of list.values()) {
|
|
133
|
+
* console.log(value); // 1, 2, 3
|
|
134
|
+
* }
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
values(): ArrayIterator<VALUE>;
|
|
138
|
+
/**
|
|
139
|
+
* Makes the list iterable.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```typescript
|
|
143
|
+
* const list = new List(['a', 'b', 'c']);
|
|
144
|
+
* for (const item of list) {
|
|
145
|
+
* console.log(item); // 'a', 'b', 'c'
|
|
146
|
+
* }
|
|
147
|
+
*
|
|
148
|
+
* const array = [...list]; // ['a', 'b', 'c']
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
[Symbol.iterator](): ArrayIterator<VALUE>;
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=list.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../src/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,IAAI,CAAC,KAAK,CAAE,YAAW,QAAQ,CAAC,KAAK,CAAC;IACjD,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,aAAa,CAAC,CAA0B;IAChD,OAAO,CAAC,aAAa,CAAC,CAA0B;IAChD,OAAO,CAAC,YAAY,CAAC,CAAe;IAEpC,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;IAEnC;;;;;;;;;;;;OAYG;IACK,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IAElF;;;;;;;;;;;;OAYG;IACK,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,GAAG,SAAS,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IAEjF;;;;;;;;;;;;OAYG;IACK,KAAK,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAE3C;;;;;;;;;;;;;;;;;;;;;OAqBG;gBACS,KAAK,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;IAiGnC;;;;;;;;;;;;OAYG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS;IAIrC;;;;;;;;;;;OAWG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;IACD;;;;;;;;;;OAUG;IACH,MAAM;IAGN;;;;;;;;;;;;OAYG;IACH,CAAC,MAAM,CAAC,QAAQ,CAAC;CAGlB"}
|
package/dist/list.js
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { Stream } from "./stream";
|
|
2
|
+
/**
|
|
3
|
+
* A reactive List that provides array-like functionality with stream-based mutation events.
|
|
4
|
+
* Emits events when items are inserted, deleted, or the list is cleared.
|
|
5
|
+
* Supports negative indexing with modulo wrapping.
|
|
6
|
+
* @template VALUE - The type of values stored in the list
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const todos = new List<string>();
|
|
11
|
+
*
|
|
12
|
+
* // Listen to insertions
|
|
13
|
+
* todos.insert.listen(([index, item]) => {
|
|
14
|
+
* console.log(`Added "${item}" at index ${index}`);
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* // Listen to deletions
|
|
18
|
+
* todos.delete.listen(([index, item]) => {
|
|
19
|
+
* console.log(`Removed "${item}" from index ${index}`);
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* todos.insert(0, "Buy milk"); //Added "Buy milk" at index 0
|
|
23
|
+
* todos.insert(1, "Walk dog"); //Added "Walk dog" at index 1
|
|
24
|
+
* todos.insert(-1, "kechma haja"); //Added "kechma haja" at index 2
|
|
25
|
+
* todos[0] = "Buy organic milk"; // Added "Buy organic milk" at index 0
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export class List {
|
|
29
|
+
/**
|
|
30
|
+
* Creates a new reactive List.
|
|
31
|
+
*
|
|
32
|
+
* @param items - Optional iterable of initial items
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* // Empty list
|
|
37
|
+
* const list = new List<number>();
|
|
38
|
+
*
|
|
39
|
+
* // With initial items
|
|
40
|
+
* const todos = new List(['Buy milk', 'Walk dog']);
|
|
41
|
+
*
|
|
42
|
+
* // Listen to changes
|
|
43
|
+
* todos.insert.listen(([index, item]) => updateUI(index, item));
|
|
44
|
+
* todos.delete.listen(([index, item]) => removeFromUI(index));
|
|
45
|
+
*
|
|
46
|
+
* // Index access with modulo wrapping
|
|
47
|
+
* console.log(todos[0]); // 'Buy milk'
|
|
48
|
+
* console.log(todos[-1]); // 'Walk dog' (last item)
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
constructor(items) {
|
|
52
|
+
this._items = [];
|
|
53
|
+
if (items)
|
|
54
|
+
this._items = [...items];
|
|
55
|
+
const self = this;
|
|
56
|
+
function normalizeIndex(index, length) {
|
|
57
|
+
if (length === 0)
|
|
58
|
+
return 0;
|
|
59
|
+
return index < 0 ? ((index % length) + length) % length : index % length;
|
|
60
|
+
}
|
|
61
|
+
this.insert = new Proxy((index, value) => {
|
|
62
|
+
const actualIndex = index < 0 ? Math.max(0, self._items.length + index + 1) : Math.min(index, self._items.length);
|
|
63
|
+
self._items.splice(actualIndex, 0, value);
|
|
64
|
+
self._insertStream?.push([actualIndex, value]);
|
|
65
|
+
return proxy;
|
|
66
|
+
}, {
|
|
67
|
+
get(target, prop) {
|
|
68
|
+
if (prop in target)
|
|
69
|
+
return target[prop];
|
|
70
|
+
if (!self._insertStream)
|
|
71
|
+
self._insertStream = new Stream();
|
|
72
|
+
return self._insertStream[prop];
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
this.delete = new Proxy((index) => {
|
|
76
|
+
if (index < 0 || index >= self._items.length)
|
|
77
|
+
return undefined;
|
|
78
|
+
const value = self._items.splice(index, 1)[0];
|
|
79
|
+
self._deleteStream?.push([index, value]);
|
|
80
|
+
return value;
|
|
81
|
+
}, {
|
|
82
|
+
get(target, prop) {
|
|
83
|
+
if (prop in target)
|
|
84
|
+
return target[prop];
|
|
85
|
+
if (!self._deleteStream)
|
|
86
|
+
self._deleteStream = new Stream();
|
|
87
|
+
return self._deleteStream[prop];
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
this.clear = new Proxy(() => {
|
|
91
|
+
if (self._items.length > 0) {
|
|
92
|
+
self._items.length = 0;
|
|
93
|
+
self._clearStream?.push();
|
|
94
|
+
}
|
|
95
|
+
}, {
|
|
96
|
+
get(target, prop) {
|
|
97
|
+
if (prop in target)
|
|
98
|
+
return target[prop];
|
|
99
|
+
if (!self._clearStream)
|
|
100
|
+
self._clearStream = new Stream();
|
|
101
|
+
return self._clearStream[prop];
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
const proxy = new Proxy(this, {
|
|
105
|
+
get(target, prop) {
|
|
106
|
+
if (typeof prop === "string" && /^-?\d+$/.test(prop)) {
|
|
107
|
+
const index = parseInt(prop);
|
|
108
|
+
if (target._items.length === 0)
|
|
109
|
+
return undefined;
|
|
110
|
+
const actualIndex = normalizeIndex(index, target._items.length);
|
|
111
|
+
return target._items[actualIndex];
|
|
112
|
+
}
|
|
113
|
+
return target[prop];
|
|
114
|
+
},
|
|
115
|
+
set(target, prop, value) {
|
|
116
|
+
if (typeof prop === "string" && /^-?\d+$/.test(prop)) {
|
|
117
|
+
const index = parseInt(prop);
|
|
118
|
+
if (target._items.length === 0) {
|
|
119
|
+
// Empty array: any index mutation adds first element at index 0
|
|
120
|
+
target._items.push(value);
|
|
121
|
+
target._insertStream?.push([0, value]);
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
const actualIndex = normalizeIndex(index, target._items.length);
|
|
125
|
+
const oldValue = target._items[actualIndex];
|
|
126
|
+
if (oldValue !== value) {
|
|
127
|
+
target._items[actualIndex] = value;
|
|
128
|
+
target._insertStream?.push([actualIndex, value]);
|
|
129
|
+
}
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
target[prop] = value;
|
|
133
|
+
return true;
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
return proxy;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Gets the value at the specified index without modulo wrapping.
|
|
140
|
+
*
|
|
141
|
+
* @param index - The index to access
|
|
142
|
+
* @returns The value at the index or undefined
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```typescript
|
|
146
|
+
* const list = new List([10, 20, 30]);
|
|
147
|
+
* console.log(list.get(1)); // 20
|
|
148
|
+
* console.log(list.get(5)); // undefined
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
get(index) {
|
|
152
|
+
return this._items[index];
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Gets the current length of the list.
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```typescript
|
|
159
|
+
* const list = new List([1, 2, 3]);
|
|
160
|
+
* console.log(list.length); // 3
|
|
161
|
+
*
|
|
162
|
+
* list.insert(0, 0);
|
|
163
|
+
* console.log(list.length); // 4
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
get length() {
|
|
167
|
+
return this._items.length;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Returns an iterator for the list values.
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```typescript
|
|
174
|
+
* const list = new List([1, 2, 3]);
|
|
175
|
+
* for (const value of list.values()) {
|
|
176
|
+
* console.log(value); // 1, 2, 3
|
|
177
|
+
* }
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
values() {
|
|
181
|
+
return this._items[Symbol.iterator]();
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Makes the list iterable.
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* ```typescript
|
|
188
|
+
* const list = new List(['a', 'b', 'c']);
|
|
189
|
+
* for (const item of list) {
|
|
190
|
+
* console.log(item); // 'a', 'b', 'c'
|
|
191
|
+
* }
|
|
192
|
+
*
|
|
193
|
+
* const array = [...list]; // ['a', 'b', 'c']
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
196
|
+
[Symbol.iterator]() {
|
|
197
|
+
return this._items[Symbol.iterator]();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=list.js.map
|
package/dist/list.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../src/list.ts"],"names":[],"mappings":"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"}
|
package/dist/map.d.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { Stream } from "./stream";
|
|
2
|
+
/**
|
|
3
|
+
* A reactive Map that extends the native Map with stream-based mutation events.
|
|
4
|
+
* Emits events when entries are set, deleted, or the map is cleared.
|
|
5
|
+
*
|
|
6
|
+
* @template KEY - The type of keys in the map
|
|
7
|
+
* @template VALUE - The type of values in the map
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const cache = new Map<string, any>();
|
|
12
|
+
*
|
|
13
|
+
* // Listen to cache updates
|
|
14
|
+
* cache.set.listen(([key, value]) => {
|
|
15
|
+
* console.log(`Cache updated: ${key} = ${value}`);
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* // Listen to cache evictions
|
|
19
|
+
* cache.delete.listen(([key, value]) => {
|
|
20
|
+
* console.log(`Cache evicted: ${key}`);
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* cache.set('user:123', { name: 'John' });
|
|
24
|
+
* cache.delete('user:123');
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare class Map<KEY, VALUE> extends globalThis.Map<KEY, VALUE> {
|
|
28
|
+
protected _setStream?: Stream<[KEY, VALUE]>;
|
|
29
|
+
protected _deleteStream?: Stream<[KEY, VALUE]>;
|
|
30
|
+
protected _clearStream?: Stream<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Sets a key-value pair in the map and emits the entry to listeners.
|
|
33
|
+
* Only emits if the value actually changes (not same key-value pair).
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const config = new Map<string, string>();
|
|
38
|
+
* config.set.listen(([key, value]) => console.log(`Set: ${key}=${value}`));
|
|
39
|
+
*
|
|
40
|
+
* config.set('theme', 'dark'); // Set: theme=dark
|
|
41
|
+
* config.set('theme', 'dark'); // No emission (same value)
|
|
42
|
+
* config.set('theme', 'light'); // Set: theme=light
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
set: ((key: KEY, value: VALUE) => this) & Stream<[KEY, VALUE]>;
|
|
46
|
+
/**
|
|
47
|
+
* Deletes a key from the map and emits the deleted entry to listeners.
|
|
48
|
+
* Only emits if the key was actually deleted (existed in map).
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* const users = new Map([['alice', { age: 30 }], ['bob', { age: 25 }]]);
|
|
53
|
+
* users.delete.listen(([key, value]) => console.log(`Removed: ${key}`));
|
|
54
|
+
*
|
|
55
|
+
* users.delete('alice'); // Removed: alice
|
|
56
|
+
* users.delete('charlie'); // No emission (didn't exist)
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
delete: ((key: KEY) => boolean) & Stream<[KEY, VALUE]>;
|
|
60
|
+
/**
|
|
61
|
+
* Clears all entries from the map and emits to listeners.
|
|
62
|
+
* Only emits if the map was not already empty.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* const store = new Map([['a', 1], ['b', 2]]);
|
|
67
|
+
* store.clear.listen(() => console.log('Store cleared'));
|
|
68
|
+
*
|
|
69
|
+
* store.clear(); // Store cleared
|
|
70
|
+
* store.clear(); // No emission (already empty)
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
clear: (() => void) & Stream<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Creates a new reactive Map.
|
|
76
|
+
*
|
|
77
|
+
* @param entries - Optional iterable of initial key-value pairs
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* // Empty map
|
|
82
|
+
* const cache = new Map<string, any>();
|
|
83
|
+
*
|
|
84
|
+
* // With initial entries
|
|
85
|
+
* const config = new Map([
|
|
86
|
+
* ['theme', 'dark'],
|
|
87
|
+
* ['lang', 'en']
|
|
88
|
+
* ]);
|
|
89
|
+
*
|
|
90
|
+
* // Listen to changes
|
|
91
|
+
* config.set.listen(([key, value]) => saveConfig(key, value));
|
|
92
|
+
* config.delete.listen(([key]) => removeConfig(key));
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
constructor(entries?: Iterable<[KEY, VALUE]>);
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map.d.ts","sourceRoot":"","sources":["../src/map.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,GAAG,CAAC,GAAG,EAAE,KAAK,CAAE,SAAQ,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC;IAC7D,SAAS,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IAC5C,SAAS,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IAC/C,SAAS,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAEtC;;;;;;;;;;;;;OAaG;IACK,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IAEvE;;;;;;;;;;;;OAYG;IACK,MAAM,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IAE/D;;;;;;;;;;;;OAYG;IACK,KAAK,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAE3C;;;;;;;;;;;;;;;;;;;;OAoBG;gBACS,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;CAuD7C"}
|