All files / src sort.ts

97.82% Statements 45/46
95% Branches 38/40
100% Functions 15/15
97.22% Lines 35/36

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133147x                                                                     61535x 61535x 61359x       57743x       3528x   88x           61535x         388x 256x 256x 168x   88x     132x       822x       59734x         168x         604x 434x         308x 220x         29823x       29735x         30128x       29999x       147x       69862x 61156x 60600x         60600x 59734x   866x 822x 388x 220x    
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 {
      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)]]);
  Iif (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);
}