Explorar o código

Working relay configuration for vanilla JS

Andrew Swistak %!s(int64=6) %!d(string=hai) anos
pai
achega
71323952c4

+ 90 - 0
app/javascript/packs/frontend/__generated__/relayTestQuery.graphql.ts

@@ -0,0 +1,90 @@
+/* tslint:disable */
+
+import { ConcreteRequest } from "relay-runtime";
+export type relayTestQueryVariables = {};
+export type relayTestQueryResponse = {
+    readonly manyPokemon: ReadonlyArray<{
+        readonly id: string;
+        readonly iid: string;
+        readonly nickname: string | null;
+    }>;
+};
+export type relayTestQuery = {
+    readonly response: relayTestQueryResponse;
+    readonly variables: relayTestQueryVariables;
+};
+
+
+
+/*
+query relayTestQuery {
+  manyPokemon {
+    id
+    iid
+    nickname
+  }
+}
+*/
+
+const node: ConcreteRequest = (function(){
+var v0 = [
+  {
+    "kind": "LinkedField",
+    "alias": null,
+    "name": "manyPokemon",
+    "storageKey": null,
+    "args": null,
+    "concreteType": "Pokemon",
+    "plural": true,
+    "selections": [
+      {
+        "kind": "ScalarField",
+        "alias": null,
+        "name": "id",
+        "args": null,
+        "storageKey": null
+      },
+      {
+        "kind": "ScalarField",
+        "alias": null,
+        "name": "iid",
+        "args": null,
+        "storageKey": null
+      },
+      {
+        "kind": "ScalarField",
+        "alias": null,
+        "name": "nickname",
+        "args": null,
+        "storageKey": null
+      }
+    ]
+  }
+];
+return {
+  "kind": "Request",
+  "fragment": {
+    "kind": "Fragment",
+    "name": "relayTestQuery",
+    "type": "Query",
+    "metadata": null,
+    "argumentDefinitions": [],
+    "selections": (v0/*: any*/)
+  },
+  "operation": {
+    "kind": "Operation",
+    "name": "relayTestQuery",
+    "argumentDefinitions": [],
+    "selections": (v0/*: any*/)
+  },
+  "params": {
+    "operationKind": "query",
+    "name": "relayTestQuery",
+    "id": null,
+    "text": "query relayTestQuery {\n  manyPokemon {\n    id\n    iid\n    nickname\n  }\n}\n",
+    "metadata": {}
+  }
+};
+})();
+(node as any).hash = '5eed67aa0a2af74dfb92fe2656178710';
+export default node;

+ 5 - 0
app/javascript/packs/frontend/app.tsx

@@ -7,6 +7,7 @@ import ApplicationLayout from './components/layout/application_layout';
 const Pokemon = lazy((): Promise<any> => import('./components/pages/pokemon'));
 const NotFound = lazy((): Promise<any> => import('./components/pages/not_found'));
 const TestComponent = lazy((): Promise<any> => import('./components/test_component'));
+const RelayTest = lazy((): Promise<any> => import('./components/relay_test'));
 
 import './assets/stylesheets/app.scss';
 
