update service status
This commit is contained in:
Submodule epess-database updated: 152f3220bf...4f40a566c8
22
package-lock.json
generated
22
package-lock.json
generated
@@ -25,6 +25,8 @@
|
||||
"@nestjs/swagger": "^7.4.2",
|
||||
"@pothos/core": "^4.2.0",
|
||||
"@pothos/plugin-add-graphql": "^4.1.0",
|
||||
"@pothos/plugin-authz": "^3.5.10",
|
||||
"@pothos/plugin-errors": "^4.2.0",
|
||||
"@pothos/plugin-prisma": "^4.2.1",
|
||||
"@pothos/plugin-prisma-utils": "^1.2.0",
|
||||
"@pothos/plugin-relay": "^4.3.0",
|
||||
@@ -4860,6 +4862,26 @@
|
||||
"graphql": ">=16.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@pothos/plugin-authz": {
|
||||
"version": "3.5.10",
|
||||
"resolved": "https://registry.npmjs.org/@pothos/plugin-authz/-/plugin-authz-3.5.10.tgz",
|
||||
"integrity": "sha512-HIrz72+KnbvJjRKEtuy+c/J69jxET/yiSKLx/q3IV8FC4GyPKnPxlwuGlMczxlpK6+UG0gE0ziCAwY6LWEd2Yg==",
|
||||
"license": "ISC",
|
||||
"peerDependencies": {
|
||||
"@graphql-authz/core": "*",
|
||||
"graphql": ">=15.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@pothos/plugin-errors": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@pothos/plugin-errors/-/plugin-errors-4.2.0.tgz",
|
||||
"integrity": "sha512-Yt87hn7z0+1bv7bhrJCD5GH9+NTO/5CJEkbebyM4scnnmQ0rpqyO/yViIirtzCXk/NKBHEiLrthL2frQxUmJ5w==",
|
||||
"license": "ISC",
|
||||
"peerDependencies": {
|
||||
"@pothos/core": "*",
|
||||
"graphql": ">=16.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@pothos/plugin-prisma": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@pothos/plugin-prisma/-/plugin-prisma-4.2.1.tgz",
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
"@nestjs/swagger": "^7.4.2",
|
||||
"@pothos/core": "^4.2.0",
|
||||
"@pothos/plugin-add-graphql": "^4.1.0",
|
||||
"@pothos/plugin-authz": "^3.5.10",
|
||||
"@pothos/plugin-errors": "^4.2.0",
|
||||
"@pothos/plugin-prisma": "^4.2.1",
|
||||
"@pothos/plugin-prisma-utils": "^1.2.0",
|
||||
"@pothos/plugin-relay": "^4.3.0",
|
||||
|
||||
@@ -18,11 +18,17 @@ import SmartSubscriptionPlugin, {
|
||||
subscribeOptionsFromIterator,
|
||||
} from '@pothos/plugin-smart-subscriptions';
|
||||
import RelayPlugin from '@pothos/plugin-relay';
|
||||
import ErrorsPlugin from '@pothos/plugin-errors';
|
||||
import AuthzPlugin from '@pothos/plugin-authz';
|
||||
import { User } from '@prisma/client';
|
||||
// import { rules } from '../common/graphql/common.graphql.auth-rule';
|
||||
|
||||
export interface SchemaContext {
|
||||
req: Request;
|
||||
res: Response;
|
||||
generator: PrismaCrudGenerator<BuilderTypes>;
|
||||
me: User;
|
||||
pubSub: PubSub;
|
||||
generator: PrismaCrudGenerator<BuilderTypes>;
|
||||
}
|
||||
|
||||
export interface SchemaBuilderOption {
|
||||
@@ -32,6 +38,7 @@ export interface SchemaBuilderOption {
|
||||
Connection: {
|
||||
totalCount: number | (() => number | Promise<number>);
|
||||
};
|
||||
// AuthZRule: keyof typeof rules;
|
||||
Scalars: {
|
||||
DateTime: {
|
||||
Input: Date;
|
||||
@@ -60,6 +67,8 @@ export class Builder extends SchemaBuilder<SchemaBuilderOption> {
|
||||
SimpleObjectPlugin,
|
||||
SmartSubscriptionPlugin,
|
||||
RelayPlugin,
|
||||
ErrorsPlugin,
|
||||
AuthzPlugin,
|
||||
],
|
||||
smartSubscriptions: {
|
||||
debounceDelay: 1000,
|
||||
@@ -75,6 +84,9 @@ export class Builder extends SchemaBuilder<SchemaBuilderOption> {
|
||||
onUnusedQuery: process.env.NODE_ENV === 'production' ? null : 'warn',
|
||||
dmmf: getDatamodel(),
|
||||
},
|
||||
errors: {
|
||||
defaultTypes: [],
|
||||
},
|
||||
});
|
||||
this.generator = new PrismaCrudGenerator<BuilderTypes>(this);
|
||||
this.addScalarType('DateTime', DateTimeResolver);
|
||||
@@ -83,7 +95,7 @@ export class Builder extends SchemaBuilder<SchemaBuilderOption> {
|
||||
|
||||
this.queryType({});
|
||||
this.mutationType({});
|
||||
// this.subscriptionType({});
|
||||
this.subscriptionType({});
|
||||
|
||||
this.globalConnectionField('totalCount', (t) =>
|
||||
t.int({
|
||||
|
||||
@@ -6,6 +6,7 @@ import { PothosApolloDriver } from '@smatch-corp/nestjs-pothos-apollo-driver';
|
||||
import { Builder } from './graphql.builder';
|
||||
import { PrismaService } from '../Prisma/prisma.service';
|
||||
import { GraphQLValidationMiddleware } from '../middlewares/graphql.middleware';
|
||||
import { CommonModule } from '../common/common.module';
|
||||
import { PrismaModule } from '../Prisma/prisma.module';
|
||||
import { UserModule } from '../User/user.module';
|
||||
import { CenterModule } from '../Center/center.module';
|
||||
@@ -33,6 +34,7 @@ import { ManagedServiceModule } from '../ManagedService/managedservice.module';
|
||||
@Global()
|
||||
@Module({
|
||||
imports: [
|
||||
CommonModule,
|
||||
PrismaModule,
|
||||
UserModule,
|
||||
CenterModule,
|
||||
@@ -64,9 +66,9 @@ import { ManagedServiceModule } from '../ManagedService/managedservice.module';
|
||||
GraphQLModule.forRoot<ApolloDriverConfig>({
|
||||
driver: PothosApolloDriver,
|
||||
path: process.env.API_PATH + '/graphql',
|
||||
debug: process.env.NODE_ENV === 'development',
|
||||
playground: true,
|
||||
introspection: true,
|
||||
debug: process.env.NODE_ENV === 'development' || false,
|
||||
playground: process.env.NODE_ENV === 'development' || false,
|
||||
introspection: process.env.NODE_ENV === 'development' || false,
|
||||
installSubscriptionHandlers: true,
|
||||
subscriptions: {
|
||||
'graphql-ws': true,
|
||||
|
||||
@@ -79,18 +79,66 @@ export class MessageSchema extends PothosSchema {
|
||||
});
|
||||
},
|
||||
}),
|
||||
messagesByChatRoomId: t.prismaField({
|
||||
type: [this.message()],
|
||||
description: 'Retrieve a list of messages by chat room ID.',
|
||||
args: this.builder.generator.findManyArgs('Message'),
|
||||
resolve: async (query, root, args) => {
|
||||
return await this.prisma.message.findMany({
|
||||
...query,
|
||||
where: args.filter ?? undefined,
|
||||
});
|
||||
},
|
||||
}),
|
||||
}));
|
||||
|
||||
// mutations
|
||||
this.builder.mutationFields((t) => ({
|
||||
sendMessage: t.prismaField({
|
||||
type: this.message(),
|
||||
description: 'Send a message to a chat room.',
|
||||
args: {
|
||||
input: t.arg({
|
||||
type: this.builder.generator.getCreateInput('Message'),
|
||||
description: 'The message to send.',
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
resolve: async (query, root, args, ctx, info) => {
|
||||
const message = await this.prisma.message.create({
|
||||
...query,
|
||||
data: args.input,
|
||||
});
|
||||
ctx.pubSub.publish('MESSAGE_SENT', message);
|
||||
return message;
|
||||
},
|
||||
}),
|
||||
}));
|
||||
|
||||
// subscriptions
|
||||
// this.builder.subscriptionFields((t) => ({
|
||||
// messageSent: t.field({
|
||||
// subscribe: (_parent, _args, ctx) => {
|
||||
// return ctx.pubSub.asyncIterator('MESSAGE_SENT');
|
||||
// },
|
||||
// resolve: (payload) => payload as any,
|
||||
// }),
|
||||
// }));
|
||||
/* The code snippet `subscriptions` is currently commented out in the provided TypeScript class. It
|
||||
appears to be a placeholder or a section where subscription-related logic or fields could be
|
||||
defined. In GraphQL, subscriptions are used to listen for real-time events or changes in data
|
||||
and receive updates when those events occur. */
|
||||
|
||||
this.builder.subscriptionFields((t) => ({
|
||||
messageSent: t.field({
|
||||
subscribe: (_, __, ctx) => {
|
||||
return {
|
||||
[Symbol.asyncIterator]: () =>
|
||||
ctx.pubSub.asyncIterator('MESSAGE_SENT'),
|
||||
};
|
||||
},
|
||||
type: this.message(), // Add the type property
|
||||
resolve: (payload) =>
|
||||
payload as {
|
||||
message: 'Json';
|
||||
id: string;
|
||||
senderId: string;
|
||||
chatRoomId: string;
|
||||
sentAt: Date;
|
||||
},
|
||||
}),
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,24 @@ export class PrismaService extends PrismaClient implements OnModuleInit {
|
||||
async onModuleInit() {
|
||||
this.logger.log('Try to connect database...');
|
||||
|
||||
await this.$connect();
|
||||
for (let attempt = 1; attempt <= 3; attempt++) {
|
||||
try {
|
||||
await this.$connect();
|
||||
break; // Exit loop if connection is successful
|
||||
} catch (error) {
|
||||
if (attempt < 3) {
|
||||
this.logger.warn(
|
||||
`Connection attempt ${attempt} failed. Retrying in 5000ms...`,
|
||||
);
|
||||
await new Promise((resolve) => setTimeout(resolve, 5000));
|
||||
} else {
|
||||
this.logger.error(
|
||||
'Failed to connect to the database after 3 attempts.',
|
||||
);
|
||||
throw error; // Rethrow the error after 3 failed attempts
|
||||
}
|
||||
}
|
||||
}
|
||||
this.logger.log('Connected.');
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
import { Builder } from '../Graphql/graphql.builder';
|
||||
import { PrismaService } from '../Prisma/prisma.service';
|
||||
import { MinioService } from '../Minio/minio.service';
|
||||
import { ServiceStatus } from '@prisma/client';
|
||||
@Injectable()
|
||||
export class ServiceSchema extends PothosSchema {
|
||||
constructor(
|
||||
@@ -55,6 +56,11 @@ export class ServiceSchema extends PothosSchema {
|
||||
imageFileUrl: t.exposeString('imageFileUrl', {
|
||||
description: 'The URL of the image file for the service.',
|
||||
}),
|
||||
status: t.expose('status', {
|
||||
type: ServiceStatus,
|
||||
nullable: true,
|
||||
description: 'The status of the service.',
|
||||
}),
|
||||
createdAt: t.expose('createdAt', {
|
||||
type: 'DateTime',
|
||||
nullable: true,
|
||||
@@ -125,6 +131,7 @@ export class ServiceSchema extends PothosSchema {
|
||||
description:
|
||||
'Retrieve a list of services with optional filtering, ordering, and pagination.',
|
||||
type: [this.service()],
|
||||
|
||||
args: this.builder.generator.findManyArgs('Service'),
|
||||
resolve: async (query, root, args, ctx, info) => {
|
||||
return await this.prisma.service.findMany({
|
||||
|
||||
@@ -8,6 +8,9 @@ import {
|
||||
import { Builder } from '../Graphql/graphql.builder';
|
||||
import { PrismaService } from '../Prisma/prisma.service';
|
||||
import { clerkClient } from '@clerk/express';
|
||||
import type { Session } from '@clerk/express';
|
||||
import { UnauthorizedException } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class UserSchema extends PothosSchema {
|
||||
constructor(
|
||||
@@ -89,17 +92,51 @@ export class UserSchema extends PothosSchema {
|
||||
@Pothos()
|
||||
init(): void {
|
||||
this.builder.queryFields((t) => ({
|
||||
// me: t.prismaField({
|
||||
// description: 'Retrieve the current user.',
|
||||
// type: this.user(),
|
||||
// resolve: async (query, root, args, ctx, info) => {
|
||||
// const sessionId = ctx.req.headers.sessionId;
|
||||
// const userId = await clerkClient.users.getUser()
|
||||
// return await this.prisma.user.findUnique({
|
||||
// where: { id: ctx.req.headers.authorization },
|
||||
// });
|
||||
// },
|
||||
// }),
|
||||
session: t.field({
|
||||
type: 'Json',
|
||||
args: {
|
||||
sessionId: t.arg({ type: 'String', required: true }),
|
||||
},
|
||||
resolve: async (_, { sessionId }) => {
|
||||
const session = await clerkClient.sessions.getSession(sessionId);
|
||||
return JSON.parse(JSON.stringify(session));
|
||||
},
|
||||
}),
|
||||
newSession: t.field({
|
||||
type: 'String',
|
||||
args: {
|
||||
userId: t.arg({
|
||||
type: 'String',
|
||||
required: true,
|
||||
}),
|
||||
},
|
||||
resolve: async (_, { userId }) => {
|
||||
const session = await clerkClient.signInTokens.createSignInToken({
|
||||
userId,
|
||||
expiresInSeconds: 60 * 60 * 24,
|
||||
});
|
||||
return session.id;
|
||||
},
|
||||
}),
|
||||
me: t.prismaField({
|
||||
description: 'Retrieve the current user.',
|
||||
type: this.user(),
|
||||
resolve: async (query, root, args, ctx, info) => {
|
||||
const sessionCookie = ctx.req.headers.cookie
|
||||
?.split('; ')
|
||||
.find((row) => row.startsWith('__session='))
|
||||
?.split('=')[1];
|
||||
if (!sessionCookie)
|
||||
throw new UnauthorizedException({
|
||||
message: 'No session cookie found',
|
||||
});
|
||||
const session = await clerkClient.sessions.getSession(sessionCookie);
|
||||
if (!session) throw new UnauthorizedException();
|
||||
return await this.prisma.user.findUnique({
|
||||
where: { id: session.userId },
|
||||
});
|
||||
},
|
||||
}),
|
||||
|
||||
users: t.prismaField({
|
||||
description:
|
||||
|
||||
9
src/common/common.module.ts
Normal file
9
src/common/common.module.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { CommonGraphqlError } from './graphql/common.graphql.error';
|
||||
|
||||
@Module({
|
||||
imports: [],
|
||||
providers: [CommonGraphqlError],
|
||||
exports: [CommonGraphqlError],
|
||||
})
|
||||
export class CommonModule {}
|
||||
0
src/common/graphql/common.graphql.auth-rule.ts
Normal file
0
src/common/graphql/common.graphql.auth-rule.ts
Normal file
24
src/common/graphql/common.graphql.error.ts
Normal file
24
src/common/graphql/common.graphql.error.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Builder } from '../../Graphql/graphql.builder';
|
||||
import {
|
||||
PothosRef,
|
||||
PothosSchema,
|
||||
SchemaBuilderToken,
|
||||
} from '@smatch-corp/nestjs-pothos';
|
||||
|
||||
@Injectable()
|
||||
export class CommonGraphqlError extends PothosSchema {
|
||||
constructor(@Inject(SchemaBuilderToken) private readonly builder: Builder) {
|
||||
super();
|
||||
}
|
||||
|
||||
@PothosRef()
|
||||
error() {
|
||||
return this.builder.objectType(Error, {
|
||||
name: 'Error',
|
||||
fields: (t) => ({
|
||||
message: t.exposeString('message'),
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
10
src/main.ts
10
src/main.ts
@@ -2,6 +2,7 @@ import { NestFactory } from '@nestjs/core';
|
||||
import { AppModule } from './app.module';
|
||||
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
|
||||
import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.js';
|
||||
import { clerkMiddleware } from '@clerk/express';
|
||||
import { Logger } from '@nestjs/common';
|
||||
|
||||
async function bootstrap() {
|
||||
@@ -11,11 +12,7 @@ async function bootstrap() {
|
||||
app.enableCors({
|
||||
origin: corsOrigin,
|
||||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
|
||||
allowedHeaders: [
|
||||
'Content-Type',
|
||||
'Authorization',
|
||||
'x-apollo-operation-name',
|
||||
],
|
||||
allowedHeaders: ['Content-Type', '*', 'x-apollo-operation-name'],
|
||||
credentials: true,
|
||||
});
|
||||
|
||||
@@ -46,6 +43,9 @@ async function bootstrap() {
|
||||
},
|
||||
};
|
||||
|
||||
// clerk middleware
|
||||
app.use(clerkMiddleware({}));
|
||||
|
||||
// graphql upload
|
||||
app.use(
|
||||
graphqlUploadExpress({
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user