Skip to content

Commit 143f65e

Browse files
committed
✨ setValueMutate
1 parent 6f714f2 commit 143f65e

File tree

5 files changed

+314
-4
lines changed

5 files changed

+314
-4
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "graphql-js-tree",
3-
"version": "0.2.4",
3+
"version": "0.2.5",
44
"private": false,
55
"license": "MIT",
66
"description": "GraphQL Parser providing simplier structure",

src/Models/Spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ export enum Value {
2929
EnumValue = 'EnumValue',
3030
ListValue = 'ListValue',
3131
ObjectValue = 'ObjectValue',
32+
IDValue = 'IDValue',
33+
ScalarValue = 'ScalarValue',
3234
}
3335
export enum Type {
3436
NamedType = 'NamedType',

src/TreeOperations/shared.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { AllTypes, FieldType, Options, ParserField, TypeExtension } from '@/Models';
1+
import { AllTypes, FieldType, Options, ParserField, ScalarTypes, TypeExtension } from '@/Models';
22
import { generateNodeId, getTypeName } from '@/shared';
33

44
export function filterNotNull<T>(t: T | null): t is T {
@@ -102,3 +102,26 @@ export const ChangeAllRelatedNodes = ({
102102
}) => {
103103
nodes.forEach((n) => ChangeRelatedNode({ oldName, newName, node: n }));
104104
};
105+
106+
export const isScalarArgument = (field: ParserField, scalarTypes: string[]) => {
107+
const typeName = getTypeName(field.type.fieldType);
108+
if (typeName === ScalarTypes.Boolean) {
109+
return true;
110+
}
111+
if (typeName === ScalarTypes.Float) {
112+
return true;
113+
}
114+
if (typeName === ScalarTypes.ID) {
115+
return true;
116+
}
117+
if (typeName === ScalarTypes.Int) {
118+
return true;
119+
}
120+
if (typeName === ScalarTypes.String) {
121+
return true;
122+
}
123+
return scalarTypes.includes(typeName);
124+
};
125+
126+
export const isArrayType = (f: FieldType) =>
127+
f.type === Options.required ? f.nest.type === Options.array : f.type === Options.array;

src/TreeOperations/tree.ts

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,26 @@
1-
import { ParserField, TypeDefinition, TypeSystemDefinition, TypeExtension, ParserTree } from '@/Models';
1+
import {
2+
ParserField,
3+
TypeDefinition,
4+
TypeSystemDefinition,
5+
TypeExtension,
6+
ParserTree,
7+
Value,
8+
ScalarTypes,
9+
} from '@/Models';
210
import { getTypeName } from '@/shared';
311
import {
412
changeInterfaceField,
513
updateInterfaceNodeAddField,
614
_getAllConnectedInterfaces,
715
} from '@/TreeOperations/interface';
8-
import { ChangeAllRelatedNodes, filterNotNull, isExtensionNode, regenerateId } from '@/TreeOperations/shared';
16+
import {
17+
ChangeAllRelatedNodes,
18+
filterNotNull,
19+
isArrayType,
20+
isExtensionNode,
21+
isScalarArgument,
22+
regenerateId,
23+
} from '@/TreeOperations/shared';
924

1025
export const mutate = (tree: ParserTree, allNodes: ParserField[]) => {
1126
const mutateParentIfField = (node: ParserField) => {
@@ -145,6 +160,12 @@ export const mutate = (tree: ParserTree, allNodes: ParserField[]) => {
145160
.filter(filterNotNull);
146161
regenerateId(node);
147162
};
163+
const setValueNode = (node: ParserField, value: string) => {
164+
node.value = {
165+
value,
166+
type: checkValueType(node, allNodes),
167+
};
168+
};
148169
return {
149170
deleteFieldFromNode,
150171
updateFieldOnNode,
@@ -153,5 +174,45 @@ export const mutate = (tree: ParserTree, allNodes: ParserField[]) => {
153174
removeNode,
154175
implementInterface,
155176
deImplementInterface,
177+
setValueNode,
156178
};
157179
};
180+
181+
const checkValueType = (node: ParserField, nodes: ParserField[]) => {
182+
const isArray = isArrayType(node.type.fieldType);
183+
if (isArray) return Value.ListValue;
184+
const tName = getTypeName(node.type.fieldType);
185+
const scalarTypes = nodes.filter((n) => n.data.type === TypeDefinition.ScalarTypeDefinition).map((n) => n.name);
186+
if (isScalarArgument(node, scalarTypes)) {
187+
if (tName === ScalarTypes.Boolean) {
188+
return Value.BooleanValue;
189+
}
190+
if (tName === ScalarTypes.Float) {
191+
return Value.FloatValue;
192+
}
193+
if (tName === ScalarTypes.ID) {
194+
return Value.IDValue;
195+
}
196+
if (tName === ScalarTypes.Int) {
197+
return Value.IntValue;
198+
}
199+
if (tName === ScalarTypes.String) {
200+
return Value.StringValue;
201+
}
202+
return Value.ScalarValue;
203+
}
204+
const parentNode = nodes.find((n) => n.name === tName);
205+
if (
206+
parentNode?.data.type === TypeDefinition.InputObjectTypeDefinition ||
207+
parentNode?.data.type === TypeExtension.InputObjectTypeExtension
208+
) {
209+
return Value.ObjectValue;
210+
}
211+
if (
212+
parentNode?.data.type === TypeDefinition.EnumTypeDefinition ||
213+
parentNode?.data.type === TypeExtension.EnumTypeExtension
214+
) {
215+
return Value.EnumValue;
216+
}
217+
return Value.Variable;
218+
};

src/__tests__/TreeOperations/tree.spec.ts

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
TypeDefinition,
88
TypeDefinitionDisplayStrings,
99
TypeSystemDefinition,
10+
Value,
1011
ValueDefinition,
1112
} from '../../Models';
1213
const mainMock: ParserTree = {
@@ -109,10 +110,149 @@ const mainMock: ParserTree = {
109110
},
110111
name: 'id',
111112
}),
113+
createParserField({
114+
data: {
115+
type: ValueDefinition.InputValueDefinition,
116+
},
117+
type: {
118+
fieldType: {
119+
type: Options.name,
120+
name: ScalarTypes.Int,
121+
},
122+
},
123+
name: 'age',
124+
}),
125+
createParserField({
126+
data: {
127+
type: ValueDefinition.InputValueDefinition,
128+
},
129+
type: {
130+
fieldType: {
131+
type: Options.name,
132+
name: ScalarTypes.Float,
133+
},
134+
},
135+
name: 'degrees',
136+
}),
137+
createParserField({
138+
data: {
139+
type: ValueDefinition.InputValueDefinition,
140+
},
141+
type: {
142+
fieldType: {
143+
type: Options.name,
144+
name: ScalarTypes.Boolean,
145+
},
146+
},
147+
name: 'isOk',
148+
}),
149+
createParserField({
150+
data: {
151+
type: ValueDefinition.InputValueDefinition,
152+
},
153+
type: {
154+
fieldType: {
155+
type: Options.name,
156+
name: 'AnInput',
157+
},
158+
},
159+
name: 'testInput',
160+
}),
161+
createParserField({
162+
data: {
163+
type: ValueDefinition.InputValueDefinition,
164+
},
165+
type: {
166+
fieldType: {
167+
type: Options.array,
168+
nest: {
169+
type: Options.name,
170+
name: ScalarTypes.String,
171+
},
172+
},
173+
},
174+
name: 'testList',
175+
}),
176+
createParserField({
177+
data: {
178+
type: ValueDefinition.InputValueDefinition,
179+
},
180+
type: {
181+
fieldType: {
182+
type: Options.name,
183+
name: 'AnEnum',
184+
},
185+
},
186+
name: 'testEnum',
187+
}),
112188
],
113189
}),
114190
],
115191
}),
192+
createParserField({
193+
name: 'AnInput',
194+
data: {
195+
type: TypeDefinition.InputObjectTypeDefinition,
196+
},
197+
type: {
198+
fieldType: {
199+
type: Options.name,
200+
name: TypeDefinitionDisplayStrings.input,
201+
},
202+
},
203+
args: [
204+
createParserField({
205+
data: {
206+
type: ValueDefinition.InputValueDefinition,
207+
},
208+
name: 'firstName',
209+
type: {
210+
fieldType: {
211+
type: Options.name,
212+
name: ScalarTypes.String,
213+
},
214+
},
215+
}),
216+
],
217+
}),
218+
createParserField({
219+
name: 'AnEnum',
220+
data: {
221+
type: TypeDefinition.EnumTypeDefinition,
222+
},
223+
type: {
224+
fieldType: {
225+
type: Options.name,
226+
name: TypeDefinitionDisplayStrings.enum,
227+
},
228+
},
229+
args: [
230+
createParserField({
231+
name: 'HELLO',
232+
data: {
233+
type: ValueDefinition.EnumValueDefinition,
234+
},
235+
type: {
236+
fieldType: {
237+
type: Options.name,
238+
name: ValueDefinition.EnumValueDefinition,
239+
},
240+
},
241+
}),
242+
createParserField({
243+
name: 'WORLD',
244+
data: {
245+
type: ValueDefinition.EnumValueDefinition,
246+
},
247+
type: {
248+
fieldType: {
249+
type: Options.name,
250+
name: ValueDefinition.EnumValueDefinition,
251+
},
252+
},
253+
}),
254+
],
255+
}),
116256
],
117257
};
118258

