graphql-data-generator 0.4.1-alpha.6 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/codegen.js +96 -22
- package/package.json +1 -1
- package/script/codegen.js +96 -22
package/esm/codegen.js
CHANGED
|
@@ -262,6 +262,9 @@ const serializeType = (type, variables = false, depth = 0) => {
|
|
|
262
262
|
...ands.slice(1),
|
|
263
263
|
].filter(Boolean).join(" & ")}${type.optional ? " | null" : ""}`;
|
|
264
264
|
}
|
|
265
|
+
case "Union":
|
|
266
|
+
return type.value.map(member => serializeType(member, variables, depth)).join(" | ") +
|
|
267
|
+
(type.optional ? " | null" : "");
|
|
265
268
|
case "StringLiteral":
|
|
266
269
|
return `"${type.value}"`;
|
|
267
270
|
}
|
|
@@ -296,6 +299,11 @@ const fillOutInput = (input, inputs, references) => {
|
|
|
296
299
|
return input;
|
|
297
300
|
return serializeInput(def[0].fields ?? [], input.optional, inputs, references);
|
|
298
301
|
}
|
|
302
|
+
case "Union":
|
|
303
|
+
return {
|
|
304
|
+
...input,
|
|
305
|
+
value: input.value.map(member => fillOutInput(member, inputs, references))
|
|
306
|
+
};
|
|
299
307
|
case "StringLiteral":
|
|
300
308
|
return input;
|
|
301
309
|
}
|
|
@@ -565,31 +573,97 @@ ${usedTypes.map(([name]) => ` ${name}: ${rename(name)};`).join("\n")}
|
|
|
565
573
|
// Generate types for fragments
|
|
566
574
|
const fragmentTypes = Object.entries(fragments).map(([fragmentName, fragment]) => {
|
|
567
575
|
const fragmentSelections = getSelectionsType(fragment.typeCondition.name.value, fragment.selectionSet.selections, types, fragments, references, includeTypenames);
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
576
|
+
// Check if fragment is on a union type by looking for grouped selections (inline fragments)
|
|
577
|
+
const groupedSelections = new Map();
|
|
578
|
+
for (const [name, type, group] of fragmentSelections) {
|
|
579
|
+
if (!groupedSelections.has(group)) {
|
|
580
|
+
groupedSelections.set(group, []);
|
|
581
|
+
}
|
|
582
|
+
groupedSelections.get(group).push([name, type]);
|
|
583
|
+
}
|
|
584
|
+
// If we have multiple groups, this is a union fragment
|
|
585
|
+
const hasMultipleGroups = groupedSelections.size > 1 ||
|
|
586
|
+
(groupedSelections.size === 1 && !groupedSelections.has(undefined));
|
|
587
|
+
if (hasMultipleGroups) {
|
|
588
|
+
// Generate discriminated union for union fragments
|
|
589
|
+
const unionMembers = [];
|
|
590
|
+
for (const [group, selections] of groupedSelections) {
|
|
591
|
+
if (group) {
|
|
592
|
+
// This is an inline fragment group - create an object type for it
|
|
593
|
+
const memberFields = selections.reduce((fields, [name, type]) => {
|
|
594
|
+
fields[name] = type;
|
|
595
|
+
return fields;
|
|
596
|
+
}, {});
|
|
597
|
+
// Add __typename for the specific union member type
|
|
598
|
+
if (includeTypenames) {
|
|
599
|
+
Object.defineProperty(memberFields, "__typename", {
|
|
600
|
+
enumerable: true,
|
|
601
|
+
value: {
|
|
602
|
+
kind: "StringLiteral",
|
|
603
|
+
value: group.split(':')[0], // Handle nested groups
|
|
604
|
+
optional: false,
|
|
605
|
+
},
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
unionMembers.push({
|
|
609
|
+
kind: "Object",
|
|
610
|
+
value: memberFields,
|
|
611
|
+
optional: false,
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
else {
|
|
615
|
+
// Fields without group (shouldn't happen in union fragments, but handle gracefully)
|
|
616
|
+
const sharedFields = selections.reduce((fields, [name, type]) => {
|
|
617
|
+
fields[name] = type;
|
|
618
|
+
return fields;
|
|
619
|
+
}, {});
|
|
620
|
+
if (Object.keys(sharedFields).length > 0) {
|
|
621
|
+
unionMembers.push({
|
|
622
|
+
kind: "Object",
|
|
623
|
+
value: sharedFields,
|
|
624
|
+
optional: false,
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
return [
|
|
630
|
+
fragmentName,
|
|
631
|
+
{
|
|
632
|
+
kind: "Union",
|
|
633
|
+
value: unionMembers,
|
|
580
634
|
optional: false,
|
|
581
635
|
},
|
|
582
|
-
|
|
636
|
+
[...new Set(fragmentSelections.map(([name]) => name))]
|
|
637
|
+
];
|
|
638
|
+
}
|
|
639
|
+
else {
|
|
640
|
+
// Regular object fragment (not on union type)
|
|
641
|
+
const fragmentFields = fragmentSelections.reduce((fields, [name, type]) => {
|
|
642
|
+
fields[name] = type;
|
|
643
|
+
return fields;
|
|
644
|
+
}, {});
|
|
645
|
+
// Add __typename for object types
|
|
646
|
+
const baseTypeDef = types[fragment.typeCondition.name.value];
|
|
647
|
+
if (includeTypenames && baseTypeDef?.[0].kind === "ObjectTypeDefinition") {
|
|
648
|
+
Object.defineProperty(fragmentFields, "__typename", {
|
|
649
|
+
enumerable: true,
|
|
650
|
+
value: {
|
|
651
|
+
kind: "StringLiteral",
|
|
652
|
+
value: fragment.typeCondition.name.value,
|
|
653
|
+
optional: false,
|
|
654
|
+
},
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
return [
|
|
658
|
+
fragmentName,
|
|
659
|
+
{
|
|
660
|
+
kind: "Object",
|
|
661
|
+
value: fragmentFields,
|
|
662
|
+
optional: false,
|
|
663
|
+
},
|
|
664
|
+
[...new Set(fragmentSelections.map(([name]) => name))]
|
|
665
|
+
];
|
|
583
666
|
}
|
|
584
|
-
return [
|
|
585
|
-
fragmentName,
|
|
586
|
-
{
|
|
587
|
-
kind: "Object",
|
|
588
|
-
value: fragmentFields,
|
|
589
|
-
optional: false,
|
|
590
|
-
},
|
|
591
|
-
[...new Set(fragmentSelections.map(([name]) => name))]
|
|
592
|
-
];
|
|
593
667
|
});
|
|
594
668
|
if (fragmentTypes.length) {
|
|
595
669
|
serializedTypes.unshift(...fragmentTypes.map(([name, type, _fields]) => `${exports.includes("types") ? "export " : ""}type ${name} = ${serializeType(type, false)};`).filter(filterOutputTypes));
|
package/package.json
CHANGED
package/script/codegen.js
CHANGED
|
@@ -268,6 +268,9 @@ const serializeType = (type, variables = false, depth = 0) => {
|
|
|
268
268
|
...ands.slice(1),
|
|
269
269
|
].filter(Boolean).join(" & ")}${type.optional ? " | null" : ""}`;
|
|
270
270
|
}
|
|
271
|
+
case "Union":
|
|
272
|
+
return type.value.map(member => serializeType(member, variables, depth)).join(" | ") +
|
|
273
|
+
(type.optional ? " | null" : "");
|
|
271
274
|
case "StringLiteral":
|
|
272
275
|
return `"${type.value}"`;
|
|
273
276
|
}
|
|
@@ -302,6 +305,11 @@ const fillOutInput = (input, inputs, references) => {
|
|
|
302
305
|
return input;
|
|
303
306
|
return serializeInput(def[0].fields ?? [], input.optional, inputs, references);
|
|
304
307
|
}
|
|
308
|
+
case "Union":
|
|
309
|
+
return {
|
|
310
|
+
...input,
|
|
311
|
+
value: input.value.map(member => fillOutInput(member, inputs, references))
|
|
312
|
+
};
|
|
305
313
|
case "StringLiteral":
|
|
306
314
|
return input;
|
|
307
315
|
}
|
|
@@ -571,31 +579,97 @@ ${usedTypes.map(([name]) => ` ${name}: ${rename(name)};`).join("\n")}
|
|
|
571
579
|
// Generate types for fragments
|
|
572
580
|
const fragmentTypes = Object.entries(fragments).map(([fragmentName, fragment]) => {
|
|
573
581
|
const fragmentSelections = getSelectionsType(fragment.typeCondition.name.value, fragment.selectionSet.selections, types, fragments, references, includeTypenames);
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
582
|
+
// Check if fragment is on a union type by looking for grouped selections (inline fragments)
|
|
583
|
+
const groupedSelections = new Map();
|
|
584
|
+
for (const [name, type, group] of fragmentSelections) {
|
|
585
|
+
if (!groupedSelections.has(group)) {
|
|
586
|
+
groupedSelections.set(group, []);
|
|
587
|
+
}
|
|
588
|
+
groupedSelections.get(group).push([name, type]);
|
|
589
|
+
}
|
|
590
|
+
// If we have multiple groups, this is a union fragment
|
|
591
|
+
const hasMultipleGroups = groupedSelections.size > 1 ||
|
|
592
|
+
(groupedSelections.size === 1 && !groupedSelections.has(undefined));
|
|
593
|
+
if (hasMultipleGroups) {
|
|
594
|
+
// Generate discriminated union for union fragments
|
|
595
|
+
const unionMembers = [];
|
|
596
|
+
for (const [group, selections] of groupedSelections) {
|
|
597
|
+
if (group) {
|
|
598
|
+
// This is an inline fragment group - create an object type for it
|
|
599
|
+
const memberFields = selections.reduce((fields, [name, type]) => {
|
|
600
|
+
fields[name] = type;
|
|
601
|
+
return fields;
|
|
602
|
+
}, {});
|
|
603
|
+
// Add __typename for the specific union member type
|
|
604
|
+
if (includeTypenames) {
|
|
605
|
+
Object.defineProperty(memberFields, "__typename", {
|
|
606
|
+
enumerable: true,
|
|
607
|
+
value: {
|
|
608
|
+
kind: "StringLiteral",
|
|
609
|
+
value: group.split(':')[0], // Handle nested groups
|
|
610
|
+
optional: false,
|
|
611
|
+
},
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
unionMembers.push({
|
|
615
|
+
kind: "Object",
|
|
616
|
+
value: memberFields,
|
|
617
|
+
optional: false,
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
else {
|
|
621
|
+
// Fields without group (shouldn't happen in union fragments, but handle gracefully)
|
|
622
|
+
const sharedFields = selections.reduce((fields, [name, type]) => {
|
|
623
|
+
fields[name] = type;
|
|
624
|
+
return fields;
|
|
625
|
+
}, {});
|
|
626
|
+
if (Object.keys(sharedFields).length > 0) {
|
|
627
|
+
unionMembers.push({
|
|
628
|
+
kind: "Object",
|
|
629
|
+
value: sharedFields,
|
|
630
|
+
optional: false,
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
return [
|
|
636
|
+
fragmentName,
|
|
637
|
+
{
|
|
638
|
+
kind: "Union",
|
|
639
|
+
value: unionMembers,
|
|
586
640
|
optional: false,
|
|
587
641
|
},
|
|
588
|
-
|
|
642
|
+
[...new Set(fragmentSelections.map(([name]) => name))]
|
|
643
|
+
];
|
|
644
|
+
}
|
|
645
|
+
else {
|
|
646
|
+
// Regular object fragment (not on union type)
|
|
647
|
+
const fragmentFields = fragmentSelections.reduce((fields, [name, type]) => {
|
|
648
|
+
fields[name] = type;
|
|
649
|
+
return fields;
|
|
650
|
+
}, {});
|
|
651
|
+
// Add __typename for object types
|
|
652
|
+
const baseTypeDef = types[fragment.typeCondition.name.value];
|
|
653
|
+
if (includeTypenames && baseTypeDef?.[0].kind === "ObjectTypeDefinition") {
|
|
654
|
+
Object.defineProperty(fragmentFields, "__typename", {
|
|
655
|
+
enumerable: true,
|
|
656
|
+
value: {
|
|
657
|
+
kind: "StringLiteral",
|
|
658
|
+
value: fragment.typeCondition.name.value,
|
|
659
|
+
optional: false,
|
|
660
|
+
},
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
return [
|
|
664
|
+
fragmentName,
|
|
665
|
+
{
|
|
666
|
+
kind: "Object",
|
|
667
|
+
value: fragmentFields,
|
|
668
|
+
optional: false,
|
|
669
|
+
},
|
|
670
|
+
[...new Set(fragmentSelections.map(([name]) => name))]
|
|
671
|
+
];
|
|
589
672
|
}
|
|
590
|
-
return [
|
|
591
|
-
fragmentName,
|
|
592
|
-
{
|
|
593
|
-
kind: "Object",
|
|
594
|
-
value: fragmentFields,
|
|
595
|
-
optional: false,
|
|
596
|
-
},
|
|
597
|
-
[...new Set(fragmentSelections.map(([name]) => name))]
|
|
598
|
-
];
|
|
599
673
|
});
|
|
600
674
|
if (fragmentTypes.length) {
|
|
601
675
|
serializedTypes.unshift(...fragmentTypes.map(([name, type, _fields]) => `${exports.includes("types") ? "export " : ""}type ${name} = ${serializeType(type, false)};`).filter(filterOutputTypes));
|