add api web service

This commit is contained in:
Warunee Tamkoo 2025-08-07 13:05:58 +07:00
parent dab30e6325
commit 89d22b0274
4 changed files with 779 additions and 0 deletions

View file

@ -0,0 +1,609 @@
import { ApiAttribute } from "./../entities/ApiAttribute";
import { CreateApi } from "./../entities/ApiName";
import { PosMaster } from "../entities/PosMaster";
import { OrgChild4 } from "../entities/OrgChild4";
import { OrgChild3 } from "../entities/OrgChild3";
import { OrgChild2 } from "../entities/OrgChild2";
import { OrgChild1 } from "../entities/OrgChild1";
import { OrgRoot } from "../entities/OrgRoot";
import { ProfileEmployee } from "../entities/ProfileEmployee";
import { ProfileSalary } from "../entities/ProfileSalary";
import { ProfileOther } from "../entities/ProfileOther";
import { ProfileNopaid } from "../entities/ProfileNopaid";
import { ProfileLeave } from "../entities/ProfileLeave";
import { ProfileInsignia } from "../entities/ProfileInsignia";
import { ProfileHonor } from "../entities/ProfileHonor";
import { ProfileGovernment } from "../entities/ProfileGovernment";
import { ProfileFamilyMother } from "../entities/ProfileFamilyMother";
import { ProfileFamilyFather } from "../entities/ProfileFamilyFather";
import { ProfileFamilyCouple } from "../entities/ProfileFamilyCouple";
import { ProfileEducation } from "../entities/ProfileEducation";
import { ProfileDuty } from "../entities/ProfileDuty";
import { ProfileDiscipline } from "../entities/ProfileDiscipline";
import { ProfileDevelopment } from "../entities/ProfileDevelopment";
import { ProfileChildren } from "../entities/ProfileChildren";
import { ProfileChangeName } from "../entities/ProfileChangeName";
import { ProfileCertificate } from "../entities/ProfileCertificate";
import { ProfileAssessment } from "../entities/ProfileAssessment";
import { ProfileAbility } from "../entities/ProfileAbility";
import {
Controller,
Post,
Delete,
Route,
Security,
Tags,
Body,
Path,
Request,
Response,
Get,
Put,
Query,
} from "tsoa";
import { AppDataSource } from "../database/data-source";
import HttpSuccess from "../interfaces/http-success";
import HttpStatusCode from "../interfaces/http-status";
import HttpError from "../interfaces/http-error";
import { RequestWithUser } from "../middlewares/user";
import { ApiName } from "../entities/ApiName";
import { Profile } from "../entities/Profile";
@Route("api/v1/org/api-manage")
@Tags("ApiKey")
@Security("bearerAuth")
@Response(
HttpStatusCode.INTERNAL_SERVER_ERROR,
"เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง",
)
export class ApiManageController extends Controller {
// private apiNameRepository = AppDataSource.getRepository(ApiName);
private profileRepository = AppDataSource.getRepository(Profile);
private profileEmployeeRepository = AppDataSource.getRepository(ProfileEmployee);
private profileGovernmentRepository = AppDataSource.getRepository(ProfileGovernment);
private profileProfileSalaryRepository = AppDataSource.getRepository(ProfileSalary);
private profileAbilityRepository = AppDataSource.getRepository(ProfileAbility);
private profileAssessmentRepository = AppDataSource.getRepository(ProfileAssessment);
private profileCertificateRepository = AppDataSource.getRepository(ProfileCertificate);
private profileHonorRepository = AppDataSource.getRepository(ProfileHonor);
private profileInsigniaRepository = AppDataSource.getRepository(ProfileInsignia);
private profileLeaveRepository = AppDataSource.getRepository(ProfileLeave);
private profileChangeNameRepository = AppDataSource.getRepository(ProfileChangeName);
private profileDevelopmentRepository = AppDataSource.getRepository(ProfileDevelopment);
private profileDisciplineRepository = AppDataSource.getRepository(ProfileDiscipline);
private profileDutyRepository = AppDataSource.getRepository(ProfileDuty);
private profileEducationRepository = AppDataSource.getRepository(ProfileEducation);
private profileFamilyCoupleRepository = AppDataSource.getRepository(ProfileFamilyCouple);
private profileFamilyFatherRepository = AppDataSource.getRepository(ProfileFamilyFather);
private profileFamilyMotherRepository = AppDataSource.getRepository(ProfileFamilyMother);
private profileChildrenRepository = AppDataSource.getRepository(ProfileChildren);
private profileNopaidRepository = AppDataSource.getRepository(ProfileNopaid);
private profileOtherRepository = AppDataSource.getRepository(ProfileOther);
private orgRootRepository = AppDataSource.getRepository(OrgRoot);
private orgChild1Repository = AppDataSource.getRepository(OrgChild1);
private orgChild2Repository = AppDataSource.getRepository(OrgChild2);
private orgChild3Repository = AppDataSource.getRepository(OrgChild3);
private orgChild4Repository = AppDataSource.getRepository(OrgChild4);
private posMasterRepository = AppDataSource.getRepository(PosMaster);
private systems = [
{
code: "registry",
name: "ข้อมูลทะเบียนประวัติข้าราชการ",
},
{
code: "registry_emp",
name: "ข้อมูลทะเบียนประวัติลูกจ้างประจำ",
},
{
code: "registry_temp",
name: "ข้อมูลทะเบียนประวัติลูกจ้างชั่วคราว",
},
{
code: "organization",
name: "ข้อมูลโครงสร้างและอัตรากำลัง",
},
];
/**
* list systems
* @summary systems
*/
@Get("/systems")
async listSystems() {
return new HttpSuccess(this.systems);
}
/**
* list fields by systems
* @summary fields systems
*/
@Get("/:system/fields")
async listAttribute(
@Request() req: RequestWithUser,
@Path("system") system: "registry" | "registry_emp" | "registry_temp" | "organization",
): Promise<HttpSuccess | HttpError> {
try {
if (!req.user.role.includes("SUPER_ADMIN")) {
throw new HttpError(HttpStatusCode.FORBIDDEN, "คุณไม่มีสิทธิ์ในการเข้าถึงข้อมูลนี้");
}
const entities = [
{
name: "Profile",
repository: this.profileRepository,
description: "ข้อมูลหลัก",
system: ["registry"],
},
{
name: "ProfileEmployee",
repository: this.profileEmployeeRepository,
description: "ข้อมูลหลัก",
system: ["registry_emp", "registry_temp"],
},
{
name: "ProfileGovernment",
repository: this.profileGovernmentRepository,
description: "ข้อมูลราชการ",
system: ["registry", "registry_emp", "registry_temp"],
},
{
name: "ProfileSalary",
repository: this.profileProfileSalaryRepository,
description: "ข้อมูลตำแหน่ง/เงินเดือน",
system: ["registry", "registry_emp", "registry_temp"],
},
{
name: "ProfileAbility",
repository: this.profileAbilityRepository,
description: "ข้อมูลความสามารถ",
system: ["registry", "registry_emp", "registry_temp"],
},
{
name: "ProfileAssessment",
repository: this.profileAssessmentRepository,
description: "ข้อมูลการประเมิน",
system: ["registry", "registry_emp", "registry_temp"],
},
{
name: "ProfileCertificate",
repository: this.profileCertificateRepository,
description: "ข้อมูลใบรับรอง",
system: ["registry", "registry_emp", "registry_temp"],
},
{
name: "ProfileHonor",
repository: this.profileHonorRepository,
description: "ข้อมูลเกียรติบัตร",
system: ["registry", "registry_emp", "registry_temp"],
},
{
name: "ProfileInsignia",
repository: this.profileInsigniaRepository,
description: "ข้อมูลเครื่องหมาย",
system: ["registry", "registry_emp", "registry_temp"],
},
{
name: "ProfileLeave",
repository: this.profileLeaveRepository,
description: "ข้อมูลการลา",
system: ["registry", "registry_emp", "registry_temp"],
},
{
name: "ProfileChangeName",
repository: this.profileChangeNameRepository,
description: "ข้อมูลการเปลี่ยนชื่อ",
system: ["registry", "registry_emp", "registry_temp"],
},
{
name: "ProfileDevelopment",
repository: this.profileDevelopmentRepository,
description: "ข้อมูลการพัฒนา",
system: ["registry", "registry_emp", "registry_temp"],
},
{
name: "ProfileDiscipline",
repository: this.profileDisciplineRepository,
description: "ข้อมูลวินัย",
system: ["registry", "registry_emp", "registry_temp"],
},
{
name: "ProfileDuty",
repository: this.profileDutyRepository,
description: "ข้อมูลหน้าที่ปฏิบัติราชการ",
system: ["registry", "registry_emp", "registry_temp"],
},
{
name: "ProfileEducation",
repository: this.profileEducationRepository,
description: "ข้อมูลการศึกษา",
system: ["registry", "registry_emp", "registry_temp"],
},
{
name: "ProfileFamilyCouple",
repository: this.profileFamilyCoupleRepository,
description: "ข้อมูลคู่สมรส",
system: ["registry", "registry_emp", "registry_temp"],
},
{
name: "ProfileFamilyFather",
repository: this.profileFamilyFatherRepository,
description: "ข้อมูลบิดา",
system: ["registry", "registry_emp", "registry_temp"],
},
{
name: "ProfileFamilyMother",
repository: this.profileFamilyMotherRepository,
description: "ข้อมูลมารดา",
system: ["registry", "registry_emp", "registry_temp"],
},
{
name: "ProfileChildren",
repository: this.profileChildrenRepository,
description: "ข้อมูลบุตร",
system: ["registry", "registry_emp", "registry_temp"],
},
{
name: "ProfileNopaid",
repository: this.profileNopaidRepository,
description: "ข้อมูลการไม่จ่ายเงินเดือน",
system: ["registry", "registry_emp", "registry_temp"],
},
{
name: "ProfileOther",
repository: this.profileOtherRepository,
description: "ข้อมูลอื่นๆ",
system: ["registry", "registry_emp", "registry_temp"],
},
{
name: "OrgRoot",
repository: this.orgRootRepository,
description: "ข้อมูลหน่วยงาน",
system: ["organization"],
},
{
name: "OrgChild1",
repository: this.orgChild1Repository,
description: "ข้อมูลส่วนราชการ ระดับที่ 1",
system: ["organization"],
},
{
name: "OrgChild2",
repository: this.orgChild2Repository,
description: "ข้อมูลส่วนราชการ ระดับที่ 2",
system: ["organization"],
},
{
name: "OrgChild3",
repository: this.orgChild3Repository,
description: "ข้อมูลส่วนราชการ ระดับที่ 3",
system: ["organization"],
},
{
name: "OrgChild4",
repository: this.orgChild4Repository,
description: "ข้อมูลส่วนราชการ ระดับที่ 4",
system: ["organization"],
},
{
name: "PosMaster",
repository: this.posMasterRepository,
description: "ข้อมูลตำแหน่ง",
system: ["organization"],
},
];
const result = entities
.filter((s) => s.system.includes(system))
.map(({ name, repository, description }) => ({
tb: name,
description,
propertys: repository.metadata.columns
.filter(
(column) =>
!column.isPrimary &&
column.propertyName !== "createdUserId" &&
column.propertyName !== "lastUpdateUserId",
)
.map((column) => ({
propertyName: column.propertyName,
type: column.type,
comment: column.comment,
key: `${name}.${column.propertyName}`,
})),
}));
return new HttpSuccess(result);
} catch (error) {
throw new HttpError(
HttpStatusCode.INTERNAL_SERVER_ERROR,
(error instanceof Error ? error.message : String(error)) ||
"เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง",
);
}
}
/**
* list api
* @summary api
*/
@Get("/lists")
async listApi(
@Request() req: RequestWithUser,
@Query("page") page: number = 1,
@Query("pageSize") pageSize: number = 10,
@Query() searchKeyword: string = "",
): Promise<HttpSuccess | HttpError> {
try {
if (!req.user.role.includes("SUPER_ADMIN")) {
throw new HttpError(HttpStatusCode.FORBIDDEN, "คุณไม่มีสิทธิ์ในการเข้าถึงข้อมูลนี้");
}
const offset = (page - 1) * pageSize;
const queryBuilder = AppDataSource.getRepository(ApiName)
.createQueryBuilder("apiName")
.select([
"apiName.id",
"apiName.name",
"apiName.code",
"apiName.pathApi",
"apiName.methodApi",
"apiName.system",
"apiName.isActive",
"apiName.createdAt",
"apiName.lastUpdatedAt",
]);
if (searchKeyword?.trim()) {
queryBuilder.where(
"(apiName.name LIKE :keyword OR apiName.code LIKE :keyword OR apiName.pathApi LIKE :keyword)",
{ keyword: `%${searchKeyword.trim()}%` },
);
}
const [apiNames, total] = await queryBuilder
.skip(offset)
.take(pageSize)
.orderBy("apiName.lastUpdatedAt", "DESC")
.addOrderBy("apiName.createdAt", "ASC")
.getManyAndCount();
return new HttpSuccess({
data: apiNames,
total,
});
} catch (error) {
throw new HttpError(
HttpStatusCode.INTERNAL_SERVER_ERROR,
(error instanceof Error ? error.message : String(error)) ||
"เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง",
);
}
}
/**
* api
* @summary api
*/
@Post("")
async createApi(
@Request() req: RequestWithUser,
@Body() apiData: CreateApi,
): Promise<HttpSuccess | HttpError> {
try {
const queryRunner = AppDataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
if (!req.user.role.includes("SUPER_ADMIN")) {
throw new HttpError(HttpStatusCode.FORBIDDEN, "คุณไม่มีสิทธิ์ในการเข้าถึงข้อมูลนี้");
}
const code = Math.random().toString(36).substring(2, 10).toUpperCase();
const postData = {
name: apiData.name,
code,
pathApi: `/api/v2/org/api-service/${apiData.system}/${code}`,
methodApi: apiData.methodApi || "GET",
system: apiData.system || "registry",
isActive: apiData.isActive || false,
createdUserId: req.user?.sub || undefined,
createdFullName: req.user?.name || "",
};
const apiName = await queryRunner.manager.getRepository(ApiName).save(postData);
if (apiData.apiAttributes?.length) {
let orderingCounter = 0;
const attributesToSave = apiData.apiAttributes.flatMap((attr) =>
attr.propertyKey.map((propertyKey) => ({
apiNameId: apiName.id,
tbName: attr.tbName,
propertyKey,
ordering: orderingCounter++,
createdUserId: req.user?.sub || undefined,
createdFullName: req.user?.name || "",
})),
);
await queryRunner.manager.getRepository(ApiAttribute).save(attributesToSave);
}
await queryRunner.commitTransaction();
return new HttpSuccess(apiName.id);
} catch (transactionError) {
await queryRunner.rollbackTransaction();
throw transactionError;
} finally {
await queryRunner.release();
}
} catch (error) {
throw new HttpError(
HttpStatusCode.INTERNAL_SERVER_ERROR,
(error instanceof Error ? error.message : String(error)) ||
"เกิดข้อผิดพลาด ไม่สามารถบันทึกข้อมูลได้ กรุณาลองใหม่ในภายหลัง",
);
}
}
/**
* api
* @summary api
*/
@Get("/{id}")
async getApiById(
@Request() req: RequestWithUser,
@Path("id") id: string,
): Promise<HttpSuccess | HttpError> {
try {
if (!req.user.role.includes("SUPER_ADMIN")) {
throw new HttpError(HttpStatusCode.FORBIDDEN, "คุณไม่มีสิทธิ์ในการเข้าถึงข้อมูลนี้");
}
const apiName = await AppDataSource.getRepository(ApiName).findOne({
select: {
id: true,
name: true,
code: true,
pathApi: true,
methodApi: true,
system: true,
isActive: true,
apiAttributes: true,
},
where: { id },
relations: ["apiAttributes"],
order: {
apiAttributes: {
ordering: "ASC",
},
},
});
if (!apiName) {
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบ API ที่ต้องการแก้ไข");
}
const items = {
...apiName,
apiAttributes: apiName.apiAttributes.map((attr) => ({
tbName: attr.tbName,
propertyKey: attr.propertyKey,
})),
};
return new HttpSuccess(items);
} catch (error) {
throw new HttpError(
HttpStatusCode.INTERNAL_SERVER_ERROR,
(error instanceof Error ? error.message : String(error)) ||
"เกิดข้อผิดพลาด ไม่สามารถบันทึกข้อมูลได้ กรุณาลองใหม่ในภายหลัง",
);
}
}
/**
* api
* @summary api
*/
@Put("/{id}")
async editApi(
@Request() req: RequestWithUser,
@Path("id") id: string,
@Body() apiData: CreateApi,
): Promise<HttpSuccess | HttpError> {
try {
const queryRunner = AppDataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
if (!req.user.role.includes("SUPER_ADMIN")) {
throw new HttpError(HttpStatusCode.FORBIDDEN, "คุณไม่มีสิทธิ์ในการเข้าถึงข้อมูลนี้");
}
const apiName = await queryRunner.manager.getRepository(ApiName).findOneBy({ id });
if (!apiName) {
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบ API ที่ต้องการแก้ไข");
}
const updateData = {
name: apiData.name,
pathApi: `/api/v2/org/api-service/${apiData.system}/${apiName.code}`,
methodApi: apiData.methodApi || "GET",
system: apiData.system || "registry",
isActive: apiData.isActive || false,
lastUpdateUserId: req.user?.sub || undefined,
lastUpdateFullName: req.user?.name || "",
};
await queryRunner.manager.getRepository(ApiName).update(id, updateData);
await queryRunner.manager.getRepository(ApiAttribute).delete({ apiNameId: id });
if (apiData.apiAttributes?.length) {
let orderingCounter = 0;
const attributesToSave = apiData.apiAttributes.flatMap((attr) =>
attr.propertyKey.map((propertyKey) => ({
apiNameId: apiName.id,
tbName: attr.tbName,
propertyKey,
ordering: orderingCounter++,
lastUpdateUserId: req.user?.sub || undefined,
lastUpdateFullName: req.user?.name || "",
})),
);
await queryRunner.manager.getRepository(ApiAttribute).save(attributesToSave);
}
await queryRunner.commitTransaction();
return new HttpSuccess();
} catch (transactionError) {
await queryRunner.rollbackTransaction();
throw transactionError;
} finally {
await queryRunner.release();
}
} catch (error) {
throw new HttpError(
HttpStatusCode.INTERNAL_SERVER_ERROR,
(error instanceof Error ? error.message : String(error)) ||
"เกิดข้อผิดพลาด ไม่สามารถบันทึกข้อมูลได้ กรุณาลองใหม่ในภายหลัง",
);
}
}
/**
* api
* @summary api
*/
@Delete("/{id}")
async deleteApi(
@Request() req: RequestWithUser,
@Path("id") id: string,
): Promise<HttpSuccess | HttpError> {
try {
const queryRunner = AppDataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
if (!req.user.role.includes("SUPER_ADMIN")) {
throw new HttpError(HttpStatusCode.FORBIDDEN, "คุณไม่มีสิทธิ์ในการเข้าถึงข้อมูลนี้");
}
await queryRunner.manager.getRepository(ApiName).delete({ id });
await queryRunner.manager.getRepository(ApiAttribute).delete({ apiNameId: id });
await queryRunner.commitTransaction();
return new HttpSuccess();
} catch (transactionError) {
await queryRunner.rollbackTransaction();
throw transactionError;
} finally {
await queryRunner.release();
}
} catch (error) {
throw new HttpError(
HttpStatusCode.INTERNAL_SERVER_ERROR,
(error instanceof Error ? error.message : String(error)) ||
"เกิดข้อผิดพลาด ไม่สามารถบันทึกข้อมูลได้ กรุณาลองใหม่ในภายหลัง",
);
}
}
}

