From 404bf6cfc56011f848b01f334ba6335718bef2b6 Mon Sep 17 00:00:00 2001
From: nostrdev-com <support@nostrdev.com>
Date: Mon, 31 Mar 2025 17:01:21 +0300
Subject: [PATCH] feat: added coffee model and routes

---
 .vscode/settings.json            | 10 ++++++-
 src/index.ts                     |  4 ++-
 src/models/coffee.ts             | 26 ++++++++++++++++++
 src/models/index.ts              |  1 +
 src/routes/coffee.router.ts      | 46 ++++++++++++++++++++++++++++++++
 src/routes/index.ts              |  1 +
 src/services/database.service.ts |  5 ++++
 src/types/database.ts            |  3 ++-
 src/types/products.ts            |  8 ++++++
 src/types/routes.ts              |  3 ++-
 10 files changed, 103 insertions(+), 4 deletions(-)
 create mode 100644 src/models/coffee.ts
 create mode 100644 src/routes/coffee.router.ts

diff --git a/.vscode/settings.json b/.vscode/settings.json
index 9ac967d..20a0eaa 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,3 +1,11 @@
 {
-  "cSpell.words": ["biodynamic", "koji", "Nostr", "npub", "RRP", "screwcap"]
+  "cSpell.words": [
+    "biodynamic",
+    "koji",
+    "Nostr",
+    "npub",
+    "RRP",
+    "screwcap",
+    "sundried"
+  ]
 }
diff --git a/src/index.ts b/src/index.ts
index 07fce95..81c087c 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -7,7 +7,8 @@ import {
   reviewsRouter,
   winesRouter,
   sakeRouter,
-  spiritsRouter
+  spiritsRouter,
+  coffeeRouter
 } from './routes'
 import { Routes } from './types'
 
@@ -24,6 +25,7 @@ connectToDatabase()
     app.use(Routes.Wines, winesRouter)
     app.use(Routes.Sake, sakeRouter)
     app.use(Routes.Spirits, spiritsRouter)
