diff --git a/warp/defer/client/schema.graphql b/warp/defer/client/schema.graphql index 482ec9d..1e0a002 100644 --- a/warp/defer/client/schema.graphql +++ b/warp/defer/client/schema.graphql @@ -1,6 +1,12 @@ -directive @defer on FIELD +directive @defer( + """Relay fragment label""" + label: String +) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT -directive @stream on FIELD +directive @stream( + """Relay fragment label""" + label: String +) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT type Book { title: String! diff --git a/warp/defer/client/src/__generated__/pagesQuery_graphql.bs.js b/warp/defer/client/src/__generated__/pagesQuery_graphql.bs.js index d1a525d..e9ebcf7 100644 --- a/warp/defer/client/src/__generated__/pagesQuery_graphql.bs.js +++ b/warp/defer/client/src/__generated__/pagesQuery_graphql.bs.js @@ -4,7 +4,7 @@ import * as ReasonRelay from "reason-relay/src/ReasonRelay.bs.js"; var Types = { }; -var responseConverter = ({"__root":{"books_comments":{"n":""}}}); +var responseConverter = ({"__root":{"books":{"f":""}}}); function convertResponse(v) { return ReasonRelay._convertObj(v, responseConverter, undefined, undefined); @@ -27,84 +27,105 @@ var Internal = { var Utils = { }; -var node = ((function(){ -var v0 = [ - { - "alias": null, - "args": null, - "concreteType": "Book", - "kind": "LinkedField", - "name": "books", - "plural": true, +var node = ({ + "fragment": { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "pagesQuery", "selections": [ { "alias": null, "args": null, - "kind": "ScalarField", - "name": "title", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "author", + "concreteType": "Book", + "kind": "LinkedField", + "name": "books", + "plural": true, + "selections": [ + { + "args": null, + "kind": "FragmentSpread", + "name": "pages_book" + } + ], "storageKey": null - }, + } + ], + "type": "Query" + }, + "kind": "Request", + "operation": { + "argumentDefinitions": [], + "kind": "Operation", + "name": "pagesQuery", + "selections": [ { "alias": null, "args": null, - "concreteType": "Comment", + "concreteType": "Book", "kind": "LinkedField", - "name": "comments", + "name": "books", "plural": true, "selections": [ { "alias": null, "args": null, "kind": "ScalarField", - "name": "user", + "name": "title", "storageKey": null }, { "alias": null, "args": null, "kind": "ScalarField", - "name": "text", + "name": "author", "storageKey": null + }, + { + "if": null, + "kind": "Defer", + "label": "pages_book$defer$pages_comments_book", + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Comment", + "kind": "LinkedField", + "name": "comments", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "text", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "user", + "storageKey": null + } + ], + "storageKey": null + } + ] } ], "storageKey": null } - ], - "storageKey": null - } -]; -return { - "fragment": { - "argumentDefinitions": [], - "kind": "Fragment", - "metadata": null, - "name": "pagesQuery", - "selections": (v0/*: any*/), - "type": "Query" - }, - "kind": "Request", - "operation": { - "argumentDefinitions": [], - "kind": "Operation", - "name": "pagesQuery", - "selections": (v0/*: any*/) + ] }, "params": { "id": null, "metadata": {}, "name": "pagesQuery", "operationKind": "query", - "text": "query pagesQuery {\n books {\n title\n author\n comments @defer {\n user\n text\n }\n }\n}\n" + "text": "query pagesQuery {\n books {\n ...pages_book\n }\n}\n\nfragment pages_book on Book {\n title\n author\n ...pages_comments_book @defer(label: \"pages_book$defer$pages_comments_book\")\n}\n\nfragment pages_comments_book on Book {\n comments {\n text\n user\n }\n}\n" } -}; -})()); +}); var include = ReasonRelay.MakePreloadQuery({ query: node, diff --git a/warp/defer/client/src/__generated__/pagesQuery_graphql.re b/warp/defer/client/src/__generated__/pagesQuery_graphql.re index aee45a5..fd9e13d 100644 --- a/warp/defer/client/src/__generated__/pagesQuery_graphql.re +++ b/warp/defer/client/src/__generated__/pagesQuery_graphql.re @@ -1,14 +1,9 @@ /* @generated */ module Types = { - type response_books_comments = { - user: string, - text: string, - }; type response_books = { - title: string, - author: string, - comments: option(array(response_books_comments)), + getFragmentRefs: + unit => {. "__$fragment_ref__pages_book": Pages_book_graphql.t}, }; type response = {books: array(response_books)}; @@ -18,7 +13,7 @@ module Types = { module Internal = { type responseRaw; let responseConverter: Js.Dict.t(Js.Dict.t(Js.Dict.t(string))) = [%raw - {json| {"__root":{"books_comments":{"n":""}}} |json} + {json| {"__root":{"books":{"f":""}}} |json} ]; let responseConverterMap = (); let convertResponse = v => @@ -49,84 +44,105 @@ module Utils = {}; type operationType = ReasonRelay.queryNode; let node: operationType = [%raw - {json| (function(){ -var v0 = [ - { - "alias": null, - "args": null, - "concreteType": "Book", - "kind": "LinkedField", - "name": "books", - "plural": true, + {json| { + "fragment": { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "pagesQuery", "selections": [ { "alias": null, "args": null, - "kind": "ScalarField", - "name": "title", - "storageKey": null - }, - { - "alias": null, - "args": null, - "kind": "ScalarField", - "name": "author", + "concreteType": "Book", + "kind": "LinkedField", + "name": "books", + "plural": true, + "selections": [ + { + "args": null, + "kind": "FragmentSpread", + "name": "pages_book" + } + ], "storageKey": null - }, + } + ], + "type": "Query" + }, + "kind": "Request", + "operation": { + "argumentDefinitions": [], + "kind": "Operation", + "name": "pagesQuery", + "selections": [ { "alias": null, "args": null, - "concreteType": "Comment", + "concreteType": "Book", "kind": "LinkedField", - "name": "comments", + "name": "books", "plural": true, "selections": [ { "alias": null, "args": null, "kind": "ScalarField", - "name": "user", + "name": "title", "storageKey": null }, { "alias": null, "args": null, "kind": "ScalarField", - "name": "text", + "name": "author", "storageKey": null + }, + { + "if": null, + "kind": "Defer", + "label": "pages_book$defer$pages_comments_book", + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Comment", + "kind": "LinkedField", + "name": "comments", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "text", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "user", + "storageKey": null + } + ], + "storageKey": null + } + ] } ], "storageKey": null } - ], - "storageKey": null - } -]; -return { - "fragment": { - "argumentDefinitions": [], - "kind": "Fragment", - "metadata": null, - "name": "pagesQuery", - "selections": (v0/*: any*/), - "type": "Query" - }, - "kind": "Request", - "operation": { - "argumentDefinitions": [], - "kind": "Operation", - "name": "pagesQuery", - "selections": (v0/*: any*/) + ] }, "params": { "id": null, "metadata": {}, "name": "pagesQuery", "operationKind": "query", - "text": "query pagesQuery {\n books {\n title\n author\n comments @defer {\n user\n text\n }\n }\n}\n" + "text": "query pagesQuery {\n books {\n ...pages_book\n }\n}\n\nfragment pages_book on Book {\n title\n author\n ...pages_comments_book @defer(label: \"pages_book$defer$pages_comments_book\")\n}\n\nfragment pages_comments_book on Book {\n comments {\n text\n user\n }\n}\n" } -}; -})() |json} +} |json} ]; include ReasonRelay.MakePreloadQuery({ diff --git a/warp/defer/client/src/__generated__/pages_book_graphql.bs.js b/warp/defer/client/src/__generated__/pages_book_graphql.bs.js new file mode 100644 index 0000000..57c972f --- /dev/null +++ b/warp/defer/client/src/__generated__/pages_book_graphql.bs.js @@ -0,0 +1,62 @@ + + +import * as ReasonRelay from "reason-relay/src/ReasonRelay.bs.js"; + +var Types = { }; + +var fragmentConverter = ({"__root":{"":{"f":""}}}); + +function convertFragment(v) { + return ReasonRelay._convertObj(v, fragmentConverter, undefined, undefined); +} + +var Internal = { + fragmentConverter: fragmentConverter, + fragmentConverterMap: undefined, + convertFragment: convertFragment +}; + +var Utils = { }; + +var node = ({ + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "pages_book", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "title", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "author", + "storageKey": null + }, + { + "kind": "Defer", + "selections": [ + { + "args": null, + "kind": "FragmentSpread", + "name": "pages_comments_book" + } + ] + } + ], + "type": "Book" +}); + +export { + Types , + Internal , + Utils , + node , + +} +/* fragmentConverter Not a pure module */ diff --git a/warp/defer/client/src/__generated__/pages_book_graphql.re b/warp/defer/client/src/__generated__/pages_book_graphql.re new file mode 100644 index 0000000..5c205b2 --- /dev/null +++ b/warp/defer/client/src/__generated__/pages_book_graphql.re @@ -0,0 +1,74 @@ +/* @generated */ + +module Types = { + type fragment = { + title: string, + author: string, + getFragmentRefs: + unit => + { + . + "__$fragment_ref__pages_comments_book": Pages_comments_book_graphql.t, + }, + }; +}; + +module Internal = { + type fragmentRaw; + let fragmentConverter: Js.Dict.t(Js.Dict.t(Js.Dict.t(string))) = [%raw + {json| {"__root":{"":{"f":""}}} |json} + ]; + let fragmentConverterMap = (); + let convertFragment = v => + v + ->ReasonRelay._convertObj( + fragmentConverter, + fragmentConverterMap, + Js.undefined, + ); +}; + +type t; +type fragmentRef; +type fragmentRefSelector('a) = {.. "__$fragment_ref__pages_book": t} as 'a; +external getFragmentRef: fragmentRefSelector('a) => fragmentRef = "%identity"; + +module Utils = {}; + +type operationType = ReasonRelay.fragmentNode; + +let node: operationType = [%raw + {json| { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "pages_book", + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "title", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "author", + "storageKey": null + }, + { + "kind": "Defer", + "selections": [ + { + "args": null, + "kind": "FragmentSpread", + "name": "pages_comments_book" + } + ] + } + ], + "type": "Book" +} |json} +]; diff --git a/warp/defer/client/src/__generated__/pages_comments_book_graphql.bs.js b/warp/defer/client/src/__generated__/pages_comments_book_graphql.bs.js new file mode 100644 index 0000000..6dbe0c2 --- /dev/null +++ b/warp/defer/client/src/__generated__/pages_comments_book_graphql.bs.js @@ -0,0 +1,63 @@ + + +import * as ReasonRelay from "reason-relay/src/ReasonRelay.bs.js"; + +var Types = { }; + +var fragmentConverter = ({"__root":{"comments":{"n":""}}}); + +function convertFragment(v) { + return ReasonRelay._convertObj(v, fragmentConverter, undefined, undefined); +} + +var Internal = { + fragmentConverter: fragmentConverter, + fragmentConverterMap: undefined, + convertFragment: convertFragment +}; + +var Utils = { }; + +var node = ({ + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "pages_comments_book", + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Comment", + "kind": "LinkedField", + "name": "comments", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "text", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "user", + "storageKey": null + } + ], + "storageKey": null + } + ], + "type": "Book" +}); + +export { + Types , + Internal , + Utils , + node , + +} +/* fragmentConverter Not a pure module */ diff --git a/warp/defer/client/src/__generated__/pages_comments_book_graphql.re b/warp/defer/client/src/__generated__/pages_comments_book_graphql.re new file mode 100644 index 0000000..c618c75 --- /dev/null +++ b/warp/defer/client/src/__generated__/pages_comments_book_graphql.re @@ -0,0 +1,72 @@ +/* @generated */ + +module Types = { + type fragment_comments = { + text: string, + user: string, + }; + + type fragment = {comments: option(array(fragment_comments))}; +}; + +module Internal = { + type fragmentRaw; + let fragmentConverter: Js.Dict.t(Js.Dict.t(Js.Dict.t(string))) = [%raw + {json| {"__root":{"comments":{"n":""}}} |json} + ]; + let fragmentConverterMap = (); + let convertFragment = v => + v + ->ReasonRelay._convertObj( + fragmentConverter, + fragmentConverterMap, + Js.undefined, + ); +}; + +type t; +type fragmentRef; +type fragmentRefSelector('a) = + {.. "__$fragment_ref__pages_comments_book": t} as 'a; +external getFragmentRef: fragmentRefSelector('a) => fragmentRef = "%identity"; + +module Utils = {}; + +type operationType = ReasonRelay.fragmentNode; + +let node: operationType = [%raw + {json| { + "argumentDefinitions": [], + "kind": "Fragment", + "metadata": null, + "name": "pages_comments_book", + "selections": [ + { + "alias": null, + "args": null, + "concreteType": "Comment", + "kind": "LinkedField", + "name": "comments", + "plural": true, + "selections": [ + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "text", + "storageKey": null + }, + { + "alias": null, + "args": null, + "kind": "ScalarField", + "name": "user", + "storageKey": null + } + ], + "storageKey": null + } + ], + "type": "Book" +} |json} +]; diff --git a/warp/defer/client/src/pages/index.bs.js b/warp/defer/client/src/pages/index.bs.js index b6956ad..05a53fd 100644 --- a/warp/defer/client/src/pages/index.bs.js +++ b/warp/defer/client/src/pages/index.bs.js @@ -5,10 +5,13 @@ import * as React from "react"; import * as RelayEnv from "../helpers/RelayEnv.bs.js"; import * as Belt_Array from "bs-platform/lib/es6/belt_Array.js"; import * as Belt_Option from "bs-platform/lib/es6/belt_Option.js"; +import * as Caml_option from "bs-platform/lib/es6/caml_option.js"; import * as ReasonRelay from "reason-relay/src/ReasonRelay.bs.js"; import * as ErrorBoundary from "../components/ErrorBoundary.bs.js"; import * as ReactExperimental from "reason-relay/src/ReactExperimental.bs.js"; import * as PagesQuery_graphql from "../__generated__/pagesQuery_graphql.bs.js"; +import * as Pages_book_graphql from "../__generated__/pages_book_graphql.bs.js"; +import * as Pages_comments_book_graphql from "../__generated__/pages_comments_book_graphql.bs.js"; var convertResponse = PagesQuery_graphql.Internal.convertResponse; @@ -38,9 +41,33 @@ var Query = { usePreloaded: Query_usePreloaded }; +var convertFragment = Pages_comments_book_graphql.Internal.convertFragment; + +var UseFragment = ReasonRelay.MakeUseFragment({ + fragmentSpec: Pages_comments_book_graphql.node, + convertFragment: convertFragment + }); + +function use$1(fRef) { + return Curry._1(UseFragment.use, fRef); +} + +function useOpt(opt_fRef) { + return Curry._1(UseFragment.useOpt, opt_fRef !== undefined ? Caml_option.some(Caml_option.valFromOption(opt_fRef)) : undefined); +} + +var BookCommentsFragment = { + Operation: undefined, + Types: undefined, + UseFragment: UseFragment, + use: use$1, + useOpt: useOpt +}; + function Index$Comments(Props) { - var comments = Props.comments; - return Belt_Array.map(Belt_Option.getWithDefault(comments, []), (function (comment) { + var bookRef = Props.bookRef; + var book = Curry._1(UseFragment.use, bookRef); + return Belt_Array.map(Belt_Option.getWithDefault(book.comments, []), (function (comment) { var text = comment.text; var user = comment.user; return React.createElement("li", { @@ -53,12 +80,36 @@ var Comments = { make: Index$Comments }; +var convertFragment$1 = Pages_book_graphql.Internal.convertFragment; + +var UseFragment$1 = ReasonRelay.MakeUseFragment({ + fragmentSpec: Pages_book_graphql.node, + convertFragment: convertFragment$1 + }); + +function use$2(fRef) { + return Curry._1(UseFragment$1.use, fRef); +} + +function useOpt$1(opt_fRef) { + return Curry._1(UseFragment$1.useOpt, opt_fRef !== undefined ? Caml_option.some(Caml_option.valFromOption(opt_fRef)) : undefined); +} + +var BookFragment = { + Operation: undefined, + Types: undefined, + UseFragment: UseFragment$1, + use: use$2, + useOpt: useOpt$1 +}; + function Index$Book(Props) { - var title = Props.title; - var author = Props.author; - var comments = Props.comments; + var bookRef = Props.bookRef; + var book = Curry._1(UseFragment$1.use, bookRef); + var title = book.title; + var author = book.author; return React.createElement("div", undefined, React.createElement("p", undefined, "" + (String(title) + (" by " + (String(author) + "")))), React.createElement(Index$Comments, { - comments: comments + bookRef: Curry._1(book.getFragmentRefs, undefined) })); } @@ -69,15 +120,12 @@ var Book = { function Index$Books(Props) { var response = Curry._6(use, undefined, undefined, undefined, undefined, undefined, undefined); var booksCount = response.books.length; - console.log("books: ", response.books); return React.createElement("div", undefined, React.createElement("h2", { className: "text-4xl font-extrabold tracking-tight text-gray-900 leading-10 sm:text-5xl sm:leading-none md:text-6xl pb-10" - }, "Streaming " + (String(booksCount) + " books....")), Belt_Array.map(response.books, (function (book) { + }, "Streaming " + (String(booksCount) + " books....")), Belt_Array.mapWithIndex(response.books, (function (idx, book) { return React.createElement(Index$Book, { - title: book.title, - author: book.author, - comments: book.comments, - key: book.title + bookRef: Curry._1(book.getFragmentRefs, undefined), + key: String(idx) }); }))); } @@ -105,7 +153,9 @@ var $$default = Index; export { Query , + BookCommentsFragment , Comments , + BookFragment , Book , Books , make , diff --git a/warp/defer/client/src/pages/index.re b/warp/defer/client/src/pages/index.re index 94cd61f..b0af85d 100644 --- a/warp/defer/client/src/pages/index.re +++ b/warp/defer/client/src/pages/index.re @@ -2,39 +2,58 @@ module Query = [%relay.query {| query pagesQuery { books { - title - author - comments @defer { - user - text - } + ...pages_book } } |} ]; +module BookCommentsFragment = [%relay.fragment + {| + fragment pages_comments_book on Book { + comments { + text + user + } + } +|} +]; + module Comments = { [@react.component] - let make = (~comments) => { - Query.Types.( - comments - ->Belt.Option.getWithDefault([||]) - ->Belt.Array.map(comment => { - let text = comment.text; - let user = comment.user; -
{j|$title by $author|j}->React.string
-