File size: 3,687 Bytes
d76f93d 2200342 d76f93d 2200342 d76f93d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
import {
Controller,
Get,
Route,
Tags,
Post,
Body,
Path,
Delete,
Patch,
Response,
Produces,
} from "tsoa";
import { Visitor, CreateVisitorRequest, VisitorWithBooks } from "../models/Visitor";
import { readMyData, writeMyData } from "../utils/fileStorage";
import { wrapResponse, ApiResponse } from "../utils/responseWrapper";
import { ValidationError, NotFoundError } from "../utils/apiErrors";
import { v4 as uuidv4 } from "uuid";
import { VisitorValidator } from "../validators/visitorValidator";
import { visitorLinkManager } from "../models/Visitor";
@Route("visitors")
@Tags("Visitors")
export class VisitorController extends Controller {
private readonly file = "visitors.sea";
@Get("/")
public async getVisitors(): Promise<ApiResponse<VisitorWithBooks[]>> {
const visitors = await readMyData<Visitor>(this.file);
const enriched = await Promise.all(
visitors.map((v) => visitorLinkManager.enrichWithBooks(v))
);
return wrapResponse(enriched);
}
@Get("/{id}")
public async getVisitor(@Path() id: string): Promise<ApiResponse<VisitorWithBooks>> {
const visitors = await readMyData<Visitor>(this.file);
const visitor = visitors.find((v) => v.id === id);
if (!visitor) {
throw new NotFoundError(`Visitor with id ${id} not found`);
}
const enriched = await visitorLinkManager.enrichWithBooks(visitor);
return wrapResponse(enriched);
}
@Post("/")
public async addVisitor(
@Body() body: CreateVisitorRequest
): Promise<ApiResponse<Visitor>> {
VisitorValidator.validate(body);
const visitors = await readMyData<Visitor>(this.file);
const newVisitor: Visitor = {
id: uuidv4(),
name: body.name.trim(),
surname: body.surname.trim(),
registrationDate: body.registrationDate,
currentBooks: [],
history: [],
};
visitors.push(newVisitor);
await writeMyData(this.file, visitors);
return wrapResponse(newVisitor);
}
@Patch("/{id}")
public async updateVisitor(
@Path() id: string,
@Body() body: Partial<CreateVisitorRequest>
): Promise<ApiResponse<VisitorWithBooks>> {
VisitorValidator.validateForUpdate(body);
const visitors = await readMyData<Visitor>(this.file);
const index = visitors.findIndex((v) => v.id === id);
if (index === -1) {
throw new NotFoundError(`Visitor with id ${id} not found`);
}
visitors[index] = { ...visitors[index], ...body };
await writeMyData(this.file, visitors);
const enriched = await visitorLinkManager.enrichWithBooks(visitors[index]);
return wrapResponse(enriched);
}
@Delete("/{id}")
public async deleteVisitor(@Path() id: string): Promise<ApiResponse<void>> {
const visitors = await readMyData<Visitor>(this.file);
const index = visitors.findIndex((v) => v.id === id);
if (index === -1) {
throw new NotFoundError(`Visitor with id ${id} not found`);
}
if (
visitors[index].currentBooks &&
visitors[index].currentBooks.length > 0
) {
throw new ValidationError(
"Cannot delete visitor with unreturned books"
);
}
visitors.splice(index, 1);
await writeMyData(this.file, visitors);
return wrapResponse();
}
@Get("/{id}/download")
@Produces("application/json")
@Response(200, "File download")
public async downloadVisitor(@Path() id: string): Promise<string> {
const visitor = await this.getVisitor(id);
return JSON.stringify(visitor.data, null, 2);
}
} |