From a1f544b06fd06f6625640264be105ede661cc69a Mon Sep 17 00:00:00 2001 From: Ion-Gavrilencu <157795149+Ion-Gavrilencu@users.noreply.github.com> Date: Fri, 29 Nov 2024 08:53:54 +0200 Subject: [PATCH] update01 --- app.js | 33 +-- controller/contactsController.js | 66 ++++++ models/contacts.js | 41 ++-- models/contacts.json | 40 ++-- package-lock.json | 389 +++++++++++++++++++++++++++++-- package.json | 6 +- routes/api/contacts.js | 142 +++++++++-- server.js | 2 +- utils/connectToDb.js | 17 ++ 9 files changed, 648 insertions(+), 88 deletions(-) create mode 100644 controller/contactsController.js create mode 100644 utils/connectToDb.js diff --git a/app.js b/app.js index 40fd9bc167f..7022962be97 100644 --- a/app.js +++ b/app.js @@ -1,25 +1,26 @@ -const express = require('express') -const logger = require('morgan') -const cors = require('cors') +import express from "express"; +import logger from "morgan"; +import cors from "cors"; +import contactsRouter from "./routes/api/contacts.js"; +import connectToDb from "./utils/connectToDb.js"; +const app = express(); -const contactsRouter = require('./routes/api/contacts') +const formatsLogger = app.get("env") === "development" ? "dev" : "short"; -const app = express() +connectToDb(); -const formatsLogger = app.get('env') === 'development' ? 'dev' : 'short' +app.use(logger(formatsLogger)); +app.use(cors()); +app.use(express.json()); -app.use(logger(formatsLogger)) -app.use(cors()) -app.use(express.json()) - -app.use('/api/contacts', contactsRouter) +app.use("/api/contacts", contactsRouter); app.use((req, res) => { - res.status(404).json({ message: 'Not found' }) -}) + res.status(404).json({ message: "Not found" }); +}); app.use((err, req, res, next) => { - res.status(500).json({ message: err.message }) -}) + res.status(500).json({ message: err.message }); +}); -module.exports = app +export default app; diff --git a/controller/contactsController.js b/controller/contactsController.js new file mode 100644 index 00000000000..493439e9f57 --- /dev/null +++ b/controller/contactsController.js @@ -0,0 +1,66 @@ + // import (promises as fs) from fs; +// eslint-disable-next-line +import { v4 as uuidv4 } from "uuid"; +import Contact from "../models/contacts.js"; + +const ContactsController = { + listContacts, + getContactsById, + addContact, + updateStatusContact, + updateContact, + deleteContact, +}; + +async function listContacts() { + console.log("--- List Contacts --- "); + try { + return Contact.find(); + } catch (error) { + console.error(error); + } +} + +async function getContactsById(id) { + console.log(`--- List Contacts by id #{id} --- `); + try { + return Contact.findById(id); + } catch (error) { + console.error(error); + } +} + +async function addContact(contact) { + return Contact.create(contact); +} + + + +async function deleteContact(contactId) { + return Contact.findByIdAndDelete(contactId); +} + +async function updateContact(contactId, updatedData) { + try { + // Găsește contactul după ID și actualizează complet + return await Contact.findByIdAndUpdate(contactId, updatedData, { new: true, runValidators: true }); + } catch (error) { + console.error("Error updating contact:", error); + return null; + } +} + + +async function updateStatusContact(contactId, updateData) { + try { + // Găsește contactul după ID și actualizează câmpul `favorite` + return await Contact.findByIdAndUpdate(contactId, updateData, { new: true }); + } catch (error) { + console.error("Error updating contact status:", error); + return null; + } +} + + + +export default ContactsController; \ No newline at end of file diff --git a/models/contacts.js b/models/contacts.js index 409d11c7c09..1eb54e0de90 100644 --- a/models/contacts.js +++ b/models/contacts.js @@ -1,19 +1,26 @@ -// const fs = require('fs/promises') +import mongoose from "mongoose"; +const { Schema, model } = mongoose; -const listContacts = async () => {} +const schema = new Schema( + { + name: { + type: String, + required: [true, 'Set name for contact'], + }, + email: { + type: String, + }, + phone: { + type: String, + }, + favorite: { + type: Boolean, + default: false, + }, + }, + + { collection: "contacts" } +); +const Contact = model("Contact", schema); -const getContactById = async (contactId) => {} - -const removeContact = async (contactId) => {} - -const addContact = async (body) => {} - -const updateContact = async (contactId, body) => {} - -module.exports = { - listContacts, - getContactById, - removeContact, - addContact, - updateContact, -} +export default Contact; diff --git a/models/contacts.json b/models/contacts.json index a21679132de..f2fa2e4600a 100644 --- a/models/contacts.json +++ b/models/contacts.json @@ -1,62 +1,62 @@ [ { - "id": "AeHIrLTr6JkxGE6SN-0Rw", "name": "Allen Raymond", "email": "nulla.ante@vestibul.co.uk", - "phone": "(992) 914-3792" + "phone": "(992) 914-3792", + "favorite": false }, { - "id": "qdggE76Jtbfd9eWJHrssH", "name": "Chaim Lewis", "email": "dui.in@egetlacus.ca", - "phone": "(294) 840-6685" + "phone": "(294) 840-6685", + "favorite": true }, { - "id": "drsAJ4SHPYqZeG-83QTVW", "name": "Kennedy Lane", "email": "mattis.Cras@nonenimMauris.net", - "phone": "(542) 451-7038" + "phone": "(542) 451-7038", + "favorite": false }, { - "id": "vza2RIzNGIwutCVCs4mCL", "name": "Wylie Pope", "email": "est@utquamvel.net", - "phone": "(692) 802-2949" + "phone": "(692) 802-2949", + "favorite": true }, { - "id": "05olLMgyVQdWRwgKfg5J6", "name": "Cyrus Jackson", "email": "nibh@semsempererat.com", - "phone": "(501) 472-5218" + "phone": "(501) 472-5218", + "favorite": true }, { - "id": "1DEXoP8AuCGYc1YgoQ6hw", "name": "Abbot Franks", "email": "scelerisque@magnis.org", - "phone": "(186) 568-3720" + "phone": "(186) 568-3720", + "favorite": true }, { - "id": "Z5sbDlS7pCzNsnAHLtDJd", "name": "Reuben Henry", "email": "pharetra.ut@dictum.co.uk", - "phone": "(715) 598-5792" + "phone": "(715) 598-5792", + "favorite": true }, { - "id": "C9sjBfCo4UJCWjzBnOtxl", "name": "Simon Morton", "email": "dui.Fusce.diam@Donec.com", - "phone": "(233) 738-2360" + "phone": "(233) 738-2360", + "favorite": true }, { - "id": "e6ywwRe4jcqxXfCZOj_1e", "name": "Thomas Lucas", "email": "nec@Nulla.com", - "phone": "(704) 398-7993" + "phone": "(704) 398-7993", + "favorite": false }, { - "id": "rsKkOQUi80UsgVPCcLZZW", "name": "Alec Howard", "email": "Donec.elementum@scelerisquescelerisquedui.net", - "phone": "(748) 206-2688" + "phone": "(748) 206-2688", + "favorite": true } ] diff --git a/package-lock.json b/package-lock.json index e6d047044e5..5ed30153618 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,8 +10,11 @@ "dependencies": { "cors": "2.8.5", "cross-env": "7.0.3", + "dotenv": "^16.4.5", "express": "4.17.1", - "morgan": "1.10.0" + "mongoose": "^8.8.3", + "morgan": "1.10.0", + "uuid": "^11.0.3" }, "devDependencies": { "eslint": "7.19.0", @@ -141,6 +144,15 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", + "integrity": "sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==", + "license": "MIT", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, "node_modules/@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -168,6 +180,21 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", + "license": "MIT" + }, + "node_modules/@types/whatwg-url": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", + "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", + "license": "MIT", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -452,6 +479,15 @@ "node": ">=8" } }, + "node_modules/bson": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.0.tgz", + "integrity": "sha512-ROchNosXMJD2cbQGm84KoP7vOGPO6/bOAW0veMMbzhXLqoZptcaYRVLitwvuhwhjjpU1qP4YZRWLhgETdgqUQw==", + "license": "Apache-2.0", + "engines": { + "node": ">=16.20.1" + } + }, "node_modules/bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -728,7 +764,6 @@ "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -823,6 +858,18 @@ "node": ">=8" } }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", @@ -2215,6 +2262,15 @@ "json5": "lib/cli.js" } }, + "node_modules/kareem": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", + "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -2327,6 +2383,12 @@ "node": ">= 0.6" } }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "license": "MIT" + }, "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -2397,6 +2459,90 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "node_modules/mongodb": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.10.0.tgz", + "integrity": "sha512-gP9vduuYWb9ZkDM546M+MP2qKVk5ZG2wPF63OvSRuUbqCR+11ZCAE1mOfllhlAG0wcoJY5yDL/rV3OmYEwXIzg==", + "license": "Apache-2.0", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.7.0", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz", + "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==", + "license": "Apache-2.0", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "node_modules/mongoose": { + "version": "8.8.3", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.8.3.tgz", + "integrity": "sha512-/I4n/DcXqXyIiLRfAmUIiTjj3vXfeISke8dt4U4Y8Wfm074Wa6sXnQrXN49NFOFf2mM1kUdOXryoBvkuCnr+Qw==", + "license": "MIT", + "dependencies": { + "bson": "^6.7.0", + "kareem": "2.6.3", + "mongodb": "~6.10.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "17.1.3" + }, + "engines": { + "node": ">=16.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, "node_modules/morgan": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", @@ -2433,11 +2579,31 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "license": "MIT", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -2863,10 +3029,10 @@ } }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", "engines": { "node": ">=6" } @@ -3185,6 +3351,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sift": { + "version": "17.1.3", + "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", + "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==", + "license": "MIT" + }, "node_modules/signal-exit": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", @@ -3208,6 +3380,15 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "license": "MIT", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -3392,6 +3573,18 @@ "nodetouch": "bin/nodetouch.js" } }, + "node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/tsconfig-paths": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", @@ -3544,6 +3737,19 @@ "node": ">= 0.4.0" } }, + "node_modules/uuid": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz", + "integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -3558,6 +3764,28 @@ "node": ">= 0.8" } }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "license": "MIT", + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -3757,6 +3985,14 @@ "strip-json-comments": "^3.1.1" } }, + "@mongodb-js/saslprep": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", + "integrity": "sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==", + "requires": { + "sparse-bitfield": "^3.0.3" + } + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -3778,6 +4014,19 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" + }, + "@types/whatwg-url": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", + "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", + "requires": { + "@types/webidl-conversions": "*" + } + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -3997,6 +4246,11 @@ "fill-range": "^7.0.1" } }, + "bson": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.0.tgz", + "integrity": "sha512-ROchNosXMJD2cbQGm84KoP7vOGPO6/bOAW0veMMbzhXLqoZptcaYRVLitwvuhwhjjpU1qP4YZRWLhgETdgqUQw==" + }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -4198,7 +4452,6 @@ "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", - "dev": true, "requires": { "ms": "2.1.2" } @@ -4267,6 +4520,11 @@ "is-obj": "^2.0.0" } }, + "dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==" + }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", @@ -5312,6 +5570,11 @@ "minimist": "^1.2.0" } }, + "kareem": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", + "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==" + }, "keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -5399,6 +5662,11 @@ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, + "memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" + }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -5448,6 +5716,46 @@ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, + "mongodb": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.10.0.tgz", + "integrity": "sha512-gP9vduuYWb9ZkDM546M+MP2qKVk5ZG2wPF63OvSRuUbqCR+11ZCAE1mOfllhlAG0wcoJY5yDL/rV3OmYEwXIzg==", + "requires": { + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.7.0", + "mongodb-connection-string-url": "^3.0.0" + } + }, + "mongodb-connection-string-url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz", + "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==", + "requires": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "mongoose": { + "version": "8.8.3", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.8.3.tgz", + "integrity": "sha512-/I4n/DcXqXyIiLRfAmUIiTjj3vXfeISke8dt4U4Y8Wfm074Wa6sXnQrXN49NFOFf2mM1kUdOXryoBvkuCnr+Qw==", + "requires": { + "bson": "^6.7.0", + "kareem": "2.6.3", + "mongodb": "~6.10.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "17.1.3" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, "morgan": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", @@ -5480,11 +5788,23 @@ } } }, + "mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==" + }, + "mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "requires": { + "debug": "4.x" + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "natural-compare": { "version": "1.4.0", @@ -5795,10 +6115,9 @@ } }, "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" }, "pupa": { "version": "2.1.1", @@ -6047,6 +6366,11 @@ "object-inspect": "^1.9.0" } }, + "sift": { + "version": "17.1.3", + "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", + "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==" + }, "signal-exit": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", @@ -6064,6 +6388,14 @@ "is-fullwidth-code-point": "^3.0.0" } }, + "sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "requires": { + "memory-pager": "^1.0.2" + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -6204,6 +6536,14 @@ "nopt": "~1.0.10" } }, + "tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "requires": { + "punycode": "^2.3.0" + } + }, "tsconfig-paths": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", @@ -6326,6 +6666,11 @@ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, + "uuid": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz", + "integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==" + }, "v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -6337,6 +6682,20 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" + }, + "whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "requires": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 5045e827160..dd866175846 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,13 @@ "dependencies": { "cors": "2.8.5", "cross-env": "7.0.3", + "dotenv": "^16.4.5", "express": "4.17.1", - "morgan": "1.10.0" + "mongoose": "^8.8.3", + "morgan": "1.10.0", + "uuid": "^11.0.3" }, + "type": "module", "devDependencies": { "eslint": "7.19.0", "eslint-config-prettier": "^8.3.0", diff --git a/routes/api/contacts.js b/routes/api/contacts.js index a60ebd69231..aac0336fabd 100644 --- a/routes/api/contacts.js +++ b/routes/api/contacts.js @@ -1,25 +1,131 @@ -const express = require('express') +import express from "express"; +import ContactsController from "../../controller/contactsController.js"; -const router = express.Router() +const router = express.Router(); +const STATUS_CODES = { + success: 200, + deleted: 204, + error: 500, +}; -router.get('/', async (req, res, next) => { - res.json({ message: 'template message' }) -}) +/* GET localhost:3000/api/contacts */ +router.get("/", async (req, res, next) => { + try { + const contacts = await ContactsController.listContacts(); -router.get('/:contactId', async (req, res, next) => { - res.json({ message: 'template message' }) -}) + res + .status(STATUS_CODES.success) + .json({ message: "Lista a fost returnata cu succes", data: contacts }); + } catch (error) { + respondWithError(res, error); + } +}); -router.post('/', async (req, res, next) => { - res.json({ message: 'template message' }) -}) +/* GET localhost:3000/api/contacts/:id */ +router.get("/:id", async (req, res, next) => { + try { + const contact = await ContactsController.getContactsById(req.params.id); + if (!contact) { + throw new Error("Contactul nu a fost gasit"); + } + res + .status(STATUS_CODES.success) + .json({ message: "Contactul a fost returnat cu succes", data: contact}); + } catch (error) { + respondWithError(res, error); + } +}); -router.delete('/:contactId', async (req, res, next) => { - res.json({ message: 'template message' }) -}) +/* POST localhost:3000/api/contacts/ */ +router.post("/", async (req, res, next) => { + try { + const isValid = checkIsContactValid(req.body); + if (!isValid) { + throw new Error("Contactul introdus nu are toate campurile necesare."); + } -router.put('/:contactId', async (req, res, next) => { - res.json({ message: 'template message' }) -}) + const contact = req.body; + await ContactsController.addContact(contact); + res + .status(201) + .json({ message: `Contactul ${contact.name} a fost adaugat cu succes.` }); + } catch (error) { + respondWithError(res, error); + } +}); -module.exports = router +/* DELETE localhost:3000/api/contacts/:id */ +router.delete("/:id", async (req, res, next) => { + try { + await ContactsController.deleteContact(req.params.id); + + res + .status(STATUS_CODES.deleted) + .json({ message: "Contactul a fost sters cu succes" }); + } catch (error) { + respondWithError(res, error); + } +}); + +/* PUT localhost:3000/api/contacts/:id */ +router.put("/:id", async (req, res, next) => { + try { + const { id } = req.params; + const { name, email, phone, favorite } = req.body; + + // Verifică dacă toate câmpurile necesare există + if (!name || !email || !phone || favorite === undefined) { + return res.status(400).json({ message: "missing required fields" }); + } + + const updatedContact = await ContactsController.updateContact(id, { name, email, phone, favorite }); + if (!updatedContact) { + return res.status(404).json({ message: "Not found" }); + } + + res.status(200).json({ message: "Contact updated successfully", data: updatedContact }); + } catch (error) { + console.error(error); + res.status(500).json({ message: "Internal server error" }); + } +}); + + +/* PATCH localhost:3000/api/contacts/:id */ +router.patch("/:id/favorite", async (req, res, next) => { + try { + const { id } = req.params; + const { favorite } = req.body; + + if (favorite === undefined) { + return res.status(400).json({ message: "missing field favorite" }); + } + + const updatedContact = await ContactsController.updateStatusContact(id, { favorite }); + if (!updatedContact) { + return res.status(404).json({ message: "Not found" }); + } + + res.status(200).json({ message: "Contact updated successfully", data: updatedContact }); + } catch (error) { + console.error(error); + res.status(500).json({ message: "Internal server error" }); + } +}); + + + +export default router; + +function checkIsContactValid(contact) { + if (!contact?.name || !contact?.email || !contact?.phone) { + return false; + } + + return true; +} + +function respondWithError(res, error) { + console.error(error); + res.status(STATUS_CODES.error).json({ message: `${error}` }); +} \ No newline at end of file diff --git a/server.js b/server.js index fc4e4c6bb3a..ceedb898532 100644 --- a/server.js +++ b/server.js @@ -1,4 +1,4 @@ -const app = require("./app"); +import app from "./app.js"; app.listen(3000, () => { console.log("Server is running. Use our API on port: 3000"); diff --git a/utils/connectToDb.js b/utils/connectToDb.js new file mode 100644 index 00000000000..e602ba615db --- /dev/null +++ b/utils/connectToDb.js @@ -0,0 +1,17 @@ +import mongoose from "mongoose"; +import dotenv from "dotenv"; + +dotenv.config(); // Încărcăm variabilele de mediu din fișierul .env + +async function connectToDb() { + try { + await mongoose.connect(process.env.MONGO_URI); + console.log("Database connection successful"); + } catch (error) { + console.error(error); + process.exit(1); + } +} + + +export default connectToDb;