Initial commit

This commit is contained in:
2026-07-27 18:01:07 +02:00
commit 0758b00d54
192 changed files with 45091 additions and 0 deletions

139
apps/api/src/main.ts Normal file
View File

@@ -0,0 +1,139 @@
import express from 'express';
import { ProductsService } from '@org/api/products';
import { ApiResponse, Product, ProductFilter, PaginatedResponse } from '@org/models';
const host = process.env.HOST ?? 'localhost';
const port = process.env.PORT ? Number(process.env.PORT) : 3333;
const app = express();
const productsService = new ProductsService();
// Middleware
app.use(express.json());
// CORS configuration for Angular app
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
if (req.method === 'OPTIONS') {
res.sendStatus(200);
} else {
next();
}
});
app.get('/', (req, res) => {
res.send({ message: 'Hello API' });
});
// Products endpoints
app.get('/api/products', (req, res) => {
try {
const filter: ProductFilter = {};
if (req.query.category) {
filter.category = req.query.category as string;
}
if (req.query.minPrice) {
filter.minPrice = Number(req.query.minPrice);
}
if (req.query.maxPrice) {
filter.maxPrice = Number(req.query.maxPrice);
}
if (req.query.inStock !== undefined) {
filter.inStock = req.query.inStock === 'true';
}
if (req.query.searchTerm) {
filter.searchTerm = req.query.searchTerm as string;
}
const page = req.query.page ? Number(req.query.page) : 1;
const pageSize = req.query.pageSize ? Number(req.query.pageSize) : 12;
const result = productsService.getAllProducts(filter, page, pageSize);
const response: ApiResponse<PaginatedResponse<Product>> = {
data: result,
success: true,
};
res.json(response);
} catch (error) {
const response: ApiResponse<null> = {
data: null,
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
};
res.status(500).json(response);
}
});
app.get('/api/products/:id', (req, res) => {
try {
const product = productsService.getProductById(req.params.id);
if (!product) {
const response: ApiResponse<null> = {
data: null,
success: false,
error: 'Product not found',
};
return res.status(404).json(response);
}
const response: ApiResponse<Product> = {
data: product,
success: true,
};
res.json(response);
} catch (error) {
const response: ApiResponse<null> = {
data: null,
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
};
res.status(500).json(response);
}
});
app.get('/api/products-metadata/categories', (req, res) => {
try {
const categories = productsService.getCategories();
const response: ApiResponse<string[]> = {
data: categories,
success: true,
};
res.json(response);
} catch (error) {
const response: ApiResponse<null> = {
data: null,
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
};
res.status(500).json(response);
}
});
app.get('/api/products-metadata/price-range', (req, res) => {
try {
const priceRange = productsService.getPriceRange();
const response: ApiResponse<{ min: number; max: number }> = {
data: priceRange,
success: true,
};
res.json(response);
} catch (error) {
const response: ApiResponse<null> = {
data: null,
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
};
res.status(500).json(response);
}
});
app.listen(port, host, () => {
console.log(`[ ready ] http://${host}:${port}`);
});