@@ -14,7 +14,7 @@ import {
1414 normalizeOutputParam ,
1515 Types ,
1616} from '@graphql-codegen/plugin-helpers' ;
17- import { NoTypeDefinitionsFound } from '@graphql-tools/load' ;
17+ import { NoTypeDefinitionsFound , type UnnormalizedTypeDefPointer } from '@graphql-tools/load' ;
1818import { mergeTypeDefs } from '@graphql-tools/merge' ;
1919import { CodegenContext , ensureContext } from './config.js' ;
2020import { getDocumentTransform } from './documentTransforms.js' ;
@@ -86,6 +86,7 @@ export async function executeCodegen(
8686 let rootConfig : { [ key : string ] : any } = { } ;
8787 let rootSchemas : Types . Schema [ ] ;
8888 let rootDocuments : Types . OperationDocument [ ] ;
89+ let rootExternalDocuments : Types . OperationDocument [ ] ;
8990 const generates : { [ filename : string ] : Types . ConfiguredOutput } = { } ;
9091
9192 const cache = createCache ( ) ;
@@ -136,6 +137,11 @@ export async function executeCodegen(
136137 /* Normalize root "documents" field */
137138 rootDocuments = normalizeInstanceOrArray < Types . OperationDocument > ( config . documents ) ;
138139
140+ /* Normalize root "externalDocuments" field */
141+ rootExternalDocuments = normalizeInstanceOrArray < Types . OperationDocument > (
142+ config . externalDocuments ,
143+ ) ;
144+
139145 /* Normalize "generators" field */
140146 const generateKeys = Object . keys ( config . generates || { } ) ;
141147
@@ -228,13 +234,15 @@ export async function executeCodegen(
228234 let outputSchemaAst : GraphQLSchema ;
229235 let outputSchema : DocumentNode ;
230236 const outputFileTemplateConfig = outputConfig . config || { } ;
231- let outputDocuments : Types . DocumentFile [ ] = [ ] ;
237+ const outputDocuments : Types . DocumentFile [ ] = [ ] ;
232238 const outputSpecificSchemas = normalizeInstanceOrArray < Types . Schema > (
233239 outputConfig . schema ,
234240 ) ;
235241 let outputSpecificDocuments = normalizeInstanceOrArray < Types . OperationDocument > (
236242 outputConfig . documents ,
237243 ) ;
244+ let outputSpecificExternalDocuments =
245+ normalizeInstanceOrArray < Types . OperationDocument > ( outputConfig . externalDocuments ) ;
238246
239247 const preset : Types . OutputPreset | null = hasPreset
240248 ? typeof outputConfig . preset === 'string'
@@ -247,6 +255,10 @@ export async function executeCodegen(
247255 filename ,
248256 outputSpecificDocuments ,
249257 ) ;
258+ outputSpecificExternalDocuments = await preset . prepareDocuments (
259+ filename ,
260+ outputSpecificExternalDocuments ,
261+ ) ;
250262 }
251263
252264 return subTask . newListr (
@@ -308,41 +320,102 @@ export async function executeCodegen(
308320 task : wrapTask (
309321 async ( ) => {
310322 debugLog ( `[CLI] Loading Documents` ) ;
311- const documentPointerMap : any = { } ;
323+
324+ const populateDocumentPointerMap = (
325+ allDocumentsDenormalizedPointers : Types . OperationDocument [ ] ,
326+ ) : UnnormalizedTypeDefPointer => {
327+ const pointer : UnnormalizedTypeDefPointer = { } ;
328+ for ( const denormalizedPtr of allDocumentsDenormalizedPointers ) {
329+ if ( typeof denormalizedPtr === 'string' ) {
330+ pointer [ denormalizedPtr ] = { } ;
331+ } else if ( typeof denormalizedPtr === 'object' ) {
332+ Object . assign ( pointer , denormalizedPtr ) ;
333+ }
334+ }
335+ return pointer ;
336+ } ;
337+
312338 const allDocumentsDenormalizedPointers = [
313339 ...rootDocuments ,
314340 ...outputSpecificDocuments ,
315341 ] ;
316- for ( const denormalizedPtr of allDocumentsDenormalizedPointers ) {
317- if ( typeof denormalizedPtr === 'string' ) {
318- documentPointerMap [ denormalizedPtr ] = { } ;
319- } else if ( typeof denormalizedPtr === 'object' ) {
320- Object . assign ( documentPointerMap , denormalizedPtr ) ;
321- }
322- }
342+ const documentPointerMap = populateDocumentPointerMap (
343+ allDocumentsDenormalizedPointers ,
344+ ) ;
323345
324346 const hash = JSON . stringify ( documentPointerMap ) ;
325- const result = await cache ( 'documents' , hash , async ( ) => {
326- try {
327- const documents = await context . loadDocuments ( documentPointerMap ) ;
328- return {
329- documents,
330- } ;
331- } catch ( error : any ) {
332- if (
333- error instanceof NoTypeDefinitionsFound &&
334- config . ignoreNoDocuments
335- ) {
336- return {
337- documents : [ ] ,
338- } ;
347+ const outputDocumentsStandard = await cache (
348+ 'documents' ,
349+ hash ,
350+ async ( ) : Promise < Types . DocumentFile [ ] > => {
351+ try {
352+ const documents = await context . loadDocuments (
353+ documentPointerMap ,
354+ 'standard' ,
355+ ) ;
356+ return documents ;
357+ } catch ( error ) {
358+ if (
359+ error instanceof NoTypeDefinitionsFound &&
360+ config . ignoreNoDocuments
361+ ) {
362+ return [ ] ;
363+ }
364+ throw error ;
365+ }
366+ } ,
367+ ) ;
368+
369+ const allExternalDocumentsDenormalizedPointers = [
370+ ...rootExternalDocuments ,
371+ ...outputSpecificExternalDocuments ,
372+ ] ;
373+
374+ const externalDocumentsPointerMap = populateDocumentPointerMap (
375+ allExternalDocumentsDenormalizedPointers ,
376+ ) ;
377+
378+ const externalDocumentHash = JSON . stringify ( externalDocumentsPointerMap ) ;
379+ const outputExternalDocuments = await cache (
380+ 'documents' ,
381+ externalDocumentHash ,
382+ async ( ) : Promise < Types . DocumentFile [ ] > => {
383+ try {
384+ const documents = await context . loadDocuments (
385+ externalDocumentsPointerMap ,
386+ 'external' ,
387+ ) ;
388+ return documents ;
389+ } catch ( error ) {
390+ if (
391+ error instanceof NoTypeDefinitionsFound &&
392+ config . ignoreNoDocuments
393+ ) {
394+ return [ ] ;
395+ }
396+ throw error ;
339397 }
398+ } ,
399+ ) ;
340400
341- throw error ;
401+ /**
402+ * Merging `standard` and `external` documents here,
403+ * so they can be processed the same way,
404+ * before passed into presets and plugins
405+ */
406+ const processedFile : Record < string , true > = { } ;
407+ const mergedDocuments = [
408+ ...outputDocumentsStandard ,
409+ ...outputExternalDocuments ,
410+ ] ;
411+ for ( const file of mergedDocuments ) {
412+ if ( processedFile [ file . hash ] ) {
413+ continue ;
342414 }
343- } ) ;
344415
345- outputDocuments = result . documents ;
416+ outputDocuments . push ( file ) ;
417+ processedFile [ file . hash ] = true ;
418+ }
346419 } ,
347420 filename ,
348421 `Load GraphQL documents: ${ filename } ` ,
@@ -437,7 +510,7 @@ export async function executeCodegen(
437510 pluginContext,
438511 profiler : context . profiler ,
439512 documentTransforms,
440- } ,
513+ } satisfies Types . GenerateOptions ,
441514 ] ;
442515
443516 const process = async ( outputArgs : Types . GenerateOptions ) => {
0 commit comments