├── Procfile
├── globals.d.ts
├── .eslintignore
├── .gitignore
├── periqles-logo.png
├── public
├── assets
│ ├── ian.jpeg
│ ├── joe.jpeg
│ ├── FVAlmelo.ttf
│ ├── cameron.jpeg
│ ├── kelly.jpeg
│ ├── FVAlmelo.woff
│ ├── FVAlmelo.woff2
│ ├── periqles-logo.png
│ ├── npm-logo-black.png
│ └── Github-Mark-64px.png
├── index.html
└── index.css
├── ts
├── apolloCache.ts
├── components
│ ├── LogoSection.tsx
│ ├── CreatorCard.tsx
│ ├── Creators.tsx
│ ├── LinksSection.tsx
│ ├── Demo.tsx
│ ├── ApolloUserProfile.tsx
│ └── relay
│ │ └── UserProfile.tsx
├── app.tsx
└── mutations
│ └── AddUserMutation.js
├── testing.js
├── types
├── index.d.ts
├── relay-runtime_types.js
├── periqles
│ └── index.d.ts
└── react-relay_types.js
├── relay.config.js
├── scripts
└── updateSchema.js
├── .babelrc
├── data
├── schema
│ ├── queries
│ │ └── demoUserQuery.js
│ ├── index.js
│ ├── mutations
│ │ └── AddUserMutation.js
│ └── nodes.js
├── schema.graphql
└── database.js
├── .eslintrc.cjs
├── README.md
├── apolloSchema.js
├── apolloResolvers.js
├── LICENSE
├── tsconfig.json
├── jest.config.js
├── server.js
├── webpack.config.js
├── package.json
└── __generated__
└── relay
├── UserProfileQuery.graphql.js
└── UserProfile_AddUserMutation.graphql.js
/Procfile:
--------------------------------------------------------------------------------
1 | web: npm run quick-start
--------------------------------------------------------------------------------
/globals.d.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom/extend-expect';
2 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | lib
3 | flow-typed
4 | types
5 | __generated__
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .eslintcache
3 | .env
4 | node_modules
5 | dist
6 | periqles-**.tgz
--------------------------------------------------------------------------------
/periqles-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/periqles-demo/HEAD/periqles-logo.png
--------------------------------------------------------------------------------
/public/assets/ian.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/periqles-demo/HEAD/public/assets/ian.jpeg
--------------------------------------------------------------------------------
/public/assets/joe.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/periqles-demo/HEAD/public/assets/joe.jpeg
--------------------------------------------------------------------------------
/public/assets/FVAlmelo.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/periqles-demo/HEAD/public/assets/FVAlmelo.ttf
--------------------------------------------------------------------------------
/public/assets/cameron.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/periqles-demo/HEAD/public/assets/cameron.jpeg
--------------------------------------------------------------------------------
/public/assets/kelly.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/periqles-demo/HEAD/public/assets/kelly.jpeg
--------------------------------------------------------------------------------
/public/assets/FVAlmelo.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/periqles-demo/HEAD/public/assets/FVAlmelo.woff
--------------------------------------------------------------------------------
/public/assets/FVAlmelo.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/periqles-demo/HEAD/public/assets/FVAlmelo.woff2
--------------------------------------------------------------------------------
/public/assets/periqles-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/periqles-demo/HEAD/public/assets/periqles-logo.png
--------------------------------------------------------------------------------
/public/assets/npm-logo-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/periqles-demo/HEAD/public/assets/npm-logo-black.png
--------------------------------------------------------------------------------
/public/assets/Github-Mark-64px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oslabs-beta/periqles-demo/HEAD/public/assets/Github-Mark-64px.png
--------------------------------------------------------------------------------
/ts/apolloCache.ts:
--------------------------------------------------------------------------------
1 | import { InMemoryCache, Reference } from '@apollo/client';
2 |
3 | export const cache: InMemoryCache = new InMemoryCache({});
4 |
--------------------------------------------------------------------------------
/testing.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const title = 'Hello React';
4 |
5 | const App = () => {
6 | return
{title}
;
7 | };
8 |
9 | export default App;
10 |
--------------------------------------------------------------------------------
/types/index.d.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable flowtype/object-type-delimiter */
2 | type FlatObject = Record;
3 |
4 | // commitMutation parameters
5 | type Input = FlatObject;
6 | interface Variables {
7 | input: Input;
8 | }
9 |
--------------------------------------------------------------------------------
/relay.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // Configuration options accepted by the `relay-compiler` command-line tool and `babel-plugin-relay`.
3 | src: './ts',
4 | schema: './data/schema.graphql',
5 | exclude: ["**/node_modules/**", "**/__mocks__/**", "**/__generated__/**"],
6 | // include: './dist',
7 | };
8 |
--------------------------------------------------------------------------------
/scripts/updateSchema.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env babel-node
2 | const fs = require('fs');
3 | const path = require('path');
4 | const {schema} = require('../data/schema/index.js');
5 | const {printSchema} = require('graphql');
6 |
7 | const schemaPath = path.resolve(__dirname, '../data/schema.graphql');
8 |
9 | fs.writeFileSync(schemaPath, printSchema(schema));
10 |
11 | console.log('Wrote ' + schemaPath);
12 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | ["relay", {"artifactDirectory": "./__generated__/relay/"}],
4 | "@babel/plugin-transform-runtime",
5 | "@babel/plugin-proposal-class-properties",
6 | "@babel/plugin-transform-typescript",
7 | "transform-react-jsx-img-import"
8 | ],
9 | "presets": [
10 | "@babel/preset-react",
11 | "@babel/preset-env",
12 | "@babel/preset-typescript"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/data/schema/queries/demoUserQuery.js:
--------------------------------------------------------------------------------
1 | const {demoGraphQLUser} = require('../nodes.js');
2 | const {
3 | DemoUser,
4 | getLastDemoUserOrThrow,
5 | getAllUsers,
6 | } = require('../../database.js');
7 |
8 | const demoUserQuery = {
9 | type: demoGraphQLUser,
10 | resolve: (root) => {
11 |
12 | getAllUsers();
13 | return getLastDemoUserOrThrow();
14 | },
15 | };
16 |
17 | module.exports = {demoUserQuery};
18 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Periqles Demo
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/ts/components/LogoSection.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 |
3 | const LogoSection = (): JSX.Element => {
4 |
5 | return (
6 |
7 |
10 |
11 | Painless forms for GraphQL.
12 |
13 |
14 | );
15 | };
16 |
17 | export default LogoSection;
18 |
--------------------------------------------------------------------------------
/types/relay-runtime_types.js:
--------------------------------------------------------------------------------
1 | declare module 'relay-runtime' {
2 | declare export var ConnectionHandler: any;
3 | declare export var RecordSource: any;
4 | declare export var Store: any;
5 | declare export var Environment: any;
6 | declare export var Network: any;
7 |
8 | declare export type RequestNode = any;
9 | declare export type Variables = any;
10 | declare export type ReaderFragment = any;
11 | declare export type ConcreteRequest = any;
12 | declare export opaque type FragmentReference;
13 | }
14 |
--------------------------------------------------------------------------------
/ts/components/CreatorCard.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | interface CreatorCardProps {
4 | key: number;
5 | author: {
6 | img: string;
7 | name: string;
8 | link: string;
9 | }
10 | }
11 |
12 | const CreatorCard = ({author}: CreatorCardProps): JSX.Element => {
13 | const {img, name, link} = author;
14 |
15 | return (
16 |
17 | {/* */}
21 | {name}
22 |
23 | );
24 | };
25 |
26 | export default CreatorCard;
--------------------------------------------------------------------------------
/data/schema/index.js:
--------------------------------------------------------------------------------
1 | const {GraphQLObjectType, GraphQLSchema} = require('graphql');
2 | const {nodeField} = require('./nodes.js');
3 | const {demoUserQuery} = require('./queries/demoUserQuery.js');
4 | const {AddUserMutation} = require('./mutations/AddUserMutation.js');
5 |
6 | const Query = new GraphQLObjectType({
7 | name: 'Query',
8 | fields: {
9 | demoUser: demoUserQuery,
10 | node: nodeField,
11 | },
12 | });
13 |
14 | const Mutation = new GraphQLObjectType({
15 | name: 'Mutation',
16 | fields: {
17 | addUser: AddUserMutation,
18 | },
19 | });
20 |
21 | const schema = new GraphQLSchema({
22 | query: Query,
23 | mutation: Mutation,
24 | });
25 |
26 | module.exports = {schema};
27 |
--------------------------------------------------------------------------------
/ts/app.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import ReactDOM from 'react-dom';
3 |
4 | import Demo from './components/Demo';
5 | import Creators from './components/Creators';
6 | import LogoSection from './components/LogoSection';
7 | import LinksSection from './components/LinksSection';
8 |
9 | const rootElement = document.getElementById('root');
10 |
11 |
12 | if (rootElement) {
13 | ReactDOM.render(
14 |
15 |
16 | {/* header returns user to top of page on click */}
17 |
18 |
19 |
20 |
21 |
22 |
23 | ,
24 | rootElement,
25 | );
26 | }
27 |
--------------------------------------------------------------------------------
/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: [
3 | 'eslint:recommended',
4 | 'fbjs/strict',
5 | 'plugin:prettier/recommended',
6 | 'plugin:react/recommended',
7 | 'plugin:relay/recommended',
8 | 'prettier/react',
9 | 'plugin:@typescript-eslint/eslint-recommended',
10 | 'plugin:@typescript-eslint/recommended',
11 | ],
12 | parser: 'babel-eslint',
13 | plugins: ['babel', 'prettier', 'react', 'relay', '@typescript-eslint'],
14 | rules: {
15 | 'no-console': 'off',
16 | 'one-var': 'off',
17 | 'react/prop-types': 'off', // Replaced by flow types
18 |
19 | // Mutations aren't located in the same file as Components
20 | 'relay/unused-fields': 'off',
21 | 'relay/generated-flow-types': 'off',
22 | },
23 | settings: {
24 | react: {
25 | version: '16.8.1',
26 | flowVersion: '0.94.0',
27 | },
28 | },
29 | };
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | periqles
6 |
7 | Painless forms for GraphQL.
8 |
9 |
10 | This is a demo of [periqles](https://github.com/oslabs-beta/periqles/blob/main/README.md), a form library for GraphQL that supports Relay and Apollo clients.
11 |
12 | [See it deployed →](https://periqles.herokuapp.com/)
13 |
14 | This repo uses Relay and Apollo clients side-by-side on the same Express server to demonstrate how to use periqles in either client. As such, it's a little bootstrappy on the backend; your own backend will probably look very different. Please consult [the periqles readme](https://github.com/oslabs-beta/periqles/blob/main/README.md) for documentation.
15 |
16 | If there's anything else about periqles you'd like to see demonstrated, please write an [issue](https://github.com/oslabs-beta/periqles-demo/issues) or open a pull request.
17 |
--------------------------------------------------------------------------------
/ts/components/Creators.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import CreatorCard from './CreatorCard';
3 |
4 | const Creators = (): JSX.Element => {
5 | const authors = [
6 | {
7 | img: '../../public/assets/cameron.jpeg',
8 | name: 'Cameron Baumgartner',
9 | link: 'https://github.com/cameronbaumgartner',
10 | },
11 | {
12 | img: '../../public/assets/ian.jpeg',
13 | name: 'Ian Garrett',
14 | link: 'https://github.com/eeeeean',
15 | },
16 | {
17 | img: '../../public/assets/kelly.jpeg',
18 | name: 'Kelly Porter',
19 | link: 'https://github.com/kporter101',
20 | },
21 | {
22 | img: '../../public/assets/joe.jpeg',
23 | name: 'Joe Toledano',
24 | link: 'https://github.com/JosephToledano',
25 | },
26 | ];
27 |
28 | return (
29 |
35 | );
36 | };
37 |
38 | export default Creators;
--------------------------------------------------------------------------------
/apolloSchema.js:
--------------------------------------------------------------------------------
1 | // const { gql } = require('apollo-server-express');
2 |
3 |
4 |
5 | // const typeDefs = gql`
6 | // type Query {
7 | // demoUser: DemoUser
8 | // }
9 |
10 | // type Mutation {
11 | // addUser(
12 | // input: AddUserInput!): DemoUser
13 | // }
14 |
15 | // input AddUserInput {
16 | // username: String!
17 | // password: String!
18 | // email: String!
19 | // gender: GenderEnum!
20 | // pizzaTopping: PizzaToppingEnum!
21 | // age: Int!
22 | // }
23 |
24 | // type DemoUser {
25 | // id: ID!
26 | // userId: String!
27 | // username: String!
28 | // password: String!
29 | // email: String!
30 | // gender: GenderEnum!
31 | // pizzaTopping: PizzaToppingEnum!
32 | // age: Int!
33 | // }
34 |
35 | // enum GenderEnum {
36 | // NON_BINARY
37 | // FEMALE
38 | // MALE
39 | // }
40 |
41 | // enum PizzaToppingEnum {
42 | // BUFFALO_CHICKEN
43 | // PEPPERONI
44 | // MEATLOVERS
45 | // EGGPLANT_PARM
46 | // OLIVES
47 | // HAWAIIAN
48 | // }
49 | // `;
50 |
51 | // export default typeDefs;
52 |
--------------------------------------------------------------------------------
/apolloResolvers.js:
--------------------------------------------------------------------------------
1 | const { getLastDemoUserOrThrow, addUser } = require('./data/database.js');
2 |
3 | module.exports = {
4 | Query: {
5 | // demoUser: (_, __, { database }) => database.getLastDemoUserOrThrow(),
6 | demoUser: (_, __, ___) => getLastDemoUserOrThrow(),
7 | },
8 | Mutation: {
9 | // addUser: (_, {
10 | // username,
11 | // password,
12 | // email,
13 | // gender,
14 | // pizzaTopping,
15 | // age,
16 | // }, { database }) => database.addUser(username, password, email, gender, pizzaTopping, age),
17 | addUser: (_, { input }, ___) => {
18 | return addUser(input);
19 | },
20 | },
21 | };
22 |
23 | // mutation AddUser {
24 | // addUser(username: "asdf", password: "asdf", email: "asdf@asdf", gender: "NON_BINARY", pizzaTopping: "HAWAIIAN", age: 1) {
25 | // username
26 | // }
27 | // }
28 | // query DemoUser {
29 | // demoUser {
30 | // username
31 | // password
32 | // email
33 | // gender
34 | // pizzaTopping
35 | // age
36 | // }
37 | // }
38 | // "eslintConfig": {
39 | // "extends": "react-app"
40 | // },
41 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 OSLabs Beta
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/ts/components/LinksSection.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 |
3 | const LinksSection = (): JSX.Element => {
4 |
5 | return (
6 |
7 |
8 | Periqles is a component library for Relay and Apollo that makes it easy to collect user input.
9 |
10 | Periqles abstracts away the dirty work of form creation — with override switches built in for the design-conscious developer — so you can be free to focus on business logic.
11 |
12 |
26 |
27 | );
28 | };
29 |
30 | export default LinksSection;
31 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "./dist/", // path to output directory
4 | "sourceMap": true, // allow sourcemap support
5 | "strictNullChecks": true, // enable strict null checks as a best practice
6 | "module": "commonjs", // specify module code generation
7 | "jsx": "react", // use typescript to transpile jsx to js
8 | "target": "es5", // specify ECMAScript target version
9 | "allowJs": true, // allow a partial TypeScript and JavaScript codebase
10 | "moduleResolution": "node", // use Node.js's module resolution strategy to resolve non-relative imports
11 | "allowSyntheticDefaultImports": true,
12 | // Ensure that .d.ts files are created by tsc, but not .js files
13 | "declaration": true, // generate .d.ts automatically from types throughout project
14 | "emitDeclarationOnly": true, // only generate .d.ts, not .js
15 | // Ensure that Babel can safely transpile files in the TypeScript project
16 | "isolatedModules": true,
17 | "esModuleInterop": true, //flag enabled for compatibility with Jest (and Babel):
18 | "typeRoots": [
19 | "./types",
20 | "node_modules/@types"
21 | ]
22 | },
23 | "paths": {
24 | "components/*": ["ts/components/*"]
25 | },
26 | "include": ["./ts/"]
27 | }
28 |
--------------------------------------------------------------------------------
/data/schema.graphql:
--------------------------------------------------------------------------------
1 | type Query {
2 | demoUser: DemoUser
3 |
4 | """Fetches an object given its ID"""
5 | node(
6 | """The ID of an object"""
7 | id: ID!
8 | ): Node
9 | }
10 |
11 | type DemoUser {
12 | """The ID of an object"""
13 | id: ID!
14 | userId: String!
15 | username: String!
16 | password: String!
17 | email: String!
18 | gender: GenderEnum!
19 | pizzaTopping: PizzaToppingEnum!
20 | age: Int!
21 | }
22 |
23 | enum GenderEnum {
24 | NON_BINARY
25 | FEMALE
26 | MALE
27 | }
28 |
29 | enum PizzaToppingEnum {
30 | BUFFALO_CHICKEN
31 | PEPPERONI
32 | MEATLOVERS
33 | EGGPLANT_PARM
34 | OLIVES
35 | HAWAIIAN
36 | }
37 |
38 | """An object with an ID"""
39 | interface Node {
40 | """The id of the object."""
41 | id: ID!
42 | }
43 |
44 | type Mutation {
45 | addUser(input: AddUserInput!): AddUserPayload
46 | }
47 |
48 | type AddUserPayload {
49 | userId: String!
50 | username: String!
51 | password: String!
52 | email: String!
53 | gender: GenderEnum!
54 | pizzaTopping: PizzaToppingEnum!
55 | age: Int!
56 | clientMutationId: String
57 | }
58 |
59 | input AddUserInput {
60 | username: String!
61 | password: String!
62 | email: String!
63 | gender: GenderEnum!
64 | pizzaTopping: PizzaToppingEnum!
65 | age: Int!
66 | clientMutationId: String
67 | }
68 |
--------------------------------------------------------------------------------
/ts/mutations/AddUserMutation.js:
--------------------------------------------------------------------------------
1 | import {commitMutation, graphql} from 'react-relay';
2 |
3 | const mutation = graphql`
4 | mutation AddUserMutation($input: AddUserInput!) {
5 | addUser(input: $input) {
6 | userId
7 | username
8 | password
9 | email
10 | gender
11 | pizzaTopping
12 | age
13 | }
14 | }
15 | `;
16 |
17 | let tempID = 0;
18 |
19 | function commit(
20 | environment,
21 | username,
22 | password,
23 | email,
24 | gender,
25 | pizzaTopping,
26 | age,
27 | ) {
28 | const input = {
29 | username,
30 | password,
31 | email,
32 | gender,
33 | pizzaTopping,
34 | age,
35 | clientMutationId: `${tempID++}`,
36 | };
37 |
38 | return commitMutation(environment, {
39 | mutation,
40 | variables: {
41 | input,
42 | },
43 | updater: (store) => {
44 | const payload = store.getRootField('addUser');
45 | const newUserId = payload.getValue('userId');
46 | const newUsername = payload.getValue('username');
47 | const newPassword = payload.getValue('password');
48 | const newEmail = payload.getValue('email');
49 | const newGender = payload.getValue('gender');
50 | const newPizzaTopping = payload.getValue('pizzaTopping');
51 | const newAge = payload.getValue('age');
52 | },
53 | });
54 | }
55 |
56 | export default {commit};
57 |
--------------------------------------------------------------------------------
/ts/components/Demo.tsx:
--------------------------------------------------------------------------------
1 | import React, {useState} from 'react';
2 | import UserProfile from './relay/UserProfile';
3 | import ApolloUserProfile from './ApolloUserProfile';
4 | import {
5 | ApolloClient,
6 | NormalizedCacheObject,
7 | ApolloProvider
8 | } from '@apollo/client';
9 | import { cache } from '../apolloCache';
10 |
11 | let URI = '';
12 | if (process.env.NODE_ENV === 'development') {
13 | URI = 'http://localhost:8080/graphql';
14 | }
15 | else URI = 'https://periqles.herokuapp.com/graphql';
16 |
17 | const client: ApolloClient = new ApolloClient({
18 | cache,
19 | uri: URI,
20 | });
21 |
22 | const Demo = (): JSX.Element => {
23 | const [relay, setRelay] = useState(true);
24 |
25 | return (
26 |
27 | {relay
28 | ? Relay Demo
29 | : Apollo Demo
30 | }
31 |
32 | Apollo
33 |
34 | setRelay(e.target.checked)}/>
37 |
38 |
39 | Relay
40 |
41 | This site is just for demonstration purposes. Please don't enter personal information.
42 | {relay
43 | ?
44 | : (
45 |
46 |
47 | )
48 | }
49 |
50 | )
51 | }
52 |
53 | export default Demo;
--------------------------------------------------------------------------------
/data/schema/mutations/AddUserMutation.js:
--------------------------------------------------------------------------------
1 | const graphqlRelay = require('graphql-relay');
2 | const graphql = require('graphql');
3 | const {GenderEnum, PizzaToppingEnum} = require('../nodes.js');
4 | const {addUser, getDemoUserOrThrow} = require('../../database.js');
5 |
6 | const {mutationWithClientMutationId} = graphqlRelay;
7 | const {GraphQLNonNull, GraphQLString, GraphQLInt} = graphql;
8 |
9 | const AddUserMutation = mutationWithClientMutationId({
10 | name: 'AddUser',
11 | inputFields: {
12 | username: {type: new GraphQLNonNull(GraphQLString)},
13 | password: {type: new GraphQLNonNull(GraphQLString)},
14 | email: {type: new GraphQLNonNull(GraphQLString)},
15 | gender: {type: new GraphQLNonNull(GenderEnum)},
16 | pizzaTopping: {type: new GraphQLNonNull(PizzaToppingEnum)},
17 | age: {type: new GraphQLNonNull(GraphQLInt)},
18 | },
19 | outputFields: {
20 | userId: {
21 | type: new GraphQLNonNull(GraphQLString),
22 | resolve: ({userId}) => userId,
23 | },
24 | username: {
25 | type: new GraphQLNonNull(GraphQLString),
26 | resolve: ({username}) => username,
27 | },
28 | password: {
29 | type: new GraphQLNonNull(GraphQLString),
30 | resolve: ({password}) => password,
31 | },
32 | email: {
33 | type: new GraphQLNonNull(GraphQLString),
34 | resolve: ({email}) => email,
35 | },
36 | gender: {
37 | type: new GraphQLNonNull(GenderEnum),
38 | resolve: ({gender}) => gender,
39 | },
40 | pizzaTopping: {
41 | type: new GraphQLNonNull(PizzaToppingEnum),
42 | resolve: ({pizzaTopping}) => pizzaTopping,
43 | },
44 | age: {
45 | type: new GraphQLNonNull(GraphQLInt),
46 | resolve: ({age}) => age,
47 | },
48 | },
49 | mutateAndGetPayload: (input) => {
50 | const newUser = addUser(input);
51 | return newUser;
52 | },
53 | });
54 |
55 | module.exports = {AddUserMutation};
56 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | // import jestConfig from 'jest-config';
2 | // const {defaults} = jestConfig;
3 | const {defaults} = require('jest-config');
4 |
5 | module.exports = {
6 | roots: ['./__tests__'],
7 | globals: {
8 | 'ts-jest': {
9 | // Tell ts-jest about our typescript config.
10 | // You can specify a path to your tsconfig.json file,
11 | // but since we're compiling specifically for node here,
12 | // this works too.
13 | tsConfig: {
14 | target: './tsconfig.json',
15 | },
16 | },
17 | },
18 | // Transforms tell jest how to process our non-javascript files.
19 | // Here we're using babel for .js and .jsx files, and ts-jest for
20 | // .ts and .tsx files. You *can* just use babel-jest for both, if
21 | // you already have babel set up to compile typescript files.
22 | transform: {
23 | // '^.+\\.jsx?$': 'babel-jest',
24 | // '^.+\\.tsx?$': 'ts-jest',
25 | // If you're using babel for both:
26 | '^.+\\.[jt]sx?$': 'babel-jest',
27 | },
28 | // In webpack projects, we often allow importing things like css files or jpg
29 | // files, and let a webpack loader plugin take care of loading these resources.
30 | // In a unit test, though, we're running in node.js which doesn't know how
31 | // to import these, so this tells jest what to do for these.
32 | moduleNameMapper: {
33 | // Resolve .css and similar files to identity-obj-proxy instead.
34 | '.+\\.(css|styl|less|sass|scss)$': `identity-obj-proxy`,
35 | // Resolve .jpg and similar files to __mocks__/file-mock.js
36 | '.+\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': `/__mocks__/file-mock.js`,
37 | },
38 | // Tells Jest what folders to ignore for tests
39 | testPathIgnorePatterns: [`node_modules`, `\\.cache`],
40 | testURL: `http://localhost`,
41 | moduleFileExtensions: [
42 | ...defaults.moduleFileExtensions,
43 | '.ts',
44 | '.tsx',
45 | '.js',
46 | '.jsx',
47 | ],
48 | };
49 |
--------------------------------------------------------------------------------
/data/database.js:
--------------------------------------------------------------------------------
1 | //DEMO USER CLASSES, FUNCTIONS AND INFO
2 |
3 | // DemoUser class:
4 | class DemoUser {
5 | constructor(userId, username, password, email, gender, pizzaTopping, age) {
6 | this.userId = userId;
7 | this.username = username;
8 | this.password = password;
9 | this.email = email;
10 | this.gender = gender;
11 | this.pizzaTopping = pizzaTopping;
12 | this.age = age;
13 | }
14 | }
15 |
16 | // Mock database seeded with initial user
17 | const demoUsersById = new Map([
18 | [0, new DemoUser('0', 'bob', 'anna', 'bob@bob.io', 'MALE', 'HAWAIIAN', 10)],
19 | ]);
20 |
21 | // Seed initial user
22 | let nextUserId = 1;
23 |
24 | function getDemoUser(userId) {
25 | return demoUsersById.get(userId);
26 | }
27 | function getDemoUserOrThrow(userId) {
28 | const demoUser = getDemoUser(userId);
29 | if (!demoUser) {
30 | throw new Error(`Invariant exception, DemoUser ${userId} not found`);
31 | }
32 |
33 | return demoUser;
34 | }
35 |
36 | function getLastDemoUserOrThrow() {
37 | let lastDemoUser;
38 | const demoUsersIterator = demoUsersById[Symbol.iterator]();
39 |
40 | for (const userItem of demoUsersIterator) {
41 | lastDemoUser = userItem[1];
42 | }
43 |
44 | return lastDemoUser;
45 | }
46 |
47 | function getAllUsers() {
48 | let demoUserList = [];
49 | const demoUsersIterator = demoUsersById[Symbol.iterator]();
50 |
51 | for (const userItem of demoUsersIterator) {
52 | demoUserList.push(userItem[1]);
53 | }
54 |
55 | return demoUserList;
56 | }
57 |
58 | // addUser function
59 | function addUser({
60 | userId,
61 | username,
62 | password,
63 | email,
64 | gender,
65 | pizzaTopping,
66 | age,
67 | }) {
68 | const newUser = new DemoUser(
69 | `${nextUserId++}`,
70 | username,
71 | password,
72 | email,
73 | gender,
74 | pizzaTopping,
75 | age,
76 | );
77 | demoUsersById.set(newUser.userId, newUser);
78 | return newUser;
79 | }
80 |
81 | module.exports = {
82 | DemoUser,
83 | getDemoUserOrThrow,
84 | getLastDemoUserOrThrow,
85 | getAllUsers,
86 | addUser,
87 | };
88 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const {graphqlHTTP} = require('express-graphql');
3 | const path = require('path');
4 | const cors = require('cors');
5 | const {schema} = require('./data/schema/index.js');
6 |
7 | const app = express();
8 | const PORT = process.env.PORT || 3000;
9 |
10 | app.use(cors());
11 |
12 | app.use('*', (req, res, next) => {
13 | console.log('Incoming request:', req.method, req.baseUrl);
14 | return next();
15 | });
16 |
17 | // only needed when in production mode
18 | if (process.env.NODE_ENV === 'production' || process.env.NODE_ENV === undefined) {
19 | app.get('/', (req, res) => {
20 | return res.status(200)
21 | .sendFile(path.join(__dirname, '/public/index.html'));
22 | });
23 | app.get('/index.css', (req, res) => {
24 | return res.status(200)
25 | .set('Content-Type', 'text/css')
26 | .sendFile(path.join(__dirname, '/public/index.css'));
27 | });
28 | app.use('/dist/', express.static(path.join(__dirname, 'dist')));
29 | }
30 |
31 |
32 |
33 | // Set up GraphQL endpoint for POSTs
34 | app.post(
35 | '/graphql',
36 | graphqlHTTP({
37 | schema: schema,
38 | pretty: true, // pretty-print JSON responses
39 | }),
40 | );
41 |
42 | // Send a GET to /graphql to use GraphiQL in the dev environment
43 | if (process.env.NODE_ENV === 'development'){
44 | app.get(
45 | '/graphql',
46 | graphqlHTTP({
47 | schema: schema,
48 | pretty: true,
49 | graphiql: true,
50 | }),
51 | );
52 | }
53 |
54 | app.use(express.json());
55 |
56 | //ERROR HANDLING
57 | app.use((err, req, res, next) => {
58 | const error = {
59 | log: 'Express error handler caught unknown middleware error',
60 | status: 500,
61 | message: {
62 | err: 'A server error occured',
63 | },
64 | };
65 | error.message = err.message;
66 | if (err.status) error.status = err.status;
67 |
68 | console.log('SERVER ERROR: ', error.message);
69 | res.status(error.status).send(error.message);
70 | });
71 |
72 | app.listen(PORT, () => {
73 | console.log(`Backend server listening on port: ${PORT}`);
74 | });
75 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const CopyWebpackPlugin = require('copy-webpack-plugin');
3 |
4 | module.exports = {
5 | mode: process.env.NODE_ENV,
6 | entry: './ts/app.tsx',
7 | output: {
8 | filename: './bundle.js',
9 | path: path.resolve(__dirname, 'dist'),
10 | publicPath: '/dist/', // location of bundle.js
11 | },
12 | devServer: {
13 | contentBase: path.join(__dirname, 'public'), // static assets: serve html/css
14 | publicPath: '/dist/', // location of bundle.js
15 | port: 8080, // port used in development mode
16 | hot: true, // hot module replacement
17 | open: true, // opens the page when server starts
18 | // TODO: a more secure setting for allowed origins
19 | headers: {'Access-Control-Allow-Origin': '*'}, // allow cors from any host
20 | historyApiFallback: true, // if 404, serve index.html
21 | proxy: {
22 | // '/graphql/*': 'http://localhost:3000',
23 | '/graphql': 'http://localhost:3000',
24 | },
25 | onListening: function (server) {
26 | const port = server.listeningApp.address().port;
27 | console.log('Frontend listening on port:', port);
28 | },
29 | },
30 | resolve: {
31 | extensions: ['.ts', '.tsx', '.js', '.jsx'],
32 | },
33 | module: {
34 | rules: [
35 | {
36 | test: /\.(t|j)sx?$/,
37 | enforce: 'pre',
38 | loader: 'babel-loader',
39 | exclude: /node_modules/,
40 | },
41 | {
42 | test: /\.(css)$/,
43 | use: ['style-loader', 'css-loader'],
44 | },
45 | // use this loader if you want to require assets into files where they are used
46 | {
47 | test: /\.(png|jpg|jpeg|gif|ttf|woff|woff2)$/,
48 | loader: 'file-loader',
49 | options: {
50 | publicPath: 'dist' // after build, static assets currently in ./public will be findable in ./dist/public
51 | }
52 | },
53 | ],
54 | },
55 | plugins: [
56 | new CopyWebpackPlugin({
57 | patterns: [
58 | { from: 'public/assets' }
59 | ]
60 | })
61 | ],
62 | devtool: 'source-map',
63 | };
--------------------------------------------------------------------------------
/data/schema/nodes.js:
--------------------------------------------------------------------------------
1 | const {
2 | GraphQLNonNull,
3 | GraphQLObjectType,
4 | GraphQLString,
5 | GraphQLEnumType,
6 | GraphQLInt,
7 | } = require('graphql');
8 | const {fromGlobalId, globalIdField, nodeDefinitions} = require('graphql-relay');
9 | const {DemoUser, getLastDemoUserOrThrow} = require('../database.js');
10 |
11 | const {nodeInterface, nodeField} = nodeDefinitions(
12 | (globalId) => {
13 | const {type, id} = fromGlobalId(globalId);
14 | if (type === 'DemoUser') {
15 | return getLastDemoUserOrThrow();
16 | }
17 | return null;
18 | },
19 | (obj) => {
20 | if (obj instanceof DemoUser) {
21 | return obj;
22 | }
23 |
24 | return null;
25 | },
26 | );
27 |
28 | const GenderEnum = new GraphQLEnumType({
29 | name: 'GenderEnum',
30 | values: {
31 | NON_BINARY: {
32 | value: 'NON_BINARY',
33 | },
34 | FEMALE: {
35 | value: 'FEMALE',
36 | },
37 | MALE: {
38 | value: 'MALE',
39 | },
40 | },
41 | });
42 |
43 | const PizzaToppingEnum = new GraphQLEnumType({
44 | name: 'PizzaToppingEnum',
45 | values: {
46 | BUFFALO_CHICKEN: {
47 | value: 'BUFFALO_CHICKEN',
48 | },
49 | PEPPERONI: {
50 | value: 'PEPPERONI',
51 | },
52 | MEATLOVERS: {
53 | value: 'MEATLOVERS',
54 | },
55 | EGGPLANT_PARM: {
56 | value: 'EGGPLANT_PARM',
57 | },
58 | OLIVES: {
59 | value: 'OLIVES',
60 | },
61 | HAWAIIAN: {
62 | value: 'HAWAIIAN',
63 | },
64 | },
65 | });
66 |
67 | const demoGraphQLUser = new GraphQLObjectType({
68 | name: 'DemoUser',
69 | fields: {
70 | id: globalIdField('DemoUser'),
71 | userId: {
72 | type: new GraphQLNonNull(GraphQLString),
73 | resolve: (demoUser) => demoUser.userId,
74 | },
75 | username: {
76 | type: new GraphQLNonNull(GraphQLString),
77 | resolve: (demoUser) => demoUser.username,
78 | },
79 | password: {
80 | type: new GraphQLNonNull(GraphQLString),
81 | resolve: (demoUser) => demoUser.password,
82 | },
83 | email: {
84 | type: new GraphQLNonNull(GraphQLString),
85 | resolve: (demoUser) => demoUser.email,
86 | },
87 | gender: {
88 | type: new GraphQLNonNull(GenderEnum),
89 | resolve: (demoUser) => demoUser.gender,
90 | },
91 | pizzaTopping: {
92 | type: new GraphQLNonNull(PizzaToppingEnum),
93 | resolve: (demoUser) => demoUser.pizzaTopping,
94 | },
95 | age: {
96 | type: new GraphQLNonNull(GraphQLInt),
97 | resolve: (demoUser) => demoUser.age,
98 | },
99 | },
100 | });
101 |
102 | module.exports = {nodeField, demoGraphQLUser, GenderEnum, PizzaToppingEnum};
103 |
--------------------------------------------------------------------------------
/types/periqles/index.d.ts:
--------------------------------------------------------------------------------
1 | type Scalar = number | boolean | string;
2 | type FormState = Record;
3 |
4 |
5 | // PROPS FOR PERIQLES COMPONENTS
6 | interface PeriqlesSpecifications {
7 | header?: string;
8 | fields?: Record;
9 | }
10 |
11 | interface PeriqlesFieldSpecs {
12 | element: string;
13 | label: string | JSX.Element;
14 | options?: PeriqlesOptionSpec[];
15 | render?: (
16 | formState: FormState,
17 | setFormState: React.Dispatch>,
18 | handleChange: (e) => void,
19 | ) => JSX.Element;
20 | src?: string;
21 | min?: number;
22 | max?: number;
23 | }
24 |
25 | interface PeriqlesOptionSpec {
26 | label: string | JSX.Element;
27 | value: number | string;
28 | }
29 |
30 | // objects returned by generateFieldsArray
31 | interface PeriqlesField {
32 | name: string;
33 | label?: string | JSX.Element;
34 | type?: string;
35 | options?: PeriqlesFieldOption[];
36 | required?: boolean;
37 | }
38 |
39 | // options objects prepared for input fields represented by dropdowns/radios
40 | interface PeriqlesFieldOption {
41 | name: string;
42 | label: string | JSX.Element;
43 | value: number | string;
44 | type: string;
45 | }
46 |
47 | interface PeriqlesCallbacks {
48 | onSuccess?: (response: object) => any;
49 | onFailure?: (err: object) => any;
50 | }
51 |
52 | type PeriqlesMutationArgs = Record;
53 |
54 | interface RelayEnvironment {
55 | store: any;
56 | networkLayer: any;
57 | handlerProvider?: any;
58 | }
59 |
60 | interface PeriqlesFormProps {
61 | // eventually: this environment will accept RelayEnvironment | ApolloClient
62 | environment?: RelayEnvironment;
63 | mutationName: string;
64 | mutationGQL?: string | object;
65 | specifications?: PeriqlesSpecifications;
66 | args?: PeriqlesMutationArgs;
67 | callbacks?: PeriqlesCallbacks;
68 | useMutation?: any;
69 | }
70 |
71 | interface PeriqlesFieldProps {
72 | field: PeriqlesField;
73 | formState: FormState;
74 | handleChange: (e) => void;
75 | specs?: PeriqlesFieldSpecs;
76 | setFormState: React.Dispatch>;
77 | }
78 |
79 | // PERIQLES HELPER FUNCTIONS
80 | type GenerateDefaultElement = (params: {
81 | field: PeriqlesField,
82 | formState: FormState,
83 | handleChange: (e) => void,
84 | }) => JSX.Element;
85 |
86 | type GenerateSpecifiedElement = (params: {
87 | field: PeriqlesField,
88 | specs: PeriqlesFieldSpecs,
89 | formState: FormState,
90 | handleChange: (e) => void,
91 | setFormState: React.Dispatch>,
92 | }) => JSX.Element;
93 |
94 | // RESULT OF INTROSPECTION QUERY
95 |
96 | interface InputType {
97 | name: string;
98 | inputFields: InputField[];
99 | }
100 |
101 | interface InputField {
102 | name: string;
103 | type: GraphQLType;
104 | }
105 |
106 | interface GraphQLType {
107 | name: string;
108 | kind: string;
109 | ofType?: GraphQLOfType;
110 | enumValues?: EnumValue[];
111 | }
112 |
113 | interface GraphQLOfType {
114 | name: string;
115 | kind: string;
116 | enumValues?: EnumValue[];
117 | }
118 |
119 | // Although EnumValue's one propety is called "name", it actuallly holds a value.
120 | interface EnumValue {
121 | name: number | string;
122 | }
123 |
124 | // commitMutation parameters
125 | type Input = Record;
126 | interface Variables {
127 | input: Input;
128 | }
129 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "engines": {
4 | "node": "12.x",
5 | "npm": "6.x"
6 | },
7 | "scripts": {
8 | "tsc": "tsc --watch",
9 | "start": "NODE_ENV='development' webpack serve & nodemon -r dotenv/config server.js",
10 | "start:prod": "shx rm -rf dist && NODE_ENV='production' webpack & node -r dotenv/config server.js",
11 | "quick-start": "NODE_ENV='production' webpack & node -r dotenv/config server.js",
12 | "build:relay": "relay-compiler --src ./ts/ --schema ./data/schema.graphql --artifactDirectory ./__generated__/relay --extensions js jsx ts tsx --exclude ./__generated__/",
13 | "update-schema": "babel-node ./scripts/updateSchema.js",
14 | "install-periqles": "npm install ~/periqles-2.1.0.tgz",
15 | "lint": "eslint .",
16 | "test": "jest --verbose",
17 | "jest": "node --experimental-vm-modules node_modules/.bin/jest"
18 | },
19 | "dependencies": {
20 | "@apollo/client": "^3.3.11",
21 | "@babel/core": "^7.12.9",
22 | "@babel/node": "^7.12.6",
23 | "@babel/plugin-proposal-class-properties": "^7.12.1",
24 | "@babel/plugin-transform-runtime": "^7.12.1",
25 | "@babel/preset-env": "^7.12.17",
26 | "@babel/preset-react": "^7.12.7",
27 | "@babel/preset-typescript": "^7.12.17",
28 | "@babel/runtime": "^7.12.5",
29 | "@testing-library/jest-dom": "^5.11.9",
30 | "@types/react": "^17.0.2",
31 | "@types/react-dom": "^17.0.1",
32 | "apollo-server-express": "^2.21.0",
33 | "babel-loader": "^8.2.2",
34 | "babel-plugin-relay": "^10.1.0",
35 | "babel-plugin-transform-react-jsx-img-import": "^0.1.4",
36 | "classnames": "2.2.6",
37 | "copy-webpack-plugin": "^7.0.0",
38 | "cors": "^2.8.5",
39 | "css-loader": "^5.0.2",
40 | "dotenv": "^8.2.0",
41 | "express": "^4.16.4",
42 | "express-graphql": "^0.12.0",
43 | "file-loader": "^6.2.0",
44 | "graphql": "^15.4.0",
45 | "graphql-relay": "^0.6.0",
46 | "graphql-tag": "^2.11.0",
47 | "periqles": "^2.1.0",
48 | "react": "^17.0.1",
49 | "react-dom": "^17.0.1",
50 | "react-relay": "^10.1.0",
51 | "react-syntax-highlighter": "^15.4.3",
52 | "shx": "^0.3.3",
53 | "style-loader": "^2.0.0",
54 | "ts-graphql-plugin": "^2.1.3",
55 | "ts-loader": "^8.0.17",
56 | "webpack": "^5.0.0",
57 | "webpack-cli": "^4.5.0",
58 | "yarn": "^1.22.10"
59 | },
60 | "devDependencies": {
61 | "@babel/eslint-parser": "^7.12.17",
62 | "@testing-library/dom": "^7.29.6",
63 | "@testing-library/react": "^11.2.5",
64 | "@types/jest": "^26.0.20",
65 | "@typescript-eslint/eslint-plugin": "^4.15.1",
66 | "@typescript-eslint/parser": "^4.15.1",
67 | "babel-jest": "^26.6.3",
68 | "enzyme": "^3.11.0",
69 | "enzyme-adapter-react-16": "^1.15.6",
70 | "enzyme-to-json": "^3.6.1",
71 | "eslint": "^7.14.0",
72 | "eslint-config-fbjs": "^3.1.1",
73 | "eslint-config-prettier": "^6.15.0",
74 | "eslint-plugin-babel": "^5.3.1",
75 | "eslint-plugin-jsx-a11y": "^6.4.1",
76 | "eslint-plugin-prettier": "^3.2.0",
77 | "eslint-plugin-react": "^7.21.5",
78 | "eslint-plugin-relay": "^1.8.1",
79 | "jest": "^26.6.3",
80 | "jest-webpack-resolver": "^0.3.0",
81 | "nodemon": "^2.0.7",
82 | "prettier": "^2.2.1",
83 | "relay-compiler": "^10.1.0",
84 | "ts-jest": "^26.5.1",
85 | "typescript": "^4.1.5",
86 | "webpack-dev-server": "3.10.3",
87 | "webpack-livereload-plugin": "^2.3.0"
88 | },
89 | "prettier": {
90 | "singleQuote": true,
91 | "trailingComma": "all",
92 | "bracketSpacing": false,
93 | "jsxBracketSameLine": true
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/__generated__/relay/UserProfileQuery.graphql.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @flow
3 | */
4 |
5 | /* eslint-disable */
6 |
7 | 'use strict';
8 |
9 | /*::
10 | import type { ConcreteRequest } from 'relay-runtime';
11 | export type GenderEnum = "FEMALE" | "MALE" | "NON_BINARY" | "%future added value";
12 | export type PizzaToppingEnum = "BUFFALO_CHICKEN" | "EGGPLANT_PARM" | "HAWAIIAN" | "MEATLOVERS" | "OLIVES" | "PEPPERONI" | "%future added value";
13 | export type UserProfileQueryVariables = {||};
14 | export type UserProfileQueryResponse = {|
15 | +demoUser: ?{|
16 | +userId: string,
17 | +username: string,
18 | +password: string,
19 | +email: string,
20 | +gender: GenderEnum,
21 | +pizzaTopping: PizzaToppingEnum,
22 | +age: number,
23 | |}
24 | |};
25 | export type UserProfileQuery = {|
26 | variables: UserProfileQueryVariables,
27 | response: UserProfileQueryResponse,
28 | |};
29 | */
30 |
31 |
32 | /*
33 | query UserProfileQuery {
34 | demoUser {
35 | userId
36 | username
37 | password
38 | email
39 | gender
40 | pizzaTopping
41 | age
42 | id
43 | }
44 | }
45 | */
46 |
47 | const node/*: ConcreteRequest*/ = (function(){
48 | var v0 = {
49 | "alias": null,
50 | "args": null,
51 | "kind": "ScalarField",
52 | "name": "userId",
53 | "storageKey": null
54 | },
55 | v1 = {
56 | "alias": null,
57 | "args": null,
58 | "kind": "ScalarField",
59 | "name": "username",
60 | "storageKey": null
61 | },
62 | v2 = {
63 | "alias": null,
64 | "args": null,
65 | "kind": "ScalarField",
66 | "name": "password",
67 | "storageKey": null
68 | },
69 | v3 = {
70 | "alias": null,
71 | "args": null,
72 | "kind": "ScalarField",
73 | "name": "email",
74 | "storageKey": null
75 | },
76 | v4 = {
77 | "alias": null,
78 | "args": null,
79 | "kind": "ScalarField",
80 | "name": "gender",
81 | "storageKey": null
82 | },
83 | v5 = {
84 | "alias": null,
85 | "args": null,
86 | "kind": "ScalarField",
87 | "name": "pizzaTopping",
88 | "storageKey": null
89 | },
90 | v6 = {
91 | "alias": null,
92 | "args": null,
93 | "kind": "ScalarField",
94 | "name": "age",
95 | "storageKey": null
96 | };
97 | return {
98 | "fragment": {
99 | "argumentDefinitions": [],
100 | "kind": "Fragment",
101 | "metadata": null,
102 | "name": "UserProfileQuery",
103 | "selections": [
104 | {
105 | "alias": null,
106 | "args": null,
107 | "concreteType": "DemoUser",
108 | "kind": "LinkedField",
109 | "name": "demoUser",
110 | "plural": false,
111 | "selections": [
112 | (v0/*: any*/),
113 | (v1/*: any*/),
114 | (v2/*: any*/),
115 | (v3/*: any*/),
116 | (v4/*: any*/),
117 | (v5/*: any*/),
118 | (v6/*: any*/)
119 | ],
120 | "storageKey": null
121 | }
122 | ],
123 | "type": "Query",
124 | "abstractKey": null
125 | },
126 | "kind": "Request",
127 | "operation": {
128 | "argumentDefinitions": [],
129 | "kind": "Operation",
130 | "name": "UserProfileQuery",
131 | "selections": [
132 | {
133 | "alias": null,
134 | "args": null,
135 | "concreteType": "DemoUser",
136 | "kind": "LinkedField",
137 | "name": "demoUser",
138 | "plural": false,
139 | "selections": [
140 | (v0/*: any*/),
141 | (v1/*: any*/),
142 | (v2/*: any*/),
143 | (v3/*: any*/),
144 | (v4/*: any*/),
145 | (v5/*: any*/),
146 | (v6/*: any*/),
147 | {
148 | "alias": null,
149 | "args": null,
150 | "kind": "ScalarField",
151 | "name": "id",
152 | "storageKey": null
153 | }
154 | ],
155 | "storageKey": null
156 | }
157 | ]
158 | },
159 | "params": {
160 | "cacheID": "008d2a939fead39076a8f348e1e16a70",
161 | "id": null,
162 | "metadata": {},
163 | "name": "UserProfileQuery",
164 | "operationKind": "query",
165 | "text": "query UserProfileQuery {\n demoUser {\n userId\n username\n password\n email\n gender\n pizzaTopping\n age\n id\n }\n}\n"
166 | }
167 | };
168 | })();
169 | // prettier-ignore
170 | (node/*: any*/).hash = '580eda27b22841abb40c50c703c7ed8d';
171 |
172 | module.exports = node;
173 |
--------------------------------------------------------------------------------
/__generated__/relay/UserProfile_AddUserMutation.graphql.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @flow
3 | */
4 |
5 | /* eslint-disable */
6 |
7 | 'use strict';
8 |
9 | /*::
10 | import type { ConcreteRequest } from 'relay-runtime';
11 | export type GenderEnum = "FEMALE" | "MALE" | "NON_BINARY" | "%future added value";
12 | export type PizzaToppingEnum = "BUFFALO_CHICKEN" | "EGGPLANT_PARM" | "HAWAIIAN" | "MEATLOVERS" | "OLIVES" | "PEPPERONI" | "%future added value";
13 | export type AddUserInput = {|
14 | username: string,
15 | password: string,
16 | email: string,
17 | gender: GenderEnum,
18 | pizzaTopping: PizzaToppingEnum,
19 | age: number,
20 | clientMutationId?: ?string,
21 | |};
22 | export type UserProfile_AddUserMutationVariables = {|
23 | input: AddUserInput
24 | |};
25 | export type UserProfile_AddUserMutationResponse = {|
26 | +addUser: ?{|
27 | +userId: string,
28 | +username: string,
29 | +password: string,
30 | +email: string,
31 | +gender: GenderEnum,
32 | +pizzaTopping: PizzaToppingEnum,
33 | +age: number,
34 | |}
35 | |};
36 | export type UserProfile_AddUserMutation = {|
37 | variables: UserProfile_AddUserMutationVariables,
38 | response: UserProfile_AddUserMutationResponse,
39 | |};
40 | */
41 |
42 |
43 | /*
44 | mutation UserProfile_AddUserMutation(
45 | $input: AddUserInput!
46 | ) {
47 | addUser(input: $input) {
48 | userId
49 | username
50 | password
51 | email
52 | gender
53 | pizzaTopping
54 | age
55 | }
56 | }
57 | */
58 |
59 | const node/*: ConcreteRequest*/ = (function(){
60 | var v0 = [
61 | {
62 | "defaultValue": null,
63 | "kind": "LocalArgument",
64 | "name": "input"
65 | }
66 | ],
67 | v1 = [
68 | {
69 | "alias": null,
70 | "args": [
71 | {
72 | "kind": "Variable",
73 | "name": "input",
74 | "variableName": "input"
75 | }
76 | ],
77 | "concreteType": "AddUserPayload",
78 | "kind": "LinkedField",
79 | "name": "addUser",
80 | "plural": false,
81 | "selections": [
82 | {
83 | "alias": null,
84 | "args": null,
85 | "kind": "ScalarField",
86 | "name": "userId",
87 | "storageKey": null
88 | },
89 | {
90 | "alias": null,
91 | "args": null,
92 | "kind": "ScalarField",
93 | "name": "username",
94 | "storageKey": null
95 | },
96 | {
97 | "alias": null,
98 | "args": null,
99 | "kind": "ScalarField",
100 | "name": "password",
101 | "storageKey": null
102 | },
103 | {
104 | "alias": null,
105 | "args": null,
106 | "kind": "ScalarField",
107 | "name": "email",
108 | "storageKey": null
109 | },
110 | {
111 | "alias": null,
112 | "args": null,
113 | "kind": "ScalarField",
114 | "name": "gender",
115 | "storageKey": null
116 | },
117 | {
118 | "alias": null,
119 | "args": null,
120 | "kind": "ScalarField",
121 | "name": "pizzaTopping",
122 | "storageKey": null
123 | },
124 | {
125 | "alias": null,
126 | "args": null,
127 | "kind": "ScalarField",
128 | "name": "age",
129 | "storageKey": null
130 | }
131 | ],
132 | "storageKey": null
133 | }
134 | ];
135 | return {
136 | "fragment": {
137 | "argumentDefinitions": (v0/*: any*/),
138 | "kind": "Fragment",
139 | "metadata": null,
140 | "name": "UserProfile_AddUserMutation",
141 | "selections": (v1/*: any*/),
142 | "type": "Mutation",
143 | "abstractKey": null
144 | },
145 | "kind": "Request",
146 | "operation": {
147 | "argumentDefinitions": (v0/*: any*/),
148 | "kind": "Operation",
149 | "name": "UserProfile_AddUserMutation",
150 | "selections": (v1/*: any*/)
151 | },
152 | "params": {
153 | "cacheID": "ae10689a7b5a621a1a09d833975f7f73",
154 | "id": null,
155 | "metadata": {},
156 | "name": "UserProfile_AddUserMutation",
157 | "operationKind": "mutation",
158 | "text": "mutation UserProfile_AddUserMutation(\n $input: AddUserInput!\n) {\n addUser(input: $input) {\n userId\n username\n password\n email\n gender\n pizzaTopping\n age\n }\n}\n"
159 | }
160 | };
161 | })();
162 | // prettier-ignore
163 | (node/*: any*/).hash = '4ad681667ade44b20d61b8c3be8a43f8';
164 |
165 | module.exports = node;
166 |
--------------------------------------------------------------------------------
/ts/components/ApolloUserProfile.tsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable*/
2 | import React, {useState} from 'react';
3 | import { gql, useQuery, useMutation } from '@apollo/client';
4 | import PeriqlesForm from 'periqles';
5 | import { PrismLight as SyntaxHighlighter } from 'react-syntax-highlighter';
6 | import jsx from 'react-syntax-highlighter/dist/esm/languages/prism/jsx';
7 | import js from 'react-syntax-highlighter/dist/esm/languages/prism/graphql';
8 | import {vscDarkPlus} from 'react-syntax-highlighter/dist/esm/styles/prism';
9 |
10 | SyntaxHighlighter.registerLanguage('jsx', jsx);
11 | SyntaxHighlighter.registerLanguage('js', js);
12 |
13 | export const USER_DATA = gql`
14 | fragment UserData on DemoUser {
15 | username
16 | password
17 | email
18 | gender
19 | pizzaTopping
20 | age
21 | }
22 | `;
23 |
24 | export const GET_USER = gql`
25 | query DemoUser {
26 | demoUser {
27 | ...UserData
28 | }
29 | }
30 | ${USER_DATA}
31 | `;
32 |
33 | export const ADD_USER = gql`
34 | mutation AddUser($input: AddUserInput!){
35 | addUser(input: $input){
36 | username
37 | email
38 | gender
39 | pizzaTopping
40 | age
41 | }
42 | }
43 | `;
44 |
45 | const ApolloUserProfile = () => {
46 | const [updated, setUpdate] = useState(false);
47 | const {
48 | data,
49 | loading,
50 | error,
51 | refetch
52 | } = useQuery(GET_USER);
53 | const [
54 | addUser,
55 | respObj
56 | ] = useMutation(
57 | ADD_USER,
58 | );
59 |
60 | const specifications: PeriqlesSpecifications = {
61 | header: 'Sign Up',
62 | fields: {
63 | gender: {
64 | element: 'radio',
65 | label: 'Gender',
66 | options: [
67 | {label: 'Non-binary', value: 'NON_BINARY'},
68 | {label: 'Male', value: 'MALE'},
69 | {label: 'Female', value: 'FEMALE'},
70 | ],
71 | },
72 | pizzaTopping: {
73 | label: 'Favorite pizza topping:',
74 | element: 'select',
75 | options: [
76 | {label: 'Buffalo chicken', value: 'BUFFALO_CHICKEN'},
77 | {label: 'Pepperoni', value: 'PEPPERONI'},
78 | {label: 'Meat lovers', value: 'MEATLOVERS'},
79 | {label: 'Eggplant parmesan', value: 'EGGPLANT_PARM'},
80 | {label: 'Olives', value: 'OLIVES'},
81 | {label: 'Hawaiian', value: 'HAWAIIAN'},
82 | ],
83 | },
84 | },
85 | };
86 |
87 | const args = {clientMutationId: '0000'};
88 |
89 | const onSuccess = (response) => {
90 | refetch(GET_USER);
91 | };
92 |
93 | const onFailure = (error) => {
94 | alert(`Problem submitting form: ${error.toString()}`);
95 | };
96 |
97 | const renderUser = (demoUser) => {
98 | return (
99 |
100 |
Username: {demoUser.username}
101 |
Email: {demoUser.email}
102 |
Gender: {demoUser.gender}
103 |
Favorite Pizza Topping: {demoUser.pizzaTopping}
104 |
Age: {demoUser.age}
105 |
106 | )
107 | }
108 |
109 | return (
110 |
111 |
112 |
119 |
120 | Most Recently Added User
121 | {loading ? Loading data...
: null}
122 | {error ? ERROR: {JSON.stringify(error)}
: null}
123 | {data && data.demoUser ? renderUser(data.demoUser): Sign up...
}
124 |
125 |
126 |
127 | Apollo Code Examples
128 |
129 |
130 | Mutation Schema
131 |
132 | {"mutation AddUser($input: AddUserInput!){\n"+
133 | " addUser(input: $input) {\n"+
134 | " username\n"+
135 | " password\n"+
136 | " email\n"+
137 | " gender\n"+
138 | " pizzaTopping\n"+
139 | " age\n"+
140 | " }\n"+
141 | "}"}
142 |
143 |
144 |
145 | PeriqlesForm Tag
146 |
147 | {" \n"+
154 | "\n"+
155 | "\n"}
156 |
157 |
158 |
159 |
160 |
161 | );
162 | };
163 |
164 | export default ApolloUserProfile;
165 |
--------------------------------------------------------------------------------
/ts/components/relay/UserProfile.tsx:
--------------------------------------------------------------------------------
1 | import React, {useState} from 'react';
2 | import {QueryRenderer, graphql} from 'react-relay';
3 | import {Environment, Network, RecordSource, Store} from 'relay-runtime';
4 | import PeriqlesForm from 'periqles';
5 | import { PrismLight as SyntaxHighlighter } from 'react-syntax-highlighter';
6 | import jsx from 'react-syntax-highlighter/dist/esm/languages/prism/jsx';
7 | import js from 'react-syntax-highlighter/dist/esm/languages/prism/graphql';
8 | import {vscDarkPlus} from 'react-syntax-highlighter/dist/esm/styles/prism';
9 |
10 | SyntaxHighlighter.registerLanguage('jsx', jsx);
11 | SyntaxHighlighter.registerLanguage('js', js);
12 | interface QueryResponse {
13 | demoUser?: Record;
14 | }
15 |
16 | const UserProfile = (): JSX.Element => {
17 | const [updated, setUpdate] = useState(false);
18 |
19 | async function fetchQuery(operation, variables): Promise<{}> {
20 | const response = await fetch('/graphql', {
21 | method: 'POST',
22 | headers: {
23 | 'Content-Type': 'application/json',
24 | },
25 | body: JSON.stringify({
26 | query: operation.text,
27 | variables,
28 | }),
29 | });
30 |
31 | return response.json();
32 | }
33 |
34 | const modernEnvironment: Environment = new Environment({
35 | network: Network.create(fetchQuery),
36 | store: new Store(new RecordSource()),
37 | });
38 |
39 | const mutationGQL = graphql`
40 | mutation UserProfile_AddUserMutation($input: AddUserInput!) {
41 | addUser(input: $input) {
42 | userId
43 | username
44 | password
45 | email
46 | gender
47 | pizzaTopping
48 | age
49 | }
50 | }
51 | `;
52 |
53 | const specifications: PeriqlesSpecifications = {
54 | header: 'Sign Up',
55 | fields: {
56 | gender: {
57 | element: 'radio',
58 | label: 'Gender',
59 | options: [
60 | {label: 'Non-binary', value: 'NON_BINARY'},
61 | {label: 'Male', value: 'MALE'},
62 | {label: 'Female', value: 'FEMALE'},
63 | ],
64 | },
65 | pizzaTopping: {
66 | label: 'Favorite pizza topping',
67 | element: 'select',
68 | options: [
69 | {label: 'Buffalo chicken', value: 'BUFFALO_CHICKEN'},
70 | {label: 'Pepperoni', value: 'PEPPERONI'},
71 | {label: 'Meat lovers', value: 'MEATLOVERS'},
72 | {label: 'Eggplant parmesan', value: 'EGGPLANT_PARM'},
73 | {label: 'Olives', value: 'OLIVES'},
74 | {label: 'Hawaiian', value: 'HAWAIIAN'},
75 | ],
76 | },
77 | },
78 | };
79 |
80 | const onSuccess = (response) => {
81 | setUpdate(!updated);
82 | };
83 |
84 | const onFailure = (error) => {
85 | alert(`Problem submitting form: ${error.toString()}`);
86 | };
87 |
88 | const args = {clientMutationId: '0000'};
89 |
90 | return (
91 |
92 |
93 |
101 |
102 | Most Recently Added User
103 | {
119 | if (props && !props.demoUser) {
120 | return Sign up...
;
121 | }
122 | if (props && props.demoUser) {
123 | const {demoUser} = props;
124 | return (
125 |
126 |
Username: {demoUser.username}
127 |
Email: {demoUser.email}
128 |
Gender: {demoUser.gender}
129 |
Favorite Pizza Topping: {demoUser.pizzaTopping}
130 |
Age: {demoUser.age}
131 |
132 | );
133 | } else if (error) {
134 | console.error(error);
135 | return Something went wrong...
;
136 | }
137 |
138 | return Loading...
;
139 | }}
140 | />
141 |
142 |
143 |
144 | Relay Code Examples
145 |
146 |
147 | Mutation Schema
148 |
149 | {"mutation UserProfile_AddUserMutation($input: AddUserInput!) {\n"+
150 | " addUser(input: $input) {\n"+
151 | " userId\n"+
152 | " username\n"+
153 | " password\n"+
154 | " email\n"+
155 | " gender\n"+
156 | " pizzaTopping\n"+
157 | " age\n"+
158 | " }\n"+
159 | "}"}
160 |
161 |
162 |
163 | PeriqlesForm Tag
164 |
165 | {" \n"+
173 | "\n"+
174 | "\n"}
175 |
176 |
177 |
178 |
179 |
180 | );
181 | };
182 |
183 | export default UserProfile;
184 |
--------------------------------------------------------------------------------
/public/index.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'FV Almelo';
3 | src: url('FVAlmelo.woff2') format('woff2'),
4 | url('FVAlmelo.woff') format('woff'),
5 | url('FVAlmelo.ttf') format('truetype');
6 | font-weight: 500;
7 | font-style: normal;
8 | font-display: swap;
9 | }
10 |
11 | html,
12 | body, #root {
13 | margin: 0;
14 | padding: 0;
15 | width: 100%;
16 | height: 100%;
17 | }
18 |
19 |
20 | body {
21 | font: 18px 'Helvetica Neue', Helvetica, Arial, sans-serif;
22 | line-height: 1.4em;
23 | background: #ffffff;
24 | color: black;
25 | -webkit-font-smoothing: antialiased;
26 | -moz-osx-font-smoothing: grayscale;
27 | font-weight: 400;
28 | position: relative;
29 | }
30 |
31 | body * {
32 | box-sizing: border-box;
33 | }
34 |
35 | button {
36 | margin: 0;
37 | padding: 0;
38 | border: 0;
39 | width: 100%;
40 | background: none;
41 | font-size: 100%;
42 | vertical-align: baseline;
43 | font-family: inherit;
44 | font-weight: inherit;
45 | color: inherit;
46 | -webkit-appearance: none;
47 | appearance: none;
48 | -webkit-font-smoothing: antialiased;
49 | -moz-osx-font-smoothing: grayscale;
50 | background-color: #C9E465;
51 | color: black;
52 | }
53 |
54 | button:hover {
55 | background-color: #b1c955;
56 | color: white;
57 | }
58 |
59 | header {
60 | font-family: 'FVAlmelo', Helvetica, Arial, sans-serif;
61 | background-color: black;
62 | color: #b1c955;
63 | margin: 0;
64 | padding: 25px 50px;
65 | height: 75px;
66 | position: fixed;
67 | right: 0;
68 | left: 0;
69 | z-index: 999;
70 | }
71 |
72 | header h1 {
73 | margin: 0;
74 | text-align: right;
75 | color: #b1c955;
76 | }
77 |
78 | header a, footer a {
79 | color: inherit;
80 | text-decoration: none;
81 | }
82 |
83 | header a:hover, footer a:hover {
84 | color: white;
85 | }
86 |
87 | a {
88 | color: inherit;
89 | }
90 |
91 | a:visited {
92 | color: inherit;
93 | }
94 |
95 | .LogoSection {
96 | background-color: black;
97 | color: white;
98 | padding: 75px 30px 30px 30px;
99 | width: 100vw;
100 | height: 85vh;
101 | display: flex;
102 | flex-direction: column;
103 | justify-content: center;
104 | align-items: center;
105 | }
106 |
107 | #periqles-logo {
108 | width: 90%;
109 | max-width: 500px;
110 | }
111 |
112 | .LinksSection {
113 | background-color: #b1c955;
114 | color: white;
115 | padding: 30px;
116 | width: 100vw;
117 | min-height: 400px;
118 | display: flex;
119 | flex-direction: column;
120 | align-items: center;
121 | }
122 |
123 | #long-pitch {
124 | margin-top: 100px;
125 | }
126 |
127 | .repo-logos {
128 | display: flex;
129 | flex-direction: row;
130 | align-items: center;
131 | }
132 |
133 | .marketing-logo {
134 | margin: 0 10px;
135 | }
136 |
137 | .Demo {
138 | width: 100%;
139 | margin: 0 auto 50px auto;
140 | padding: 10px;
141 | text-align: center;
142 | }
143 |
144 | .UserProfile {
145 | margin-top: 50px;
146 | display: flex;
147 | flex-direction: column;
148 | justify-content: space-around;
149 | align-items: center;
150 | }
151 |
152 | .PeriqlesForm {
153 | border: 1px solid rgba(0, 0, 0, 0.16);
154 | width: 90%;
155 | }
156 |
157 | .PeriqlesForm, .PeriqlesForm * {
158 | border-radius: 10px;
159 | }
160 |
161 | /* one method to hide label text */
162 | /* .PeriqlesForm label:not(.periqles-radio-option-label) {
163 | color:white;
164 | } */
165 |
166 | .UserProfile-main {
167 | text-align:left;
168 | margin-top: 20px;
169 | border: 1px solid rgba(0, 0, 0, 0.16);
170 | border-radius: 10px;
171 | padding: 4%;
172 | }
173 |
174 | .UserProfile-main label {
175 | font-weight: bold;
176 | }
177 |
178 | .CodeDemo {
179 | background-color: #b1c955;
180 | color: white;
181 | display: flex;
182 | flex-direction: column;
183 | align-items: center;
184 | margin-top: 75px;
185 | }
186 |
187 | .CodeDemo h1 {
188 | margin-block-start: 0.75em;
189 | margin-block-end: 0.25em;
190 | }
191 |
192 | .CodeDemo h3 {
193 | margin-block-end: 0;
194 | }
195 |
196 | .Codeblocks {
197 | display: flex;
198 | flex-direction: column;
199 | justify-content: space-evenly;
200 | align-items: center;
201 | width: 100%;
202 | padding: 10px 10px 20px 10px;
203 | }
204 |
205 | .SchemaCode, .PeriqlesCode {
206 | width: 90%;
207 | max-width: 750px;
208 | overflow-x: auto;
209 | }
210 |
211 | footer {
212 | font-family: 'FVAlmelo', Helvetica, Arial, sans-serif;
213 | background-color: black;
214 | color: #C9E465;
215 | margin: 0;
216 | padding: 25px;
217 | height: auto;
218 | width: 100%;
219 | text-align: center;
220 | }
221 |
222 | h1 {
223 | font-size: 36px;
224 | line-height: 45px;
225 | }
226 |
227 | h2 {
228 | font-size: 28px;
229 | line-height: 35px;
230 | }
231 |
232 | /* Relay/Apollo toggle */
233 | /* The switch - the box around the slider */
234 | .switch {
235 | position: relative;
236 | display: inline-block;
237 | width: 60px;
238 | height: 34px;
239 | margin: 0 10px;
240 | }
241 |
242 | /* Hide default HTML checkbox */
243 | .switch input {
244 | opacity: 0;
245 | width: 0;
246 | height: 0;
247 | }
248 |
249 | /* The slider */
250 | .slider {
251 | position: absolute;
252 | cursor: pointer;
253 | top: 0;
254 | left: 0;
255 | right: 0;
256 | bottom: 0;
257 | background-color: #b1c955;
258 | -webkit-transition: .4s;
259 | transition: .4s;
260 | }
261 |
262 | .slider:before {
263 | position: absolute;
264 | content: "";
265 | height: 26px;
266 | width: 26px;
267 | left: 4px;
268 | bottom: 4px;
269 | background-color: white;
270 | -webkit-transition: .4s;
271 | transition: .4s;
272 | }
273 |
274 | input:checked + .slider {
275 | background-color: #C9E465;
276 | }
277 |
278 | input:focus + .slider {
279 | box-shadow: 0 0 1px #b1c955;
280 | }
281 |
282 | input:checked + .slider:before {
283 | -webkit-transform: translateX(26px);
284 | -ms-transform: translateX(26px);
285 | transform: translateX(26px);
286 | }
287 |
288 | /* Rounded sliders */
289 | .slider.round {
290 | border-radius: 34px;
291 | }
292 |
293 | .slider.round:before {
294 | border-radius: 50%;
295 | }
296 |
297 | @media (min-width: 700px) {
298 | button {
299 | width: fit-content;
300 | }
301 |
302 | .LogoSection, .LinksSection {
303 | flex-direction: row;
304 | justify-content: space-evenly;
305 | padding: 30px 15%;
306 | }
307 |
308 | .Demo {
309 | padding: 30px;
310 | }
311 |
312 | #periqles-logo {
313 | width: 40%;
314 | }
315 |
316 | #short-pitch, #long-pitch {
317 | max-width: 500px;
318 | }
319 |
320 | #short-pitch {
321 | margin-left: 40px;
322 | }
323 |
324 | #long-pitch {
325 | margin-right: 40px;
326 | margin-top: 10px;
327 | }
328 |
329 | .marketing-logo {
330 | margin: 0 20px;
331 | }
332 |
333 | .UserProfile {
334 | flex-direction: row;
335 | justify-content: space-evenly;
336 | align-items: flex-start;
337 | }
338 |
339 | .PeriqlesForm {
340 | width: 500px;
341 | margin-right: 30px;
342 | }
343 |
344 | .UserProfile-main {
345 | margin: 0;
346 | }
347 |
348 | footer {
349 | text-align: left;
350 | padding: 30px 15%;
351 | }
352 | }
353 |
354 | @media (min-width: 1690px) {
355 | .Codeblocks {
356 | height: 440px;
357 | flex-direction: row;
358 | justify-content: space-evenly;
359 | align-items: center;
360 | padding: 30px 30px 60px 30px;
361 | }
362 |
363 | .SchemaCode {
364 | margin-right: 30px;
365 | }
366 | }
--------------------------------------------------------------------------------
/types/react-relay_types.js:
--------------------------------------------------------------------------------
1 | // flow-typed signature: 311012da78555b97190c86fa4c196bf3
2 | // flow-typed version: 443dcee08c/react-relay_v1.x.x/flow_>=v0.47.x
3 |
4 | // https://raw.githubusercontent.com/mrtnzlml/quick-payments/8a0fa46a490647aec676fc823c88079e8319dee5/frontend/flow-typed/npm/react-relay_v1.x.x.js
5 |
6 | import * as React from 'react';
7 |
8 | import {FragmentReference} from 'relay-runtime';
9 |
10 | declare module 'react-relay' {
11 | declare export type RecordState = 'EXISTENT' | 'NONEXISTENT' | 'UNKNOWN';
12 |
13 | declare export type onCompleted = (
14 | response: ?Object,
15 | errors: ?Array,
16 | ) => void;
17 | declare export type onError = (error: Error) => void;
18 |
19 | declare export type CommitOptions = {
20 | onCompleted: onCompleted,
21 | onError: onError,
22 | };
23 |
24 | /**
25 | * Ideally this would be a union of Field/Fragment/Mutation/Query/Subscription,
26 | * but that causes lots of Flow errors.
27 | */
28 | declare export type ConcreteBatchCallVariable = {
29 | jsonPath: string,
30 | kind: 'BatchCallVariable',
31 | sourceQueryID: string,
32 | };
33 | declare export type ConcreteCall = {
34 | kind: 'Call',
35 | metadata: {
36 | type?: ?string,
37 | },
38 | name: string,
39 | value: ?ConcreteValue,
40 | };
41 | declare export type ConcreteCallValue = {
42 | callValue: mixed,
43 | kind: 'CallValue',
44 | };
45 | declare export type ConcreteCallVariable = {
46 | callVariableName: string,
47 | kind: 'CallVariable',
48 | };
49 | declare export type ConcreteDirective = {
50 | args: Array,
51 | kind: 'Directive',
52 | name: string,
53 | };
54 | declare export type ConcreteDirectiveArgument = {
55 | name: string,
56 | value: ?ConcreteDirectiveValue,
57 | };
58 | declare export type ConcreteDirectiveValue =
59 | | ConcreteCallValue
60 | | ConcreteCallVariable
61 | | Array;
62 | declare export type ConcreteFieldMetadata = {
63 | canHaveSubselections?: ?boolean,
64 | inferredPrimaryKey?: ?string,
65 | inferredRootCallName?: ?string,
66 | isAbstract?: boolean,
67 | isConnection?: boolean,
68 | isConnectionWithoutNodeID?: boolean,
69 | isFindable?: boolean,
70 | isGenerated?: boolean,
71 | isPlural?: boolean,
72 | isRequisite?: boolean,
73 | };
74 | declare export type ConcreteFragmentMetadata = {
75 | isAbstract?: boolean,
76 | pattern?: boolean,
77 | plural?: boolean,
78 | };
79 | declare export type ConcreteMutation = {
80 | calls: Array,
81 | children?: ?Array,
82 | directives?: ?Array,
83 | kind: 'Mutation',
84 | metadata: {
85 | inputType?: ?string,
86 | },
87 | name: string,
88 | responseType: string,
89 | };
90 | declare export type ConcreteOperationMetadata = {
91 | inputType?: ?string,
92 | };
93 | declare export type ConcreteQuery = {
94 | calls?: ?Array,
95 | children?: ?Array,
96 | directives?: ?Array,
97 | fieldName: string,
98 | isDeferred?: boolean,
99 | kind: 'Query',
100 | metadata: {
101 | identifyingArgName?: ?string,
102 | identifyingArgType?: ?string,
103 | isAbstract?: ?boolean,
104 | isPlural?: ?boolean,
105 | },
106 | name: string,
107 | type: string,
108 | };
109 | declare export type ConcreteQueryMetadata = {
110 | identifyingArgName: ?string,
111 | identifyingArgType: ?string,
112 | isAbstract: ?boolean,
113 | isDeferred: ?boolean,
114 | isPlural: ?boolean,
115 | };
116 | declare export type ConcreteSubscription = {
117 | calls: Array,
118 | children?: ?Array,
119 | directives?: ?Array,
120 | kind: 'Subscription',
121 | name: string,
122 | responseType: string,
123 | metadata: {
124 | inputType?: ?string,
125 | },
126 | };
127 | declare export type ConcreteValue =
128 | | ConcreteBatchCallVariable
129 | | ConcreteCallValue
130 | | ConcreteCallVariable
131 | | Array;
132 |
133 | /**
134 | * The output of a graphql-tagged fragment definition.
135 | */
136 | declare export type ConcreteFragmentDefinition = {
137 | kind: 'FragmentDefinition',
138 | argumentDefinitions: Array,
139 | node: ConcreteFragment,
140 | };
141 |
142 | declare export type ConcreteLocalArgumentDefinition = {
143 | kind: 'LocalArgument',
144 | name: string,
145 | defaultValue: mixed,
146 | };
147 |
148 | declare export type ConcreteRootArgumentDefinition = {
149 | kind: 'RootArgument',
150 | name: string,
151 | };
152 |
153 | /**
154 | * The output of a graphql-tagged operation definition.
155 | */
156 | declare export type ConcreteOperationDefinition = {
157 | kind: 'OperationDefinition',
158 | argumentDefinitions: Array,
159 | name: string,
160 | operation: 'mutation' | 'query' | 'subscription',
161 | node: ConcreteFragment | ConcreteMutation | ConcreteSubscription,
162 | };
163 |
164 | declare export type ConcreteArgument = ConcreteLiteral | ConcreteVariable;
165 | declare export type ConcreteArgumentDefinition =
166 | | ConcreteLocalArgument
167 | | ConcreteRootArgument;
168 | /**
169 | * Represents a single ConcreteRoot along with metadata for processing it at
170 | * runtime. The persisted `id` (or `text`) can be used to fetch the query,
171 | * the `fragment` can be used to read the root data (masking data from child
172 | * fragments), and the `query` can be used to normalize server responses.
173 | *
174 | * NOTE: The use of "batch" in the name is intentional, as this wrapper around
175 | * the ConcreteRoot will provide a place to store multiple concrete nodes that
176 | * are part of the same batch, e.g. in the case of deferred nodes or
177 | * for streaming connections that are represented as distinct concrete roots but
178 | * are still conceptually tied to one source query.
179 | */
180 | declare export type ConcreteBatch = {
181 | kind: 'Batch',
182 | fragment: ConcreteFragment,
183 | id: ?string,
184 | metadata: {[key: string]: mixed},
185 | name: string,
186 | query: ConcreteRoot,
187 | text: ?string,
188 | };
189 | declare export type ConcreteCondition = {
190 | kind: 'Condition',
191 | passingValue: boolean,
192 | condition: string,
193 | selections: Array,
194 | };
195 | declare export type ConcreteField = ConcreteScalarField | ConcreteLinkedField;
196 | declare export type ConcreteFragment = {
197 | argumentDefinitions: Array,
198 | kind: 'Fragment',
199 | metadata: ?{[key: string]: mixed},
200 | name: string,
201 | selections: Array,
202 | type: string,
203 | };
204 | declare export type ConcreteFragmentSpread = {
205 | args: ?Array,
206 | kind: 'FragmentSpread',
207 | name: string,
208 | };
209 | declare export type ConcreteHandle =
210 | | ConcreteScalarHandle
211 | | ConcreteLinkedHandle;
212 | declare export type ConcreteRootArgument = {
213 | kind: 'RootArgument',
214 | name: string,
215 | type: ?string,
216 | };
217 | declare export type ConcreteInlineFragment = {
218 | kind: 'InlineFragment',
219 | selections: Array,
220 | type: string,
221 | };
222 | declare export type ConcreteLinkedField = {
223 | alias: ?string,
224 | args: ?Array,
225 | concreteType: ?string,
226 | kind: 'LinkedField',
227 | name: string,
228 | plural: boolean,
229 | selections: Array,
230 | storageKey: ?string,
231 | };
232 | declare export type ConcreteLinkedHandle = {
233 | alias: ?string,
234 | args: ?Array,
235 | kind: 'LinkedHandle',
236 | name: string,
237 | handle: string,
238 | key: string,
239 | filters: ?Array,
240 | };
241 | declare export type ConcreteLiteral = {
242 | kind: 'Literal',
243 | name: string,
244 | type: ?string,
245 | value: mixed,
246 | };
247 | declare export type ConcreteLocalArgument = {
248 | defaultValue: mixed,
249 | kind: 'LocalArgument',
250 | name: string,
251 | type: string,
252 | };
253 | declare export type ConcreteNode =
254 | | ConcreteCondition
255 | | ConcreteLinkedField
256 | | ConcreteFragment
257 | | ConcreteInlineFragment
258 | | ConcreteRoot;
259 | declare export type ConcreteRoot = {
260 | argumentDefinitions: Array,
261 | kind: 'Root',
262 | name: string,
263 | operation: 'mutation' | 'query' | 'subscription',
264 | selections: Array,
265 | };
266 | declare export type ConcreteScalarField = {
267 | alias: ?string,
268 | args: ?Array,
269 | kind: 'ScalarField',
270 | name: string,
271 | storageKey: ?string,
272 | };
273 | declare export type ConcreteScalarHandle = {
274 | alias: ?string,
275 | args: ?Array,
276 | kind: 'ScalarHandle',
277 | name: string,
278 | handle: string,
279 | key: string,
280 | filters: ?Array,
281 | };
282 | declare export type ConcreteSelection =
283 | | ConcreteCondition
284 | | ConcreteField
285 | | ConcreteFragmentSpread
286 | | ConcreteHandle
287 | | ConcreteInlineFragment;
288 | declare export type ConcreteVariable = {
289 | kind: 'Variable',
290 | name: string,
291 | type: ?string,
292 | variableName: string,
293 | };
294 | declare export type ConcreteSelectableNode = ConcreteFragment | ConcreteRoot;
295 | declare export type GeneratedNode = ConcreteBatch | ConcreteFragment;
296 |
297 | // The type of a graphql`...` tagged template expression.
298 | declare export type GraphQLTaggedNode =
299 | | (() => ConcreteFragment | ConcreteBatch)
300 | | {
301 | modern: () => ConcreteFragment | ConcreteBatch,
302 | classic: () => ConcreteFragmentDefinition | ConcreteOperationDefinition,
303 | };
304 |
305 | declare export function graphql(strings: Array): GraphQLTaggedNode;
306 |
307 | declare export type GeneratedNodeMap = {[key: string]: GraphQLTaggedNode};
308 |
309 | declare export type RelayProp = {
310 | environment: Environment,
311 | };
312 |
313 | declare export type $FragmentRef = {
314 | +$fragmentRefs: $PropertyType,
315 | };
316 |
317 | // prettier-ignore
318 | declare export type $RelayProps = $ObjMap<
319 | $Diff,
320 | & (( T) => T)
321 | & ((?T) => ?T)
322 | & (( T ) => $FragmentRef )
323 | & ((? T ) => ? $FragmentRef )
324 | & (( $ReadOnlyArray< T>) => $ReadOnlyArray< $FragmentRef>)
325 | & ((?$ReadOnlyArray< T>) => ?$ReadOnlyArray< $FragmentRef>)
326 | & (( $ReadOnlyArray) => $ReadOnlyArray$FragmentRef>)
327 | & ((?$ReadOnlyArray) => ?$ReadOnlyArray$FragmentRef>)
328 | & ((T) => T),
329 | >
330 |
331 | declare export function createFragmentContainer<
332 | Props: {},
333 | TComponent: React$ComponentType,
334 | >(
335 | Component: TComponent,
336 | fragmentSpec: GeneratedNodeMap,
337 | ): React$ComponentType<
338 | $RelayProps, RelayProp>,
339 | >;
340 |
341 | declare export function createRefetchContainer<
342 | Props: {},
343 | TComponent: React$ComponentType,
344 | >(
345 | Component: TComponent,
346 | fragmentSpec: GeneratedNodeMap,
347 | taggedNode: GraphQLTaggedNode,
348 | ): React$ComponentType<
349 | $RelayProps, RelayRefetchProp>,
350 | >;
351 |
352 | declare type FragmentVariablesGetter = (
353 | prevVars: Variables,
354 | totalCount: number,
355 | ) => Variables;
356 |
357 | declare export type PageInfo = {
358 | endCursor: ?string,
359 | hasNextPage: boolean,
360 | hasPreviousPage: boolean,
361 | startCursor: ?string,
362 | };
363 |
364 | declare export type ConnectionData = {
365 | edges?: ?Array,
366 | pageInfo?: ?PageInfo,
367 | };
368 |
369 | declare export type ConnectionConfig = {
370 | direction?: 'backward' | 'forward',
371 | getConnectionFromProps?: (props: Object) => ?ConnectionData,
372 | getFragmentVariables?: FragmentVariablesGetter,
373 | getVariables: (
374 | props: Object,
375 | paginationInfo: {count: number, cursor: ?string},
376 | fragmentVariables: Variables,
377 | ) => Variables,
378 | query: GraphQLTaggedNode,
379 | };
380 |
381 | declare export function createPaginationContainer<
382 | Props: {},
383 | TComponent: React$ComponentType,
384 | >(
385 | Component: TComponent,
386 | fragmentSpec: GeneratedNodeMap,
387 | connectionConfig: ConnectionConfig,
388 | ): React$ComponentType<
389 | $RelayProps, RelayPaginationProp>,
390 | >;
391 |
392 | declare type Variable =
393 | | string
394 | | null
395 | | boolean
396 | | number
397 | | Variables
398 | | void
399 | | Array
400 | | {};
401 | declare export type Variables = ?{[string]: Variable};
402 | declare export type DataID = string;
403 |
404 | declare type TEnvironment = Environment;
405 | declare type TFragment = ConcreteFragment;
406 | declare type TGraphQLTaggedNode = GraphQLTaggedNode;
407 | declare type TNode = ConcreteSelectableNode;
408 | declare export type TOperation = ConcreteBatch;
409 | declare type TPayload = RelayResponsePayload;
410 |
411 | declare export type FragmentMap = CFragmentMap;
412 | declare export type OperationSelector = COperationSelector;
413 | declare export type RelayContext = CRelayContext;
414 | declare export type Selector = CSelector;
415 | declare export type TSnapshot = CSnapshot;
416 | declare export type Snapshot = TSnapshot;
417 | declare export type ProxySnapshot = TSnapshot;
418 | declare export type UnstableEnvironmentCore = CUnstableEnvironmentCore<
419 | TEnvironment,
420 | TFragment,
421 | TGraphQLTaggedNode,
422 | TNode,
423 | TOperation,
424 | >;
425 |
426 | declare export interface IRecordSource {
427 | get(dataID: DataID): ?TRecord;
428 | }
429 |
430 | /**
431 | * A read-only interface for accessing cached graph data.
432 | */
433 | declare export interface RecordSource extends IRecordSource {
434 | get(dataID: DataID): ?Record;
435 |
436 | getRecordIDs(): Array;
437 |
438 | getStatus(dataID: DataID): RecordState;
439 |
440 | has(dataID: DataID): boolean;
441 |
442 | load(
443 | dataID: DataID,
444 | callback: (error: ?Error, record: ?Record) => void,
445 | ): void;
446 |
447 | size(): number;
448 | }
449 |
450 | /**
451 | * A read/write interface for accessing and updating graph data.
452 | */
453 | declare export interface MutableRecordSource extends RecordSource {
454 | clear(): void;
455 |
456 | delete(dataID: DataID): void;
457 |
458 | remove(dataID: DataID): void;
459 |
460 | set(dataID: DataID, record: Record): void;
461 | }
462 |
463 | /**
464 | * An interface for keeping multiple views of data consistent across an
465 | * application.
466 | */
467 | declare export interface Store {
468 | /**
469 | * Get a read-only view of the store's internal RecordSource.
470 | */
471 | getSource(): RecordSource;
472 |
473 | /**
474 | * Determine if the selector can be resolved with data in the store (i.e. no
475 | * fields are missing).
476 | */
477 | check(selector: Selector): boolean;
478 |
479 | /**
480 | * Read the results of a selector from in-memory records in the store.
481 | */
482 | lookup(selector: Selector): Snapshot;
483 |
484 | /**
485 | * Notify subscribers (see `subscribe`) of any data that was published
486 | * (`publish()`) since the last time `notify` was called.
487 | */
488 | notify(): void;
489 |
490 | /**
491 | * Publish new information (e.g. from the network) to the store, updating its
492 | * internal record source. Subscribers are not immediately notified - this
493 | * occurs when `notify()` is called.
494 | */
495 | publish(source: RecordSource): void;
496 |
497 | /**
498 | * Attempts to load all the records necessary to fulfill the selector into the
499 | * target record source.
500 | */
501 | resolve(
502 | target: MutableRecordSource,
503 | selector: Selector,
504 | callback: AsyncLoadCallback,
505 | ): void;
506 |
507 | /**
508 | * Ensure that all the records necessary to fulfill the given selector are
509 | * retained in-memory. The records will not be eligible for garbage collection
510 | * until the returned reference is disposed.
511 | */
512 | retain(selector: Selector): Disposable;
513 |
514 | /**
515 | * Subscribe to changes to the results of a selector. The callback is called
516 | * when `notify()` is called *and* records have been published that affect the
517 | * selector results relative to the last `notify()`.
518 | */
519 | subscribe(
520 | snapshot: Snapshot,
521 | callback: (snapshot: Snapshot) => void,
522 | ): Disposable;
523 | }
524 |
525 | /**
526 | * An interface for imperatively getting/setting properties of a `Record`. This interface
527 | * is designed to allow the appearance of direct Record manipulation while
528 | * allowing different implementations that may e.g. create a changeset of
529 | * the modifications.
530 | */
531 | declare export interface RecordProxy {
532 | copyFieldsFrom(source: RecordProxy): void;
533 |
534 | getDataID(): DataID;
535 |
536 | getLinkedRecord(name: string, args?: ?Variables): RecordProxy;
537 |
538 | getLinkedRecords(name: string, args?: ?Variables): ?Array;
539 |
540 | getOrCreateLinkedRecord(
541 | name: string,
542 | typeName: string,
543 | args?: ?Variables,
544 | ): RecordProxy;
545 |
546 | getType(): string;
547 |
548 | getValue(name: string, args?: ?Variables): mixed;
549 |
550 | setLinkedRecord(
551 | record: RecordProxy,
552 | name: string,
553 | args?: ?Variables,
554 | ): RecordProxy;
555 |
556 | setLinkedRecords(
557 | records: Array,
558 | name: string,
559 | args?: ?Variables,
560 | ): RecordProxy;
561 |
562 | setValue(value: mixed, name: string, args?: ?Variables): RecordProxy;
563 | }
564 |
565 | /**
566 | * An interface for imperatively getting/setting properties of a `RecordSource`. This interface
567 | * is designed to allow the appearance of direct RecordSource manipulation while
568 | * allowing different implementations that may e.g. create a changeset of
569 | * the modifications.
570 | */
571 | declare export interface RecordSourceProxy
572 | extends IRecordSource {
573 | create(dataID: DataID, typeName: string): RecordProxy;
574 |
575 | delete(dataID: DataID): void;
576 |
577 | get(dataID: DataID): ?RecordProxy;
578 |
579 | getRoot(): RecordProxy;
580 | }
581 |
582 | /**
583 | * Extends the RecordSourceProxy interface with methods for accessing the root
584 | * fields of a Selector.
585 | */
586 | declare export interface RecordSourceSelectorProxy
587 | extends IRecordSource {
588 | create(dataID: DataID, typeName: string): RecordProxy;
589 |
590 | delete(dataID: DataID): void;
591 |
592 | get(dataID: DataID): ?RecordProxy;
593 |
594 | getRoot(): RecordProxy;
595 |
596 | getRootField(fieldName: string): RecordProxy;
597 |
598 | getPluralRootField(fieldName: string): ?Array;
599 |
600 | getResponse(): ?Object;
601 | }
602 |
603 | declare export interface IRecordReader {
604 | getDataID(record: TRecord): DataID;
605 |
606 | getType(record: TRecord): string;
607 |
608 | getValue(record: TRecord, name: string, args?: ?Variables): mixed;
609 |
610 | getLinkedRecordID(
611 | record: TRecord,
612 | name: string,
613 | args?: ?Variables,
614 | ): ?DataID;
615 |
616 | getLinkedRecordIDs(
617 | record: TRecord,
618 | name: string,
619 | args?: ?Variables,
620 | ): ?Array;
621 | }
622 |
623 | /**
624 | * Settings for how a query response may be cached.
625 | *
626 | * - `force`: causes a query to be issued unconditionally, irrespective of the
627 | * state of any configured response cache.
628 | * - `poll`: causes a query to live update by polling at the specified interval
629 | in milliseconds. (This value will be passed to setTimeout.)
630 | */
631 | declare export type CacheConfig = {
632 | force?: ?boolean,
633 | poll?: ?number,
634 | };
635 |
636 | /**
637 | * Represents any resource that must be explicitly disposed of. The most common
638 | * use-case is as a return value for subscriptions, where calling `dispose()`
639 | * would cancel the subscription.
640 | */
641 | declare export type Disposable = {
642 | dispose(): void,
643 | };
644 |
645 | /**
646 | * Arbitrary data e.g. received by a container as props.
647 | */
648 | declare export type Props = {[key: string]: mixed};
649 |
650 | /*
651 | * An individual cached graph object.
652 | */
653 | declare export type Record = {[key: string]: mixed};
654 |
655 | /**
656 | * A collection of records keyed by id.
657 | */
658 | declare export type RecordMap = {[dataID: DataID]: ?T};
659 |
660 | /**
661 | * A selector defines the starting point for a traversal into the graph for the
662 | * purposes of targeting a subgraph.
663 | */
664 | declare export type CSelector = {
665 | dataID: DataID,
666 | node: TNode,
667 | variables: Variables,
668 | };
669 |
670 | /**
671 | * A representation of a selector and its results at a particular point in time.
672 | */
673 | declare export type CSnapshot = CSelector & {
674 | data: ?SelectorData,
675 | seenRecords: RecordMap,
676 | };
677 |
678 | /**
679 | * The results of a selector given a store/RecordSource.
680 | */
681 | declare export type SelectorData = {[key: string]: mixed};
682 |
683 | /**
684 | * The results of reading the results of a FragmentMap given some input
685 | * `Props`.
686 | */
687 | declare export type FragmentSpecResults = {[key: string]: mixed};
688 |
689 | /**
690 | * A utility for resolving and subscribing to the results of a fragment spec
691 | * (key -> fragment mapping) given some "props" that determine the root ID
692 | * and variables to use when reading each fragment. When props are changed via
693 | * `setProps()`, the resolver will update its results and subscriptions
694 | * accordingly. Internally, the resolver:
695 | * - Converts the fragment map & props map into a map of `Selector`s.
696 | * - Removes any resolvers for any props that became null.
697 | * - Creates resolvers for any props that became non-null.
698 | * - Updates resolvers with the latest props.
699 | */
700 | declare export interface FragmentSpecResolver {
701 | /**
702 | * Stop watching for changes to the results of the fragments.
703 | */
704 | dispose(): void;
705 |
706 | /**
707 | * Get the current results.
708 | */
709 | resolve(): FragmentSpecResults;
710 |
711 | /**
712 | * Update the resolver with new inputs. Call `resolve()` to get the updated
713 | * results.
714 | */
715 | setProps(props: Props): void;
716 |
717 | /**
718 | * Override the variables used to read the results of the fragments. Call
719 | * `resolve()` to get the updated results.
720 | */
721 | setVariables(variables: Variables): void;
722 | }
723 |
724 | declare export type CFragmentMap = {[key: string]: TFragment};
725 |
726 | /**
727 | * An operation selector describes a specific instance of a GraphQL operation
728 | * with variables applied.
729 | *
730 | * - `root`: a selector intended for processing server results or retaining
731 | * response data in the store.
732 | * - `fragment`: a selector intended for use in reading or subscribing to
733 | * the results of the the operation.
734 | */
735 | declare export type COperationSelector = {
736 | fragment: CSelector,
737 | node: TOperation,
738 | root: CSelector,
739 | variables: Variables,
740 | };
741 |
742 | /**
743 | * The public API of Relay core. Represents an encapsulated environment with its
744 | * own in-memory cache.
745 | */
746 | declare export interface CEnvironment<
747 | TEnvironment,
748 | TFragment,
749 | TGraphQLTaggedNode,
750 | TNode,
751 | TOperation,
752 | TPayload,
753 | > {
754 | /**
755 | * Read the results of a selector from in-memory records in the store.
756 | */
757 | lookup(selector: CSelector): CSnapshot;
758 |
759 | /**
760 | * Subscribe to changes to the results of a selector. The callback is called
761 | * when data has been committed to the store that would cause the results of
762 | * the snapshot's selector to change.
763 | */
764 | subscribe(
765 | snapshot: CSnapshot,
766 | callback: (snapshot: CSnapshot) => void,
767 | ): Disposable;
768 |
769 | /**
770 | * Ensure that all the records necessary to fulfill the given selector are
771 | * retained in-memory. The records will not be eligible for garbage collection
772 | * until the returned reference is disposed.
773 | *
774 | * Note: This is a no-op in the classic core.
775 | */
776 | retain(selector: CSelector): Disposable;
777 |
778 | /**
779 | * Send a query to the server with request/response semantics: the query will
780 | * either complete successfully (calling `onNext` and `onCompleted`) or fail
781 | * (calling `onError`).
782 | *
783 | * Note: Most applications should use `streamQuery` in order to
784 | * optionally receive updated information over time, should that feature be
785 | * supported by the network/server. A good rule of thumb is to use this method
786 | * if you would otherwise immediately dispose the `streamQuery()`
787 | * after receving the first `onNext` result.
788 | */
789 | sendQuery(config: {|
790 | cacheConfig?: ?CacheConfig,
791 | onCompleted?: ?() => void,
792 | onError?: ?(error: Error) => void,
793 | onNext?: ?(payload: TPayload) => void,
794 | operation: COperationSelector,
795 | |}): Disposable;
796 |
797 | /**
798 | * Send a query to the server with request/subscription semantics: one or more
799 | * responses may be returned (via `onNext`) over time followed by either
800 | * the request completing (`onCompleted`) or an error (`onError`).
801 | *
802 | * Networks/servers that support subscriptions may choose to hold the
803 | * subscription open indefinitely such that `onCompleted` is not called.
804 | */
805 | streamQuery(config: {|
806 | cacheConfig?: ?CacheConfig,
807 | onCompleted?: ?() => void,
808 | onError?: ?(error: Error) => void,
809 | onNext?: ?(payload: TPayload) => void,
810 | operation: COperationSelector,
811 | |}): Disposable;
812 |
813 | unstable_internal: CUnstableEnvironmentCore<
814 | TEnvironment,
815 | TFragment,
816 | TGraphQLTaggedNode,
817 | TNode,
818 | TOperation,
819 | >;
820 | }
821 |
822 | declare export interface CUnstableEnvironmentCore<
823 | TEnvironment,
824 | TFragment,
825 | TGraphQLTaggedNode,
826 | TNode,
827 | TOperation,
828 | > {
829 | /**
830 | * Create an instance of a FragmentSpecResolver.
831 | *
832 | * TODO: The FragmentSpecResolver *can* be implemented via the other methods
833 | * defined here, so this could be moved out of core. It's convenient to have
834 | * separate implementations until the experimental core is in OSS.
835 | */
836 | createFragmentSpecResolver: (
837 | context: CRelayContext,
838 | containerName: string,
839 | fragments: CFragmentMap,
840 | props: Props,
841 | callback: () => void,
842 | ) => FragmentSpecResolver;
843 |
844 | /**
845 | * Creates an instance of an OperationSelector given an operation definition
846 | * (see `getOperation`) and the variables to apply. The input variables are
847 | * filtered to exclude variables that do not matche defined arguments on the
848 | * operation, and default values are populated for null values.
849 | */
850 | createOperationSelector: (
851 | operation: TOperation,
852 | variables: Variables,
853 | ) => COperationSelector;
854 |
855 | /**
856 | * Given a graphql`...` tagged template, extract a fragment definition usable
857 | * by this version of Relay core. Throws if the value is not a fragment.
858 | */
859 | getFragment: (node: TGraphQLTaggedNode) => TFragment;
860 |
861 | /**
862 | * Given a graphql`...` tagged template, extract an operation definition
863 | * usable by this version of Relay core. Throws if the value is not an
864 | * operation.
865 | */
866 | getOperation: (node: TGraphQLTaggedNode) => TOperation;
867 |
868 | /**
869 | * Determine if two selectors are equal (represent the same selection). Note
870 | * that this function returns `false` when the two queries/fragments are
871 | * different objects, even if they select the same fields.
872 | */
873 | areEqualSelectors: (a: CSelector, b: CSelector) => boolean;
874 |
875 | /**
876 | * Given the result `item` from a parent that fetched `fragment`, creates a
877 | * selector that can be used to read the results of that fragment for that item.
878 | *
879 | * Example:
880 | *
881 | * Given two fragments as follows:
882 | *
883 | * ```
884 | * fragment Parent on User {
885 | * id
886 | * ...Child
887 | * }
888 | * fragment Child on User {
889 | * name
890 | * }
891 | * ```
892 | *
893 | * And given some object `parent` that is the results of `Parent` for id "4",
894 | * the results of `Child` can be accessed by first getting a selector and then
895 | * using that selector to `lookup()` the results against the environment:
896 | *
897 | * ```
898 | * const childSelector = getSelector(queryVariables, Child, parent);
899 | * const childData = environment.lookup(childSelector).data;
900 | * ```
901 | */
902 | getSelector: (
903 | operationVariables: Variables,
904 | fragment: TFragment,
905 | prop: mixed,
906 | ) => ?CSelector;
907 |
908 | /**
909 | * Given the result `items` from a parent that fetched `fragment`, creates a
910 | * selector that can be used to read the results of that fragment on those
911 | * items. This is similar to `getSelector` but for "plural" fragments that
912 | * expect an array of results and therefore return an array of selectors.
913 | */
914 | getSelectorList: (
915 | operationVariables: Variables,
916 | fragment: TFragment,
917 | props: Array,
918 | ) => ?Array>;
919 |
920 | /**
921 | * Given a mapping of keys -> results and a mapping of keys -> fragments,
922 | * extracts the selectors for those fragments from the results.
923 | *
924 | * The canonical use-case for this function are Relay Containers, which
925 | * use this function to convert (props, fragments) into selectors so that they
926 | * can read the results to pass to the inner component.
927 | */
928 | getSelectorsFromObject: (
929 | operationVariables: Variables,
930 | fragments: CFragmentMap,
931 | props: Props,
932 | ) => {[key: string]: ?(CSelector | Array>)};
933 |
934 | /**
935 | * Given a mapping of keys -> results and a mapping of keys -> fragments,
936 | * extracts a mapping of keys -> id(s) of the results.
937 | *
938 | * Similar to `getSelectorsFromObject()`, this function can be useful in
939 | * determining the "identity" of the props passed to a component.
940 | */
941 | getDataIDsFromObject: (
942 | fragments: CFragmentMap,
943 | props: Props,
944 | ) => {[key: string]: ?(DataID | Array)};
945 |
946 | /**
947 | * Given a mapping of keys -> results and a mapping of keys -> fragments,
948 | * extracts the merged variables that would be in scope for those
949 | * fragments/results.
950 | *
951 | * This can be useful in determing what varaibles were used to fetch the data
952 | * for a Relay container, for example.
953 | */
954 | getVariablesFromObject: (
955 | operationVariables: Variables,
956 | fragments: CFragmentMap,
957 | props: Props,
958 | ) => Variables;
959 | }
960 |
961 | /**
962 | * The type of the `relay` property set on React context by the React/Relay
963 | * integration layer (e.g. QueryRenderer, FragmentContainer, etc).
964 | */
965 | declare export type CRelayContext = {
966 | environment: TEnvironment,
967 | variables: Variables,
968 | };
969 |
970 | /**
971 | * The public API of Relay core. Represents an encapsulated environment with its
972 | * own in-memory cache.
973 | */
974 | declare export interface Environment
975 | extends CEnvironment<
976 | TEnvironment,
977 | TFragment,
978 | TGraphQLTaggedNode,
979 | TNode,
980 | TOperation,
981 | TPayload,
982 | > {
983 | /**
984 | * Applies an optimistic mutation to the store without committing it to the
985 | * server. The returned Disposable can be used to revert this change at a
986 | * later time.
987 | */
988 | applyMutation(config: {|
989 | configs: Array,
990 | operation: ConcreteOperationDefinition,
991 | optimisticResponse: Object,
992 | variables: Variables,
993 | |}): Disposable;
994 |
995 | /**
996 | * Applies an optimistic mutation if provided and commits the mutation to the
997 | * server. The returned Disposable can be used to bypass the `onCompleted`
998 | * and `onError` callbacks when the server response is returned.
999 | */
1000 | sendMutation(config: {|
1001 | configs: Array,
1002 | onCompleted?: ?(response: ResponseType) => void,
1003 | onError?: ?(error: Error) => void,
1004 | operation: ConcreteOperationDefinition,
1005 | optimisticOperation?: ?ConcreteOperationDefinition,
1006 | optimisticResponse?: ?Object,
1007 | variables: Variables,
1008 | uploadables?: UploadableMap,
1009 | |}): Disposable;
1010 | }
1011 |
1012 | declare export type Observer = {
1013 | onCompleted?: ?() => void,
1014 | onError?: ?(error: Error) => void,
1015 | onNext?: ?(data: T) => void,
1016 | };
1017 |
1018 | /**
1019 | * The results of reading data for a fragment. This is similar to a `Selector`,
1020 | * but references the (fragment) node by name rather than by value.
1021 | */
1022 | declare export type FragmentPointer = {
1023 | __id: DataID,
1024 | __fragments: {[fragmentName: string]: Variables},
1025 | };
1026 |
1027 | /**
1028 | * A callback for resolving a Selector from a source.
1029 | */
1030 | declare export type AsyncLoadCallback = (loadingState: LoadingState) => void;
1031 | declare export type LoadingState = $Exact<{
1032 | status: 'aborted' | 'complete' | 'error' | 'missing',
1033 | error?: Error,
1034 | }>;
1035 |
1036 | /**
1037 | * A map of records affected by an update operation.
1038 | */
1039 | declare export type UpdatedRecords = {[dataID: DataID]: boolean};
1040 |
1041 | /**
1042 | * A function that updates a store (via a proxy) given the results of a "handle"
1043 | * field payload.
1044 | */
1045 | declare export type Handler = {
1046 | update: (
1047 | store: RecordSourceProxy,
1048 | fieldPayload: HandleFieldPayload,
1049 | ) => void,
1050 | };
1051 |
1052 | /**
1053 | * A payload that is used to initialize or update a "handle" field with
1054 | * information from the server.
1055 | */
1056 | declare export type HandleFieldPayload = $Exact<{
1057 | // The arguments that were fetched.
1058 | args: Variables,
1059 | // The __id of the record containing the source/handle field.
1060 | dataID: DataID,
1061 | // The (storage) key at which the original server data was written.
1062 | fieldKey: string,
1063 | // The name of the handle.
1064 | handle: string,
1065 | // The (storage) key at which the handle's data should be written by the
1066 | // handler.
1067 | handleKey: string,
1068 | }>;
1069 |
1070 | /**
1071 | * A function that receives a proxy over the store and may trigger side-effects
1072 | * (indirectly) by calling `set*` methods on the store or its record proxies.
1073 | */
1074 | declare export type StoreUpdater = (store: RecordSourceProxy) => void;
1075 |
1076 | /**
1077 | * Similar to StoreUpdater, but accepts a proxy tied to a specific selector in
1078 | * order to easily access the root fields of a query/mutation.
1079 | */
1080 | declare export type SelectorStoreUpdater = (
1081 | store: RecordSourceSelectorProxy,
1082 | ) => void;
1083 |
1084 | declare export type CallValue = ?(
1085 | | boolean
1086 | | number
1087 | | string
1088 | | {[key: string]: CallValue}
1089 | | Array
1090 | );
1091 |
1092 | declare export type RangeBehaviorsFunction = (connectionArgs: {
1093 | [argName: string]: CallValue,
1094 | }) =>
1095 | | 'APPEND'
1096 | | 'IGNORE'
1097 | | 'PREPEND'
1098 | | 'REFETCH'
1099 | | 'REMOVE'
1100 | | 'NODE_DELETE_HANDLER'
1101 | | 'RANGE_ADD_HANDLER'
1102 | | 'RANGE_DELETE_HANDLER'
1103 | | 'HANDLER_TYPES'
1104 | | 'OPTIMISTIC_UPDATE'
1105 | | 'SERVER_UPDATE'
1106 | | 'POLLER_UPDATE'
1107 | | 'UPDATE_TYPES'
1108 | | 'RANGE_OPERATIONS';
1109 |
1110 | declare export type RangeBehaviorsObject = {
1111 | [key: string]: 'APPEND' | 'IGNORE' | 'PREPEND' | 'REFETCH' | 'REMOVE',
1112 | };
1113 |
1114 | declare export type RangeBehaviors =
1115 | | RangeBehaviorsFunction
1116 | | RangeBehaviorsObject;
1117 |
1118 | declare export type RelayConcreteNode = mixed;
1119 |
1120 | declare export type RelayMutationConfig =
1121 | | {
1122 | type: 'FIELDS_CHANGE',
1123 | fieldIDs: {[fieldName: string]: DataID | Array},
1124 | }
1125 | | {
1126 | type: 'RANGE_ADD',
1127 | parentName?: string,
1128 | parentID?: string,
1129 | connectionInfo?: Array<{
1130 | key: string,
1131 | filters?: Variables,
1132 | rangeBehavior: string,
1133 | }>,
1134 | connectionName?: string,
1135 | edgeName: string,
1136 | rangeBehaviors?: RangeBehaviors,
1137 | }
1138 | | {
1139 | type: 'NODE_DELETE',
1140 | parentName?: string,
1141 | parentID?: string,
1142 | connectionName?: string,
1143 | deletedIDFieldName: string,
1144 | }
1145 | | {
1146 | type: 'RANGE_DELETE',
1147 | parentName?: string,
1148 | parentID?: string,
1149 | connectionKeys?: Array<{
1150 | key: string,
1151 | filters?: Variables,
1152 | }>,
1153 | connectionName?: string,
1154 | deletedIDFieldName: string | Array,
1155 | pathToConnection: Array,
1156 | }
1157 | | {
1158 | type: 'REQUIRED_CHILDREN',
1159 | children: Array,
1160 | };
1161 |
1162 | declare export type MutationConfig = {|
1163 | configs?: Array,
1164 | mutation: GraphQLTaggedNode,
1165 | variables: Variables,
1166 | uploadables?: UploadableMap,
1167 | onCompleted?: ?(response: T, errors: ?Array) => void,
1168 | onError?: ?(error: Error) => void,
1169 | optimisticUpdater?: ?SelectorStoreUpdater,
1170 | optimisticResponse?: Object,
1171 | updater?: ?SelectorStoreUpdater,
1172 | |};
1173 |
1174 | // a.k.a commitRelayModernMutation
1175 | declare export function commitMutation(
1176 | environment: Environment,
1177 | config: MutationConfig,
1178 | ): Disposable;
1179 |
1180 | declare export type ReadyState = {
1181 | error: ?Error,
1182 | props: ?Object,
1183 | retry: ?() => void,
1184 | };
1185 |
1186 | /**
1187 | * Classic environment below here
1188 | */
1189 | declare export class RelayQueryFragment {
1190 | // stub
1191 | }
1192 |
1193 | declare export class RelayQueryNode {
1194 | // stub
1195 | }
1196 |
1197 | declare export class RelayQueryRoot {
1198 | // stub
1199 | }
1200 |
1201 | declare export class RelayStoreData {
1202 | // stub
1203 | }
1204 |
1205 | declare export type RelayQuerySet = {[queryName: string]: ?RelayQueryRoot};
1206 | declare export type ReadyStateChangeCallback = (
1207 | readyState: ReadyState,
1208 | ) => void;
1209 | declare export type Abortable = {
1210 | abort(): void,
1211 | };
1212 | declare export type StoreReaderData = Object;
1213 | declare export type StoreReaderOptions = {
1214 | traverseFragmentReferences?: boolean,
1215 | traverseGeneratedFields?: boolean,
1216 | };
1217 | declare export type FragmentResolver = {
1218 | dispose(): void,
1219 | resolve(
1220 | fragment: RelayQueryFragment,
1221 | dataIDs: DataID | Array,
1222 | ): ?(StoreReaderData | Array),
1223 | };
1224 |
1225 | declare export interface RelayEnvironmentInterface {
1226 | forceFetch(
1227 | querySet: RelayQuerySet,
1228 | onReadyStateChange: ReadyStateChangeCallback,
1229 | ): Abortable;
1230 | getFragmentResolver(
1231 | fragment: RelayQueryFragment,
1232 | onNext: () => void,
1233 | ): FragmentResolver;
1234 | getStoreData(): RelayStoreData;
1235 | primeCache(
1236 | querySet: RelayQuerySet,
1237 | onReadyStateChange: ReadyStateChangeCallback,
1238 | ): Abortable;
1239 | read(
1240 | node: RelayQueryNode,
1241 | dataID: DataID,
1242 | options?: StoreReaderOptions,
1243 | ): ?StoreReaderData;
1244 | readQuery(
1245 | root: RelayQueryRoot,
1246 | options?: StoreReaderOptions,
1247 | ): Array;
1248 | }
1249 |
1250 | declare export type ClassicEnvironment = RelayEnvironmentInterface;
1251 |
1252 | declare export class QueryRenderer extends React$Component<{
1253 | cacheConfig?: ?CacheConfig,
1254 | environment: Environment | ClassicEnvironment,
1255 | query: ?GraphQLTaggedNode,
1256 | render: (readyState: ReadyState) => ?React$Element<*>,
1257 | variables: Variables,
1258 | }> {}
1259 |
1260 | // https://github.com/facebook/relay/blob/master/packages/relay-runtime/network/RelayNetworkTypes.js
1261 | /**
1262 | * A cache for saving respones to queries (by id) and variables.
1263 | */
1264 | declare export interface ResponseCache {
1265 | get(id: string, variables: Variables): ?QueryPayload;
1266 | set(id: string, variables: Variables, payload: QueryPayload): void;
1267 | }
1268 |
1269 | /**
1270 | * An interface for fetching the data for one or more (possibly interdependent)
1271 | * queries.
1272 | */
1273 | declare export interface Network {
1274 | fetch: FetchFunction;
1275 | request: RequestResponseFunction;
1276 | requestStream: RequestStreamFunction;
1277 | }
1278 |
1279 | declare export type PayloadData = {[key: string]: mixed};
1280 |
1281 | declare export type PayloadError = {
1282 | message: string,
1283 | locations?: Array<{
1284 | line: number,
1285 | column: number,
1286 | }>,
1287 | };
1288 |
1289 | /**
1290 | * The shape of a GraphQL response as dictated by the
1291 | * [spec](http://facebook.github.io/graphql/#sec-Response)
1292 | */
1293 | declare export type QueryPayload = {|
1294 | data?: ?PayloadData,
1295 | errors?: Array,
1296 | rerunVariables?: Variables,
1297 | |};
1298 |
1299 | /**
1300 | * The shape of data that is returned by the Relay network layer for a given
1301 | * query.
1302 | */
1303 | declare export type RelayResponsePayload = {|
1304 | fieldPayloads?: ?Array,
1305 | source: MutableRecordSource,
1306 | errors: ?Array,
1307 | |};
1308 |
1309 | declare export type PromiseOrValue = Promise | T | Error;
1310 |
1311 | /**
1312 | * A function that executes a GraphQL operation with request/response semantics,
1313 | * with exactly one raw server response returned
1314 | */
1315 | declare export type FetchFunction = (
1316 | operation: ConcreteBatch,
1317 | variables: Variables,
1318 | cacheConfig: ?CacheConfig,
1319 | uploadables?: UploadableMap,
1320 | ) => PromiseOrValue;
1321 |
1322 | /**
1323 | * A function that executes a GraphQL operation with request/subscription
1324 | * semantics, returning one or more raw server responses over time.
1325 | */
1326 | declare export type SubscribeFunction = (
1327 | operation: ConcreteBatch,
1328 | variables: Variables,
1329 | cacheConfig: ?CacheConfig,
1330 | observer: Observer,
1331 | ) => Disposable;
1332 |
1333 | /**
1334 | * A function that executes a GraphQL operation with request/subscription
1335 | * semantics, returning one or more responses over time that include the
1336 | * initial result and optional updates e.g. as the results of the operation
1337 | * change.
1338 | */
1339 | declare export type RequestStreamFunction = (
1340 | operation: ConcreteBatch,
1341 | variables: Variables,
1342 | cacheConfig: ?CacheConfig,
1343 | observer: Observer,
1344 | ) => Disposable;
1345 |
1346 | /**
1347 | * A function that executes a GraphQL operation with request/response semantics,
1348 | * with exactly one response returned.
1349 | */
1350 | declare export type RequestResponseFunction = (
1351 | operation: ConcreteBatch,
1352 | variables: Variables,
1353 | cacheConfig?: ?CacheConfig,
1354 | uploadables?: UploadableMap,
1355 | ) => PromiseOrValue;
1356 |
1357 | declare export type Uploadable = File | Blob;
1358 | declare export type UploadableMap = {[key: string]: Uploadable};
1359 |
1360 | declare export type RerunParam = {
1361 | param: string,
1362 | import: string,
1363 | max_runs: number,
1364 | };
1365 |
1366 | declare export type RelayPaginationProp = {
1367 | ...RelayProp,
1368 | hasMore: () => boolean,
1369 | isLoading: () => boolean,
1370 | loadMore: (
1371 | pageSize: number,
1372 | callback: ?(error: ?Error) => void,
1373 | options?: RefetchOptions,
1374 | ) => ?Disposable,
1375 | refetchConnection: (
1376 | totalCount: number,
1377 | callback: (error: ?Error) => void,
1378 | refetchVariables: ?Variables,
1379 | ) => ?Disposable,
1380 | };
1381 |
1382 | declare export type RelayRefetchProp = {
1383 | ...RelayProp,
1384 | refetch: (
1385 | refetchVariables:
1386 | | Variables
1387 | | ((fragmentVariables: Variables) => Variables),
1388 | renderVariables: ?Variables,
1389 | callback: ?(error: ?Error) => void,
1390 | options?: RefetchOptions,
1391 | ) => Disposable,
1392 | };
1393 |
1394 | declare export type RefetchOptions = {
1395 | force?: boolean,
1396 | rerunParamExperimental?: RerunParam,
1397 | };
1398 | }
1399 |
1400 | declare module 'react-relay/compat' {
1401 | declare module.exports: any;
1402 | }
1403 |
1404 | declare module 'react-relay/classic' {
1405 | declare module.exports: any;
1406 | }
1407 |
1408 | declare module 'react-relay/lib/assertFragmentMap' {
1409 | declare module.exports: any;
1410 | }
1411 |
1412 | declare module 'react-relay/lib/buildReactRelayContainer' {
1413 | declare module.exports: any;
1414 | }
1415 |
1416 | declare module 'react-relay/lib/buildRQL' {
1417 | declare module.exports: any;
1418 | }
1419 |
1420 | declare module 'react-relay/lib/callsFromGraphQL' {
1421 | declare module.exports: any;
1422 | }
1423 |
1424 | declare module 'react-relay/lib/callsToGraphQL' {
1425 | declare module.exports: any;
1426 | }
1427 |
1428 | declare module 'react-relay/lib/checkRelayQueryData' {
1429 | declare module.exports: any;
1430 | }
1431 |
1432 | declare module 'react-relay/lib/ConcreteQuery' {
1433 | declare module.exports: any;
1434 | }
1435 |
1436 | declare module 'react-relay/lib/containsRelayQueryRootCall' {
1437 | declare module.exports: any;
1438 | }
1439 |
1440 | declare module 'react-relay/lib/createRelayQuery' {
1441 | declare module.exports: any;
1442 | }
1443 |
1444 | declare module 'react-relay/lib/dedent' {
1445 | declare module.exports: any;
1446 | }
1447 |
1448 | declare module 'react-relay/lib/deepFreeze' {
1449 | declare module.exports: any;
1450 | }
1451 |
1452 | declare module 'react-relay/lib/diffRelayQuery' {
1453 | declare module.exports: any;
1454 | }
1455 |
1456 | declare module 'react-relay/lib/directivesToGraphQL' {
1457 | declare module.exports: any;
1458 | }
1459 |
1460 | declare module 'react-relay/lib/filterExclusiveKeys' {
1461 | declare module.exports: any;
1462 | }
1463 |
1464 | declare module 'react-relay/lib/filterRelayQuery' {
1465 | declare module.exports: any;
1466 | }
1467 |
1468 | declare module 'react-relay/lib/findRelayQueryLeaves' {
1469 | declare module.exports: any;
1470 | }
1471 |
1472 | declare module 'react-relay/lib/flattenRelayQuery' {
1473 | declare module.exports: any;
1474 | }
1475 |
1476 | declare module 'react-relay/lib/flattenSplitRelayQueries' {
1477 | declare module.exports: any;
1478 | }
1479 |
1480 | declare module 'react-relay/lib/ForceRelayClassicContext' {
1481 | declare module.exports: any;
1482 | }
1483 |
1484 | declare module 'react-relay/lib/forEachRootCallArg' {
1485 | declare module.exports: any;
1486 | }
1487 |
1488 | declare module 'react-relay/lib/formatStorageKey' {
1489 | declare module.exports: any;
1490 | }
1491 |
1492 | declare module 'react-relay/lib/fromGraphQL' {
1493 | declare module.exports: any;
1494 | }
1495 |
1496 | declare module 'react-relay/lib/generateClientEdgeID' {
1497 | declare module.exports: any;
1498 | }
1499 |
1500 | declare module 'react-relay/lib/generateClientID' {
1501 | declare module.exports: any;
1502 | }
1503 |
1504 | declare module 'react-relay/lib/generateConcreteFragmentID' {
1505 | declare module.exports: any;
1506 | }
1507 |
1508 | declare module 'react-relay/lib/generateForceIndex' {
1509 | declare module.exports: any;
1510 | }
1511 |
1512 | declare module 'react-relay/lib/generateRQLFieldAlias' {
1513 | declare module.exports: any;
1514 | }
1515 |
1516 | declare module 'react-relay/lib/getRangeBehavior' {
1517 | declare module.exports: any;
1518 | }
1519 |
1520 | declare module 'react-relay/lib/getRelayHandleKey' {
1521 | declare module.exports: any;
1522 | }
1523 |
1524 | declare module 'react-relay/lib/getRelayQueries' {
1525 | declare module.exports: any;
1526 | }
1527 |
1528 | declare module 'react-relay/lib/GraphQLMutatorConstants' {
1529 | declare module.exports: any;
1530 | }
1531 |
1532 | declare module 'react-relay/lib/GraphQLQueryRunner' {
1533 | declare module.exports: any;
1534 | }
1535 |
1536 | declare module 'react-relay/lib/GraphQLRange' {
1537 | declare module.exports: any;
1538 | }
1539 |
1540 | declare module 'react-relay/lib/GraphQLSegment' {
1541 | declare module.exports: any;
1542 | }
1543 |
1544 | declare module 'react-relay/lib/GraphQLStoreChangeEmitter' {
1545 | declare module.exports: any;
1546 | }
1547 |
1548 | declare module 'react-relay/lib/GraphQLStoreQueryResolver' {
1549 | declare module.exports: any;
1550 | }
1551 |
1552 | declare module 'react-relay/lib/GraphQLStoreRangeUtils' {
1553 | declare module.exports: any;
1554 | }
1555 |
1556 | declare module 'react-relay/lib/intersectRelayQuery' {
1557 | declare module.exports: any;
1558 | }
1559 |
1560 | declare module 'react-relay/lib/isClassicRelayContext' {
1561 | declare module.exports: any;
1562 | }
1563 |
1564 | declare module 'react-relay/lib/isClassicRelayEnvironment' {
1565 | declare module.exports: any;
1566 | }
1567 |
1568 | declare module 'react-relay/lib/isCompatibleRelayFragmentType' {
1569 | declare module.exports: any;
1570 | }
1571 |
1572 | declare module 'react-relay/lib/isRelayContainer' {
1573 | declare module.exports: any;
1574 | }
1575 |
1576 | declare module 'react-relay/lib/isRelayContext' {
1577 | declare module.exports: any;
1578 | }
1579 |
1580 | declare module 'react-relay/lib/isRelayEnvironment' {
1581 | declare module.exports: any;
1582 | }
1583 |
1584 | declare module 'react-relay/lib/isRelayModernContext' {
1585 | declare module.exports: any;
1586 | }
1587 |
1588 | declare module 'react-relay/lib/isRelayVariables' {
1589 | declare module.exports: any;
1590 | }
1591 |
1592 | declare module 'react-relay/lib/isScalarAndEqual' {
1593 | declare module.exports: any;
1594 | }
1595 |
1596 | declare module 'react-relay/lib/prettyStringify' {
1597 | declare module.exports: any;
1598 | }
1599 |
1600 | declare module 'react-relay/lib/printRelayOSSQuery' {
1601 | declare module.exports: any;
1602 | }
1603 |
1604 | declare module 'react-relay/lib/printRelayQuery' {
1605 | declare module.exports: any;
1606 | }
1607 |
1608 | declare module 'react-relay/lib/QueryBuilder' {
1609 | declare module.exports: any;
1610 | }
1611 |
1612 | declare module 'react-relay/lib/rangeOperationToMetadataKey' {
1613 | declare module.exports: any;
1614 | }
1615 |
1616 | declare module 'react-relay/lib/ReactRelayClassicExports' {
1617 | declare module.exports: any;
1618 | }
1619 |
1620 | declare module 'react-relay/lib/ReactRelayCompatContainerBuilder' {
1621 | declare module.exports: any;
1622 | }
1623 |
1624 | declare module 'react-relay/lib/ReactRelayCompatPublic' {
1625 | declare module.exports: any;
1626 | }
1627 |
1628 | declare module 'react-relay/lib/ReactRelayContainerProfiler' {
1629 | declare module.exports: any;
1630 | }
1631 |
1632 | declare module 'react-relay/lib/ReactRelayFragmentContainer-flowtest' {
1633 | declare module.exports: any;
1634 | }
1635 |
1636 | declare module 'react-relay/lib/ReactRelayFragmentContainer' {
1637 | declare module.exports: any;
1638 | }
1639 |
1640 | declare module 'react-relay/lib/ReactRelayFragmentMockRenderer' {
1641 | declare module.exports: any;
1642 | }
1643 |
1644 | declare module 'react-relay/lib/ReactRelayPaginationContainer-flowtest' {
1645 | declare module.exports: any;
1646 | }
1647 |
1648 | declare module 'react-relay/lib/ReactRelayPaginationContainer' {
1649 | declare module.exports: any;
1650 | }
1651 |
1652 | declare module 'react-relay/lib/ReactRelayPropTypes' {
1653 | declare module.exports: any;
1654 | }
1655 |
1656 | declare module 'react-relay/lib/ReactRelayPublic' {
1657 | declare module.exports: any;
1658 | }
1659 |
1660 | declare module 'react-relay/lib/ReactRelayQueryRenderer' {
1661 | declare module.exports: any;
1662 | }
1663 |
1664 | declare module 'react-relay/lib/ReactRelayRefetchContainer-flowtest' {
1665 | declare module.exports: any;
1666 | }
1667 |
1668 | declare module 'react-relay/lib/ReactRelayRefetchContainer' {
1669 | declare module.exports: any;
1670 | }
1671 |
1672 | declare module 'react-relay/lib/ReactRelayTypes' {
1673 | declare module.exports: any;
1674 | }
1675 |
1676 | declare module 'react-relay/lib/readRelayQueryData' {
1677 | declare module.exports: any;
1678 | }
1679 |
1680 | declare module 'react-relay/lib/recycleNodesInto' {
1681 | declare module.exports: any;
1682 | }
1683 |
1684 | declare module 'react-relay/lib/RelayCacheProcessor' {
1685 | declare module.exports: any;
1686 | }
1687 |
1688 | declare module 'react-relay/lib/RelayChangeTracker' {
1689 | declare module.exports: any;
1690 | }
1691 |
1692 | declare module 'react-relay/lib/RelayClassicCore' {
1693 | declare module.exports: any;
1694 | }
1695 |
1696 | declare module 'react-relay/lib/RelayClassicRecordState' {
1697 | declare module.exports: any;
1698 | }
1699 |
1700 | declare module 'react-relay/lib/RelayCombinedEnvironmentTypes' {
1701 | declare module.exports: any;
1702 | }
1703 |
1704 | declare module 'react-relay/lib/RelayCompatContainer' {
1705 | declare module.exports: any;
1706 | }
1707 |
1708 | declare module 'react-relay/lib/RelayCompatEnvironment' {
1709 | declare module.exports: any;
1710 | }
1711 |
1712 | declare module 'react-relay/lib/RelayCompatMutations' {
1713 | declare module.exports: any;
1714 | }
1715 |
1716 | declare module 'react-relay/lib/RelayCompatPaginationContainer' {
1717 | declare module.exports: any;
1718 | }
1719 |
1720 | declare module 'react-relay/lib/RelayCompatRefetchContainer' {
1721 | declare module.exports: any;
1722 | }
1723 |
1724 | declare module 'react-relay/lib/RelayCompatTypes' {
1725 | declare module.exports: any;
1726 | }
1727 |
1728 | declare module 'react-relay/lib/RelayConcreteNode' {
1729 | declare module.exports: any;
1730 | }
1731 |
1732 | declare module 'react-relay/lib/RelayConnectionInterface' {
1733 | declare module.exports: any;
1734 | }
1735 |
1736 | declare module 'react-relay/lib/RelayContainer' {
1737 | declare module.exports: any;
1738 | }
1739 |
1740 | declare module 'react-relay/lib/RelayContainerComparators' {
1741 | declare module.exports: any;
1742 | }
1743 |
1744 | declare module 'react-relay/lib/RelayContainerProxy' {
1745 | declare module.exports: any;
1746 | }
1747 |
1748 | declare module 'react-relay/lib/RelayContainerUtils' {
1749 | declare module.exports: any;
1750 | }
1751 |
1752 | declare module 'react-relay/lib/RelayDefaultHandleKey' {
1753 | declare module.exports: any;
1754 | }
1755 |
1756 | declare module 'react-relay/lib/RelayDefaultNetworkLayer' {
1757 | declare module.exports: any;
1758 | }
1759 |
1760 | declare module 'react-relay/lib/RelayEnvironment' {
1761 | declare module.exports: any;
1762 | }
1763 |
1764 | declare module 'react-relay/lib/RelayEnvironmentSerializer' {
1765 | declare module.exports: any;
1766 | }
1767 |
1768 | declare module 'react-relay/lib/RelayEnvironmentTypes' {
1769 | declare module.exports: any;
1770 | }
1771 |
1772 | declare module 'react-relay/lib/RelayError' {
1773 | declare module.exports: any;
1774 | }
1775 |
1776 | declare module 'react-relay/lib/RelayEventStatus' {
1777 | declare module.exports: any;
1778 | }
1779 |
1780 | declare module 'react-relay/lib/RelayFetchMode' {
1781 | declare module.exports: any;
1782 | }
1783 |
1784 | declare module 'react-relay/lib/RelayFragmentPointer' {
1785 | declare module.exports: any;
1786 | }
1787 |
1788 | declare module 'react-relay/lib/RelayFragmentReference' {
1789 | declare module.exports: any;
1790 | }
1791 |
1792 | declare module 'react-relay/lib/RelayFragmentSpecResolver' {
1793 | declare module.exports: any;
1794 | }
1795 |
1796 | declare module 'react-relay/lib/RelayGarbageCollection' {
1797 | declare module.exports: any;
1798 | }
1799 |
1800 | declare module 'react-relay/lib/RelayGarbageCollector' {
1801 | declare module.exports: any;
1802 | }
1803 |
1804 | declare module 'react-relay/lib/RelayGraphQLMutation' {
1805 | declare module.exports: any;
1806 | }
1807 |
1808 | declare module 'react-relay/lib/RelayGraphQLTag' {
1809 | declare module.exports: any;
1810 | }
1811 |
1812 | declare module 'react-relay/lib/RelayInternals' {
1813 | declare module.exports: any;
1814 | }
1815 |
1816 | declare module 'react-relay/lib/RelayInternalTypes' {
1817 | declare module.exports: any;
1818 | }
1819 |
1820 | declare module 'react-relay/lib/RelayMetaRoute' {
1821 | declare module.exports: any;
1822 | }
1823 |
1824 | declare module 'react-relay/lib/RelayMetricsRecorder' {
1825 | declare module.exports: any;
1826 | }
1827 |
1828 | declare module 'react-relay/lib/RelayMockRenderer' {
1829 | declare module.exports: any;
1830 | }
1831 |
1832 | declare module 'react-relay/lib/RelayMutation' {
1833 | declare module.exports: any;
1834 | }
1835 |
1836 | declare module 'react-relay/lib/RelayMutationDebugPrinter' {
1837 | declare module.exports: any;
1838 | }
1839 |
1840 | declare module 'react-relay/lib/RelayMutationQuery' {
1841 | declare module.exports: any;
1842 | }
1843 |
1844 | declare module 'react-relay/lib/RelayMutationQueue' {
1845 | declare module.exports: any;
1846 | }
1847 |
1848 | declare module 'react-relay/lib/RelayMutationRequest' {
1849 | declare module.exports: any;
1850 | }
1851 |
1852 | declare module 'react-relay/lib/RelayMutationTracker' {
1853 | declare module.exports: any;
1854 | }
1855 |
1856 | declare module 'react-relay/lib/RelayMutationTransaction' {
1857 | declare module.exports: any;
1858 | }
1859 |
1860 | declare module 'react-relay/lib/RelayMutationTransactionStatus' {
1861 | declare module.exports: any;
1862 | }
1863 |
1864 | declare module 'react-relay/lib/RelayMutationType' {
1865 | declare module.exports: any;
1866 | }
1867 |
1868 | declare module 'react-relay/lib/RelayNetworkDebug' {
1869 | declare module.exports: any;
1870 | }
1871 |
1872 | declare module 'react-relay/lib/RelayNetworkLayer' {
1873 | declare module.exports: any;
1874 | }
1875 |
1876 | declare module 'react-relay/lib/RelayNodeInterface' {
1877 | declare module.exports: any;
1878 | }
1879 |
1880 | declare module 'react-relay/lib/RelayOperationSelector' {
1881 | declare module.exports: any;
1882 | }
1883 |
1884 | declare module 'react-relay/lib/RelayOptimisticMutationUtils' {
1885 | declare module.exports: any;
1886 | }
1887 |
1888 | declare module 'react-relay/lib/RelayOSSConnectionInterface' {
1889 | declare module.exports: any;
1890 | }
1891 |
1892 | declare module 'react-relay/lib/RelayPendingQueryTracker' {
1893 | declare module.exports: any;
1894 | }
1895 |
1896 | declare module 'react-relay/lib/RelayProfiler' {
1897 | declare module.exports: any;
1898 | }
1899 |
1900 | declare module 'react-relay/lib/RelayPropTypes' {
1901 | declare module.exports: any;
1902 | }
1903 |
1904 | declare module 'react-relay/lib/RelayPublic' {
1905 | declare module.exports: any;
1906 | }
1907 |
1908 | declare module 'react-relay/lib/RelayQL_GENERATED' {
1909 | declare module.exports: any;
1910 | }
1911 |
1912 | declare module 'react-relay/lib/RelayQL' {
1913 | declare module.exports: any;
1914 | }
1915 |
1916 | declare module 'react-relay/lib/RelayQuery' {
1917 | declare module.exports: any;
1918 | }
1919 |
1920 | declare module 'react-relay/lib/RelayQueryCaching' {
1921 | declare module.exports: any;
1922 | }
1923 |
1924 | declare module 'react-relay/lib/RelayQueryConfig' {
1925 | declare module.exports: any;
1926 | }
1927 |
1928 | declare module 'react-relay/lib/RelayQueryPath' {
1929 | declare module.exports: any;
1930 | }
1931 |
1932 | declare module 'react-relay/lib/RelayQueryRequest' {
1933 | declare module.exports: any;
1934 | }
1935 |
1936 | declare module 'react-relay/lib/RelayQueryResultObservable' {
1937 | declare module.exports: any;
1938 | }
1939 |
1940 | declare module 'react-relay/lib/RelayQueryTracker' {
1941 | declare module.exports: any;
1942 | }
1943 |
1944 | declare module 'react-relay/lib/RelayQueryTransform' {
1945 | declare module.exports: any;
1946 | }
1947 |
1948 | declare module 'react-relay/lib/RelayQueryVisitor' {
1949 | declare module.exports: any;
1950 | }
1951 |
1952 | declare module 'react-relay/lib/RelayQueryWriter' {
1953 | declare module.exports: any;
1954 | }
1955 |
1956 | declare module 'react-relay/lib/RelayReadyState' {
1957 | declare module.exports: any;
1958 | }
1959 |
1960 | declare module 'react-relay/lib/RelayReadyStateRenderer' {
1961 | declare module.exports: any;
1962 | }
1963 |
1964 | declare module 'react-relay/lib/RelayRecord' {
1965 | declare module.exports: any;
1966 | }
1967 |
1968 | declare module 'react-relay/lib/RelayRecordStatusMap' {
1969 | declare module.exports: any;
1970 | }
1971 |
1972 | declare module 'react-relay/lib/RelayRecordStore' {
1973 | declare module.exports: any;
1974 | }
1975 |
1976 | declare module 'react-relay/lib/RelayRecordWriter' {
1977 | declare module.exports: any;
1978 | }
1979 |
1980 | declare module 'react-relay/lib/RelayRefQueryDescriptor' {
1981 | declare module.exports: any;
1982 | }
1983 |
1984 | declare module 'react-relay/lib/RelayRenderer' {
1985 | declare module.exports: any;
1986 | }
1987 |
1988 | declare module 'react-relay/lib/RelayRootContainer' {
1989 | declare module.exports: any;
1990 | }
1991 |
1992 | declare module 'react-relay/lib/RelayRoute' {
1993 | declare module.exports: any;
1994 | }
1995 |
1996 | declare module 'react-relay/lib/RelayRouteFragment' {
1997 | declare module.exports: any;
1998 | }
1999 |
2000 | declare module 'react-relay/lib/RelaySelector' {
2001 | declare module.exports: any;
2002 | }
2003 |
2004 | declare module 'react-relay/lib/RelayShallowMock' {
2005 | declare module.exports: any;
2006 | }
2007 |
2008 | declare module 'react-relay/lib/RelayStore' {
2009 | declare module.exports: any;
2010 | }
2011 |
2012 | declare module 'react-relay/lib/RelayStoreConstants' {
2013 | declare module.exports: any;
2014 | }
2015 |
2016 | declare module 'react-relay/lib/RelayStoreData' {
2017 | declare module.exports: any;
2018 | }
2019 |
2020 | declare module 'react-relay/lib/RelayTaskQueue' {
2021 | declare module.exports: any;
2022 | }
2023 |
2024 | declare module 'react-relay/lib/RelayTypes' {
2025 | declare module.exports: any;
2026 | }
2027 |
2028 | declare module 'react-relay/lib/relayUnstableBatchedUpdates' {
2029 | declare module.exports: any;
2030 | }
2031 |
2032 | declare module 'react-relay/lib/relayUnstableBatchedUpdates.native' {
2033 | declare module.exports: any;
2034 | }
2035 |
2036 | declare module 'react-relay/lib/RelayVariable' {
2037 | declare module.exports: any;
2038 | }
2039 |
2040 | declare module 'react-relay/lib/RelayVariables' {
2041 | declare module.exports: any;
2042 | }
2043 |
2044 | declare module 'react-relay/lib/restoreRelayCacheData' {
2045 | declare module.exports: any;
2046 | }
2047 |
2048 | declare module 'react-relay/lib/serializeRelayQueryCall' {
2049 | declare module.exports: any;
2050 | }
2051 |
2052 | declare module 'react-relay/lib/simpleClone' {
2053 | declare module.exports: any;
2054 | }
2055 |
2056 | declare module 'react-relay/lib/splitDeferredRelayQueries' {
2057 | declare module.exports: any;
2058 | }
2059 |
2060 | declare module 'react-relay/lib/stableJSONStringify' {
2061 | declare module.exports: any;
2062 | }
2063 |
2064 | declare module 'react-relay/lib/stableStringify' {
2065 | declare module.exports: any;
2066 | }
2067 |
2068 | declare module 'react-relay/lib/testEditDistance' {
2069 | declare module.exports: any;
2070 | }
2071 |
2072 | declare module 'react-relay/lib/throwFailedPromise' {
2073 | declare module.exports: any;
2074 | }
2075 |
2076 | declare module 'react-relay/lib/toGraphQL' {
2077 | declare module.exports: any;
2078 | }
2079 |
2080 | declare module 'react-relay/lib/transformRelayQueryPayload' {
2081 | declare module.exports: any;
2082 | }
2083 |
2084 | declare module 'react-relay/lib/validateMutationConfig' {
2085 | declare module.exports: any;
2086 | }
2087 |
2088 | declare module 'react-relay/lib/validateRelayReadQuery' {
2089 | declare module.exports: any;
2090 | }
2091 |
2092 | declare module 'react-relay/lib/writeRelayQueryPayload' {
2093 | declare module.exports: any;
2094 | }
2095 |
2096 | declare module 'react-relay/lib/writeRelayUpdatePayload' {
2097 | declare module.exports: any;
2098 | }
2099 |
2100 | // Manually added:
2101 |
2102 | declare module 'relay-runtime/lib/RelayNetworkLogger' {
2103 | declare module.exports: any;
2104 | }
2105 |
2106 | declare module 'relay-runtime/lib/RelayQueryResponseCache' {
2107 | declare module.exports: any;
2108 | }
2109 |
--------------------------------------------------------------------------------