Fix issues and connect everything
This commit is contained in:
parent
4d1da02b5f
commit
500be26fbe
|
|
@ -38,6 +38,7 @@ bower_components
|
||||||
|
|
||||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
build/Release
|
build/Release
|
||||||
|
build
|
||||||
|
|
||||||
# Dependency directories
|
# Dependency directories
|
||||||
node_modules/
|
node_modules/
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
postgresdb:
|
||||||
|
image: postgres
|
||||||
|
restart: unless-stopped
|
||||||
|
env_file: ./.env
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=$POSTGRESDB_USER
|
||||||
|
- POSTGRES_PASSWORD=$POSTGRESDB_ROOT_PASSWORD
|
||||||
|
- POSTGRES_DB=$POSTGRESDB_DATABASE
|
||||||
|
ports:
|
||||||
|
- $POSTGRESDB_LOCAL_PORT:$POSTGRESDB_DOCKER_PORT
|
||||||
|
volumes:
|
||||||
|
- db:/var/lib/postgres
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
db:
|
||||||
File diff suppressed because it is too large
Load Diff
24
package.json
24
package.json
|
|
@ -1,10 +1,34 @@
|
||||||
{
|
{
|
||||||
|
"name": "prueba_intricom",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Rest API using Node.js, TypeScript, Express, Posgresql",
|
||||||
|
"main": "src/server.ts",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"build": "tsc",
|
||||||
|
"dev": "node ./build/server.js",
|
||||||
|
"start": "tsc && npm run dev"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"express",
|
||||||
|
"typescript",
|
||||||
|
"api",
|
||||||
|
"posgresql",
|
||||||
|
"nodejs"
|
||||||
|
],
|
||||||
|
"author": "bezkoder",
|
||||||
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/cors": "^2.8.17",
|
||||||
|
"@types/express": "^5.0.0",
|
||||||
"@types/node": "^22.10.1",
|
"@types/node": "^22.10.1",
|
||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
"typescript": "^5.7.2"
|
"typescript": "^5.7.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"cors": "^2.8.5",
|
||||||
|
"dotenv": "^16.4.5",
|
||||||
|
"express": "^4.21.1",
|
||||||
"pg": "^8.13.1",
|
"pg": "^8.13.1",
|
||||||
"sequelize": "^6.37.5",
|
"sequelize": "^6.37.5",
|
||||||
"sequelize-typescript": "^2.1.6"
|
"sequelize-typescript": "^2.1.6"
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,7 @@
|
||||||
export const config = {
|
export const config = {
|
||||||
HOST: "localhost",
|
HOST: process.env.POSTGRESDB_HOST,
|
||||||
USER: "postgres",
|
USER: process.env.POSTGRESDB_USER,
|
||||||
PASSWORD: "123",
|
PASSWORD: process.env.POSTGRESDB_ROOT_PASSWORD,
|
||||||
DB: "testdb",
|
DB: process.env.POSTGRESDB_DATABASE,
|
||||||
pool: {
|
PORT: process.env.POSTGRESDB_LOCAL_PORT || 5432,
|
||||||
max: 5,
|
|
||||||
min: 0,
|
|
||||||
acquire: 30000,
|
|
||||||
idle: 10000
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const dialect = "postgres";
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,20 +4,20 @@ import Booking from "../models/booking.model";
|
||||||
import BookingRepository from "../repositories/booking.repository";
|
import BookingRepository from "../repositories/booking.repository";
|
||||||
|
|
||||||
export default class BookingController {
|
export default class BookingController {
|
||||||
async create(req: Request, res Response) {
|
async create(req: Request, res: Response) {
|
||||||
if (!req.body.hotelId || !req.body.clientId) {
|
if (!req.body.hotelId || !req.body.clientId) {
|
||||||
res.status(400).json({
|
res.status(400).json({
|
||||||
message: "Content cannot be empty"
|
message: "Content cannot be empty"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const booking = {
|
const bookingParams = {
|
||||||
hotelId: req.body.hotelId,
|
hotelId: req.body.hotelId,
|
||||||
clientId: req.body.clientId,
|
clientId: req.body.clientId,
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const booking = await BookingRepository.create(booking);
|
const booking = await BookingRepository.create(bookingParams);
|
||||||
res.status(201).json(booking);
|
res.status(201).json(booking);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
res.status(500).json({
|
res.status(500).json({
|
||||||
|
|
@ -26,7 +26,7 @@ export default class BookingController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async findAll(req: Request, res Response) {
|
async findAll(req: Request, res: Response) {
|
||||||
try {
|
try {
|
||||||
const bookings = await BookingRepository.retrieveAll();
|
const bookings = await BookingRepository.retrieveAll();
|
||||||
res.status(200).json(bookings);
|
res.status(200).json(bookings);
|
||||||
|
|
@ -37,7 +37,7 @@ export default class BookingController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async findOne(req: Request, res Response) {
|
async findOne(req: Request, res: Response) {
|
||||||
if (!req.body.id) {
|
if (!req.body.id) {
|
||||||
res.status(400).json({
|
res.status(400).json({
|
||||||
message: "id cannot be empty"
|
message: "id cannot be empty"
|
||||||
|
|
@ -54,13 +54,13 @@ export default class BookingController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(req: Request, res Response) {
|
async update(req: Request, res: Response) {
|
||||||
res.status(405).json({
|
res.status(405).json({
|
||||||
message: "Cannot update booking"
|
message: "Cannot update booking"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(req: Request, res Response) {
|
async delete(req: Request, res: Response) {
|
||||||
if (!req.body.id) {
|
if (!req.body.id) {
|
||||||
res.status(400).json({
|
res.status(400).json({
|
||||||
message: "id cannot be empty"
|
message: "id cannot be empty"
|
||||||
|
|
@ -77,7 +77,7 @@ export default class BookingController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteAll(req: Request, res Response) {
|
async deleteAll(req: Request, res: Response) {
|
||||||
try {
|
try {
|
||||||
await BookingRepository.deleteAll();
|
await BookingRepository.deleteAll();
|
||||||
res.status(204);
|
res.status(204);
|
||||||
|
|
|
||||||
|
|
@ -4,21 +4,21 @@ import Client from "../models/client.model";
|
||||||
import ClientRepository from "../repositories/client.repository";
|
import ClientRepository from "../repositories/client.repository";
|
||||||
|
|
||||||
export default class ClientController {
|
export default class ClientController {
|
||||||
async create(req: Request, res Response) {
|
async create(req: Request, res: Response) {
|
||||||
if (!req.body.name || !req.body.address || !req.body.phone) {
|
if (!req.body.name || !req.body.address || !req.body.phone) {
|
||||||
res.status(400).json({
|
res.status(400).json({
|
||||||
message: "Content cannot be empty"
|
message: "Content cannot be empty"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const client = {
|
const clientParams = {
|
||||||
name: req.body.name,
|
name: req.body.name,
|
||||||
address: req.body.address,
|
address: req.body.address,
|
||||||
phone: req.body.phone,
|
phone: req.body.phone,
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const client = await ClientRepository.create(client);
|
const client = await ClientRepository.create(clientParams);
|
||||||
res.status(201).json(client);
|
res.status(201).json(client);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
res.status(500).json({
|
res.status(500).json({
|
||||||
|
|
@ -27,10 +27,10 @@ export default class ClientController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async findAll(req: Request, res Response) {
|
async findAll(req: Request, res: Response) {
|
||||||
const name = req.query.name;
|
const name = req.query.name as string;
|
||||||
const address = req.query.address;
|
const address = req.query.address as string;
|
||||||
const phone = req.query.phone;
|
const phone = req.query.phone as string;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const clients = await ClientRepository.retrieveAll({name, address, phone});
|
const clients = await ClientRepository.retrieveAll({name, address, phone});
|
||||||
|
|
@ -42,7 +42,7 @@ export default class ClientController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async findOne(req: Request, res Response) {
|
async findOne(req: Request, res: Response) {
|
||||||
if (!req.body.id) {
|
if (!req.body.id) {
|
||||||
res.status(400).json({
|
res.status(400).json({
|
||||||
message: "id cannot be empty"
|
message: "id cannot be empty"
|
||||||
|
|
@ -59,7 +59,7 @@ export default class ClientController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(req: Request, res Response) {
|
async update(req: Request, res: Response) {
|
||||||
if (!req.body.id) {
|
if (!req.body.id) {
|
||||||
res.status(400).json({
|
res.status(400).json({
|
||||||
message: "id cannot be empty"
|
message: "id cannot be empty"
|
||||||
|
|
@ -73,7 +73,14 @@ export default class ClientController {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const client = await clientRepository.retrieveById(id);
|
const client = await ClientRepository.retrieveById(req.body.id);
|
||||||
|
|
||||||
|
if (client === null) {
|
||||||
|
res.status(404).json({
|
||||||
|
message: "Not found"
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (req.body.name) {
|
if (req.body.name) {
|
||||||
client.name = req.body.name;
|
client.name = req.body.name;
|
||||||
|
|
@ -87,7 +94,7 @@ export default class ClientController {
|
||||||
client.phone = req.body.phone;
|
client.phone = req.body.phone;
|
||||||
}
|
}
|
||||||
|
|
||||||
await clientRepository.update(client);
|
await ClientRepository.update(client);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
res.status(404).json({
|
res.status(404).json({
|
||||||
message: err || "Not found"
|
message: err || "Not found"
|
||||||
|
|
@ -95,7 +102,7 @@ export default class ClientController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(req: Request, res Response) {
|
async delete(req: Request, res: Response) {
|
||||||
if (!req.body.id) {
|
if (!req.body.id) {
|
||||||
res.status(400).json({
|
res.status(400).json({
|
||||||
message: "id cannot be empty"
|
message: "id cannot be empty"
|
||||||
|
|
@ -112,7 +119,7 @@ export default class ClientController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteAll(req: Request, res Response) {
|
async deleteAll(req: Request, res: Response) {
|
||||||
try {
|
try {
|
||||||
await ClientRepository.deleteAll();
|
await ClientRepository.deleteAll();
|
||||||
res.status(204);
|
res.status(204);
|
||||||
|
|
|
||||||
|
|
@ -4,20 +4,20 @@ import Hotel from "../models/hotel.model";
|
||||||
import HotelRepository from "../repositories/hotel.repository";
|
import HotelRepository from "../repositories/hotel.repository";
|
||||||
|
|
||||||
export default class HotelController {
|
export default class HotelController {
|
||||||
async create(req: Request, res Response) {
|
async create(req: Request, res: Response) {
|
||||||
if (!req.body.name || !req.body.address) {
|
if (!req.body.name || !req.body.address) {
|
||||||
res.status(400).json({
|
res.status(400).json({
|
||||||
message: "Content cannot be empty"
|
message: "Content cannot be empty"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const hotel = {
|
const hotelParams = {
|
||||||
name: req.body.name,
|
name: req.body.name,
|
||||||
address: req.body.address,
|
address: req.body.address,
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const hotel = await HotelRepository.create(hotel);
|
const hotel = await HotelRepository.create(hotelParams);
|
||||||
res.status(201).json(hotel);
|
res.status(201).json(hotel);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
res.status(500).json({
|
res.status(500).json({
|
||||||
|
|
@ -26,9 +26,9 @@ export default class HotelController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async findAll(req: Request, res Response) {
|
async findAll(req: Request, res: Response) {
|
||||||
const name = req.query.name;
|
const name = req.query.name as string;
|
||||||
const address = req.query.address;
|
const address = req.query.address as string;;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const hotels = await HotelRepository.retrieveAll({name, address});
|
const hotels = await HotelRepository.retrieveAll({name, address});
|
||||||
|
|
@ -40,7 +40,7 @@ export default class HotelController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async findOne(req: Request, res Response) {
|
async findOne(req: Request, res: Response) {
|
||||||
if (!req.body.id) {
|
if (!req.body.id) {
|
||||||
res.status(400).json({
|
res.status(400).json({
|
||||||
message: "id cannot be empty"
|
message: "id cannot be empty"
|
||||||
|
|
@ -57,7 +57,7 @@ export default class HotelController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(req: Request, res Response) {
|
async update(req: Request, res: Response) {
|
||||||
if (!req.body.id) {
|
if (!req.body.id) {
|
||||||
res.status(400).json({
|
res.status(400).json({
|
||||||
message: "id cannot be empty"
|
message: "id cannot be empty"
|
||||||
|
|
@ -71,7 +71,14 @@ export default class HotelController {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const hotel = await hotelRepository.retrieveById(id);
|
const hotel = await HotelRepository.retrieveById(req.body.id);
|
||||||
|
|
||||||
|
if (hotel === null) {
|
||||||
|
res.status(404).json({
|
||||||
|
message: "Not found"
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (req.body.name) {
|
if (req.body.name) {
|
||||||
hotel.name = req.body.name;
|
hotel.name = req.body.name;
|
||||||
|
|
@ -81,15 +88,15 @@ export default class HotelController {
|
||||||
hotel.name = req.body.address;
|
hotel.name = req.body.address;
|
||||||
}
|
}
|
||||||
|
|
||||||
await hotelRepository.update(hotel);
|
await HotelRepository.update(hotel);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
res.status(404).json({
|
res.status(500).json({
|
||||||
message: err || "Not found"
|
message: err || "Internal Server Error!"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(req: Request, res Response) {
|
async delete(req: Request, res: Response) {
|
||||||
if (!req.body.id) {
|
if (!req.body.id) {
|
||||||
res.status(400).json({
|
res.status(400).json({
|
||||||
message: "id cannot be empty"
|
message: "id cannot be empty"
|
||||||
|
|
@ -106,7 +113,7 @@ export default class HotelController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteAll(req: Request, res Response) {
|
async deleteAll(req: Request, res: Response) {
|
||||||
try {
|
try {
|
||||||
await HotelRepository.deleteAll();
|
await HotelRepository.deleteAll();
|
||||||
res.status(204);
|
res.status(204);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { Model, Table, Column, DataType } from "sequelize-typescript";
|
import { Model, Table, Column, DataType, BelongsTo, ForeignKey, CreatedAt, Unique } from "sequelize-typescript";
|
||||||
|
|
||||||
import Hotel from "./hotel.model.ts";
|
import Hotel from "./hotel.model";
|
||||||
import Client from "./client.model.ts";
|
import Client from "./client.model";
|
||||||
|
|
||||||
@Table({
|
@Table({
|
||||||
tableName: "HotelBooking",
|
tableName: "HotelBooking",
|
||||||
|
|
@ -13,27 +13,27 @@ export default class Booking extends Model {
|
||||||
autoIncrement: true,
|
autoIncrement: true,
|
||||||
field: "id"
|
field: "id"
|
||||||
})
|
})
|
||||||
id: number;
|
id?: number;
|
||||||
|
|
||||||
@ForeignKey(() => Hotel)
|
@ForeignKey(() => Hotel)
|
||||||
@Column({
|
@Column({
|
||||||
field: "HotelId"
|
field: "HotelId"
|
||||||
})
|
})
|
||||||
hotelId: number;
|
hotelId?: number;
|
||||||
|
|
||||||
@BelongsTo(() => Hotel)
|
@BelongsTo(() => Hotel)
|
||||||
hotel: Hotel;
|
hotel?: Hotel;
|
||||||
|
|
||||||
@CreatedAt
|
@CreatedAt
|
||||||
createdDate: Date;
|
createdDate?: Date;
|
||||||
|
|
||||||
@ForeignKey(() => Client)
|
@ForeignKey(() => Client)
|
||||||
@Column({
|
@Column({
|
||||||
field: "clientId"
|
field: "clientId"
|
||||||
})
|
})
|
||||||
clientId: number;
|
clientId?: number;
|
||||||
|
|
||||||
@BelongsTo(() => Client)
|
@BelongsTo(() => Client)
|
||||||
client: Client;
|
client?: Client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { Model, Table, Column, DataType } from "sequelize-typescript";
|
import { Model, Table, Column, DataType, HasMany, CreatedAt, Unique } from "sequelize-typescript";
|
||||||
|
|
||||||
import Hotel from "./hotel.model.ts";
|
import Hotel from "./hotel.model";
|
||||||
import Booking from "./booking.model.ts";
|
import Booking from "./booking.model";
|
||||||
|
|
||||||
@Table({
|
@Table({
|
||||||
tableName: "Client",
|
tableName: "Client",
|
||||||
|
|
@ -13,27 +13,27 @@ export default class Client extends Model {
|
||||||
autoIncrement: true,
|
autoIncrement: true,
|
||||||
field: "id"
|
field: "id"
|
||||||
})
|
})
|
||||||
id: number;
|
id?: number;
|
||||||
|
|
||||||
@Column({
|
@Column({
|
||||||
field: "Name"
|
field: "Name"
|
||||||
})
|
})
|
||||||
name: string;
|
name?: string;
|
||||||
|
|
||||||
@Column({
|
@Column({
|
||||||
field: "Address"
|
field: "Address"
|
||||||
})
|
})
|
||||||
address: string;
|
address?: string;
|
||||||
|
|
||||||
@Column({
|
@Column({
|
||||||
field: "Phone"
|
field: "Phone"
|
||||||
})
|
})
|
||||||
phone: string;
|
phone?: string;
|
||||||
|
|
||||||
@CreatedAt
|
@CreatedAt
|
||||||
createdDate: Date;
|
createdDate?: Date;
|
||||||
|
|
||||||
@HasMany(() => Booking)
|
@HasMany(() => Booking)
|
||||||
bookings: Booking[];
|
bookings?: Booking[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { Model, Table, Column, DataType } from "sequelize-typescript";
|
import { Model, Table, Column, DataType, HasMany, CreatedAt, Unique } from "sequelize-typescript";
|
||||||
|
|
||||||
import Client from "./client.model.ts";
|
import Client from "./client.model";
|
||||||
import Booking from "./booking.model.ts";
|
import Booking from "./booking.model";
|
||||||
|
|
||||||
@Table({
|
@Table({
|
||||||
tableName: "Hotel",
|
tableName: "Hotel",
|
||||||
|
|
@ -14,22 +14,22 @@ export default class Hotel extends Model {
|
||||||
autoIncrement: true,
|
autoIncrement: true,
|
||||||
field: "id"
|
field: "id"
|
||||||
})
|
})
|
||||||
id: number;
|
id?: number;
|
||||||
|
|
||||||
@Column({
|
@Column({
|
||||||
field: "Name"
|
field: "Name"
|
||||||
})
|
})
|
||||||
name: string;
|
name?: string;
|
||||||
|
|
||||||
@Column({
|
@Column({
|
||||||
field: "Address"
|
field: "Address"
|
||||||
})
|
})
|
||||||
address: string;
|
address?: string;
|
||||||
|
|
||||||
@CreatedAt
|
@CreatedAt
|
||||||
createdDate: Date;
|
createdDate?: Date;
|
||||||
|
|
||||||
@HasMany(() => Booking)
|
@HasMany(() => Booking)
|
||||||
bookings: Booking[];
|
bookings?: Booking[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { Sequelize } from "sequelize-typescript";
|
import { Sequelize } from "sequelize-typescript";
|
||||||
import { config, dialect } from "../config/db.config";
|
import { config } from "../config/db.config";
|
||||||
|
|
||||||
import Hotel from "./hotel.model";
|
import Hotel from "./hotel.model";
|
||||||
import Client from "./client.model";
|
import Client from "./client.model";
|
||||||
import Booking from "./hotel.model";
|
import Booking from "./booking.model";
|
||||||
|
|
||||||
class Database {
|
class Database {
|
||||||
public sequelize: Sequelize | undefined;
|
public sequelize: Sequelize | undefined;
|
||||||
|
|
@ -18,12 +18,13 @@ class Database {
|
||||||
username: config.USER,
|
username: config.USER,
|
||||||
password: config.PASSWORD,
|
password: config.PASSWORD,
|
||||||
host: config.HOST,
|
host: config.HOST,
|
||||||
dialect: dialect,
|
port: +config.PORT,
|
||||||
|
dialect: 'postgres',
|
||||||
pool: {
|
pool: {
|
||||||
max: config.pool.max,
|
max: 5,
|
||||||
min: config.pool.min,
|
min: 0,
|
||||||
acquire: config.pool.acquire,
|
acquire: 30000,
|
||||||
idle: config.pool.idle
|
idle: 10000
|
||||||
},
|
},
|
||||||
models: [Hotel, Client, Booking]
|
models: [Hotel, Client, Booking]
|
||||||
});
|
});
|
||||||
|
|
@ -36,6 +37,7 @@ class Database {
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error("Unable to connect to the Database:", err);
|
console.error("Unable to connect to the Database:", err);
|
||||||
});
|
});
|
||||||
|
await this.sequelize.sync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ interface IBookingRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
class BookingRepository implements IBookingRepository {
|
class BookingRepository implements IBookingRepository {
|
||||||
async save(booking: {clientId: number, hotelId: number}): Promise<Booking> {
|
async create(booking: {clientId: number, hotelId: number}): Promise<Booking> {
|
||||||
try {
|
try {
|
||||||
return await Booking.create(booking);
|
return await Booking.create(booking);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,12 @@ interface IClientRepository {
|
||||||
deleteAll(): Promise<number>;
|
deleteAll(): Promise<number>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SearchCondition = {
|
||||||
|
name?: { [Op.like]: string};
|
||||||
|
address?: { [Op.like]: string};
|
||||||
|
phone?: { [Op.like]: string};
|
||||||
|
};
|
||||||
|
|
||||||
class ClientRepository implements IClientRepository {
|
class ClientRepository implements IClientRepository {
|
||||||
async create(client: {name: string, address: string, phone: string}): Promise<Client> {
|
async create(client: {name: string, address: string, phone: string}): Promise<Client> {
|
||||||
try {
|
try {
|
||||||
|
|
@ -23,7 +29,7 @@ class ClientRepository implements IClientRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async retrieveAll(searchParams: {name?: string, address?: string, phone?: string): Promise<Client[]> {
|
async retrieveAll(searchParams: {name?: string, address?: string, phone?: string}): Promise<Client[]> {
|
||||||
try {
|
try {
|
||||||
let condition: SearchCondition = {};
|
let condition: SearchCondition = {};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,11 @@ interface IHotelRepository {
|
||||||
deleteAll(): Promise<number>;
|
deleteAll(): Promise<number>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SearchCondition = {
|
||||||
|
name?: { [Op.like]: string};
|
||||||
|
address?: { [Op.like]: string};
|
||||||
|
};
|
||||||
|
|
||||||
class HotelRepository implements IHotelRepository {
|
class HotelRepository implements IHotelRepository {
|
||||||
async create(hotel: {name: string, address: string}): Promise<Hotel> {
|
async create(hotel: {name: string, address: string}): Promise<Hotel> {
|
||||||
try {
|
try {
|
||||||
|
|
@ -22,7 +27,7 @@ class HotelRepository implements IHotelRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async retrieveAll(searchParams: {name?: string, address?: string): Promise<Hotel[]> {
|
async retrieveAll(searchParams: {name?: string, address?: string}): Promise<Hotel[]> {
|
||||||
try {
|
try {
|
||||||
let condition: SearchCondition = {};
|
let condition: SearchCondition = {};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,8 @@ import hotelRoutes from "./hotel.routes";
|
||||||
import clientRoutes from "./client.routes";
|
import clientRoutes from "./client.routes";
|
||||||
import bookingRoutes from "./booking.routes";
|
import bookingRoutes from "./booking.routes";
|
||||||
|
|
||||||
export default class Routes {
|
export default function createRoutes(app: Application) {
|
||||||
constructor(app: Application) {
|
|
||||||
app.use("/api/hotels", hotelRoutes);
|
app.use("/api/hotels", hotelRoutes);
|
||||||
app.use("/api/client", clientRoutes);
|
app.use("/api/clients", clientRoutes);
|
||||||
app.use("/api/booking", bookingRoutes);
|
app.use("/api/bookings", bookingRoutes);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
import express, { Application } from "express";
|
||||||
|
import cors, { CorsOptions } from "cors";
|
||||||
|
import dotenv from "dotenv";
|
||||||
|
dotenv.config();
|
||||||
|
|
||||||
|
import createRoutes from "./routes";
|
||||||
|
import Database from "./models";
|
||||||
|
|
||||||
|
|
||||||
|
const db = new Database();
|
||||||
|
const app: Application = express();
|
||||||
|
const port: number = process.env.PORT ? parseInt(process.env.PORT, 10) : 8080;
|
||||||
|
|
||||||
|
const corsOptions: CorsOptions = {
|
||||||
|
origin: `http://localhost:${port}`
|
||||||
|
};
|
||||||
|
|
||||||
|
app.use(cors(corsOptions));
|
||||||
|
app.use(express.json());
|
||||||
|
app.use(express.urlencoded({ extended: true }));
|
||||||
|
|
||||||
|
createRoutes(app);
|
||||||
|
|
||||||
|
app.listen(port, "localhost", function () {
|
||||||
|
console.log(`Server is running on port ${port}.`);
|
||||||
|
})
|
||||||
|
.on("error", (err: any) => {
|
||||||
|
if (err.code === "EADDRINUSE") {
|
||||||
|
console.log("Error: address already in use");
|
||||||
|
} else {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
114
tsconfig.json
114
tsconfig.json
|
|
@ -1,9 +1,111 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
...
|
/* Visit https://aka.ms/tsconfig to read more about this file */
|
||||||
"target": "es6", // or a more recent ecmascript version
|
|
||||||
"experimentalDecorators": true,
|
|
||||||
"emitDecoratorMetadata": true,
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Projects */
|
||||||
|
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
|
||||||
|
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||||
|
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
|
||||||
|
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
|
||||||
|
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||||
|
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||||
|
|
||||||
|
/* Language and Environment */
|
||||||
|
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||||
|
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||||
|
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||||
|
"experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
|
||||||
|
"emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||||
|
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
|
||||||
|
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||||
|
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
|
||||||
|
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
|
||||||
|
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||||
|
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||||
|
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
||||||
|
|
||||||
|
/* Modules */
|
||||||
|
"module": "commonjs", /* Specify what module code is generated. */
|
||||||
|
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||||
|
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||||
|
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||||
|
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||||
|
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||||
|
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
|
||||||
|
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
||||||
|
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||||
|
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
|
||||||
|
// "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
|
||||||
|
// "rewriteRelativeImportExtensions": true, /* Rewrite '.ts', '.tsx', '.mts', and '.cts' file extensions in relative import paths to their JavaScript equivalent in output files. */
|
||||||
|
// "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
|
||||||
|
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
|
||||||
|
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
|
||||||
|
// "noUncheckedSideEffectImports": true, /* Check side effect imports. */
|
||||||
|
"resolveJsonModule": true, /* Enable importing .json files. */
|
||||||
|
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
|
||||||
|
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
|
||||||
|
|
||||||
|
/* JavaScript Support */
|
||||||
|
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
|
||||||
|
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
||||||
|
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
||||||
|
|
||||||
|
/* Emit */
|
||||||
|
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
||||||
|
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
||||||
|
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||||
|
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
||||||
|
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
||||||
|
// "noEmit": true, /* Disable emitting files from a compilation. */
|
||||||
|
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
||||||
|
"outDir": "./build", /* Specify an output folder for all emitted files. */
|
||||||
|
// "removeComments": true, /* Disable emitting comments. */
|
||||||
|
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
||||||
|
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|
||||||
|
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
|
||||||
|
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||||
|
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
|
||||||
|
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
|
||||||
|
// "newLine": "crlf", /* Set the newline character for emitting files. */
|
||||||
|
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
|
||||||
|
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
|
||||||
|
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
|
||||||
|
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
|
||||||
|
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
|
||||||
|
|
||||||
|
/* Interop Constraints */
|
||||||
|
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||||
|
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
|
||||||
|
// "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
|
||||||
|
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
||||||
|
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
|
||||||
|
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||||
|
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
|
||||||
|
|
||||||
|
/* Type Checking */
|
||||||
|
"strict": true, /* Enable all strict type-checking options. */
|
||||||
|
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
||||||
|
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
||||||
|
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||||
|
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
|
||||||
|
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
||||||
|
// "strictBuiltinIteratorReturn": true, /* Built-in iterators are instantiated with a 'TReturn' type of 'undefined' instead of 'any'. */
|
||||||
|
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
|
||||||
|
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
|
||||||
|
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
||||||
|
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
|
||||||
|
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
|
||||||
|
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||||
|
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
||||||
|
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||||
|
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
|
||||||
|
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
||||||
|
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
|
||||||
|
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||||
|
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||||
|
|
||||||
|
/* Completeness */
|
||||||
|
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||||
|
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue