@okikio/observables 1.0.2

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 (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +578 -0
  3. package/esm/_dnt.polyfills.d.ts +20 -0
  4. package/esm/_dnt.polyfills.d.ts.map +1 -0
  5. package/esm/_dnt.polyfills.js +12 -0
  6. package/esm/_spec.d.ts +260 -0
  7. package/esm/_spec.d.ts.map +1 -0
  8. package/esm/_spec.js +1 -0
  9. package/esm/_types.d.ts +141 -0
  10. package/esm/_types.d.ts.map +1 -0
  11. package/esm/_types.js +20 -0
  12. package/esm/error.d.ts +331 -0
  13. package/esm/error.d.ts.map +1 -0
  14. package/esm/error.js +408 -0
  15. package/esm/events.d.ts +320 -0
  16. package/esm/events.d.ts.map +1 -0
  17. package/esm/events.js +451 -0
  18. package/esm/helpers/_types.d.ts +188 -0
  19. package/esm/helpers/_types.d.ts.map +1 -0
  20. package/esm/helpers/_types.js +1 -0
  21. package/esm/helpers/mod.d.ts +90 -0
  22. package/esm/helpers/mod.d.ts.map +1 -0
  23. package/esm/helpers/mod.js +90 -0
  24. package/esm/helpers/operations/batch.d.ts +109 -0
  25. package/esm/helpers/operations/batch.d.ts.map +1 -0
  26. package/esm/helpers/operations/batch.js +140 -0
  27. package/esm/helpers/operations/combination.d.ts +162 -0
  28. package/esm/helpers/operations/combination.d.ts.map +1 -0
  29. package/esm/helpers/operations/combination.js +350 -0
  30. package/esm/helpers/operations/conditional.d.ts +211 -0
  31. package/esm/helpers/operations/conditional.d.ts.map +1 -0
  32. package/esm/helpers/operations/conditional.js +280 -0
  33. package/esm/helpers/operations/core.d.ts +198 -0
  34. package/esm/helpers/operations/core.d.ts.map +1 -0
  35. package/esm/helpers/operations/core.js +264 -0
  36. package/esm/helpers/operations/errors.d.ts +277 -0
  37. package/esm/helpers/operations/errors.d.ts.map +1 -0
  38. package/esm/helpers/operations/errors.js +378 -0
  39. package/esm/helpers/operations/mod.d.ts +26 -0
  40. package/esm/helpers/operations/mod.d.ts.map +1 -0
  41. package/esm/helpers/operations/mod.js +25 -0
  42. package/esm/helpers/operations/timing.d.ts +206 -0
  43. package/esm/helpers/operations/timing.d.ts.map +1 -0
  44. package/esm/helpers/operations/timing.js +457 -0
  45. package/esm/helpers/operators.d.ts +520 -0
  46. package/esm/helpers/operators.d.ts.map +1 -0
  47. package/esm/helpers/operators.js +563 -0
  48. package/esm/helpers/pipe.d.ts +118 -0
  49. package/esm/helpers/pipe.d.ts.map +1 -0
  50. package/esm/helpers/pipe.js +129 -0
  51. package/esm/helpers/utils.d.ts +142 -0
  52. package/esm/helpers/utils.d.ts.map +1 -0
  53. package/esm/helpers/utils.js +193 -0
  54. package/esm/mod.d.ts +863 -0
  55. package/esm/mod.d.ts.map +1 -0
  56. package/esm/mod.js +861 -0
  57. package/esm/observable.d.ts +1610 -0
  58. package/esm/observable.d.ts.map +1 -0
  59. package/esm/observable.js +1970 -0
  60. package/esm/package.json +3 -0
  61. package/esm/queue.d.ts +201 -0
  62. package/esm/queue.d.ts.map +1 -0
  63. package/esm/queue.js +273 -0
  64. package/esm/symbol.d.ts +60 -0
  65. package/esm/symbol.d.ts.map +1 -0
  66. package/esm/symbol.js +132 -0
  67. package/package.json +96 -0
  68. package/script/_dnt.polyfills.d.ts +20 -0
  69. package/script/_dnt.polyfills.d.ts.map +1 -0
  70. package/script/_dnt.polyfills.js +13 -0
  71. package/script/_spec.d.ts +260 -0
  72. package/script/_spec.d.ts.map +1 -0
  73. package/script/_spec.js +2 -0
  74. package/script/_types.d.ts +141 -0
  75. package/script/_types.d.ts.map +1 -0
  76. package/script/_types.js +22 -0
  77. package/script/error.d.ts +331 -0
  78. package/script/error.d.ts.map +1 -0
  79. package/script/error.js +414 -0
  80. package/script/events.d.ts +320 -0
  81. package/script/events.d.ts.map +1 -0
  82. package/script/events.js +458 -0
  83. package/script/helpers/_types.d.ts +188 -0
  84. package/script/helpers/_types.d.ts.map +1 -0
  85. package/script/helpers/_types.js +2 -0
  86. package/script/helpers/mod.d.ts +90 -0
  87. package/script/helpers/mod.d.ts.map +1 -0
  88. package/script/helpers/mod.js +106 -0
  89. package/script/helpers/operations/batch.d.ts +109 -0
  90. package/script/helpers/operations/batch.d.ts.map +1 -0
  91. package/script/helpers/operations/batch.js +144 -0
  92. package/script/helpers/operations/combination.d.ts +162 -0
  93. package/script/helpers/operations/combination.d.ts.map +1 -0
  94. package/script/helpers/operations/combination.js +355 -0
  95. package/script/helpers/operations/conditional.d.ts +211 -0
  96. package/script/helpers/operations/conditional.d.ts.map +1 -0
  97. package/script/helpers/operations/conditional.js +286 -0
  98. package/script/helpers/operations/core.d.ts +198 -0
  99. package/script/helpers/operations/core.d.ts.map +1 -0
  100. package/script/helpers/operations/core.js +272 -0
  101. package/script/helpers/operations/errors.d.ts +277 -0
  102. package/script/helpers/operations/errors.d.ts.map +1 -0
  103. package/script/helpers/operations/errors.js +387 -0
  104. package/script/helpers/operations/mod.d.ts +26 -0
  105. package/script/helpers/operations/mod.d.ts.map +1 -0
  106. package/script/helpers/operations/mod.js +41 -0
  107. package/script/helpers/operations/timing.d.ts +206 -0
  108. package/script/helpers/operations/timing.d.ts.map +1 -0
  109. package/script/helpers/operations/timing.js +464 -0
  110. package/script/helpers/operators.d.ts +520 -0
  111. package/script/helpers/operators.d.ts.map +1 -0
  112. package/script/helpers/operators.js +570 -0
  113. package/script/helpers/pipe.d.ts +118 -0
  114. package/script/helpers/pipe.d.ts.map +1 -0
  115. package/script/helpers/pipe.js +132 -0
  116. package/script/helpers/utils.d.ts +142 -0
  117. package/script/helpers/utils.d.ts.map +1 -0
  118. package/script/helpers/utils.js +200 -0
  119. package/script/mod.d.ts +863 -0
  120. package/script/mod.d.ts.map +1 -0
  121. package/script/mod.js +877 -0
  122. package/script/observable.d.ts +1610 -0
  123. package/script/observable.d.ts.map +1 -0
  124. package/script/observable.js +1984 -0
  125. package/script/package.json +3 -0
  126. package/script/queue.d.ts +201 -0
  127. package/script/queue.d.ts.map +1 -0
  128. package/script/queue.js +286 -0
  129. package/script/symbol.d.ts +60 -0
  130. package/script/symbol.d.ts.map +1 -0
  131. package/script/symbol.js +135 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,201 @@
1
+ /**
2
+ * A lightweight circular-buffer queue for the library's hot paths.
3
+ *
4
+ * This entrypoint exposes the small FIFO data structure that backs replay,
5
+ * buffering, and event fan-out inside the Observable runtime. It keeps
6
+ * enqueue/dequeue work O(1) by moving `head` and `tail` pointers around a fixed
7
+ * array instead of repeatedly calling `Array.shift()`, which has to move every
8
+ * remaining element one slot to the left.
9
+ *
10
+ * Use this module when you need predictable queue performance and explicit
11
+ * capacity control. It is especially useful for buffers that grow and shrink
12
+ * frequently, where repeated array reindexing would turn steady traffic into an
13
+ * unnecessary O(n) cost.
14
+ *
15
+ * @example
16
+ * ```
17
+ * import { createQueue, enqueue, dequeue, peek } from './queue.ts';
18
+ *
19
+ * const taskQueue = createQueue<string>(100); // capacity of 100
20
+ * enqueue(taskQueue, 'process-order-123'); // add task
21
+ * enqueue(taskQueue, 'send-email-456'); // add another
22
+ *
23
+ * console.log(peek(taskQueue)); // 'process-order-123' (doesn't remove)
24
+ * console.log(dequeue(taskQueue)); // 'process-order-123' (removes and returns)
25
+ *
26
+ * clear(taskQueue); // empty the queue instantly
27
+ * ```
28
+ *
29
+ * @module
30
+ */
31
+ /**
32
+ * Represents a circular buffer-based queue for efficient FIFO operations.
33
+ *
34
+ * @template T - The type of elements stored in the queue
35
+ */
36
+ import "./_dnt.polyfills.js";
37
+ export interface Queue<T> {
38
+ /** The backing array that holds queue elements */
39
+ items: T[];
40
+ /** Index pointing to the front element (next to dequeue) */
41
+ head: number;
42
+ /** Index pointing to where the next element will be added */
43
+ tail: number;
44
+ /** Current number of elements in the queue */
45
+ size: number;
46
+ /** Maximum capacity of the queue */
47
+ capacity: number;
48
+ }
49
+ /**
50
+ * Creates a new empty queue with the specified capacity.
51
+ *
52
+ * The queue uses a circular buffer internally, which means operations
53
+ * like enqueue and dequeue run in constant O(1) time regardless of
54
+ * queue size.
55
+ *
56
+ * @param capacity - Maximum number of elements the queue can hold (default: 1000)
57
+ * @returns A new empty queue ready for use
58
+ *
59
+ * @example
60
+ * ```
61
+ * const messageQueue = createQueue<string>(50); // for messages
62
+ * const numberQueue = createQueue<number>(); // uses default capacity
63
+ * ```
64
+ */
65
+ export declare function createQueue<T>(capacity?: number): Queue<T>;
66
+ /**
67
+ * Adds an element to the back of the queue (FIFO: last in, first served).
68
+ * Runs in O(1) constant time.
69
+ *
70
+ * @param queue - The target queue
71
+ * @param item - Element to add to the queue
72
+ * @throws Error if the queue is at capacity
73
+ *
74
+ * @example
75
+ * ```
76
+ * enqueue(userQueue, { id: 123, name: 'Alice' });
77
+ * enqueue(userQueue, { id: 124, name: 'Bob' });
78
+ * ```
79
+ */
80
+ export declare function enqueue<T>(queue: Queue<T>, item: T): void;
81
+ /**
82
+ * Removes and returns the front element from the queue (FIFO: first in, first out).
83
+ * Runs in O(1) constant time.
84
+ *
85
+ * @param queue - The target queue
86
+ * @returns The front element, or undefined if queue is empty
87
+ *
88
+ * @example
89
+ * ```
90
+ * const nextTask = dequeue(taskQueue);
91
+ * if (nextTask) {
92
+ * console.log('Processing:', nextTask);
93
+ * }
94
+ * ```
95
+ */
96
+ export declare function dequeue<T>(queue: Queue<T>): T | undefined;
97
+ /**
98
+ * Returns the front element without removing it from the queue.
99
+ * Useful for checking what's next without consuming it.
100
+ * Runs in O(1) constant time.
101
+ *
102
+ * @param queue - The target queue
103
+ * @returns The front element, or undefined if queue is empty
104
+ *
105
+ * @example
106
+ * ```
107
+ * const nextInLine = peek(queue);
108
+ * if (nextInLine?.priority === 'urgent') {
109
+ * // handle urgent task immediately
110
+ * dequeue(queue);
111
+ * }
112
+ * ```
113
+ */
114
+ export declare function peek<T>(queue: Queue<T>): T | undefined;
115
+ /**
116
+ * Checks if the queue contains no elements.
117
+ *
118
+ * @param queue - The target queue
119
+ * @returns true if the queue is empty, false otherwise
120
+ */
121
+ export declare function isEmpty<T>(queue: Queue<T>): boolean;
122
+ /**
123
+ * Checks if the queue has reached its maximum capacity.
124
+ *
125
+ * @param queue - The target queue
126
+ * @returns true if the queue is full, false otherwise
127
+ */
128
+ export declare function isFull<T>(queue: Queue<T>): boolean;
129
+ /**
130
+ * Returns the current number of elements in the queue.
131
+ *
132
+ * @param queue - The target queue
133
+ * @returns Current queue size (0 to capacity)
134
+ */
135
+ export declare function getSize<T>(queue: Queue<T>): number;
136
+ /**
137
+ * Returns how many more elements can be added before hitting capacity.
138
+ *
139
+ * @param queue - The target queue
140
+ * @returns Number of available slots
141
+ *
142
+ * @example
143
+ * ```
144
+ * if (remainingSpace(queue) < 10) {
145
+ * console.warn('Queue nearly full, consider processing items');
146
+ * }
147
+ * ```
148
+ */
149
+ export declare function remainingSpace<T>(queue: Queue<T>): number;
150
+ /**
151
+ * Empties the queue instantly using the `.length = 0` optimization[87][90].
152
+ * This immediately releases all object references for garbage collection,
153
+ * making it much faster than dequeuing items one by one.
154
+ *
155
+ * Runs in O(1) constant time regardless of queue size.
156
+ *
157
+ * @param queue - The target queue
158
+ *
159
+ * @example
160
+ * ```
161
+ * // Instead of: while (!isEmpty(queue)) dequeue(queue); // O(n)
162
+ * clear(queue); // O(1) - much faster!
163
+ * ```
164
+ */
165
+ export declare function clear<T>(queue: Queue<T>): void;
166
+ /**
167
+ * Creates a new array containing all queue elements in order (front to back).
168
+ * Useful for debugging, logging, or when you need array methods.
169
+ *
170
+ * Note: This is O(n) operation - use sparingly in performance-critical code.
171
+ *
172
+ * @param queue - The source queue
173
+ * @returns New array with queue elements in FIFO order
174
+ *
175
+ * @example
176
+ * ```
177
+ * const queueSnapshot = toArray(queue);
178
+ * console.log('Current queue:', queueSnapshot.join(' -> '));
179
+ *
180
+ * // Process without modifying original queue
181
+ * const urgentItems = queueSnapshot.filter(item => item.priority === 'urgent');
182
+ * ```
183
+ */
184
+ export declare function toArray<T>(queue: Queue<T>): T[];
185
+ /**
186
+ * Applies a function to each element in the queue without modifying it.
187
+ * Elements are visited in FIFO order (front to back).
188
+ *
189
+ * @param queue - The target queue
190
+ * @param callback - Function to call for each element
191
+ *
192
+ * @example
193
+ * ```
194
+ * // Log all pending tasks
195
+ * forEach(taskQueue, (task, index) => {
196
+ * console.log(`Task ${index + 1}: ${task.description}`);
197
+ * });
198
+ * ```
199
+ */
200
+ export declare function forEach<T>(queue: Queue<T>, callback: (item: T, index: number) => void): void;
201
+ //# sourceMappingURL=queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAMH;;;;GAIG;AACH,OAAO,qBAAqB,CAAC;AAE7B,MAAM,WAAW,KAAK,CAAC,CAAC;IACtB,kDAAkD;IAClD,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAkBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,QAAQ,GAAE,MAAa,GAAG,KAAK,CAAC,CAAC,CAAC,CAQhE;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAUzD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAWzD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS,CAEtD;AAMD;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,OAAO,CAEnD;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,OAAO,CAElD;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAElD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAEzD;AAMD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAS9C;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAc/C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,OAAO,CAAC,CAAC,EACvB,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EACf,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GACzC,IAAI,CAON"}
@@ -0,0 +1,286 @@
1
+ "use strict";
2
+ /**
3
+ * A lightweight circular-buffer queue for the library's hot paths.
4
+ *
5
+ * This entrypoint exposes the small FIFO data structure that backs replay,
6
+ * buffering, and event fan-out inside the Observable runtime. It keeps
7
+ * enqueue/dequeue work O(1) by moving `head` and `tail` pointers around a fixed
8
+ * array instead of repeatedly calling `Array.shift()`, which has to move every
9
+ * remaining element one slot to the left.
10
+ *
11
+ * Use this module when you need predictable queue performance and explicit
12
+ * capacity control. It is especially useful for buffers that grow and shrink
13
+ * frequently, where repeated array reindexing would turn steady traffic into an
14
+ * unnecessary O(n) cost.
15
+ *
16
+ * @example
17
+ * ```
18
+ * import { createQueue, enqueue, dequeue, peek } from './queue.ts';
19
+ *
20
+ * const taskQueue = createQueue<string>(100); // capacity of 100
21
+ * enqueue(taskQueue, 'process-order-123'); // add task
22
+ * enqueue(taskQueue, 'send-email-456'); // add another
23
+ *
24
+ * console.log(peek(taskQueue)); // 'process-order-123' (doesn't remove)
25
+ * console.log(dequeue(taskQueue)); // 'process-order-123' (removes and returns)
26
+ *
27
+ * clear(taskQueue); // empty the queue instantly
28
+ * ```
29
+ *
30
+ * @module
31
+ */
32
+ Object.defineProperty(exports, "__esModule", { value: true });
33
+ exports.createQueue = createQueue;
34
+ exports.enqueue = enqueue;
35
+ exports.dequeue = dequeue;
36
+ exports.peek = peek;
37
+ exports.isEmpty = isEmpty;
38
+ exports.isFull = isFull;
39
+ exports.getSize = getSize;
40
+ exports.remainingSpace = remainingSpace;
41
+ exports.clear = clear;
42
+ exports.toArray = toArray;
43
+ exports.forEach = forEach;
44
+ ///////////////////////
45
+ // Core Data Types //
46
+ ///////////////////////
47
+ /**
48
+ * Represents a circular buffer-based queue for efficient FIFO operations.
49
+ *
50
+ * @template T - The type of elements stored in the queue
51
+ */
52
+ require("./_dnt.polyfills.js");
53
+ /**
54
+ * Advances a circular-buffer index by one slot and wraps back to `0` at the end.
55
+ *
56
+ * This keeps the same O(1) behavior as `% capacity`, but avoids paying modulo
57
+ * cost for arbitrary capacities in the queue hot path. It is private because
58
+ * it only exists to speed up internal queue pointer movement.
59
+ */
60
+ function advanceIndex(index, capacity) {
61
+ const next = index + 1;
62
+ return next === capacity ? 0 : next;
63
+ }
64
+ ////////////////////////////
65
+ // Factory & Core Setup //
66
+ ////////////////////////////
67
+ /**
68
+ * Creates a new empty queue with the specified capacity.
69
+ *
70
+ * The queue uses a circular buffer internally, which means operations
71
+ * like enqueue and dequeue run in constant O(1) time regardless of
72
+ * queue size.
73
+ *
74
+ * @param capacity - Maximum number of elements the queue can hold (default: 1000)
75
+ * @returns A new empty queue ready for use
76
+ *
77
+ * @example
78
+ * ```
79
+ * const messageQueue = createQueue<string>(50); // for messages
80
+ * const numberQueue = createQueue<number>(); // uses default capacity
81
+ * ```
82
+ */
83
+ function createQueue(capacity = 1000) {
84
+ return {
85
+ items: new Array(capacity),
86
+ head: 0,
87
+ tail: 0,
88
+ size: 0,
89
+ capacity,
90
+ };
91
+ }
92
+ /////////////////////////
93
+ // Core Queue Operations //
94
+ /////////////////////////
95
+ /**
96
+ * Adds an element to the back of the queue (FIFO: last in, first served).
97
+ * Runs in O(1) constant time.
98
+ *
99
+ * @param queue - The target queue
100
+ * @param item - Element to add to the queue
101
+ * @throws Error if the queue is at capacity
102
+ *
103
+ * @example
104
+ * ```
105
+ * enqueue(userQueue, { id: 123, name: 'Alice' });
106
+ * enqueue(userQueue, { id: 124, name: 'Bob' });
107
+ * ```
108
+ */
109
+ function enqueue(queue, item) {
110
+ if (isFull(queue)) {
111
+ throw new Error(`Queue overflow: cannot add item, capacity ${queue.capacity} reached`);
112
+ }
113
+ queue.items[queue.tail] = item;
114
+ queue.tail = advanceIndex(queue.tail, queue.capacity);
115
+ queue.size++;
116
+ }
117
+ /**
118
+ * Removes and returns the front element from the queue (FIFO: first in, first out).
119
+ * Runs in O(1) constant time.
120
+ *
121
+ * @param queue - The target queue
122
+ * @returns The front element, or undefined if queue is empty
123
+ *
124
+ * @example
125
+ * ```
126
+ * const nextTask = dequeue(taskQueue);
127
+ * if (nextTask) {
128
+ * console.log('Processing:', nextTask);
129
+ * }
130
+ * ```
131
+ */
132
+ function dequeue(queue) {
133
+ if (isEmpty(queue)) {
134
+ return undefined;
135
+ }
136
+ const item = queue.items[queue.head];
137
+ queue.items[queue.head] = undefined; // help garbage collector
138
+ queue.head = advanceIndex(queue.head, queue.capacity);
139
+ queue.size--;
140
+ return item;
141
+ }
142
+ /**
143
+ * Returns the front element without removing it from the queue.
144
+ * Useful for checking what's next without consuming it.
145
+ * Runs in O(1) constant time.
146
+ *
147
+ * @param queue - The target queue
148
+ * @returns The front element, or undefined if queue is empty
149
+ *
150
+ * @example
151
+ * ```
152
+ * const nextInLine = peek(queue);
153
+ * if (nextInLine?.priority === 'urgent') {
154
+ * // handle urgent task immediately
155
+ * dequeue(queue);
156
+ * }
157
+ * ```
158
+ */
159
+ function peek(queue) {
160
+ return isEmpty(queue) ? undefined : queue.items[queue.head];
161
+ }
162
+ ////////////////////////////////
163
+ // Utility & Status Functions //
164
+ ////////////////////////////////
165
+ /**
166
+ * Checks if the queue contains no elements.
167
+ *
168
+ * @param queue - The target queue
169
+ * @returns true if the queue is empty, false otherwise
170
+ */
171
+ function isEmpty(queue) {
172
+ return queue.size === 0;
173
+ }
174
+ /**
175
+ * Checks if the queue has reached its maximum capacity.
176
+ *
177
+ * @param queue - The target queue
178
+ * @returns true if the queue is full, false otherwise
179
+ */
180
+ function isFull(queue) {
181
+ return queue.size >= queue.capacity;
182
+ }
183
+ /**
184
+ * Returns the current number of elements in the queue.
185
+ *
186
+ * @param queue - The target queue
187
+ * @returns Current queue size (0 to capacity)
188
+ */
189
+ function getSize(queue) {
190
+ return queue.size;
191
+ }
192
+ /**
193
+ * Returns how many more elements can be added before hitting capacity.
194
+ *
195
+ * @param queue - The target queue
196
+ * @returns Number of available slots
197
+ *
198
+ * @example
199
+ * ```
200
+ * if (remainingSpace(queue) < 10) {
201
+ * console.warn('Queue nearly full, consider processing items');
202
+ * }
203
+ * ```
204
+ */
205
+ function remainingSpace(queue) {
206
+ return queue.capacity - queue.size;
207
+ }
208
+ /////////////////////////////
209
+ // Advanced Utility Functions //
210
+ /////////////////////////////
211
+ /**
212
+ * Empties the queue instantly using the `.length = 0` optimization[87][90].
213
+ * This immediately releases all object references for garbage collection,
214
+ * making it much faster than dequeuing items one by one.
215
+ *
216
+ * Runs in O(1) constant time regardless of queue size.
217
+ *
218
+ * @param queue - The target queue
219
+ *
220
+ * @example
221
+ * ```
222
+ * // Instead of: while (!isEmpty(queue)) dequeue(queue); // O(n)
223
+ * clear(queue); // O(1) - much faster!
224
+ * ```
225
+ */
226
+ function clear(queue) {
227
+ // Fast array truncation - instantly releases references for GC[87][90]
228
+ queue.items.length = 0;
229
+ queue.items.length = queue.capacity; // restore original capacity
230
+ // Reset pointers
231
+ queue.head = 0;
232
+ queue.tail = 0;
233
+ queue.size = 0;
234
+ }
235
+ /**
236
+ * Creates a new array containing all queue elements in order (front to back).
237
+ * Useful for debugging, logging, or when you need array methods.
238
+ *
239
+ * Note: This is O(n) operation - use sparingly in performance-critical code.
240
+ *
241
+ * @param queue - The source queue
242
+ * @returns New array with queue elements in FIFO order
243
+ *
244
+ * @example
245
+ * ```
246
+ * const queueSnapshot = toArray(queue);
247
+ * console.log('Current queue:', queueSnapshot.join(' -> '));
248
+ *
249
+ * // Process without modifying original queue
250
+ * const urgentItems = queueSnapshot.filter(item => item.priority === 'urgent');
251
+ * ```
252
+ */
253
+ function toArray(queue) {
254
+ if (isEmpty(queue)) {
255
+ return [];
256
+ }
257
+ const result = new Array(queue.size);
258
+ let index = queue.head;
259
+ for (let i = 0; i < queue.size; i++) {
260
+ result[i] = queue.items[index];
261
+ index = advanceIndex(index, queue.capacity);
262
+ }
263
+ return result;
264
+ }
265
+ /**
266
+ * Applies a function to each element in the queue without modifying it.
267
+ * Elements are visited in FIFO order (front to back).
268
+ *
269
+ * @param queue - The target queue
270
+ * @param callback - Function to call for each element
271
+ *
272
+ * @example
273
+ * ```
274
+ * // Log all pending tasks
275
+ * forEach(taskQueue, (task, index) => {
276
+ * console.log(`Task ${index + 1}: ${task.description}`);
277
+ * });
278
+ * ```
279
+ */
280
+ function forEach(queue, callback) {
281
+ let index = queue.head;
282
+ for (let i = 0; i < queue.size; i++) {
283
+ callback(queue.items[index], i);
284
+ index = advanceIndex(index, queue.capacity);
285
+ }
286
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * > Inspired by https://jsr.io/@nick/dispose/1.1.0/symbol.ts
3
+ *
4
+ * Extensions to the global Symbol constructor for interoperability with
5
+ * Observable.
6
+ *
7
+ * This interface extends the standard Symbol constructor with well-known
8
+ * symbols needed for Observable interoperability and resource cleanup:
9
+ *
10
+ * 1. `Symbol.observable`: For Observable interoperability (TC39 proposal)
11
+ *
12
+ * These symbols enable our implementation to work with:
13
+ * - Other Observable libraries via Symbol.observable
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * // Using Symbol.observable for interop
18
+ * const myObservable = {
19
+ * [Symbol.observable]() {
20
+ * return new Observable(observer => {
21
+ * observer.next('Hello');
22
+ * observer.complete();
23
+ * });
24
+ * }
25
+ * };
26
+ * ```
27
+ *
28
+ * @module
29
+ */
30
+ export interface SymbolConstructor extends Omit<typeof globalThis.Symbol, "observable"> {
31
+ /**
32
+ * Well-known symbol for Observable interoperability.
33
+ *
34
+ * This symbol allows any object to define how it converts to an Observable.
35
+ * Objects with a `[Symbol.observable]()` method can be passed directly to
36
+ * `Observable.from()` and will be properly converted.
37
+ *
38
+ * This is analogous to how `Symbol.iterator` enables iteration interop.
39
+ *
40
+ * @see {@link https://github.com/tc39/proposal-observable | TC39 Observable proposal}
41
+ */
42
+ readonly observable: unique symbol;
43
+ }
44
+ /**
45
+ * Provides a cross-platform Symbol implementation with Observable
46
+ * and resource management symbols.
47
+ *
48
+ * This implementation:
49
+ * 1. Uses the native Symbol if available
50
+ * 2. Falls back to a polyfill if Symbol is not supported
51
+ * 3. Adds our special symbols if they don't exist natively
52
+ *
53
+ * The polyfill is lightweight and provides basic Symbol functionality
54
+ * for environments that don't support it natively.
55
+ *
56
+ * Note: The polyfill does not implement the full Symbol specification
57
+ * and is intended only for basic interoperability in legacy environments.
58
+ */
59
+ export declare const Symbol: SymbolConstructor;
60
+ //# sourceMappingURL=symbol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbol.d.ts","sourceRoot":"","sources":["../src/symbol.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,WAAW,iBACf,SAAQ,IAAI,CAAC,OAAO,UAAU,CAAC,MAAM,EAAE,YAAY,CAAC;IACpD;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,UAAU,EAAE,OAAO,MAAM,CAAC;CACpC;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,MAAM,EAAE,iBAIiB,CAAC"}
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Symbol = void 0;
4
+ /**
5
+ * Provides a cross-platform Symbol implementation with Observable
6
+ * and resource management symbols.
7
+ *
8
+ * This implementation:
9
+ * 1. Uses the native Symbol if available
10
+ * 2. Falls back to a polyfill if Symbol is not supported
11
+ * 3. Adds our special symbols if they don't exist natively
12
+ *
13
+ * The polyfill is lightweight and provides basic Symbol functionality
14
+ * for environments that don't support it natively.
15
+ *
16
+ * Note: The polyfill does not implement the full Symbol specification
17
+ * and is intended only for basic interoperability in legacy environments.
18
+ */
19
+ exports.Symbol = (globalThis.Symbol ??
20
+ ((description) => ({
21
+ description,
22
+ toString: () => `Symbol(${description})`,
23
+ })));
24
+ /**
25
+ * Adds Symbol.dispose if it doesn't exist natively.
26
+ *
27
+ * Symbol.dispose enables automatic resource cleanup using the `using` declaration.
28
+ * When a variable declared with `using` goes out of scope, its `[Symbol.dispose]()`
29
+ * method is called automatically, ensuring cleanup happens even if errors occur.
30
+ *
31
+ * @example Basic resource cleanup with using
32
+ * ```ts
33
+ * import { Observable } from './observable.ts';
34
+ *
35
+ * {
36
+ * using subscription = Observable.of(1, 2, 3).subscribe({
37
+ * next: (val) => console.log('Value:', val)
38
+ * });
39
+ *
40
+ * // Use the subscription here
41
+ * // ...
42
+ * } // subscription.unsubscribe() called automatically at block end
43
+ * ```
44
+ *
45
+ * @example Automatic cleanup on error
46
+ * ```ts
47
+ * import { Observable } from './observable.ts';
48
+ *
49
+ * function processData() {
50
+ * using sub = Observable.from(dataStream).subscribe({
51
+ * next: (data) => processItem(data)
52
+ * });
53
+ *
54
+ * if (invalidCondition) {
55
+ * throw new Error('Processing failed');
56
+ * }
57
+ * // sub.unsubscribe() called even if error thrown
58
+ * }
59
+ * ```
60
+ */
61
+ if (typeof globalThis.Symbol === "function" &&
62
+ typeof exports.Symbol.dispose !== "symbol") {
63
+ Reflect.defineProperty(exports.Symbol, "dispose", {
64
+ // deno-lint-ignore no-explicit-any
65
+ value: exports.Symbol("Symbol.dispose"),
66
+ enumerable: false,
67
+ configurable: false,
68
+ writable: false,
69
+ });
70
+ }
71
+ /**
72
+ * Adds Symbol.asyncDispose if it doesn't exist natively.
73
+ *
74
+ * Symbol.asyncDispose enables automatic async resource cleanup using `await using`.
75
+ * When a variable declared with `await using` goes out of scope, its
76
+ * `[Symbol.asyncDispose]()` method is called and awaited automatically,
77
+ * ensuring async cleanup (like closing connections) happens safely.
78
+ *
79
+ * @example Async resource cleanup with await using
80
+ * ```ts
81
+ * import { Observable } from './observable.ts';
82
+ *
83
+ * async function streamData() {
84
+ * await using sub = Observable.of(1, 2, 3).subscribe({
85
+ * next: async (data) => await saveData(data)
86
+ * });
87
+ *
88
+ * // Use the subscription here
89
+ * // ...
90
+ * } // sub.unsubscribe() (or async dispose) awaited automatically at block end
91
+ * ```
92
+ *
93
+ * @example Guaranteed async cleanup on error
94
+ * ```ts
95
+ * import { Observable } from './observable.ts';
96
+ *
97
+ * async function fetchAndProcess() {
98
+ * await using sub = Observable.from(apiStream).subscribe({
99
+ * next: async (item) => await processAsync(item)
100
+ * });
101
+ *
102
+ * if (errorCondition) {
103
+ * throw new Error('Failed');
104
+ * }
105
+ * // Async cleanup guaranteed even if error thrown
106
+ * }
107
+ * ```
108
+ */
109
+ if (typeof globalThis.Symbol === "function" &&
110
+ typeof exports.Symbol.asyncDispose !== "symbol") {
111
+ Reflect.defineProperty(exports.Symbol, "asyncDispose", {
112
+ // deno-lint-ignore no-explicit-any
113
+ value: exports.Symbol("Symbol.asyncDispose"),
114
+ enumerable: false,
115
+ configurable: false,
116
+ writable: false,
117
+ });
118
+ }
119
+ /**
120
+ * Adds Symbol.observable if it doesn't exist natively.
121
+ *
122
+ * This ensures Symbol.observable is available for Observable
123
+ * interoperability, even in environments that don't support
124
+ * it natively.
125
+ */
126
+ if (typeof globalThis.Symbol === "function" &&
127
+ typeof exports.Symbol.observable !== "symbol") {
128
+ Reflect.defineProperty(exports.Symbol, "observable", {
129
+ // deno-lint-ignore no-explicit-any
130
+ value: exports.Symbol("Symbol.observable"),
131
+ enumerable: false,
132
+ configurable: false,
133
+ writable: false,
134
+ });
135
+ }