View file

@ -0,0 +1,79 @@
import {
Controller,
Post,
Route,
Security,
Tags,
Body,
Path,
Request,
Response,
Get,
Query,
} from "tsoa";
import { AppDataSource } from "../database/data-source";
import HttpSuccess from "../interfaces/http-success";
import HttpStatusCode from "../interfaces/http-status";
import HttpError from "../interfaces/http-error";
import { ApiName } from "../entities/ApiName";
import { Profile } from "../entities/Profile";
@Route("api/v2/org/api-service")
@Tags("ApiKey")
// @Security("bearerAuth")
@Response(
HttpStatusCode.INTERNAL_SERVER_ERROR,
"เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง",
)
export class ApiWebServiceController extends Controller {
private apiNameRepository = AppDataSource.getRepository(ApiName);
/**
* list fields by systems
* @summary fields systems
*/
@Get("/:system/:code")
async listAttribute(
@Path("system") system: "registry" | "registry_emp" | "registry_temp" | "organization",
@Path("code") code: string,
@Query("page") page: number = 1,
@Query("pageSize") pageSize: number = 100,
): Promise<HttpSuccess | HttpError> {
try {
const apiName = await this.apiNameRepository.findOne({
where: { code },
select: ["id", "code", "methodApi", "system", "isActive"],
relations: ["apiAttributes"],
order: {
apiAttributes: {
ordering: "ASC",
},
},
});
if (!apiName || apiName.system != system || !apiName.isActive || apiName.methodApi != "GET") {
throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบ API ที่ระบุ");
}
const offset = (page - 1) * pageSize;
const propertyKey = apiName.apiAttributes.map((attr) => `${attr.tbName}.${attr.propertyKey}`);
const queryBuilder = AppDataSource.getRepository(Profile)
.createQueryBuilder("Profile")
.select(propertyKey);
const [items, total] = await queryBuilder
.skip(offset)
.take(pageSize)
.orderBy("Profile.createdAt", "DESC")
.getManyAndCount();
return new HttpSuccess({ items, total });
} catch (error) {
throw new HttpError(
HttpStatusCode.INTERNAL_SERVER_ERROR,
(error instanceof Error ? error.message : String(error)) ||
"เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง",
);
}
}
}

