/* 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;
}, {});
}