|
@@ -1,11 +1,11 @@
|
|
|
import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
|
|
import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
|
|
|
import { z } from '@hono/zod-openapi';
|
|
import { z } from '@hono/zod-openapi';
|
|
|
-import { GenericCrudService, CrudOptions } from './generic-crud.service';
|
|
|
|
|
|
|
+import { CrudOptions } from './generic-crud.service';
|
|
|
import { ErrorSchema } from './errorHandler';
|
|
import { ErrorSchema } from './errorHandler';
|
|
|
import { AuthContext } from '../types/context';
|
|
import { AuthContext } from '../types/context';
|
|
|
import { ObjectLiteral } from 'typeorm';
|
|
import { ObjectLiteral } from 'typeorm';
|
|
|
-import { AppDataSource } from '../data-source';
|
|
|
|
|
import { parseWithAwait } from './parseWithAwait';
|
|
import { parseWithAwait } from './parseWithAwait';
|
|
|
|
|
+import { ConcreteCrudService } from './concrete-crud.service';
|
|
|
|
|
|
|
|
export function createCrudRoutes<
|
|
export function createCrudRoutes<
|
|
|
T extends ObjectLiteral,
|
|
T extends ObjectLiteral,
|
|
@@ -16,15 +16,6 @@ export function createCrudRoutes<
|
|
|
>(options: CrudOptions<T, CreateSchema, UpdateSchema, GetSchema, ListSchema>) {
|
|
>(options: CrudOptions<T, CreateSchema, UpdateSchema, GetSchema, ListSchema>) {
|
|
|
const { entity, createSchema, updateSchema, getSchema, listSchema, searchFields, relations, middleware = [], userTracking, relationFields, readOnly = false } = options;
|
|
const { entity, createSchema, updateSchema, getSchema, listSchema, searchFields, relations, middleware = [], userTracking, relationFields, readOnly = false } = options;
|
|
|
|
|
|
|
|
- // 创建CRUD服务实例
|
|
|
|
|
- // 抽象类不能直接实例化,需要创建具体实现类
|
|
|
|
|
- class ConcreteCrudService extends GenericCrudService<T> {
|
|
|
|
|
- constructor() {
|
|
|
|
|
- super(AppDataSource, entity, { userTracking, relationFields });
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- const crudService = new ConcreteCrudService();
|
|
|
|
|
-
|
|
|
|
|
// 创建路由实例
|
|
// 创建路由实例
|
|
|
const app = new OpenAPIHono<AuthContext>();
|
|
const app = new OpenAPIHono<AuthContext>();
|
|
|
|
|
|
|
@@ -227,7 +218,7 @@ export function createCrudRoutes<
|
|
|
try {
|
|
try {
|
|
|
const query = c.req.valid('query') as any;
|
|
const query = c.req.valid('query') as any;
|
|
|
const { page, pageSize, keyword, sortBy, sortOrder, filters } = query;
|
|
const { page, pageSize, keyword, sortBy, sortOrder, filters } = query;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 构建排序对象
|
|
// 构建排序对象
|
|
|
const order: any = {};
|
|
const order: any = {};
|
|
|
if (sortBy) {
|
|
if (sortBy) {
|
|
@@ -235,7 +226,7 @@ export function createCrudRoutes<
|
|
|
} else {
|
|
} else {
|
|
|
order['id'] = 'DESC';
|
|
order['id'] = 'DESC';
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 解析筛选条件
|
|
// 解析筛选条件
|
|
|
let parsedFilters: any = undefined;
|
|
let parsedFilters: any = undefined;
|
|
|
if (filters) {
|
|
if (filters) {
|
|
@@ -245,7 +236,11 @@ export function createCrudRoutes<
|
|
|
return c.json({ code: 400, message: '筛选条件格式错误' }, 400);
|
|
return c.json({ code: 400, message: '筛选条件格式错误' }, 400);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+ const crudService = new ConcreteCrudService(entity, {
|
|
|
|
|
+ userTracking: userTracking,
|
|
|
|
|
+ relationFields: relationFields
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
const [data, total] = await crudService.getList(
|
|
const [data, total] = await crudService.getList(
|
|
|
page,
|
|
page,
|
|
|
pageSize,
|
|
pageSize,
|
|
@@ -256,7 +251,7 @@ export function createCrudRoutes<
|
|
|
order,
|
|
order,
|
|
|
parsedFilters
|
|
parsedFilters
|
|
|
);
|
|
);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
return c.json({
|
|
return c.json({
|
|
|
// data: z.array(listSchema).parse(data),
|
|
// data: z.array(listSchema).parse(data),
|
|
|
data: await parseWithAwait(z.array(listSchema), data),
|
|
data: await parseWithAwait(z.array(listSchema), data),
|
|
@@ -276,6 +271,11 @@ export function createCrudRoutes<
|
|
|
try {
|
|
try {
|
|
|
const data = c.req.valid('json');
|
|
const data = c.req.valid('json');
|
|
|
const user = c.get('user');
|
|
const user = c.get('user');
|
|
|
|
|
+
|
|
|
|
|
+ const crudService = new ConcreteCrudService(entity, {
|
|
|
|
|
+ userTracking: userTracking,
|
|
|
|
|
+ relationFields: relationFields
|
|
|
|
|
+ });
|
|
|
const result = await crudService.create(data, user?.id);
|
|
const result = await crudService.create(data, user?.id);
|
|
|
return c.json(result, 201);
|
|
return c.json(result, 201);
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
@@ -291,12 +291,17 @@ export function createCrudRoutes<
|
|
|
.openapi(getRouteDef, async (c: any) => {
|
|
.openapi(getRouteDef, async (c: any) => {
|
|
|
try {
|
|
try {
|
|
|
const { id } = c.req.valid('param');
|
|
const { id } = c.req.valid('param');
|
|
|
|
|
+
|
|
|
|
|
+ const crudService = new ConcreteCrudService(entity, {
|
|
|
|
|
+ userTracking: userTracking,
|
|
|
|
|
+ relationFields: relationFields
|
|
|
|
|
+ });
|
|
|
const result = await crudService.getById(id, relations || []);
|
|
const result = await crudService.getById(id, relations || []);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (!result) {
|
|
if (!result) {
|
|
|
return c.json({ code: 404, message: '资源不存在' }, 404);
|
|
return c.json({ code: 404, message: '资源不存在' }, 404);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// return c.json(await getSchema.parseAsync(result), 200);
|
|
// return c.json(await getSchema.parseAsync(result), 200);
|
|
|
return c.json(await parseWithAwait(getSchema, result), 200);
|
|
return c.json(await parseWithAwait(getSchema, result), 200);
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
@@ -314,12 +319,17 @@ export function createCrudRoutes<
|
|
|
const { id } = c.req.valid('param');
|
|
const { id } = c.req.valid('param');
|
|
|
const data = c.req.valid('json');
|
|
const data = c.req.valid('json');
|
|
|
const user = c.get('user');
|
|
const user = c.get('user');
|
|
|
|
|
+
|
|
|
|
|
+ const crudService = new ConcreteCrudService(entity, {
|
|
|
|
|
+ userTracking: userTracking,
|
|
|
|
|
+ relationFields: relationFields
|
|
|
|
|
+ });
|
|
|
const result = await crudService.update(id, data, user?.id);
|
|
const result = await crudService.update(id, data, user?.id);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (!result) {
|
|
if (!result) {
|
|
|
return c.json({ code: 404, message: '资源不存在' }, 404);
|
|
return c.json({ code: 404, message: '资源不存在' }, 404);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
return c.json(result, 200);
|
|
return c.json(result, 200);
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
if (error instanceof z.ZodError) {
|
|
if (error instanceof z.ZodError) {
|
|
@@ -334,12 +344,17 @@ export function createCrudRoutes<
|
|
|
.openapi(deleteRouteDef, async (c: any) => {
|
|
.openapi(deleteRouteDef, async (c: any) => {
|
|
|
try {
|
|
try {
|
|
|
const { id } = c.req.valid('param');
|
|
const { id } = c.req.valid('param');
|
|
|
|
|
+
|
|
|
|
|
+ const crudService = new ConcreteCrudService(entity, {
|
|
|
|
|
+ userTracking: userTracking,
|
|
|
|
|
+ relationFields: relationFields
|
|
|
|
|
+ });
|
|
|
const success = await crudService.delete(id);
|
|
const success = await crudService.delete(id);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (!success) {
|
|
if (!success) {
|
|
|
return c.json({ code: 404, message: '资源不存在' }, 404);
|
|
return c.json({ code: 404, message: '资源不存在' }, 404);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
return c.body(null, 204);
|
|
return c.body(null, 204);
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
if (error instanceof z.ZodError) {
|
|
if (error instanceof z.ZodError) {
|
|
@@ -360,7 +375,7 @@ export function createCrudRoutes<
|
|
|
try {
|
|
try {
|
|
|
const query = c.req.valid('query') as any;
|
|
const query = c.req.valid('query') as any;
|
|
|
const { page, pageSize, keyword, sortBy, sortOrder, filters } = query;
|
|
const { page, pageSize, keyword, sortBy, sortOrder, filters } = query;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 构建排序对象
|
|
// 构建排序对象
|
|
|
const order: any = {};
|
|
const order: any = {};
|
|
|
if (sortBy) {
|
|
if (sortBy) {
|
|
@@ -368,7 +383,7 @@ export function createCrudRoutes<
|
|
|
} else {
|
|
} else {
|
|
|
order['id'] = 'DESC';
|
|
order['id'] = 'DESC';
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 解析筛选条件
|
|
// 解析筛选条件
|
|
|
let parsedFilters: any = undefined;
|
|
let parsedFilters: any = undefined;
|
|
|
if (filters) {
|
|
if (filters) {
|
|
@@ -378,7 +393,11 @@ export function createCrudRoutes<
|
|
|
return c.json({ code: 400, message: '筛选条件格式错误' }, 400);
|
|
return c.json({ code: 400, message: '筛选条件格式错误' }, 400);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+ const crudService = new ConcreteCrudService(entity, {
|
|
|
|
|
+ userTracking: userTracking,
|
|
|
|
|
+ relationFields: relationFields
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
const [data, total] = await crudService.getList(
|
|
const [data, total] = await crudService.getList(
|
|
|
page,
|
|
page,
|
|
|
pageSize,
|
|
pageSize,
|
|
@@ -389,7 +408,7 @@ export function createCrudRoutes<
|
|
|
order,
|
|
order,
|
|
|
parsedFilters
|
|
parsedFilters
|
|
|
);
|
|
);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
return c.json({
|
|
return c.json({
|
|
|
data: await parseWithAwait(z.array(listSchema), data),
|
|
data: await parseWithAwait(z.array(listSchema), data),
|
|
|
pagination: { total, current: page, pageSize }
|
|
pagination: { total, current: page, pageSize }
|
|
@@ -407,12 +426,17 @@ export function createCrudRoutes<
|
|
|
.openapi(getRouteDef, async (c: any) => {
|
|
.openapi(getRouteDef, async (c: any) => {
|
|
|
try {
|
|
try {
|
|
|
const { id } = c.req.valid('param');
|
|
const { id } = c.req.valid('param');
|
|
|
|
|
+
|
|
|
|
|
+ const crudService = new ConcreteCrudService(entity, {
|
|
|
|
|
+ userTracking: userTracking,
|
|
|
|
|
+ relationFields: relationFields
|
|
|
|
|
+ });
|
|
|
const result = await crudService.getById(id, relations || []);
|
|
const result = await crudService.getById(id, relations || []);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (!result) {
|
|
if (!result) {
|
|
|
return c.json({ code: 404, message: '资源不存在' }, 404);
|
|
return c.json({ code: 404, message: '资源不存在' }, 404);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
return c.json(await parseWithAwait(getSchema, result), 200);
|
|
return c.json(await parseWithAwait(getSchema, result), 200);
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
if (error instanceof z.ZodError) {
|
|
if (error instanceof z.ZodError) {
|