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 133408x                                                                     297363x 297363x 296507x       278011x       18068x   428x           297363x         1933x 1276x 1276x 848x   428x     657x       4023x       288412x         848x         2896x 2090x         1513x 1085x         144073x       143615x         145399x       144797x       408x       336710x 295505x 292634x         292634x 288412x   4222x 4023x 1933x 1085x    
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);
}