-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathterm-list-clause.ts
94 lines (83 loc) · 2.32 KB
/
term-list-clause.ts
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
import {
flatMapDeep,
map,
isPlainObject,
isString,
isArray,
castArray,
reduce,
Dictionary,
Many,
} from 'lodash';
import { Clause } from '../clause';
export type Properties = Many<string | Dictionary<string>>;
export type Term
= string
| Dictionary<Properties>;
export class TermListClause extends Clause {
protected terms: Term[];
/**
* Accepts:
* node -> string
* many nodes -> string[]
* nodes with aliases -> Dictionary<string>
* node properties -> Dictionary<string[]>
* node properties with aliases -> Dictionary<Dictionary<string>[]>
* or an array of any combination
*/
constructor(terms: Many<Term>) {
super();
this.terms = castArray(terms);
}
build() {
return this.toString();
}
toString() {
return flatMapDeep(this.terms, term => this.stringifyTerm(term)).join(', ');
}
private stringifyTerm(term: Term): string[] {
// Just a node
if (isString(term)) {
return [this.stringifyProperty(term)];
}
// Node properties or aliases
if (isPlainObject(term)) {
return this.stringifyDictionary(term);
}
return [];
}
private stringifyProperty(prop: string, alias?: string, node?: string): string {
const prefixString = node ? `${node}.` : '';
const aliasString = alias ? `${alias} AS ` : '';
return prefixString + aliasString + prop;
}
private stringifyProperties(props: Properties, alias?: string, node?: string): string[] {
const convertToString = (list: string[], prop: string | Dictionary<string>) => {
if (isString(prop)) {
// Single node property
list.push(this.stringifyProperty(prop, alias, node));
} else {
// Node properties with aliases
list.push(...map(prop, (name, alias) => this.stringifyProperty(name, alias, node)));
}
return list;
};
return reduce(castArray(props), convertToString, []);
}
private stringifyDictionary(node: Dictionary<Properties>): string[] {
return reduce(
node,
(list, prop, key) => {
if (isString(prop)) {
// Alias
list.push(this.stringifyProperty(prop, key));
} else {
// Node with properties
list.push(...this.stringifyProperties(prop, undefined, key));
}
return list;
},
[] as string[],
);
}
}