Fix issues and connect everything

This commit is contained in:
Alex Piqueras 2024-12-02 13:11:27 +01:00
parent 4d1da02b5f
commit 500be26fbe
21 changed files with 1239 additions and 95 deletions

1
.gitignore vendored
View File

@ -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/

18
docker-compose.yml Normal file
View File

@ -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:

947
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -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"

View File

@ -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";

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;
} }

View File

@ -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[];
} }

View File

@ -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[];
} }

View File

@ -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();
} }
} }

View File

@ -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) {

View File

@ -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 = {};

View File

@ -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 = {};

View File

@ -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);
}
} }

35
src/server.ts Normal file
View File

@ -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);
}
});

View File

@ -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. */
}
}