@@ -3,13 +3,17 @@ import fs from 'fs-extra';
33import  *  as  toolbox  from  'gluegun' ; 
44import  *  as  graphql  from  'graphql/language' ; 
55import  immutable  from  'immutable' ; 
6+ import  {  create  }  from  'ipfs-http-client' ; 
7+ import  yaml  from  'js-yaml' ; 
68import  prettier  from  'prettier' ; 
79// @ts -expect-error TODO: type out if necessary 
810import  uncrashable  from  '@float-capital/float-subgraph-uncrashable/src/Index.bs.js' ; 
911import  DataSourceTemplateCodeGenerator  from  './codegen/template' ; 
1012import  {  GENERATED_FILE_NOTE ,  ModuleImports  }  from  './codegen/typescript' ; 
13+ import  {  appendApiVersionForGraph  }  from  './command-helpers/compiler' ; 
1114import  {  displayPath  }  from  './command-helpers/fs' ; 
1215import  {  Spinner ,  step ,  withSpinner  }  from  './command-helpers/spinner' ; 
16+ import  {  GRAPH_CLI_SHARED_HEADERS  }  from  './constants' ; 
1317import  debug  from  './debug' ; 
1418import  {  applyMigrations  }  from  './migrations' ; 
1519import  Protocol  from  './protocols' ; 
@@ -28,6 +32,8 @@ export interface TypeGeneratorOptions {
2832  skipMigrations ?: boolean ; 
2933  uncrashable : boolean ; 
3034  uncrashableConfig : string ; 
35+   subgraphSources : string [ ] ; 
36+   ipfsUrl : string ; 
3137} 
3238
3339export  default  class  TypeGenerator  { 
@@ -65,6 +71,11 @@ export default class TypeGenerator {
6571      return ; 
6672    } 
6773
74+     if  ( this . options . subgraphSources . length  >  0 )  { 
75+       typeGenDebug . extend ( 'generateTypes' ) ( 'Subgraph uses subgraph datasources.' ) ; 
76+       toolbox . print . success ( 'Subgraph uses subgraph datasources.' ) ; 
77+     } 
78+ 
6879    try  { 
6980      if  ( ! this . options . skipMigrations  &&  this . options . subgraphManifest )  { 
7081        await  applyMigrations ( { 
@@ -93,6 +104,30 @@ export default class TypeGenerator {
93104      typeGenDebug . extend ( 'generateTypes' ) ( 'Generating types for schema' ) ; 
94105      await  this . generateTypesForSchema ( schema ) ; 
95106
107+       if  ( this . options . subgraphSources . length  >  0 )  { 
108+         const  ipfsClient  =  create ( { 
109+           url : appendApiVersionForGraph ( this . options . ipfsUrl . toString ( ) ) , 
110+           headers : { 
111+             ...GRAPH_CLI_SHARED_HEADERS , 
112+           } , 
113+         } ) ; 
114+ 
115+         await  Promise . all ( 
116+           this . options . subgraphSources . map ( async  manifest  =>  { 
117+             const  subgraphSchemaFile  =  await  this . loadSubgraphSchemaFromIPFS ( ipfsClient ,  manifest ) ; 
118+ 
119+             const  subgraphSchema  =  await  Schema . loadFromString ( 
120+               `js${ manifest }  , 
121+               subgraphSchemaFile , 
122+             ) ; 
123+             typeGenDebug . extend ( 'generateTypes' ) ( 
124+               `Generating types for subgraph datasource ${ manifest }  , 
125+             ) ; 
126+             await  this . generateTypesForSchema ( subgraphSchema ,  `subgraph-${ manifest }  ) ; 
127+           } ) , 
128+         ) ; 
129+       } 
130+ 
96131      toolbox . print . success ( '\nTypes generated successfully\n' ) ; 
97132
98133      if  ( this . options . uncrashable  &&  this . options . uncrashableConfig )  { 
@@ -105,6 +140,37 @@ export default class TypeGenerator {
105140    } 
106141  } 
107142
143+   async  loadSubgraphSchemaFromIPFS ( ipfsClient : any ,  manifest : string )  { 
144+     typeGenDebug . extend ( 'loadSubgraphSchemaFromIPFS' ) ( `Loading schema from IPFS ${ manifest }  ) ; 
145+     try  { 
146+       const  manifestBuffer  =  ipfsClient . cat ( manifest ) ; 
147+       let  manifestFile  =  '' ; 
148+       for  await  ( const  chunk  of  manifestBuffer )  { 
149+         manifestFile  +=  Buffer . from ( chunk ) . toString ( 'utf8' ) ;  // Explicitly convert each chunk to UTF-8 
150+       } 
151+ 
152+       const  manifestYaml : any  =  yaml . safeLoad ( manifestFile ) ; 
153+       let  schema  =  manifestYaml . schema . file [ '/' ] ; 
154+ 
155+       if  ( schema . startsWith ( '/ipfs/' ) )  { 
156+         schema  =  schema . slice ( 6 ) ; 
157+       } 
158+ 
159+       const  schemaBuffer  =  ipfsClient . cat ( schema ) ; 
160+       let  schemaFile  =  '' ; 
161+       for  await  ( const  chunk  of  schemaBuffer )  { 
162+         schemaFile  +=  Buffer . from ( chunk ) . toString ( 'utf8' ) ;  // Explicitly convert each chunk to UTF-8 
163+       } 
164+       return  schemaFile ; 
165+     }  catch  ( e )  { 
166+       typeGenDebug . extend ( 'loadSubgraphSchemaFromIPFS' ) ( 
167+         `Failed to load schema from IPFS ${ manifest }  , 
168+       ) ; 
169+       typeGenDebug . extend ( 'loadSubgraphSchemaFromIPFS' ) ( e ) ; 
170+       throw  Error ( `Failed to load schema from IPFS ${ manifest }  ) ; 
171+     } 
172+   } 
173+ 
108174  async  generateUncrashableEntities ( graphSchema : any )  { 
109175    const  ast  =  graphql . parse ( graphSchema . document ) ; 
110176    const  entityDefinitions  =  ast [ 'definitions' ] ; 
@@ -160,7 +226,11 @@ export default class TypeGenerator {
160226    ) ; 
161227  } 
162228
163-   async  generateTypesForSchema ( schema : any )  { 
229+   async  generateTypesForSchema ( 
230+     schema : any , 
231+     fileName  =  'schema.ts' ,  // Default file name 
232+     outputDir : string  =  this . options . outputDir ,  // Default output directory 
233+   )  { 
164234    return  await  withSpinner ( 
165235      `Generate types for GraphQL schema` , 
166236      `Failed to generate types for GraphQL schema` , 
@@ -180,7 +250,7 @@ export default class TypeGenerator {
180250          } , 
181251        ) ; 
182252
183-         const  outputFile  =  path . join ( this . options . outputDir ,  'schema.ts' ) ; 
253+         const  outputFile  =  path . join ( outputDir ,  fileName ) ;   // Use provided outputDir and fileName 
184254        step ( spinner ,  'Write types to' ,  displayPath ( outputFile ) ) ; 
185255        await  fs . mkdirs ( path . dirname ( outputFile ) ) ; 
186256        await  fs . writeFile ( outputFile ,  code ) ; 
0 commit comments