diff --git a/__tests__/ReactRelayQueryRenderer-test.tsx b/__tests__/ReactRelayQueryRenderer-test.tsx index 528bbeb0..a8174da8 100644 --- a/__tests__/ReactRelayQueryRenderer-test.tsx +++ b/__tests__/ReactRelayQueryRenderer-test.tsx @@ -288,7 +288,7 @@ describe('ReactRelayQueryRenderer', () => { id: '4', name: 'Zuck', username: 'Zuck', - __isWithinUnmatchedTypeRefinement: false, + __id: '4', __fragments: { ReactRelayQueryRendererTestFragment: {}, @@ -309,7 +309,7 @@ describe('ReactRelayQueryRenderer', () => { id: '4', name: 'Zuck', username: 'Zuck', - __isWithinUnmatchedTypeRefinement: false, + __id: '4', __fragments: { ReactRelayQueryRendererTestFragment: {}, @@ -356,7 +356,7 @@ describe('ReactRelayQueryRenderer', () => { id: '4', name: 'Zuck', username: undefined, - __isWithinUnmatchedTypeRefinement: false, + __id: '4', __fragments: { ReactRelayQueryRendererTestFragment: {}, @@ -377,7 +377,7 @@ describe('ReactRelayQueryRenderer', () => { id: '4', name: 'Zuck', username: 'Zuck', - __isWithinUnmatchedTypeRefinement: false, + __id: '4', __fragments: { ReactRelayQueryRendererTestFragment: {}, @@ -431,7 +431,7 @@ describe('ReactRelayQueryRenderer', () => { data: { node: { id: '4', - __isWithinUnmatchedTypeRefinement: false, + __fragments: { ReactRelayQueryRendererTestFragment: {}, @@ -479,7 +479,6 @@ describe('ReactRelayQueryRenderer', () => { data: { node: { id: '4', - __isWithinUnmatchedTypeRefinement: false, __fragments: { ReactRelayQueryRendererTestFragment: {}, @@ -532,7 +531,6 @@ describe('ReactRelayQueryRenderer', () => { data: { node: { id: '4', - __isWithinUnmatchedTypeRefinement: false, __fragments: { ReactRelayQueryRendererTestFragment: {}, @@ -576,7 +574,6 @@ describe('ReactRelayQueryRenderer', () => { data: { node: { id: '4', - __isWithinUnmatchedTypeRefinement: false, __fragments: { ReactRelayQueryRendererTestFragment: {}, @@ -706,7 +703,6 @@ describe('ReactRelayQueryRenderer', () => { data: { node: { id: '4', - __isWithinUnmatchedTypeRefinement: false, __fragments: { ReactRelayQueryRendererTestFragment: {}, @@ -732,7 +728,6 @@ describe('ReactRelayQueryRenderer', () => { data: { node: { id: '4', - __isWithinUnmatchedTypeRefinement: false, __fragments: { ReactRelayQueryRendererTestFragment: {}, @@ -800,7 +795,6 @@ describe('ReactRelayQueryRenderer', () => { data: { node: { id: '4', - __isWithinUnmatchedTypeRefinement: false, __fragments: { ReactRelayQueryRendererTestFragment: {}, @@ -826,7 +820,6 @@ describe('ReactRelayQueryRenderer', () => { data: { node: { id: '4', - __isWithinUnmatchedTypeRefinement: false, __fragments: { ReactRelayQueryRendererTestFragment: {}, @@ -879,7 +872,6 @@ describe('ReactRelayQueryRenderer', () => { data: { node: { id: '4', - __isWithinUnmatchedTypeRefinement: false, __fragments: { ReactRelayQueryRendererTestFragment: {}, @@ -939,7 +931,6 @@ describe('ReactRelayQueryRenderer', () => { data: { node: { id: '6', - __isWithinUnmatchedTypeRefinement: false, __fragments: { ReactRelayQueryRendererTestFragment: {}, @@ -1011,7 +1002,6 @@ describe('ReactRelayQueryRenderer', () => { data: { node: { id: '4', - __isWithinUnmatchedTypeRefinement: false, __fragments: { ReactRelayQueryRendererTestFragment: {}, @@ -1048,7 +1038,6 @@ describe('ReactRelayQueryRenderer', () => { data: { node: { id: '4', - __isWithinUnmatchedTypeRefinement: false, __fragments: { ReactRelayQueryRendererTestFragment: {}, @@ -1534,7 +1523,6 @@ describe('ReactRelayQueryRenderer', () => { data: { node: { id: '4', - __isWithinUnmatchedTypeRefinement: false, __fragments: { ReactRelayQueryRendererTestFragment: {}, @@ -1588,7 +1576,6 @@ describe('ReactRelayQueryRenderer', () => { data: { node: { id: '4', - __isWithinUnmatchedTypeRefinement: false, __fragments: { ReactRelayQueryRendererTestFragment: {}, @@ -1605,7 +1592,6 @@ describe('ReactRelayQueryRenderer', () => { data: { node: { id: '4', - __isWithinUnmatchedTypeRefinement: false, __fragments: { ReactRelayQueryRendererTestFragment: {}, @@ -1658,7 +1644,7 @@ describe('ReactRelayQueryRenderer', () => { data: { node: { id: '4', - __isWithinUnmatchedTypeRefinement: false, + __fragments: { ReactRelayQueryRendererTestFragment: {}, }, @@ -2280,7 +2266,6 @@ describe('ReactRelayQueryRenderer', () => { __fragmentOwner: owner.request, __id: '4', - __isWithinUnmatchedTypeRefinement: false, }, }, retry: expect.any(Function), diff --git a/__tests__/testschema.graphql b/__tests__/testschema.graphql new file mode 100644 index 00000000..1431d3c3 --- /dev/null +++ b/__tests__/testschema.graphql @@ -0,0 +1,1202 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. + +schema { + query: Query + mutation: Mutation + subscription: Subscription +} + +directive @customDirective(level: Int!) on FIELD + +directive @fixme_fat_interface on FIELD + +directive @defer( + label: String! + if: Boolean = true +) on FRAGMENT_SPREAD | INLINE_FRAGMENT + +directive @stream( + label: String! + initialCount: Int! + if: Boolean = true + useCustomizedBatch: Boolean = false +) on FIELD + +directive @fetchable(field_name: String!) on OBJECT + +directive @relay_client_component_server(module_id: String!) on FRAGMENT_SPREAD + +directive @fb_actor_change on FIELD + +directive @live_query( + enabled: Boolean = true + polling_interval: Int + config_id: String + partial: Boolean + event_stream: String +) on QUERY + +type Query { + checkinSearchQuery(query: CheckinSearchInput): CheckinSearchResult + defaultSettings: Settings + route(waypoints: [WayPoint!]!): Route + items(filter: ItemFilterInput): ItemFilterResult + maybeNodeInterface: MaybeNodeInterface + maybeNode: MaybeNode + neverNode: NeverNode + named: Named + me: User + node(id: ID): Node + node_id_required(id: ID!): Node + nodes(ids: [ID!]): [Node] + settings(environment: Environment): Settings + story: Story + task(number: Int): Task + username(name: String!): Actor + usernames(names: [String!]!): [Actor] + viewer: Viewer + _mutation: Mutation + fetch__User(id: ID!): User + fetch__NonNodeStory(input_fetch_id: ID!): NonNodeStory + nonNodeStory(id: ID!): NonNodeStory + userOrPage(id: ID!): UserOrPage +} + +union UserOrPage = User | Page + +interface MaybeNodeInterface { + name: String +} + +scalar JSON +scalar NonNodeID + +union MaybeNode = Story | FakeNode | NonNode + +interface AllConcreteTypesImplementNode { + count: Int +} + +type FakeNode { + id: ID! +} + +type NonNode { + id: NonNodeID + name: String +} + +type NonNodeNoID implements MaybeNodeInterface { + name: String +} + +union NeverNode = FakeNode | NonNode + +type Task { + title: String +} + +input WayPoint { + lat: String + lon: String +} + +type Route { + steps: [RouteStep] +} + +type RouteStep { + lat: String + lon: String + note: String +} + +type Mutation { + actorSubscribe(input: ActorSubscribeInput): ActorSubscribeResponsePayload + actorNameChange(input: ActorNameChangeInput): ActorNameChangePayload + applicationRequestDeleteAll( + input: ApplicationRequestDeleteAllInput + ): ApplicationRequestDeleteAllResponsePayload + commentCreate(input: CommentCreateInput): CommentCreateResponsePayload + commentsCreate(input: CommentsCreateInput): CommentsCreateResponsePayload + commentDelete(input: CommentDeleteInput): CommentDeleteResponsePayload + commentsDelete(input: CommentsDeleteInput): CommentsDeleteResponsePayload + feedbackLike(input: FeedbackLikeInput): FeedbackLikeResponsePayload + feedbackLikeStrict( + input: FeedbackLikeInputStrict! + ): FeedbackLikeResponsePayload + feedbackLikeSubscribe(input: FeedbackLikeInput): FeedbackLikeResponsePayload + nodeSavedState(input: NodeSaveStateInput): NodeSavedStateResponsePayload + unfriend(input: UnfriendInput): UnfriendResponsePayload + viewerNotificationsUpdateAllSeenState( + input: UpdateAllSeenStateInput + ): ViewerNotificationsUpdateAllSeenStateResponsePayload + setLocation(input: LocationInput): setLocationResponsePayload + storyUpdate(input: StoryUpdateInput): StoryUpdateResponsePayload +} + +type Subscription { + feedbackLikeSubscribe(input: FeedbackLikeInput): FeedbackLikeResponsePayload + commentCreateSubscribe( + input: CommentCreateSubscriptionInput + ): CommentCreateResponsePayload + configCreateSubscribe: ConfigCreateSubscriptResponsePayload +} + +input ActorSubscribeInput { + subscribeeId: ID +} + +input ActorNameChangeInput { + newName: String +} + +input ApplicationRequestDeleteAllInput { + deletedRequestIds: [ID] +} + +input CommentCreateInput { + feedbackId: ID + feedback: CommentfeedbackFeedback +} + +input CommentsCreateInput { + feedbackId: ID + feedback: [CommentfeedbackFeedback] +} + +input CommentfeedbackFeedback { + comment: FeedbackcommentComment +} + +input FeedbackcommentComment { + feedback: CommentfeedbackFeedback +} + +input CommentCreateSubscriptionInput { + feedbackId: ID + text: String +} + +input CommentDeleteInput { + commentId: ID +} + +input CommentsDeleteInput { + commentIds: [ID] +} + +input FeedbackLikeInput { + feedbackId: ID +} + +input FeedbackLikeInputStrict { + userID: ID! + feedbackId: ID! + description: String +} + +input NodeSaveStateInput { + nodeId: ID +} + +input UpdateAllSeenStateInput { + storyIds: [ID] +} + +input LocationInput { + longitude: Float + latitude: Float +} + +type setLocationResponsePayload { + viewer: Viewer +} + +type ActorSubscribeResponsePayload { + subscribee: Actor +} + +type ActorNameChangePayload { + actor: Actor +} + +type ApplicationRequestDeleteAllResponsePayload { + deletedRequestIds: [ID] +} + +type CheckinSearchResult { + query: String +} + +input CheckinSearchInput { + query: String + inputs: [CheckinSearchInput] +} + +input StoryUpdateInput { + body: InputText +} + +type PlainCommentBody { + text: Text +} + +type MarkdownCommentBody { + text: Text +} + +union CommentBody = PlainCommentBody | MarkdownCommentBody + +type Comment implements Node { + actor: Actor + actors: [Actor] + actorCount: Int + address: StreetAddress + allPhones: [Phone] + author: User + backgroundImage: Image + birthdate: Date + body: Text + canViewerComment: Boolean + canViewerLike: Boolean + commentBody(supported: [String!]!): CommentBody + comments( + after: ID + before: ID + first: Int + last: Int + orderby: String + ): CommentsConnection + doesViewerLike: Boolean + emailAddresses: [String] + feedback: Feedback + firstName(if: Boolean, unless: Boolean): String + friends( + after: ID + before: ID + first: Int + last: Int + orderby: [String] + find: String + isViewerFriend: Boolean + if: Boolean + unless: Boolean + traits: [PersonalityTraits] + ): FriendsConnection + hometown: Page + id: ID! + lastName: String + likers(first: Int): LikersOfContentConnection + likeSentence: Text + message: Text + name: String + profilePicture(size: [Int], preset: PhotoSize): Image + # This is added in TestSchema.js + # + # profilePicture2( + # size: [Int], + # preset: PhotoSize, + # cropPosition: CropPosition, + # fileExtension: FileExtension, + # additionalParameters: JSON + # ): Image + segments(first: Int): Segments + screennames: [Screenname] + subscribeStatus: String + subscribers(first: Int): SubscribersConnection + topLevelComments(first: Int): TopLevelCommentsConnection + commentsFrom(name: String!): [CommentsEdge] + tracking: String + url(relative: Boolean, site: String): String + websites: [String] + username: String + viewerSavedState: String +} + +type ConfigCreateSubscriptResponsePayload { + config: Config +} + +type CommentCreateResponsePayload { + comment: Comment + feedback: Feedback + feedbackCommentEdge: CommentsEdge + viewer: Viewer +} + +type CommentsCreateResponsePayload { + comments: [Comment] + feedback: [Feedback] + feedbackCommentEdges: [CommentsEdge] + viewer: Viewer +} + +type CommentDeleteResponsePayload { + deletedCommentId: ID + feedback: Feedback +} + +type CommentsDeleteResponsePayload { + deletedCommentIds: [ID] + feedback: Feedback +} + +type StoryUpdateResponsePayload { + story: Story +} + +type CommentsConnection { + count: Int + edges: [CommentsEdge] + pageInfo: PageInfo +} + +type CommentsEdge { + cursor: String + node: Comment + source: Feedback +} + +type CommentBodiesConnection { + count: Int + edges: [CommentBodiesEdge] + pageInfo: PageInfo +} + +type CommentBodiesEdge { + cursor: String + node: CommentBody # union type + source: Feedback +} + +type ConfigsConnection { + edges: [ConfigsConnectionEdge] + pageInfo: PageInfo +} + +type ConfigsConnectionEdge { + node: Config +} + +type Config { + name: String + isEnabled: Boolean +} + +type Date { + day: Int + month: Int + year: Int +} + +type Feedback implements Node & HasJsField { + js(module: String!, id: String): JSDependency + actor: Actor + actors: [Actor] + actorCount: Int + address: StreetAddress + allPhones: [Phone] + author: User + backgroundImage: Image + birthdate: Date + body: Text + canViewerComment: Boolean + canViewerLike: Boolean + comments( + after: ID + before: ID + first: Int + last: Int + orderby: String + ): CommentsConnection + commentBodies( + after: ID + before: ID + first: Int + last: Int + orderby: String + ): CommentBodiesConnection + doesViewerLike: Boolean + emailAddresses: [String] + feedback: Feedback + firstName(if: Boolean, unless: Boolean): String + friends( + after: ID + before: ID + first: Int + last: Int + orderby: [String] + find: String + isViewerFriend: Boolean + if: Boolean + unless: Boolean + traits: [PersonalityTraits] + ): FriendsConnection + hometown: Page + id: ID! + lastName: String + likers(first: Int): LikersOfContentConnection + likeSentence: Text + message: Text + name: String + profilePicture(size: [Int], preset: PhotoSize): Image + segments(first: Int): Segments + screennames: [Screenname] + subscribeStatus: String + subscribers(first: Int): SubscribersConnection + topLevelComments( + orderBy: [TopLevelCommentsOrdering] + first: Int + ): TopLevelCommentsConnection + tracking: String + url(relative: Boolean, site: String): String + websites: [String] + username: String + viewedBy: [Actor] + viewerSavedState: String +} + +type FeedbackLikeResponsePayload { + feedback: Feedback +} + +interface FeedUnit { + actor: Actor + actorCount: Int + feedback: Feedback + id: ID! + message: Text + tracking: String + actor_key: ID! +} + +type FriendsConnection { + count: Int + edges: [FriendsEdge] + pageInfo: PageInfo +} + +type FriendsEdge { + cursor: String + node: User + source: User +} + +type Image { + uri: String + width: Int + height: Int + test_enums: TestEnums +} + +type LikersOfContentConnection { + count: Int + edges: [LikersEdge] + pageInfo: PageInfo +} + +type LikersEdge { + cursor: String + node: Actor +} + +interface Named { + name: String +} + +interface Entity { + url(relative: Boolean, site: String): String +} + +type SimpleNamed implements Named { + name: String +} + +type NewsFeedConnection { + edges: [NewsFeedEdge] + pageInfo: PageInfo +} + +type NewsFeedEdge { + cursor: String + node: FeedUnit + sortKey: String + showBeeper: Boolean +} + +interface Node { + actor: Actor + actors: [Actor] + actorCount: Int + address: StreetAddress + allPhones: [Phone] + author: User + backgroundImage: Image + birthdate: Date + body: Text + canViewerComment: Boolean + canViewerLike: Boolean + comments( + after: ID + before: ID + first: Int + last: Int + orderby: String + ): CommentsConnection + doesViewerLike: Boolean + emailAddresses: [String] + feedback: Feedback + firstName(if: Boolean, unless: Boolean): String + friends( + after: ID + before: ID + first: Int + last: Int + orderby: [String] + find: String + isViewerFriend: Boolean + if: Boolean + unless: Boolean + traits: [PersonalityTraits] + ): FriendsConnection + hometown: Page + id: ID! + lastName: String + likers(first: Int): LikersOfContentConnection + likeSentence: Text + message: Text + name: String + profilePicture(size: [Int], preset: PhotoSize): Image + segments(first: Int): Segments + screennames: [Screenname] + subscribeStatus: String + subscribers(first: Int): SubscribersConnection + topLevelComments(first: Int): TopLevelCommentsConnection + tracking: String + url(relative: Boolean, site: String): String + websites: [String] + username: String + viewerSavedState: String +} + +interface Actor { + address: StreetAddress + allPhones: [Phone] + birthdate: Date + emailAddresses: [String] + firstName(if: Boolean, unless: Boolean): String + friends( + after: ID + before: ID + first: Int + last: Int + orderby: [String] + find: String + isViewerFriend: Boolean + if: Boolean + unless: Boolean + traits: [PersonalityTraits] + ): FriendsConnection + hometown: Page + id: ID! + lastName: String + name: String + nameRenderer(supported: [String!]): UserNameRenderer + nameRenderable(supported: [String!]): UserNameRenderable + profilePicture(size: [Int], preset: PhotoSize): Image + screennames: [Screenname] + subscribeStatus: String + subscribers(first: Int): SubscribersConnection + url(relative: Boolean, site: String): String + websites: [String] + username: String + actor_key: ID! +} + +type NodeSavedStateResponsePayload { + node: Node +} + +type Page implements Node & Actor & Entity { + actor: Actor + actors: [Actor] + actorCount: Int + address: StreetAddress + allPhones: [Phone] + author: User + backgroundImage: Image + birthdate: Date + body: Text + canViewerComment: Boolean + canViewerLike: Boolean + comments( + after: ID + before: ID + first: Int + last: Int + orderby: String + ): CommentsConnection + doesViewerLike: Boolean + emailAddresses: [String] + feedback: Feedback + firstName(if: Boolean, unless: Boolean): String + friends( + after: ID + before: ID + first: Int + last: Int + orderby: [String] + find: String + isViewerFriend: Boolean + if: Boolean + unless: Boolean + traits: [PersonalityTraits] + ): FriendsConnection + hometown: Page + id: ID! + lastName: String + likers(first: Int): LikersOfContentConnection + likeSentence: Text + message: Text + name: String + nameRenderer(supported: [String!]): UserNameRenderer + nameRenderable(supported: [String!]): UserNameRenderable + profilePicture(size: [Int], preset: PhotoSize): Image + segments(first: Int): Segments + screennames: [Screenname] + subscribeStatus: String + subscribers(first: Int): SubscribersConnection + topLevelComments(first: Int): TopLevelCommentsConnection + tracking: String + url(relative: Boolean, site: String): String + websites: [String] + username: String + viewerSavedState: String + nameWithArgs(capitalize: Boolean!): String + nameWithDefaultArgs(capitalize: Boolean! = false): String + actor_key: ID! +} + +type PageInfo { + hasPreviousPage: Boolean + hasNextPage: Boolean + endCursor: String + startCursor: String +} + +type PendingPostsConnection { + count: Int + edges: [PendingPostsConnectionEdge] + pageInfo: PageInfo +} + +type PendingPostsConnectionEdge { + cursor: String + node: PendingPost +} + +type PendingPost { + text: String +} + +type Phone { + isVerified: Boolean + phoneNumber: PhoneNumber +} + +type PhoneNumber { + displayNumber: String + countryCode: String +} + +type Screenname { + name: String + service: String +} + +type Segments { + edges: SegmentsEdge +} + +type SegmentsEdge { + node: String +} + +type NonNodeStory implements FeedUnit @fetchable(field_name: "fetch_id") { + actor: Actor + actorCount: Int + feedback: Feedback + id: ID! + fetch_id: ID! + message: Text + tracking: String + comments( + after: ID + before: ID + first: Int + last: Int + orderby: String + ): CommentsConnection + actor_key: ID! +} + +type PhotoStory implements FeedUnit & Node { + # PhotoStory + photo: Image + + # FeedUnit + canViewerDelete: Boolean + seenState: String + + # Node + actor: Actor + actors: [Actor] + actorCount: Int + address: StreetAddress + allPhones: [Phone] + author: User + backgroundImage: Image + birthdate: Date + body: Text + canViewerComment: Boolean + canViewerLike: Boolean + comments( + after: ID + before: ID + first: Int + last: Int + orderby: String + ): CommentsConnection + doesViewerLike: Boolean + emailAddresses: [String] + feedback: Feedback + firstName(if: Boolean, unless: Boolean): String + friends( + after: ID + before: ID + first: Int + last: Int + orderby: [String] + find: String + isViewerFriend: Boolean + if: Boolean + unless: Boolean + traits: [PersonalityTraits] + ): FriendsConnection + hometown: Page + id: ID! + lastName: String + likers(first: Int): LikersOfContentConnection + likeSentence: Text + message: Text + name: String + profilePicture(size: [Int], preset: PhotoSize): Image + segments(first: Int): Segments + screennames: [Screenname] + subscribeStatus: String + subscribers(first: Int): SubscribersConnection + topLevelComments(first: Int): TopLevelCommentsConnection + tracking: String + url(relative: Boolean, site: String): String + websites: [String] + username: String + viewerSavedState: String + actor_key: ID! +} + +type Story implements FeedUnit & Node & MaybeNodeInterface { + attachments: [StoryAttachment] + + # FeedUnit + canViewerDelete: Boolean + seenState: String + + # Node + actor: Actor + actors: [Actor] + actorCount: Int + address: StreetAddress + allPhones: [Phone] + author: User + backgroundImage: Image + birthdate: Date + body: Text + canViewerComment: Boolean + canViewerLike: Boolean + comments( + after: ID + before: ID + first: Int + last: Int + orderby: String + ): CommentsConnection + doesViewerLike: Boolean + emailAddresses: [String] + feedback: Feedback + firstName(if: Boolean, unless: Boolean): String + friends( + after: ID + before: ID + first: Int + last: Int + orderby: [String] + find: String + isViewerFriend: Boolean + if: Boolean + unless: Boolean + traits: [PersonalityTraits] + ): FriendsConnection + hometown: Page + id: ID! + lastName: String + likers(first: Int): LikersOfContentConnection + likeSentence: Text + message: Text + name: String + profilePicture(size: [Int], preset: PhotoSize): Image + segments(first: Int): Segments + screennames: [Screenname] + subscribeStatus: String + subscribers(first: Int): SubscribersConnection + topLevelComments(first: Int): TopLevelCommentsConnection + tracking: String + url(relative: Boolean, site: String): String + websites: [String] + username: String + viewerSavedState: String + flight(component: String, props: ReactFlightProps): ReactFlightComponent + actor_key: ID! +} + +type StoryAttachment { + cache_id: ID! + target: Story + styleList: [String] +} + +type StreetAddress { + city: String + country: String + postal_code: String + street: String +} + +type SubscribersConnection { + count: Int + edges: [FriendsEdge] + pageInfo: PageInfo +} + +type SubscribersEdge { + cursor: String + node: User + source: User +} + +type Text { + text: String + ranges: [String] +} + +input InputText { + text: String + ranges: [String] +} + +type TimezoneInfo { + timezone: String +} + +type TopLevelCommentsConnection { + count: Int + edges: [CommentsEdge] + pageInfo: PageInfo + totalCount: Int +} + +input UnfriendInput { + friendId: ID +} + +type UnfriendResponsePayload { + actor: Actor + formerFriend: User +} + +scalar JSDependency + +interface HasJsField { + js(module: String!, id: String): JSDependency +} + +type PlainUserNameRenderer implements HasJsField & UserNameRenderable { + plaintext: String + data: PlainUserNameData + user: User + js(module: String!, id: String): JSDependency + name: String +} + +type PlainUserNameData { + id: ID + text: String +} + +type MarkdownUserNameRenderer implements HasJsField & UserNameRenderable { + markdown: String + data: MarkdownUserNameData + user: User + js(module: String!, id: String): JSDependency + name: String +} + +type MarkdownUserNameData { + id: ID + markup: String +} + +type CustomNameRenderer { + customField: String + user: User +} + +type PlainUserRenderer { + user: User + js(module: String!, id: String): JSDependency +} + +union UserNameRenderer = + PlainUserNameRenderer + | MarkdownUserNameRenderer + | CustomNameRenderer + +interface UserNameRenderable { + name: String +} + +input ProfilePictureOptions { + newName: String +} + +type User implements Named & Node & Actor & HasJsField & Entity & AllConcreteTypesImplementNode { + actor: Actor + actors: [Actor] + actorCount: Int + address: StreetAddress + allPhones: [Phone] + author: User + backgroundImage: Image + birthdate: Date + body: Text + canViewerComment: Boolean + canViewerLike: Boolean + checkins(environments: [Environment!]!): CheckinSearchResult + comments( + after: ID + before: ID + first: Int + last: Int + orderby: String + ): CommentsConnection + doesViewerLike: Boolean + emailAddresses: [String] + environment: Environment + feedback: Feedback + firstName(if: Boolean, unless: Boolean): String + friends( + after: ID + before: ID + first: Int + last: Int + orderby: [String] + named: String + scale: Float + find: String + isViewerFriend: Boolean + if: Boolean + unless: Boolean + traits: [PersonalityTraits] + ): FriendsConnection + hometown: Page + id: ID! + js(module: String!, id: String): JSDependency + lastName: String + likers(first: Int): LikersOfContentConnection + likeSentence: Text + message: Text + name: String + alternate_name: String + nameRenderable(supported: [String!]): UserNameRenderable + nameRendererNoSupportedArg: UserNameRenderer + nameRenderer(supported: [String!]): UserNameRenderer + nameRendererForContext( + context: NameRendererContext + supported: [String!]! + ): UserNameRenderer + nameRenderers(supported: [String!]): [UserNameRenderer] + storySearch(query: StorySearchInput): [Story] + storyCommentSearch(query: StoryCommentSearchInput): [Comment] + profilePicture(size: [Int], preset: PhotoSize): Image + profile_picture(scale: Float): Image + segments(first: Int): Segments + screennames: [Screenname] + subscribeStatus: String + subscribers(first: Int): SubscribersConnection + topLevelComments(first: Int): TopLevelCommentsConnection + tracking: String + traits: [PersonalityTraits] + url(relative: Boolean, site: String): String + websites: [String] + username: String + viewerSavedState: String + plainUserRenderer: PlainUserRenderer + profilePicture2( + size: [Int] + preset: PhotoSize + cropPosition: CropPosition + fileExtension: FileExtension + additionalParameters: JSON + options: ProfilePictureOptions + ): Image + neighbors: [User!] + nearest_neighbor: User! + parents: [User!]! + actor_key: ID! +} + +enum NameRendererContext { + HEADER + OTHER +} + +input StorySearchInput { + text: String + limit: Int + offset: Int + type: StoryType +} + +input StoryCommentSearchInput { + text: String + limit: Int + offset: Int +} + +type ItemFilterResult { + date: String +} + +input ItemFilterInput { + date: String +} + +type Viewer { + configs(named: [String]): ConfigsConnection + actor: Actor + account_user: User + allTimezones: [TimezoneInfo] + isFbEmployee: Boolean + newsFeed(after: ID, first: Int, find: ID): NewsFeedConnection + notificationStories(after: ID, first: Int): NewsFeedConnection + pendingPosts(first: Int): PendingPostsConnection + primaryEmail: String + timezoneEstimate: TimezoneInfo + marketplace_explore( + marketplace_browse_context: MarketplaceBrowseContext + with_price_between: [Float] + ): MarketplaceExploreConnection + marketplace_settings: MarketPlaceSettings +} + +type MarketPlaceSettings { + location: MarketPlaceSellLocation + categories: [String] +} + +type MarketPlaceSellLocation { + longitude: Float + latitude: Float +} + +type MarketplaceExploreConnection { + count: Int +} + +type ViewerNotificationsUpdateAllSeenStateResponsePayload { + stories: [Story] +} + +enum Environment { + WEB + MOBILE +} + +enum MarketplaceBrowseContext { + BROWSE_FEED + CATEGORY_FEED +} + +enum PhotoSize { + SMALL + LARGE +} + +enum PersonalityTraits { + CHEERFUL + DERISIVE + HELPFUL + SNARKY +} + +enum StoryType { + DIRECTED + UNDIRECTED +} + +enum TopLevelCommentsOrdering { + chronological + ranked_threaded + recent_activity + toplevel +} + +enum CropPosition { + TOP + CENTER + BOTTOM + LEFT + RIGHT +} + +enum FileExtension { + JPG + PNG +} + +enum TestEnums { + mark + zuck +} + +type Settings { + cache_id: ID + notificationSounds: Boolean + notifications(environment: Environment): Boolean +} + +type IDFieldTests { + id_non_null: IDFieldIsIDNonNull + id_null: IDFieldIsIDNull + id: IDFieldIsID +} +scalar IDFieldIsID +type IDFieldIsIDNonNull { + id: ID! +} +type IDFieldIsIDNull { + id: ID +} + +scalar ReactFlightComponent +scalar ReactFlightProps diff --git a/__tests__/useFragment-test.tsx b/__tests__/useFragment-test.tsx index 32521db2..b41db7d4 100644 --- a/__tests__/useFragment-test.tsx +++ b/__tests__/useFragment-test.tsx @@ -14,18 +14,8 @@ import * as React from 'react'; import { useMemo, useState } from 'react'; import * as TestRenderer from 'react-test-renderer'; -import { - useFragment as useFragmentNodeOriginal, - useFragmentSubscription, - ReactRelayContext, -} from '../src'; -import { - FRAGMENT_OWNER_KEY, - FRAGMENTS_KEY, - ID_KEY, - createOperationDescriptor, - graphql, -} from 'relay-runtime'; +import { useFragment as useFragmentNodeOriginal, useFragmentSubscription, ReactRelayContext } from '../src'; +import { FRAGMENT_OWNER_KEY, FRAGMENTS_KEY, ID_KEY, createOperationDescriptor, graphql } from 'relay-runtime'; /** * Copyright (c) Facebook, Inc. and its affiliates. @@ -57,10 +47,7 @@ const { function assertYieldsWereCleared(_scheduler) { const actualYields = _scheduler.unstable_clearYields(); if (actualYields.length !== 0) { - throw new Error( - 'Log of yielded values is not empty. ' + - 'Call expect(Scheduler).toHaveYielded(...) first.', - ); + throw new Error('Log of yielded values is not empty. ' + 'Call expect(Scheduler).toHaveYielded(...) first.'); } } @@ -147,7 +134,6 @@ function createFragmentRef(id, owner, __isWithinUnmatchedTypeRefinement = false) useFragmentTestNestedUserFragment: {}, }, [FRAGMENT_OWNER_KEY]: owner.request, - __isWithinUnmatchedTypeRefinement, }; } @@ -305,9 +291,7 @@ beforeEach(() => { setEnvironment = _setEnv; - return ( - {children} - ); + return {children}; }; renderSingularFragment = (args) => { diff --git a/__tests__/useFragmentNode-test.tsx b/__tests__/useFragmentNode-test.tsx index d38392b5..ca02a9e8 100644 --- a/__tests__/useFragmentNode-test.tsx +++ b/__tests__/useFragmentNode-test.tsx @@ -44,10 +44,9 @@ jest.doMock('relay-runtime', () => { }, }; }); -jest.spyOn( - require('relay-runtime').__internal, - 'getPromiseForActiveRequest', -).mockImplementationOnce(() => Promise.resolve()); +jest.spyOn(require('relay-runtime').__internal, 'getPromiseForActiveRequest').mockImplementationOnce(() => + Promise.resolve(), +); import * as React from 'react'; import { useMemo, useRef, useState } from 'react'; @@ -71,10 +70,7 @@ const warning = require('fbjs/lib/warning'); function assertYieldsWereCleared(_scheduler) { const actualYields = (_scheduler as any).unstable_clearYields(); if (actualYields.length !== 0) { - throw new Error( - 'Log of yielded values is not empty. ' + - 'Call expect(Scheduler).toHaveYielded(...) first.', - ); + throw new Error('Log of yielded values is not empty. ' + 'Call expect(Scheduler).toHaveYielded(...) first.'); } } @@ -149,7 +145,6 @@ function createFragmentRef(id, owner) { useFragmentNodeTestNestedUserFragment: {}, }, [FRAGMENT_OWNER_KEY]: owner.request, - __isWithinUnmatchedTypeRefinement: false, }; } @@ -254,7 +249,6 @@ beforeEach(() => { useFragmentNodeTestUserFragment: {}, }, [FRAGMENT_OWNER_KEY]: owner.request, - __isWithinUnmatchedTypeRefinement: false, }; /* eslint-enable indent */ setSingularOwner = _setOwner; @@ -276,7 +270,6 @@ beforeEach(() => { useFragmentNodeTestUsersFragment: {}, }, [FRAGMENT_OWNER_KEY]: owner.request, - __isWithinUnmatchedTypeRefinement: false, })); /* eslint-enable indent */ const [usersData] = useFragmentNode(gqlPluralFragment, usersRef); @@ -289,9 +282,7 @@ beforeEach(() => { setEnvironment = _setEnv; - return ( - {children} - ); + return {children}; }; renderSingularFragment = (args?: { isConcurrent?: boolean; owner?: any; userRef?: any }) => { @@ -303,8 +294,7 @@ beforeEach(() => { , // any[prop-missing] - error revealed when flow-typing ReactTestRenderer - { unstable_isConcurrent: isConcurrent, - unstable_concurrentUpdatesByDefault: true, }, + { unstable_isConcurrent: isConcurrent, unstable_concurrentUpdatesByDefault: true }, ); }; @@ -317,8 +307,7 @@ beforeEach(() => { , // any[prop-missing] - error revealed when flow-typing ReactTestRenderer - { unstable_isConcurrent: isConcurrent, - unstable_concurrentUpdatesByDefault: true, }, + { unstable_isConcurrent: isConcurrent, unstable_concurrentUpdatesByDefault: true }, ); }; }); @@ -1110,9 +1099,7 @@ it('should warn if fragment reference is non-null but read-out data is null', () // any[prop-missing] const [, warningMessage] = warning.mock.calls[1]; expect( - warningMessage.startsWith( - 'Relay: Expected to have been able to read non-null data for fragment `%s`', - ), + warningMessage.startsWith('Relay: Expected to have been able to read non-null data for fragment `%s`'), ).toEqual(true); // any[prop-missing] warning.mockClear(); @@ -1148,9 +1135,7 @@ it('should warn if plural fragment reference is non-null but read-out data is nu // any[prop-missing] const [, warningMessage] = warning.mock.calls[1]; expect( - warningMessage.startsWith( - 'Relay: Expected to have been able to read non-null data for fragment `%s`', - ), + warningMessage.startsWith('Relay: Expected to have been able to read non-null data for fragment `%s`'), ).toEqual(true); // any[prop-missing] warning.mockClear(); @@ -1313,8 +1298,8 @@ it('should subscribe for updates to plural fragments even if there is missing da name: 'Mark', }, ], + }); }); - }) // Assert render output with updated data assertFragmentResults([ diff --git a/__tests__/usePaginationFragment-test.tsx b/__tests__/usePaginationFragment-test.tsx index d9dd427d..891ed9e2 100644 --- a/__tests__/usePaginationFragment-test.tsx +++ b/__tests__/usePaginationFragment-test.tsx @@ -166,7 +166,6 @@ describe('usePaginationFragment', () => { usePaginationFragmentTestNestedUserFragment: {}, }, [FRAGMENT_OWNER_KEY]: owner.request, - __isWithinUnmatchedTypeRefinement: false, }; } diff --git a/__tests__/useRefetchableFragment-test.tsx b/__tests__/useRefetchableFragment-test.tsx index 55ae5054..669087b8 100644 --- a/__tests__/useRefetchableFragment-test.tsx +++ b/__tests__/useRefetchableFragment-test.tsx @@ -163,7 +163,6 @@ describe('useRefetchableFragmentNode', () => { [fragmentName]: {}, }, [FRAGMENT_OWNER_KEY]: owner.request, - __isWithinUnmatchedTypeRefinement, }; } diff --git a/examples/relay-hook-example/pagination-nextjs-ssr/package.json b/examples/relay-hook-example/pagination-nextjs-ssr/package.json index 10f61870..6b1023bc 100644 --- a/examples/relay-hook-example/pagination-nextjs-ssr/package.json +++ b/examples/relay-hook-example/pagination-nextjs-ssr/package.json @@ -35,6 +35,7 @@ "whatwg-fetch": "3.0.0", "react-infinite-scroller": "1.2.6" }, + "resolutions": { "**/@types/react": "17.0.2", "**/@types/react-transition-group": "4.2.0" }, "devDependencies": { "@babel/core": "^7.3.4", "@babel/node": "^7.2.2", @@ -43,7 +44,7 @@ "babel-plugin-styled-components": "^2.1.4", "@babel/preset-env": "^7.3.4", "@babel/preset-react": "^7.0.0", - "@babel/runtime": "^7.3.4", + "@babel/runtime": "^7.15.4", "@types/node": "^12.7.12", "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", @@ -52,8 +53,8 @@ "babel-loader": "^8.0.5", "babel-plugin-relay": "13.0.1", "cross-env": "6.0.3", - "relay-compiler": "13.0.1", - "relay-compiler-language-typescript": "14.2.1", + "relay-compiler": "16.0.0", + "relay-compiler-language-typescript": "15.0.1", "typescript": "^4.2.4" } } diff --git a/package-lock.json b/package-lock.json index cb4e82be..00c6199a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "relay-hooks", - "version": "8.0.2", + "version": "9.0.0-rc.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "relay-hooks", - "version": "8.0.2", + "version": "9.0.0-rc.2", "license": "MIT", "dependencies": { "@restart/hooks": "^0.4.9", @@ -46,10 +46,10 @@ "promise-polyfill": "6.1.0", "react": "^18.0.0", "react-test-renderer": "^18.0.0", - "relay-compiler": "^15.0.0", - "relay-runtime": "^15.0.0", - "relay-test-utils": "^15.0.0", - "relay-test-utils-internal": "^15.0.0", + "relay-compiler": "^16.0.0", + "relay-runtime": "^16.0.0", + "relay-test-utils": "^16.0.0", + "relay-test-utils-internal": "^16.0.0", "replace-in-file": "6.2.0", "rimraf": "^2.5.4", "rollup": "^2.23.0", @@ -65,7 +65,7 @@ }, "peerDependencies": { "react": "^16.9.0 || ^17 || ^18", - "relay-runtime": "^13.2.0 || ^14.0.0 || ^15.0.0" + "relay-runtime": "^16.0.0" } }, "node_modules/@babel/cli": { @@ -16598,18 +16598,18 @@ } }, "node_modules/relay-compiler": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/relay-compiler/-/relay-compiler-15.0.0.tgz", - "integrity": "sha512-19gIIdrVe/lk7Dkz/hqxpBd54bBDWAKG+kR5ael+xznJPdjlr/rlAmh5Tqi6Mgf/wiEQGdtKiZqeNdOW2/wVRw==", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/relay-compiler/-/relay-compiler-16.0.0.tgz", + "integrity": "sha512-qZKII4EN1R7VdEoJyDxzBtsfhLOJ8WLfl7iESk8h3HfbyHJzw2ygFuk334Qjeq+QN6soCim4quhJpAgp0+qBlQ==", "dev": true, "bin": { "relay-compiler": "cli.js" } }, "node_modules/relay-runtime": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/relay-runtime/-/relay-runtime-15.0.0.tgz", - "integrity": "sha512-7AXkXLQo6gpJNBhk4Kii5b+Yat62HSDD1TgJBi021iSjT1muI8iYd4UZG4f/If209LmaVjkZt2HTNAlk6xtslw==", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/relay-runtime/-/relay-runtime-16.0.0.tgz", + "integrity": "sha512-gJ70upfOxmFgtvFEKn7sU72uN2XF9Bg5Bml9oGRqe0rFWJDj1ItsljWzOZ972EyDE+pZG/VKbqiz3gUjhbsejQ==", "dev": true, "dependencies": { "@babel/runtime": "^7.0.0", @@ -16618,26 +16618,26 @@ } }, "node_modules/relay-test-utils": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/relay-test-utils/-/relay-test-utils-15.0.0.tgz", - "integrity": "sha512-0e0hLdH7YbPhsEBNgx2FGvWz/MROHiDhz6TH79QcuylNnVHS/M9rpPQt2EpxfGTu0yUfvW62B3UuFHo6I0QnCA==", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/relay-test-utils/-/relay-test-utils-16.0.0.tgz", + "integrity": "sha512-lYlYEIl544aOVwNQ5x8XYNnZhzUH42Z26k5d10dGW7uIPWe6dBC5pJzLM0nRtZIlZ7JuBI8vRh5w9ODguEQ+7A==", "dev": true, "dependencies": { "@babel/runtime": "^7.0.0", "fbjs": "^3.0.2", "invariant": "^2.2.4", - "relay-runtime": "15.0.0" + "relay-runtime": "16.0.0" } }, "node_modules/relay-test-utils-internal": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/relay-test-utils-internal/-/relay-test-utils-internal-15.0.0.tgz", - "integrity": "sha512-NKrRv9Oa+eXLzpCyiIikRqCQ0eXqHpIJ/Jq2/cvJxg/oxgiC03kFISl497oPkidsBdKvMg9xkDNwbpFad+rJjw==", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/relay-test-utils-internal/-/relay-test-utils-internal-16.0.0.tgz", + "integrity": "sha512-trkNbAQ2xjteXTNETY5gLIvgPyGpvX1d2nadV9C4OP9r0cfgHxhZkBQgUAL2vidwWFJH7TU839ZYA5ciC8VQlg==", "dev": true, "dependencies": { "@babel/runtime": "^7.0.0", "fbjs": "^3.0.2", - "relay-runtime": "15.0.0" + "relay-runtime": "16.0.0" } }, "node_modules/remove-trailing-separator": { @@ -32829,15 +32829,15 @@ "dev": true }, "relay-compiler": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/relay-compiler/-/relay-compiler-15.0.0.tgz", - "integrity": "sha512-19gIIdrVe/lk7Dkz/hqxpBd54bBDWAKG+kR5ael+xznJPdjlr/rlAmh5Tqi6Mgf/wiEQGdtKiZqeNdOW2/wVRw==", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/relay-compiler/-/relay-compiler-16.0.0.tgz", + "integrity": "sha512-qZKII4EN1R7VdEoJyDxzBtsfhLOJ8WLfl7iESk8h3HfbyHJzw2ygFuk334Qjeq+QN6soCim4quhJpAgp0+qBlQ==", "dev": true }, "relay-runtime": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/relay-runtime/-/relay-runtime-15.0.0.tgz", - "integrity": "sha512-7AXkXLQo6gpJNBhk4Kii5b+Yat62HSDD1TgJBi021iSjT1muI8iYd4UZG4f/If209LmaVjkZt2HTNAlk6xtslw==", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/relay-runtime/-/relay-runtime-16.0.0.tgz", + "integrity": "sha512-gJ70upfOxmFgtvFEKn7sU72uN2XF9Bg5Bml9oGRqe0rFWJDj1ItsljWzOZ972EyDE+pZG/VKbqiz3gUjhbsejQ==", "dev": true, "requires": { "@babel/runtime": "^7.0.0", @@ -32846,26 +32846,26 @@ } }, "relay-test-utils": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/relay-test-utils/-/relay-test-utils-15.0.0.tgz", - "integrity": "sha512-0e0hLdH7YbPhsEBNgx2FGvWz/MROHiDhz6TH79QcuylNnVHS/M9rpPQt2EpxfGTu0yUfvW62B3UuFHo6I0QnCA==", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/relay-test-utils/-/relay-test-utils-16.0.0.tgz", + "integrity": "sha512-lYlYEIl544aOVwNQ5x8XYNnZhzUH42Z26k5d10dGW7uIPWe6dBC5pJzLM0nRtZIlZ7JuBI8vRh5w9ODguEQ+7A==", "dev": true, "requires": { "@babel/runtime": "^7.0.0", "fbjs": "^3.0.2", "invariant": "^2.2.4", - "relay-runtime": "15.0.0" + "relay-runtime": "16.0.0" } }, "relay-test-utils-internal": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/relay-test-utils-internal/-/relay-test-utils-internal-15.0.0.tgz", - "integrity": "sha512-NKrRv9Oa+eXLzpCyiIikRqCQ0eXqHpIJ/Jq2/cvJxg/oxgiC03kFISl497oPkidsBdKvMg9xkDNwbpFad+rJjw==", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/relay-test-utils-internal/-/relay-test-utils-internal-16.0.0.tgz", + "integrity": "sha512-trkNbAQ2xjteXTNETY5gLIvgPyGpvX1d2nadV9C4OP9r0cfgHxhZkBQgUAL2vidwWFJH7TU839ZYA5ciC8VQlg==", "dev": true, "requires": { "@babel/runtime": "^7.0.0", "fbjs": "^3.0.2", - "relay-runtime": "15.0.0" + "relay-runtime": "16.0.0" } }, "remove-trailing-separator": { diff --git a/package.json b/package.json index 6dba138f..d8c3a058 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "relay-hooks", - "version": "8.0.2", + "version": "9.0.0-rc.2", "keywords": [ "graphql", "relay", @@ -38,7 +38,7 @@ }, "relay": { "src": "./__tests__", - "schema": "./node_modules/relay-test-utils-internal/lib/testschema.graphql", + "schema": "./__tests__/testschema.graphql", "excludes": [ "__generated__", "node_modules" @@ -52,7 +52,7 @@ }, "peerDependencies": { "react": "^16.9.0 || ^17 || ^18", - "relay-runtime": "^13.2.0 || ^14.0.0 || ^15.0.0" + "relay-runtime": "^16.0.0" }, "devDependencies": { "babel-preset-fbjs": "^3.3.0", @@ -89,10 +89,10 @@ "promise-polyfill": "6.1.0", "react": "^18.0.0", "react-test-renderer": "^18.0.0", - "relay-compiler": "^15.0.0", - "relay-runtime": "^15.0.0", - "relay-test-utils": "^15.0.0", - "relay-test-utils-internal": "^15.0.0", + "relay-compiler": "^16.0.0", + "relay-runtime": "^16.0.0", + "relay-test-utils": "^16.0.0", + "relay-test-utils-internal": "^16.0.0", "rimraf": "^2.5.4", "rollup": "^2.23.0", "rollup-plugin-sourcemaps": "0.6.2", diff --git a/src/FragmentResolver.ts b/src/FragmentResolver.ts index 8c483c75..2c70d417 100644 --- a/src/FragmentResolver.ts +++ b/src/FragmentResolver.ts @@ -414,14 +414,14 @@ export class FragmentResolver { ); } - const { fragmentRefPathInResponse, identifierField, refetchableRequest } = getRefetchMetadata( + const { fragmentRefPathInResponse, identifierInfo, refetchableRequest } = getRefetchMetadata( this._fragment, name, - ); + ) as any; const fragmentData = this.getData().data; const identifierValue = - identifierField != null && fragmentData != null && typeof fragmentData === 'object' - ? fragmentData[identifierField] + identifierInfo?.identifierField != null && fragmentData != null && typeof fragmentData === 'object' + ? fragmentData[identifierInfo.identifierField] : null; let parentVariables; @@ -452,8 +452,7 @@ export class FragmentResolver { ...fragmentVariables, ...variables, }; - - if (identifierField != null && !variables.hasOwnProperty('id')) { + if (identifierInfo != null && !variables.hasOwnProperty(identifierInfo.identifierQueryVariableName)) { // @refetchable fragments are guaranteed to have an `id` selection // if the type is Node, implements Node, or is @fetchable. Double-check // that there actually is a value at runtime. @@ -461,11 +460,11 @@ export class FragmentResolver { warning( false, 'Relay: Expected result to have a string ' + '`%s` in order to refetch, got `%s`.', - identifierField, + identifierInfo, identifierValue, ); } - refetchVariables.id = identifierValue; + refetchVariables[identifierInfo.identifierQueryVariableName] = identifierValue; } const onNext = (operation: OperationDescriptor, snapshot: Snapshot, doUpdate: boolean): void => { @@ -568,11 +567,14 @@ export class FragmentResolver { this.name, ); - const { paginationRequest, paginationMetadata, identifierField, connectionPathInFragmentData } = - getPaginationMetadata(this._fragment, this.name); + const { paginationRequest, paginationMetadata, connectionPathInFragmentData } = getPaginationMetadata( + this._fragment, + this.name, + ); + const { identifierInfo } = getRefetchMetadata(this._fragment, this._fragment.name) as any; const identifierValue = - identifierField != null && fragmentData != null && typeof fragmentData === 'object' - ? fragmentData[identifierField] + identifierInfo != null && fragmentData != null && typeof fragmentData === 'object' + ? fragmentData[identifierInfo.identifierField] : null; const parentVariables = (this._selector as SingularReaderSelector).owner.variables; @@ -594,7 +596,7 @@ export class FragmentResolver { // If the query needs an identifier value ('id' or similar) and one // was not explicitly provided, read it from the fragment data. - if (identifierField != null) { + if (identifierInfo != null) { // @refetchable fragments are guaranteed to have an `id` selection // if the type is Node, implements Node, or is @fetchable. Double-check // that there actually is a value at runtime. @@ -602,11 +604,11 @@ export class FragmentResolver { warning( false, 'Relay: Expected result to have a string ' + '`%s` in order to refetch, got `%s`.', - identifierField, + identifierInfo, identifierValue, ); } - paginationVariables.id = identifierValue; + paginationVariables[identifierInfo.identifierQueryVariableName] = identifierValue; } const complete = (error, doUpdate) => {