🛣️ Product Routes
Product routes provide pre-configured HTTP endpoints for product management operations in Nodeblocks applications. These routes combine handlers, validators, and middleware to create complete API endpoints with proper authentication, authorization, and error handling.
🎯 Overview
Product routes are designed to:
- Provide complete API endpoints for product management operations
- Combine handlers with validators for secure operations
- Include authentication and authorization checks
- Support functional composition patterns
- Handle logging and error management automatically
📋 Route Structure
Each product route follows a consistent pattern:
- HTTP Method: Defines the operation type (GET, POST, PATCH, DELETE)
- Path: Specifies the endpoint URL with parameters
- Handler: Composed function chain for business logic
- Validators: Authentication and authorization checks
🔧 Available Product Routes
createProductRoute
Creates a new product and returns the created resource.
Purpose: Handles product creation with full resource retrieval
Route Details:
- Method:
POST - Path:
/products - Authentication: Required (Bearer token)
Handlers: createProduct, getProductById, normalizeProduct, orThrow
Validators: isAuthenticated, checkIdentityType(['admin'])
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.createProductRoute);
findProductsRoute
Retrieves all products with normalized list format.
Purpose: Lists products with pagination
Route Details:
- Method:
GET - Path:
/products - Authentication: Not required
Handlers: findProducts, normalizeProductsListTerminator
Validators: None
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.findProductsRoute);
createProductBatchRoute
Creates multiple products in batch and returns the created resources.
Purpose: Handles batch product creation
Route Details:
- Method:
POST - Path:
/products/batch - Authentication: Required (Bearer token)
Handlers: createProductBatch, getProductsByIds, normalizeProducts, orThrow
Validators: isAuthenticated, checkIdentityType(['admin'])
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.createProductBatchRoute);
updateProductBatchRoute
Updates multiple products in batch and returns the updated resources.
Purpose: Handles batch product updates
Route Details:
- Method:
PATCH - Path:
/products/batch - Authentication: Required (Bearer token)
Handlers: updateProductBatch, getProductsByIds, normalizeProductsListTerminator
Validators: isAuthenticated, checkIdentityType(['admin'])
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.updateProductBatchRoute);
deleteProductBatchRoute
Deletes multiple products in batch.
Purpose: Handles batch product deletion
Route Details:
- Method:
DELETE - Path:
/products/batch - Authentication: Required (Bearer token)
Handlers: deleteProductBatch, deleteBatchProductsTerminator
Validators: isAuthenticated, checkIdentityType(['admin'])
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.deleteProductBatchRoute);
getProductRoute
Retrieves a specific product by ID.
Purpose: Fetches product data
Route Details:
- Method:
GET - Path:
/products/:productId - Authentication: Not required
Handlers: getProductById, normalizeProductTerminator
Validators: None
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.getProductRoute);
updateProductRoute
Updates an existing product and returns the updated resource.
Purpose: Modifies product data with access control
Route Details:
- Method:
PATCH - Path:
/products/:productId - Authentication: Required (Bearer token)
Handlers: updateProduct, getProductById, normalizeProductTerminator
Validators: isAuthenticated, checkIdentityType(['admin'])
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.updateProductRoute);
deleteProductRoute
Deletes a product by ID with automatic image cleanup.
Purpose: Removes product with access control and cleans up associated images from storage
Route Details:
- Method:
DELETE - Path:
/products/:productId - Authentication: Required (Bearer token)
Blocks: deleteImagesOfProduct, deleteProduct
Terminators: Built-in success/error mapping via orThrow with 204 status code
Validators: isAuthenticated, checkIdentityType(['admin'])
Response (204 No Content): Empty response body on successful deletion
Error Responses:
401 Unauthorized: Authentication failed403 Forbidden: Non-admin user attempting deletion404 Not Found: Product not found500 Internal Server Error: Database operation or image cleanup failed
Handler Process:
- Validates authentication and path parameters
- Deletes all product images from file storage
- Deletes product from database
- Returns 204 No Content on successful deletion
Authorization Notes:
- Currently restricted to admin users only
- TODO: Add organization-based access control
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.deleteProductRoute);
// Client usage:
const response = await fetch('/api/products/product-123', {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`
}
});
if (response.status === 204) {
// Product and all its images deleted successfully
}
copyProductRoute
Creates a copy of an existing product.
Purpose: Duplicates product with access control
Route Details:
- Method:
POST - Path:
/products/:productId/copy - Authentication: Required (Bearer token)
Handlers: copyProduct, getProductById, normalizeProductTerminator
Validators: isAuthenticated, checkIdentityType(['admin'])
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.copyProductRoute);
copyProductBatchRoute
Creates copies of multiple products in batch.
Purpose: Handles batch product copying
Route Details:
- Method:
POST - Path:
/products/batch/copy - Authentication: Required (Bearer token)
Handlers: copyProductBatch, getProductsByIds, normalizeProductsListTerminator
Validators: isAuthenticated, checkIdentityType(['admin'])
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.copyProductBatchRoute);
getProductImageUploadUrlRoute
Generates a signed URL to upload a product image via GET /products/:productId/image-upload-url.
Purpose: Issues a pre-signed URL for secure product image uploads
Route Details:
- Method:
GET - Path:
/products/:productId/image-upload-url - Authentication: Required (Bearer token)
Blocks: generateProductImageUploadUrl
Terminators: Built-in success/error mapping via orThrow
Validators: isAuthenticated, checkIdentityType(['admin'])
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.getProductImageUploadUrlRoute);
createProductImageRoute
Creates a new product image for a specific product via POST /products/:productId/images.
Purpose: Adds a new image to an existing product's images array
Route Details:
- Method:
POST - Path:
/products/:productId/images - Authentication: Required (Bearer token)
Blocks: createProductImage, getProductImageById
Terminators: Built-in success/error mapping via orThrow with 201 status code
Validators: isAuthenticated, checkIdentityType(['admin'])
Request Body:
{
"objectId": "string (uuid)",
"type": "string"
}
Response (201 Created):
{
"id": "string (uuid)",
"objectId": "string (uuid)",
"type": "string",
"createdAt": "string (datetime)",
"updatedAt": "string (datetime)"
}
Error Responses:
404: Product not found or image not found after creation500: Database operation failed
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.createProductImageRoute);
// Client usage:
const response = await fetch('/api/products/prod-123/images', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
objectId: '550e8400-e29b-41d4-a716-446655440000',
type: 'image/png'
})
});
deleteProductImageRoute
Deletes a product image via DELETE /products/:productId/images/:imageId.
Purpose: Removes an image from a product's images array and deletes the file from storage
Route Details:
- Method:
DELETE - Path:
/products/:productId/images/:imageId - Authentication: Required (Bearer token)
Blocks: deleteProductImage
Terminators: Built-in success/error mapping via orThrow with 204 status code
Validators: isAuthenticated, checkIdentityType(['admin'])
Response (204 No Content): Empty response body on success
Error Responses:
404: Product not found or image not found in product500: Database operation failed or file storage deletion failed
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.deleteProductImageRoute);
// Client usage:
const response = await fetch('/api/products/prod-123/images/img-456', {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`
}
});
if (response.status === 204) {
console.log('Image deleted successfully');
}
Operation Details:
- Removes image from product's images array in database
- Deletes the actual image file from file storage
- Updates product's
updatedAttimestamp - Returns 204 No Content on success
createProductVariantRoute
Creates a new product variant via POST /products/:productId/variants.
Purpose: Adds a new variant to an existing product with full validation and normalization
Route Details:
- Method:
POST - Path:
/products/:productId/variants - Authentication: Required (Bearer token)
Blocks: createProductVariant, getProductVariantById, normalizeRawDocument
Terminators: Built-in success/error mapping via orThrow with 201 status code
Validators: isAuthenticated, checkIdentityType(['admin'])
Request Body:
{
"title": "string (required)",
"description": "string (optional)",
"sku": "string (optional)",
"imageIds": ["string"] (optional),
"price": {
"amount": "number (optional)",
"currency": "string (optional)",
"taxIncluded": "boolean (optional)",
"taxable": "boolean (optional)"
}
}
Response (201 Created):
{
"id": "string (uuid)",
"productId": "string",
"title": "string",
"description": "string",
"sku": "string",
"imageIds": ["string"],
"price": {
"amount": "number",
"currency": "string",
"taxIncluded": "boolean",
"taxable": "boolean"
},
"delFlg": 0,
"createdAt": "string (datetime)",
"updatedAt": "string (datetime)"
}
Error Responses:
400 Bad Request: Invalid request body or missing required fields404 Not Found: Product variant not found after creation500 Internal Server Error: Database operation failed
Handler Process:
- Validates request body and path parameters
- Creates product variant in database with auto-generated ID and timestamps
- Retrieves the created variant to confirm successful creation
- Normalizes response by removing MongoDB
_idfield - Returns 201 Created with normalized variant data
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.createProductVariantRoute);
// Client usage:
const response = await fetch('/api/products/prod-123/variants', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: 'Blue Baseball Cap',
sku: 'BBC-BLUE',
price: {
amount: 2999,
currency: 'USD',
taxIncluded: false,
taxable: true
},
imageIds: ['img-456', 'img-789']
})
});
const variant = await response.json();
Authorization Notes:
- Currently restricted to admin users only
- TODO: Add organization-based access control
- TODO: Add email verification checks
createProductVariantBulkRoute
Creates multiple product variants in bulk via POST /product/:productId/variants/bulk.
Purpose: Efficiently creates multiple product variants in a single operation with comprehensive validation and normalization.
Route Details:
- Method:
POST - Path:
/product/:productId/variants/bulk - Authentication: Required (Bearer token)
Blocks: createProductVariantBulk, buildFilterToGetProductVariantsByIds, findProductVariants, normalizeDocuments
Terminators: Built-in success/error mapping via orThrow with 201 status code
Validators: isAuthenticated, checkIdentityType(['admin'])
Path Parameters:
productId: string- Product ID to associate all variants with (from URL path)
Request Body (Array):
[
{
"title": "string (required)",
"description": "string (optional)",
"sku": "string (optional)",
"price": {
"amount": "number (optional)",
"currency": "string (optional)"
},
"imageIds": ["string"] (optional),
"isActive": "boolean (optional)"
}
]
Response (201 Created):
[
{
"id": "string (uuid)",
"productId": "string",
"title": "string",
"description": "string",
"sku": "string",
"price": {
"amount": "number",
"currency": "string"
},
"imageIds": ["string"],
"isActive": "boolean",
"createdAt": "string (datetime)",
"updatedAt": "string (datetime)"
}
]
Constraints:
- Maximum 100 variants per request
- Minimum 1 variant per request
- Each variant must have
productIdandtitle
Error Responses:
400 Bad Request: Invalid request body, missing required fields, or constraint violations401 Unauthorized: Authentication failed403 Forbidden: Non-admin user attempting bulk creation500 Internal Server Error: Database operation failed or bulk write error
Handler Process:
- Validates authentication, path parameters, and request body array
- Creates multiple product variants in bulk database operation with product association
- Retrieves created variants by their generated IDs
- Normalizes response by removing MongoDB
_idfields - Returns 201 Created with array of normalized variant data
Key Features:
- Bulk Efficiency: Single database operation for multiple variants
- Atomic Operations: All variants succeed or all fail
- Error Specificity: Detailed error reporting for bulk write failures
- Data Normalization: Automatic MongoDB field cleanup in responses
Authorization Notes:
- Currently restricted to admin users only
- TODO: Add organization-based access control
- TODO: Add email verification checks
- TODO: Add product ownership validation for each variant
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.createProductVariantBulkRoute);
// Client usage:
const response = await fetch('/api/product/prod-123/variants/bulk', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify([
{
title: 'Small - Red',
sku: 'S-RED',
price: { amount: 1999, currency: 'USD' }
},
{
title: 'Medium - Blue',
sku: 'M-BLUE',
price: { amount: 2099, currency: 'USD' }
}
])
});
const variants = await response.json();
updateProductVariantBulkRoute
Updates multiple product variants in bulk via PATCH /product/:productId/variants/bulk.
Purpose: Efficiently updates multiple product variants in a single operation with comprehensive validation and data normalization.
Route Details:
- Method:
PATCH - Path:
/product/:productId/variants/bulk - Authentication: Required (Bearer token)
Blocks: updateProductVariantBulk, buildFilterToGetProductVariantsByIds, findProductVariants, normalizeDocuments
Terminators: Built-in success/error mapping via orThrow with 200 status code
Validators: isAuthenticated, checkIdentityType(['admin'])
Path Parameters:
productId: string- Product ID to associate variants with (from URL path)
Request Body:
{
"ids": ["string"],
"data": {
"description": "string (optional)",
"sku": "string (optional)",
"price": {
"amount": "number (optional)",
"currency": "string (optional)"
},
"imageIds": ["string"] (optional),
"title": "string (optional)"
}
}
Response (200 OK):
[
{
"id": "string",
"productId": "string",
"title": "string",
"description": "string",
"sku": "string",
"price": {
"amount": "number",
"currency": "string"
},
"imageIds": ["string"],
"createdAt": "string",
"updatedAt": "string"
}
]
Constraints:
- Maximum 100 variant IDs per request
- Minimum 1 variant ID per request
- Each ID must correspond to an existing variant
Error Responses:
400 Bad Request: Invalid request body, missing required fields, or constraint violations401 Unauthorized: Authentication failed403 Forbidden: Non-admin user attempting bulk update404 Not Found: One or more product variants not found500 Internal Server Error: Database operation failed
Handler Process:
- Validates authentication, path parameters, and request body structure
- Updates all specified variants in bulk database operation
- Retrieves updated variants by their IDs
- Normalizes response by removing MongoDB
_idfields - Returns 200 OK with array of normalized variant data
Key Features:
- Bulk Efficiency: Single database operation for multiple variant updates
- Atomic Operations: All updates succeed or entire operation fails
- Data Normalization: Automatic MongoDB field cleanup in responses
- Flexible Updates: Update any combination of variant fields
Authorization Notes:
- Currently restricted to admin users only
- TODO: Add organization-based access control
- TODO: Add email verification requirements
- TODO: Add product ownership validation for each variant
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.updateProductVariantBulkRoute);
// Client usage:
const response = await fetch('/api/product/prod-123/variants/bulk', {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
ids: ['var-123', 'var-456', 'var-789'],
data: {
description: 'Updated description for all variants',
price: { amount: 2999, currency: 'USD' }
}
})
});
const variants = await response.json();
deleteProductVariantBulkRoute
Deletes multiple product variants in bulk via POST /product/:productId/variants/bulk-delete.
Purpose: Efficiently removes multiple product variants in a single operation with comprehensive validation and error handling.
Route Details:
- Method:
POST - Path:
/product/:productId/variants/bulk-delete - Authentication: Required (Bearer token)
Blocks: deleteProductVariantBulk, normalizeEmptyBody
Terminators: Built-in success/error mapping via orThrow with 204 status code
Validators: isAuthenticated, checkIdentityType(['admin'])
Path Parameters:
productId: string- Product ID to associate variants with (from URL path)
Request Body:
["string", "string", "string"]
Response (204 No Content): Empty response body on successful deletion
Constraints:
- Maximum 100 variant IDs per request
- Minimum 1 variant ID per request
- Each ID must correspond to an existing variant
Error Responses:
400 Bad Request: Invalid request body, missing required fields, or constraint violations401 Unauthorized: Authentication failed403 Forbidden: Non-admin user attempting bulk deletion500 Internal Server Error: Database operation failed
Handler Process:
- Validates authentication, path parameters, and request body structure
- Deletes all specified variants in bulk database operation
- Validates that at least one variant was deleted
- Returns 204 No Content on successful deletion
Key Features:
- Bulk Efficiency: Single database operation for multiple variant deletions
- Atomic Operations: All deletions succeed or entire operation fails
- Validation: Ensures at least one variant is deleted before returning success
- Clean Response: Returns 204 No Content for successful bulk deletions
Authorization Notes:
- Currently restricted to admin users only
- TODO: Add organization-based access control
- TODO: Add email verification requirements
- TODO: Add product ownership validation for each variant
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.deleteProductVariantBulkRoute);
// Client usage:
const response = await fetch('/api/product/prod-123/variants/bulk-delete', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify([
'var-123',
'var-456',
'var-789'
])
});
// 204 No Content on success
if (response.status === 204) {
console.log('All variants deleted successfully');
}
getProductVariantRoute
Retrieves a product variant via GET /products/:productId/variants/:productVariantId.
Purpose: Gets detailed information about a specific product variant with data normalization
Route Details:
- Method:
GET - Path:
/products/:productId/variants/:productVariantId - Authentication: Required (Bearer token)
Blocks: getProductVariantById, normalizeRawDocument
Terminators: Built-in success/error mapping via orThrow with 200 status code
Validators: isAuthenticated
Response (200 OK):
{
"id": "string (uuid)",
"productId": "string",
"title": "string",
"description": "string",
"sku": "string",
"imageIds": ["string"],
"price": {
"amount": "number",
"currency": "string",
"taxIncluded": "boolean",
"taxable": "boolean"
},
"delFlg": 0,
"createdAt": "string (datetime)",
"updatedAt": "string (datetime)"
}
Error Responses:
401 Unauthorized: Authentication failed404 Not Found: Product variant not found or doesn't belong to the specified product500 Internal Server Error: Database operation failed
Handler Process:
- Validates authentication and path parameters
- Retrieves product variant from database with product scoping
- Normalizes response by removing MongoDB
_idfield - Returns 200 OK with normalized variant data
Authorization Notes:
- Requires authentication only (no role restrictions currently)
- TODO: Add organization-based access control
- TODO: Add email verification checks
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.getProductVariantRoute);
// Client usage:
const response = await fetch('/api/products/prod-123/variants/var-456', {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`
}
});
const variant = await response.json();
// Returns 200 OK with product variant details
updateProductVariantRoute
Updates a product variant via PATCH /products/:productId/variants/:productVariantId.
Purpose: Modifies existing product variant data with full validation and normalization
Route Details:
- Method:
PATCH - Path:
/products/:productId/variants/:productVariantId - Authentication: Required (Bearer token)
Blocks: updateProductVariant, getProductVariantById, normalizeRawDocument
Terminators: Built-in success/error mapping via orThrow with 200 status code
Validators: isAuthenticated, checkIdentityType(['admin'])
Request Body:
{
"title": "string (optional)",
"description": "string (optional)",
"sku": "string (optional)",
"imageIds": ["string"] (optional),
"price": {
"amount": "number (optional)",
"currency": "string (optional)",
"taxIncluded": "boolean (optional)",
"taxable": "boolean (optional)"
}
}
Response (200 OK):
{
"id": "string (uuid)",
"productId": "string",
"title": "string",
"description": "string",
"sku": "string",
"imageIds": ["string"],
"price": {
"amount": "number",
"currency": "string",
"taxIncluded": "boolean",
"taxable": "boolean"
},
"delFlg": 0,
"createdAt": "string (datetime)",
"updatedAt": "string (datetime)"
}
Error Responses:
400 Bad Request: Invalid request body or additional properties401 Unauthorized: Authentication failed403 Forbidden: Non-admin user attempting update404 Not Found: Product variant not found500 Internal Server Error: Database operation failed
Handler Process:
- Validates authentication and path parameters
- Updates product variant in database with optional constraints
- Retrieves updated variant to confirm successful modification
- Normalizes response by removing MongoDB
_idfield - Returns 200 OK with normalized updated variant data
Authorization Notes:
- Currently restricted to admin users only
- TODO: Add organization-based access control
- TODO: Add email verification checks
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.updateProductVariantRoute);
// Client usage:
const response = await fetch('/api/products/prod-123/variants/var-456', {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
price: {
amount: 2499,
currency: 'USD'
},
sku: 'BBC-BLUE-UPDATED'
})
});
const updatedVariant = await response.json();
// Returns 200 OK with updated product variant
deleteProductVariantRoute
Deletes a product variant via DELETE /products/:productId/variants/:productVariantId.
Purpose: Removes a product variant from the database with proper validation and error handling
Route Details:
- Method:
DELETE - Path:
/products/:productId/variants/:productVariantId - Authentication: Required (Bearer token)
Blocks: deleteProductVariant, normalizeEmptyBody
Terminators: Built-in success/error mapping via orThrow with 204 status code
Validators: isAuthenticated, checkIdentityType(['admin'])
Response (204 No Content): Empty response body on successful deletion
Error Responses:
401 Unauthorized: Authentication failed403 Forbidden: Non-admin user attempting deletion500 Internal Server Error: Database operation failed or variant not found
Handler Process:
- Validates authentication and path parameters
- Deletes product variant from database by ID
- Normalizes empty response body
- Returns 204 No Content on successful deletion
Authorization Notes:
- Currently restricted to admin users only
- TODO: Add organization-based access control
- TODO: Add email verification checks
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.deleteProductVariantRoute);
// Client usage:
const response = await fetch('/api/products/prod-123/variants/var-456', {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${token}`
}
});
if (response.status === 204) {
// Product variant deleted successfully
}
findProductVariantsRoute
Retrieves product variants for a specific product via GET /products/:productId/variants.
Purpose: Lists all product variants for a given product with pagination and proper data normalization
Route Details:
- Method:
GET - Path:
/products/:productId/variants - Authentication: Not required (TODO: Add authentication and authorization)
Blocks: buildFilterToGetProductVariantsByProductId, findProductVariants, normalizeDocuments
Terminators: Built-in pagination and response formatting
Validators: None currently (TODO: Add product existence validation)
Response (200 OK):
{
"data": [
{
"id": "string",
"productId": "string",
"title": "string",
"description": "string",
"sku": "string",
"imageIds": ["string"],
"price": {
"amount": "number",
"currency": "string"
},
"createdAt": "string",
"updatedAt": "string"
}
],
"metadata": {
"pagination": {
"page": 1,
"limit": 10,
"total": 25,
"totalPages": 3,
"hasNext": true,
"hasPrev": false
}
}
}
Query Parameters:
page?: number- Page number for pagination (default: 1)limit?: number- Number of items per page (default: 10)sort?: string- Field to sort byorder?: "asc" | "desc"- Sort order direction
Error Responses:
500 Internal Server Error: Database operation failed
Handler Process:
- Builds filter to get product variants by product ID
- Queries database for product variants with pagination
- Normalizes documents by removing MongoDB
_idfields - Formats response with data and pagination metadata
- Returns 200 OK with paginated variant list
Authorization Notes:
- Currently no authentication or authorization required
- TODO: Add product existence validation
- TODO: Add organization-based access control
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.findProductVariantsRoute);
// Client usage with pagination:
const response = await fetch('/api/products/prod-123/variants?page=1&limit=5');
const result = await response.json();
// result.data contains array of product variants
// result.metadata.pagination contains pagination info
findProductsByOrganizationIdRoute
Retrieves products by organization ID via GET /products/organizations/:organizationId.
Purpose: Lists products scoped to a specific organization with pagination, image normalization, and proper authorization controls.
Route Details:
- Method:
GET - Path:
/products/organizations/:organizationId - Authentication: Required (Bearer token)
Blocks: buildOrganizationIdFilter, buildWithoutMongoIdFindOptions, findProductResources, normalizeImagesOfProducts, normalizeProducts
Terminators: Built-in success/error mapping via orThrow with 200 status code
Validators: isAuthenticated, hasOrgRole(['owner', 'admin', 'member'], path to organizationId)
Query Parameters:
page?: number- Page number for pagination (default: 1)limit?: number- Number of items per page (default: 10)sort?: string- Field to sort byorder?: "asc" | "desc"- Sort order direction
Response (200 OK):
{
"data": [
{
"id": "prod-123",
"organizationId": "org-456",
"name": "Premium Widget",
"description": "High-quality widget for professionals",
"images": [
{
"id": "img-789",
"objectId": "abc123...",
"type": "image/jpeg",
"url": "https://storage.googleapis.com/bucket/abc123..."
}
],
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
}
],
"metadata": {
"pagination": {
"page": 1,
"limit": 10,
"total": 25,
"totalPages": 3,
"hasNext": true,
"hasPrev": false
}
}
}
Path Parameters:
organizationId: string- Organization identifier to scope product retrieval
Constraints:
- User must have organization membership (owner, admin, or member role)
- Products are filtered by organization ID for multi-tenant support
- Image normalization requires file storage driver configuration
Error Responses:
401 Unauthorized: Authentication failed403 Forbidden: User doesn't have access to the organization500 Internal Server Error: Database operation failed or file storage error
Handler Process:
- Validates authentication and organization access permissions
- Builds organization-specific filter for product queries
- Configures MongoDB find options without
_idfield projection - Queries products using paginated resource retrieval
- Normalizes product images with signed URLs
- Formats and normalizes product data for API response
- Returns 200 OK with paginated product list and metadata
Key Features:
- Organization Scoping: Ensures users can only access products within their organizations
- Image Normalization: Automatic URL generation for product images
- Pagination Support: Built-in pagination with configurable limits and sorting
- Data Normalization: MongoDB field cleanup and URL enrichment
- Authorization: Role-based access control with organization membership validation
Authorization Notes:
- Requires authentication and organization membership
- Supports owner, admin, and member roles for access
- TODO: Add email verification requirements
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.findProductsByOrganizationIdRoute);
// Client usage with organization scoping:
const response = await fetch('/api/products/organizations/org-123?page=1&limit=5', {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`
}
});
const result = await response.json();
// result.data contains organization-scoped products
// result.metadata.pagination contains pagination info
getProductLikersRoute
Retrieves product likers via GET /products/:productId/likers.
Purpose: Lists users who have liked a specific product with pagination, avatar normalization, and proper authorization controls.
Route Details:
- Method:
GET - Path:
/products/:productId/likers - Authentication: Required (Bearer token)
Blocks: getProductByIdBlock, buildProductLikersByLikeProductIdQuery, buildWithoutMongoIdFindOptions, findProfiles, normalizeFollowers
Terminators: Built-in success/error mapping via orThrow with 200 status code
Validators: isAuthenticated, checkIdentityType(['admin'])
Query Parameters:
page?: number- Page number for pagination (default: 1)limit?: number- Number of items per page (default: 10)sort?: string- Field to sort byorder?: "asc" | "desc"- Sort order direction
Response (200 OK):
{
"data": [
{
"id": "user-123",
"name": "John Doe",
"avatar": {
"id": "avatar-456",
"objectId": "abc123...",
"type": "image/jpeg",
"url": "https://storage.googleapis.com/bucket/abc123..."
}
}
],
"metadata": {
"pagination": {
"page": 1,
"limit": 10,
"total": 25,
"totalPages": 3,
"hasNext": true,
"hasPrev": false
}
}
}
Path Parameters:
productId: string- Product identifier to retrieve likers for
Constraints:
- Product must exist in the database
- User profiles are filtered by product likes relationship
- Avatar normalization requires file storage driver configuration
- Admin-only access for security
Error Responses:
401 Unauthorized: Authentication failed403 Forbidden: Non-admin user attempting to view likers404 Not Found: Product not found500 Internal Server Error: Database operation failed or file storage error
Handler Process:
- Validates authentication and admin authorization
- Verifies product existence in database
- Builds query filter for users who liked the product
- Configures MongoDB find options without
_idfield projection - Queries user profiles with pagination support
- Normalizes user avatars with signed URLs
- Formats response with user data and pagination metadata
- Returns 200 OK with paginated likers list
Key Features:
- Social Engagement: Displays users who have liked a product
- Avatar Normalization: Automatic URL generation for user avatars
- Pagination Support: Built-in pagination with configurable limits and sorting
- Data Normalization: MongoDB field cleanup and URL enrichment
- Admin Security: Restricted to admin users for privacy protection
Authorization Notes:
- Currently restricted to admin users only for privacy reasons
- TODO: Add product ownership validation
- TODO: Consider public access for product owners
Usage:
import { routes } from '@nodeblocks/backend-sdk';
// Register route with Express app
app.use('/api', routes.getProductLikersRoute);
// Client usage with product likers retrieval:
const response = await fetch('/api/products/prod-123/likers?page=1&limit=5', {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`
}
});
const result = await response.json();
// result.data contains user profiles who liked the product
// result.metadata.pagination contains pagination info