Skip to content

Commit dac4857

Browse files
committed
update docker-compose file
1 parent 9f16777 commit dac4857

34 files changed

Lines changed: 5598 additions & 0 deletions
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
node_modules
2+
npm-debug.log
3+
dist
4+
.env
5+
.git
6+
.gitignore

Node.js/Todo-App/Backend/.env

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
PORT=5000
2+
POSTGRES_USER=postgres
3+
POSTGRES_PASSWORD=postgres
4+
POSTGRES_DB=todo_app
5+
POSTGRES_HOST=172.22.226.90
6+
POSTGRES_PORT=5432
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Use Node.js LTS version
2+
FROM node:20-alpine
3+
4+
# Create app directory
5+
WORKDIR /usr/src/app
6+
7+
# Copy package files
8+
COPY package*.json ./
9+
10+
# Install dependencies
11+
RUN npm install
12+
13+
# Copy source code
14+
COPY . .
15+
16+
# Build TypeScript code
17+
RUN npm run build
18+
19+
# Expose port
20+
EXPOSE 5000
21+
22+
# Start the application
23+
CMD ["npm", "start"]
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"use strict";
2+
var __importDefault = (this && this.__importDefault) || function (mod) {
3+
return (mod && mod.__esModule) ? mod : { "default": mod };
4+
};
5+
Object.defineProperty(exports, "__esModule", { value: true });
6+
exports.pool = void 0;
7+
const pg_1 = require("pg");
8+
const dotenv_1 = __importDefault(require("dotenv"));
9+
dotenv_1.default.config();
10+
exports.pool = new pg_1.Pool({
11+
user: process.env.POSTGRES_USER,
12+
password: process.env.POSTGRES_PASSWORD,
13+
host: process.env.POSTGRES_HOST,
14+
port: parseInt(process.env.POSTGRES_PORT || '5432'),
15+
database: process.env.POSTGRES_DB,
16+
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"use strict";
2+
Object.defineProperty(exports, "__esModule", { value: true });
3+
exports.handleError = exports.ApiError = void 0;
4+
class ApiError extends Error {
5+
constructor(statusCode, message) {
6+
super(message);
7+
this.statusCode = statusCode;
8+
this.name = 'ApiError';
9+
}
10+
}
11+
exports.ApiError = ApiError;
12+
const handleError = (error) => {
13+
if (error instanceof ApiError) {
14+
return { statusCode: error.statusCode, message: error.message };
15+
}
16+
console.error('Unexpected error:', error);
17+
return { statusCode: 500, message: 'Internal server error' };
18+
};
19+
exports.handleError = handleError;
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
"use strict";
2+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4+
return new (P || (P = Promise))(function (resolve, reject) {
5+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8+
step((generator = generator.apply(thisArg, _arguments || [])).next());
9+
});
10+
};
11+
var __importDefault = (this && this.__importDefault) || function (mod) {
12+
return (mod && mod.__esModule) ? mod : { "default": mod };
13+
};
14+
Object.defineProperty(exports, "__esModule", { value: true });
15+
const express_1 = __importDefault(require("express"));
16+
const cors_1 = __importDefault(require("cors"));
17+
const db_1 = require("./db");
18+
const errors_1 = require("./errors");
19+
const app = (0, express_1.default)();
20+
const port = process.env.PORT || 5000;
21+
app.use((0, cors_1.default)());
22+
app.use(express_1.default.json());
23+
const validateTodoInput = (data) => {
24+
if (!data.title) {
25+
throw new errors_1.ApiError(400, 'Title is required');
26+
}
27+
if (data.title.length > 255) {
28+
throw new errors_1.ApiError(400, 'Title must be less than 255 characters');
29+
}
30+
};
31+
const initializeDatabase = () => __awaiter(void 0, void 0, void 0, function* () {
32+
try {
33+
yield db_1.pool.query(`
34+
CREATE TABLE IF NOT EXISTS todos (
35+
id SERIAL PRIMARY KEY,
36+
title VARCHAR(255) NOT NULL,
37+
description TEXT,
38+
completed BOOLEAN DEFAULT FALSE,
39+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
40+
)
41+
`);
42+
console.log('Database initialized successfully');
43+
}
44+
catch (error) {
45+
console.error('Failed to initialize database:', error);
46+
process.exit(1);
47+
}
48+
});
49+
// Get all todos
50+
app.get('/api/todos', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
51+
try {
52+
const result = yield db_1.pool.query('SELECT * FROM todos ORDER BY created_at DESC');
53+
res.json(result.rows);
54+
}
55+
catch (error) {
56+
const { statusCode, message } = (0, errors_1.handleError)(error);
57+
res.status(statusCode).json({ error: message });
58+
}
59+
}));
60+
// Get a single todo
61+
app.get('/api/todos/:id', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
62+
try {
63+
const { id } = req.params;
64+
if (!Number.isInteger(Number(id))) {
65+
throw new errors_1.ApiError(400, 'Invalid ID format');
66+
}
67+
const result = yield db_1.pool.query('SELECT * FROM todos WHERE id = $1', [id]);
68+
if (result.rows.length === 0) {
69+
throw new errors_1.ApiError(404, 'Todo not found');
70+
}
71+
res.json(result.rows[0]);
72+
}
73+
catch (error) {
74+
const { statusCode, message } = (0, errors_1.handleError)(error);
75+
res.status(statusCode).json({ error: message });
76+
}
77+
}));
78+
// Create a todo
79+
app.post('/api/todos', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
80+
try {
81+
const todoData = req.body;
82+
validateTodoInput(todoData);
83+
const result = yield db_1.pool.query('INSERT INTO todos (title, description) VALUES ($1, $2) RETURNING *', [todoData.title, todoData.description]);
84+
res.status(201).json(result.rows[0]);
85+
}
86+
catch (error) {
87+
const { statusCode, message } = (0, errors_1.handleError)(error);
88+
res.status(statusCode).json({ error: message });
89+
}
90+
}));
91+
// Update a todo
92+
app.put('/api/todos/:id', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
93+
try {
94+
const { id } = req.params;
95+
const { title, description, completed } = req.body;
96+
if (!Number.isInteger(Number(id))) {
97+
throw new errors_1.ApiError(400, 'Invalid ID format');
98+
}
99+
if (title) {
100+
validateTodoInput({ title });
101+
}
102+
const result = yield db_1.pool.query('UPDATE todos SET title = $1, description = $2, completed = $3 WHERE id = $4 RETURNING *', [title, description, completed, id]);
103+
if (result.rows.length === 0) {
104+
throw new errors_1.ApiError(404, 'Todo not found');
105+
}
106+
res.json(result.rows[0]);
107+
}
108+
catch (error) {
109+
const { statusCode, message } = (0, errors_1.handleError)(error);
110+
res.status(statusCode).json({ error: message });
111+
}
112+
}));
113+
// Delete a todo
114+
app.delete('/api/todos/:id', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
115+
try {
116+
const { id } = req.params;
117+
if (!Number.isInteger(Number(id))) {
118+
throw new errors_1.ApiError(400, 'Invalid ID format');
119+
}
120+
const result = yield db_1.pool.query('DELETE FROM todos WHERE id = $1 RETURNING *', [id]);
121+
if (result.rows.length === 0) {
122+
throw new errors_1.ApiError(404, 'Todo not found');
123+
}
124+
res.json({ message: 'Todo deleted successfully' });
125+
}
126+
catch (error) {
127+
const { statusCode, message } = (0, errors_1.handleError)(error);
128+
res.status(statusCode).json({ error: message });
129+
}
130+
}));
131+
// Graceful shutdown
132+
const shutdown = () => __awaiter(void 0, void 0, void 0, function* () {
133+
try {
134+
yield db_1.pool.end();
135+
console.log('Database pool has ended');
136+
process.exit(0);
137+
}
138+
catch (error) {
139+
console.error('Error during shutdown:', error);
140+
process.exit(1);
141+
}
142+
});
143+
process.on('SIGTERM', shutdown);
144+
process.on('SIGINT', shutdown);
145+
// Start the server
146+
const startServer = () => __awaiter(void 0, void 0, void 0, function* () {
147+
yield initializeDatabase();
148+
app.listen(port, () => {
149+
console.log(`Server running on port ${port}`);
150+
});
151+
});
152+
startServer().catch((error) => {
153+
console.error('Failed to start server:', error);
154+
process.exit(1);
155+
});
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
"use strict";
2+
Object.defineProperty(exports, "__esModule", { value: true });

0 commit comments

Comments
 (0)