UNPKG

@sqb/connect

Version:

Multi-dialect database connection framework written with TypeScript

62 lines (61 loc) 1.94 kB
import { splitString } from 'fast-tokenizer'; const FIELD_PATTERN = /^([+-])?([a-z_$]\w*)$/i; const NO_DOT_BRACKET_PATTERN = /[^.]\(/g; export class FieldsProjection { } (function (FieldsProjection) { class Item { } FieldsProjection.Item = Item; })(FieldsProjection || (FieldsProjection = {})); export function parseFieldsProjection(projection, keepCase) { const arr = Array.isArray(projection) ? projection : [projection]; if (!(arr && arr.length)) return; const out = new FieldsProjection(); for (let s of arr) { if (!keepCase) s = s.toLowerCase(); parse(s, out); } return out; } function parse(input, target) { /** Add dot before brackets which is required to split fields */ input = input.replace(NO_DOT_BRACKET_PATTERN, s => s.charAt(0) + '.' + s.substring(1)); const fields = splitString(input, { delimiters: '.', brackets: true, keepBrackets: false, }); for (let i = 0; i < fields.length; i++) { const f = fields[i]; if (f.includes(',')) { const subFields = splitString(f, { delimiters: ',', brackets: true, keepBrackets: true, }); for (const n of subFields) { parse(n, target); } continue; } const m = FIELD_PATTERN.exec(f); /* istanbul ignore next */ if (!m) throw new TypeError(`Invalid field path (${input})`); const fieldName = m[2]; const treeItem = (target[fieldName] = target[fieldName] || new FieldsProjection.Item()); if (m[1]) treeItem.sign = m[1]; if (i === fields.length - 1) { delete treeItem.projection; } else { target = treeItem.projection = treeItem.projection || new FieldsProjection(); } } }