/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at . */ // @flow import type { ResourceBound, Id, ResourceValues } from "./core"; import { makeResourceQuery, type ResourceQuery, type QueryFilter, type QueryMap, type QueryReduce, } from "./base-query"; import { queryCacheWeak, queryCacheShallow, queryCacheStrict, type WeakArgsBound, type ShallowArgsBound, } from "./query-cache"; import { memoizeResourceShallow } from "./memoize"; import { shallowEqual } from "./compare"; export function filterAllIds( values: ResourceValues ): Array> { return Object.keys(values); } /** * Create a query function to take a list of IDs and map each Reduceding * resource object into a mapped form. */ export type WeakQuery< R: ResourceBound, Args: WeakArgsBound, Reduced > = ResourceQuery; export function makeWeakQuery< R: ResourceBound, Args: WeakArgsBound, Mapped, Reduced >({ filter, map, reduce, }: {| filter: QueryFilter, map: QueryMap, reduce: QueryReduce, |}): WeakQuery { return makeResourceQuery({ cache: queryCacheWeak, filter, map: memoizeResourceShallow(map), reduce, resultCompare: shallowEqual, }); } /** * Create a query function to take a list of IDs and map each Reduceding * resource object into a mapped form. */ export type ShallowQuery = ResourceQuery< R, Args, Reduced >; export function makeShallowQuery< R: ResourceBound, Args: ShallowArgsBound, Mapped, Reduced >({ filter, map, reduce, }: {| filter: QueryFilter, map: QueryMap, reduce: QueryReduce, |}): ShallowQuery { return makeResourceQuery({ cache: queryCacheShallow, filter, map: memoizeResourceShallow(map), reduce, resultCompare: shallowEqual, }); } /** * Create a query function to take a list of IDs and map each Reduceding * resource object into a mapped form. */ export type StrictQuery = ResourceQuery< R, Args, Reduced >; export function makeStrictQuery({ filter, map, reduce, }: {| filter: QueryFilter, map: QueryMap, reduce: QueryReduce, |}): StrictQuery { return makeResourceQuery({ cache: queryCacheStrict, filter, map: memoizeResourceShallow(map), reduce, resultCompare: shallowEqual, }); } /** * Create a query function to take a list of IDs and map each Reduceding * resource object into a mapped form. */ export type IdQuery = WeakQuery< R, Array>, Array >; export function makeIdQuery( map: QueryMap ): IdQuery { return makeWeakQuery({ filter: (state, ids) => ids, map: (r, identity) => map(r, identity), reduce: items => items.slice(), }); } /** * Create a query function to take a list of IDs and map each Reduceding * resource object into a mapped form. */ export type LoadQuery = WeakQuery< R, Array>, $ReadOnly<{ [Id]: Mapped }> >; export function makeLoadQuery( map: QueryMap ): LoadQuery { return makeWeakQuery({ filter: (state, ids) => ids, map: (r, identity) => map(r, identity), reduce: reduceMappedArrayToObject, }); } /** * Create a query function that accepts an argument and can filter the * resource items to a subset before mapping each reduced resource. */ export type FilterQuery< R: ResourceBound, Args: WeakArgsBound, Mapped > = WeakQuery]: Mapped }>>; export function makeFilterQuery( filter: (R, Args) => boolean, map: QueryMap ): FilterQuery { return makeWeakQuery({ filter: (values, args) => { const ids = []; for (const id of Object.keys(values)) { if (filter(values[id], args)) { ids.push(id); } } return ids; }, map, reduce: reduceMappedArrayToObject, }); } /** * Create a query function that accepts an argument and can filter the * resource items to a subset before mapping each resulting resource. */ export type ReduceQuery< R: ResourceBound, Args: ShallowArgsBound, Reduced > = ShallowQuery; export function makeReduceQuery< R: ResourceBound, Args: ShallowArgsBound, Mapped, Reduced >( map: QueryMap, reduce: QueryReduce ): ReduceQuery { return makeShallowQuery({ filter: filterAllIds, map, reduce, }); } /** * Create a query function that accepts an argument and can filter the * resource items to a subset before mapping each resulting resource. */ export type ReduceAllQuery = ShallowQuery< R, void, Reduced >; export function makeReduceAllQuery( map: QueryMap, reduce: QueryReduce ): ReduceAllQuery { return makeStrictQuery({ filter: filterAllIds, map, reduce, }); } function reduceMappedArrayToObject( items: $ReadOnlyArray, ids: $ReadOnlyArray, args: Args ): { [ID]: Mapped } { return items.reduce((acc: { [ID]: Mapped }, item, i) => { acc[ids[i]] = item; return acc; }, {}); }