summaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
Diffstat (limited to 'backend')
-rw-r--r--backend/package-lock.json169
-rw-r--r--backend/package.json13
-rw-r--r--backend/src/db.ts (renamed from backend/src/db.js)31
-rw-r--r--backend/src/routes/api.js12
-rw-r--r--backend/src/routes/api.ts10
-rw-r--r--backend/src/routes/events.ts (renamed from backend/src/routes/events.js)62
-rw-r--r--backend/src/routes/users.ts (renamed from backend/src/routes/users.js)42
-rw-r--r--backend/src/server.js40
-rw-r--r--backend/src/server.ts37
-rw-r--r--backend/src/types.ts24
-rw-r--r--backend/tsconfig.json46
11 files changed, 367 insertions, 119 deletions
diff --git a/backend/package-lock.json b/backend/package-lock.json
index 47e566a..e2ddc64 100644
--- a/backend/package-lock.json
+++ b/backend/package-lock.json
@@ -14,6 +14,154 @@
"express": "^4.21.2",
"helmet": "^8.1.0",
"morgan": "^1.10.1"
+ },
+ "devDependencies": {
+ "@types/better-sqlite3": "^7.6.13",
+ "@types/cookie-parser": "^1.4.10",
+ "@types/cors": "^2.8.19",
+ "@types/express": "^5.0.6",
+ "@types/morgan": "^1.9.10",
+ "@types/node": "^25.0.9",
+ "typescript": "^5.9.3"
+ }
+ },
+ "node_modules/@types/better-sqlite3": {
+ "version": "7.6.13",
+ "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.13.tgz",
+ "integrity": "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/body-parser": {
+ "version": "1.19.6",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
+ "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/connect": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/connect": {
+ "version": "3.4.38",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
+ "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/cookie-parser": {
+ "version": "1.4.10",
+ "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.10.tgz",
+ "integrity": "sha512-B4xqkqfZ8Wek+rCOeRxsjMS9OgvzebEzzLYw7NHYuvzb7IdxOkI0ZHGgeEBX4PUM7QGVvNSK60T3OvWj3YfBRg==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/express": "*"
+ }
+ },
+ "node_modules/@types/cors": {
+ "version": "2.8.19",
+ "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz",
+ "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/express": {
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.6.tgz",
+ "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "^5.0.0",
+ "@types/serve-static": "^2"
+ }
+ },
+ "node_modules/@types/express-serve-static-core": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz",
+ "integrity": "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/@types/http-errors": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
+ "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/morgan": {
+ "version": "1.9.10",
+ "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.10.tgz",
+ "integrity": "sha512-sS4A1zheMvsADRVfT0lYbJ4S9lmsey8Zo2F7cnbYjWHP67Q0AwMYuuzLlkIM2N8gAbb9cubhIVFwcIN2XyYCkA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "25.0.9",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.9.tgz",
+ "integrity": "sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~7.16.0"
+ }
+ },
+ "node_modules/@types/qs": {
+ "version": "6.14.0",
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz",
+ "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/range-parser": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
+ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/send": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz",
+ "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/serve-static": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-2.2.0.tgz",
+ "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/http-errors": "*",
+ "@types/node": "*"
}
},
"node_modules/accepts": {
@@ -1324,6 +1472,27 @@
"node": ">= 0.6"
}
},
+ "node_modules/typescript": {
+ "version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "7.16.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
+ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
diff --git a/backend/package.json b/backend/package.json
index b6c45cd..77bb09b 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -4,8 +4,8 @@
"private": true,
"type": "module",
"scripts": {
- "start": "NODE_ENV=production node src/server.js",
- "dev": "node --watch src/server.js"
+ "start": "NODE_ENV=production node dist/server.js",
+ "dev": "node --watch dist/server.js"
},
"dependencies": {
"better-sqlite3": "^11.10.0",
@@ -14,5 +14,14 @@
"express": "^4.21.2",
"helmet": "^8.1.0",
"morgan": "^1.10.1"
+ },
+ "devDependencies": {
+ "@types/better-sqlite3": "^7.6.13",
+ "@types/cookie-parser": "^1.4.10",
+ "@types/cors": "^2.8.19",
+ "@types/express": "^5.0.6",
+ "@types/morgan": "^1.9.10",
+ "@types/node": "^25.0.9",
+ "typescript": "^5.9.3"
}
}
diff --git a/backend/src/db.js b/backend/src/db.ts
index f20cac1..2b124f1 100644
--- a/backend/src/db.js
+++ b/backend/src/db.ts
@@ -1,16 +1,15 @@
-import Database from 'better-sqlite3';
-import EVENTS from './data/events.json' with {type: 'json'};
-import USERS from './data/users.json' with {type: 'json'};
-import RSVPS from './data/rsvps.json' with {type: 'json'};
+import DatabaseConstructor, { type Database } from "better-sqlite3";
+import EVENTS from "./data/events.json" with { type: "json" };
+import USERS from "./data/users.json" with { type: "json" };
+import RSVPS from "./data/rsvps.json" with { type: "json" };
-
-const db = new Database('src/sqlite.db', { verbose: console.log });
+const db: Database = new DatabaseConstructor("src/sqlite.db", {
+ verbose: console.log,
+});
console.log(`Initializing database: ${db.name} `);
-
-db.pragma('foreign_keys = ON');
-
+db.pragma("foreign_keys = ON");
db.exec(`
CREATE TABLE IF NOT EXISTS users (
@@ -32,24 +31,22 @@ db.exec(`
CREATE INDEX IF NOT EXISTS eventhosts ON events(host_id);
`);
-
const upsertUser = db.prepare(`
INSERT INTO users VALUES (@id, @username, @name, @email)
ON CONFLICT(id) DO NOTHING
- `)
+ `);
USERS.map((user) => upsertUser.run(user));
const upsertEvent = db.prepare(`
INSERT INTO events VALUES (@id, @title, @description, @image_url, @date, @host_id)
ON CONFLICT(id) DO NOTHING
- `)
+ `);
EVENTS.map((event) => {
- upsertEvent.run(event);
+ upsertEvent.run(event);
});
-
db.exec(`
CREATE TABLE IF NOT EXISTS rsvps (
event_id INTEGER REFERENCES events NOT NULL,
@@ -64,9 +61,7 @@ const upsertRSVP = db.prepare(`
INSERT INTO rsvps VALUES (@event_id, @name, @email)
`);
RSVPS.map((rsvp) => {
- upsertRSVP.run(rsvp);
+ upsertRSVP.run(rsvp);
});
-
-
-export default db; \ No newline at end of file
+export default db;
diff --git a/backend/src/routes/api.js b/backend/src/routes/api.js
deleted file mode 100644
index 2eb07d1..0000000
--- a/backend/src/routes/api.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import { Router } from 'express';
-import usersRouter from './users.js';
-import eventsRouter from './events.js';
-
-
-const router = Router();
-
-router.use('/users', usersRouter);
-router.use('/events', eventsRouter);
-
-
-export default router;
diff --git a/backend/src/routes/api.ts b/backend/src/routes/api.ts
new file mode 100644
index 0000000..92eae46
--- /dev/null
+++ b/backend/src/routes/api.ts
@@ -0,0 +1,10 @@
+import { Router } from "express";
+import usersRouter from "./users.js";
+import eventsRouter from "./events.js";
+
+const router = Router();
+
+router.use("/users", usersRouter);
+router.use("/events", eventsRouter);
+
+export default router;
diff --git a/backend/src/routes/events.js b/backend/src/routes/events.ts
index b95c747..df65eb5 100644
--- a/backend/src/routes/events.js
+++ b/backend/src/routes/events.ts
@@ -1,52 +1,56 @@
-import db from '../db.js';
-import { Router } from 'express';
-import { getUser } from './users.js';
+import db from "../db.js";
+import { Router } from "express";
+import { getUser } from "./users.js";
+import { type Event, type Id, type Rsvps, type User } from "../types.js";
const router = Router();
-const joinHost = (event) => {
- const host = getUser(event.host_id);
+const joinHost = (event: Event) => {
+ const host = getUser(event.host_id) as User;
return { ...event, host };
-}
+};
-const joinRSVPs = (event) => {
+const joinRSVPs = (event: Event) => {
const { id } = event;
- const getRSVPs = db.prepare('SELECT * FROM rsvps WHERE event_id = @id');
- const rsvps = getRSVPs.all({ id });
+ const getRSVPs = db.prepare("SELECT * FROM rsvps WHERE event_id = @id");
+ const rsvps = getRSVPs.all({ id }) as Rsvps[];
return { ...event, rsvps };
-}
+};
-const getEvent = (eventId) => {
- const byId = db.prepare('SELECT * FROM events WHERE id = @eventId');
- const event = byId.get({ eventId });
+const getEvent = (eventId: Id) => {
+ const byId = db.prepare("SELECT * FROM events WHERE id = @eventId");
+ const event = byId.get({ eventId }) as Event;
return joinHost(event);
-}
+};
-router.get('/', (_req, res) => {
+router.get("/", (_req, res) => {
const listEvents = db.prepare(`SELECT * FROM events`);
- const events = listEvents.all();
+ const events = listEvents.all() as Event[];
res.json(events.map(joinHost).map(joinRSVPs));
});
-const insertEvent = db.prepare(`INSERT INTO events VALUES (@id, @title, @description, @image_url, @date, @host_id)`);
+const insertEvent = db.prepare(
+ `INSERT INTO events VALUES (@id, @title, @description, @image_url, @date, @host_id)`,
+);
-router.post('/new', (req, res) => {
+router.post("/new", (req, res) => {
const data = req.body;
- const { lastInsertRowid: id } = insertEvent.run(data);
+ const { lastInsertRowid } = insertEvent.run(data);
+ const id = lastInsertRowid as number;
const event = getEvent(id);
res.status(201).json(event);
});
-router.get('/:id', (req, res) => {
+router.get("/:id", (req, res) => {
const id = parseInt(req.params.id);
const event = getEvent(id);
if (!event) {
- return res.status(404).json({ error: 'Event not found' });
+ return res.status(404).json({ error: "Event not found" });
}
res.json(event);
});
-router.patch('/:id', (req, res) => {
+router.patch("/:id", (req, res) => {
const eventId = parseInt(req.params.id);
const patch = req.body;
@@ -64,23 +68,27 @@ router.patch('/:id', (req, res) => {
res.json(updated);
});
-router.delete('/:id', (req, res) => {
+router.delete("/:id", (req, res) => {
const deleteEvent = db.prepare(`DELETE FROM events WHERE id = @eventId`);
const eventId = parseInt(req.params.id);
const event = getEvent(eventId);
if (!event) {
- return res.status(404).json({ error: 'Event not found' });
+ return res.status(404).json({ error: "Event not found" });
}
deleteEvent.run({ eventId });
res.json(event);
});
-router.post('/:id/rsvp', (req, res) => {
+router.post("/:id/rsvp", (req, res) => {
const eventId = parseInt(req.params.id);
const { name, email } = req.body;
- const getRSVP = db.prepare(`SELECT * FROM rsvps WHERE (event_id = ${eventId} AND email = '${email}')`);
- const insertRSVP = db.prepare(`INSERT INTO rsvps VALUES (@eventId, @name, @email)`);
+ const getRSVP = db.prepare(
+ `SELECT * FROM rsvps WHERE (event_id = ${eventId} AND email = '${email}')`,
+ );
+ const insertRSVP = db.prepare(
+ `INSERT INTO rsvps VALUES (@eventId, @name, @email)`,
+ );
let [rsvp] = getRSVP.all({ eventId, email });
if (rsvp) {
diff --git a/backend/src/routes/users.js b/backend/src/routes/users.ts
index 6d874e9..98ec361 100644
--- a/backend/src/routes/users.js
+++ b/backend/src/routes/users.ts
@@ -1,40 +1,42 @@
-import { Router } from 'express';
-import db from '../db.js';
+import { Router } from "express";
+import db from "../db.js";
+import type { User } from "../types.js";
const router = Router();
-export const getUser = (userId) => {
- const byId = db.prepare('SELECT * FROM users WHERE id = @userId');
+export const getUser = (userId: User["id"]) => {
+ const byId = db.prepare("SELECT * FROM users WHERE id = @userId");
return byId.get({ userId });
-}
+};
-router.get('/', (_req, res) => {
- const listUsers = db.prepare(`SELECT * FROM users`)
+router.get("/", (_req, res) => {
+ const listUsers = db.prepare(`SELECT * FROM users`);
const users = listUsers.all();
res.json(users);
});
-router.post('/new', (req, res) => {
+router.post("/new", (req, res) => {
const data = req.body;
- const cols = Object.keys(data).join(' , ');
- const vals = Object.values(data).join(' , ');
+ const cols = Object.keys(data).join(" , ");
+ const vals = Object.values(data).join(" , ");
const insertUser = db.prepare(`INSERT INTO users(@cols) VALUES (@vals)`);
- const { lastInsertRowid: id } = insertUser.run({ cols, vals });
+ const { lastInsertRowid } = insertUser.run({ cols, vals });
+ const id = lastInsertRowid as number;
const user = getUser(id);
res.json(user);
});
-router.get('/:id', (req, res) => {
- const id = req.params.id;
+router.get("/:id", (req, res) => {
+ const id = Number(req.params.id);
const user = getUser(id);
if (!user) {
- res.status(404).json({ error: 'User not found' });
+ res.status(404).json({ error: "User not found" });
}
res.json(user);
});
-router.patch('/:id', (req, res) => {
- const userId = req.params.id;
+router.patch("/:id", (req, res) => {
+ const userId = Number(req.params.id);
const patch = req.body;
const updateCol = db.prepare(`
@@ -43,7 +45,7 @@ router.patch('/:id', (req, res) => {
const updateUser = db.transaction((patch) => {
for (const [col, val] of Object.entries(patch)) {
updateCol.run(col, val, userId);
- };
+ }
});
updateUser(Object.entries(patch));
@@ -51,12 +53,12 @@ router.patch('/:id', (req, res) => {
res.json(updated);
});
-router.delete('/:id', (req, res) => {
- const deleteUser = db.prepare(`DELETE FROM users WHERE id = @userId`)
+router.delete("/:id", (req, res) => {
+ const deleteUser = db.prepare(`DELETE FROM users WHERE id = @userId`);
const userId = parseInt(req.params.id);
const user = getUser(userId);
if (!user) {
- res.status(404).json({ error: 'User not found' });
+ res.status(404).json({ error: "User not found" });
}
deleteUser.run({ userId });
res.json(user);
diff --git a/backend/src/server.js b/backend/src/server.js
deleted file mode 100644
index 8b579b3..0000000
--- a/backend/src/server.js
+++ /dev/null
@@ -1,40 +0,0 @@
-import express from 'express';
-import cookieParser from 'cookie-parser';
-import logger from 'morgan';
-import cors from 'cors';
-import helmet from 'helmet';
-
-import apiRouter from './routes/api.js';
-
-
-const PORT = process.env.PORT || 3000;
-const NODE_ENV = process.env.NODE_ENV || 'development';
-
-const app = express();
-
-
-app.use(logger('dev'));
-app.use(express.json());
-app.use(express.urlencoded({ extended: false }));
-app.use(cookieParser());
-app.use(helmet());
-app.use(cors({
- origin: 'http://localhost:5173'
-}));
-
-app.use('/api', apiRouter);
-
-app.use((_req, res) => {
- res.status(404).json({
- error: 'Not Found',
- endpoints: [
- '/api/events',
- '/api/users'
- ]
- });
-});
-
-app.listen(PORT, () => {
- console.log(`\nServer listening at http://localhost:${PORT}`);
- console.log(`Server running in ${NODE_ENV} mode\n`);
-}); \ No newline at end of file
diff --git a/backend/src/server.ts b/backend/src/server.ts
new file mode 100644
index 0000000..8582347
--- /dev/null
+++ b/backend/src/server.ts
@@ -0,0 +1,37 @@
+import express from "express";
+import cookieParser from "cookie-parser";
+import logger from "morgan";
+import cors from "cors";
+import helmet from "helmet";
+
+import apiRouter from "./routes/api.js";
+
+const PORT = process.env.PORT || 3000;
+const NODE_ENV = process.env.NODE_ENV || "development";
+
+const app = express();
+
+app.use(logger("dev"));
+app.use(express.json());
+app.use(express.urlencoded({ extended: false }));
+app.use(cookieParser());
+app.use(helmet());
+app.use(
+ cors({
+ origin: "http://localhost:5173",
+ }),
+);
+
+app.use("/api", apiRouter);
+
+app.use((_req, res) => {
+ res.status(404).json({
+ error: "Not Found",
+ endpoints: ["/api/events", "/api/users"],
+ });
+});
+
+app.listen(PORT, () => {
+ console.log(`\nServer listening at http://localhost:${PORT}`);
+ console.log(`Server running in ${NODE_ENV} mode\n`);
+});
diff --git a/backend/src/types.ts b/backend/src/types.ts
new file mode 100644
index 0000000..5c8112c
--- /dev/null
+++ b/backend/src/types.ts
@@ -0,0 +1,24 @@
+export type Id = number;
+
+export interface Event {
+ id: Id;
+ title: string;
+ description?: string;
+ date: Date;
+ host_id: number;
+ image_url?: string;
+ host: User;
+ rsvps: Rsvps[];
+}
+
+export interface User {
+ id: number;
+ name: string;
+ email: string;
+}
+
+export interface Rsvps {
+ id: number;
+ name: string;
+ email: string;
+}
diff --git a/backend/tsconfig.json b/backend/tsconfig.json
new file mode 100644
index 0000000..0373555
--- /dev/null
+++ b/backend/tsconfig.json
@@ -0,0 +1,46 @@
+{
+ "extends": "@tsconfig/node-lts/tsconfig.json",
+ // Visit https://aka.ms/tsconfig to read more about this file
+ "compilerOptions": {
+ // File Layout
+ "rootDir": "./src",
+ "outDir": "./dist",
+
+ // Environment Settings
+ // See also https://aka.ms/tsconfig/module
+ "module": "nodenext",
+ "target": "esnext",
+ "types": [
+ "node"
+ ],
+ // For nodejs:
+ // "lib": ["esnext"],
+ // and npm install -D @types/node
+
+ // Other Outputs
+ "sourceMap": true,
+ "declaration": true,
+ "declarationMap": true,
+
+ // Stricter Typechecking Options
+ "noUncheckedIndexedAccess": true,
+ "exactOptionalPropertyTypes": true,
+
+ // Style Options
+ // "noImplicitReturns": true,
+ // "noImplicitOverride": true,
+ // "noUnusedLocals": true,
+ // "noUnusedParameters": true,
+ // "noFallthroughCasesInSwitch": true,
+ // "noPropertyAccessFromIndexSignature": true,
+
+ // Recommended Options
+ "strict": true,
+ "jsx": "react-jsx",
+ "verbatimModuleSyntax": true,
+ "isolatedModules": true,
+ "noUncheckedSideEffectImports": true,
+ "moduleDetection": "force",
+ "skipLibCheck": true,
+ }
+}