@nmarks/graphql-codegen-per-operation-file-preset 1.0.1 → 1.0.3
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/cjs/index.js +104 -2
- package/esm/index.js +105 -3
- package/package.json +1 -1
package/cjs/index.js
CHANGED
|
@@ -5,7 +5,6 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const path_1 = require("path");
|
|
6
6
|
const graphql_1 = require("graphql");
|
|
7
7
|
const add_1 = tslib_1.__importDefault(require("@graphql-codegen/add"));
|
|
8
|
-
const plugin_helpers_1 = require("@graphql-codegen/plugin-helpers");
|
|
9
8
|
const visitor_plugin_common_1 = require("@graphql-codegen/visitor-plugin-common");
|
|
10
9
|
const resolve_document_imports_js_1 = require("./resolve-document-imports.js");
|
|
11
10
|
const utils_js_1 = require("./utils.js");
|
|
@@ -24,6 +23,109 @@ function extractDefinitions(document) {
|
|
|
24
23
|
}
|
|
25
24
|
return definitions;
|
|
26
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Check if a document actually needs type imports from the schema.
|
|
28
|
+
* Only returns true if the document uses:
|
|
29
|
+
* - Enums
|
|
30
|
+
* - Custom scalars that aren't mapped to primitives
|
|
31
|
+
* - Input types (in variables)
|
|
32
|
+
*
|
|
33
|
+
* Does NOT return true for just referencing object types.
|
|
34
|
+
*/
|
|
35
|
+
function needsSchemaTypesImport(document, schema, config) {
|
|
36
|
+
const builtInScalars = ['String', 'Int', 'Float', 'Boolean', 'ID'];
|
|
37
|
+
const primitiveTypes = ['any', 'string', 'number', 'boolean', 'null', 'undefined', 'void', 'never', 'unknown'];
|
|
38
|
+
let needsImport = false;
|
|
39
|
+
// Get scalar mappings from config
|
|
40
|
+
const scalarMappings = config.scalars || {};
|
|
41
|
+
// Collect all type names referenced in the document
|
|
42
|
+
const referencedTypeNames = new Set();
|
|
43
|
+
(0, graphql_1.visit)(document, {
|
|
44
|
+
// Check variable types for input types or custom scalars
|
|
45
|
+
VariableDefinition: (node) => {
|
|
46
|
+
const typeName = getBaseTypeName(node.type);
|
|
47
|
+
referencedTypeNames.add(typeName);
|
|
48
|
+
},
|
|
49
|
+
// Collect fragment type conditions
|
|
50
|
+
FragmentDefinition: (node) => {
|
|
51
|
+
referencedTypeNames.add(node.typeCondition.name.value);
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
// Helper to recursively check if a type needs importing
|
|
55
|
+
const checkType = (type) => {
|
|
56
|
+
if (!type)
|
|
57
|
+
return false;
|
|
58
|
+
// Unwrap lists and non-null
|
|
59
|
+
while ('ofType' in type && type.ofType) {
|
|
60
|
+
type = type.ofType;
|
|
61
|
+
}
|
|
62
|
+
// Enums always need to be imported
|
|
63
|
+
if ((0, graphql_1.isEnumType)(type)) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
// Custom scalars need to be imported UNLESS mapped to primitives
|
|
67
|
+
if ((0, graphql_1.isScalarType)(type) && !builtInScalars.includes(type.name)) {
|
|
68
|
+
// Check if this scalar is mapped to a primitive type
|
|
69
|
+
const mapping = scalarMappings[type.name];
|
|
70
|
+
if (mapping) {
|
|
71
|
+
// If mapped to a primitive type string, no import needed
|
|
72
|
+
if (typeof mapping === 'string' && primitiveTypes.includes(mapping)) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
// If mapped to an object like { input: 'any', output: 'any' }, check both
|
|
76
|
+
if (typeof mapping === 'object') {
|
|
77
|
+
const inputMapping = mapping.input || mapping.output;
|
|
78
|
+
const outputMapping = mapping.output || mapping.input;
|
|
79
|
+
if (primitiveTypes.includes(inputMapping) && primitiveTypes.includes(outputMapping)) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
// No mapping specified, defaults to 'any', so no import needed
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
// Scalar is mapped to something non-primitive, needs import
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
// Input types need to be imported
|
|
92
|
+
if ((0, graphql_1.isInputObjectType)(type)) {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
return false;
|
|
96
|
+
};
|
|
97
|
+
// Check variable types
|
|
98
|
+
for (const typeName of referencedTypeNames) {
|
|
99
|
+
const type = schema.getType(typeName);
|
|
100
|
+
if (checkType(type)) {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// Now we need to check all fields in the document to see if any return enums/custom scalars
|
|
105
|
+
// We'll do a more thorough traversal with TypeInfo
|
|
106
|
+
const typeInfo = new graphql_1.TypeInfo(schema);
|
|
107
|
+
(0, graphql_1.visit)(document, (0, graphql_1.visitWithTypeInfo)(typeInfo, {
|
|
108
|
+
Field: () => {
|
|
109
|
+
const fieldType = typeInfo.getType();
|
|
110
|
+
if (checkType(fieldType)) {
|
|
111
|
+
needsImport = true;
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
}));
|
|
115
|
+
return needsImport;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Extract the base type name from a type node
|
|
119
|
+
*/
|
|
120
|
+
function getBaseTypeName(type) {
|
|
121
|
+
if (type.kind === 'NamedType') {
|
|
122
|
+
return type.name.value;
|
|
123
|
+
}
|
|
124
|
+
if (type.kind === 'ListType' || type.kind === 'NonNullType') {
|
|
125
|
+
return getBaseTypeName(type.type);
|
|
126
|
+
}
|
|
127
|
+
return '';
|
|
128
|
+
}
|
|
27
129
|
exports.preset = {
|
|
28
130
|
buildGeneratesSection: options => {
|
|
29
131
|
var _a, _b;
|
|
@@ -84,7 +186,7 @@ exports.preset = {
|
|
|
84
186
|
...source.externalFragments.map(fragment => fragment.node),
|
|
85
187
|
],
|
|
86
188
|
};
|
|
87
|
-
const needsTypesImport = (
|
|
189
|
+
const needsTypesImport = needsSchemaTypesImport(singleDefDocumentWithFragments, schemaObject, options.config);
|
|
88
190
|
// Generate the types import statement if needed
|
|
89
191
|
const importStatements = [];
|
|
90
192
|
if (needsTypesImport && !options.config.globalNamespace) {
|
package/esm/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { join } from 'path';
|
|
2
|
-
import { buildASTSchema, Kind } from 'graphql';
|
|
2
|
+
import { buildASTSchema, isEnumType, isInputObjectType, isScalarType, Kind, TypeInfo, visit, visitWithTypeInfo } from 'graphql';
|
|
3
3
|
import addPlugin from '@graphql-codegen/add';
|
|
4
|
-
import { isUsingTypes } from '@graphql-codegen/plugin-helpers';
|
|
5
4
|
import { generateImportStatement, getConfigValue, resolveImportSource, } from '@graphql-codegen/visitor-plugin-common';
|
|
6
5
|
import { resolveDocumentImports } from './resolve-document-imports.js';
|
|
7
6
|
import { generateOperationFilePath } from './utils.js';
|
|
@@ -20,6 +19,109 @@ function extractDefinitions(document) {
|
|
|
20
19
|
}
|
|
21
20
|
return definitions;
|
|
22
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Check if a document actually needs type imports from the schema.
|
|
24
|
+
* Only returns true if the document uses:
|
|
25
|
+
* - Enums
|
|
26
|
+
* - Custom scalars that aren't mapped to primitives
|
|
27
|
+
* - Input types (in variables)
|
|
28
|
+
*
|
|
29
|
+
* Does NOT return true for just referencing object types.
|
|
30
|
+
*/
|
|
31
|
+
function needsSchemaTypesImport(document, schema, config) {
|
|
32
|
+
const builtInScalars = ['String', 'Int', 'Float', 'Boolean', 'ID'];
|
|
33
|
+
const primitiveTypes = ['any', 'string', 'number', 'boolean', 'null', 'undefined', 'void', 'never', 'unknown'];
|
|
34
|
+
let needsImport = false;
|
|
35
|
+
// Get scalar mappings from config
|
|
36
|
+
const scalarMappings = config.scalars || {};
|
|
37
|
+
// Collect all type names referenced in the document
|
|
38
|
+
const referencedTypeNames = new Set();
|
|
39
|
+
visit(document, {
|
|
40
|
+
// Check variable types for input types or custom scalars
|
|
41
|
+
VariableDefinition: (node) => {
|
|
42
|
+
const typeName = getBaseTypeName(node.type);
|
|
43
|
+
referencedTypeNames.add(typeName);
|
|
44
|
+
},
|
|
45
|
+
// Collect fragment type conditions
|
|
46
|
+
FragmentDefinition: (node) => {
|
|
47
|
+
referencedTypeNames.add(node.typeCondition.name.value);
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
// Helper to recursively check if a type needs importing
|
|
51
|
+
const checkType = (type) => {
|
|
52
|
+
if (!type)
|
|
53
|
+
return false;
|
|
54
|
+
// Unwrap lists and non-null
|
|
55
|
+
while ('ofType' in type && type.ofType) {
|
|
56
|
+
type = type.ofType;
|
|
57
|
+
}
|
|
58
|
+
// Enums always need to be imported
|
|
59
|
+
if (isEnumType(type)) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
// Custom scalars need to be imported UNLESS mapped to primitives
|
|
63
|
+
if (isScalarType(type) && !builtInScalars.includes(type.name)) {
|
|
64
|
+
// Check if this scalar is mapped to a primitive type
|
|
65
|
+
const mapping = scalarMappings[type.name];
|
|
66
|
+
if (mapping) {
|
|
67
|
+
// If mapped to a primitive type string, no import needed
|
|
68
|
+
if (typeof mapping === 'string' && primitiveTypes.includes(mapping)) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
// If mapped to an object like { input: 'any', output: 'any' }, check both
|
|
72
|
+
if (typeof mapping === 'object') {
|
|
73
|
+
const inputMapping = mapping.input || mapping.output;
|
|
74
|
+
const outputMapping = mapping.output || mapping.input;
|
|
75
|
+
if (primitiveTypes.includes(inputMapping) && primitiveTypes.includes(outputMapping)) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
// No mapping specified, defaults to 'any', so no import needed
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
// Scalar is mapped to something non-primitive, needs import
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
// Input types need to be imported
|
|
88
|
+
if (isInputObjectType(type)) {
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
return false;
|
|
92
|
+
};
|
|
93
|
+
// Check variable types
|
|
94
|
+
for (const typeName of referencedTypeNames) {
|
|
95
|
+
const type = schema.getType(typeName);
|
|
96
|
+
if (checkType(type)) {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Now we need to check all fields in the document to see if any return enums/custom scalars
|
|
101
|
+
// We'll do a more thorough traversal with TypeInfo
|
|
102
|
+
const typeInfo = new TypeInfo(schema);
|
|
103
|
+
visit(document, visitWithTypeInfo(typeInfo, {
|
|
104
|
+
Field: () => {
|
|
105
|
+
const fieldType = typeInfo.getType();
|
|
106
|
+
if (checkType(fieldType)) {
|
|
107
|
+
needsImport = true;
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
}));
|
|
111
|
+
return needsImport;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Extract the base type name from a type node
|
|
115
|
+
*/
|
|
116
|
+
function getBaseTypeName(type) {
|
|
117
|
+
if (type.kind === 'NamedType') {
|
|
118
|
+
return type.name.value;
|
|
119
|
+
}
|
|
120
|
+
if (type.kind === 'ListType' || type.kind === 'NonNullType') {
|
|
121
|
+
return getBaseTypeName(type.type);
|
|
122
|
+
}
|
|
123
|
+
return '';
|
|
124
|
+
}
|
|
23
125
|
export const preset = {
|
|
24
126
|
buildGeneratesSection: options => {
|
|
25
127
|
var _a, _b;
|
|
@@ -80,7 +182,7 @@ export const preset = {
|
|
|
80
182
|
...source.externalFragments.map(fragment => fragment.node),
|
|
81
183
|
],
|
|
82
184
|
};
|
|
83
|
-
const needsTypesImport =
|
|
185
|
+
const needsTypesImport = needsSchemaTypesImport(singleDefDocumentWithFragments, schemaObject, options.config);
|
|
84
186
|
// Generate the types import statement if needed
|
|
85
187
|
const importStatements = [];
|
|
86
188
|
if (needsTypesImport && !options.config.globalNamespace) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nmarks/graphql-codegen-per-operation-file-preset",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "GraphQL Code Generator preset for generating one file per operation/fragment",
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
|