@@ -290,6 +430,90 @@ describe('Tree Operations tests', () => {
290430
expect(treeMock.nodes[1].args[1].id).not.toEqual(oldFieldId);
291431
expect(treeMock.nodes[1].id).not.toEqual(oldQueryId);
292432
});
433+
test('Set input value default value - StringValue', () => {
434+
const treeMock = createMock();
435+
const updatedInputValue = createParserField({
436+
...treeMock.nodes[1].args[1].args[0],
437+
value: {
438+
type: Value.StringValue,
439+
value: 'Hello',
440+
},
441+
});
442+
mutate(treeMock, treeMock.nodes).setValueNode(treeMock.nodes[1].args[1].args[0], 'Hello');
443+
expect(treeMock.nodes[1].args[1].args).toContainEqual(updatedInputValue);
444+
});
445+
test('Set input value default value - IntValue', () => {
446+
const treeMock = createMock();
447+
const updatedInputValue = createParserField({
448+
...treeMock.nodes[1].args[1].args[1],
449+
value: {
450+
type: Value.IntValue,
451+
value: '18',
452+
},
453+
});
454+
mutate(treeMock, treeMock.nodes).setValueNode(treeMock.nodes[1].args[1].args[1], '18');
455+
expect(treeMock.nodes[1].args[1].args).toContainEqual(updatedInputValue);
456+
});
457+
test('Set input value default value - FloatValue', () => {
458+
const treeMock = createMock();
459+
const updatedInputValue = createParserField({
460+
...treeMock.nodes[1].args[1].args[2],
461+
value: {
462+
type: Value.FloatValue,
463+
value: '36.7',
464+
},
465+
});
466+
mutate(treeMock, treeMock.nodes).setValueNode(treeMock.nodes[1].args[1].args[2], '36.7');
467+
expect(treeMock.nodes[1].args[1].args).toContainEqual(updatedInputValue);
468+
});
469+
test('Set input value default value - BooleanValue', () => {
470+
const treeMock = createMock();
471+
const updatedInputValue = createParserField({
472+
...treeMock.nodes[1].args[1].args[3],
473+
value: {
474+
type: Value.BooleanValue,
475+
value: 'true',
476+
},
477+
});
478+
mutate(treeMock, treeMock.nodes).setValueNode(treeMock.nodes[1].args[1].args[3], 'true');
479+
expect(treeMock.nodes[1].args[1].args).toContainEqual(updatedInputValue);
480+
});
481+
test('Set input value default value - ObjectValue', () => {
482+
const treeMock = createMock();
483+
const updatedInputValue = createParserField({
484+
...treeMock.nodes[1].args[1].args[4],
485+
value: {
486+
type: Value.ObjectValue,
487+
value: `{ firstName:"Hello" }`,
488+
},
489+
});
490+
mutate(treeMock, treeMock.nodes).setValueNode(treeMock.nodes[1].args[1].args[4], `{ firstName:"Hello" }`);
491+
expect(treeMock.nodes[1].args[1].args).toContainEqual(updatedInputValue);
492+
});
493+
test('Set input value default value - ListValue', () => {
494+
const treeMock = createMock();
495+
const updatedInputValue = createParserField({
496+
...treeMock.nodes[1].args[1].args[5],
497+
value: {
498+
type: Value.ListValue,
499+
value: `["Hello"]`,
500+
},
501+
});
502+
mutate(treeMock, treeMock.nodes).setValueNode(treeMock.nodes[1].args[1].args[5], `["Hello"]`);
503+
expect(treeMock.nodes[1].args[1].args).toContainEqual(updatedInputValue);
504+
});
505+
test('Set input value default value - EnumValue', () => {
506+
const treeMock = createMock();
507+
const updatedInputValue = createParserField({
508+
...treeMock.nodes[1].args[1].args[6],
509+
value: {
510+
type: Value.EnumValue,
511+
value: `HELLO`,
512+
},
513+
});
514+
mutate(treeMock, treeMock.nodes).setValueNode(treeMock.nodes[1].args[1].args[6], `HELLO`);
515+
expect(treeMock.nodes[1].args[1].args).toContainEqual(updatedInputValue);
516+
});
293517
test('Implement interface', () => {
294518
const treeMock = createInterfaceMock();
295519
mutate(treeMock, treeMock.nodes).implementInterface(treeMock.nodes[2], treeMock.nodes[0]);

0 commit comments

Comments
 (0)