From 1c26c2ba9e817141f6da98a03309a573cfcb621a Mon Sep 17 00:00:00 2001 From: Oleh Mysko Date: Tue, 23 Sep 2025 16:36:33 +0300 Subject: [PATCH 1/8] solution --- src/createServer.js | 60 +++++++++++++++++++++++++++++++++++++++++---- src/index.html | 28 +++++++++++++++++++++ 2 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 src/index.html diff --git a/src/createServer.js b/src/createServer.js index 1cf1dda..bea6b33 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -1,10 +1,60 @@ 'use strict'; +const http = require('http'); +const path = require('path'); +const fs = require('fs'); + function createServer() { - /* Write your code here */ - // Return instance of http.Server class + return http.createServer((req, res) => { + const indexPath = path.resolve('src', 'index.html'); + + if (req.method === 'GET' && req.url === '/') { + try { + const file = fs.readFileSync(indexPath); + + res.writeHead(200, { 'Content-Type': 'text/html' }); + res.end(file); + } catch { + res.writeHead(404, { 'Content-Type': 'text/plain' }); + res.end('file not found'); + } + + return; + } + + + if (req.method === 'POST' && req.url === '/add-expense') { + const chunks = []; + + req.on('data', (chunk) => chunks.push(chunk)); + + req.on('end', () => { + try { + const buffer = Buffer.concat(chunks).toString(); + const obj = JSON.parse(buffer); + + if (!obj.date || !obj.title || !obj.amount) { + res.writeHead(400, { 'Content-Type': 'text/plain' }); + res.end('Invalid expense data'); + + return; + } + + fs.writeFileSync('db/expense.json', JSON.stringify(obj, null, 2)); + + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify(obj)); + } catch (err) { + res.writeHead(400, { 'Content-Type': 'text/plain' }); + res.end('Invalid JSON'); + } + }); + + return; + } + res.writeHead(404, { 'Content-Type': 'text/plain' }); + res.end('Not found'); + }); } -module.exports = { - createServer, -}; +module.exports = { createServer }; diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..836e8e7 --- /dev/null +++ b/src/index.html @@ -0,0 +1,28 @@ + + + + + + Add Expense + + +

Add Expense

+
+ +
+ + +
+ + + + +
+ + From 173c51af86b3627b27136b245b90e1bf2bd92de4 Mon Sep 17 00:00:00 2001 From: Oleh Mysko Date: Tue, 23 Sep 2025 16:37:04 +0300 Subject: [PATCH 2/8] solutio --- src/createServer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/createServer.js b/src/createServer.js index bea6b33..90530fd 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -22,7 +22,6 @@ function createServer() { return; } - if (req.method === 'POST' && req.url === '/add-expense') { const chunks = []; From 1e07f1192866ce767286eaf02af4cfaeef63bcb6 Mon Sep 17 00:00:00 2001 From: Oleh Mysko Date: Tue, 23 Sep 2025 17:07:30 +0300 Subject: [PATCH 3/8] solutio --- src/createServer.js | 19 +++++++++++++++++-- src/index.html | 8 ++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/createServer.js b/src/createServer.js index 90530fd..1db940a 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -39,10 +39,25 @@ function createServer() { return; } - fs.writeFileSync('db/expense.json', JSON.stringify(obj, null, 2)); + let ar = []; + + try { + const file = fs.readFileSync('db/expense.json', 'utf-8'); + + ar = JSON.parse(file); + + if (!Array.isArray(ar)) { + ar = []; + } + } catch { + ar = []; + } + ar.push(obj); + + fs.writeFileSync('db/expense.json', JSON.stringify(ar, null, 2)); res.writeHead(200, { 'Content-Type': 'application/json' }); - res.end(JSON.stringify(obj)); + res.end(`
${JSON.stringify(obj)}
`); } catch (err) { res.writeHead(400, { 'Content-Type': 'text/plain' }); res.end('Invalid JSON'); diff --git a/src/index.html b/src/index.html index 836e8e7..05489c6 100644 --- a/src/index.html +++ b/src/index.html @@ -7,7 +7,7 @@

Add Expense

-
+
- + +
From d3be6f50b315b4b609d93314fdd5b71dad464639 Mon Sep 17 00:00:00 2001 From: Oleh Mysko Date: Tue, 23 Sep 2025 17:09:08 +0300 Subject: [PATCH 4/8] solutio --- src/createServer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/createServer.js b/src/createServer.js index 1db940a..d40f08f 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -57,7 +57,7 @@ function createServer() { fs.writeFileSync('db/expense.json', JSON.stringify(ar, null, 2)); res.writeHead(200, { 'Content-Type': 'application/json' }); - res.end(`
${JSON.stringify(obj)}
`); + res.end(JSON.stringify(obj)); } catch (err) { res.writeHead(400, { 'Content-Type': 'text/plain' }); res.end('Invalid JSON'); From 6f4f672453ea2197a97fac13a44346e43b5c7578 Mon Sep 17 00:00:00 2001 From: Oleh Mysko Date: Tue, 23 Sep 2025 17:11:50 +0300 Subject: [PATCH 5/8] solutio --- src/createServer.js | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/createServer.js b/src/createServer.js index d40f08f..89a157a 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -1,27 +1,27 @@ 'use strict'; const http = require('http'); -const path = require('path'); const fs = require('fs'); +const path = require('path'); function createServer() { return http.createServer((req, res) => { const indexPath = path.resolve('src', 'index.html'); + if (req.method === 'GET' && req.url === '/') { try { const file = fs.readFileSync(indexPath); - res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(file); } catch { res.writeHead(404, { 'Content-Type': 'text/plain' }); res.end('file not found'); } - return; } + if (req.method === 'POST' && req.url === '/add-expense') { const chunks = []; @@ -32,33 +32,34 @@ function createServer() { const buffer = Buffer.concat(chunks).toString(); const obj = JSON.parse(buffer); + if (!obj.date || !obj.title || !obj.amount) { res.writeHead(400, { 'Content-Type': 'text/plain' }); res.end('Invalid expense data'); - return; } - let ar = []; + let arr = []; + try { const file = fs.readFileSync('db/expense.json', 'utf-8'); - - ar = JSON.parse(file); - - if (!Array.isArray(ar)) { - ar = []; - } + arr = JSON.parse(file); + if (!Array.isArray(arr)) arr = []; } catch { - ar = []; + arr = []; } - ar.push(obj); - fs.writeFileSync('db/expense.json', JSON.stringify(ar, null, 2)); + + arr.push(obj); + + + fs.writeFileSync('db/expense.json', JSON.stringify(arr, null, 2)); + res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(obj)); - } catch (err) { + } catch { res.writeHead(400, { 'Content-Type': 'text/plain' }); res.end('Invalid JSON'); } @@ -66,6 +67,8 @@ function createServer() { return; } + + res.writeHead(404, { 'Content-Type': 'text/plain' }); res.end('Not found'); }); From 790db020a25c9c9cbbd76f3496aeb3501a1613d5 Mon Sep 17 00:00:00 2001 From: Oleh Mysko Date: Tue, 23 Sep 2025 18:54:23 +0300 Subject: [PATCH 6/8] se --- src/createServer.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/createServer.js b/src/createServer.js index 89a157a..5d097b4 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -8,20 +8,20 @@ function createServer() { return http.createServer((req, res) => { const indexPath = path.resolve('src', 'index.html'); - if (req.method === 'GET' && req.url === '/') { try { const file = fs.readFileSync(indexPath); + res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(file); } catch { res.writeHead(404, { 'Content-Type': 'text/plain' }); res.end('file not found'); } + return; } - if (req.method === 'POST' && req.url === '/add-expense') { const chunks = []; @@ -32,30 +32,30 @@ function createServer() { const buffer = Buffer.concat(chunks).toString(); const obj = JSON.parse(buffer); - if (!obj.date || !obj.title || !obj.amount) { res.writeHead(400, { 'Content-Type': 'text/plain' }); res.end('Invalid expense data'); + return; } let arr = []; - try { const file = fs.readFileSync('db/expense.json', 'utf-8'); + arr = JSON.parse(file); - if (!Array.isArray(arr)) arr = []; + + if (!Array.isArray(arr)) { + arr = []; + } } catch { arr = []; } - arr.push(obj); - - fs.writeFileSync('db/expense.json', JSON.stringify(arr, null, 2)); - + fs.writeFileSync('db/expense.json', JSON.stringify(obj, null, 2)); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(obj)); @@ -68,7 +68,6 @@ function createServer() { return; } - res.writeHead(404, { 'Content-Type': 'text/plain' }); res.end('Not found'); }); From dea5059d4fa7de80d95b6bdbdf335401aa8919cf Mon Sep 17 00:00:00 2001 From: Oleh Mysko Date: Tue, 23 Sep 2025 19:08:48 +0300 Subject: [PATCH 7/8] se --- src/createServer.js | 3 +- src/index.html | 84 +++++++++++++++++++++++++++++---------------- 2 files changed, 55 insertions(+), 32 deletions(-) diff --git a/src/createServer.js b/src/createServer.js index 5d097b4..9c51a41 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -55,8 +55,7 @@ function createServer() { arr.push(obj); - fs.writeFileSync('db/expense.json', JSON.stringify(obj, null, 2)); - + fs.writeFileSync('db/expense.json', JSON.stringify(arr, null, 2)); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(obj)); } catch { diff --git a/src/index.html b/src/index.html index 05489c6..7e88077 100644 --- a/src/index.html +++ b/src/index.html @@ -1,32 +1,56 @@ - + - - - - Add Expense - - -

Add Expense

-
- -
- - -
- - -
- - -
- + + + Add Expense + + +

Add Expense

+
+
+
+
+ +
+ +

All Expenses

+
+ + + + From dfd13087f35cd8231295f6879deab8c84aa16d8f Mon Sep 17 00:00:00 2001 From: Oleh Mysko Date: Tue, 23 Sep 2025 19:47:01 +0300 Subject: [PATCH 8/8] aa --- src/createServer.js | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/createServer.js b/src/createServer.js index 9c51a41..ddeb5c5 100644 --- a/src/createServer.js +++ b/src/createServer.js @@ -4,10 +4,13 @@ const http = require('http'); const fs = require('fs'); const path = require('path'); +const DATA_PATH = path.resolve('db', 'expense.json'); + function createServer() { return http.createServer((req, res) => { const indexPath = path.resolve('src', 'index.html'); + if (req.method === 'GET' && req.url === '/') { try { const file = fs.readFileSync(indexPath); @@ -22,6 +25,7 @@ function createServer() { return; } + if (req.method === 'POST' && req.url === '/add-expense') { const chunks = []; @@ -39,23 +43,9 @@ function createServer() { return; } - let arr = []; - try { - const file = fs.readFileSync('db/expense.json', 'utf-8'); + fs.writeFileSync(DATA_PATH, JSON.stringify(obj, null, 2)); - arr = JSON.parse(file); - - if (!Array.isArray(arr)) { - arr = []; - } - } catch { - arr = []; - } - - arr.push(obj); - - fs.writeFileSync('db/expense.json', JSON.stringify(arr, null, 2)); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(obj)); } catch { @@ -66,6 +56,22 @@ function createServer() { return; } + if (req.method === 'GET' && req.url === '/expenses') { + try { + const data = fs.existsSync(DATA_PATH) + ? fs.readFileSync(DATA_PATH, 'utf-8') + : ''; + const obj = data ? JSON.parse(data) : {}; + + res.writeHead(200, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify(obj)); + } catch { + res.writeHead(500, { 'Content-Type': 'text/plain' }); + res.end('Failed to read expense'); + } + + return; + } res.writeHead(404, { 'Content-Type': 'text/plain' }); res.end('Not found');