thang an bi ngu

This commit is contained in:
2024-10-06 20:42:02 +07:00
parent 7b678a7ef2
commit 83b453c3b8
9 changed files with 202 additions and 23 deletions

View File

@@ -1,5 +1,3 @@
const { environments } = require('eslint-plugin-prettier');
module.exports = { module.exports = {
parser: '@typescript-eslint/parser', parser: '@typescript-eslint/parser',
parserOptions: { parserOptions: {

64
package-lock.json generated
View File

@@ -23,6 +23,7 @@
"@nestjs/graphql": "^12.2.0", "@nestjs/graphql": "^12.2.0",
"@nestjs/jwt": "^10.2.0", "@nestjs/jwt": "^10.2.0",
"@nestjs/platform-express": "^10.0.0", "@nestjs/platform-express": "^10.0.0",
"@nestjs/swagger": "^7.4.2",
"@pothos/core": "^4.2.0", "@pothos/core": "^4.2.0",
"@pothos/plugin-add-graphql": "^4.1.0", "@pothos/plugin-add-graphql": "^4.1.0",
"@pothos/plugin-prisma": "^4.2.1", "@pothos/plugin-prisma": "^4.2.1",
@@ -40,6 +41,7 @@
"passport-jwt": "^4.0.1", "passport-jwt": "^4.0.1",
"reflect-metadata": "^0.2.0", "reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1", "rxjs": "^7.8.1",
"swagger-ui-express": "^5.0.1",
"type-graphql": "^2.0.0-rc.2" "type-graphql": "^2.0.0-rc.2"
}, },
"devDependencies": { "devDependencies": {
@@ -4910,6 +4912,12 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/@microsoft/tsdoc": {
"version": "0.15.0",
"resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.0.tgz",
"integrity": "sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==",
"license": "MIT"
},
"node_modules/@nestjs/apollo": { "node_modules/@nestjs/apollo": {
"version": "12.2.0", "version": "12.2.0",
"resolved": "https://registry.npmjs.org/@nestjs/apollo/-/apollo-12.2.0.tgz", "resolved": "https://registry.npmjs.org/@nestjs/apollo/-/apollo-12.2.0.tgz",
@@ -5303,6 +5311,39 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@nestjs/swagger": {
"version": "7.4.2",
"resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-7.4.2.tgz",
"integrity": "sha512-Mu6TEn1M/owIvAx2B4DUQObQXqo2028R2s9rSZ/hJEgBK95+doTwS0DjmVA2wTeZTyVtXOoN7CsoM5pONBzvKQ==",
"license": "MIT",
"dependencies": {
"@microsoft/tsdoc": "^0.15.0",
"@nestjs/mapped-types": "2.0.5",
"js-yaml": "4.1.0",
"lodash": "4.17.21",
"path-to-regexp": "3.3.0",
"swagger-ui-dist": "5.17.14"
},
"peerDependencies": {
"@fastify/static": "^6.0.0 || ^7.0.0",
"@nestjs/common": "^9.0.0 || ^10.0.0",
"@nestjs/core": "^9.0.0 || ^10.0.0",
"class-transformer": "*",
"class-validator": "*",
"reflect-metadata": "^0.1.12 || ^0.2.0"
},
"peerDependenciesMeta": {
"@fastify/static": {
"optional": true
},
"class-transformer": {
"optional": true
},
"class-validator": {
"optional": true
}
}
},
"node_modules/@nestjs/testing": { "node_modules/@nestjs/testing": {
"version": "10.4.4", "version": "10.4.4",
"resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.4.tgz", "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.4.tgz",
@@ -7212,7 +7253,6 @@
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true,
"license": "Python-2.0" "license": "Python-2.0"
}, },
"node_modules/array-flatten": { "node_modules/array-flatten": {
@@ -11602,7 +11642,6 @@
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"argparse": "^2.0.1" "argparse": "^2.0.1"
@@ -14247,6 +14286,27 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/swagger-ui-dist": {
"version": "5.17.14",
"resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.17.14.tgz",
"integrity": "sha512-CVbSfaLpstV65OnSjbXfVd6Sta3q3F7Cj/yYuvHMp1P90LztOLs6PfUnKEVAeiIVQt9u2SaPwv0LiH/OyMjHRw==",
"license": "Apache-2.0"
},
"node_modules/swagger-ui-express": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.1.tgz",
"integrity": "sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA==",
"license": "MIT",
"dependencies": {
"swagger-ui-dist": ">=5.0.0"
},
"engines": {
"node": ">= v0.10.32"
},
"peerDependencies": {
"express": ">=4.0.0 || >=5.0.0-beta"
}
},
"node_modules/swap-case": { "node_modules/swap-case": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/swap-case/-/swap-case-2.0.2.tgz", "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-2.0.2.tgz",

View File

@@ -37,6 +37,7 @@
"@nestjs/graphql": "^12.2.0", "@nestjs/graphql": "^12.2.0",
"@nestjs/jwt": "^10.2.0", "@nestjs/jwt": "^10.2.0",
"@nestjs/platform-express": "^10.0.0", "@nestjs/platform-express": "^10.0.0",
"@nestjs/swagger": "^7.4.2",
"@pothos/core": "^4.2.0", "@pothos/core": "^4.2.0",
"@pothos/plugin-add-graphql": "^4.1.0", "@pothos/plugin-add-graphql": "^4.1.0",
"@pothos/plugin-prisma": "^4.2.1", "@pothos/plugin-prisma": "^4.2.1",
@@ -54,6 +55,7 @@
"passport-jwt": "^4.0.1", "passport-jwt": "^4.0.1",
"reflect-metadata": "^0.2.0", "reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1", "rxjs": "^7.8.1",
"swagger-ui-express": "^5.0.1",
"type-graphql": "^2.0.0-rc.2" "type-graphql": "^2.0.0-rc.2"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -1,11 +1,13 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { GraphqlModule } from './graphql/graphql.module'; import { GraphqlModule } from './graphql/graphql.module';
import { ClerkModule } from './clerk/clerk.module'; import { ClerkModule } from './clerk/clerk.module';
import { RestfulModule } from './restful/restful.module';
@Module({ @Module({
imports: [ imports: [
GraphqlModule, // GraphQL setup GraphqlModule, // GraphQL setup
ClerkModule, // Clerk setup ClerkModule, // Clerk setup
RestfulModule, // RESTful API module
], ],
}) })
export class AppModule {} export class AppModule {}

View File

@@ -2,6 +2,7 @@ import SchemaBuilder from '@pothos/core';
import PrismaPlugin from '@pothos/plugin-prisma'; import PrismaPlugin from '@pothos/plugin-prisma';
import PrismaUtils from '@pothos/plugin-prisma-utils'; import PrismaUtils from '@pothos/plugin-prisma-utils';
import { DateTimeResolver } from 'graphql-scalars'; import { DateTimeResolver } from 'graphql-scalars';
import { GraphQLInt } from 'graphql';
import { PrismaService } from '../prisma/prisma.service'; import { PrismaService } from '../prisma/prisma.service';
import type PrismaTypes from '../types/pothos.generated'; import type PrismaTypes from '../types/pothos.generated';
import { getDatamodel } from '../types/pothos.generated'; import { getDatamodel } from '../types/pothos.generated';
@@ -32,6 +33,4 @@ export const builder = new SchemaBuilder<{
export const SortOrder = builder.enumType('SortOrder', { export const SortOrder = builder.enumType('SortOrder', {
values: ['asc', 'desc'], values: ['asc', 'desc'],
}); });
builder.addScalarType('DateTime', DateTimeResolver, {}); builder.addScalarType('DateTime', DateTimeResolver, {});

View File

@@ -32,7 +32,25 @@ builder.prismaObject('User', {
builder.prismaObject('Order', { builder.prismaObject('Order', {
fields: (t) => ({ fields: (t) => ({
id: t.exposeID('id'), id: t.exposeID('id'),
paymentId: t.exposeString('paymentId'),
userId: t.exposeID('userId'), userId: t.exposeID('userId'),
serviceId: t.exposeID('serviceId'),
status: t.exposeString('status'),
total: t.expose('total', {
type: 'Int',
}),
createdAt: t.expose('createdAt', {
type: 'DateTime',
nullable: true,
}),
updatedAt: t.expose('updatedAt', {
type: 'DateTime',
nullable: true,
}),
user: t.relation('user'),
payment: t.relation('payment'),
service: t.relation('service'),
refundTicket: t.relation('refundTicket'),
}), }),
}); });
@@ -59,6 +77,45 @@ builder.prismaObject('Message', {
}), }),
}); });
builder.prismaObject('Payment', {
fields: (t) => ({
id: t.exposeID('id'),
amount: t.expose('amount', {
type: 'Float',
}),
status: t.exposeString('status'),
createdAt: t.expose('createdAt', {
type: 'DateTime',
nullable: true,
}),
updatedAt: t.expose('updatedAt', {
type: 'DateTime',
nullable: true,
}),
order: t.relation('Order'),
}),
});
builder.prismaObject('RefundTicket', {
fields: (t) => ({
id: t.exposeID('id'),
orderId: t.exposeID('orderId'),
amount: t.expose('amount', {
type: 'Float',
}),
status: t.exposeString('status'),
createdAt: t.expose('createdAt', {
type: 'DateTime',
nullable: true,
}),
updatedAt: t.expose('updatedAt', {
type: 'DateTime',
nullable: true,
}),
order: t.relation('order'),
}),
});
builder.prismaObject('Service', { builder.prismaObject('Service', {
fields: (t) => ({ fields: (t) => ({
id: t.exposeID('id'), id: t.exposeID('id'),
@@ -146,6 +203,7 @@ builder.prismaObject('ChatRoom', {
builder.prismaObject('CenterStaff', { builder.prismaObject('CenterStaff', {
fields: (t) => ({ fields: (t) => ({
staffId: t.exposeID('staffId'), staffId: t.exposeID('staffId'),
staff: t.relation('staff'),
centerId: t.exposeID('centerId'), centerId: t.exposeID('centerId'),
serviceId: t.exposeID('serviceId'), serviceId: t.exposeID('serviceId'),
}), }),
@@ -261,28 +319,27 @@ builder.queryType({
take: t.arg.int(), take: t.arg.int(),
skip: t.arg.int(), skip: t.arg.int(),
}, },
resolve: (query, root, args, ctx, info) => { resolve: async (query, root, args, ctx, info) => {
return prisma.service.findMany({ return prisma.service.findMany({
// process filters // handle where condition
where: { where: {
name: { name: {
contains: args.where?.nameContain as string, contains: args.where?.nameContain as string | undefined,
startsWith: args.where?.nameStartsWith as string, startsWith: args.where?.nameStartsWith as string | undefined,
endsWith: args.where?.nameEndsWith as string, endsWith: args.where?.nameEndsWith as string | undefined,
}, },
}, },
// process order by // handle orderBy condition
orderBy: { orderBy: {
rating: args.orderBy?.rating as Prisma.SortOrder, rating: args.orderBy?.rating as Prisma.SortOrder,
price: args.orderBy?.price as Prisma.SortOrder, price: args.orderBy?.price as Prisma.SortOrder,
}, },
// process pagination // handle pagination
cursor: args.cursor as Prisma.ServiceWhereUniqueInput, cursor: args.cursor as Prisma.ServiceWhereUniqueInput | undefined,
take: args.take as number, take: args.take as number | undefined,
skip: args.skip as number, skip: args.skip as number | undefined,
...query,
}); });
}, },
}), }),
service: t.prismaField({ service: t.prismaField({
type: 'Service', type: 'Service',

View File

@@ -1,10 +1,36 @@
import { NestFactory } from '@nestjs/core'; import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module'; import { AppModule } from './app.module';
import { cors } from './common/utils/cors.utils'; import { cors } from './common/utils/cors.utils';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
// Import DateTime scalar if necessary
require('./common/utils/datetime.utils');
async function bootstrap() { async function bootstrap() {
const app = await NestFactory.create(AppModule); const app = await NestFactory.create(AppModule);
app.enableCors(cors); app.enableCors(cors);
await app.listen(3069);
const config = new DocumentBuilder()
.setTitle('EPESS API')
.setDescription('API documentation for EPESS application')
.setVersion('1.0')
.addBearerAuth()
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document);
document.paths['/graphql'] = {
get: {
summary: 'GraphQL Playground',
description: 'Access the GraphQL Playground to interact with the GraphQL API.',
responses: {
'200': {
description: 'GraphQL Playground',
},
},
},
};
await app.listen(3000);
} }
bootstrap(); bootstrap();

View File

@@ -1,5 +1,9 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { RestfulController } from './restful.controller';
import { RestfulService } from './restful.service';
@Module({ @Module({
imports: [], controllers: [RestfulController],
providers: [RestfulService],
}) })
export class RestfulModule {} export class RestfulModule {}

View File

@@ -0,0 +1,31 @@
import { Injectable } from '@nestjs/common';
@Injectable()
export class RestfulService {
getAllItems() {
// Implementation to get all items
return []; // Replace with actual logic
}
getItem(id: string) {
// Implementation to get a single item by id
return {}; // Replace with actual logic
}
createItem(createDto: any) {
// Implementation to create a new item
return {}; // Replace with actual logic
}
updateItem(id: string, updateDto: any) {
// Implementation to update an item by id
return {}; // Replace with actual logic
}
deleteItem(id: string) {
// Implementation to delete an item by id
return {}; // Replace with actual logic
}
}
export default RestfulService;