View file

@ -0,0 +1,39 @@
import { ApiName } from "./ApiName";
import { Entity, Column, ManyToOne, JoinColumn } from "typeorm";
import { EntityBase } from "./base/Base";
@Entity("apiAttribute")
export class ApiAttribute extends EntityBase {
@Column({
nullable: false,
comment: "ชื่อตาราง",
length: 50,
})
tbName: string;
@Column({
nullable: false,
comment: "คีย์ของแอตทริบิวต์",
length: 255,
})
propertyKey: string;
@Column({
nullable: false,
comment: "ลำดับการแสดงผล",
default: 0,
type: "int",
})
ordering: number;
@Column({
nullable: false,
comment: "ไอดีของ API Name",
length: 36, // UUID length
})
apiNameId: string;
@ManyToOne(() => ApiName, (apiName) => apiName.apiAttributes)
@JoinColumn({ name: "apiNameId" })
apiName: ApiName;
}

View file

@ -1,3 +1,4 @@
import { ApiAttribute } from "./ApiAttribute";
import { Entity, Column, ManyToMany, JoinTable, OneToMany } from "typeorm";
import { EntityBase } from "./base/Base";
import { ApiKey } from "./ApiKey";
@ -29,10 +30,61 @@ export class ApiName extends EntityBase {
})
methodApi: string;
@Column({
nullable: false,
comment: "code สำหรับการเรียก API",
length: 8,
})
code: string;
@Column({
nullable: false,
comment: "code ระบบสำหรับการเรียก API",
length: 50,
default: "registry",
})
system: string;
@Column({
nullable: false,
comment: "สถานะการใช้งาน",
type: "boolean",
default: false,
})
isActive: boolean;
@ManyToMany(() => ApiKey, (apiKey) => apiKey.apiNames)
@JoinTable()
apiKeys: ApiKey[];
@OneToMany(() => ApiHistory, (v) => v.apiName)
apiHistorys: ApiHistory[];
@OneToMany(() => ApiAttribute, (v) => v.apiName)
apiAttributes: ApiAttribute[];
}
export class CreateApi {
@Column()
name: string;
@Column()
methodApi: "GET" | "POST" | "PUT";
@Column()
system: string;
@Column()
isActive: boolean;
@Column()
apiAttributes: CreateApiAttribute[];
}
export class CreateApiAttribute {
@Column()
tbName: string;
@Column()
propertyKey: string[];
}