@@ -17,6 +18,7 @@ function App(): React.ReactElement {
         <Suspense fallback={<div>Loading...</div>}>
           <Switch>
             <Route component={TestComponent} exact path='/' />
+            <Route component={RelayTest} exact path='/relay' />
             <Route component={Pokemon} path='/pokemon' />
 
             <Route component={NotFound} />
@@ -25,6 +27,9 @@ function App(): React.ReactElement {
           <p>
             <Link to='/pokemon'>Show me the pokemon!</Link>
           </p>
+          <p>
+            <Link to='/relay'>Take me to relay</Link>
+          </p>
         </Suspense>
       </ApplicationLayout>
     </BrowserRouter>

+ 44 - 0
app/javascript/packs/frontend/components/relay_test.jsx

@@ -0,0 +1,44 @@
+import React from 'react';
+import {graphql, QueryRenderer} from 'react-relay';
+import {Link} from 'react-router-dom';
+
+import environment from '../graphqlEnvironment';
+
+function RelayTest() {
+  return (
+    <QueryRenderer
+      environment={environment}
+      query={graphql`
+        query relayTestQuery {
+          manyPokemon {
+            id
+            iid
+            nickname
+          }
+        }
+      `}
+      render={({error, props}) => {
+        if (error) {
+          return <div>Error!</div>;
+        }
+        if (!props) {
+          return <div>Loading...</div>;
+        }
+        return (
+          <ul>
+            {props.manyPokemon.map(pkmn => (
+              <li key={pkmn.id}>
+                <Link to={'/pokemon/' + pkmn.id}>
+                  [{pkmn.iid}] {pkmn.id}: {pkmn.nickname}
+                </Link>
+              </li>
+            ))}
+          </ul>
+        );
+      }}
+      variables={{}}
+    />
+  );
+}
+
+export default RelayTest;

+ 21 - 0
app/javascript/packs/frontend/graphqlEnvironment.ts

@@ -0,0 +1,21 @@
+import {Environment, Network, RecordSource, Store} from 'relay-runtime';
+
+function fetchQuery(operation, variables): Promise<void> {
+  return fetch('/api/graphql', {
+    method: 'POST',
+    headers: {
+      'Content-Type': 'application/json',
+    },
+    body: JSON.stringify({
+      query: operation.text,
+      variables,
+    }),
+  }).then((response): Promise<void> => response.json());
+}
+
+const environment = new Environment({
+  network: Network.create(fetchQuery),
+  store: new Store(new RecordSource()),
+});
+
+export default environment;

+ 6 - 1
babel.config.js

@@ -36,7 +36,12 @@ module.exports = function(api) {
     plugins: [
       require('react-hot-loader/babel'),
       require('babel-plugin-macros'),
-      require('babel-plugin-relay'),
+      [
+        require('babel-plugin-relay'),
+        {
+          artifactDirectory: './app/javascript/packs/frontend/__generated__',
+        },
+      ],
       require('@babel/plugin-syntax-dynamic-import').default,
       isTestEnv && require('babel-plugin-dynamic-import-node'),
       require('@babel/plugin-transform-destructuring').default,

+ 5 - 1
package.json

@@ -10,7 +10,7 @@
     "test": "jest --verbose false",
     "test:update_snapshots": "jest --updateSnapshot",
     "test:watch": "jest --watchAll",
-    "relay": "relay-compiler --src ./app/javascript/packs --schema ./db/schema.graphql --extensions js jsx ts tsx"
+    "relay": "relay-compiler --src ./app/javascript/packs --schema ./db/schema.graphql --language typescript --extensions js jsx ts tsx --artifactDirectory ./app/javascript/packs/frontend/__generated__"
   },
   "jest": {
     "preset": "ts-jest",
@@ -46,6 +46,7 @@
     "react-router": "^5.0.0",
     "react-router-bootstrap": "^0.25.0",
     "react-router-dom": "^5.0.0",
+    "relay-runtime": "^4.0.0",
     "webpack-cli": "^3.3.0"
   },
   "devDependencies": {
@@ -57,8 +58,10 @@
     "@types/react": "^16.8.14",
     "@types/react-bootstrap": "^0.32.17",
     "@types/react-dom": "^16.8.4",
+    "@types/react-relay": "^1.3.14",
     "@types/react-router": "^4.4.5",
     "@types/react-router-dom": "^4.3.2",
+    "@types/relay-runtime": "^1.3.12",
     "@typescript-eslint/eslint-plugin": "^1.7.0",
     "@typescript-eslint/parser": "^1.7.0",
     "babel-core": "^7.0.0-bridge.0",
@@ -78,6 +81,7 @@
     "prettier": "^1.17.0",
     "react-test-renderer": "^16.8.6",
     "relay-compiler": "^4.0.0",
+    "relay-compiler-language-typescript": "^4.3.0",
     "resolve-url-loader": "^3.1.0",
     "source-map-loader": "^0.2.4",
     "ts-jest": "^24.0.2",

+ 27 - 1
yarn.lock

@@ -1127,6 +1127,14 @@
   dependencies:
     "@types/react" "*"
 
+"@types/react-relay@^1.3.14":
+  version "1.3.14"
+  resolved "https://registry.yarnpkg.com/@types/react-relay/-/react-relay-1.3.14.tgz#72b590be03b193feca4c732370d80647fb64bda7"
+  integrity sha512-Zh5IpiG15D3eZQuhxnqpBrxcszmGv1JfDB4BdBkd4WnfZ0iHUqHTLX506BT/Nk8x9fezfqxOv9c4W8yITZizMQ==
+  dependencies:
+    "@types/react" "*"
+    "@types/relay-runtime" "*"
+
 "@types/react-router-dom@^4.3.2":
   version "4.3.2"
   resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-4.3.2.tgz#52c17c3682597638f31c17c42620403dc5c2a3f5"
@@ -1152,6 +1160,11 @@
     "@types/prop-types" "*"
     csstype "^2.2.0"
 
+"@types/relay-runtime@*", "@types/relay-runtime@^1.3.12":
+  version "1.3.12"
+  resolved "https://registry.yarnpkg.com/@types/relay-runtime/-/relay-runtime-1.3.12.tgz#602b98eb333b47d98213816d7e40273edaac3e90"
+  integrity sha512-MXM7ElUpLzPfaIlG6263qDd7+zdNpqy43K90yyQzB0ax1hKMJ+R3WfaVLFxn/X49YR8fa6kwA3ikjh2A/JNFJg==
+
 "@types/stack-utils@^1.0.1":
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
@@ -4663,6 +4676,11 @@ ignore@^4.0.6:
   resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
   integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
 
+immutable@^3.8.2:
+  version "3.8.2"
+  resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3"
+  integrity sha1-wkOZUUVbs5kT2vKBN28VMOEErfM=
+
 immutable@~3.7.6:
   version "3.7.6"
   resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.7.6.tgz#13b4d3cb12befa15482a26fe1b2ebae640071e4b"
@@ -8361,6 +8379,14 @@ regjsparser@^0.6.0:
   dependencies:
     jsesc "~0.5.0"
 
+relay-compiler-language-typescript@^4.3.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/relay-compiler-language-typescript/-/relay-compiler-language-typescript-4.3.0.tgz#4069253adfe7866d677324c50f166ee20ea53240"
+  integrity sha512-X7hOG3Q/YkkwCuP6MA881aY3JmqatpsnCpW/J58LOaS6NQ6osl1aurmL7qVwfrIUfk+aSXvUbyUrFeQUj/DhXg==
+  dependencies:
+    immutable "^3.8.2"
+    invariant "^2.2.2"
+
 relay-compiler@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/relay-compiler/-/relay-compiler-4.0.0.tgz#d97dd2819d3b92669599c9cfec8049c9b487be67"
@@ -8384,7 +8410,7 @@ relay-compiler@^4.0.0:
     signedsource "^1.0.0"
     yargs "^9.0.0"
 
-relay-runtime@4.0.0:
+relay-runtime@4.0.0, relay-runtime@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/relay-runtime/-/relay-runtime-4.0.0.tgz#5cf50f52e3ea56ec81f0b5fed05b03e99a9e3906"
   integrity sha512-Fd5nAMNfySINAYPf1zgtcYbCk33pO5ANiYfaMhKYzukfc2GCmn6RP7NEpG69GxVezu/E1aOxo72t+Y1NspDV8A==