From 5885504c18a13de6dd8d42d39e1d3e7157bdf622 Mon Sep 17 00:00:00 2001 From: Remi R Date: Wed, 15 Nov 2023 10:10:27 +0100 Subject: [PATCH 1/4] feat: add connection to database (not working yet. Due to database parameters ?) --- API-Project/package-lock.json | 187 ++++++++++++++++++ API-Project/package.json | 2 + .../src/controllers/ingredients.controller.ts | 15 +- API-Project/src/database/connection.ts | 8 + API-Project/src/server.ts | 2 +- API-Project/src/types/ingredients.ts | 7 +- API-Project/src/types/recipes.ts | 6 +- 7 files changed, 214 insertions(+), 13 deletions(-) create mode 100644 API-Project/src/database/connection.ts diff --git a/API-Project/package-lock.json b/API-Project/package-lock.json index 2aac7c4..5367fb0 100644 --- a/API-Project/package-lock.json +++ b/API-Project/package-lock.json @@ -14,6 +14,8 @@ "express": "^4.18.2", "morgan": "^1.10.0", "nodemon": "^3.0.1", + "pg": "^8.11.3", + "pg-promise": "^11.5.4", "ts-node": "^10.9.1", "tsup": "^7.2.0", "typescript": "^5.2.2" @@ -620,6 +622,14 @@ "node": ">=8" } }, + "node_modules/assert-options": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/assert-options/-/assert-options-0.8.1.tgz", + "integrity": "sha512-5lNGRB5g5i2bGIzb+J1QQE1iKU/WEMVBReFIc5pPDWjcPj23otPL0eI6PB2v7QPi0qU6Mhym5D3y0ZiSIOf3GA==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -692,6 +702,14 @@ "node": ">=8" } }, + "node_modules/buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", + "engines": { + "node": ">=4" + } + }, "node_modules/bundle-require": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-4.0.2.tgz", @@ -1683,6 +1701,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -1720,6 +1743,111 @@ "node": ">=8" } }, + "node_modules/pg": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", + "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", + "dependencies": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.6.2", + "pg-pool": "^3.6.1", + "pg-protocol": "^1.6.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + }, + "engines": { + "node": ">= 8.0.0" + }, + "optionalDependencies": { + "pg-cloudflare": "^1.1.1" + }, + "peerDependencies": { + "pg-native": ">=3.0.1" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + } + }, + "node_modules/pg-cloudflare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "optional": true + }, + "node_modules/pg-connection-string": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-minify": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-1.6.3.tgz", + "integrity": "sha512-NoSsPqXxbkD8RIe+peQCqiea4QzXgosdTKY8p7PsbbGsh2F8TifDj/vJxfuR8qJwNYrijdSs7uf0tAe6WOyCsQ==", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/pg-pool": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", + "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", + "peerDependencies": { + "pg": ">=8.0" + } + }, + "node_modules/pg-promise": { + "version": "11.5.4", + "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-11.5.4.tgz", + "integrity": "sha512-esYSkDt2h6NQOkfotGAm1Ld5OjoITJLpB88Z1PIlcAU/RQ0XQE2PxW0bLJEOMHPGV5iaRnj1Y7ARznXbgN4FNw==", + "dependencies": { + "assert-options": "0.8.1", + "pg": "8.11.3", + "pg-minify": "1.6.3", + "spex": "3.3.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", + "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pgpass": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", + "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "dependencies": { + "split2": "^4.1.0" + } + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -1767,6 +1895,41 @@ } } }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -2078,6 +2241,22 @@ "node": ">= 8" } }, + "node_modules/spex": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/spex/-/spex-3.3.0.tgz", + "integrity": "sha512-VNiXjFp6R4ldPbVRYbpxlD35yRHceecVXlct1J4/X80KuuPnW2AXMq3sGwhnJOhKkUsOxAT6nRGfGE5pocVw5w==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -2400,6 +2579,14 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/API-Project/package.json b/API-Project/package.json index 6460bb0..cdb41d9 100644 --- a/API-Project/package.json +++ b/API-Project/package.json @@ -16,6 +16,8 @@ "express": "^4.18.2", "morgan": "^1.10.0", "nodemon": "^3.0.1", + "pg": "^8.11.3", + "pg-promise": "^11.5.4", "ts-node": "^10.9.1", "tsup": "^7.2.0", "typescript": "^5.2.2" diff --git a/API-Project/src/controllers/ingredients.controller.ts b/API-Project/src/controllers/ingredients.controller.ts index a466374..91c81b6 100644 --- a/API-Project/src/controllers/ingredients.controller.ts +++ b/API-Project/src/controllers/ingredients.controller.ts @@ -1,14 +1,23 @@ import { Request, Response, NextFunction } from "express"; import { Router } from "express"; import { Exceptions } from "../utils/exception"; +import { IIngredient } from "../types/ingredients"; +import { pool } from "../database/connection"; +import { queryResult } from "pg-promise"; const IngredientsController = Router() /** To get all ingredients */ IngredientsController.get('/', (req, res) => { - res.status(200) - res.send("Liste des ingredients"); + pool.query('SELECT * FROM Ingredients ORDER BY id', (error: Error, results: queryResult) => { + if (error) { + throw(error) + } + res.status(200); + res.send("Liste des ingredients").json(results); + }) + return res; }) @@ -17,7 +26,7 @@ IngredientsController.get('/:id', (req, res) => { const id = Number(req.params.id); if (!Number.isInteger(id)) { - throw new Exceptions.BadRequestException('id invalid !') + throw new Exceptions.BadRequestException('id invalid !'); } res.send(`Searching for ingredient with id = ${id}...`); diff --git a/API-Project/src/database/connection.ts b/API-Project/src/database/connection.ts new file mode 100644 index 0000000..5f5795e --- /dev/null +++ b/API-Project/src/database/connection.ts @@ -0,0 +1,8 @@ +const Pool = require('pg').Pool +export const pool = new Pool({ + user: 'rgregnault', + host: 'localhost', + database: 'leftovers', + password: 'Cl@ssicP@ssw0rd', + port: 5432, +}) \ No newline at end of file diff --git a/API-Project/src/server.ts b/API-Project/src/server.ts index 6823ff0..71d8c43 100644 --- a/API-Project/src/server.ts +++ b/API-Project/src/server.ts @@ -1,5 +1,5 @@ import express from "express"; -import { IngredientsController } from "./controllers/ingredients.controller" +import { IngredientsController } from "./controllers/ingredients.controller"; import { RecipesController } from "./controllers/recipes.controller"; const app = express(); diff --git a/API-Project/src/types/ingredients.ts b/API-Project/src/types/ingredients.ts index d1cac99..6caa43b 100644 --- a/API-Project/src/types/ingredients.ts +++ b/API-Project/src/types/ingredients.ts @@ -1,9 +1,4 @@ -export class Ingredient { +export interface IIngredient { readonly id: number; readonly name: string; - - constructor(init_id: number, init_name: string) { - this.id = init_id; - this.name = init_name; - } } \ No newline at end of file diff --git a/API-Project/src/types/recipes.ts b/API-Project/src/types/recipes.ts index 5296704..3f93c4b 100644 --- a/API-Project/src/types/recipes.ts +++ b/API-Project/src/types/recipes.ts @@ -1,10 +1,10 @@ -import type { Ingredient } from "./ingredients" +import type { IIngredient } from "./ingredients" -export interface Recipe { +export interface IRecipe { id: number, name: string, description: string, time_to_cook: number, - ingredients: Ingredient[], + ingredients: IIngredient[], steps: string[] } \ No newline at end of file -- 2.36.3 From 337fd3ce96cba39d47f3a30d5c7db16214cd45af Mon Sep 17 00:00:00 2001 From: Remi R Date: Wed, 15 Nov 2023 11:20:49 +0100 Subject: [PATCH 2/4] feat: searching for one ingredient in local db is working, searching for all ingredient in local db is working --- API-Project/package-lock.json | 125 +++++++++++++----- API-Project/package.json | 4 +- .../src/controllers/ingredients.controller.ts | 22 ++- API-Project/src/database/connection.ts | 2 +- 4 files changed, 110 insertions(+), 43 deletions(-) diff --git a/API-Project/package-lock.json b/API-Project/package-lock.json index 5367fb0..4168255 100644 --- a/API-Project/package-lock.json +++ b/API-Project/package-lock.json @@ -15,10 +15,12 @@ "morgan": "^1.10.0", "nodemon": "^3.0.1", "pg": "^8.11.3", - "pg-promise": "^11.5.4", "ts-node": "^10.9.1", "tsup": "^7.2.0", "typescript": "^5.2.2" + }, + "devDependencies": { + "@types/pg": "^8.10.9" } }, "node_modules/@cspotcode/source-map-support": { @@ -522,6 +524,74 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/pg": { + "version": "8.10.9", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.10.9.tgz", + "integrity": "sha512-UksbANNE/f8w0wOMxVKKIrLCbEMV+oM1uKejmwXr39olg4xqcfBDbXxObJAt6XxHbDa4XTKOlUEcEltXDX+XLQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^4.0.1" + } + }, + "node_modules/@types/pg/node_modules/pg-types": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-4.0.1.tgz", + "integrity": "sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==", + "dev": true, + "dependencies": { + "pg-int8": "1.0.1", + "pg-numeric": "1.0.2", + "postgres-array": "~3.0.1", + "postgres-bytea": "~3.0.0", + "postgres-date": "~2.0.1", + "postgres-interval": "^3.0.0", + "postgres-range": "^1.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/pg/node_modules/postgres-array": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-3.0.2.tgz", + "integrity": "sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@types/pg/node_modules/postgres-bytea": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-3.0.0.tgz", + "integrity": "sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==", + "dev": true, + "dependencies": { + "obuf": "~1.1.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/pg/node_modules/postgres-date": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-2.0.1.tgz", + "integrity": "sha512-YtMKdsDt5Ojv1wQRvUhnyDJNSr2dGIC96mQVKz7xufp07nfuFONzdaowrMHjlAzY6GDLd4f+LUHHAAM1h4MdUw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@types/pg/node_modules/postgres-interval": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-3.0.0.tgz", + "integrity": "sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/@types/qs": { "version": "6.9.10", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz", @@ -622,14 +692,6 @@ "node": ">=8" } }, - "node_modules/assert-options": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/assert-options/-/assert-options-0.8.1.tgz", - "integrity": "sha512-5lNGRB5g5i2bGIzb+J1QQE1iKU/WEMVBReFIc5pPDWjcPj23otPL0eI6PB2v7QPi0qU6Mhym5D3y0ZiSIOf3GA==", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1660,6 +1722,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -1790,12 +1858,13 @@ "node": ">=4.0.0" } }, - "node_modules/pg-minify": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-1.6.3.tgz", - "integrity": "sha512-NoSsPqXxbkD8RIe+peQCqiea4QzXgosdTKY8p7PsbbGsh2F8TifDj/vJxfuR8qJwNYrijdSs7uf0tAe6WOyCsQ==", + "node_modules/pg-numeric": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pg-numeric/-/pg-numeric-1.0.2.tgz", + "integrity": "sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==", + "dev": true, "engines": { - "node": ">=12.0.0" + "node": ">=4" } }, "node_modules/pg-pool": { @@ -1806,20 +1875,6 @@ "pg": ">=8.0" } }, - "node_modules/pg-promise": { - "version": "11.5.4", - "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-11.5.4.tgz", - "integrity": "sha512-esYSkDt2h6NQOkfotGAm1Ld5OjoITJLpB88Z1PIlcAU/RQ0XQE2PxW0bLJEOMHPGV5iaRnj1Y7ARznXbgN4FNw==", - "dependencies": { - "assert-options": "0.8.1", - "pg": "8.11.3", - "pg-minify": "1.6.3", - "spex": "3.3.0" - }, - "engines": { - "node": ">=14.0" - } - }, "node_modules/pg-protocol": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", @@ -1930,6 +1985,12 @@ "node": ">=0.10.0" } }, + "node_modules/postgres-range": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/postgres-range/-/postgres-range-1.1.3.tgz", + "integrity": "sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==", + "dev": true + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -2241,14 +2302,6 @@ "node": ">= 8" } }, - "node_modules/spex": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/spex/-/spex-3.3.0.tgz", - "integrity": "sha512-VNiXjFp6R4ldPbVRYbpxlD35yRHceecVXlct1J4/X80KuuPnW2AXMq3sGwhnJOhKkUsOxAT6nRGfGE5pocVw5w==", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/split2": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", diff --git a/API-Project/package.json b/API-Project/package.json index cdb41d9..cf98969 100644 --- a/API-Project/package.json +++ b/API-Project/package.json @@ -17,9 +17,11 @@ "morgan": "^1.10.0", "nodemon": "^3.0.1", "pg": "^8.11.3", - "pg-promise": "^11.5.4", "ts-node": "^10.9.1", "tsup": "^7.2.0", "typescript": "^5.2.2" + }, + "devDependencies": { + "@types/pg": "^8.10.9" } } diff --git a/API-Project/src/controllers/ingredients.controller.ts b/API-Project/src/controllers/ingredients.controller.ts index 91c81b6..12d2dab 100644 --- a/API-Project/src/controllers/ingredients.controller.ts +++ b/API-Project/src/controllers/ingredients.controller.ts @@ -3,19 +3,20 @@ import { Router } from "express"; import { Exceptions } from "../utils/exception"; import { IIngredient } from "../types/ingredients"; import { pool } from "../database/connection"; -import { queryResult } from "pg-promise"; +import { QueryResult } from "pg"; const IngredientsController = Router() /** To get all ingredients */ IngredientsController.get('/', (req, res) => { - pool.query('SELECT * FROM Ingredients ORDER BY id', (error: Error, results: queryResult) => { + pool.query({text:'SELECT * FROM Ingredients ORDER BY id'}, (error: Error, results: QueryResult) => { if (error) { throw(error) } + res.status(200); - res.send("Liste des ingredients").json(results); + res.json(results.rows); }) return res; @@ -29,8 +30,19 @@ IngredientsController.get('/:id', (req, res) => { throw new Exceptions.BadRequestException('id invalid !'); } - res.send(`Searching for ingredient with id = ${id}...`); - res.status(200); + pool.query({text:'SELECT * FROM Ingredients WHERE id =$1', + values: [id]}, (error: Error, results: QueryResult) => { + if (error) { + throw(error) + } + + if (results.rowCount == 0) { + throw new Exceptions.NotFoundException('no ingredient with this id'); + } + + res.status(200) + res.json(results.rows) + }) return res; }) diff --git a/API-Project/src/database/connection.ts b/API-Project/src/database/connection.ts index 5f5795e..23bc6cf 100644 --- a/API-Project/src/database/connection.ts +++ b/API-Project/src/database/connection.ts @@ -3,6 +3,6 @@ export const pool = new Pool({ user: 'rgregnault', host: 'localhost', database: 'leftovers', - password: 'Cl@ssicP@ssw0rd', + password: 'motdepasse', port: 5432, }) \ No newline at end of file -- 2.36.3 From df10669f3e6fa73a8a248eaac038a2d48b618513 Mon Sep 17 00:00:00 2001 From: Remi R Date: Wed, 15 Nov 2023 14:30:46 +0100 Subject: [PATCH 3/4] update: ingredients controller send an array of ingredient instead of pure json --- .../src/controllers/ingredients.controller.ts | 17 ++++++++++------- API-Project/src/types/ingredients.ts | 10 ++++++++++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/API-Project/src/controllers/ingredients.controller.ts b/API-Project/src/controllers/ingredients.controller.ts index 12d2dab..0f0a5f5 100644 --- a/API-Project/src/controllers/ingredients.controller.ts +++ b/API-Project/src/controllers/ingredients.controller.ts @@ -1,24 +1,27 @@ import { Request, Response, NextFunction } from "express"; import { Router } from "express"; import { Exceptions } from "../utils/exception"; -import { IIngredient } from "../types/ingredients"; +import { IIngredient, Ingredient } from "../types/ingredients"; import { pool } from "../database/connection"; -import { QueryResult } from "pg"; +import { Query, QueryResult } from "pg"; const IngredientsController = Router() /** To get all ingredients */ IngredientsController.get('/', (req, res) => { + let ingredients:Ingredient[] = [] pool.query({text:'SELECT * FROM Ingredients ORDER BY id'}, (error: Error, results: QueryResult) => { if (error) { - throw(error) + throw(error); + } + for (let key in results.rows) { + let ingredient:Ingredient = new Ingredient(Number(results.rows[key].id), results.rows[key].name); + ingredients.push(ingredient); } - res.status(200); - res.json(results.rows); + res.json(ingredients); }) - return res; }) @@ -39,7 +42,7 @@ IngredientsController.get('/:id', (req, res) => { if (results.rowCount == 0) { throw new Exceptions.NotFoundException('no ingredient with this id'); } - + res.status(200) res.json(results.rows) }) diff --git a/API-Project/src/types/ingredients.ts b/API-Project/src/types/ingredients.ts index 6caa43b..9e696d3 100644 --- a/API-Project/src/types/ingredients.ts +++ b/API-Project/src/types/ingredients.ts @@ -1,4 +1,14 @@ export interface IIngredient { readonly id: number; readonly name: string; +} + +export class Ingredient implements IIngredient { + id: number; + name: string; + + constructor (id: number, name: string) { + this.id = id + this.name = name + } } \ No newline at end of file -- 2.36.3 From acff49b692d6fabb8bb2a3bf92e467a29f31edb6 Mon Sep 17 00:00:00 2001 From: Remi R Date: Thu, 16 Nov 2023 10:11:51 +0100 Subject: [PATCH 4/4] feat: divide old ingredients controller into new ingredient controller and ingredient gateway --- .../src/controllers/ingredients.controller.ts | 54 +++++++++---------- .../src/controllers/recipes.controller.ts | 25 ++++++++- API-Project/src/database/connection.ts | 28 +++++++++- .../src/gateways/ingredients.gateway.ts | 45 ++++++++++++++++ API-Project/src/types/recipes.ts | 34 ++++++++++-- 5 files changed, 151 insertions(+), 35 deletions(-) create mode 100644 API-Project/src/gateways/ingredients.gateway.ts diff --git a/API-Project/src/controllers/ingredients.controller.ts b/API-Project/src/controllers/ingredients.controller.ts index 0f0a5f5..16ea131 100644 --- a/API-Project/src/controllers/ingredients.controller.ts +++ b/API-Project/src/controllers/ingredients.controller.ts @@ -4,50 +4,48 @@ import { Exceptions } from "../utils/exception"; import { IIngredient, Ingredient } from "../types/ingredients"; import { pool } from "../database/connection"; import { Query, QueryResult } from "pg"; +import { IngredientsGateway } from "../gateways/ingredients.gateway"; const IngredientsController = Router() +const ingredient_gw = new IngredientsGateway() + /** To get all ingredients */ -IngredientsController.get('/', (req, res) => { - let ingredients:Ingredient[] = [] - pool.query({text:'SELECT * FROM Ingredients ORDER BY id'}, (error: Error, results: QueryResult) => { - if (error) { - throw(error); - } - for (let key in results.rows) { - let ingredient:Ingredient = new Ingredient(Number(results.rows[key].id), results.rows[key].name); - ingredients.push(ingredient); - } - res.status(200); - res.json(ingredients); - }) - return res; +IngredientsController.get('/', async (req, res) => { + try { + const ingredients = await ingredient_gw.getAll() + + res.status(200).json(ingredients) + } catch (error) { + const error_error = error as Error + res.status(500).send(error_error.message) + } }) /** To get one ingredient by id */ -IngredientsController.get('/:id', (req, res) => { +IngredientsController.get('/:id', async (req, res) => { const id = Number(req.params.id); if (!Number.isInteger(id)) { throw new Exceptions.BadRequestException('id invalid !'); } - pool.query({text:'SELECT * FROM Ingredients WHERE id =$1', - values: [id]}, (error: Error, results: QueryResult) => { - if (error) { - throw(error) - } - - if (results.rowCount == 0) { - throw new Exceptions.NotFoundException('no ingredient with this id'); - } + try { + const ingredient = await ingredient_gw.findOneById(id) - res.status(200) - res.json(results.rows) - }) + if (ingredient == null) { + res.status(404).send('not found') + } + else { + const ingredient_ingredient = ingredient as Ingredient - return res; + res.status(200).json(ingredient) + } + } catch (error) { + const error_error = error as Error + res.status(500).send(error_error.message) + } }) export { IngredientsController } \ No newline at end of file diff --git a/API-Project/src/controllers/recipes.controller.ts b/API-Project/src/controllers/recipes.controller.ts index 2d89476..1dccdc8 100644 --- a/API-Project/src/controllers/recipes.controller.ts +++ b/API-Project/src/controllers/recipes.controller.ts @@ -1,11 +1,32 @@ import { Request, Response, NextFunction } from "express"; import { Router } from "express"; +import { pool } from "../database/connection"; +import { Query, QueryResult } from "pg"; +import { IRecipe, Recipe } from "../types/recipes"; +import { IngredientsController } from "./ingredients.controller"; +import { IIngredient } from "../types/ingredients"; const RecipesController = Router() -RecipesController.get('/', (req, res) => { - res.send("Liste des recettes"); +RecipesController.get('/', async (req, res) => { + let recipes:IRecipe[] = [] + await pool.query('SELECT * FROM Recipe ORDER BY id', async (error: Error, result: QueryResult) => { + if (error) { + throw error; + } + + for (let key in result.rows) { + const current = result.rows[key] + let recipe = new Recipe(current.id, current.name, current.description, current.time_to_cook); + const ingr_ids = current.ingredients + for (let ingr_id in ingr_ids) { + + } + } + + res.json(result.rows) + }) return res; }) diff --git a/API-Project/src/database/connection.ts b/API-Project/src/database/connection.ts index 23bc6cf..fe3cb39 100644 --- a/API-Project/src/database/connection.ts +++ b/API-Project/src/database/connection.ts @@ -1,8 +1,34 @@ +import { Client } from "pg" + const Pool = require('pg').Pool + export const pool = new Pool({ user: 'rgregnault', host: 'localhost', database: 'leftovers', password: 'motdepasse', port: 5432, -}) \ No newline at end of file +}) + + +export class Connection { + public client:Client + clientIsConnected:boolean = false + + constructor() { + this.client = new Client({ + user: 'rgregnault', + host: 'localhost', + database: 'leftovers', + password: 'motdepasse', + port: 5432, + }) + } + + public async connect() { + if (!this.clientIsConnected) { + await this.client.connect() + this.clientIsConnected = true + } + } +} \ No newline at end of file diff --git a/API-Project/src/gateways/ingredients.gateway.ts b/API-Project/src/gateways/ingredients.gateway.ts new file mode 100644 index 0000000..dca6feb --- /dev/null +++ b/API-Project/src/gateways/ingredients.gateway.ts @@ -0,0 +1,45 @@ +import { QueryResult } from "pg"; +import { Ingredient } from "../types/ingredients"; +import { Connection } from "../database/connection" + +export class IngredientsGateway { + connection:Connection + + constructor() { + this.connection = new Connection() + } + + async getAll() : Promise { + this.connection.connect() + + const res = await this.connection.client.query('SELECT * FROM Ingredients ORDER BY id') + + let ingredients:Ingredient[] = [] + + for (let key in res.rows) { + let ingredient:Ingredient = new Ingredient(Number(res.rows[key].id), res.rows[key].name); + ingredients.push(ingredient); + } + + return ingredients + } + + async findOneById(id: number) : Promise { + this.connection.connect() + + const query = { + text: 'SELECT * FROM Ingredients WHERE id =$1', + values: [id], + } + + const res = await this.connection.client.query(query) + + if (res.rowCount != 1) { + return null + } + + const ingredient = new Ingredient(Number(res.rows[0].id), String(res.rows[0].name)) + + return ingredient + } +} \ No newline at end of file diff --git a/API-Project/src/types/recipes.ts b/API-Project/src/types/recipes.ts index 3f93c4b..be9cfa8 100644 --- a/API-Project/src/types/recipes.ts +++ b/API-Project/src/types/recipes.ts @@ -1,10 +1,36 @@ import type { IIngredient } from "./ingredients" export interface IRecipe { - id: number, - name: string, - description: string, - time_to_cook: number, + readonly id: number, + readonly name: string, + readonly description: string, + readonly time_to_cook: number, ingredients: IIngredient[], steps: string[] +} + +export class Recipe implements IRecipe { + id: number + name: string + description: string + time_to_cook: number + ingredients: IIngredient[] + steps: string[] + + constructor(id: number, name: string, description: string, time_to_cook: number) { + this.id = id + this.name = name + this.description = description + this.time_to_cook = time_to_cook + this.ingredients = [] + this.steps = [] + } + + addStep(newStep: string) { + this.steps.push(newStep) + } + + addIngredient(newIngredient: IIngredient) { + this.ingredients.push(newIngredient) + } } \ No newline at end of file -- 2.36.3