graphql codegen

This commit is contained in:
Kalle (Sendou) 2020-10-16 00:27:09 +03:00
parent a05eb7cb2d
commit 745ad1f4cd
10 changed files with 20316 additions and 772 deletions

11
codegen.yml Normal file
View File

@ -0,0 +1,11 @@
overwrite: true
schema: "http://localhost:3000/api/graphql"
documents:
- "scenes/**/queries/*.graphql"
- "scenes/**/mutations/*.graphql"
generates:
generated/graphql.tsx:
plugins:
- "typescript"
- "typescript-operations"
- "typescript-react-apollo"

109
generated/graphql.tsx Normal file
View File

@ -0,0 +1,109 @@
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
export type Maybe<T> = T | null;
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
ID: string;
String: string;
Boolean: boolean;
Int: number;
Float: number;
};
export type Profile = {
__typename?: 'Profile';
customUrlPath?: Maybe<Scalars['String']>;
twitchName?: Maybe<Scalars['String']>;
youtubeId?: Maybe<Scalars['String']>;
country?: Maybe<Scalars['String']>;
bio?: Maybe<Scalars['String']>;
sensMotion?: Maybe<Scalars['Int']>;
sensStick?: Maybe<Scalars['Int']>;
weaponPool: Array<Scalars['String']>;
};
export type Query = {
__typename?: 'Query';
getUserByIdentifier?: Maybe<User>;
};
export type QueryGetUserByIdentifierArgs = {
identifier: Scalars['String'];
};
export type User = {
__typename?: 'User';
discordId: Scalars['String'];
username: Scalars['String'];
discriminator: Scalars['String'];
discordAvatar?: Maybe<Scalars['String']>;
profile?: Maybe<Profile>;
fullUsername: Scalars['String'];
avatarUrl?: Maybe<Scalars['String']>;
profilePath: Scalars['String'];
};
export type GetUserByIdentifierQueryVariables = Exact<{
identifier: Scalars['String'];
}>;
export type GetUserByIdentifierQuery = (
{ __typename?: 'Query' }
& { getUserByIdentifier?: Maybe<(
{ __typename?: 'User' }
& Pick<User, 'fullUsername' | 'avatarUrl'>
& { profile?: Maybe<(
{ __typename?: 'Profile' }
& Pick<Profile, 'customUrlPath' | 'twitchName' | 'youtubeId' | 'country' | 'bio' | 'sensMotion' | 'sensStick' | 'weaponPool'>
)> }
)> }
);
export const GetUserByIdentifierDocument = gql`
query GetUserByIdentifier($identifier: String!) {
getUserByIdentifier(identifier: $identifier) {
fullUsername
avatarUrl
profile {
customUrlPath
twitchName
youtubeId
country
bio
sensMotion
sensStick
weaponPool
}
}
}
`;
/**
* __useGetUserByIdentifierQuery__
*
* To run a query within a React component, call `useGetUserByIdentifierQuery` and pass it any options that fit your needs.
* When your component renders, `useGetUserByIdentifierQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useGetUserByIdentifierQuery({
* variables: {
* identifier: // value for 'identifier'
* },
* });
*/
export function useGetUserByIdentifierQuery(baseOptions?: Apollo.QueryHookOptions<GetUserByIdentifierQuery, GetUserByIdentifierQueryVariables>) {
return Apollo.useQuery<GetUserByIdentifierQuery, GetUserByIdentifierQueryVariables>(GetUserByIdentifierDocument, baseOptions);
}
export function useGetUserByIdentifierLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetUserByIdentifierQuery, GetUserByIdentifierQueryVariables>) {
return Apollo.useLazyQuery<GetUserByIdentifierQuery, GetUserByIdentifierQueryVariables>(GetUserByIdentifierDocument, baseOptions);
}
export type GetUserByIdentifierQueryHookResult = ReturnType<typeof useGetUserByIdentifierQuery>;
export type GetUserByIdentifierLazyQueryHookResult = ReturnType<typeof useGetUserByIdentifierLazyQuery>;
export type GetUserByIdentifierQueryResult = Apollo.QueryResult<GetUserByIdentifierQuery, GetUserByIdentifierQueryVariables>;

View File

