fusee-framework 2.7.2 → 2.7.3

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.
@@ -1,757 +0,0 @@
1
- import { computed } from '../core/signal.js'
2
-
3
- /** Default ascending comparer used by orderBy()/thenBy() when no comparer is supplied. */
4
- function defaultComparer(a, b) {
5
- if (a === b) return 0
6
- if (a == null) return b == null ? 0 : -1
7
- if (b == null) return 1
8
- return a < b ? -1 : a > b ? 1 : 0
9
- }
10
-
11
- /** Splits the flexible (predicate?, defaultValue?) argument list used by the *OrDefault() methods. */
12
- function resolveOrDefaultArgs(args) {
13
- if (args.length === 0) return { predicate: undefined, defaultValue: null }
14
- if (typeof args[0] === 'function') {
15
- return { predicate: args[0], defaultValue: args.length > 1 ? args[1] : null }
16
- }
17
- return { predicate: undefined, defaultValue: args[0] }
18
- }
19
-
20
- /** Wraps a group's key with its elements; iterating the result yields the elements, like a LINQ grouping. */
21
- function createGrouping(key, items) {
22
- const grouping = new Enumerable(() => items)
23
- grouping.key = key
24
- return grouping
25
- }
26
-
27
- /**
28
- * A lazily-evaluated LINQ-to-Objects style sequence.
29
- * Every intermediate operator (where, select, orderBy, ...) is deferred
30
- */
31
- export class Enumerable {
32
- constructor(iteratorFactory) {
33
- this._iteratorFactory = iteratorFactory
34
- }
35
-
36
- [Symbol.iterator]() {
37
- const iterable = this._iteratorFactory()
38
- return iterable[Symbol.iterator] ? iterable[Symbol.iterator]() : iterable
39
- }
40
-
41
- // deferred (lazy) operators - each returns a new Enumerable
42
-
43
- where(predicate) {
44
- const self = this
45
- return new Enumerable(function* () {
46
- let i = 0
47
- for (const item of self)
48
- if (predicate(item, i++))
49
- yield item
50
- })
51
- }
52
-
53
- select(selector) {
54
- const self = this
55
- return new Enumerable(function* () {
56
- let i = 0
57
- for (const item of self)
58
- yield selector(item, i++)
59
- })
60
- }
61
-
62
- selectMany(collectionSelector, resultSelector) {
63
- const self = this
64
- return new Enumerable(function* () {
65
- let i = 0
66
- for (const item of self) {
67
- for (const inner of collectionSelector(item, i++)) {
68
- yield resultSelector ? resultSelector(item, inner) : inner
69
- }
70
- }
71
- })
72
- }
73
-
74
- take(count) {
75
- const self = this
76
- return new Enumerable(function* () {
77
- if (count <= 0) return
78
- let i = 0
79
- for (const item of self) {
80
- yield item
81
- if (++i >= count) break
82
- }
83
- })
84
- }
85
-
86
- takeWhile(predicate) {
87
- const self = this
88
- return new Enumerable(function* () {
89
- let i = 0
90
- for (const item of self) {
91
- if (!predicate(item, i++)) break
92
- yield item
93
- }
94
- })
95
- }
96
-
97
- takeLast(count) {
98
- return new Enumerable(() => {
99
- if (count <= 0) return []
100
- const buffer = []
101
- for (const item of this) {
102
- buffer.push(item)
103
- if (buffer.length > count)
104
- buffer.shift()
105
- }
106
- return buffer
107
- })
108
- }
109
-
110
- skip(count) {
111
- const self = this
112
- return new Enumerable(function* () {
113
- let i = 0
114
- for (const item of self) {
115
- if (i++ < count) continue
116
- yield item
117
- }
118
- })
119
- }
120
-
121
- skipWhile(predicate) {
122
- const self = this
123
- return new Enumerable(function* () {
124
- let i = 0
125
- let skipping = true
126
- for (const item of self) {
127
- if (skipping && predicate(item, i++)) continue
128
- skipping = false
129
- yield item
130
- }
131
- })
132
- }
133
-
134
- skipLast(count) {
135
- const self = this
136
- return new Enumerable(function* () {
137
- if (count <= 0) {
138
- yield* self
139
- return
140
- }
141
-
142
- const buffer = []
143
- for (const item of self) {
144
- buffer.push(item)
145
- if (buffer.length > count) {
146
- yield buffer.shift()
147
- }
148
- }
149
- })
150
- }
151
-
152
- distinct(keySelector) {
153
- const self = this
154
- return new Enumerable(function* () {
155
- const seen = new Set()
156
- for (const item of self) {
157
- const key = keySelector ? keySelector(item) : item
158
- if (seen.has(key)) continue
159
- seen.add(key)
160
- yield item
161
- }
162
- })
163
- }
164
-
165
- concat(...others) {
166
- const self = this
167
- return new Enumerable(function* () {
168
- yield* self
169
- for (const other of others)
170
- yield* from(other)
171
- })
172
- }
173
-
174
- union(other, keySelector) {
175
- return this.concat(other).distinct(keySelector)
176
- }
177
-
178
- intersect(other, keySelector) {
179
- const self = this
180
- return new Enumerable(function* () {
181
- const otherKeys = new Set()
182
- for (const item of from(other))
183
- otherKeys.add(keySelector ? keySelector(item) : item)
184
- const seen = new Set()
185
- for (const item of self) {
186
- const key = keySelector ? keySelector(item) : item
187
- if (otherKeys.has(key) && !seen.has(key)) {
188
- seen.add(key)
189
- yield item
190
- }
191
- }
192
- })
193
- }
194
-
195
- except(other, keySelector) {
196
- const self = this
197
- return new Enumerable(function* () {
198
- const otherKeys = new Set()
199
- for (const item of from(other))
200
- otherKeys.add(keySelector ? keySelector(item) : item)
201
- const seen = new Set()
202
- for (const item of self) {
203
- const key = keySelector ? keySelector(item) : item
204
- if (!otherKeys.has(key) && !seen.has(key)) {
205
- seen.add(key)
206
- yield item
207
- }
208
- }
209
- })
210
- }
211
-
212
- zip(other, resultSelector) {
213
- const self = this
214
- return new Enumerable(function* () {
215
- const it1 = self[Symbol.iterator]()
216
- const it2 = from(other)[Symbol.iterator]()
217
- while (true) {
218
- const a = it1.next()
219
- const b = it2.next()
220
- if (a.done || b.done) return
221
- yield resultSelector ? resultSelector(a.value, b.value) : [a.value, b.value]
222
- }
223
- })
224
- }
225
-
226
- append(item) {
227
- return this.concat([item])
228
- }
229
-
230
- prepend(item) {
231
- const self = this
232
- return new Enumerable(function* () {
233
- yield item
234
- yield* self
235
- })
236
- }
237
-
238
- defaultIfEmpty(defaultValue = null) {
239
- const self = this
240
- return new Enumerable(function* () {
241
- let any = false
242
- for (const item of self) {
243
- any = true
244
- yield item
245
- }
246
- if (!any) yield defaultValue
247
- })
248
- }
249
-
250
- chunk(size) {
251
- if (!(size > 0)) throw new Error('[framework] chunk() size must be greater than 0')
252
- const self = this
253
- return new Enumerable(function* () {
254
- let buffer = []
255
- for (const item of self) {
256
- buffer.push(item)
257
- if (buffer.length === size) {
258
- yield buffer
259
- buffer = []
260
- }
261
- }
262
- if (buffer.length) yield buffer
263
- })
264
- }
265
-
266
- reverse() {
267
- const self = this
268
- return new Enumerable(function* () {
269
- const items = [...self]
270
- for (let i = items.length - 1; i >= 0; i--)
271
- yield items[i]
272
- })
273
- }
274
-
275
- orderBy(keySelector, comparer = defaultComparer) {
276
- return new OrderedEnumerable(() => this, [{ keySelector, comparer, descending: false }])
277
- }
278
-
279
- orderByDescending(keySelector, comparer = defaultComparer) {
280
- return new OrderedEnumerable(() => this, [{ keySelector, comparer, descending: true }])
281
- }
282
-
283
- groupBy(keySelector, elementSelector, resultSelector) {
284
- const self = this
285
- return new Enumerable(function* () {
286
- const groups = new Map()
287
- for (const item of self) {
288
- const key = keySelector(item)
289
- const element = elementSelector ? elementSelector(item) : item
290
- if (!groups.has(key))
291
- groups.set(key, [])
292
- groups.get(key).push(element)
293
- }
294
- for (const [key, items] of groups) {
295
- yield resultSelector ? resultSelector(key, items) : createGrouping(key, items)
296
- }
297
- })
298
- }
299
-
300
- join(inner, outerKeySelector, innerKeySelector, resultSelector) {
301
- const self = this
302
- return new Enumerable(function* () {
303
- const innerMap = new Map()
304
- for (const item of from(inner)) {
305
- const key = innerKeySelector(item)
306
- if (!innerMap.has(key))
307
- innerMap.set(key, [])
308
- innerMap.get(key).push(item)
309
- }
310
- for (const outerItem of self) {
311
- const matches = innerMap.get(outerKeySelector(outerItem))
312
- if (!matches)
313
- continue
314
- for (const innerItem of matches)
315
- yield resultSelector(outerItem, innerItem)
316
- }
317
- })
318
- }
319
-
320
- groupJoin(inner, outerKeySelector, innerKeySelector, resultSelector) {
321
- const self = this
322
- return new Enumerable(function* () {
323
- const innerMap = new Map()
324
- for (const item of from(inner)) {
325
- const key = innerKeySelector(item)
326
- if (!innerMap.has(key))
327
- innerMap.set(key, [])
328
- innerMap.get(key).push(item)
329
- }
330
- for (const outerItem of self) {
331
- const matches = innerMap.get(outerKeySelector(outerItem)) || []
332
- yield resultSelector(outerItem, matches)
333
- }
334
- })
335
- }
336
-
337
- // terminal (eager) operators
338
-
339
- ofType(type) {
340
- const self = this
341
- return new Enumerable(function* () {
342
- if (typeof type === 'string') {
343
- for (const item of self) {
344
- if (typeof item === type)
345
- yield item
346
- }
347
- } else if (typeof type === 'function') {
348
- for (const item of self) {
349
- if (item instanceof type)
350
- yield item
351
- }
352
- }
353
- })
354
- }
355
-
356
- toArray() {
357
- return [...this]
358
- }
359
-
360
- toMap(keySelector, valueSelector) {
361
- const map = new Map()
362
- let i = 0
363
- for (const item of this) {
364
- const key = keySelector(item, i)
365
- if (map.has(key))
366
- console.warn(`[framework] toMap(): duplicate key "${key}", overwriting previous value`)
367
- map.set(key, valueSelector ? valueSelector(item, i) : item)
368
- i++
369
- }
370
- return map
371
- }
372
-
373
- toSet(keySelector) {
374
- const set = new Set()
375
- let i = 0
376
- for (const item of this) {
377
- set.add(keySelector ? keySelector(item, i++) : item)
378
- }
379
- return set
380
- }
381
-
382
- toLookup(keySelector, elementSelector) {
383
- const map = new Map()
384
- let i = 0
385
- for (const item of this) {
386
- const key = keySelector(item, i)
387
- if (!map.has(key)) map.set(key, [])
388
- map.get(key).push(elementSelector ? elementSelector(item, i) : item)
389
- i++
390
- }
391
- return map
392
- }
393
-
394
- toObject(keySelector, valueSelector = x => x) {
395
- const obj = Object.create(null)
396
- let i = 0
397
- for (const item of this) {
398
- obj[keySelector(item, i)] = valueSelector(item, i)
399
- i++
400
- }
401
- return obj
402
- }
403
-
404
- forEach(action) {
405
- let i = 0
406
- for (const item of this)
407
- action(item, i++)
408
- }
409
-
410
- count(predicate) {
411
- let n = 0, i = 0
412
- for (const item of this) {
413
- if (!predicate || predicate(item, i)) n++
414
- i++
415
- }
416
- return n
417
- }
418
-
419
- any(predicate) {
420
- let i = 0
421
- for (const item of this) {
422
- if (!predicate || predicate(item, i)) return true
423
- i++
424
- }
425
- return false
426
- }
427
-
428
- all(predicate) {
429
- let i = 0
430
- for (const item of this) {
431
- if (!predicate(item, i)) return false
432
- i++
433
- }
434
- return true
435
- }
436
-
437
- contains(value, comparer = Object.is) {
438
- for (const item of this)
439
- if (comparer(item, value))
440
- return true
441
- return false
442
- }
443
-
444
- sequenceEqual(other, comparer = Object.is) {
445
- const it1 = this[Symbol.iterator]()
446
- const it2 = from(other)[Symbol.iterator]()
447
- while (true) {
448
- const a = it1.next()
449
- const b = it2.next()
450
- if (a.done && b.done)
451
- return true
452
- if (a.done !== b.done)
453
- return false
454
- if (!comparer(a.value, b.value))
455
- return false
456
- }
457
- }
458
-
459
- first(predicate) {
460
- let i = 0
461
- for (const item of this) {
462
- if (!predicate || predicate(item, i)) return item
463
- i++
464
- }
465
- throw new Error('[framework] first(): sequence contains no matching element')
466
- }
467
-
468
- firstOrDefault(...args) {
469
- const { predicate, defaultValue } = resolveOrDefaultArgs(args)
470
- let i = 0
471
- for (const item of this) {
472
- if (!predicate || predicate(item, i)) return item
473
- i++
474
- }
475
- return defaultValue
476
- }
477
-
478
- last(predicate) {
479
- let found, has = false, i = 0
480
- for (const item of this) {
481
- if (!predicate || predicate(item, i)) {
482
- found = item
483
- has = true
484
- }
485
- i++
486
- }
487
- if (!has)
488
- throw new Error('[framework] last(): sequence contains no matching element')
489
- return found
490
- }
491
-
492
- lastOrDefault(...args) {
493
- const { predicate, defaultValue } = resolveOrDefaultArgs(args)
494
- let found = defaultValue, has = false, i = 0
495
- for (const item of this) {
496
- if (!predicate || predicate(item, i)) {
497
- found = item
498
- has = true
499
- }
500
- i++
501
- }
502
- return has ? found : defaultValue
503
- }
504
-
505
- single(predicate) {
506
- let found, n = 0, i = 0
507
- for (const item of this) {
508
- if (!predicate || predicate(item, i)) {
509
- if (++n > 1)
510
- throw new Error('[framework] single(): sequence contains more than one matching element')
511
- found = item
512
- }
513
- i++
514
- }
515
- if (n === 0)
516
- throw new Error('[framework] single(): sequence contains no matching element')
517
- return found
518
- }
519
-
520
- singleOrDefault(...args) {
521
- const { predicate, defaultValue } = resolveOrDefaultArgs(args)
522
- let found = defaultValue, n = 0, i = 0
523
- for (const item of this) {
524
- if (!predicate || predicate(item, i)) {
525
- if (++n > 1)
526
- throw new Error('[framework] singleOrDefault(): sequence contains more than one matching element')
527
- found = item
528
- }
529
- i++
530
- }
531
- return n === 0 ? defaultValue : found
532
- }
533
-
534
- elementAt(index) {
535
- let i = 0
536
- for (const item of this)
537
- if (i++ === index)
538
- return item
539
- throw new Error(`[framework] elementAt(): index ${index} is out of range`)
540
- }
541
-
542
- elementAtOrDefault(index, defaultValue = null) {
543
- let i = 0
544
- for (const item of this)
545
- if (i++ === index)
546
- return item
547
- return defaultValue
548
- }
549
-
550
- sum(selector) {
551
- let total = 0
552
- for (const item of this)
553
- total += selector ? selector(item) : item
554
- return total
555
- }
556
-
557
- average(selector) {
558
- let total = 0, n = 0
559
- for (const item of this) {
560
- total += selector ? selector(item) : item
561
- n++
562
- }
563
- if (n === 0)
564
- throw new Error('[framework] average(): sequence contains no elements')
565
- return total / n
566
- }
567
-
568
- min(selector) {
569
- let result, has = false
570
- for (const item of this) {
571
- const value = selector ? selector(item) : item
572
- if (!has || value < result) {
573
- result = value
574
- has = true
575
- }
576
- }
577
- if (!has)
578
- throw new Error('[framework] min(): sequence contains no elements')
579
- return result
580
- }
581
-
582
- max(selector) {
583
- let result, has = false
584
- for (const item of this) {
585
- const value = selector ? selector(item) : item
586
- if (!has || value > result) {
587
- result = value
588
- has = true
589
- }
590
- }
591
- if (!has)
592
- throw new Error('[framework] max(): sequence contains no elements')
593
- return result
594
- }
595
-
596
- minBy(keySelector, comparer = defaultComparer) {
597
- let minItem = null
598
- let minKey
599
- let has = false
600
-
601
- for (const item of this) {
602
- const key = keySelector(item)
603
- if (!has || comparer(key, minKey) < 0) {
604
- minKey = key
605
- minItem = item
606
- has = true
607
- }
608
- }
609
-
610
- return minItem
611
- }
612
-
613
- maxBy(keySelector, comparer = defaultComparer) {
614
- return this.minBy(keySelector, (a, b) => comparer(b, a))
615
- }
616
-
617
- aggregate(...args) {
618
- if (args.length === 1) {
619
- const [func] = args
620
- let acc, has = false, i = 0
621
- for (const item of this) {
622
- acc = has ? func(acc, item, i) : item
623
- has = true
624
- i++
625
- }
626
- if (!has)
627
- throw new Error('[framework] aggregate(): sequence contains no elements')
628
- return acc
629
- }
630
- const [seed, func, resultSelector] = args
631
- let acc = seed, i = 0
632
- for (const item of this) {
633
- acc = func(acc, item, i)
634
- i++
635
- }
636
- return resultSelector ? resultSelector(acc) : acc
637
- }
638
-
639
- scan(...args) {
640
- const self = this
641
- if (args.length === 1) {
642
- const [func] = args
643
- return new Enumerable(function* () {
644
- let acc, has = false, i = 0
645
- for (const item of self) {
646
- acc = has ? func(acc, item, i) : item
647
- has = true
648
- i++
649
- yield acc
650
- }
651
- })
652
- }
653
- const [seed, func] = args
654
- return new Enumerable(function* () {
655
- let acc = seed, i = 0
656
- for (const item of self) {
657
- acc = func(acc, item, i)
658
- i++
659
- yield acc
660
- }
661
- })
662
- }
663
-
664
- // reactivity bridge
665
-
666
- /** Wraps a terminal call to this query in computed(), so the result stays in sync with any signals it reads. */
667
- toSignal(terminalOp) {
668
- const run = terminalOp || (query => query.toArray())
669
- return computed(() => run(this))
670
- }
671
-
672
- // JS-flavored aliases, for readability at call sites
673
-
674
- filter(predicate) {
675
- return this.where(predicate)
676
- }
677
- map(selector) {
678
- return this.select(selector)
679
- }
680
- flatMap(collectionSelector, resultSelector) {
681
- return this.selectMany(collectionSelector, resultSelector)
682
- }
683
- reduce(...args) {
684
- return this.aggregate(...args)
685
- }
686
- }
687
-
688
- /** An Enumerable produced by orderBy()/orderByDescending() that supports additional thenBy() tie-breakers. */
689
- export class OrderedEnumerable extends Enumerable {
690
- constructor(sourceFactory, comparers) {
691
- super(function* () {
692
- const items = [...sourceFactory()]
693
- const indices = items.map((_, i) => i)
694
- indices.sort((a, b) => {
695
- for (const { keySelector, comparer, descending } of comparers) {
696
- const cmp = comparer(keySelector(items[a]), keySelector(items[b]))
697
- if (cmp !== 0)
698
- return descending ? -cmp : cmp
699
- }
700
- return a - b
701
- })
702
- for (const i of indices)
703
- yield items[i]
704
- })
705
- this._sourceFactory = sourceFactory
706
- this._comparers = comparers
707
- }
708
-
709
- thenBy(keySelector, comparer = defaultComparer) {
710
- return new OrderedEnumerable(this._sourceFactory, [...this._comparers, { keySelector, comparer, descending: false }])
711
- }
712
-
713
- thenByDescending(keySelector, comparer = defaultComparer) {
714
- return new OrderedEnumerable(this._sourceFactory, [...this._comparers, { keySelector, comparer, descending: true }])
715
- }
716
- }
717
-
718
- /**
719
- * Wraps a source into a queryable, lazily-evaluated Enumerable.
720
- * Accepts arrays, strings, Maps/Sets, any iterable, another Enumerable, or a
721
- * function - including a Fusée signal/computed/resource accessor
722
- */
723
- export function from(source) {
724
- if (source instanceof Enumerable)
725
- return source
726
- if (source == null)
727
- return new Enumerable(function* () {})
728
- if (typeof source === 'function') {
729
- return new Enumerable(function* () {
730
- const resolved = source()
731
- if (resolved != null)
732
- yield* resolved
733
- })
734
- }
735
- return new Enumerable(function* () { yield* source })
736
- }
737
-
738
- /** Produces a lazy sequence of `count` consecutive integers starting at `start`. */
739
- export function range(start, count) {
740
- return new Enumerable(function* () {
741
- for (let i = 0; i < count; i++)
742
- yield start + i
743
- })
744
- }
745
-
746
- /** Produces a lazy sequence that repeats `element` `count` times. */
747
- export function repeat(element, count) {
748
- return new Enumerable(function* () {
749
- for (let i = 0; i < count; i++)
750
- yield element
751
- })
752
- }
753
-
754
- /** Returns an empty sequence. */
755
- export function empty() {
756
- return new Enumerable(function* () {})
757
- }