UNPKG

@e22m4u/js-repository

Version:

Реализация репозитория для работы с базами данных в Node.js

101 lines (96 loc) 2.84 kB
import {Service} from '@e22m4u/js-service'; import {getValueByPath} from '../utils/index.js'; import {InvalidArgumentError} from '../errors/index.js'; /** * Order clause tool. */ export class OrderClauseTool extends Service { /** * Sort. * * @param {object[]} entities * @param {string|string[]|undefined} clause */ sort(entities, clause) { if (clause == null) return; if (Array.isArray(clause) === false) clause = [clause]; if (!clause.length) return; const mapping = []; clause.forEach((key, index) => { if (!key || typeof key !== 'string') throw new InvalidArgumentError( 'The provided option "order" should be a non-empty String ' + 'or an Array of non-empty String, but %v was given.', key, ); let reverse = 1; const matches = key.match(/\s+(A|DE)SC$/i); if (matches) { key = key.replace(/\s+(A|DE)SC/i, ''); if (matches[1].toLowerCase() === 'de') reverse = -1; } mapping[index] = {key: key, reverse}; }); entities.sort(compareFn.bind(mapping)); } /** * Validate order clause. * * @param {string|string[]|undefined} clause */ static validateOrderClause(clause) { if (clause == null) return; if (Array.isArray(clause) === false) clause = [clause]; if (!clause.length) return; clause.forEach(field => { if (!field || typeof field !== 'string') throw new InvalidArgumentError( 'The provided option "order" should be a non-empty String ' + 'or an Array of non-empty String, but %v was given.', field, ); }); } /** * Normalize order clause. * * @param {string|string[]|undefined} clause * @returns {string[]|undefined} */ static normalizeOrderClause(clause) { if (clause == null) return; if (Array.isArray(clause) === false) clause = [clause]; if (!clause.length) return; clause.forEach(field => { if (!field || typeof field !== 'string') throw new InvalidArgumentError( 'The provided option "order" should be a non-empty String ' + 'or an Array of non-empty String, but %v was given.', field, ); }); return clause; } } /** * Compare fn. * * @param {*} a * @param {*} b * @returns {number} */ function compareFn(a, b) { let undefinedA, undefinedB; for (let i = 0, l = this.length; i < l; i++) { const aVal = getValueByPath(a, this[i].key); const bVal = getValueByPath(b, this[i].key); undefinedB = bVal === undefined && aVal !== undefined; undefinedA = aVal === undefined && bVal !== undefined; if (undefinedB || aVal > bVal) { return this[i].reverse; } else if (undefinedA || aVal < bVal) { return -1 * this[i].reverse; } } return 0; }