From 483ad3292d3885d5b508544457614e4f41062b5e Mon Sep 17 00:00:00 2001
From: nostrdev-com <support@nostrdev.com>
Date: Mon, 31 Mar 2025 16:31:59 +0300
Subject: [PATCH] feat: added spirit model and routes

---
 src/index.ts                     |  4 ++-
 src/models/index.ts              |  1 +
 src/models/spirit.ts             | 29 ++++++++++++++++++++
 src/routes/index.ts              |  1 +
 src/routes/spirits.router.ts     | 46 ++++++++++++++++++++++++++++++++
 src/services/database.service.ts |  5 ++++
 src/types/database.ts            |  3 ++-
 src/types/products.ts            |  2 ++
 src/types/routes.ts              |  3 ++-
 9 files changed, 91 insertions(+), 3 deletions(-)
 create mode 100644 src/models/spirit.ts
 create mode 100644 src/routes/spirits.router.ts

diff --git a/src/index.ts b/src/index.ts
index b4166ab..07fce95 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -6,7 +6,8 @@ import {
   nostrRouter,
   reviewsRouter,
   winesRouter,
-  sakeRouter
+  sakeRouter,
+  spiritsRouter
 } from './routes'
 import { Routes } from './types'
 
@@ -22,6 +23,7 @@ connectToDatabase()
     app.use(Routes.Reviews, reviewsRouter)
     app.use(Routes.Wines, winesRouter)
     app.use(Routes.Sake, sakeRouter)
+    app.use(Routes.Spirits, spiritsRouter)
 
     app.listen(port, () => {
       console.log(`Server started at http://localhost:${port}`)
diff --git a/src/models/index.ts b/src/models/index.ts
index 1a8481d..d8205e6 100644
--- a/src/models/index.ts
+++ b/src/models/index.ts
@@ -3,3 +3,4 @@ export * from './nostrEvent'
 export * from './review'
 export * from './wine'
 export * from './sake'
+export * from './spirit'
diff --git a/src/models/spirit.ts b/src/models/spirit.ts
new file mode 100644
index 0000000..819778b
--- /dev/null
+++ b/src/models/spirit.ts
@@ -0,0 +1,29 @@
+import { ObjectId } from 'mongodb'
+import { SpiritType } from '../types'
+import { Alpha2Code } from 'i18n-iso-countries'
+import { CurrencyCode } from 'currency-codes-ts/dist/types'
+
+export class Spirit {
+  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 name: string, // label
+    public producerId: ObjectId, // product producer
+    public type: SpiritType, // spirit type
+    // TODO: add SpiritVariant type
+    public variant: string, // vodka, rum, liqueur cream, etc
+    public ingredients: string[], // an array of ingredients(flavouring)
+    public alcohol: number, // alcohol percentage
+    public standardDrinks: number, // number representing an amount of standard drinks per bottle
+    public vintage: string, // year, nv (non-vintage) or mv (multi-vintage)
+    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/routes/index.ts b/src/routes/index.ts
index ebf0de0..7bb4301 100644
--- a/src/routes/index.ts
+++ b/src/routes/index.ts
@@ -3,3 +3,4 @@ export * from './nostr.router'
 export * from './reviews.router'
 export * from './wines.router'
 export * from './sake.router'
+export * from './spirits.router'
diff --git a/src/routes/spirits.router.ts b/src/routes/spirits.router.ts
new file mode 100644
index 0000000..6904a61
--- /dev/null
+++ b/src/routes/spirits.router.ts
@@ -0,0 +1,46 @@
+import express, { Request, Response } from 'express'
+import { collections } from '../services/database.service'
+import { Spirit } from '../models'
+
+// Global Config
+export const spiritsRouter = express.Router()
+
+spiritsRouter.use(express.json())
+
+// GET
+spiritsRouter.get('/', async (_req: Request, res: Response) => {
+  try {
+    const spirits = await collections.spirits?.find({}).toArray()
+
+    res.status(200).send(spirits)
+  } catch (error: unknown) {
+    console.error(error)
+
+    if (error instanceof Error) {
+      res.status(500).send(error.message)
+    }
+  }
+})
+
+// POST
+spiritsRouter.post('/', async (req: Request, res: Response) => {
+  try {
+    const spirit = req.body as Spirit
+
+    const result = await collections.spirits?.insertOne(spirit)
+
+    if (result) {
+      res
+        .status(201)
+        .send(`Successfully created a new spirit with id ${result.insertedId}`)
+    } else {
+      res.status(500).send('Failed to create a new spirit.')
+    }
+  } catch (error: unknown) {
+    console.error(error)
+
+    if (error instanceof Error) {
+      res.status(400).send(error.message)
+    }
+  }
+})
diff --git a/src/services/database.service.ts b/src/services/database.service.ts
index af6d89c..4b3aa08 100644
--- a/src/services/database.service.ts
+++ b/src/services/database.service.ts
@@ -9,6 +9,7 @@ export const collections: {
   [DBcollections.Reviews]?: mongoDB.Collection
   [DBcollections.Wines]?: mongoDB.Collection
   [DBcollections.Sake]?: mongoDB.Collection
+  [DBcollections.Spirits]?: mongoDB.Collection
 } = {}
 
 // Initialize Connection
@@ -36,12 +37,16 @@ export async function connectToDatabase() {
   )
   const winesCollection: mongoDB.Collection = db.collection(DBcollections.Wines)
   const sakeCollection: mongoDB.Collection = db.collection(DBcollections.Sake)
+  const spiritsCollection: mongoDB.Collection = db.collection(
+    DBcollections.Spirits
+  )
 
   collections.users = usersCollection
   collections.nostrEvents = nostrEventsCollection
   collections.reviews = reviewsCollection
   collections.wines = winesCollection
   collections.sake = sakeCollection
+  collections.spirits = spiritsCollection
 
   console.log(
     `Successfully connected to database: ${db.databaseName} and collections:
diff --git a/src/types/database.ts b/src/types/database.ts
index e08b3ef..a6a3ec8 100644
--- a/src/types/database.ts
+++ b/src/types/database.ts
@@ -3,5 +3,6 @@ export enum DBcollections {
   NostrEvents = 'nostrEvents',
   Reviews = 'reviews',
   Wines = 'wines',
-  Sake = 'sake'
+  Sake = 'sake',
+  Spirits = 'spirits'
 }
diff --git a/src/types/products.ts b/src/types/products.ts
index 29c3b53..2a6f337 100644
--- a/src/types/products.ts
+++ b/src/types/products.ts
@@ -13,3 +13,5 @@ export type SakeDesignation =
   | 'mirin:new'
   | 'mirin:true'
   | 'mirin:salt'
+
+export type SpiritType = 'white' | 'dark' | 'liqueurs'
diff --git a/src/types/routes.ts b/src/types/routes.ts
index 013d2c0..e942798 100644
--- a/src/types/routes.ts
+++ b/src/types/routes.ts
@@ -3,5 +3,6 @@ export enum Routes {
   NostrEvents = '/nostr',
   Reviews = '/reviews',
   Wines = '/wines',
-  Sake = '/sake'
+  Sake = '/sake',
+  Spirits = '/spirits'
 }
-- 
2.43.0