forked from atulmy/gql-query-builder
-
Notifications
You must be signed in to change notification settings - Fork 0
/
DefaultQueryAdapter.ts
117 lines (110 loc) · 3.47 KB
/
DefaultQueryAdapter.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*
@class DefaultQueryAdapter
@desc A basic implementation to use
@desc modify the output of the query template by passing a second argument to query(options, AdapterClass)
*/
import Fields from "../Fields";
import IQueryBuilderOptions, { IOperation } from "../IQueryBuilderOptions";
import OperationType from "../OperationType";
import Utils from "../Utils";
import IQueryAdapter from "./IQueryAdapter";
import VariableOptions from "../VariableOptions";
export default class DefaultQueryAdapter implements IQueryAdapter {
private variables!: any | undefined;
private fields: Fields | undefined;
private operation!: string | IOperation;
private config: { [key: string]: unknown };
constructor(
options: IQueryBuilderOptions | IQueryBuilderOptions[],
configuration?: { [key: string]: unknown }
) {
// Default configs
this.config = {
operationName: "",
};
if (configuration) {
Object.entries(configuration).forEach(([key, value]) => {
this.config[key] = value;
});
}
if (Array.isArray(options)) {
this.variables = Utils.resolveVariables(options);
} else {
this.variables = options.variables;
this.fields = options.fields || [];
this.operation = options.operation;
}
}
// kicks off building for a single query
public queryBuilder() {
return this.operationWrapperTemplate(
this.operationTemplate(this.variables)
);
}
// if we have an array of options, call this
public queriesBuilder(queries: IQueryBuilderOptions[]) {
const content = () => {
const tmpl: string[] = [];
queries.forEach((query) => {
if (query) {
this.operation = query.operation;
this.fields = query.fields;
tmpl.push(this.operationTemplate(query.variables));
}
});
return tmpl.join(" ");
};
return this.operationWrapperTemplate(content());
}
// Convert object to argument and type map. eg: ($id: Int)
private queryDataArgumentAndTypeMap(): string {
let variablesUsed: { [key: string]: unknown } = this.variables;
if (this.fields && typeof this.fields === "object") {
variablesUsed = {
...Utils.getNestedVariables(this.fields),
...variablesUsed,
};
}
return variablesUsed && Object.keys(variablesUsed).length > 0
? `(${Object.keys(variablesUsed).reduce(
(dataString, key, i) =>
`${dataString}${i !== 0 ? ", " : ""}$${key}: ${Utils.queryDataType(
variablesUsed[key]
)}`,
""
)})`
: "";
}
private operationWrapperTemplate(content: string): {
variables: { [p: string]: unknown };
query: string;
} {
let query = `${
OperationType.Query
} ${this.queryDataArgumentAndTypeMap()} { ${content} }`;
query = query.replace(
"query",
`query${
this.config.operationName !== "" ? " " + this.config.operationName : ""
}`
);
return {
query,
variables: Utils.queryVariablesMap(this.variables, this.fields),
};
}
// query
private operationTemplate(variables: VariableOptions | undefined) {
const operation =
typeof this.operation === "string"
? this.operation
: `${this.operation.alias}: ${this.operation.name}`;
return `${operation} ${
variables ? Utils.queryDataNameAndArgumentMap(variables) : ""
} ${
this.fields && this.fields.length > 0
? "{ " + Utils.queryFieldsMap(this.fields) + " }"
: ""
}`;
}
}