Refactor code structure and dependencies

This commit is contained in:
2024-09-29 21:46:03 +07:00
parent 34d9ee63e6
commit 88176bddc1
12 changed files with 500 additions and 45 deletions

View File

@@ -1,3 +1,5 @@
const { environments } = require('eslint-plugin-prettier');
module.exports = { module.exports = {
parser: '@typescript-eslint/parser', parser: '@typescript-eslint/parser',
parserOptions: { parserOptions: {
@@ -14,6 +16,7 @@ module.exports = {
env: { env: {
node: true, node: true,
jest: true, jest: true,
browser: true,
}, },
ignorePatterns: ['.eslintrc.js'], ignorePatterns: ['.eslintrc.js'],
rules: { rules: {

View File

@@ -26,12 +26,6 @@ COPY --from=node_modules /app/node_modules ./node_modules
# Expose the port # Expose the port
EXPOSE 3000 EXPOSE 3000
# run migrations
RUN npm run prisma:migrate
# generate prisma client
RUN npm run prisma:generate
# Start the application # Start the application
CMD ["npm", "run", "start:dev"] CMD ["npm", "run", "start:dev"]

14
codegen.ts Normal file
View File

@@ -0,0 +1,14 @@
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
overwrite: true,
schema: "https://api.epess.org/graphql",
generates: {
"src/graphql/types/graphql.d.ts": {
plugins: ["typescript", "typescript-resolvers"]
}
}
};
export default config;

52
package-lock.json generated
View File

@@ -11,6 +11,7 @@
"dependencies": { "dependencies": {
"@apollo/server": "^4.11.0", "@apollo/server": "^4.11.0",
"@graphql-codegen/cli": "^5.0.2", "@graphql-codegen/cli": "^5.0.2",
"@graphql-codegen/introspection": "^4.0.3",
"@graphql-codegen/typescript": "^4.0.9", "@graphql-codegen/typescript": "^4.0.9",
"@graphql-codegen/typescript-operations": "^4.2.3", "@graphql-codegen/typescript-operations": "^4.2.3",
"@graphql-codegen/typescript-resolvers": "^4.2.1", "@graphql-codegen/typescript-resolvers": "^4.2.1",
@@ -27,8 +28,6 @@
"@pothos/plugin-prisma-utils": "^1.2.0", "@pothos/plugin-prisma-utils": "^1.2.0",
"@pothos/plugin-scope-auth": "^4.1.0", "@pothos/plugin-scope-auth": "^4.1.0",
"@prisma/client": "^5.20.0", "@prisma/client": "^5.20.0",
"@smatch-corp/nestjs-pothos": "^0.3.0",
"@smatch-corp/nestjs-pothos-apollo-driver": "^0.1.0",
"apollo-server-express": "^3.13.0", "apollo-server-express": "^3.13.0",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"class-transformer": "^0.5.1", "class-transformer": "^0.5.1",
@@ -2360,6 +2359,26 @@
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
"license": "0BSD" "license": "0BSD"
}, },
"node_modules/@graphql-codegen/introspection": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/@graphql-codegen/introspection/-/introspection-4.0.3.tgz",
"integrity": "sha512-4cHRG15Zu4MXMF4wTQmywNf4+fkDYv5lTbzraVfliDnB8rJKcaurQpRBi11KVuQUe24YTq/Cfk4uwewfNikWoA==",
"license": "MIT",
"dependencies": {
"@graphql-codegen/plugin-helpers": "^5.0.3",
"@graphql-codegen/visitor-plugin-common": "^5.0.0",
"tslib": "~2.6.0"
},
"peerDependencies": {
"graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
}
},
"node_modules/@graphql-codegen/introspection/node_modules/tslib": {
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
"license": "0BSD"
},
"node_modules/@graphql-codegen/plugin-helpers": { "node_modules/@graphql-codegen/plugin-helpers": {
"version": "5.0.4", "version": "5.0.4",
"resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-5.0.4.tgz", "resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-5.0.4.tgz",
@@ -5440,35 +5459,6 @@
"@sinonjs/commons": "^3.0.0" "@sinonjs/commons": "^3.0.0"
} }
}, },
"node_modules/@smatch-corp/nestjs-pothos": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@smatch-corp/nestjs-pothos/-/nestjs-pothos-0.3.0.tgz",
"integrity": "sha512-MRWLe+jCKu3q2Nr5gc2o4vU4R2LDd0Fwk5Il6HOUgMAJ7yxUjvRDf7C0tCYLme2wESjEyCPTjMyoQr7yj2Ju1g==",
"license": "MIT",
"peerDependencies": {
"@nestjs/common": "^7 || ^8 || ^9",
"@nestjs/core": "^7 || ^8 || ^9",
"@nestjs/graphql": "*",
"@pothos/core": "^3",
"rxjs": "*"
}
},
"node_modules/@smatch-corp/nestjs-pothos-apollo-driver": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/@smatch-corp/nestjs-pothos-apollo-driver/-/nestjs-pothos-apollo-driver-0.1.0.tgz",
"integrity": "sha512-Xcqz6v4pOBMvJR5jm7L05EMHiOn+ZDmvKIRVfNmvK8Ttoo/fmzRIrCO3WHVJn0VdCk5nFvqgins2omHifzUwTg==",
"license": "MIT",
"dependencies": {
"@smatch-corp/nestjs-pothos": "^0.3.0"
},
"peerDependencies": {
"@nestjs/apollo": "^10",
"@nestjs/common": "^7 || ^8 || ^9",
"@nestjs/core": "^7 || ^8 || ^9",
"@nestjs/graphql": "^10",
"rxjs": "*"
}
},
"node_modules/@tsconfig/node10": { "node_modules/@tsconfig/node10": {
"version": "1.0.11", "version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",

View File

@@ -19,11 +19,13 @@
"test:watch": "jest --watch", "test:watch": "jest --watch",
"test:cov": "jest --coverage", "test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json" "test:e2e": "jest --config ./test/jest-e2e.json",
"codegen": "graphql-codegen --config codegen.ts"
}, },
"dependencies": { "dependencies": {
"@apollo/server": "^4.11.0", "@apollo/server": "^4.11.0",
"@graphql-codegen/cli": "^5.0.2", "@graphql-codegen/cli": "^5.0.2",
"@graphql-codegen/introspection": "^4.0.3",
"@graphql-codegen/typescript": "^4.0.9", "@graphql-codegen/typescript": "^4.0.9",
"@graphql-codegen/typescript-operations": "^4.2.3", "@graphql-codegen/typescript-operations": "^4.2.3",
"@graphql-codegen/typescript-resolvers": "^4.2.1", "@graphql-codegen/typescript-resolvers": "^4.2.1",
@@ -78,7 +80,10 @@
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"tsconfig-paths": "^4.2.0", "tsconfig-paths": "^4.2.0",
"typescript": "^5.1.3", "typescript": "^5.1.3",
"ws": "^8.18.0" "ws": "^8.18.0",
"@graphql-codegen/typescript-resolvers": "4.2.1",
"@graphql-codegen/typescript": "4.0.9",
"@graphql-codegen/cli": "5.0.2"
}, },
"jest": { "jest": {
"moduleFileExtensions": [ "moduleFileExtensions": [
@@ -97,4 +102,4 @@
"coverageDirectory": "../coverage", "coverageDirectory": "../coverage",
"testEnvironment": "node" "testEnvironment": "node"
} }
} }

324
src/generated/graphql.ts Normal file
View File

@@ -0,0 +1,324 @@
import { GraphQLResolveInfo, GraphQLScalarType, GraphQLScalarTypeConfig } from 'graphql';
export type Maybe<T> = T | null;
export type InputMaybe<T> = Maybe<T>;
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };
export type MakeEmpty<T extends { [key: string]: unknown }, K extends keyof T> = { [_ in K]?: never };
export type Incremental<T> = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never };
/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
ID: { input: string; output: string; }
String: { input: string; output: string; }
Boolean: { input: boolean; output: boolean; }
Int: { input: number; output: number; }
Float: { input: number; output: number; }
DateTime: { input: any; output: any; }
};
export type Center = {
__typename?: 'Center';
id?: Maybe<Scalars['ID']['output']>;
userId?: Maybe<Scalars['ID']['output']>;
};
export type CenterStaff = {
__typename?: 'CenterStaff';
centerId?: Maybe<Scalars['ID']['output']>;
serviceId?: Maybe<Scalars['ID']['output']>;
staffId?: Maybe<Scalars['ID']['output']>;
};
export type ChatRoom = {
__typename?: 'ChatRoom';
id?: Maybe<Scalars['ID']['output']>;
};
export type Order = {
__typename?: 'Order';
id?: Maybe<Scalars['ID']['output']>;
userId?: Maybe<Scalars['ID']['output']>;
};
export type Query = {
__typename?: 'Query';
users?: Maybe<Array<User>>;
};
export type Service = {
__typename?: 'Service';
id?: Maybe<Scalars['ID']['output']>;
userId?: Maybe<Scalars['ID']['output']>;
};
export type ServiceFeedback = {
__typename?: 'ServiceFeedback';
id?: Maybe<Scalars['ID']['output']>;
userId?: Maybe<Scalars['ID']['output']>;
};
export type User = {
__typename?: 'User';
CenterStaff?: Maybe<CenterStaff>;
Service?: Maybe<Array<Service>>;
WorkshopSubscription?: Maybe<Array<WorkshopSubscription>>;
center?: Maybe<Center>;
centerStaffChatRoom?: Maybe<Array<ChatRoom>>;
createdAt?: Maybe<Scalars['DateTime']['output']>;
customerChatRoom?: Maybe<Array<ChatRoom>>;
documents?: Maybe<Array<Documents>>;
email?: Maybe<Scalars['String']['output']>;
id?: Maybe<Scalars['ID']['output']>;
name?: Maybe<Scalars['String']['output']>;
order?: Maybe<Array<Order>>;
phoneNumber?: Maybe<Scalars['String']['output']>;
role?: Maybe<Scalars['String']['output']>;
sendingMessage?: Maybe<Array<SendingMessage>>;
serviceFeedbacks?: Maybe<Array<ServiceFeedback>>;
updatedAt?: Maybe<Scalars['DateTime']['output']>;
};
export type Workshop = {
__typename?: 'Workshop';
id?: Maybe<Scalars['ID']['output']>;
};
export type WorkshopSubscription = {
__typename?: 'WorkshopSubscription';
user?: Maybe<User>;
userId?: Maybe<Scalars['ID']['output']>;
workshop?: Maybe<Workshop>;
workshopId?: Maybe<Scalars['ID']['output']>;
};
export type Documents = {
__typename?: 'documents';
id?: Maybe<Scalars['ID']['output']>;
userId?: Maybe<Scalars['ID']['output']>;
};
export type SendingMessage = {
__typename?: 'sendingMessage';
id?: Maybe<Scalars['ID']['output']>;
userId?: Maybe<Scalars['ID']['output']>;
};
export type ResolverTypeWrapper<T> = Promise<T> | T;
export type ResolverWithResolve<TResult, TParent, TContext, TArgs> = {
resolve: ResolverFn<TResult, TParent, TContext, TArgs>;
};
export type Resolver<TResult, TParent = {}, TContext = {}, TArgs = {}> = ResolverFn<TResult, TParent, TContext, TArgs> | ResolverWithResolve<TResult, TParent, TContext, TArgs>;
export type ResolverFn<TResult, TParent, TContext, TArgs> = (
parent: TParent,
args: TArgs,
context: TContext,
info: GraphQLResolveInfo
) => Promise<TResult> | TResult;
export type SubscriptionSubscribeFn<TResult, TParent, TContext, TArgs> = (
parent: TParent,
args: TArgs,
context: TContext,
info: GraphQLResolveInfo
) => AsyncIterable<TResult> | Promise<AsyncIterable<TResult>>;
export type SubscriptionResolveFn<TResult, TParent, TContext, TArgs> = (
parent: TParent,
args: TArgs,
context: TContext,
info: GraphQLResolveInfo
) => TResult | Promise<TResult>;
export interface SubscriptionSubscriberObject<TResult, TKey extends string, TParent, TContext, TArgs> {
subscribe: SubscriptionSubscribeFn<{ [key in TKey]: TResult }, TParent, TContext, TArgs>;
resolve?: SubscriptionResolveFn<TResult, { [key in TKey]: TResult }, TContext, TArgs>;
}
export interface SubscriptionResolverObject<TResult, TParent, TContext, TArgs> {
subscribe: SubscriptionSubscribeFn<any, TParent, TContext, TArgs>;
resolve: SubscriptionResolveFn<TResult, any, TContext, TArgs>;
}
export type SubscriptionObject<TResult, TKey extends string, TParent, TContext, TArgs> =
| SubscriptionSubscriberObject<TResult, TKey, TParent, TContext, TArgs>
| SubscriptionResolverObject<TResult, TParent, TContext, TArgs>;
export type SubscriptionResolver<TResult, TKey extends string, TParent = {}, TContext = {}, TArgs = {}> =
| ((...args: any[]) => SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>)
| SubscriptionObject<TResult, TKey, TParent, TContext, TArgs>;
export type TypeResolveFn<TTypes, TParent = {}, TContext = {}> = (
parent: TParent,
context: TContext,
info: GraphQLResolveInfo
) => Maybe<TTypes> | Promise<Maybe<TTypes>>;
export type IsTypeOfResolverFn<T = {}, TContext = {}> = (obj: T, context: TContext, info: GraphQLResolveInfo) => boolean | Promise<boolean>;
export type NextResolverFn<T> = () => Promise<T>;
export type DirectiveResolverFn<TResult = {}, TParent = {}, TContext = {}, TArgs = {}> = (
next: NextResolverFn<TResult>,
parent: TParent,
args: TArgs,
context: TContext,
info: GraphQLResolveInfo
) => TResult | Promise<TResult>;
/** Mapping between all available schema types and the resolvers types */
export type ResolversTypes = {
Boolean: ResolverTypeWrapper<Scalars['Boolean']['output']>;
Center: ResolverTypeWrapper<Center>;
CenterStaff: ResolverTypeWrapper<CenterStaff>;
ChatRoom: ResolverTypeWrapper<ChatRoom>;
DateTime: ResolverTypeWrapper<Scalars['DateTime']['output']>;
Float: ResolverTypeWrapper<Scalars['Float']['output']>;
ID: ResolverTypeWrapper<Scalars['ID']['output']>;
Int: ResolverTypeWrapper<Scalars['Int']['output']>;
Order: ResolverTypeWrapper<Order>;
Query: ResolverTypeWrapper<{}>;
Service: ResolverTypeWrapper<Service>;
ServiceFeedback: ResolverTypeWrapper<ServiceFeedback>;
String: ResolverTypeWrapper<Scalars['String']['output']>;
User: ResolverTypeWrapper<User>;
Workshop: ResolverTypeWrapper<Workshop>;
WorkshopSubscription: ResolverTypeWrapper<WorkshopSubscription>;
documents: ResolverTypeWrapper<Documents>;
sendingMessage: ResolverTypeWrapper<SendingMessage>;
};
/** Mapping between all available schema types and the resolvers parents */
export type ResolversParentTypes = {
Boolean: Scalars['Boolean']['output'];
Center: Center;
CenterStaff: CenterStaff;
ChatRoom: ChatRoom;
DateTime: Scalars['DateTime']['output'];
Float: Scalars['Float']['output'];
ID: Scalars['ID']['output'];
Int: Scalars['Int']['output'];
Order: Order;
Query: {};
Service: Service;
ServiceFeedback: ServiceFeedback;
String: Scalars['String']['output'];
User: User;
Workshop: Workshop;
WorkshopSubscription: WorkshopSubscription;
documents: Documents;
sendingMessage: SendingMessage;
};
export type CenterResolvers<ContextType = any, ParentType extends ResolversParentTypes['Center'] = ResolversParentTypes['Center']> = {
id?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
userId?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type CenterStaffResolvers<ContextType = any, ParentType extends ResolversParentTypes['CenterStaff'] = ResolversParentTypes['CenterStaff']> = {
centerId?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
serviceId?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
staffId?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type ChatRoomResolvers<ContextType = any, ParentType extends ResolversParentTypes['ChatRoom'] = ResolversParentTypes['ChatRoom']> = {
id?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export interface DateTimeScalarConfig extends GraphQLScalarTypeConfig<ResolversTypes['DateTime'], any> {
name: 'DateTime';
}
export type OrderResolvers<ContextType = any, ParentType extends ResolversParentTypes['Order'] = ResolversParentTypes['Order']> = {
id?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
userId?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type QueryResolvers<ContextType = any, ParentType extends ResolversParentTypes['Query'] = ResolversParentTypes['Query']> = {
users?: Resolver<Maybe<Array<ResolversTypes['User']>>, ParentType, ContextType>;
};
export type ServiceResolvers<ContextType = any, ParentType extends ResolversParentTypes['Service'] = ResolversParentTypes['Service']> = {
id?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
userId?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type ServiceFeedbackResolvers<ContextType = any, ParentType extends ResolversParentTypes['ServiceFeedback'] = ResolversParentTypes['ServiceFeedback']> = {
id?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
userId?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type UserResolvers<ContextType = any, ParentType extends ResolversParentTypes['User'] = ResolversParentTypes['User']> = {
CenterStaff?: Resolver<Maybe<ResolversTypes['CenterStaff']>, ParentType, ContextType>;
Service?: Resolver<Maybe<Array<ResolversTypes['Service']>>, ParentType, ContextType>;
WorkshopSubscription?: Resolver<Maybe<Array<ResolversTypes['WorkshopSubscription']>>, ParentType, ContextType>;
center?: Resolver<Maybe<ResolversTypes['Center']>, ParentType, ContextType>;
centerStaffChatRoom?: Resolver<Maybe<Array<ResolversTypes['ChatRoom']>>, ParentType, ContextType>;
createdAt?: Resolver<Maybe<ResolversTypes['DateTime']>, ParentType, ContextType>;
customerChatRoom?: Resolver<Maybe<Array<ResolversTypes['ChatRoom']>>, ParentType, ContextType>;
documents?: Resolver<Maybe<Array<ResolversTypes['documents']>>, ParentType, ContextType>;
email?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
id?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
name?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
order?: Resolver<Maybe<Array<ResolversTypes['Order']>>, ParentType, ContextType>;
phoneNumber?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
role?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
sendingMessage?: Resolver<Maybe<Array<ResolversTypes['sendingMessage']>>, ParentType, ContextType>;
serviceFeedbacks?: Resolver<Maybe<Array<ResolversTypes['ServiceFeedback']>>, ParentType, ContextType>;
updatedAt?: Resolver<Maybe<ResolversTypes['DateTime']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type WorkshopResolvers<ContextType = any, ParentType extends ResolversParentTypes['Workshop'] = ResolversParentTypes['Workshop']> = {
id?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type WorkshopSubscriptionResolvers<ContextType = any, ParentType extends ResolversParentTypes['WorkshopSubscription'] = ResolversParentTypes['WorkshopSubscription']> = {
user?: Resolver<Maybe<ResolversTypes['User']>, ParentType, ContextType>;
userId?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
workshop?: Resolver<Maybe<ResolversTypes['Workshop']>, ParentType, ContextType>;
workshopId?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type DocumentsResolvers<ContextType = any, ParentType extends ResolversParentTypes['documents'] = ResolversParentTypes['documents']> = {
id?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
userId?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type SendingMessageResolvers<ContextType = any, ParentType extends ResolversParentTypes['sendingMessage'] = ResolversParentTypes['sendingMessage']> = {
id?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
userId?: Resolver<Maybe<ResolversTypes['ID']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};
export type Resolvers<ContextType = any> = {
Center?: CenterResolvers<ContextType>;
CenterStaff?: CenterStaffResolvers<ContextType>;
ChatRoom?: ChatRoomResolvers<ContextType>;
DateTime?: GraphQLScalarType;
Order?: OrderResolvers<ContextType>;
Query?: QueryResolvers<ContextType>;
Service?: ServiceResolvers<ContextType>;
ServiceFeedback?: ServiceFeedbackResolvers<ContextType>;
User?: UserResolvers<ContextType>;
Workshop?: WorkshopResolvers<ContextType>;
WorkshopSubscription?: WorkshopSubscriptionResolvers<ContextType>;
documents?: DocumentsResolvers<ContextType>;
sendingMessage?: SendingMessageResolvers<ContextType>;
};

View File

@@ -1,8 +1,9 @@
import { Module } from '@nestjs/common'; import { MiddlewareConsumer, Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql'; import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo'; import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { PrismaService } from '../prisma/prisma.service'; import { PrismaService } from '../prisma/prisma.service';
import { schema } from './schema'; import { schema } from './schema';
import { GraphQLValidationMiddleware } from 'src/middlewares/graphql.middleware';
@Module({ @Module({
imports: [ imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({ GraphQLModule.forRoot<ApolloDriverConfig>({
@@ -15,4 +16,10 @@ import { schema } from './schema';
], ],
providers: [PrismaService], providers: [PrismaService],
}) })
export class GraphqlModule {} export class GraphqlModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(GraphQLValidationMiddleware) // Apply the custom middleware
.forRoutes('graphql'); // Ensure it only applies to the /graphql endpoint
}
}

View File

@@ -1,5 +1,4 @@
import { builder, prisma } from './graphql.builder'; import { builder, prisma } from './graphql.builder';
import type PrismaTypes from '@pothos/plugin-prisma/generated';
builder.prismaObject('User', { builder.prismaObject('User', {
fields: (t) => ({ fields: (t) => ({
@@ -114,10 +113,103 @@ builder.queryType({
}); });
}, },
}), }),
user: t.prismaField({
type: 'User',
args: {
id: t.arg.string(),
},
resolve: (query, root, args, ctx, info) => {
return prisma.user.findUnique({
where: {
id: args.id?.toString(),
},
});
},
}),
orders: t.prismaField({
type: ['Order'],
resolve: (query, root, args, ctx, info) => {
return prisma.order.findMany({
...query,
});
},
}),
serviceFeedbacks: t.prismaField({
type: ['ServiceFeedback'],
resolve: (query, root, args, ctx, info) => {
return prisma.serviceFeedback.findMany({
...query,
});
},
}),
documents: t.prismaField({
type: ['UploadedDocument'],
resolve: (query, root, args, ctx, info) => {
return prisma.uploadedDocument.findMany({
...query,
});
},
}),
messages: t.prismaField({
type: ['Message'],
resolve: (query, root, args, ctx, info) => {
return prisma.message.findMany({
...query,
});
},
}),
services: t.prismaField({
type: ['Service'],
resolve: (query, root, args, ctx, info) => {
return prisma.service.findMany({
...query,
});
},
}),
centers: t.prismaField({
type: ['Center'],
resolve: (query, root, args, ctx, info) => {
return prisma.center.findMany({
...query,
});
},
}),
chatRooms: t.prismaField({
type: ['ChatRoom'],
resolve: (query, root, args, ctx, info) => {
return prisma.chatRoom.findMany({
...query,
});
},
}),
centerStaffs: t.prismaField({
type: ['CenterStaff'],
resolve: (query, root, args, ctx, info) => {
return prisma.centerStaff.findMany({
...query,
});
},
}),
workshopSubscriptions: t.prismaField({
type: ['WorkshopSubscription'],
resolve: (query, root, args, ctx, info) => {
return prisma.workshopSubscription.findMany({
...query,
});
},
}),
workshops: t.prismaField({
type: ['Workshop'],
resolve: (query, root, args, ctx, info) => {
return prisma.workshop.findMany({
...query,
});
},
}),
}), }),
}); });
// // Mutation section // Mutation section
// builder.mutationType({ // builder.mutationType({
// fields: (t) => ({ // fields: (t) => ({
// createUser: t.prismaField({ // createUser: t.prismaField({

View File

@@ -0,0 +1,26 @@
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class GraphQLValidationMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
// Only handle POST requests
if (req.method === 'POST' && req.headers['content-type'] === 'application/json') {
const { query, mutation, subscription } = req.body;
// If none of these are present, return a custom error response
if (!query && !mutation && !subscription) {
return res.status(400).json({
errors: [
{
message: 'Must provide a valid GraphQL query, mutation, or subscription.',
},
],
});
}
}
// Continue to the next middleware or GraphQL handler
next();
}
}