+    app.use(Routes.Coffee, coffeeRouter)
 
     app.listen(port, () => {
       console.log(`Server started at http://localhost:${port}`)
diff --git a/src/models/coffee.ts b/src/models/coffee.ts
new file mode 100644
index 0000000..951517a
--- /dev/null
+++ b/src/models/coffee.ts
@@ -0,0 +1,26 @@
+import { ObjectId } from 'mongodb'
+import { CoffeeProcessingType } from '../types'
+import { Alpha2Code } from 'i18n-iso-countries'
+import { CurrencyCode } from 'currency-codes-ts/dist/types'
+
+export class Coffee {
+  constructor(
+    public productCodeEAN: string, // Article Number (https://en.wikipedia.org/wiki/International_Article_Number)
+    public productCodeUPC: string, // Product Code (https://en.wikipedia.org/wiki/Universal_Product_Code)
+    public productCodeSKU: string, // Stock keeping unit (https://en.wikipedia.org/wiki/Stock_keeping_unit)
+    public country: Alpha2Code, // two-letter country codes defined in ISO 3166-1 (https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)
+    public region: string, // appellation, village, sub-region, vineyard
+    public origin: string, // origin
+    public variety: string, // ?
+    public processingType: CoffeeProcessingType, // processing type
+    public name: string, // label
+    public producerId: ObjectId, // product producer
+    public roast: string, // ?
+    public RRPamount: number, // 20
+    public RRPcurrency: CurrencyCode, // USD
+    public description: string, // detailed description of the product
+    public url?: string, // e.g. producer's website
+    public image?: string, // (optional image URL)cellar.social
+    public id?: ObjectId // database object id
+  ) {}
+}
diff --git a/src/models/index.ts b/src/models/index.ts
index d8205e6..35a5bcb 100644
--- a/src/models/index.ts
+++ b/src/models/index.ts
@@ -4,3 +4,4 @@ export * from './review'
 export * from './wine'
 export * from './sake'
 export * from './spirit'
+export * from './coffee'
diff --git a/src/routes/coffee.router.ts b/src/routes/coffee.router.ts
new file mode 100644
index 0000000..9cfa014
--- /dev/null
+++ b/src/routes/coffee.router.ts
@@ -0,0 +1,46 @@
+import express, { Request, Response } from 'express'
+import { collections } from '../services/database.service'
+import { Coffee } from '../models'
+
+// Global Config
+export const coffeeRouter = express.Router()
+
+coffeeRouter.use(express.json())
+
+// GET
+coffeeRouter.get('/', async (_req: Request, res: Response) => {
+  try {
+    const coffee = await collections.coffee?.find({}).toArray()
+
+    res.status(200).send(coffee)
+  } catch (error: unknown) {
+    console.error(error)
+
+    if (error instanceof Error) {
+      res.status(500).send(error.message)
+    }
+  }
+})
+
+// POST
+coffeeRouter.post('/', async (req: Request, res: Response) => {
+  try {
+    const coffee = req.body as Coffee
+
+    const result = await collections.coffee?.insertOne(coffee)
+
+    if (result) {
+      res
+        .status(201)
+        .send(`Successfully created a new coffee with id ${result.insertedId}`)
+    } else {
+      res.status(500).send('Failed to create a new coffee.')
+    }
+  } catch (error: unknown) {
+    console.error(error)
+
+    if (error instanceof Error) {
+      res.status(400).send(error.message)
+    }
+  }
+})
diff --git a/src/routes/index.ts b/src/routes/index.ts
index 7bb4301..6bd8987 100644
--- a/src/routes/index.ts
+++ b/src/routes/index.ts
@@ -4,3 +4,4 @@ export * from './reviews.router'
 export * from './wines.router'
 export * from './sake.router'
 export * from './spirits.router'
+export * from './coffee.router'
diff --git a/src/services/database.service.ts b/src/services/database.service.ts
index 4b3aa08..bfc1d85 100644
--- a/src/services/database.service.ts
+++ b/src/services/database.service.ts
@@ -10,6 +10,7 @@ export const collections: {
   [DBcollections.Wines]?: mongoDB.Collection
   [DBcollections.Sake]?: mongoDB.Collection
   [DBcollections.Spirits]?: mongoDB.Collection
+  [DBcollections.Coffee]?: mongoDB.Collection
 } = {}
 
 // Initialize Connection
@@ -40,6 +41,9 @@ export async function connectToDatabase() {
   const spiritsCollection: mongoDB.Collection = db.collection(
     DBcollections.Spirits
   )
+  const coffeeCollection: mongoDB.Collection = db.collection(
+    DBcollections.Coffee
+  )
 
   collections.users = usersCollection
   collections.nostrEvents = nostrEventsCollection
@@ -47,6 +51,7 @@ export async function connectToDatabase() {
   collections.wines = winesCollection
   collections.sake = sakeCollection
   collections.spirits = spiritsCollection
+  collections.coffee = coffeeCollection
 
   console.log(
     `Successfully connected to database: ${db.databaseName} and collections:
diff --git a/src/types/database.ts b/src/types/database.ts
index a6a3ec8..5b45370 100644
--- a/src/types/database.ts
+++ b/src/types/database.ts
@@ -4,5 +4,6 @@ export enum DBcollections {
   Reviews = 'reviews',
   Wines = 'wines',
   Sake = 'sake',
-  Spirits = 'spirits'
+  Spirits = 'spirits',
+  Coffee = 'coffee'
 }
diff --git a/src/types/products.ts b/src/types/products.ts
index 2a6f337..5652fe9 100644
--- a/src/types/products.ts
+++ b/src/types/products.ts
@@ -15,3 +15,11 @@ export type SakeDesignation =
   | 'mirin:salt'
 
 export type SpiritType = 'white' | 'dark' | 'liqueurs'
+
+export type CoffeeProcessingType =
+  | 'de-caff'
+  | 'honey'
+  | 'semi-dry'
+  | 'swiss water'
+  | 'sundried'
+  | 'washed'
diff --git a/src/types/routes.ts b/src/types/routes.ts
index e942798..d273518 100644
--- a/src/types/routes.ts
+++ b/src/types/routes.ts
@@ -4,5 +4,6 @@ export enum Routes {
   Reviews = '/reviews',
   Wines = '/wines',
   Sake = '/sake',
-  Spirits = '/spirits'
+  Spirits = '/spirits',
+  Coffee = '/coffee'
 }
-- 
2.43.0