From 5f4ca74f11b9b77230655e355e42842f084942bd Mon Sep 17 00:00:00 2001 From: Rehane Date: Thu, 19 May 2022 02:08:59 +0530 Subject: [PATCH 1/2] feat : updated post query --- resolvers/post.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/resolvers/post.ts b/resolvers/post.ts index ba9490c..c18f81b 100644 --- a/resolvers/post.ts +++ b/resolvers/post.ts @@ -1,20 +1,25 @@ -import {Post} from '../entities/Post'; -import {Resolver, Query, Arg, Mutation} from 'type-graphql'; +import {Arg, Mutation, Query, Resolver} from 'type-graphql'; import {getConnection} from 'typeorm'; +import {Post} from '../entities/Post'; @Resolver() export class PostResolver { @Query(() => Post, {nullable: true}) - post( - // @Arg("id", ()=> Int) id: number, - @Arg('id') id: number - ) { + post(@Arg('id') id: number) { return Post.findOne(id); } @Query(() => [Post], {nullable: true}) - posts(): Promise { - return Post.find(); + async posts(@Arg('limit') limit: number): Promise { + const postLimit = Math.min(50, limit); + const result = await getConnection() + .getRepository(Post) + .createQueryBuilder() + .orderBy('"createdAt"', 'DESC') + .take(postLimit) + .getMany(); + + return result; } @Mutation(() => Post) From 274d61cdd2e964aee9617747e75de7047151a646 Mon Sep 17 00:00:00 2001 From: Rehane Date: Thu, 19 May 2022 03:41:51 +0530 Subject: [PATCH 2/2] fix : post entities and protect middleware --- client-ui/codegen.yml | 2 +- .../components/DashboardSideBar/index.tsx | 2 +- client-ui/generated/graphql.tsx | 87 ++++++++++++++++--- client-ui/pages/dashboard/saved.tsx | 11 ++- .../services/graphql/queries/posts.graphql | 5 ++ db.config.ts | 3 +- entities/Post.ts | 14 +-- resolvers/post.ts | 41 ++++++--- 8 files changed, 135 insertions(+), 30 deletions(-) create mode 100644 client-ui/services/graphql/queries/posts.graphql diff --git a/client-ui/codegen.yml b/client-ui/codegen.yml index d5415df..21296dc 100644 --- a/client-ui/codegen.yml +++ b/client-ui/codegen.yml @@ -1,6 +1,6 @@ overwrite: true schema: "http://localhost:4000/graphql" -documents: "graphql/**/*.graphql" +documents: "services/graphql/**/*.graphql" generates: generated/graphql.tsx: plugins: diff --git a/client-ui/components/DashboardSideBar/index.tsx b/client-ui/components/DashboardSideBar/index.tsx index 7564e36..f862bc5 100644 --- a/client-ui/components/DashboardSideBar/index.tsx +++ b/client-ui/components/DashboardSideBar/index.tsx @@ -58,7 +58,7 @@ const Index: React.FC<{ h={'100vh'} position={'relative'} > - + diff --git a/client-ui/generated/graphql.tsx b/client-ui/generated/graphql.tsx index 4e03d72..1e47367 100644 --- a/client-ui/generated/graphql.tsx +++ b/client-ui/generated/graphql.tsx @@ -19,6 +19,15 @@ export type Scalars = { Float: number; }; +export type EatherUser = { + __typename?: 'EatherUser'; + createdAt: Scalars['String']; + email: Scalars['String']; + id: Scalars['Float']; + updatedAt: Scalars['String']; + username: Scalars['String']; +}; + export type FieldError = { __typename?: 'FieldError'; field: Scalars['String']; @@ -65,7 +74,7 @@ export type Post = { export type Query = { __typename?: 'Query'; - Me?: Maybe; + Me?: Maybe; hello: Scalars['String']; post?: Maybe; posts?: Maybe>; @@ -79,19 +88,15 @@ export type QueryPostArgs = { id: Scalars['Float']; }; -export type User = { - __typename?: 'User'; - createdAt: Scalars['String']; - id: Scalars['Float']; - updatedAt: Scalars['String']; - username: Scalars['String']; +export type QueryPostsArgs = { + limit?: InputMaybe; }; export type UserResponse = { __typename?: 'UserResponse'; errors?: Maybe>; token?: Maybe; - user?: Maybe; + user?: Maybe; }; export type UsernamePasswordInput = { @@ -113,7 +118,7 @@ export type LoginMutation = { | Array<{__typename?: 'FieldError'; field: string; message: string}> | null | undefined; - user?: {__typename?: 'User'; username: string} | null | undefined; + user?: {__typename?: 'EatherUser'; username: string} | null | undefined; }; }; @@ -131,7 +136,7 @@ export type RegisterMutation = { | Array<{__typename?: 'FieldError'; field: string; message: string}> | null | undefined; - user?: {__typename?: 'User'; username: string} | null | undefined; + user?: {__typename?: 'EatherUser'; username: string} | null | undefined; }; }; @@ -139,11 +144,23 @@ export type AuthTestingQueryVariables = Exact<{[key: string]: never}>; export type AuthTestingQuery = {__typename?: 'Query'; hello: string}; +export type PostsQueryVariables = Exact<{ + limit: Scalars['Int']; +}>; + +export type PostsQuery = { + __typename?: 'Query'; + posts?: Array<{__typename?: 'Post'; title: string}> | null | undefined; +}; + export type SessionCheckQueryVariables = Exact<{[key: string]: never}>; export type SessionCheckQuery = { __typename?: 'Query'; - Me?: {__typename?: 'User'; id: number; username: string} | null | undefined; + Me?: + | {__typename?: 'EatherUser'; id: number; username: string} + | null + | undefined; }; export const LoginDocument = gql` @@ -309,6 +326,54 @@ export type AuthTestingQueryResult = Apollo.QueryResult< AuthTestingQuery, AuthTestingQueryVariables >; +export const PostsDocument = gql` + query Posts($limit: Int!) { + posts(limit: $limit) { + title + } + } +`; + +/** + * __usePostsQuery__ + * + * To run a query within a React component, call `usePostsQuery` and pass it any options that fit your needs. + * When your component renders, `usePostsQuery` 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 } = usePostsQuery({ + * variables: { + * limit: // value for 'limit' + * }, + * }); + */ +export function usePostsQuery( + baseOptions: Apollo.QueryHookOptions +) { + const options = {...defaultOptions, ...baseOptions}; + return Apollo.useQuery( + PostsDocument, + options + ); +} +export function usePostsLazyQuery( + baseOptions?: Apollo.LazyQueryHookOptions +) { + const options = {...defaultOptions, ...baseOptions}; + return Apollo.useLazyQuery( + PostsDocument, + options + ); +} +export type PostsQueryHookResult = ReturnType; +export type PostsLazyQueryHookResult = ReturnType; +export type PostsQueryResult = Apollo.QueryResult< + PostsQuery, + PostsQueryVariables +>; export const SessionCheckDocument = gql` query SessionCheck { Me { diff --git a/client-ui/pages/dashboard/saved.tsx b/client-ui/pages/dashboard/saved.tsx index e762b60..480e181 100644 --- a/client-ui/pages/dashboard/saved.tsx +++ b/client-ui/pages/dashboard/saved.tsx @@ -1,4 +1,5 @@ import DashboardSideBar from 'components/DashboardSideBar'; +import {usePostsQuery} from 'generated/graphql'; import {useRouter} from 'next/router'; import useAuth from '../../hooks/useAuth'; @@ -6,6 +7,14 @@ const Index = () => { const auth = useAuth(); const router = useRouter(); + const {data} = usePostsQuery({ + variables: { + limit: 10 + } + }); + + console.log('data : ', data); + // useEffect(() => { // if (!auth.isAuthenticated() && !auth.loading) router.push('/'); // }, [auth.isAuthenticated(), auth.loading]); @@ -14,7 +23,7 @@ const Index = () => { <> {auth.isAuthenticated() ? ( -

Please first login

+ {data?.posts?.map((item: any) => JSON.stringify(item))}
) : (

Please first login

diff --git a/client-ui/services/graphql/queries/posts.graphql b/client-ui/services/graphql/queries/posts.graphql new file mode 100644 index 0000000..5f5e3f3 --- /dev/null +++ b/client-ui/services/graphql/queries/posts.graphql @@ -0,0 +1,5 @@ +query Posts($limit: Int!) { + posts(limit: $limit){ + title + } +} \ No newline at end of file diff --git a/db.config.ts b/db.config.ts index e546e58..e47b6be 100644 --- a/db.config.ts +++ b/db.config.ts @@ -8,7 +8,8 @@ const local = { username: 'rehanchoudhury', database: 'postgres', logging: true, - entities: [Post, EatherUser] + entities: [Post, EatherUser], + synchronize: true }; const dbConfig = !__prod__ ? local : production; diff --git a/entities/Post.ts b/entities/Post.ts index 428829f..12c4dd0 100644 --- a/entities/Post.ts +++ b/entities/Post.ts @@ -1,12 +1,12 @@ +import {Field, ObjectType} from 'type-graphql'; import { - Entity, - PrimaryGeneratedColumn, + BaseEntity, Column, CreateDateColumn, - UpdateDateColumn, - BaseEntity + Entity, + PrimaryGeneratedColumn, + UpdateDateColumn } from 'typeorm'; -import {Field, ObjectType} from 'type-graphql'; @ObjectType() @Entity() @@ -26,4 +26,8 @@ export class Post extends BaseEntity { @Field() @Column() title!: string; + + @Field() + @Column() + creatorId: number; } diff --git a/resolvers/post.ts b/resolvers/post.ts index c18f81b..8a696f4 100644 --- a/resolvers/post.ts +++ b/resolvers/post.ts @@ -1,34 +1,54 @@ -import {Arg, Mutation, Query, Resolver} from 'type-graphql'; +import { + Arg, + Ctx, + Int, + Mutation, + Query, + Resolver, + UseMiddleware +} from 'type-graphql'; import {getConnection} from 'typeorm'; +import {MyContext} from '../@types/types'; import {Post} from '../entities/Post'; +import {protect} from '../middlewares/protect'; @Resolver() export class PostResolver { @Query(() => Post, {nullable: true}) + @UseMiddleware(protect) post(@Arg('id') id: number) { return Post.findOne(id); } @Query(() => [Post], {nullable: true}) - async posts(@Arg('limit') limit: number): Promise { - const postLimit = Math.min(50, limit); - const result = await getConnection() + @UseMiddleware(protect) + async posts( + @Arg('limit', () => Int, {nullable: true}) limit: number, + // @Arg('creatorId', () => Int) creatorId: number, + @Ctx() {req}: MyContext + ): Promise { + const query = getConnection() .getRepository(Post) .createQueryBuilder() - .orderBy('"createdAt"', 'DESC') - .take(postLimit) - .getMany(); + .where('"creatorId" = :creatorId', { + creatorId: req.user.id + }) + .orderBy('"createdAt"', 'DESC'); + + if (limit) query.take(limit); - return result; + return await query.getMany(); } @Mutation(() => Post) - async createPosts(@Arg('title') title: string) { - const post = Post.create({title}).save(); + @UseMiddleware(protect) + async createPosts(@Arg('title') title: string, @Ctx() {req}: MyContext) { + const post = Post.create({title, creatorId: req.user.id}).save(); return post; } @Mutation(() => Post, {nullable: true}) + @UseMiddleware(protect) async updatePost( @Arg('id') id: number, @Arg('title', () => String, {nullable: true}) title: string @@ -48,6 +68,7 @@ export class PostResolver { } @Mutation(() => Boolean) + @UseMiddleware(protect) async deletePost(@Arg('id') id: number) { try { await Post.delete({id});