Ghid complet de instalare și configurare pentru Node.js
Feed-ul generează un obiect JSON cu toate produsele indexate după SKU:
{
"SKU12345": {
"sku": "SKU12345",
"name": "Numele produsului",
"qty": "10",
"price": 150.50,
"sale_price": 120.00,
"last_update_date": "2025-08-08 10:30:00",
"description": "Descrierea completă a produsului...",
"weight": "2.5",
"images": [
{"src": "https://site-ul-vostru.com/wp-content/uploads/image1.jpg"},
{"src": "https://site-ul-vostru.com/wp-content/uploads/image2.jpg"}
],
"permalink": "https://site-ul-vostru.com/product/numele-produsului/",
"categories_tree": [
{
"id": 25,
"name": "Categoria Principală",
"parent": 0,
"image": "https://site-ul-vostru.com/category-image.jpg",
"subcategories": [
{
"id": 30,
"name": "Subcategoria",
"parent": 25,
"image": "https://site-ul-vostru.com/subcategory-image.jpg",
"subcategories": []
}
]
}
],
"breadcrumbs": [
"Categoria Principală > Subcategoria"
],
"brands": [
{
"name": "NUMELE BRANDULUI",
"image": "https://site-ul-vostru.com/brand-logo.jpg"
}
]
}
}
Descarcă pachetul Node.js pentru feed JSON:
După descărcare, extrage fișierele și navighează în director:
cd nodejs-product-feed
npm install
Creează modelul pentru produse (exemplu cu Mongoose):
// models/Product.js
const mongoose = require('mongoose');
const productSchema = new mongoose.Schema({
name: {
type: String,
required: true,
trim: true
},
description: {
type: String,
trim: true
},
price: {
type: Number,
required: true,
min: 0
},
salePrice: {
type: Number,
min: 0
},
sku: {
type: String,
required: true,
unique: true,
trim: true
},
category: {
type: String,
required: true,
trim: true
},
brand: {
type: String,
trim: true
},
subcategories: [{
type: String,
trim: true
}],
imageUrl: {
type: String,
trim: true
},
stockQuantity: {
type: Number,
default: 0,
min: 0
},
isActive: {
type: Boolean,
default: true
},
tags: [String],
attributes: {
type: Map,
of: String
},
weight: {
type: Number,
min: 0
}
}, {
timestamps: true
});
// Index pentru căutări rapide
productSchema.index({ name: 'text', description: 'text' });
productSchema.index({ category: 1 });
productSchema.index({ price: 1 });
productSchema.index({ isActive: 1 });
module.exports = mongoose.model('Product', productSchema);
Creează server-ul principal:
// server.js
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
const helmet = require('helmet');
const compression = require('compression');
const rateLimit = require('express-rate-limit');
require('dotenv').config();
const Product = require('./models/Product');
const app = express();
const PORT = process.env.PORT || 3000;
// Middleware de securitate
app.use(helmet());
app.use(compression());
app.use(cors({
origin: process.env.ALLOWED_ORIGINS?.split(',') || ['http://localhost:3000'],
credentials: true
}));
// Rate limiting
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minute
max: 100, // limit each IP to 100 requests per windowMs
message: {
error: 'Too many requests from this IP, please try again later.'
}
});
app.use('/api/', limiter);
// Middleware pentru parsing JSON
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true }));
// Conexiune la baza de date
mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost:27017/productdb', {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => console.log('Connected to MongoDB'))
.catch(err => console.error('MongoDB connection error:', err));
// Middleware pentru autentificare API (opțional)
const authenticateApiKey = (req, res, next) => {
const apiKey = req.query.api_key || req.headers['x-api-key'];
if (process.env.API_KEY && apiKey !== process.env.API_KEY) {
return res.status(401).json({ error: 'Invalid API key' });
}
next();
};
// Ruta principală pentru feed
app.get('/api/products/feed', authenticateApiKey, async (req, res) => {
try {
const {
limit = 100,
page = 1,
category,
min_price,
max_price,
search,
sort = 'createdAt',
order = 'desc'
} = req.query;
// Construiește query-ul
let query = { isActive: true };
// Filtrare după categorie
if (category) {
query.category = category;
}
// Filtrare după preț
if (min_price || max_price) {
query.price = {};
if (min_price) query.price.$gte = parseFloat(min_price);
if (max_price) query.price.$lte = parseFloat(max_price);
}
// Căutare text
if (search) {
query.$text = { $search: search };
}
// Calculează offset pentru paginare
const offset = (parseInt(page) - 1) * parseInt(limit);
// Sortează
const sortOptions = {};
sortOptions[sort] = order === 'desc' ? -1 : 1;
// Execută query-ul
const products = await Product.find(query)
.sort(sortOptions)
.skip(offset)
.limit(parseInt(limit))
.select('-__v'); // Exclude versiunea mongoose
// Numără totalul pentru paginare
const totalProducts = await Product.countDocuments(query);
// Formatează răspunsul în formatul Mixbox
const feedData = {};
products.forEach(product => {
const sku = product.sku || 'PROD-' + product._id.toString();
feedData[sku] = {
sku: sku,
name: product.name,
qty: product.stockQuantity?.toString() || '0',
price: parseFloat(product.price),
sale_price: product.salePrice || null,
last_update_date: product.updatedAt?.toISOString().slice(0, 19).replace('T', ' ') || new Date().toISOString().slice(0, 19).replace('T', ' '),
description: product.description,
weight: product.weight || null,
images: product.imageUrl ? [{ src: product.imageUrl }] : [],
permalink: `${process.env.BASE_URL || 'https://your-site.com'}/products/${product._id}`,
categories_tree: [{
id: 25,
name: product.category || 'Categoria Principală',
parent: 0,
image: 'https://site-ul-vostru.com/category-image.jpg',
subcategories: product.subcategories || [{
id: 30,
name: 'Subcategoria',
parent: 25,
image: 'https://site-ul-vostru.com/subcategory-image.jpg',
subcategories: []
}]
}],
breadcrumbs: [product.category ? product.category + ' > Subcategoria' : 'Categoria Principală > Subcategoria'],
brands: product.brand ? [{
name: product.brand,
image: 'https://site-ul-vostru.com/brand-logo.jpg'
}] : []
};
});
// Cache headers
res.set({
'Cache-Control': 'public, max-age=300', // Cache 5 minute
'Content-Type': 'application/json'
});
res.json(feedData);
} catch (error) {
console.error('Feed error:', error);
res.status(500).json({
error: 'Internal server error',
message: process.env.NODE_ENV === 'development' ? error.message : undefined
});
}
});
// Endpoint pentru sănătatea aplicației
app.get('/health', (req, res) => {
res.json({
status: 'OK',
timestamp: new Date().toISOString(),
uptime: process.uptime()
});
});
// Middleware pentru erori 404
app.use((req, res) => {
res.status(404).json({ error: 'Endpoint not found' });
});
// Middleware pentru erori generale
app.use((error, req, res, next) => {
console.error('Unhandled error:', error);
res.status(500).json({
error: 'Internal server error',
message: process.env.NODE_ENV === 'development' ? error.message : undefined
});
});
// Începe server-ul
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
console.log(`Feed available at: http://localhost:${PORT}/api/products/feed`);
});
module.exports = app;
Creează fișierul .env:
# Server Configuration
PORT=3000
NODE_ENV=development
# Database
MONGODB_URI=mongodb://localhost:27017/productdb
# Security
API_KEY=your_secret_api_key_here
ALLOWED_ORIGINS=http://localhost:3000,https://yourdomain.com
# Rate Limiting
RATE_LIMIT_WINDOW=15
RATE_LIMIT_MAX_REQUESTS=100
Fișierul package.json pentru dependințe:
{
"name": "nodejs-product-feed",
"version": "1.0.0",
"description": "Node.js Express server for JSON product feed",
"main": "server.js",
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js",
"test": "jest",
"seed": "node scripts/seed.js"
},
"dependencies": {
"express": "^4.18.2",
"mongoose": "^7.5.0",
"cors": "^2.8.5",
"helmet": "^7.0.0",
"compression": "^1.7.4",
"express-rate-limit": "^6.10.0",
"dotenv": "^16.3.1"
},
"devDependencies": {
"nodemon": "^3.0.1",
"jest": "^29.6.4",
"supertest": "^6.3.3"
},
"keywords": ["express", "api", "products", "feed", "json"],
"author": "Mixbox",
"license": "MIT"
}
Pornește server-ul și testează feed-ul:
# Pornește server-ul
npm run dev
# Testează feed-ul de bază
curl "http://localhost:3000/api/products/feed"
# Cu parametri
curl "http://localhost:3000/api/products/feed?limit=10&page=1&category=electronics"
# Cu API key
curl "http://localhost:3000/api/products/feed?api_key=your_api_key"
# Verifică sănătatea
curl "http://localhost:3000/health"
Pentru deployment în producție:
# 1. Instalează doar dependințele de producție
npm ci --only=production
# 2. Configurează variabilele de mediu pentru producție
NODE_ENV=production
MONGODB_URI=mongodb://production-server/productdb
# 3. Pornește server-ul
npm start
Adaugă logging pentru monitorizare:
// Adaugă winston pentru logging avansat
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'logs/error.log', level: 'error' }),
new winston.transports.File({ filename: 'logs/combined.log' }),
],
});
// În middleware-ul pentru feed
logger.info('Feed accessed', {
ip: req.ip,
userAgent: req.get('User-Agent'),
query: req.query,
timestamp: new Date().toISOString()
});