Skip to content

Commit c16a51a

Browse files
committed
1) Added the following support: Converts a JavaScript object into a valid query, including single directives with args, so long as any variables used are enclosed in a string with '$' included.
2) Updated linting rules, and minor refactor following.
1 parent 5bc1208 commit c16a51a

File tree

3 files changed

+56
-24
lines changed

3 files changed

+56
-24
lines changed

src/__tests__/jsonToGraphQLQuery.tests.ts

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -146,25 +146,23 @@ describe('jsonToGraphQL()', () => {
146146
}`);
147147
});
148148

149-
it('Converts a JavaScript object into a valid Apollo query, including single directives with no arguments.', () => {
149+
it('Converts a JavaScript object into a valid query, including a single directive w/ no arguments.', () => {
150150
interface ILooseObject { [key: string]: any; }
151151
let input: ILooseObject = {
152152
__typename: 'everyday-health-focuses',
153153
diet: {
154154
__typename: 'diet',
155155
id: 'diet',
156156
options: {
157-
// tslint:disable-next-line:object-literal-key-quotes
158157
__typename: 'diet-options',
159-
'calorie-count': {
158+
calorieCount: {
160159
__typename: 'calorie-count',
161160
category: 'Diet',
162161
icon: 'fa fa-question-circle',
163162
id: 'calorie-count',
164163
selected: false,
165164
text: 'Calorie Count'
166165
},
167-
// tslint:disable-next-line:object-literal-key-quotes
168166
mood: {
169167
__typename: 'mood',
170168
category: 'Diet',
@@ -173,7 +171,6 @@ describe('jsonToGraphQL()', () => {
173171
selected: false,
174172
text: 'Mood'
175173
},
176-
// tslint:disable-next-line:object-literal-key-quotes
177174
weight: {
178175
__typename: 'weight',
179176
category: 'Diet',
@@ -197,14 +194,42 @@ describe('jsonToGraphQL()', () => {
197194
input[key]['__directives'] = { client: true, };
198195
});
199196
input = {query: input};
200-
// Do I want to add some keysToStrip functionality separately?
201-
// - const input = jsonToGraphqlQuery(preInput, { keysToStrip: ['__typename'] });
202-
const expected = 'query { diet @client { id options { calorie-count { category ' +
197+
const expected = 'query { diet @client { id options { calorieCount { category ' +
203198
'icon id text } mood { category icon id text } weight { category icon id text } } ' +
204199
'title } someOtherAbritraryKey @client { arb1 arb2 } }';
205200
expect(jsonToGraphQLQuery(input)).to.equal(expected);
206201
});
207202

203+
it('Converts a JavaScript object into a valid query, including single directives ' +
204+
'with args, so long as any variables used are enclosed in a string with "$" included.', () => {
205+
interface ILooseObject { [key: string]: any; }
206+
let input: ILooseObject = {
207+
someOtherAbritraryKey: {
208+
__typename: 'someArbitraryObjType',
209+
arb1: 'arbitrary value',
210+
arb2: 'some other arbitrary value'
211+
}
212+
};
213+
Object.keys(input)
214+
.filter(filterNonConfigFields)
215+
.forEach((key) => {
216+
input[key]['__directives'] = { include: {if: '$isAwesome'}, };
217+
});
218+
input = {query: input};
219+
const expected = 'query { someOtherAbritraryKey @include(if: $isAwesome) { arb1 arb2 } }';
220+
expect(jsonToGraphQLQuery(input)).to.equal(expected);
221+
});
222+
223+
// TODO
224+
// it('Converts a JavaScript object into a valid query, including *multiple* directives ' +
225+
// 'with args, so long as any variables used are enclosed in a string with "$" included.', () => {
226+
// });
227+
228+
// TODO
229+
// it('Creates a query, stripping/ignoring certain, specified keys.', () => {
230+
// // Example usage: jsonToGraphqlQuery(preInput, { keysToStrip: ['__typename'] });
231+
// });
232+
208233
it('converts a query with nested objects', () => {
209234
const query = {
210235
query: {

src/jsonToGraphQLQuery.ts

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,23 @@ function buildVariables(varsObj: any): string {
4646
}
4747

4848
function buildDirectives(dirsObj: any): string {
49-
const numDirectives = Object.keys(dirsObj).length;
50-
if (numDirectives > 1) {
51-
throw new Error(numDirectives.toString());
49+
const directiveName = Object.keys(dirsObj)[0];
50+
const directiveValue = dirsObj[directiveName];
51+
if (typeof directiveValue === 'boolean') {
52+
return directiveName;
53+
}
54+
else if (typeof directiveValue === 'object') {
55+
const args = [];
56+
for (const argName in directiveValue) {
57+
const argVal = stringify(directiveValue[argName]).replace(/"/g, '');
58+
args.push(`${argName}: ${argVal}`);
59+
}
60+
return `${directiveName}(${args.join(', ')})`;
61+
}
62+
else {
63+
throw new Error(`Unsupported type for directive: ${typeof directiveValue}. Types allowed: object, boolean.\n` +
64+
`Offending object: ${JSON.stringify(dirsObj)}`);
5265
}
53-
// const args = [];
54-
// for (const varName in dirsObj) {
55-
// args.push(`@${varName}: ${dirsObj[varName]}`);
56-
// }
57-
// return args.join(', ');
58-
return '@' + Object.keys(dirsObj)[0];
5966
}
6067

6168
function getIndent(level: number): string {
@@ -83,15 +90,14 @@ function convertQuery(node: any, level: number, output: Array<[ string, number ]
8390
token = `${key} (${buildVariables(node[key].__variables)})`;
8491
}
8592
else if (typeof node[key].__directives === 'object') {
86-
// TODO: Add support for multiple directives on one node, if that's a thing.
87-
try {
88-
token = `${key} ${buildDirectives(node[key].__directives)}`;
89-
} catch (e) {
90-
e = e.toString().replace(/Error: /, '');
93+
// TODO: Add support for multiple directives on one node.
94+
const numDirectives = Object.keys(node[key].__directives).length;
95+
if (numDirectives > 1) {
9196
throw new Error(`Too many directives. The object/key ` +
92-
`'${Object.keys(node[key])[0]}' had ${e} directives, ` +
97+
`'${Object.keys(node[key])[0]}' had ${numDirectives} directives, ` +
9398
`but only 1 directive per object/key is supported at this time.`);
9499
}
100+
token = `${key} @${buildDirectives(node[key].__directives)}`;
95101
}
96102
else {
97103
token = `${key}`;

tslint.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
],
55
"rules": {
66
"trailing-comma": [false],
7-
"object-literal-sort-keys": [true, "as-needed"],
7+
"object-literal-sort-keys": false,
8+
"object-literal-key-qhotes": [true, "as-needed"],
89
"ordered-imports": false,
910
"no-console": [false],
1011
"no-unused-new": false,

0 commit comments

Comments
 (0)