import { BaseRecord, ID } from './BaseRecord' import { intersectSets } from './setUtils' import { StoreQueries } from './StoreQueries' export type ValueMatcher = { eq: T } | { neq: T } export type QueryExpression = { [k in keyof R & string]?: ValueMatcher // todo: handle nesting // | (R[k] extends object ? { match: QueryExpression } : never) } export function objectMatchesQuery(query: QueryExpression, object: T) { for (const [key, _matcher] of Object.entries(query)) { const matcher = _matcher as ValueMatcher const value = object[key as keyof T] // if you add mathcing logic here, make sure you also update the part // where initial data is pulled out of the indexes, since that requires different // matching logic if ('eq' in matcher && value !== matcher.eq) return false if ('neq' in matcher && value === matcher.neq) return false } return true } export function executeQuery( store: StoreQueries, typeName: TypeName, query: QueryExpression> ): Set>> { const matchIds = Object.fromEntries(Object.keys(query).map((key) => [key, new Set()])) for (const [k, matcher] of Object.entries(query)) { if ('eq' in matcher) { const index = store.index(typeName, k as any) const ids = index.value.get(matcher.eq) if (ids) { for (const id of ids) { matchIds[k].add(id) } } } else if ('neq' in matcher) { const index = store.index(typeName, k as any) for (const [value, ids] of index.value) { if (value !== matcher.neq) { for (const id of ids) { matchIds[k].add(id) } } } } } return intersectSets(Object.values(matchIds)) as Set>> }