| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- import { MongoInvalidArgumentError } from './error';
- /** @public */
- export type SortDirection =
- | 1
- | -1
- | 'asc'
- | 'desc'
- | 'ascending'
- | 'descending'
- | { $meta: string };
- /** @public */
- export type Sort =
- | string
- | Exclude<SortDirection, { $meta: string }>
- | string[]
- | { [key: string]: SortDirection }
- | Map<string, SortDirection>
- | [string, SortDirection][]
- | [string, SortDirection];
- /** Below stricter types were created for sort that correspond with type that the cmd takes */
- /** @internal */
- export type SortDirectionForCmd = 1 | -1 | { $meta: string };
- /** @internal */
- export type SortForCmd = Map<string, SortDirectionForCmd>;
- /** @internal */
- type SortPairForCmd = [string, SortDirectionForCmd];
- /** @internal */
- function prepareDirection(direction: any = 1): SortDirectionForCmd {
- const value = `${direction}`.toLowerCase();
- if (isMeta(direction)) return direction;
- switch (value) {
- case 'ascending':
- case 'asc':
- case '1':
- return 1;
- case 'descending':
- case 'desc':
- case '-1':
- return -1;
- default:
- throw new MongoInvalidArgumentError(`Invalid sort direction: ${JSON.stringify(direction)}`);
- }
- }
- /** @internal */
- function isMeta(t: SortDirection): t is { $meta: string } {
- return typeof t === 'object' && t != null && '$meta' in t && typeof t.$meta === 'string';
- }
- /** @internal */
- function isPair(t: Sort): t is [string, SortDirection] {
- if (Array.isArray(t) && t.length === 2) {
- try {
- prepareDirection(t[1]);
- return true;
- } catch (e) {
- return false;
- }
- }
- return false;
- }
- function isDeep(t: Sort): t is [string, SortDirection][] {
- return Array.isArray(t) && Array.isArray(t[0]);
- }
- function isMap(t: Sort): t is Map<string, SortDirection> {
- return t instanceof Map && t.size > 0;
- }
- /** @internal */
- function pairToMap(v: [string, SortDirection]): SortForCmd {
- return new Map([[`${v[0]}`, prepareDirection([v[1]])]]);
- }
- /** @internal */
- function deepToMap(t: [string, SortDirection][]): SortForCmd {
- const sortEntries: SortPairForCmd[] = t.map(([k, v]) => [`${k}`, prepareDirection(v)]);
- return new Map(sortEntries);
- }
- /** @internal */
- function stringsToMap(t: string[]): SortForCmd {
- const sortEntries: SortPairForCmd[] = t.map(key => [`${key}`, 1]);
- return new Map(sortEntries);
- }
- /** @internal */
- function objectToMap(t: { [key: string]: SortDirection }): SortForCmd {
- const sortEntries: SortPairForCmd[] = Object.entries(t).map(([k, v]) => [
- `${k}`,
- prepareDirection(v)
- ]);
- return new Map(sortEntries);
- }
- /** @internal */
- function mapToMap(t: Map<string, SortDirection>): SortForCmd {
- const sortEntries: SortPairForCmd[] = Array.from(t).map(([k, v]) => [
- `${k}`,
- prepareDirection(v)
- ]);
- return new Map(sortEntries);
- }
- /** converts a Sort type into a type that is valid for the server (SortForCmd) */
- export function formatSort(
- sort: Sort | undefined,
- direction?: SortDirection
- ): SortForCmd | undefined {
- if (sort == null) return undefined;
- if (typeof sort === 'string') return new Map([[sort, prepareDirection(direction)]]);
- if (typeof sort !== 'object') {
- throw new MongoInvalidArgumentError(
- `Invalid sort format: ${JSON.stringify(sort)} Sort must be a valid object`
- );
- }
- if (!Array.isArray(sort)) {
- return isMap(sort) ? mapToMap(sort) : Object.keys(sort).length ? objectToMap(sort) : undefined;
- }
- if (!sort.length) return undefined;
- if (isDeep(sort)) return deepToMap(sort);
- if (isPair(sort)) return pairToMap(sort);
- return stringsToMap(sort);
- }
|