Refactor event bus and queue system; detect cycles in DI realization and make
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2022-01-26 19:37:54 -06:00
parent 506fb55c74
commit 6d1cf18680
69 changed files with 1673 additions and 720 deletions

View File

@@ -8,6 +8,7 @@ import {
import {Iterable, StopIteration} from './Iterable'
import {applyWhere, WhereOperator} from './where'
import {AsyncPipe, Pipeline} from '../support/Pipe'
import {Awaitable} from '../support/types'
type AsyncCollectionComparable<T> = CollectionItem<T>[] | Collection<T> | AsyncCollection<T>
type AsyncKeyFunction<T, T2> = (item: CollectionItem<T>, index: number) => CollectionItem<T2> | Promise<CollectionItem<T2>>
type AsyncCollectionFunction<T, T2> = (items: AsyncCollection<T>) => T2
@@ -39,14 +40,26 @@ export class AsyncCollection<T> {
private async inChunksAll<T2>(key: KeyOperator<T, T2>, callback: (items: Collection<T2>) => any): Promise<void> {
await this.storedItems.chunk(this.iteratorChunkSize, async items => {
await callback(items.pluck(key))
if ( typeof key !== 'function' ) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
key = x => x[key]
}
await callback(items.map(key))
})
await this.storedItems.reset()
}
private async inChunksAllNumbers<T2>(key: KeyOperator<T, T2>, callback: (items: number[]) => any): Promise<void> {
await this.storedItems.chunk(this.iteratorChunkSize, async items => {
await callback(items.pluck(key).map(x => Number(x))
if ( typeof key !== 'function' ) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
key = x => x[key]
}
await callback(items.map(key).map(x => Number(x))
.all())
})
await this.storedItems.reset()
@@ -275,12 +288,12 @@ export class AsyncCollection<T> {
* @param {function} operator - item => boolean
* @return Promise<boolean>
*/
async some(operator: (item: T) => boolean): Promise<boolean> {
async some(operator: (item: T) => Awaitable<boolean|undefined|void>): Promise<boolean> {
let contains = false
await this.inChunks(items => {
await this.inChunks(async items => {
for ( const item of items.all() ) {
if ( operator(item) ) {
if ( await operator(item) ) {
contains = true
throw new StopIteration()
}
@@ -394,6 +407,14 @@ export class AsyncCollection<T> {
return new Collection<T>(newItems)
}
/**
* Like filter, but inverted. That is, filters out items that DO match the criterion.
* @param func
*/
async filterOut<T2>(func: KeyFunction<T, T2>): Promise<Collection<T>> {
return this.filter(async (...args) => !(await func(...args)))
}
/**
* Calls the passed in function if the boolean condition is true. Allows for functional syntax.
* @param {boolean} bool
@@ -677,14 +698,16 @@ export class AsyncCollection<T> {
* @param {KeyOperator} key
* @return Promise<Collection>
*/
async pluck<T2>(key: KeyOperator<T, T2>): Promise<Collection<T2>> {
let newItems: CollectionItem<T2>[] = []
async pluck<T2 extends keyof T>(key: T2): Promise<Collection<T[T2]>> {
let newItems: CollectionItem<T[T2]>[] = []
await this.inChunksAll(key, async items => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
newItems = newItems.concat(items.all())
})
return new Collection<T2>(newItems)
return new Collection<T[T2]>(newItems)
}
/**

View File

@@ -14,7 +14,9 @@ type MaybeCollectionIndex = CollectionIndex | undefined
type ComparisonFunction<T> = (item: CollectionItem<T>, otherItem: CollectionItem<T>) => number
import { WhereOperator, applyWhere, whereMatch } from './where'
import {Awaitable, Either, isLeft, Maybe, MethodsOf, right, unright} from '../support/types'
import {Awaitable, Awaited, Either, isLeft, Maybe, MethodsOf, right, unright} from '../support/types'
import {AsyncCollection} from './AsyncCollection'
import {ArrayIterable} from './ArrayIterable'
const collect = <T>(items: CollectionItem<T>[]): Collection<T> => Collection.collect(items)
const toString = (item: unknown): string => String(item)
@@ -265,6 +267,16 @@ class Collection<T> {
return new Collection(matches)
}
/**
* Like diff, but mutates the current collection.
* @param items
*/
diffInPlace<T2>(items: CollectionComparable<T|T2>): this {
const exclude = items instanceof Collection ? items.all() : items
this.storedItems = this.storedItems.filter(item => !exclude.includes(item))
return this
}
/**
* Return a collection of items that ARE in this collection, but NOT In the `items` collection
* using a helper function to determine whether two items are equal.
@@ -355,6 +367,14 @@ class Collection<T> {
return right(new Collection<TRight>(newItems))
}
/**
* Get the collection as an AsyncCollection.
*/
toAsync(): AsyncCollection<T> {
const iter = new ArrayIterable([...this.storedItems])
return new AsyncCollection<T>(iter)
}
/**
* Map a method on the underlying type, passing it any required parameters.
* This is delightfully type-safe.
@@ -365,6 +385,22 @@ class Collection<T> {
return this.map(x => x[method](...params))
}
/**
* Shortcut for .mapCall(...).awaitAll().
* @param method
* @param params
*/
async awaitMapCall<T2 extends MethodsOf<T>>(method: T2, ...params: Parameters<T[T2]>): Promise<Collection<Awaited<ReturnType<T[T2]>>>> {
return this.mapCall(method, ...params).awaitAll()
}
/**
* Await all values in the collection.
*/
async awaitAll(): Promise<Collection<Awaited<T>>> {
return this.promiseMap(async x => x as Awaited<T>)
}
/**
* Map each element in the collection to a string.
*/
@@ -462,6 +498,14 @@ class Collection<T> {
return new Collection(this.storedItems.filter(func ?? Boolean))
}
/**
* Like filter, but inverted. That is, removes items that DO match the criterion.
* @param func
*/
filterOut<T2>(func?: KeyFunction<T, T2>): Collection<T> {
return this.filter((...args) => !(func ?? Boolean)(...args))
}
whereDefined(): Collection<NonNullable<T>> {
return this.filter() as unknown as Collection<NonNullable<T>>
}
@@ -793,8 +837,8 @@ class Collection<T> {
*
* @param key
*/
pluck<T2>(key: KeyOperator<T, T2>): Collection<T2> {
return new Collection<T2>(this.allOperator(key))
pluck<T2 extends keyof T>(key: T2): Collection<T[T2]> {
return new Collection<T[T2]>(this.allOperator(key))
}
/**
@@ -1188,7 +1232,7 @@ class Collection<T> {
*
* @param func
*/
tap<T2>(func: CollectionFunction<T, T2>): Collection<T> {
tap<T2>(func: CollectionFunction<T, T2>): this {
func(this)
return this
}

View File

@@ -72,3 +72,5 @@ export type TypeArraySignature<TArr extends unknown[], TReturn> = (...params: TA
export type MethodsOf<T, TMethod = (...args: any[]) => any> = {
[K in keyof T]: T[K] extends TMethod ? K : never
}[keyof T]
export type Awaited<T> = T extends PromiseLike<infer U> ? U : T