Initial commit
This commit is contained in:
595
lib/src/collection/Collection.ts
Executable file
595
lib/src/collection/Collection.ts
Executable file
@@ -0,0 +1,595 @@
|
||||
type CollectionItem<T> = T
|
||||
type MaybeCollectionItem<T> = CollectionItem<T> | undefined
|
||||
type KeyFunction<T, T2> = (item: CollectionItem<T>, index: number) => CollectionItem<T2>
|
||||
type KeyReducerFunction<T, T2> = (current: any, item: CollectionItem<T>, index: number) => T2
|
||||
type CollectionFunction<T, T2> = (items: Collection<T>) => T2
|
||||
type KeyOperator<T, T2> = string | KeyFunction<T, T2>
|
||||
type AssociatedCollectionItem<T2, T> = { key: T2, item: CollectionItem<T> }
|
||||
type CollectionComparable<T> = CollectionItem<T>[] | Collection<T>
|
||||
type DeterminesEquality<T> = (item: CollectionItem<T>, other: any) => boolean
|
||||
type CollectionIndex = number
|
||||
type MaybeCollectionIndex = CollectionIndex | undefined
|
||||
type ComparisonFunction<T> = (item: CollectionItem<T>, other_item: CollectionItem<T>) => number
|
||||
|
||||
import { WhereOperator, applyWhere, whereMatch } from './Where.ts'
|
||||
|
||||
const collect = <T>(items: CollectionItem<T>[]): Collection<T> => Collection.collect(items)
|
||||
export {
|
||||
collect,
|
||||
Collection,
|
||||
|
||||
// Types
|
||||
CollectionItem,
|
||||
MaybeCollectionItem,
|
||||
KeyFunction,
|
||||
KeyReducerFunction,
|
||||
CollectionFunction,
|
||||
KeyOperator,
|
||||
AssociatedCollectionItem,
|
||||
CollectionComparable,
|
||||
DeterminesEquality,
|
||||
CollectionIndex,
|
||||
MaybeCollectionIndex,
|
||||
ComparisonFunction,
|
||||
}
|
||||
|
||||
class Collection<T> {
|
||||
private _items: CollectionItem<T>[] = []
|
||||
|
||||
public static collect<T>(items: CollectionItem<T>[]): Collection<T> {
|
||||
return new Collection(items)
|
||||
}
|
||||
|
||||
public static size(size: number): Collection<undefined> {
|
||||
const arr = Array(size).fill(undefined)
|
||||
return new Collection<undefined>(arr)
|
||||
}
|
||||
|
||||
public static fill<T>(size: number, item: T): Collection<T> {
|
||||
const arr = Array(size).fill(item)
|
||||
return new Collection<T>(arr)
|
||||
}
|
||||
|
||||
constructor(
|
||||
items?: CollectionItem<T>[]
|
||||
) {
|
||||
if ( items )
|
||||
this._items = items
|
||||
}
|
||||
|
||||
private _all<T2>(key: KeyOperator<T, T2>): CollectionItem<T2>[] {
|
||||
let items: CollectionItem<T2>[] = []
|
||||
if ( typeof key === 'function' ) {
|
||||
items = this._items.map(key)
|
||||
} else if ( typeof key === 'string' ) {
|
||||
items = this._items.map((item: CollectionItem<T>) => (<any>item)[key])
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
private _all_numbers<T2>(key: KeyOperator<T, T2>): number[] {
|
||||
return this._all(key).map(value => Number(value))
|
||||
}
|
||||
|
||||
private _all_associate<T2>(key: KeyOperator<T, T2>): AssociatedCollectionItem<T2, T>[] {
|
||||
const assoc_items: AssociatedCollectionItem<T2, T>[] = []
|
||||
let items = [...this._items]
|
||||
if ( typeof key === 'function' ) {
|
||||
items.map((item, index) => {
|
||||
const key_item = key(item, index)
|
||||
assoc_items.push({ key: key_item, item })
|
||||
})
|
||||
} else if ( typeof key === 'string' ) {
|
||||
items.map((item, index) => {
|
||||
assoc_items.push({ key: (<any>item)[key], item })
|
||||
})
|
||||
}
|
||||
return assoc_items
|
||||
}
|
||||
|
||||
all(): CollectionItem<T>[] {
|
||||
return [...this._items]
|
||||
}
|
||||
|
||||
average<T2>(key?: KeyOperator<T, T2>): number {
|
||||
let items
|
||||
if ( key ) items = this._all_numbers(key)
|
||||
else items = this._items.map(x => Number(x))
|
||||
if ( items.length === 0 ) return 0
|
||||
|
||||
let sum = items.reduce((prev, curr) => prev + curr)
|
||||
return sum / items.length
|
||||
}
|
||||
|
||||
median<T2>(key?: KeyOperator<T, T2>): number {
|
||||
let items
|
||||
if ( key ) items = this._all_numbers(key).sort((a, b) => a - b)
|
||||
else items = this._items.map(x => Number(x)).sort((a, b) => a - b)
|
||||
|
||||
const middle = Math.floor((items.length - 1) / 2)
|
||||
if ( items.length % 2 ) return items[middle]
|
||||
else return (items[middle] + items[middle + 1]) / 2;
|
||||
}
|
||||
|
||||
mode<T2>(key?: KeyOperator<T, T2>): number {
|
||||
let items
|
||||
if ( key ) items = this._all_numbers(key).sort((a, b) => a - b)
|
||||
else items = this._items.map(x => Number(x)).sort((a, b) => a - b)
|
||||
|
||||
let counts: any = {}
|
||||
for ( const item of items ) {
|
||||
counts[item] = (counts[item] ?? -1) + 1
|
||||
}
|
||||
|
||||
return Math.max(...Object.values(counts).map(Number))
|
||||
}
|
||||
|
||||
collapse(): Collection<any> {
|
||||
const new_items: CollectionItem<T>[] = []
|
||||
const items = [...this._items]
|
||||
const get_layer = (current: CollectionItem<T>|CollectionItem<T>[]) => {
|
||||
if ( typeof (<any>current)[Symbol.iterator] === 'function' ) {
|
||||
// @ts-ignore
|
||||
// TODO fix this
|
||||
for (const item of current) {
|
||||
if (Array.isArray(item)) {
|
||||
get_layer(item)
|
||||
} else {
|
||||
new_items.push(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get_layer(items)
|
||||
return new Collection(new_items)
|
||||
}
|
||||
|
||||
contains<T2>(key: KeyOperator<T, T2>, operator: WhereOperator, operand?: any): boolean {
|
||||
const associate = this._all_associate(key)
|
||||
const matches = applyWhere(associate, operator, operand)
|
||||
return matches.length > 0
|
||||
}
|
||||
|
||||
// TODO crossJoin
|
||||
|
||||
diff<T2>(items: CollectionComparable<T|T2>): Collection<T> {
|
||||
const exclude = items instanceof Collection ? items.all() : items
|
||||
const matches = []
|
||||
for ( const item of [...this._items] ) {
|
||||
if ( !exclude.includes(item) ) matches.push(item)
|
||||
}
|
||||
return new Collection(matches)
|
||||
}
|
||||
|
||||
diffUsing<T2>(items: CollectionComparable<T|T2>, compare: DeterminesEquality<T>): Collection<T> {
|
||||
const exclude = items instanceof Collection ? items.all() : items
|
||||
const matches = []
|
||||
for ( const item of [...this._items] ) {
|
||||
if ( !exclude.some(exc => compare(item, exc)) )
|
||||
matches.push(item)
|
||||
}
|
||||
return new Collection(matches)
|
||||
}
|
||||
|
||||
each<T2>(func: KeyFunction<T, T2>): Collection<T2> {
|
||||
return new Collection(this._items.map(func))
|
||||
}
|
||||
|
||||
map<T2>(func: KeyFunction<T, T2>): Collection<T2> {
|
||||
return this.each(func)
|
||||
}
|
||||
|
||||
every<T2>(func: KeyFunction<T, T2>): boolean {
|
||||
return this._items.every(func)
|
||||
}
|
||||
|
||||
everyWhere<T2>(key: KeyOperator<T, T2>, operator: WhereOperator, operand?: any): boolean {
|
||||
const items = this._all_associate(key)
|
||||
return items.every(item => whereMatch(item, operator, operand))
|
||||
}
|
||||
|
||||
filter<T2>(func: KeyFunction<T, T2>): Collection<T> {
|
||||
return new Collection(this._items.filter(func))
|
||||
}
|
||||
|
||||
when<T2>(bool: boolean, then: CollectionFunction<T, T2>): Collection<T> {
|
||||
if ( bool ) then(this)
|
||||
return this
|
||||
}
|
||||
|
||||
unless<T2>(bool: boolean, then: CollectionFunction<T, T2>): Collection<T> {
|
||||
if ( !bool ) then(this)
|
||||
return this
|
||||
}
|
||||
|
||||
where<T2>(key: KeyOperator<T, T2>, operator: WhereOperator, operand?: any): Collection<T> {
|
||||
const items = this._all_associate(key)
|
||||
return new Collection(applyWhere(items, operator, operand))
|
||||
}
|
||||
|
||||
whereNot<T2>(key: KeyOperator<T, T2>, operator: WhereOperator, operand?: any): Collection<T> {
|
||||
return this.diff(this.where(key, operator, operand))
|
||||
}
|
||||
|
||||
whereIn<T2>(key: KeyOperator<T, T2>, items: CollectionComparable<T2>): Collection<T> {
|
||||
const allowed = items instanceof Collection ? items.all() : items
|
||||
const matches = []
|
||||
for ( const { key: search, item } of this._all_associate(key) ) {
|
||||
if ( allowed.includes(search) ) matches.push(item)
|
||||
}
|
||||
return new Collection(matches)
|
||||
}
|
||||
|
||||
whereNotIn<T2>(key: KeyOperator<T, T2>, items: CollectionComparable<T2>): Collection<T> {
|
||||
return this.diff(this.whereIn(key, items))
|
||||
}
|
||||
|
||||
first(): MaybeCollectionItem<T> {
|
||||
if ( this.length > 0 ) return this._items[0]
|
||||
}
|
||||
|
||||
firstWhere<T2>(key: KeyOperator<T, T2>, operator: WhereOperator = '=', operand: any = true): MaybeCollectionItem<T> {
|
||||
const items = this.where(key, operator, operand).all()
|
||||
if ( items.length > 0 ) return items[0]
|
||||
}
|
||||
|
||||
firstWhereNot<T2>(key: KeyOperator<T, T2>, operator: WhereOperator, operand?: any): MaybeCollectionItem<T> {
|
||||
const items = this.whereNot(key, operator, operand).all()
|
||||
if ( items.length > 0 ) return items[0]
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this._items.length
|
||||
}
|
||||
|
||||
count() {
|
||||
return this._items.length
|
||||
}
|
||||
|
||||
// TODO flatten - depth
|
||||
|
||||
get(index: number, fallback?: any) {
|
||||
if ( this.length > index ) return this._items[index]
|
||||
else return fallback
|
||||
}
|
||||
|
||||
at(index: number): MaybeCollectionItem<T> {
|
||||
return this.get(index)
|
||||
}
|
||||
|
||||
groupBy<T2>(key: KeyOperator<T, T2>): any {
|
||||
const items = this._all_associate(key)
|
||||
const groups: any = {}
|
||||
for ( const item of items ) {
|
||||
const key = String(item.key)
|
||||
if ( !groups[key] ) groups[key] = []
|
||||
groups[key].push(item.item)
|
||||
}
|
||||
return groups
|
||||
}
|
||||
|
||||
associate<T2>(key: KeyOperator<T, T2>): any {
|
||||
const items = this._all_associate(key)
|
||||
const values: any = {}
|
||||
for ( const item of items ) {
|
||||
values[String(item.key)] = item.item
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
join(delimiter: string): string {
|
||||
return this._items.join(delimiter)
|
||||
}
|
||||
|
||||
implode(delimiter: string): string {
|
||||
return this.join(delimiter)
|
||||
}
|
||||
|
||||
intersect(items: CollectionComparable<T>, key?: KeyOperator<T, T>): Collection<T> {
|
||||
const compare = items instanceof Collection ? items.all() : items
|
||||
const intersect = []
|
||||
let all_items
|
||||
if ( key ) all_items = this._all_associate(key)
|
||||
else all_items = this._items.map(item => {
|
||||
return { key: item, item }
|
||||
})
|
||||
|
||||
for ( const item of all_items ) {
|
||||
if ( compare.includes(item.key) )
|
||||
intersect.push(item.item)
|
||||
}
|
||||
return new Collection(intersect)
|
||||
}
|
||||
|
||||
isEmpty(): boolean {
|
||||
return this.length < 1
|
||||
}
|
||||
|
||||
isNotEmpty(): boolean {
|
||||
return this.length > 0
|
||||
}
|
||||
|
||||
last(): MaybeCollectionItem<T> {
|
||||
if ( this.length > 0 ) return this._items.reverse()[0]
|
||||
}
|
||||
|
||||
lastWhere<T2>(key: KeyOperator<T, T2>, operator: WhereOperator, operand?: any): MaybeCollectionItem<T> {
|
||||
const items = this.where(key, operator, operand).all()
|
||||
if ( items.length > 0 ) return items.reverse()[0]
|
||||
}
|
||||
|
||||
lastWhereNot<T2>(key: KeyOperator<T, T2>, operator: WhereOperator, operand?: any): MaybeCollectionItem<T> {
|
||||
const items = this.whereNot(key, operator, operand).all()
|
||||
if ( items.length > 0 ) return items.reverse()[0]
|
||||
}
|
||||
|
||||
pluck<T2>(key: KeyOperator<T, T2>): Collection<T2> {
|
||||
return new Collection<T2>(this._all(key))
|
||||
}
|
||||
|
||||
max<T2>(key: KeyOperator<T, T2>): number {
|
||||
const values = this._all_numbers(key)
|
||||
return Math.max(...values)
|
||||
}
|
||||
|
||||
whereMax<T2>(key: KeyOperator<T, T2>): Collection<T> {
|
||||
return this.where(key, '=', this.max(key))
|
||||
}
|
||||
|
||||
min<T2>(key: KeyOperator<T, T2>): number {
|
||||
const values = this._all_numbers(key)
|
||||
return Math.min(...values)
|
||||
}
|
||||
|
||||
whereMin<T2>(key: KeyOperator<T, T2>): Collection<T> {
|
||||
return this.where(key, '=', this.min(key))
|
||||
}
|
||||
|
||||
merge<T2>(items: CollectionComparable<T2>): Collection<T|T2> {
|
||||
const merge = items instanceof Collection ? items.all() : items
|
||||
return new Collection([...this._items, ...merge])
|
||||
}
|
||||
|
||||
nth(n: number): Collection<T> {
|
||||
const matches: CollectionItem<T>[] = []
|
||||
let current = 1
|
||||
this._items.forEach((item, index) => {
|
||||
if ( current === 1 ) matches.push(item)
|
||||
current += 1
|
||||
if ( current > n ) current = 1
|
||||
})
|
||||
return new Collection(matches)
|
||||
}
|
||||
|
||||
forPage(page: number, perPage: number) {
|
||||
const start = page * perPage - perPage
|
||||
const end = page * perPage
|
||||
return new Collection(this._items.slice(start, end))
|
||||
}
|
||||
|
||||
pipe<T2>(func: CollectionFunction<T, T2>): any {
|
||||
return func(this)
|
||||
}
|
||||
|
||||
pop(): MaybeCollectionItem<T> {
|
||||
if ( this.length > 0 ) {
|
||||
return this._items.pop()
|
||||
}
|
||||
}
|
||||
|
||||
prepend(item: CollectionItem<T>): Collection<T> {
|
||||
this._items = [item, ...this._items]
|
||||
return this
|
||||
}
|
||||
|
||||
push(item: CollectionItem<T>): Collection<T> {
|
||||
this._items.push(item)
|
||||
return this
|
||||
}
|
||||
|
||||
concat(items: CollectionComparable<T>): Collection<T> {
|
||||
const concats = items instanceof Collection ? items.all() : items
|
||||
for ( const item of concats ) {
|
||||
this._items.push(item)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
pull(index: number, fallback: any): MaybeCollectionItem<T> {
|
||||
let value
|
||||
const new_items = []
|
||||
this._items.forEach((item, item_index) => {
|
||||
if ( item_index !== index ) new_items.push(item)
|
||||
else value = item
|
||||
})
|
||||
return value ?? fallback
|
||||
}
|
||||
|
||||
put(index: number, item: CollectionItem<T>): Collection<T> {
|
||||
const new_items = []
|
||||
let inserted = false
|
||||
this._items.forEach((existing, existing_index) => {
|
||||
if ( existing_index === index ) {
|
||||
new_items.push(item)
|
||||
inserted = true
|
||||
}
|
||||
|
||||
new_items.push(existing)
|
||||
})
|
||||
|
||||
if ( !inserted ) new_items.push(item)
|
||||
return new Collection(new_items)
|
||||
}
|
||||
|
||||
random(n: number): Collection<T> {
|
||||
const random_items: CollectionItem<T>[] = []
|
||||
const all = this._items
|
||||
if ( n > this.length ) n = this.length
|
||||
while ( random_items.length < n ) {
|
||||
const item = all[Math.floor(Math.random() * all.length)]
|
||||
if ( !random_items.includes(item) ) random_items.push(item)
|
||||
}
|
||||
return new Collection(random_items)
|
||||
}
|
||||
|
||||
reduce<T2>(reducer: KeyReducerFunction<T, T2>, initial_value?: T2): T2 | undefined {
|
||||
let current_value = initial_value
|
||||
this._items.forEach((item, index) => {
|
||||
current_value = reducer(current_value, item, index)
|
||||
})
|
||||
return current_value
|
||||
}
|
||||
|
||||
reject<T2>(truth_test: KeyFunction<T, T2>): Collection<T> {
|
||||
const rejected = this._items.filter((item, index) => {
|
||||
return !truth_test(item, index)
|
||||
})
|
||||
return new Collection(rejected)
|
||||
}
|
||||
|
||||
reverse(): Collection<T> {
|
||||
return new Collection([...this._items.reverse()])
|
||||
}
|
||||
|
||||
search(item: CollectionItem<T>): MaybeCollectionIndex {
|
||||
let found_index
|
||||
this._items.some((possible_item, index) => {
|
||||
if ( possible_item === item ) {
|
||||
found_index = index
|
||||
return true
|
||||
}
|
||||
})
|
||||
return found_index
|
||||
}
|
||||
|
||||
shift(): MaybeCollectionItem<T> {
|
||||
if ( this.length > 0 ) {
|
||||
return this._items.shift()
|
||||
}
|
||||
}
|
||||
|
||||
shuffle(): Collection<T> {
|
||||
const items = [...this._items]
|
||||
for ( let i = items.length - 1; i > 0; i-- ) {
|
||||
const j = Math.floor(Math.random() * (i + 1))
|
||||
;[items[i], items[j]] = [items[j], items[i]]
|
||||
}
|
||||
return new Collection(items)
|
||||
}
|
||||
|
||||
slice(start: number, end: number) {
|
||||
return new Collection(this._items.slice(start, end))
|
||||
}
|
||||
|
||||
// TODO split
|
||||
// TODO chunk
|
||||
|
||||
sort(compare_func?: ComparisonFunction<T>): Collection<T> {
|
||||
const items = this._items
|
||||
if ( compare_func ) items.sort(compare_func)
|
||||
else items.sort()
|
||||
return new Collection(items)
|
||||
}
|
||||
|
||||
sortBy<T2>(key?: KeyOperator<T, T2>): Collection<T> {
|
||||
let items: any[]
|
||||
if ( key ) items = this._all_associate(key)
|
||||
else items = this._items.map(item => {
|
||||
return { key: item, item }
|
||||
})
|
||||
|
||||
items.sort((a: any, b: any) => {
|
||||
if ( a.key > b.key ) return 1
|
||||
else if ( a.key < b.key ) return -1
|
||||
else return 0
|
||||
})
|
||||
return new Collection(items.map((item: AssociatedCollectionItem<T2, T>) => item.item))
|
||||
}
|
||||
|
||||
sortDesc(compare_func?: ComparisonFunction<T>): Collection<T> {
|
||||
return this.sort(compare_func).reverse()
|
||||
}
|
||||
|
||||
sortByDesc<T2>(key?: KeyOperator<T, T2>): Collection<T> {
|
||||
return this.sortBy(key).reverse()
|
||||
}
|
||||
|
||||
splice(start: CollectionIndex, deleteCount?: number): Collection<T> {
|
||||
return new Collection([...this._items].splice(start, deleteCount))
|
||||
}
|
||||
|
||||
sum<T2>(key?: KeyOperator<T, T2>): number {
|
||||
let items
|
||||
if ( key ) items = this._all_numbers(key)
|
||||
else items = this._items.map(x => Number(x))
|
||||
return items.reduce((prev, curr) => prev + curr)
|
||||
}
|
||||
|
||||
take(limit: number): Collection<T> {
|
||||
if ( limit === 0 ) return new Collection()
|
||||
else if ( limit > 0 ) {
|
||||
return new Collection(this._items.slice(0, limit))
|
||||
} else {
|
||||
return new Collection(this._items.reverse().slice(0, -1 * limit).reverse())
|
||||
}
|
||||
}
|
||||
|
||||
tap<T2>(func: CollectionFunction<T, T2>): Collection<T> {
|
||||
func(this)
|
||||
return this
|
||||
}
|
||||
|
||||
unique<T2>(key?: KeyOperator<T, T2>): Collection<T|T2> {
|
||||
const has: CollectionItem<T|T2>[] = []
|
||||
let items
|
||||
if ( key ) items = this._all<T2>(key)
|
||||
else items = [...this._items]
|
||||
for ( const item of items ) {
|
||||
if ( !has.includes(item) ) has.push(item)
|
||||
}
|
||||
return new Collection(has)
|
||||
}
|
||||
|
||||
includes(item: CollectionItem<T>): boolean {
|
||||
return this._items.includes(item)
|
||||
}
|
||||
|
||||
pad(length: number, value: CollectionItem<T>): Collection<T> {
|
||||
const items = [...this._items]
|
||||
while ( items.length < length ) items.push(value)
|
||||
return new Collection(items)
|
||||
}
|
||||
|
||||
toArray(): any[] {
|
||||
const returns: any = []
|
||||
for ( const item of this._items ) {
|
||||
if ( item instanceof Collection ) returns.push(item.toArray())
|
||||
else returns.push(item)
|
||||
}
|
||||
return returns
|
||||
}
|
||||
|
||||
toJSON(replacer = undefined, space = 4): string {
|
||||
return JSON.stringify(this.toArray(), replacer, space)
|
||||
}
|
||||
|
||||
// TODO getIterator
|
||||
// TODO getCachingIterator
|
||||
|
||||
[Symbol.iterator]() {
|
||||
const items = this._items
|
||||
return {
|
||||
current_index: 0,
|
||||
next() {
|
||||
if ( items.length < 1 || this.current_index + 1 >= items.length ) {
|
||||
return { done: true }
|
||||
}
|
||||
|
||||
const item = items[this.current_index]
|
||||
this.current_index += 1
|
||||
return { done: false, value: item }
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
75
lib/src/collection/Where.ts
Executable file
75
lib/src/collection/Where.ts
Executable file
@@ -0,0 +1,75 @@
|
||||
type WhereOperator = '&' | '>' | '>=' | '<' | '<=' | '!=' | '<=>' | '%' | '|' | '!' | '~' | '=' | '^'
|
||||
type AssociatedSearchItem = { key: any, item: any }
|
||||
type WhereResult = any[]
|
||||
|
||||
// bitwise and
|
||||
// greater than
|
||||
// greater than equal
|
||||
// less than
|
||||
// less than equal
|
||||
// not equal
|
||||
// null-safe equal
|
||||
// modulo
|
||||
// bitwise or
|
||||
// not
|
||||
// bitwise negation
|
||||
// equal
|
||||
|
||||
const whereMatch = (item: AssociatedSearchItem, operator: WhereOperator, operand?: any): boolean => {
|
||||
switch ( operator ) {
|
||||
case '&':
|
||||
if ( item.key & operand ) return true
|
||||
break
|
||||
case '>':
|
||||
if ( item.key > operand ) return true
|
||||
break
|
||||
case '>=':
|
||||
if ( item.key >= operand ) return true
|
||||
break
|
||||
case '<':
|
||||
if ( item.key < operand ) return true
|
||||
break
|
||||
case '<=':
|
||||
if ( item.key <= operand ) return true
|
||||
break
|
||||
case '!=':
|
||||
if ( item.key !== operand ) return true
|
||||
break
|
||||
case '<=>':
|
||||
if ( item.key === operand && typeof item.key !== 'undefined' && item.key !== null )
|
||||
return true
|
||||
break
|
||||
case '%':
|
||||
if ( item.key % operand ) return true
|
||||
break
|
||||
case '|':
|
||||
if ( item.key | operand ) return true
|
||||
break
|
||||
case '!':
|
||||
if ( !item.key ) return true
|
||||
break
|
||||
case '~':
|
||||
if ( ~item.key ) return true
|
||||
break
|
||||
case '=':
|
||||
if ( item.key === operand ) return true
|
||||
break
|
||||
case '^':
|
||||
if ( item.key ^ operand ) return true
|
||||
break
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
const applyWhere = (items: AssociatedSearchItem[], operator: WhereOperator, operand?: any): WhereResult => {
|
||||
const matches: WhereResult = []
|
||||
for ( const item of items ) {
|
||||
if ( whereMatch(item, operator, operand) )
|
||||
matches.push(item.item)
|
||||
}
|
||||
|
||||
return matches
|
||||
}
|
||||
|
||||
export { WhereOperator, WhereResult, AssociatedSearchItem, applyWhere, whereMatch }
|
||||
2155
lib/src/external/reflect.ts
vendored
Normal file
2155
lib/src/external/reflect.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
15
lib/src/type/UUID.ts
Executable file
15
lib/src/type/UUID.ts
Executable file
@@ -0,0 +1,15 @@
|
||||
type UUID = string
|
||||
|
||||
const isUUID = (possible: any): boolean => {
|
||||
return typeof possible === 'string' && /[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}/.test(possible)
|
||||
}
|
||||
|
||||
const uuid = (): UUID => {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||
const r = Math.random() * 16 | 0
|
||||
const v = c == 'x' ? r : (r & 0x3 | 0x8)
|
||||
return v.toString(16)
|
||||
})
|
||||
}
|
||||
|
||||
export { UUID, isUUID, uuid }
|
||||
Reference in New Issue
Block a user