@@ -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 } .graphql` ,
121+ subgraphSchemaFile ,
122+ ) ;
123+ typeGenDebug . extend ( 'generateTypes' ) (
124+ `Generating types for subgraph datasource ${ manifest } ` ,
125+ ) ;
126+ await this . generateTypesForSchema ( subgraphSchema , `subgraph-${ manifest } .ts` ) ;
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