1
1
import {
2
2
Condition ,
3
- Directive ,
4
3
Fragment ,
5
4
IRVisitor ,
6
5
LinkedField ,
7
- Metadata ,
8
6
Root ,
9
7
ScalarField ,
10
8
SchemaUtils ,
@@ -32,6 +30,7 @@ const { isAbstractType } = SchemaUtils;
32
30
33
31
const REF_TYPE = " $refType" ;
34
32
const FRAGMENT_REFS = " $fragmentRefs" ;
33
+ const FRAGMENT_REFS_TYPE_NAME = "FragmentRefs" ;
35
34
const MODULE_IMPORT_FIELD = "MODULE_IMPORT_FIELD" ;
36
35
const DIRECTIVE_NAME = "raw_response_type" ;
37
36
@@ -205,9 +204,8 @@ function selectionsToAST(
205
204
props . push (
206
205
readOnlyObjectTypeProperty (
207
206
REF_TYPE ,
208
- ts . createTypeReferenceNode (
209
- ts . createIdentifier ( fragmentTypeName ) ,
210
- undefined
207
+ ts . createLiteralTypeNode (
208
+ ts . createStringLiteral ( `${ fragmentTypeName } $ref` )
211
209
)
212
210
)
213
211
) ;
@@ -303,16 +301,6 @@ function exportType(name: string, type: ts.TypeNode) {
303
301
) ;
304
302
}
305
303
306
- function exportTypes ( types : string [ ] ) {
307
- return ts . createExportDeclaration (
308
- undefined ,
309
- undefined ,
310
- ts . createNamedExports (
311
- types . map ( type => ts . createExportSpecifier ( undefined , type ) )
312
- )
313
- ) ;
314
- }
315
-
316
304
function importTypes ( names : string [ ] , fromModule : string ) : ts . Statement {
317
305
return ts . createImportDeclaration (
318
306
undefined ,
@@ -381,14 +369,8 @@ function createVisitor(options: TypeGeneratorOptions): IRVisitor.NodeVisitor {
381
369
createRawResponseTypeVisitor ( state )
382
370
) ;
383
371
}
384
- const refetchableFragmentName = getRefetchableQueryParentFragmentName (
385
- state ,
386
- node . metadata
387
- ) ;
388
372
const nodes = [
389
- ...( refetchableFragmentName
390
- ? generateFragmentRefsForRefetchable ( refetchableFragmentName )
391
- : getFragmentImports ( state ) ) ,
373
+ ...getFragmentDeclarations ( state ) ,
392
374
...getEnumDefinitions ( state ) ,
393
375
...inputObjectTypes ,
394
376
inputVariablesType ,
@@ -444,30 +426,20 @@ function createVisitor(options: TypeGeneratorOptions): IRVisitor.NodeVisitor {
444
426
return [ selection ] ;
445
427
} ) ;
446
428
state . generatedFragments . add ( node . name ) ;
447
- const fragmentTypes = getFragmentTypes (
448
- node . name ,
449
- getRefetchableQueryPath ( state , node . directives ) ,
450
- state
451
- ) ;
452
429
const unmasked = node . metadata != null && node . metadata . mask === false ;
453
430
const baseType = selectionsToAST (
454
431
selections ,
455
432
state ,
456
433
unmasked ,
457
- unmasked ? undefined : getOldFragmentTypeName ( node . name )
434
+ unmasked ? undefined : node . name
458
435
) ;
459
436
const type = isPlural ( node )
460
437
? ts . createTypeReferenceNode ( ts . createIdentifier ( "ReadonlyArray" ) , [
461
438
baseType
462
439
] )
463
440
: baseType ;
464
441
465
- return [
466
- ...getFragmentImports ( state ) ,
467
- ...getEnumDefinitions ( state ) ,
468
- ...fragmentTypes ,
469
- exportType ( node . name , type )
470
- ] ;
442
+ return [ ...getEnumDefinitions ( state ) , exportType ( node . name , type ) ] ;
471
443
} ,
472
444
InlineFragment ( node ) {
473
445
const typeCondition = node . typeCondition ;
@@ -831,61 +803,6 @@ function generateInputVariablesType(node: Root, state: State) {
831
803
) ;
832
804
}
833
805
834
- // If it's a @refetchable fragment, we generate the $fragmentRef in generated
835
- // query, and import it in the fragment to avoid circular dependencies
836
- function getRefetchableQueryParentFragmentName (
837
- state : State ,
838
- metadata : Metadata
839
- ) : string | null {
840
- if (
841
- ! ( metadata && metadata . isRefetchableQuery ) ||
842
- ( ! state . useHaste && ! state . useSingleArtifactDirectory )
843
- ) {
844
- return null ;
845
- }
846
- const derivedFrom = metadata && metadata . derivedFrom ;
847
- if ( derivedFrom != null && typeof derivedFrom === "string" ) {
848
- return derivedFrom ;
849
- }
850
- return null ;
851
- }
852
-
853
- function getRefetchableQueryPath (
854
- state : State ,
855
- directives : ReadonlyArray < Directive >
856
- ) : string | undefined {
857
- let refetchableQuery : string | undefined ;
858
- if ( ! state . useHaste && ! state . useSingleArtifactDirectory ) {
859
- return ;
860
- }
861
- const directive = directives . find ( d => d . name === "refetchable" ) ;
862
- const refetchableArgs = directive && directive . args ;
863
- if ( ! refetchableArgs ) {
864
- return ;
865
- }
866
- const argument = refetchableArgs . find (
867
- arg => arg . kind === "Argument" && arg . name === "queryName"
868
- ) ;
869
- if (
870
- argument &&
871
- argument . value &&
872
- argument . value . kind === "Literal" &&
873
- typeof argument . value . value === "string"
874
- ) {
875
- refetchableQuery = argument . value . value ;
876
- if ( ! state . useHaste ) {
877
- refetchableQuery = "./" + refetchableQuery ;
878
- }
879
- refetchableQuery += ".graphql" ;
880
- }
881
- return refetchableQuery ;
882
- }
883
-
884
- function generateFragmentRefsForRefetchable ( name : string ) {
885
- const oldFragmentTypeName = getOldFragmentTypeName ( name ) ;
886
- return declareExportOpaqueType ( oldFragmentTypeName ) ;
887
- }
888
-
889
806
function groupRefs ( props : Selection [ ] ) : Selection [ ] {
890
807
const result : Selection [ ] = [ ] ;
891
808
const refs : string [ ] = [ ] ;
@@ -897,53 +814,23 @@ function groupRefs(props: Selection[]): Selection[] {
897
814
}
898
815
} ) ;
899
816
if ( refs . length > 0 ) {
900
- const value = ts . createIntersectionTypeNode (
901
- refs . map ( ref =>
902
- ts . createTypeReferenceNode (
903
- ts . createIdentifier ( getOldFragmentTypeName ( ref ) ) ,
904
- undefined
905
- )
906
- )
817
+ const refTypes = ts . createUnionTypeNode (
818
+ refs . map ( ref => ts . createLiteralTypeNode ( ts . createStringLiteral ( ref ) ) )
907
819
) ;
908
820
result . push ( {
909
821
key : FRAGMENT_REFS ,
910
822
conditional : false ,
911
- value
823
+ value : ts . createTypeReferenceNode ( FRAGMENT_REFS_TYPE_NAME , [ refTypes ] )
912
824
} ) ;
913
825
}
914
826
return result ;
915
827
}
916
828
917
- function createAnyTypeAlias ( name : string ) : ts . TypeAliasDeclaration {
918
- return ts . createTypeAliasDeclaration (
919
- undefined ,
920
- undefined ,
921
- ts . createIdentifier ( name ) ,
922
- undefined ,
923
- ts . createKeywordTypeNode ( ts . SyntaxKind . AnyKeyword )
924
- ) ;
925
- }
926
-
927
- function getFragmentImports ( state : State ) {
928
- const imports : ts . Statement [ ] = [ ] ;
829
+ function getFragmentDeclarations ( state : State ) : ts . Statement [ ] {
929
830
if ( state . usedFragments . size > 0 ) {
930
- const usedFragments = Array . from ( state . usedFragments ) . sort ( ) ;
931
- for ( const usedFragment of usedFragments ) {
932
- const fragmentTypeName = getOldFragmentTypeName ( usedFragment ) ;
933
- if (
934
- ! state . generatedFragments . has ( usedFragment ) &&
935
- state . useSingleArtifactDirectory &&
936
- state . existingFragmentNames . has ( usedFragment )
937
- ) {
938
- imports . push (
939
- importTypes ( [ fragmentTypeName ] , `./${ usedFragment } .graphql` )
940
- ) ;
941
- } else {
942
- imports . push ( createAnyTypeAlias ( fragmentTypeName ) ) ;
943
- }
944
- }
831
+ return [ fragmentRefsType ] ;
945
832
}
946
- return imports ;
833
+ return [ ] ;
947
834
}
948
835
949
836
function getEnumDefinitions ( {
@@ -982,62 +869,32 @@ function stringLiteralTypeAnnotation(name: string): ts.TypeNode {
982
869
return ts . createLiteralTypeNode ( ts . createLiteral ( name ) ) ;
983
870
}
984
871
985
- function getFragmentTypes (
986
- name : string ,
987
- refetchableQueryPath : undefined | string ,
988
- state : State
989
- ) {
990
- const oldFragmentTypeName = getOldFragmentTypeName ( name ) ;
991
-
992
- if ( ! state . useSingleArtifactDirectory && ! state . useHaste ) {
993
- return [
994
- exportType (
995
- oldFragmentTypeName ,
996
- ts . createKeywordTypeNode ( ts . SyntaxKind . AnyKeyword )
997
- )
998
- ] ;
999
- }
1000
-
1001
- if ( refetchableQueryPath ) {
1002
- return [
1003
- importTypes ( [ oldFragmentTypeName ] , refetchableQueryPath ) ,
1004
- exportTypes ( [ oldFragmentTypeName ] )
1005
- ] ;
1006
- }
1007
-
1008
- return declareExportOpaqueType ( oldFragmentTypeName ) ;
1009
- }
1010
-
1011
- function declareExportOpaqueType ( oldFragmentTypeName : string ) {
1012
- const _refTypeName = `_${ oldFragmentTypeName } ` ;
1013
- const _refType = ts . createVariableStatement (
1014
- [ ts . createToken ( ts . SyntaxKind . DeclareKeyword ) ] ,
1015
- ts . createVariableDeclarationList (
1016
- [
1017
- ts . createVariableDeclaration (
1018
- _refTypeName ,
1019
- ts . createTypeOperatorNode (
1020
- ts . SyntaxKind . UniqueKeyword ,
1021
- ts . createKeywordTypeNode ( ts . SyntaxKind . SymbolKeyword )
1022
- )
1023
- )
1024
- ] ,
1025
- ts . NodeFlags . Const
872
+ // type Fragments<Refs extends string> = null | {[ref in Refs]: true}
873
+ const fragmentRefsType = ts . createTypeAliasDeclaration (
874
+ undefined ,
875
+ undefined ,
876
+ FRAGMENT_REFS_TYPE_NAME ,
877
+ [
878
+ ts . createTypeParameterDeclaration (
879
+ "Refs" ,
880
+ ts . createKeywordTypeNode ( ts . SyntaxKind . StringKeyword ) ,
881
+ undefined
1026
882
)
1027
- ) ;
1028
-
1029
- return [
1030
- _refType ,
1031
- exportType (
1032
- oldFragmentTypeName ,
1033
- ts . createTypeQueryNode ( ts . createIdentifier ( _refTypeName ) )
883
+ ] ,
884
+ ts . createUnionTypeNode ( [
885
+ ts . createNull ( ) ,
886
+ ts . createMappedTypeNode (
887
+ undefined ,
888
+ ts . createTypeParameterDeclaration (
889
+ "ref" ,
890
+ ts . createTypeReferenceNode ( "Refs" , undefined ) ,
891
+ undefined
892
+ ) ,
893
+ undefined ,
894
+ ts . createLiteralTypeNode ( ts . createTrue ( ) )
1034
895
)
1035
- ] ;
1036
- }
1037
-
1038
- function getOldFragmentTypeName ( name : string ) {
1039
- return `${ name } $ref` ;
1040
- }
896
+ ] )
897
+ ) ;
1041
898
1042
899
// Should match FLOW_TRANSFORMS array
1043
900
// https://github.com/facebook/relay/blob/v6.0.0/packages/relay-compiler/language/javascript/RelayFlowGenerator.js#L621-L627
0 commit comments