implemented identity, updated session, added 'workings' list

added paginated querying, added 'common'
This commit is contained in:
lnn0q 2025-05-17 00:29:55 +03:00
parent 027deba422
commit 6ada519e06
36 changed files with 1422 additions and 279 deletions

View file

@ -43,7 +43,7 @@ export async function refreshTokenController(req: Request, res: Response) {
expiresIn: config.accessToken.expiresIn
});
const session: Session = { accessToken };
const session: Session = { userId: user.id, accessToken };
res.json(session);
} catch (error) {
console.error(error);

View file

@ -2,17 +2,21 @@
import { MutationResolvers, QueryResolvers } from '@generated/types';
/* Query */
import { BooksManyResolver } from './resolvers/booksManyResolver';
import { BookOneResolver } from './resolvers/bookOneResolver';
import { BooksManyResolver } from './resolvers/booksManyResolver';
import { IdentityResolver } from './resolvers/identityResolver';
import { UserOneResolver } from './resolvers/userOneResolver';
/* Mutation */
import { SignUpResolver } from './resolvers/auth/signUp';
import { LoginResolver } from './resolvers/auth/login';
import { LogoutResolver } from './resolvers/auth/logout';
import { SignUpResolver } from './resolvers/auth/signUp';
export const Query: QueryResolvers = {
booksMany: BooksManyResolver,
bookOne: BookOneResolver
bookOne: BookOneResolver,
identity: IdentityResolver,
userOne: UserOneResolver
};
export const Mutation: MutationResolvers = {

View file

@ -40,6 +40,7 @@ export async function LoginResolver(
});
return {
userId: user.id,
accessToken
};
}

View file

@ -0,0 +1,14 @@
import { IdentityContext } from '@app/server/identity';
import { prisma } from '@app/server/prisma/client';
import { Identity } from '@generated/types';
import { toIdentitySchema } from './mappers/identityMapper';
export async function IdentityResolver(
_: any,
__: any,
{ identity }: IdentityContext
): Promise<Identity> {
if (identity == null) throw new Error('Unauthorized.');
const model = await prisma.user.findUniqueOrThrow({ where: { id: identity.id } });
return toIdentitySchema(model);
}

View file

@ -0,0 +1,12 @@
import { Identity as IdentitySchema } from '@generated/types';
import { User } from '@prisma/client';
import { toUserSchema } from './userMapper';
export async function toIdentitySchema(model: User): Promise<IdentitySchema> {
return {
id: model.id,
email: model.email,
isDarkTheme: true,
user: await toUserSchema(model)
};
}

View file

@ -0,0 +1,11 @@
import { User as UserSchema } from '@generated/types';
import { User } from '@prisma/client';
export async function toUserSchema(model: User): Promise<UserSchema> {
return {
id: model.id,
username: model.username,
createdAt: model.createdAt.toISOString(),
updatedAt: model.updatedAt.toISOString()
};
}

View file

@ -0,0 +1,13 @@
import { IdentityContext } from '@app/server/identity';
import { prisma } from '@app/server/prisma/client';
import { QueryUserOneArgs, User } from '@generated/types';
import { toUserSchema } from './mappers/userMapper';
export async function UserOneResolver(
_: any,
{ id }: QueryUserOneArgs,
{ identity }: IdentityContext
): Promise<User> {
const model = await prisma.user.findUniqueOrThrow({ where: { id } });
return toUserSchema(model);
}

View file

@ -3,6 +3,9 @@ scalar Void
type Query {
booksMany: [Book!]!
bookOne(id: ID!): Book!
identity: Identity!
userOne(id: ID!): User!
workingMany(input: WorkingManyInput!): WorkingManyOutput!
}
type Mutation {
@ -23,11 +26,89 @@ input LoginInput {
}
type Session {
userId: ID!
accessToken: String!
}
type Identity {
id: ID!
email: String!
isDarkTheme: Boolean!
user: User!
}
type User {
id: ID!
username: String!
createdAt: String!
updatedAt: String!
}
type Book {
id: ID!
title: String!
author: String!
}
input Working
input PaginationFilterInput {
terms: String
offset: Int
size: Int
}
input WorkingManyInput {
filter: PaginationFilterInput!
}
enum WorkingProgressStatus {
inProgress
frozen
finished
}
type WorkingManyOutput {
items: [Working!]!
total: Int!
}
type Working {
id: ID!
title: String!
description: String!
author: User!
createdAt: String!
updatedAt: String!
progressStatus: WorkingProgressStatus!
wordsTotal: Int!
ratingTotal: Int!
chapters: ChapterManyOutput!
reviews: ReviewManyOutput!
}
type ChapterManyOutput {
items: [Chapter!]!
total: Int!
}
type Chapter {
id: ID!
title: String!
createdAt: String!
updatedAt: String!
foreword: String!
footnote: String!
}
type ReviewManyOutput {
items: [Review!]!
total: Int!
}
type Review {
id: ID!
author: User!
text: String!
ratingTotal: Int!
}

View file

@ -1,16 +1,17 @@
import { Session } from '@generated/types';
import 'dotenv/config';
import { Request, Response } from 'express';
import { GraphQLError } from 'graphql';
import jwt from 'jsonwebtoken';
import { config } from './main';
import { prisma } from './prisma/client';
import { GraphQLError } from 'graphql';
export interface IdentityContext {
req: Request;
res: Response;
identity?: {
id: string;
email: string;
username: string;
};
}

View file

@ -10,12 +10,14 @@ datasource db {
model User {
id String @id
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
email String @unique @db.VarChar(255)
username String @unique @db.VarChar(255)
password String
refreshToken String? @unique @db.VarChar(255)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
isDarkMode Boolean @default(true)
}