@nmarks/graphql-codegen-per-operation-file-preset 1.0.4 → 1.0.6

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 CHANGED
@@ -38,14 +38,19 @@ function needsSchemaTypesImport(document, schema, config) {
38
38
  let needsImport = false;
39
39
  // Get scalar mappings from config
40
40
  const scalarMappings = config.scalars || {};
41
- // Check if document has any variables - if so, we need Types import for Types.Exact, Types.Scalars, etc.
42
- let hasVariables = false;
41
+ // Check if document has an operation definition
42
+ // ALL operations (query/mutation/subscription) generate a Variables type that uses Types.Exact
43
+ // even if they have no variables: Types.Exact<{ [key: string]: never; }>
44
+ let hasOperation = false;
43
45
  // Collect all type names referenced in the document
44
46
  const referencedTypeNames = new Set();
45
47
  (0, graphql_1.visit)(document, {
48
+ // Operations always need Types import for their Variables type
49
+ OperationDefinition: () => {
50
+ hasOperation = true;
51
+ },
46
52
  // Check variable types for input types or custom scalars
47
53
  VariableDefinition: (node) => {
48
- hasVariables = true; // Any variable means we need Types import
49
54
  const typeName = getBaseTypeName(node.type);
50
55
  referencedTypeNames.add(typeName);
51
56
  },
@@ -54,8 +59,8 @@ function needsSchemaTypesImport(document, schema, config) {
54
59
  referencedTypeNames.add(node.typeCondition.name.value);
55
60
  },
56
61
  });
57
- // If operation has variables, it will use Types.Exact, Types.Scalars, Types.InputMaybe, etc.
58
- if (hasVariables) {
62
+ // All operations generate Variables type that uses Types.Exact
63
+ if (hasOperation) {
59
64
  return true;
60
65
  }
61
66
  // Helper to recursively check if a type needs importing
@@ -180,17 +185,65 @@ exports.preset = {
180
185
  document: singleDefDocument,
181
186
  location: source.documents[0].location,
182
187
  };
188
+ // Find other fragments in the same source file (they are "local" now but will be "external" after split)
189
+ const localFragments = definitions
190
+ .filter(d => d.definition.kind === graphql_1.Kind.FRAGMENT_DEFINITION && d.name !== name)
191
+ .map(d => d.definition);
192
+ // Add local fragments to external fragments list so they're available during generation
193
+ const localFragmentNodes = localFragments.map(frag => ({
194
+ level: 0,
195
+ isExternal: true,
196
+ name: frag.name.value,
197
+ onType: frag.typeCondition.name.value,
198
+ node: frag,
199
+ }));
200
+ const allExternalFragments = [
201
+ ...source.externalFragments,
202
+ ...localFragmentNodes,
203
+ ];
183
204
  // Update fragment imports to use the correct output path for this operation
184
205
  const updatedFragmentImports = source.fragmentImports.map(fragmentImport => ({
185
206
  ...fragmentImport,
186
207
  outputPath: filename, // Update to actual output path
187
208
  }));
209
+ // Generate fragment imports for local fragments (they'll be in separate files after splitting)
210
+ const localFragmentImports = localFragments.map((frag) => {
211
+ var _a;
212
+ const fragmentFilePath = (0, utils_js_1.generateOperationFilePath)(source.documents[0].location, frag.name.value, folder, extension);
213
+ // Get fragment import identifiers (document + type)
214
+ const identifiers = [
215
+ {
216
+ name: `${frag.name.value}FragmentDoc`,
217
+ kind: 'document',
218
+ },
219
+ {
220
+ name: `${frag.name.value}Fragment`,
221
+ kind: 'type',
222
+ },
223
+ ];
224
+ return {
225
+ baseDir,
226
+ baseOutputDir: options.baseOutputDir,
227
+ outputPath: filename,
228
+ importSource: {
229
+ path: fragmentFilePath,
230
+ identifiers,
231
+ },
232
+ emitLegacyCommonJSImports: options.config.emitLegacyCommonJSImports,
233
+ importExtension: options.config.importExtension,
234
+ typesImport: (_a = options.config.useTypeImports) !== null && _a !== void 0 ? _a : false,
235
+ };
236
+ });
237
+ const allFragmentImports = [
238
+ ...updatedFragmentImports,
239
+ ...localFragmentImports,
240
+ ];
188
241
  // Check if THIS specific operation uses types (not the whole source file)
189
242
  const singleDefDocumentWithFragments = {
190
243
  ...singleDefDocument,
191
244
  definitions: [
192
245
  ...singleDefDocument.definitions,
193
- ...source.externalFragments.map(fragment => fragment.node),
246
+ ...allExternalFragments.map(fragment => fragment.node),
194
247
  ],
195
248
  };
196
249
  const needsTypesImport = needsSchemaTypesImport(singleDefDocumentWithFragments, schemaObject, options.config);
@@ -221,8 +274,8 @@ exports.preset = {
221
274
  ...options.config,
222
275
  exportFragmentSpreadSubTypes: true,
223
276
  namespacedImportName: importTypesNamespace,
224
- externalFragments: source.externalFragments,
225
- fragmentImports: updatedFragmentImports,
277
+ externalFragments: allExternalFragments,
278
+ fragmentImports: allFragmentImports,
226
279
  };
227
280
  artifacts.push({
228
281
  ...options,
package/esm/index.js CHANGED
@@ -34,14 +34,19 @@ function needsSchemaTypesImport(document, schema, config) {
34
34
  let needsImport = false;
35
35
  // Get scalar mappings from config
36
36
  const scalarMappings = config.scalars || {};
37
- // Check if document has any variables - if so, we need Types import for Types.Exact, Types.Scalars, etc.
38
- let hasVariables = false;
37
+ // Check if document has an operation definition
38
+ // ALL operations (query/mutation/subscription) generate a Variables type that uses Types.Exact
39
+ // even if they have no variables: Types.Exact<{ [key: string]: never; }>
40
+ let hasOperation = false;
39
41
  // Collect all type names referenced in the document
40
42
  const referencedTypeNames = new Set();
41
43
  visit(document, {
44
+ // Operations always need Types import for their Variables type
45
+ OperationDefinition: () => {
46
+ hasOperation = true;
47
+ },
42
48
  // Check variable types for input types or custom scalars
43
49
  VariableDefinition: (node) => {
44
- hasVariables = true; // Any variable means we need Types import
45
50
  const typeName = getBaseTypeName(node.type);
46
51
  referencedTypeNames.add(typeName);
47
52
  },
@@ -50,8 +55,8 @@ function needsSchemaTypesImport(document, schema, config) {
50
55
  referencedTypeNames.add(node.typeCondition.name.value);
51
56
  },
52
57
  });
53
- // If operation has variables, it will use Types.Exact, Types.Scalars, Types.InputMaybe, etc.
54
- if (hasVariables) {
58
+ // All operations generate Variables type that uses Types.Exact
59
+ if (hasOperation) {
55
60
  return true;
56
61
  }
57
62
  // Helper to recursively check if a type needs importing
@@ -176,17 +181,65 @@ export const preset = {
176
181
  document: singleDefDocument,
177
182
  location: source.documents[0].location,
178
183
  };
184
+ // Find other fragments in the same source file (they are "local" now but will be "external" after split)
185
+ const localFragments = definitions
186
+ .filter(d => d.definition.kind === Kind.FRAGMENT_DEFINITION && d.name !== name)
187
+ .map(d => d.definition);
188
+ // Add local fragments to external fragments list so they're available during generation
189
+ const localFragmentNodes = localFragments.map(frag => ({
190
+ level: 0,
191
+ isExternal: true,
192
+ name: frag.name.value,
193
+ onType: frag.typeCondition.name.value,
194
+ node: frag,
195
+ }));
196
+ const allExternalFragments = [
197
+ ...source.externalFragments,
198
+ ...localFragmentNodes,
199
+ ];
179
200
  // Update fragment imports to use the correct output path for this operation
180
201
  const updatedFragmentImports = source.fragmentImports.map(fragmentImport => ({
181
202
  ...fragmentImport,
182
203
  outputPath: filename, // Update to actual output path
183
204
  }));
205
+ // Generate fragment imports for local fragments (they'll be in separate files after splitting)
206
+ const localFragmentImports = localFragments.map((frag) => {
207
+ var _a;
208
+ const fragmentFilePath = generateOperationFilePath(source.documents[0].location, frag.name.value, folder, extension);
209
+ // Get fragment import identifiers (document + type)
210
+ const identifiers = [
211
+ {
212
+ name: `${frag.name.value}FragmentDoc`,
213
+ kind: 'document',
214
+ },
215
+ {
216
+ name: `${frag.name.value}Fragment`,
217
+ kind: 'type',
218
+ },
219
+ ];
220
+ return {
221
+ baseDir,
222
+ baseOutputDir: options.baseOutputDir,
223
+ outputPath: filename,
224
+ importSource: {
225
+ path: fragmentFilePath,
226
+ identifiers,
227
+ },
228
+ emitLegacyCommonJSImports: options.config.emitLegacyCommonJSImports,
229
+ importExtension: options.config.importExtension,
230
+ typesImport: (_a = options.config.useTypeImports) !== null && _a !== void 0 ? _a : false,
231
+ };
232
+ });
233
+ const allFragmentImports = [
234
+ ...updatedFragmentImports,
235
+ ...localFragmentImports,
236
+ ];
184
237
  // Check if THIS specific operation uses types (not the whole source file)
185
238
  const singleDefDocumentWithFragments = {
186
239
  ...singleDefDocument,
187
240
  definitions: [
188
241
  ...singleDefDocument.definitions,
189
- ...source.externalFragments.map(fragment => fragment.node),
242
+ ...allExternalFragments.map(fragment => fragment.node),
190
243
  ],
191
244
  };
192
245
  const needsTypesImport = needsSchemaTypesImport(singleDefDocumentWithFragments, schemaObject, options.config);
@@ -217,8 +270,8 @@ export const preset = {
217
270
  ...options.config,
218
271
  exportFragmentSpreadSubTypes: true,
219
272
  namespacedImportName: importTypesNamespace,
220
- externalFragments: source.externalFragments,
221
- fragmentImports: updatedFragmentImports,
273
+ externalFragments: allExternalFragments,
274
+ fragmentImports: allFragmentImports,
222
275
  };
223
276
  artifacts.push({
224
277
  ...options,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nmarks/graphql-codegen-per-operation-file-preset",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
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"