diff --git a/package.json b/package.json index dbdbe4f..24e6ef9 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,8 @@ "private": true, "version": "0.0.0", "scripts": { - "dev": "ENV=DEVELOPMENT nodemon -w src/ -x tsx src/app.ts", - "start": "ENV=PRODUCTION tsx src/app.ts", + "dev": "nodemon -w src/ -x tsx src/app.ts", + "start": "tsx src/app.ts", "lint": "yarn prettier . --write", "kill": "kill -9 $(lsof -t -i :3000)", "build": "tsc" diff --git a/src/app.ts b/src/app.ts index 6d6793d..fe1c5ce 100644 --- a/src/app.ts +++ b/src/app.ts @@ -8,6 +8,7 @@ import bodyParser from "body-parser"; import errorHandler from "./middleware/error-handler"; import authRouter from "./services/auth/auth-router"; +import subscriptionRouter from "./services/subscription/subscription-router"; const app = express(); @@ -20,7 +21,9 @@ app.use("/", morgan("dev")); app.use("/", bodyParser.json()); +// API routes app.use("/auth", authRouter); +app.use("/subscription", subscriptionRouter); app.get("/status", (_, res) => { console.log(StatusCodes.OK); diff --git a/src/config.ts b/src/config.ts index e3a6f9f..ed601c8 100644 --- a/src/config.ts +++ b/src/config.ts @@ -6,6 +6,8 @@ import { getEnv } from "./utilities"; export const Environment = z.enum(["PRODUCTION", "DEVELOPMENT", "TESTING"]); +export const MailingListName = z.enum(["rp_interest"]); + export const Config = { DEFAULT_APP_PORT: 3000, ENV: Environment.parse(getEnv("ENV")), diff --git a/src/database.ts b/src/database.ts index 2e8c4c5..33fa1a2 100644 --- a/src/database.ts +++ b/src/database.ts @@ -1,5 +1,9 @@ import mongoose, { Schema } from "mongoose"; import { RoleInfo, RoleSchema } from "./services/auth/auth-schema"; +import { + SubscriptionValidator, + SubscriptionSchema, +} from "./services/subscription/subscription-schema"; mongoose.set("toObject", { versionKey: false }); @@ -32,4 +36,9 @@ function initializeModel( // Example usage export const Database = { ROLES: initializeModel("roles", RoleSchema, RoleInfo), + SUBSCRIPTION: initializeModel( + "subscription", + SubscriptionSchema, + SubscriptionValidator + ), }; diff --git a/src/services/subscription/subscription-router.ts b/src/services/subscription/subscription-router.ts new file mode 100644 index 0000000..b503fbe --- /dev/null +++ b/src/services/subscription/subscription-router.ts @@ -0,0 +1,23 @@ +import { Router } from "express"; +import { StatusCodes } from "http-status-codes"; +import { SubscriptionValidator } from "./subscription-schema"; +import { Database } from "../../database"; + +const subscriptionRouter = Router(); + +// Create a new subscription +subscriptionRouter.post("/", async (req, res, next) => { + try { + const subscriptionData = SubscriptionValidator.parse(req.body); + await Database.SUBSCRIPTION.findOneAndUpdate( + { mailingList: subscriptionData.mailingList }, + { $push: { subscriptions: subscriptionData.email } }, + { upsert: true, new: true } + ); + return res.status(StatusCodes.CREATED).json(subscriptionData); + } catch (error) { + next(error); + } +}); + +export default subscriptionRouter; diff --git a/src/services/subscription/subscription-schema.ts b/src/services/subscription/subscription-schema.ts new file mode 100644 index 0000000..32579bf --- /dev/null +++ b/src/services/subscription/subscription-schema.ts @@ -0,0 +1,17 @@ +import mongoose from "mongoose"; +import { z } from "zod"; +import { MailingListName } from "../../config"; + +// Zod schema for subscription +const SubscriptionValidator = z.object({ + email: z.string().email(), + mailingList: MailingListName, +}); + +// Mongoose schema for subscription +const SubscriptionSchema = new mongoose.Schema({ + email: { type: String, required: true }, + mailingList: { type: String, required: true }, +}); + +export { SubscriptionValidator, SubscriptionSchema };