From 09a949092c59856962e4a7d132bc5a5e76fe5e55 Mon Sep 17 00:00:00 2001 From: ertopogo Date: Sun, 18 Jan 2026 20:32:59 +0100 Subject: Initial commit: Medusa Backend + storefront + config --- backend/Dockerfile | 21 ++++++++++ backend/index.js | 45 +++++++++++++++++++++ backend/medusa-config.js | 103 +++++++++++++++++++++++++++++++++++++++++++++++ backend/package.json | 59 +++++++++++++++++++++++++++ backend/tsconfig.json | 25 ++++++++++++ 5 files changed, 253 insertions(+) create mode 100644 backend/Dockerfile create mode 100644 backend/index.js create mode 100644 backend/medusa-config.js create mode 100644 backend/package.json create mode 100644 backend/tsconfig.json (limited to 'backend') diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..6775ba5 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,21 @@ +FROM node:18-alpine + +WORKDIR /app/medusa + +COPY package.json . +COPY yarn.lock* ./ +COPY package-lock.json* ./ + +RUN npm install + +COPY . . + +# Build the project (if using TypeScript) +RUN npm run build + +# Expose port +EXPOSE 9000 + +# Start command +CMD ["npm", "run", "start"] + diff --git a/backend/index.js b/backend/index.js new file mode 100644 index 0000000..ad245ba --- /dev/null +++ b/backend/index.js @@ -0,0 +1,45 @@ +const express = require("express"); +const { GracefulShutdownServer } = require("medusa-core-utils"); + +const loaders = require("@medusajs/medusa/dist/loaders/index").default; + +(async () => { + async function start() { + const app = express(); + const directory = process.cwd(); + + try { + const { container, dbConnection } = await loaders({ + directory, + expressApp: app, + }); + + const configModule = container.resolve("configModule"); + const port = process.env.PORT ?? configModule.projectConfig.port ?? 9000; + + const server = GracefulShutdownServer.create( + app.listen(port, (err) => { + if (err) { + return; + } + console.log(`Server is ready on port: ${port}`); + }) + ); + + // Handle graceful shutdown + const shutdown = async () => { + await server.shutdown(); + await dbConnection.close(); + }; + + process.on("SIGTERM", shutdown); + process.on("SIGINT", shutdown); + } catch (err) { + console.error("Error starting server", err); + process.exit(1); + } + } + + await start(); +})(); + diff --git a/backend/medusa-config.js b/backend/medusa-config.js new file mode 100644 index 0000000..739a553 --- /dev/null +++ b/backend/medusa-config.js @@ -0,0 +1,103 @@ +const dotenv = require("dotenv"); + +let ENV_FILE_NAME = ""; +switch (process.env.NODE_ENV) { + case "production": + ENV_FILE_NAME = ".env.production"; + break; + case "staging": + ENV_FILE_NAME = ".env.staging"; + break; + case "test": + ENV_FILE_NAME = ".env.test"; + break; + case "development": + default: + ENV_FILE_NAME = ".env"; + break; +} + +try { + dotenv.config({ path: process.cwd() + "/" + ENV_FILE_NAME }); +} catch (e) {} + +// CORS when consuming Medusa from admin +const ADMIN_CORS = + process.env.ADMIN_CORS || "http://localhost:7000,http://localhost:7001"; + +// CORS to avoid issues when consuming Medusa from a client +const STORE_CORS = process.env.STORE_CORS || "http://localhost:8000"; + +const DATABASE_URL = + process.env.DATABASE_URL || "postgres://localhost/medusa-store"; + +const REDIS_URL = process.env.REDIS_URL || "redis://localhost:6379"; + +const plugins = [ + `medusa-fulfillment-manual`, + `medusa-payment-manual`, + { + resolve: `@medusajs/file-local`, + options: { + upload_dir: "uploads", + }, + }, + { + resolve: "@medusajs/admin", + /** @type {import('@medusajs/admin').PluginOptions} */ + options: { + autoRebuild: true, + develop: { + open: false, + }, + }, + }, + // Example for Stripe (uncomment and configure in .env) + // { + // resolve: `medusa-payment-stripe`, + // options: { + // api_key: process.env.STRIPE_API_KEY, + // webhook_secret: process.env.STRIPE_WEBHOOK_SECRET, + // }, + // }, +]; + +const modules = { + /* + * Enable the Redis event bus to sync events + */ + eventBus: { + resolve: "@medusajs/event-bus-redis", + options: { + redisUrl: REDIS_URL + } + }, + /* + * Enable Redis cache + */ + cacheService: { + resolve: "@medusajs/cache-redis", + options: { + redisUrl: REDIS_URL + } + }, +}; + +/** @type {import('@medusajs/medusa').ConfigModule["projectConfig"]} */ +const projectConfig = { + jwtSecret: process.env.JWT_SECRET, + cookieSecret: process.env.COOKIE_SECRET, + store_cors: STORE_CORS, + database_url: DATABASE_URL, + admin_cors: ADMIN_CORS, + // Uncomment the following lines to enable REDIS + redis_url: REDIS_URL +}; + +/** @type {import('@medusajs/medusa').ConfigModule} */ +module.exports = { + projectConfig, + plugins, + modules, +}; + diff --git a/backend/package.json b/backend/package.json new file mode 100644 index 0000000..5a4c902 --- /dev/null +++ b/backend/package.json @@ -0,0 +1,59 @@ +{ + "name": "medusa-backend", + "version": "0.0.1", + "description": "A Medusa e-commerce backend", + "author": "Lucien-sens-bon", + "license": "MIT", + "keywords": [ + "sqlite", + "postgres", + "typescript", + "ecommerce", + "headless", + "medusa" + ], + "scripts": { + "clean": "cross-env ./node_modules/.bin/rimraf dist", + "build": "cross-env ./node_modules/.bin/rimraf dist && tsc -p tsconfig.json", + "start": "cross-env npm run build && medusa start", + "start:custom": "cross-env npm run build && node --preserve-symlinks index.js", + "dev": "cross-env npm run build && medusa develop", + "seed": "medusa seed -f ./data/seed.json", + "install:cli": "npm install -g @medusajs/medusa-cli" + }, + "dependencies": { + "@medusajs/medusa": "^1.20.0", + "@medusajs/medusa-cli": "^1.3.21", + "@medusajs/cache-inmemory": "^1.8.9", + "@medusajs/cache-redis": "^1.8.9", + "@medusajs/event-bus-local": "^1.9.7", + "@medusajs/event-bus-redis": "^1.8.10", + "@medusajs/file-local": "^1.0.2", + "@medusajs/admin": "^7.1.14", + "body-parser": "^1.19.0", + "cors": "^2.8.5", + "dotenv": "16.3.1", + "express": "^4.17.1", + "medusa-interfaces": "^1.3.7", + "medusa-payment-manual": "^1.0.24", + "medusa-payment-stripe": "^6.0.7", + "typeorm": "^0.3.16", + "typescript": "^4.5.2" + }, + "devDependencies": { + "@types/express": "^4.17.13", + "@types/jest": "^27.4.0", + "@types/node": "^17.0.8", + "babel-preset-medusa-package": "^1.1.19", + "cross-env": "^7.0.3", + "eslint": "^6.8.0", + "jest": "^27.3.1", + "rimraf": "^3.0.2", + "ts-jest": "^27.0.7", + "ts-loader": "^9.2.6" + }, + "engines": { + "node": ">=16" + } +} + diff --git a/backend/tsconfig.json b/backend/tsconfig.json new file mode 100644 index 0000000..725f746 --- /dev/null +++ b/backend/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "module": "commonjs", + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "es2017", + "sourceMap": true, + "outDir": "./dist", + "baseUrl": "./", + "incremental": true, + "skipLibCheck": true + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "node_modules", + "dist", + "test" + ] +} + -- cgit v1.2.3