tyneq 1.0.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 +319 -0
- package/dist/Lazy.cjs +762 -0
- package/dist/Lazy.cjs.map +1 -0
- package/dist/Lazy.js +691 -0
- package/dist/Lazy.js.map +1 -0
- package/dist/TyneqCachedTerminalOperator.cjs +4950 -0
- package/dist/TyneqCachedTerminalOperator.cjs.map +1 -0
- package/dist/TyneqCachedTerminalOperator.d.cts +724 -0
- package/dist/TyneqCachedTerminalOperator.d.cts.map +1 -0
- package/dist/TyneqCachedTerminalOperator.d.ts +724 -0
- package/dist/TyneqCachedTerminalOperator.d.ts.map +1 -0
- package/dist/TyneqCachedTerminalOperator.js +4741 -0
- package/dist/TyneqCachedTerminalOperator.js.map +1 -0
- package/dist/ValidationBuilder.cjs +80 -0
- package/dist/ValidationBuilder.cjs.map +1 -0
- package/dist/ValidationBuilder.d.cts +319 -0
- package/dist/ValidationBuilder.d.cts.map +1 -0
- package/dist/ValidationBuilder.d.ts +319 -0
- package/dist/ValidationBuilder.d.ts.map +1 -0
- package/dist/ValidationBuilder.js +69 -0
- package/dist/ValidationBuilder.js.map +1 -0
- package/dist/core.d.cts +1393 -0
- package/dist/core.d.cts.map +1 -0
- package/dist/core.d.ts +1393 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/index.cjs +863 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1038 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +1038 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +809 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin/index.cjs +24 -0
- package/dist/plugin/index.d.cts +89 -0
- package/dist/plugin/index.d.cts.map +1 -0
- package/dist/plugin/index.d.ts +89 -0
- package/dist/plugin/index.d.ts.map +1 -0
- package/dist/plugin/index.js +2 -0
- package/dist/utility/index.cjs +9 -0
- package/dist/utility/index.d.cts +2 -0
- package/dist/utility/index.d.ts +2 -0
- package/dist/utility/index.js +3 -0
- package/package.json +96 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,863 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_TyneqCachedTerminalOperator = require("./TyneqCachedTerminalOperator.cjs");
|
|
3
|
+
const require_Lazy = require("./Lazy.cjs");
|
|
4
|
+
const require_ValidationBuilder = require("./ValidationBuilder.cjs");
|
|
5
|
+
//#region src/core/generators/range.ts
|
|
6
|
+
var RangeEnumerator = class extends require_TyneqCachedTerminalOperator.TyneqBaseEnumerator {
|
|
7
|
+
current;
|
|
8
|
+
end;
|
|
9
|
+
constructor(start, end) {
|
|
10
|
+
super();
|
|
11
|
+
this.current = start;
|
|
12
|
+
this.end = end;
|
|
13
|
+
}
|
|
14
|
+
handleNext() {
|
|
15
|
+
if (this.current > this.end) return this.done();
|
|
16
|
+
return this.yield(this.current++);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region src/core/generators/random.ts
|
|
21
|
+
var RandomEnumerator = class extends require_TyneqCachedTerminalOperator.TyneqBaseEnumerator {
|
|
22
|
+
count;
|
|
23
|
+
randomizer;
|
|
24
|
+
yieldedCount = 0;
|
|
25
|
+
constructor(count, randomizer) {
|
|
26
|
+
super();
|
|
27
|
+
this.count = count;
|
|
28
|
+
this.randomizer = randomizer;
|
|
29
|
+
}
|
|
30
|
+
handleNext() {
|
|
31
|
+
if (this.yieldedCount >= this.count) return this.done();
|
|
32
|
+
this.yieldedCount++;
|
|
33
|
+
return this.yield(this.randomizer());
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
//#endregion
|
|
37
|
+
//#region src/core/EnumerableAdapter.ts
|
|
38
|
+
/**
|
|
39
|
+
* Wraps a native `Iterable<T>` as a Tyneq {@link Enumerable}.
|
|
40
|
+
*
|
|
41
|
+
* @remarks
|
|
42
|
+
* Used by `Tyneq.from()` to adapt arrays, sets, generators, and any other iterable.
|
|
43
|
+
* Each call to `getEnumerator()` delegates to the underlying `[Symbol.iterator]()`.
|
|
44
|
+
*
|
|
45
|
+
* @internal
|
|
46
|
+
*/
|
|
47
|
+
var EnumerableAdapter = class {
|
|
48
|
+
iterable;
|
|
49
|
+
constructor(iterable) {
|
|
50
|
+
require_Lazy.ArgumentUtility.checkNotOptional({ iterable });
|
|
51
|
+
require_Lazy.ArgumentUtility.checkIterable({ iterable });
|
|
52
|
+
this.iterable = iterable;
|
|
53
|
+
}
|
|
54
|
+
[Symbol.iterator]() {
|
|
55
|
+
return this.getEnumerator();
|
|
56
|
+
}
|
|
57
|
+
getEnumerator() {
|
|
58
|
+
return this.iterable[Symbol.iterator]();
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
//#endregion
|
|
62
|
+
//#region src/core/generators/repeat.ts
|
|
63
|
+
/**
|
|
64
|
+
* Yields a single value a fixed number of times.
|
|
65
|
+
*
|
|
66
|
+
* @group Operators
|
|
67
|
+
* @category Streaming
|
|
68
|
+
* @internal
|
|
69
|
+
*/
|
|
70
|
+
var RepeatEnumerator = class extends require_TyneqCachedTerminalOperator.TyneqBaseEnumerator {
|
|
71
|
+
value;
|
|
72
|
+
count;
|
|
73
|
+
yieldedCount = 0;
|
|
74
|
+
constructor(value, count) {
|
|
75
|
+
super();
|
|
76
|
+
this.count = count;
|
|
77
|
+
this.value = value;
|
|
78
|
+
}
|
|
79
|
+
handleNext() {
|
|
80
|
+
if (this.yieldedCount >= this.count) return this.done();
|
|
81
|
+
this.yieldedCount++;
|
|
82
|
+
return this.yieldedCount === this.count ? this.doneWithYield(this.value) : this.yield(this.value);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
//#endregion
|
|
86
|
+
//#region src/core/generators/generate.ts
|
|
87
|
+
/**
|
|
88
|
+
* Yields a sequence produced by repeatedly applying a selector to the previous element.
|
|
89
|
+
*
|
|
90
|
+
* @group Operators
|
|
91
|
+
* @category Streaming
|
|
92
|
+
* @internal
|
|
93
|
+
*/
|
|
94
|
+
var GenerateEnumerator = class extends require_TyneqCachedTerminalOperator.TyneqBaseEnumerator {
|
|
95
|
+
nextSelector;
|
|
96
|
+
count;
|
|
97
|
+
value;
|
|
98
|
+
yieldedCount = 0;
|
|
99
|
+
index = 0;
|
|
100
|
+
constructor(seed, next, count) {
|
|
101
|
+
super();
|
|
102
|
+
this.value = seed;
|
|
103
|
+
this.nextSelector = next;
|
|
104
|
+
this.count = count ?? Infinity;
|
|
105
|
+
}
|
|
106
|
+
handleNext() {
|
|
107
|
+
if (this.yieldedCount >= this.count) return this.done();
|
|
108
|
+
const result = this.nextSelector(this.value, this.index++);
|
|
109
|
+
this.value = result;
|
|
110
|
+
this.yieldedCount++;
|
|
111
|
+
return this.yield(result);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
//#endregion
|
|
115
|
+
//#region src/core/generators/sourceConcat.ts
|
|
116
|
+
/**
|
|
117
|
+
* Yields all elements from each source iterable in order.
|
|
118
|
+
*
|
|
119
|
+
* @group Operators
|
|
120
|
+
* @category Streaming
|
|
121
|
+
* @internal
|
|
122
|
+
*/
|
|
123
|
+
var SourceConcatEnumerator = class extends require_TyneqCachedTerminalOperator.TyneqBaseEnumerator {
|
|
124
|
+
sources;
|
|
125
|
+
currentSourceIndex = 0;
|
|
126
|
+
currentIterator = null;
|
|
127
|
+
constructor(...sources) {
|
|
128
|
+
super();
|
|
129
|
+
this.sources = sources;
|
|
130
|
+
}
|
|
131
|
+
disposeAdditional() {
|
|
132
|
+
try {
|
|
133
|
+
this.currentIterator?.return?.();
|
|
134
|
+
} catch {}
|
|
135
|
+
this.currentIterator = null;
|
|
136
|
+
}
|
|
137
|
+
handleNext() {
|
|
138
|
+
while (this.currentSourceIndex < this.sources.length) {
|
|
139
|
+
if (this.currentIterator === null) this.currentIterator = this.sources[this.currentSourceIndex][Symbol.iterator]();
|
|
140
|
+
const result = this.currentIterator.next();
|
|
141
|
+
if (!result.done) return this.yield(result.value);
|
|
142
|
+
this.currentIterator = null;
|
|
143
|
+
this.currentSourceIndex++;
|
|
144
|
+
}
|
|
145
|
+
return this.done();
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
//#endregion
|
|
149
|
+
//#region src/core/tyneq.ts
|
|
150
|
+
/**
|
|
151
|
+
* Entry point for creating Tyneq sequences.
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* ```ts
|
|
155
|
+
* import { Tyneq } from "tyneq";
|
|
156
|
+
*
|
|
157
|
+
* const sum = Tyneq.from([1, 2, 3, 4, 5])
|
|
158
|
+
* .where((x) => x % 2 === 0)
|
|
159
|
+
* .sum((x) => x); // -> 6
|
|
160
|
+
* ```
|
|
161
|
+
*
|
|
162
|
+
* @group Classes
|
|
163
|
+
*/
|
|
164
|
+
var Tyneq = class Tyneq {
|
|
165
|
+
/**
|
|
166
|
+
* Creates a lazy sequence from any `Iterable<T>` (arrays, sets, generators, etc.).
|
|
167
|
+
*
|
|
168
|
+
* @throws {ArgumentNullError} When `source` is null or undefined.
|
|
169
|
+
* @throws {ArgumentTypeError} When `source` is not iterable.
|
|
170
|
+
*/
|
|
171
|
+
@require_TyneqCachedTerminalOperator.source({ source: "internal" }) static from(source) {
|
|
172
|
+
require_Lazy.ArgumentUtility.checkNotOptional({ source });
|
|
173
|
+
require_Lazy.ArgumentUtility.checkIterable({ source });
|
|
174
|
+
const sourceKind = Tyneq.resolveSourceKind(source);
|
|
175
|
+
return new require_TyneqCachedTerminalOperator.TyneqEnumerable(new EnumerableAdapter(source), new require_TyneqCachedTerminalOperator.QueryNode("from", [source], null, "source", sourceKind));
|
|
176
|
+
}
|
|
177
|
+
static resolveSourceKind(source) {
|
|
178
|
+
if (Array.isArray(source)) return "array";
|
|
179
|
+
if (source instanceof Set) return "set";
|
|
180
|
+
if (source instanceof Map) return "map";
|
|
181
|
+
if (typeof source === "string") return "string";
|
|
182
|
+
return "other";
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Creates a sequence of `count` elements produced by calling `randomizer` once per element.
|
|
186
|
+
*
|
|
187
|
+
* @remarks
|
|
188
|
+
* Returns an empty sequence when `count === 0`.
|
|
189
|
+
*
|
|
190
|
+
* @throws {ArgumentOutOfRangeError} When `count` is negative.
|
|
191
|
+
* @throws {ArgumentNullError} When `randomizer` is null or undefined.
|
|
192
|
+
*/
|
|
193
|
+
@require_TyneqCachedTerminalOperator.source({ source: "internal" }) static random(count, randomizer) {
|
|
194
|
+
require_Lazy.ArgumentUtility.checkNonNegative({ count });
|
|
195
|
+
require_Lazy.ArgumentUtility.checkInteger({ count });
|
|
196
|
+
require_Lazy.ArgumentUtility.checkNotOptional({ randomizer });
|
|
197
|
+
return new require_TyneqCachedTerminalOperator.TyneqEnumerable({ getEnumerator: () => new RandomEnumerator(count, randomizer) }, new require_TyneqCachedTerminalOperator.QueryNode("random", [count, randomizer], null, "source"));
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Returns `true` if `source` is `null`, `undefined`, or an iterable whose first element is `null` or `undefined`.
|
|
201
|
+
*/
|
|
202
|
+
static isNullOrEmpty(source) {
|
|
203
|
+
if (source === null || source === void 0) return true;
|
|
204
|
+
return this.from(source).isNullOrEmpty();
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Creates a sequence of `count` integers starting from `start`.
|
|
208
|
+
*
|
|
209
|
+
* @remarks
|
|
210
|
+
* Returns an empty sequence when `count === 0`.
|
|
211
|
+
*
|
|
212
|
+
* @example
|
|
213
|
+
* ```ts
|
|
214
|
+
* Tyneq.range(1, 5).toArray(); // -> [1, 2, 3, 4, 5]
|
|
215
|
+
* ```
|
|
216
|
+
*
|
|
217
|
+
* @throws {ArgumentOutOfRangeError} When `count` is negative.
|
|
218
|
+
* @throws {ArgumentError} When `count` is not an integer.
|
|
219
|
+
*/
|
|
220
|
+
@require_TyneqCachedTerminalOperator.source({ source: "internal" }) static range(start, count) {
|
|
221
|
+
require_Lazy.ArgumentUtility.checkNonNegative({ count });
|
|
222
|
+
require_Lazy.ArgumentUtility.checkInteger({ count });
|
|
223
|
+
const end = start + count - 1;
|
|
224
|
+
return new require_TyneqCachedTerminalOperator.TyneqEnumerable({ getEnumerator: () => new RangeEnumerator(start, end) }, new require_TyneqCachedTerminalOperator.QueryNode("range", [start, count], null, "source"));
|
|
225
|
+
}
|
|
226
|
+
/** Returns an empty sequence with zero elements. */
|
|
227
|
+
@require_TyneqCachedTerminalOperator.source({ source: "internal" }) static empty() {
|
|
228
|
+
return new require_TyneqCachedTerminalOperator.TyneqEnumerable(new EnumerableAdapter([]), new require_TyneqCachedTerminalOperator.QueryNode("empty", [], null, "source"));
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Creates a sequence that yields `value` exactly `count` times.
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```ts
|
|
235
|
+
* Tyneq.repeat("x", 3).toArray(); // -> ["x", "x", "x"]
|
|
236
|
+
* ```
|
|
237
|
+
*
|
|
238
|
+
* @throws {ArgumentOutOfRangeError} When `count` is negative.
|
|
239
|
+
* @throws {ArgumentError} When `count` is not an integer.
|
|
240
|
+
*/
|
|
241
|
+
@require_TyneqCachedTerminalOperator.source({ source: "internal" }) static repeat(value, count) {
|
|
242
|
+
require_Lazy.ArgumentUtility.checkNonNegative({ count });
|
|
243
|
+
require_Lazy.ArgumentUtility.checkInteger({ count });
|
|
244
|
+
return new require_TyneqCachedTerminalOperator.TyneqEnumerable({ getEnumerator: () => new RepeatEnumerator(value, count) }, new require_TyneqCachedTerminalOperator.QueryNode("repeat", [value, count], null, "source"));
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Creates a sequence by repeatedly applying `next` to produce each element from the previous one.
|
|
248
|
+
*
|
|
249
|
+
* @remarks
|
|
250
|
+
* The selector receives `(currentValue, index)`. Each call's return value becomes the input
|
|
251
|
+
* for the next call. Omit `count` for an infinite sequence; pair with `take` to bound it.
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```ts
|
|
255
|
+
* Tyneq.generate(1, (x) => x * 2, 4).toArray(); // -> [2, 4, 8, 16]
|
|
256
|
+
* ```
|
|
257
|
+
*
|
|
258
|
+
* @throws {ArgumentNullError} When `next` is null or undefined.
|
|
259
|
+
* @throws {ArgumentOutOfRangeError} When `count` is negative.
|
|
260
|
+
* @throws {ArgumentError} When `count` is not an integer.
|
|
261
|
+
*/
|
|
262
|
+
@require_TyneqCachedTerminalOperator.source({ source: "internal" }) static generate(seed, next, count) {
|
|
263
|
+
require_Lazy.ArgumentUtility.checkNotOptional({ next });
|
|
264
|
+
if (count !== void 0) {
|
|
265
|
+
require_Lazy.ArgumentUtility.checkNonNegative({ count });
|
|
266
|
+
require_Lazy.ArgumentUtility.checkInteger({ count });
|
|
267
|
+
}
|
|
268
|
+
return new require_TyneqCachedTerminalOperator.TyneqEnumerable({ getEnumerator: () => new GenerateEnumerator(seed, next, count) }, new require_TyneqCachedTerminalOperator.QueryNode("generate", [
|
|
269
|
+
seed,
|
|
270
|
+
next,
|
|
271
|
+
count
|
|
272
|
+
], null, "source"));
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Creates a sequence that yields all elements from each source in order.
|
|
276
|
+
*
|
|
277
|
+
* @remarks
|
|
278
|
+
* Returns an empty sequence when called with no arguments.
|
|
279
|
+
*
|
|
280
|
+
* @example
|
|
281
|
+
* ```ts
|
|
282
|
+
* Tyneq.concat([1, 2], [3, 4], [5]).toArray(); // -> [1, 2, 3, 4, 5]
|
|
283
|
+
* ```
|
|
284
|
+
*
|
|
285
|
+
* @throws {ArgumentNullError} When any `source` is null or undefined.
|
|
286
|
+
* @throws {ArgumentTypeError} When any `source` is not iterable.
|
|
287
|
+
*/
|
|
288
|
+
@require_TyneqCachedTerminalOperator.source({ source: "internal" }) static concat(...sources) {
|
|
289
|
+
for (const source of sources) {
|
|
290
|
+
require_Lazy.ArgumentUtility.checkNotOptional({ source });
|
|
291
|
+
require_Lazy.ArgumentUtility.checkIterable({ source });
|
|
292
|
+
}
|
|
293
|
+
return new require_TyneqCachedTerminalOperator.TyneqEnumerable({ getEnumerator: () => new SourceConcatEnumerator(...sources) }, new require_TyneqCachedTerminalOperator.QueryNode("concat", sources, null, "source"));
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Pairs each element with its zero-based index.
|
|
297
|
+
*
|
|
298
|
+
* @remarks
|
|
299
|
+
* Each iteration produces independent index counters - safe to re-enumerate.
|
|
300
|
+
*
|
|
301
|
+
* @example
|
|
302
|
+
* ```ts
|
|
303
|
+
* Tyneq.enumerate(["a", "b", "c"]).toArray();
|
|
304
|
+
* // -> [[0, "a"], [1, "b"], [2, "c"]]
|
|
305
|
+
* ```
|
|
306
|
+
*
|
|
307
|
+
* @throws {ArgumentNullError} When `source` is null or undefined.
|
|
308
|
+
* @throws {ArgumentTypeError} When `source` is not iterable.
|
|
309
|
+
*/
|
|
310
|
+
static enumerate(source) {
|
|
311
|
+
require_Lazy.ArgumentUtility.checkNotOptional({ source });
|
|
312
|
+
require_Lazy.ArgumentUtility.checkIterable({ source });
|
|
313
|
+
return this.from({ *[Symbol.iterator]() {
|
|
314
|
+
let index = 0;
|
|
315
|
+
for (const item of source) yield [index++, item];
|
|
316
|
+
} });
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
//#endregion
|
|
320
|
+
//#region src/core/errors/KeyNotFoundError.ts
|
|
321
|
+
/**
|
|
322
|
+
* Thrown when a lookup is performed with a key that does not exist in the collection.
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* ```ts
|
|
326
|
+
* try { seq.toMap((x) => x.id).get(999); }
|
|
327
|
+
* catch (e) { if (e instanceof KeyNotFoundError) { ... } }
|
|
328
|
+
* ```
|
|
329
|
+
*
|
|
330
|
+
* @see {@link TyneqError}
|
|
331
|
+
* @group Errors
|
|
332
|
+
*/
|
|
333
|
+
var KeyNotFoundError = class extends require_Lazy.TyneqError {
|
|
334
|
+
constructor(message = "The given key was not present in the dictionary.", inner) {
|
|
335
|
+
super(message, { inner });
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
//#endregion
|
|
339
|
+
//#region src/core/errors/NotSupportedError.ts
|
|
340
|
+
/**
|
|
341
|
+
* Thrown when a requested operation is not supported.
|
|
342
|
+
*
|
|
343
|
+
* @example
|
|
344
|
+
* ```ts
|
|
345
|
+
* try { iterator.throw?.(new Error()); }
|
|
346
|
+
* catch (e) { if (e instanceof NotSupportedError) { ... } }
|
|
347
|
+
* ```
|
|
348
|
+
*
|
|
349
|
+
* @see {@link TyneqError}
|
|
350
|
+
* @group Errors
|
|
351
|
+
*/
|
|
352
|
+
var NotSupportedError = class extends require_Lazy.TyneqError {
|
|
353
|
+
constructor(message = "The requested operation is not supported.", inner) {
|
|
354
|
+
super(message, { inner });
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
//#endregion
|
|
358
|
+
//#region src/core/errors/CompilerError.ts
|
|
359
|
+
/**
|
|
360
|
+
* Thrown when the query plan compiler encounters a structural or semantic error
|
|
361
|
+
* while compiling a query plan into an executable sequence.
|
|
362
|
+
*
|
|
363
|
+
* @example
|
|
364
|
+
* ```ts
|
|
365
|
+
* try { compiler.compile(plan); }
|
|
366
|
+
* catch (e) {
|
|
367
|
+
* if (e instanceof CompilerError) {
|
|
368
|
+
* console.log(e.operatorName, e.phase, e.message);
|
|
369
|
+
* }
|
|
370
|
+
* }
|
|
371
|
+
* ```
|
|
372
|
+
*
|
|
373
|
+
* @see {@link TyneqError}
|
|
374
|
+
* @group Errors
|
|
375
|
+
*/
|
|
376
|
+
var CompilerError = class extends require_Lazy.TyneqError {
|
|
377
|
+
/** The name of the operator being compiled when the error occurred, if known. */
|
|
378
|
+
operatorName;
|
|
379
|
+
/**
|
|
380
|
+
* The compilation phase in which the error occurred.
|
|
381
|
+
* - `"transform"` - during query plan transformation (pre-compile)
|
|
382
|
+
* - `"source"` - while compiling a source node
|
|
383
|
+
* - `"operator"` - while applying an operator node
|
|
384
|
+
*/
|
|
385
|
+
phase;
|
|
386
|
+
constructor(message, phase, operatorName, inner) {
|
|
387
|
+
super(message, { inner });
|
|
388
|
+
this.phase = phase;
|
|
389
|
+
this.operatorName = operatorName;
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
//#endregion
|
|
393
|
+
//#region src/queryplan/QueryPlanPrinter.ts
|
|
394
|
+
/**
|
|
395
|
+
* Converts a query plan tree into a human-readable multi-line string.
|
|
396
|
+
*
|
|
397
|
+
* Implements `QueryPlanVisitor<string>`. The output lists operators from source to
|
|
398
|
+
* terminal, one per line, with indentation showing the pipeline depth.
|
|
399
|
+
*
|
|
400
|
+
* @example
|
|
401
|
+
* ```ts
|
|
402
|
+
* import { QueryPlanPrinter } from "tyneq/queryplan";
|
|
403
|
+
*
|
|
404
|
+
* const seq = Tyneq.range(1, 10).where(x => x % 2 === 0).select(x => x * x);
|
|
405
|
+
* console.log(QueryPlanPrinter.print(seq[tyneqQueryNode]!));
|
|
406
|
+
* // range(1, 10)
|
|
407
|
+
* // -> where(<fn>)
|
|
408
|
+
* // -> select(<fn>)
|
|
409
|
+
* ```
|
|
410
|
+
*
|
|
411
|
+
* @group QueryPlan
|
|
412
|
+
*/
|
|
413
|
+
var QueryPlanPrinter = class QueryPlanPrinter {
|
|
414
|
+
indent;
|
|
415
|
+
arrow;
|
|
416
|
+
maxInlineArrayItems;
|
|
417
|
+
constructor(options = {}) {
|
|
418
|
+
this.indent = options.indent ?? " ";
|
|
419
|
+
this.arrow = options.arrow ?? "->";
|
|
420
|
+
this.maxInlineArrayItems = options.maxInlineArrayItems ?? 3;
|
|
421
|
+
}
|
|
422
|
+
/** Renders the full query plan rooted at `node` as a multi-line string. */
|
|
423
|
+
visit(node) {
|
|
424
|
+
return this.buildPlan(node);
|
|
425
|
+
}
|
|
426
|
+
/** Convenience static: creates a printer with `options` and calls `visit(node)`. */
|
|
427
|
+
static print(node, options) {
|
|
428
|
+
return new QueryPlanPrinter(options).visit(node);
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Formats a single operator argument for display.
|
|
432
|
+
* Override to customise how arguments appear in printed plans.
|
|
433
|
+
*/
|
|
434
|
+
formatArg(arg) {
|
|
435
|
+
if (typeof arg === "function") return "<fn>";
|
|
436
|
+
if (arg === null) return "null";
|
|
437
|
+
if (arg === void 0) return "undefined";
|
|
438
|
+
if (typeof arg === "string") return `"${arg}"`;
|
|
439
|
+
if (Array.isArray(arg)) {
|
|
440
|
+
if (arg.length === 0) return "[]";
|
|
441
|
+
if (arg.length <= this.maxInlineArrayItems) return `[${arg.map((a) => this.formatArg(a)).join(", ")}]`;
|
|
442
|
+
return `[...${arg.length} items]`;
|
|
443
|
+
}
|
|
444
|
+
if (typeof arg === "object") return "{...}";
|
|
445
|
+
return String(arg);
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Formats one line of the plan output.
|
|
449
|
+
* Override to customise indentation or arrow style beyond what `QueryPlanPrinterOptions` allows.
|
|
450
|
+
*/
|
|
451
|
+
formatLine(name, argStr, isRoot) {
|
|
452
|
+
return `${isRoot ? "" : `${this.indent}${this.arrow} `}${name}(${argStr})`;
|
|
453
|
+
}
|
|
454
|
+
buildPlan(node) {
|
|
455
|
+
return this.collectNodes(node).map((n, index) => {
|
|
456
|
+
const argStr = n.args.map((a) => this.formatArg(a)).join(", ");
|
|
457
|
+
return this.formatLine(n.operatorName, argStr, index === 0);
|
|
458
|
+
}).join("\n");
|
|
459
|
+
}
|
|
460
|
+
collectNodes(node) {
|
|
461
|
+
const nodes = [];
|
|
462
|
+
let current = node;
|
|
463
|
+
while (current !== null) {
|
|
464
|
+
nodes.push(current);
|
|
465
|
+
current = current.source;
|
|
466
|
+
}
|
|
467
|
+
nodes.reverse();
|
|
468
|
+
return nodes;
|
|
469
|
+
}
|
|
470
|
+
};
|
|
471
|
+
//#endregion
|
|
472
|
+
//#region src/queryplan/QueryPlanWalker.ts
|
|
473
|
+
/**
|
|
474
|
+
* Concrete base class for side-effect query plan visitors.
|
|
475
|
+
*
|
|
476
|
+
* @remarks
|
|
477
|
+
* Traverses the node chain calling {@link QueryPlanWalker.visitNode} once per node.
|
|
478
|
+
* The traversal direction defaults to `"source-to-terminal"` (bottom-up: `from` before
|
|
479
|
+
* `where` before `select`) and can be changed to `"terminal-to-source"` (top-down) via
|
|
480
|
+
* the options object.
|
|
481
|
+
*
|
|
482
|
+
* ### Usage patterns
|
|
483
|
+
*
|
|
484
|
+
* **Direct instantiation with a callback** - no subclass needed for simple traversals:
|
|
485
|
+
* ```ts
|
|
486
|
+
* const names: string[] = [];
|
|
487
|
+
* new QueryPlanWalker({ callback: node => names.push(node.operatorName) }).visit(plan);
|
|
488
|
+
* ```
|
|
489
|
+
*
|
|
490
|
+
* **Subclass** - for stateful walkers that accumulate results across nodes:
|
|
491
|
+
* ```ts
|
|
492
|
+
* class NodeCounter extends QueryPlanWalker {
|
|
493
|
+
* public count = 0;
|
|
494
|
+
* protected override visitNode(_node: QueryPlanNode): void { this.count++; }
|
|
495
|
+
* }
|
|
496
|
+
*
|
|
497
|
+
* const counter = new NodeCounter();
|
|
498
|
+
* counter.visit(seq[tyneqQueryNode]!);
|
|
499
|
+
* console.log(counter.count); // number of operators in the pipeline
|
|
500
|
+
* ```
|
|
501
|
+
*
|
|
502
|
+
* **Top-down traversal:**
|
|
503
|
+
* ```ts
|
|
504
|
+
* new QueryPlanWalker({
|
|
505
|
+
* callback: node => console.log(node.operatorName),
|
|
506
|
+
* direction: "terminal-to-source",
|
|
507
|
+
* }).visit(plan);
|
|
508
|
+
* ```
|
|
509
|
+
*
|
|
510
|
+
* **Subclass with direction override** - pass options to `super`:
|
|
511
|
+
* ```ts
|
|
512
|
+
* class ReverseCollector extends QueryPlanWalker {
|
|
513
|
+
* public readonly names: string[] = [];
|
|
514
|
+
* public constructor() { super({ direction: "terminal-to-source" }); }
|
|
515
|
+
* protected override visitNode(node: QueryPlanNode): void {
|
|
516
|
+
* this.names.push(node.operatorName);
|
|
517
|
+
* }
|
|
518
|
+
* }
|
|
519
|
+
* ```
|
|
520
|
+
*
|
|
521
|
+
* @group QueryPlan
|
|
522
|
+
*/
|
|
523
|
+
var QueryPlanWalker = class {
|
|
524
|
+
callback;
|
|
525
|
+
direction;
|
|
526
|
+
/**
|
|
527
|
+
* @param options - Optional configuration for the walker.
|
|
528
|
+
*/
|
|
529
|
+
constructor(options) {
|
|
530
|
+
this.callback = options?.callback;
|
|
531
|
+
this.direction = options?.direction ?? "source-to-terminal";
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Walks the full chain rooted at `node`, calling {@link visitNode} for each node
|
|
535
|
+
* in the configured direction.
|
|
536
|
+
*/
|
|
537
|
+
visit(node) {
|
|
538
|
+
if (this.direction === "source-to-terminal") {
|
|
539
|
+
if (node.source !== null) this.visit(node.source);
|
|
540
|
+
this.visitNode(node);
|
|
541
|
+
} else {
|
|
542
|
+
this.visitNode(node);
|
|
543
|
+
if (node.source !== null) this.visit(node.source);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* Called once per node during traversal.
|
|
548
|
+
*
|
|
549
|
+
* @remarks
|
|
550
|
+
* The default implementation fires the callback passed via options (if any).
|
|
551
|
+
* Override this method in a subclass to provide custom behaviour. Subclasses that
|
|
552
|
+
* override this method decide whether to call `super.visitNode(node)` to also fire
|
|
553
|
+
* the options callback.
|
|
554
|
+
*
|
|
555
|
+
* @param node - The current node being visited.
|
|
556
|
+
*/
|
|
557
|
+
visitNode(node) {
|
|
558
|
+
this.callback?.(node);
|
|
559
|
+
}
|
|
560
|
+
};
|
|
561
|
+
//#endregion
|
|
562
|
+
//#region src/queryplan/QueryPlanTransformer.ts
|
|
563
|
+
/**
|
|
564
|
+
* Base class for immutable query plan rewriting.
|
|
565
|
+
*
|
|
566
|
+
* @remarks
|
|
567
|
+
* Recursively rebuilds the node chain, calling {@link QueryPlanTransformer.transformNode}
|
|
568
|
+
* once per node. The default implementation is an **identity transform** - every node is
|
|
569
|
+
* reconstructed with the same data, producing a structurally equivalent copy.
|
|
570
|
+
*
|
|
571
|
+
* Subclasses override `transformNode` to intercept specific operators. Three rewrite
|
|
572
|
+
* patterns are possible:
|
|
573
|
+
*
|
|
574
|
+
* - **Rewrite a node** - return a new `QueryNode` with different `operatorName` or `args`
|
|
575
|
+
* - **Remove a node** - return `source` directly, skipping this node
|
|
576
|
+
* - **Collapse two nodes into one** - use `source` as the new node's `source` (fusing
|
|
577
|
+
* the current node with its already-transformed predecessor)
|
|
578
|
+
*
|
|
579
|
+
* @example
|
|
580
|
+
* ```ts
|
|
581
|
+
* // Rename all 'where' nodes to 'filter' in the plan view
|
|
582
|
+
* class RenameWhere extends QueryPlanTransformer {
|
|
583
|
+
* protected override transformNode(node: QueryPlanNode, source: QueryPlanNode | null): QueryPlanNode {
|
|
584
|
+
* if (node.operatorName === "where") {
|
|
585
|
+
* return new QueryNode("filter", node.args, source, node.category);
|
|
586
|
+
* }
|
|
587
|
+
* return super.transformNode(node, source);
|
|
588
|
+
* }
|
|
589
|
+
* }
|
|
590
|
+
* ```
|
|
591
|
+
*
|
|
592
|
+
* @group QueryPlan
|
|
593
|
+
*/
|
|
594
|
+
var QueryPlanTransformer = class {
|
|
595
|
+
/**
|
|
596
|
+
* Transforms the full chain rooted at `node` and returns the new root node.
|
|
597
|
+
*
|
|
598
|
+
* @remarks
|
|
599
|
+
* Processes source-first (bottom-up): the source chain is fully transformed before
|
|
600
|
+
* `transformNode` is called for the current node. This means `source` passed to
|
|
601
|
+
* `transformNode` is always already the transformed predecessor.
|
|
602
|
+
*/
|
|
603
|
+
visit(node) {
|
|
604
|
+
const transformedSource = node.source !== null ? this.visit(node.source) : null;
|
|
605
|
+
return this.transformNode(node, transformedSource);
|
|
606
|
+
}
|
|
607
|
+
/**
|
|
608
|
+
* Transforms a single node. Override to intercept specific operators.
|
|
609
|
+
*
|
|
610
|
+
* @remarks
|
|
611
|
+
* The default implementation reconstructs the node with identical data (identity transform).
|
|
612
|
+
* `source` is the already-transformed predecessor - use it as the `source` of any returned
|
|
613
|
+
* node to preserve chain continuity.
|
|
614
|
+
*
|
|
615
|
+
* @param node - The original node (unmodified).
|
|
616
|
+
* @param source - The transformed predecessor, or `null` for source nodes.
|
|
617
|
+
*/
|
|
618
|
+
transformNode(node, source) {
|
|
619
|
+
return new require_TyneqCachedTerminalOperator.QueryNode(node.operatorName, node.args, source, node.category, node.sourceKind);
|
|
620
|
+
}
|
|
621
|
+
};
|
|
622
|
+
//#endregion
|
|
623
|
+
//#region src/queryplan/QueryPlanOptimizer.ts
|
|
624
|
+
/**
|
|
625
|
+
* A built-in {@link QueryPlanTransformer} that fuses redundant consecutive operators.
|
|
626
|
+
*
|
|
627
|
+
* @remarks
|
|
628
|
+
* **This optimizer rewrites the query plan tree only - it does not affect execution of the
|
|
629
|
+
* original sequence.** The returned `QueryPlanNode` reflects what an optimized pipeline would
|
|
630
|
+
* look like; the live sequence that produced the original plan is unchanged.
|
|
631
|
+
*
|
|
632
|
+
* **Fusion is only semantics-preserving for pure, side-effect-free functions.**
|
|
633
|
+
* If a predicate or projection has side effects (e.g. logging, mutation), fusing two nodes into
|
|
634
|
+
* one changes when and how many times those effects fire. For example, in a fused `where`, the
|
|
635
|
+
* second predicate is never called for items that fail the first - any mutation inside the second
|
|
636
|
+
* predicate is skipped for those items. Do not use this optimizer on pipelines with impure
|
|
637
|
+
* predicates or projections.
|
|
638
|
+
*
|
|
639
|
+
* ### Fusions applied
|
|
640
|
+
*
|
|
641
|
+
* | Pattern | Result |
|
|
642
|
+
* |---------|--------|
|
|
643
|
+
* | `where(a) -> where(b)` | `where(x => a(x) && b(x))` |
|
|
644
|
+
* | `select(a) -> select(b)` | `select(x => b(a(x)))` |
|
|
645
|
+
*
|
|
646
|
+
* Additional fusions can be added by subclassing and overriding
|
|
647
|
+
* {@link QueryPlanTransformer.transformNode}.
|
|
648
|
+
*
|
|
649
|
+
* @example
|
|
650
|
+
* ```ts
|
|
651
|
+
* import { Tyneq, tyneqQueryNode, QueryPlanOptimizer, QueryPlanPrinter } from "tyneq";
|
|
652
|
+
*
|
|
653
|
+
* const seq = Tyneq.from([1, 2, 3])
|
|
654
|
+
* .where(x => x > 1)
|
|
655
|
+
* .where(x => x < 3)
|
|
656
|
+
* .select(x => x * 2)
|
|
657
|
+
* .select(x => x + 1);
|
|
658
|
+
*
|
|
659
|
+
* const original = seq[tyneqQueryNode]!;
|
|
660
|
+
* const optimized = new QueryPlanOptimizer().visit(original);
|
|
661
|
+
*
|
|
662
|
+
* console.log(QueryPlanPrinter.print(original));
|
|
663
|
+
* // from([...])
|
|
664
|
+
* // -> where(<fn>)
|
|
665
|
+
* // -> where(<fn>)
|
|
666
|
+
* // -> select(<fn>)
|
|
667
|
+
* // -> select(<fn>)
|
|
668
|
+
*
|
|
669
|
+
* console.log(QueryPlanPrinter.print(optimized));
|
|
670
|
+
* // from([...])
|
|
671
|
+
* // -> where(<fn>)
|
|
672
|
+
* // -> select(<fn>)
|
|
673
|
+
* ```
|
|
674
|
+
*
|
|
675
|
+
* @group QueryPlan
|
|
676
|
+
*/
|
|
677
|
+
var QueryPlanOptimizer = class extends QueryPlanTransformer {
|
|
678
|
+
transformNode(node, source) {
|
|
679
|
+
if (node.operatorName === "where" && source?.operatorName === "where") return this.fuseWhere(node, source);
|
|
680
|
+
if (node.operatorName === "select" && source?.operatorName === "select") return this.fuseSelect(node, source);
|
|
681
|
+
return super.transformNode(node, source);
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* @remarks Fusion is only semantics-preserving for pure, side-effect-free predicates.
|
|
685
|
+
*/
|
|
686
|
+
fuseWhere(node, source) {
|
|
687
|
+
const predA = source.args[0];
|
|
688
|
+
const predB = node.args[0];
|
|
689
|
+
const fused = (x) => predA(x) && predB(x);
|
|
690
|
+
return new require_TyneqCachedTerminalOperator.QueryNode("where", [fused], source.source, "streaming");
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* @remarks Fusion is only semantics-preserving for pure, side-effect-free projections.
|
|
694
|
+
*/
|
|
695
|
+
fuseSelect(node, source) {
|
|
696
|
+
const projA = source.args[0];
|
|
697
|
+
const projB = node.args[0];
|
|
698
|
+
const fused = (x) => projB(projA(x));
|
|
699
|
+
return new require_TyneqCachedTerminalOperator.QueryNode("select", [fused], source.source, "streaming");
|
|
700
|
+
}
|
|
701
|
+
};
|
|
702
|
+
//#endregion
|
|
703
|
+
//#region src/queryplan/compiler/QueryPlanCompiler.ts
|
|
704
|
+
/**
|
|
705
|
+
* Compiles a query plan tree into an executable `TyneqSequence`.
|
|
706
|
+
*
|
|
707
|
+
* @remarks
|
|
708
|
+
* Walks the `QueryPlanNode` chain from source to terminal, reconstructing each operator by
|
|
709
|
+
* looking it up in the `OperatorRegistry` and applying it to the compiled source.
|
|
710
|
+
* An optional list of `QueryPlanTransformer` instances runs before compilation, allowing
|
|
711
|
+
* optimization or rewriting of the plan.
|
|
712
|
+
*
|
|
713
|
+
* @example
|
|
714
|
+
* ```ts
|
|
715
|
+
* import { Tyneq, tyneqQueryNode, QueryPlanCompiler, QueryPlanOptimizer } from "tyneq";
|
|
716
|
+
*
|
|
717
|
+
* const seq = Tyneq.from([1, 2, 3]).where(x => x > 1).select(x => x * 2);
|
|
718
|
+
* const compiler = new QueryPlanCompiler([new QueryPlanOptimizer()]);
|
|
719
|
+
* const result = compiler.compile(seq[tyneqQueryNode]!);
|
|
720
|
+
* result.toArray(); // -> [4, 6]
|
|
721
|
+
* ```
|
|
722
|
+
*
|
|
723
|
+
* @group QueryPlan
|
|
724
|
+
*/
|
|
725
|
+
var QueryPlanCompiler = class {
|
|
726
|
+
transformers;
|
|
727
|
+
constructor(transformers = []) {
|
|
728
|
+
this.transformers = [...transformers];
|
|
729
|
+
}
|
|
730
|
+
/**
|
|
731
|
+
* Compile a query plan into an executable sequence.
|
|
732
|
+
*
|
|
733
|
+
* Runs all registered transformers before compiling. Use {@link compileRaw} to skip
|
|
734
|
+
* the transform phase when the plan is already optimised.
|
|
735
|
+
*
|
|
736
|
+
* @param node - The root node of the query plan to compile.
|
|
737
|
+
* @param options - Optional compile-time overrides. Use `options.source` to supply a
|
|
738
|
+
* different data source than the one stored in the plan.
|
|
739
|
+
* @returns The compiled sequence typed as `TyneqSequence<T>` by default.
|
|
740
|
+
* If you know the plan ends in an operator that returns a subtype (e.g. `orderBy` ->
|
|
741
|
+
* `TyneqOrderedSequence`, `memoize` -> `TyneqCachedSequence`), supply `TResult` explicitly:
|
|
742
|
+
* `compiler.compile<number, TyneqOrderedSequence<number>>(node)`.
|
|
743
|
+
*/
|
|
744
|
+
compile(node, options) {
|
|
745
|
+
if (node === null || node === void 0) throw new CompilerError("compile() received a null or undefined query plan node. Ensure the sequence was created via Tyneq.from(), Tyneq.range(), or another source operator before compiling.", "source");
|
|
746
|
+
const transformedNode = this.transform(node);
|
|
747
|
+
return this.compileNode(transformedNode, options);
|
|
748
|
+
}
|
|
749
|
+
/**
|
|
750
|
+
* Compile a pre-optimised query plan into an executable sequence, skipping the
|
|
751
|
+
* transform phase.
|
|
752
|
+
*
|
|
753
|
+
* @remarks
|
|
754
|
+
* Use this overload when you have already run transformers externally (or deliberately
|
|
755
|
+
* want to bypass them) and want to compile the node as-is. Equivalent to constructing
|
|
756
|
+
* a `QueryPlanCompiler` with no transformers and calling `compile()`.
|
|
757
|
+
*
|
|
758
|
+
* @param node - The root node of the already-transformed query plan to compile.
|
|
759
|
+
* @param options - Optional compile-time overrides. Use `options.source` to supply a
|
|
760
|
+
* different data source than the one stored in the plan.
|
|
761
|
+
*/
|
|
762
|
+
compileRaw(node, options) {
|
|
763
|
+
if (node === null || node === void 0) throw new CompilerError("compileRaw() received a null or undefined query plan node. Ensure the sequence was created via Tyneq.from(), Tyneq.range(), or another source operator before compiling.", "source");
|
|
764
|
+
return this.compileNode(node, options);
|
|
765
|
+
}
|
|
766
|
+
transform(node) {
|
|
767
|
+
let transformedNode = node;
|
|
768
|
+
for (const transformer of this.transformers) try {
|
|
769
|
+
transformedNode = transformer.visit(transformedNode);
|
|
770
|
+
} catch (e) {
|
|
771
|
+
throw new CompilerError(`Transformer "${transformer.constructor.name}" threw during transformation.`, "transform", void 0, e instanceof Error ? e : void 0);
|
|
772
|
+
}
|
|
773
|
+
return transformedNode;
|
|
774
|
+
}
|
|
775
|
+
compileNode(node, options) {
|
|
776
|
+
if (node.category === "source") return this.compileSource(node, options);
|
|
777
|
+
if (node.source === null) throw new CompilerError("Operator node is missing a source node. Every operator node must have a source.", "operator", node.operatorName);
|
|
778
|
+
return this.applyOperator(this.compileNode(node.source, options), node);
|
|
779
|
+
}
|
|
780
|
+
compileSource(node, options) {
|
|
781
|
+
const entry = require_TyneqCachedTerminalOperator.OperatorRegistry.getSource(node.operatorName);
|
|
782
|
+
if (!entry) throw new CompilerError(`Unknown source operator "${node.operatorName}". Register it via OperatorRegistry.registerSource() before compiling.`, "source", node.operatorName);
|
|
783
|
+
const args = options?.source !== void 0 ? [options.source, ...node.args.slice(1)] : [...node.args];
|
|
784
|
+
return entry.impl.apply(null, args);
|
|
785
|
+
}
|
|
786
|
+
applyOperator(source, node) {
|
|
787
|
+
const entry = this.findOperatorEntry(node.operatorName, source);
|
|
788
|
+
if (!entry) {
|
|
789
|
+
const sourceType = source !== null && source !== void 0 ? Object.getPrototypeOf(source)?.constructor?.name ?? typeof source : "null";
|
|
790
|
+
throw new CompilerError(require_TyneqCachedTerminalOperator.OperatorRegistry.hasOperator(node.operatorName) ? `Operator "${node.operatorName}" is not registered for sequence type ${sourceType}. Ensure the source sequence is of the correct type for this operator.` : `Operator "${node.operatorName}" is not registered. Register it via @operator, createOperator, or createGeneratorOperator before compiling.`, "operator", node.operatorName);
|
|
791
|
+
}
|
|
792
|
+
return entry.impl.apply(source, [...node.args]);
|
|
793
|
+
}
|
|
794
|
+
findOperatorEntry(operatorName, source) {
|
|
795
|
+
if (source === null || source === void 0) return;
|
|
796
|
+
let proto = Object.getPrototypeOf(source);
|
|
797
|
+
while (proto !== null) {
|
|
798
|
+
const ctor = proto.constructor;
|
|
799
|
+
if (ctor !== void 0) {
|
|
800
|
+
const entry = require_TyneqCachedTerminalOperator.OperatorRegistry.getOperator(operatorName, ctor);
|
|
801
|
+
if (entry !== void 0) return entry;
|
|
802
|
+
}
|
|
803
|
+
proto = Object.getPrototypeOf(proto);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
};
|
|
807
|
+
//#endregion
|
|
808
|
+
exports.ArgumentError = require_Lazy.ArgumentError;
|
|
809
|
+
exports.ArgumentNullError = require_Lazy.ArgumentNullError;
|
|
810
|
+
exports.ArgumentOutOfRangeError = require_Lazy.ArgumentOutOfRangeError;
|
|
811
|
+
exports.ArgumentTypeError = require_Lazy.ArgumentTypeError;
|
|
812
|
+
exports.ArgumentUtility = require_Lazy.ArgumentUtility;
|
|
813
|
+
exports.CompilerError = CompilerError;
|
|
814
|
+
exports.InvalidOperationError = require_TyneqCachedTerminalOperator.InvalidOperationError;
|
|
815
|
+
exports.KeyNotFoundError = KeyNotFoundError;
|
|
816
|
+
exports.Lazy = require_Lazy.Lazy;
|
|
817
|
+
exports.NotSupportedError = NotSupportedError;
|
|
818
|
+
exports.OperatorMetadata = require_TyneqCachedTerminalOperator.OperatorMetadata;
|
|
819
|
+
exports.OperatorRegistry = require_TyneqCachedTerminalOperator.OperatorRegistry;
|
|
820
|
+
exports.PluginError = require_TyneqCachedTerminalOperator.PluginError;
|
|
821
|
+
exports.QueryNode = require_TyneqCachedTerminalOperator.QueryNode;
|
|
822
|
+
exports.QueryPlanCompiler = QueryPlanCompiler;
|
|
823
|
+
exports.QueryPlanOptimizer = QueryPlanOptimizer;
|
|
824
|
+
exports.QueryPlanPrinter = QueryPlanPrinter;
|
|
825
|
+
exports.QueryPlanTransformer = QueryPlanTransformer;
|
|
826
|
+
exports.QueryPlanWalker = QueryPlanWalker;
|
|
827
|
+
exports.ReflectionContext = require_Lazy.ReflectionContext;
|
|
828
|
+
exports.ReflectionError = require_Lazy.ReflectionError;
|
|
829
|
+
exports.RegistryError = require_TyneqCachedTerminalOperator.RegistryError;
|
|
830
|
+
exports.SequenceContainsNoElementsError = require_TyneqCachedTerminalOperator.SequenceContainsNoElementsError;
|
|
831
|
+
exports.Tyneq = Tyneq;
|
|
832
|
+
exports.TyneqBaseEnumerator = require_TyneqCachedTerminalOperator.TyneqBaseEnumerator;
|
|
833
|
+
exports.TyneqCachedEnumerable = require_TyneqCachedTerminalOperator.TyneqCachedEnumerable;
|
|
834
|
+
exports.TyneqCachedEnumerator = require_TyneqCachedTerminalOperator.TyneqCachedEnumerator;
|
|
835
|
+
exports.TyneqCachedTerminalOperator = require_TyneqCachedTerminalOperator.TyneqCachedTerminalOperator;
|
|
836
|
+
exports.TyneqComparer = require_TyneqCachedTerminalOperator.TyneqComparer;
|
|
837
|
+
exports.TyneqEnumerator = require_TyneqCachedTerminalOperator.TyneqEnumerator;
|
|
838
|
+
exports.TyneqError = require_Lazy.TyneqError;
|
|
839
|
+
exports.TyneqOrderedEnumerable = require_TyneqCachedTerminalOperator.TyneqOrderedEnumerable;
|
|
840
|
+
exports.TyneqOrderedEnumerator = require_TyneqCachedTerminalOperator.TyneqOrderedEnumerator;
|
|
841
|
+
exports.TyneqOrderedTerminalOperator = require_TyneqCachedTerminalOperator.TyneqOrderedTerminalOperator;
|
|
842
|
+
exports.TyneqTerminalOperator = require_TyneqCachedTerminalOperator.TyneqTerminalOperator;
|
|
843
|
+
exports.TypeGuardUtility = require_Lazy.TypeGuardUtility;
|
|
844
|
+
exports.ValidationBuilder = require_ValidationBuilder.ValidationBuilder;
|
|
845
|
+
exports.ValidationError = require_ValidationBuilder.ValidationError;
|
|
846
|
+
exports.cachedOperator = require_TyneqCachedTerminalOperator.cachedOperator;
|
|
847
|
+
exports.cachedTerminal = require_TyneqCachedTerminalOperator.cachedTerminal;
|
|
848
|
+
exports.createCachedOperator = require_TyneqCachedTerminalOperator.createCachedOperator;
|
|
849
|
+
exports.createCachedTerminalOperator = require_TyneqCachedTerminalOperator.createCachedTerminalOperator;
|
|
850
|
+
exports.createGeneratorOperator = require_TyneqCachedTerminalOperator.createGeneratorOperator;
|
|
851
|
+
exports.createOperator = require_TyneqCachedTerminalOperator.createOperator;
|
|
852
|
+
exports.createOrderedOperator = require_TyneqCachedTerminalOperator.createOrderedOperator;
|
|
853
|
+
exports.createOrderedTerminalOperator = require_TyneqCachedTerminalOperator.createOrderedTerminalOperator;
|
|
854
|
+
exports.createTerminalOperator = require_TyneqCachedTerminalOperator.createTerminalOperator;
|
|
855
|
+
exports.isSourceNode = require_TyneqCachedTerminalOperator.isSourceNode;
|
|
856
|
+
exports.operator = require_TyneqCachedTerminalOperator.operator;
|
|
857
|
+
exports.orderedOperator = require_TyneqCachedTerminalOperator.orderedOperator;
|
|
858
|
+
exports.orderedTerminal = require_TyneqCachedTerminalOperator.orderedTerminal;
|
|
859
|
+
exports.reflect = require_Lazy.reflect;
|
|
860
|
+
exports.terminal = require_TyneqCachedTerminalOperator.terminal;
|
|
861
|
+
exports.tyneqQueryNode = require_TyneqCachedTerminalOperator.tyneqQueryNode;
|
|
862
|
+
|
|
863
|
+
//# sourceMappingURL=index.cjs.map
|