@ -8,6 +8,7 @@ export const User = objectType({
t.model.username()
t.model.discriminator()
t.model.discordAvatar()
// FIXME: this seems to generate extra query (on top of the one it's expected to generatei thi)
t.model.profile()
t.string("fullUsername", {
resolve: (root) => `${root.username}#${root.discriminator}`})
@ -45,7 +46,9 @@ export const Query = queryType({
args: {
identifier: stringArg({required: true})
},
resolve: (_root, {identifier}, ctx) => ctx.prisma.user.findFirst({
resolve: (_root, {identifier}, ctx) => {
console.log({ctx})
return ctx.prisma.user.findFirst({
where: {
// this is ok because the values are mutually exclusive: customUrlPath can't contain only numbers etc.
OR: [
@ -60,6 +63,7 @@ export const Query = queryType({
]
},
})
}
})
}
})

64
lib/apollo.ts Normal file
View File

@ -0,0 +1,64 @@
// https://github.com/vercel/next.js/blob/canary/examples/with-typescript-graphql/lib/apollo.ts
import {
ApolloClient,
InMemoryCache,
NormalizedCacheObject
} from '@apollo/client'
import { IncomingMessage, ServerResponse } from 'http'
import { useMemo } from 'react'
let apolloClient: ApolloClient<NormalizedCacheObject> | undefined
export type ResolverContext = {
req?: IncomingMessage
res?: ServerResponse
}
function createIsomorphLink(context: ResolverContext = {}) {
if (typeof window === 'undefined') {
const { SchemaLink } = require('@apollo/client/link/schema')
const { schema } = require('graphql/schema')
return new SchemaLink({ schema, context })
} else {
const { HttpLink } = require('@apollo/client')
return new HttpLink({
uri: '/api/graphql',
credentials: 'same-origin',
})
}
}
function createApolloClient(context?: ResolverContext) {
return new ApolloClient({
ssrMode: typeof window === 'undefined',
link: createIsomorphLink(context),
cache: new InMemoryCache(),
})
}
export function initializeApollo(
initialState: any = null,
// Pages with Next.js data fetching methods, like `getStaticProps`, can send
// a custom context which will be used by `SchemaLink` to server render pages
context?: ResolverContext
) {
const _apolloClient = apolloClient ?? createApolloClient(context)
// If your page has Next.js data fetching methods that use Apollo Client, the initial state
// get hydrated here
if (initialState) {
_apolloClient.cache.restore(initialState)
}
// For SSG and SSR always create a new Apollo Client
if (typeof window === 'undefined') return _apolloClient
// Create the Apollo Client once in the client
if (!apolloClient) apolloClient = _apolloClient
return _apolloClient
}
export function useApollo(initialState: any) {
const store = useMemo(() => initializeApollo(initialState), [initialState])
return store
}

20791
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,22 +10,28 @@
"migrate:up": "npx prisma migrate up --experimental",
"studio": "npx prisma studio",
"generate:prisma": "npx prisma generate",
"seed": "ts-node prisma/seed.ts"
"seed": "ts-node prisma/seed.ts",
"gen": "graphql-codegen --config codegen.yml"
},
"dependencies": {
"@apollo/client": "^3.2.4",
"@chakra-ui/core": "^1.0.0-rc.5",
"@nexus/schema": "0.15.0",
"@prisma/client": "2.8.1",
"@nexus/schema": "^0.16.0",
"@prisma/client": "^2.9.0",
"apollo-server-micro": "^2.17.0",
"graphql": "14.6.0",
"graphql": "^15.3.0",
"next": "^9.5.5",
"next-images": "^1.6.0",
"nexus-plugin-prisma": "^0.21.0",
"react": "16.13.1",
"react-dom": "16.13.1",
"nexus-plugin-prisma": "^0.22.0",
"react": "^16.14.0",
"react-dom": "^16.14.0",
"react-icons": "^3.11.0"
},
"devDependencies": {
"@graphql-codegen/cli": "1.17.10",
"@graphql-codegen/typescript": "1.17.10",
"@graphql-codegen/typescript-operations": "1.17.8",
"@graphql-codegen/typescript-react-apollo": "2.0.7",
"@prisma/cli": "^2.8.0",
"@types/react": "^16.9.49",
"ts-node": "^9.0.0",

View File

@ -1,12 +1,19 @@
import { ApolloProvider } from "@apollo/client";
import { ChakraProvider } from "@chakra-ui/core";
import { useApollo } from "lib/apollo";
import type { AppProps } from "next/app";
import Layout from "scenes/Layout";
const MyApp = (props: AppProps) => {
console.log({ props });
const apolloClient = useApollo(props.pageProps.initialApolloState);
return (
<ChakraProvider>
<Layout {...props} />
</ChakraProvider>
<ApolloProvider client={apolloClient}>
<ChakraProvider>
<Layout {...props} />
</ChakraProvider>
</ApolloProvider>
);
};

44
pages/u/[identifier].tsx Normal file
View File

@ -0,0 +1,44 @@
import {
GetUserByIdentifierDocument,
useGetUserByIdentifierQuery,
} from "generated/graphql";
import { initializeApollo } from "lib/apollo";
import { GetStaticPaths, GetStaticProps } from "next";
import Profile from "scenes/Profile";
export const getStaticPaths: GetStaticPaths = async () => {
return {
paths: [{ params: { identifier: "455039198672453645" } }],
fallback: false,
};
};
export const getStaticProps: GetStaticProps = async ({ params }) => {
const apolloClient = initializeApollo();
console.log({ params });
await apolloClient.query({
query: GetUserByIdentifierDocument,
variables: {
// FIXME: why ! needed?
identifier: params!.identifier,
},
});
console.log(apolloClient.cache.extract());
return {
props: {
initialApolloState: apolloClient.cache.extract(),
},
revalidate: 1,
};
};
const ProfilePage = () => {
const { getUserByIdentifier } = useGetUserByIdentifierQuery().data!;
return <Profile user={getUserByIdentifier!} />;
};
export default ProfilePage;

14
scenes/Profile/index.tsx Normal file
View File

@ -0,0 +1,14 @@
import { GetUserByIdentifierQuery } from "generated/graphql";
interface ProfileProps {}
interface Props {
user: NonNullable<GetUserByIdentifierQuery["getUserByIdentifier"]>;
}
const Profile: React.FC<Props> = ({ user }) => {
console.log({ user });
return <>hello from profile</>;
};
export default Profile;

View File

@ -0,0 +1,16 @@
query GetUserByIdentifier($identifier: String!) {
getUserByIdentifier(identifier: $identifier) {
fullUsername
avatarUrl
profile {
customUrlPath
twitchName
youtubeId
country
bio
sensMotion
sensStick
weaponPool
}
}
}