Skip to main content
Version: 🚧 Canary

🛣️ 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 failed
  • 403 Forbidden: Non-admin user attempting deletion
  • 404 Not Found: Product not found
  • 500 Internal Server Error: Database operation or image cleanup failed

Handler Process:

  1. Validates authentication and path parameters
  2. Deletes all product images from file storage
  3. Deletes product from database
  4. 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 creation
  • 500: 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 product
  • 500: 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:

  1. Removes image from product's images array in database
  2. Deletes the actual image file from file storage
  3. Updates product's updatedAt timestamp
  4. 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 fields
  • 404 Not Found: Product variant not found after creation
  • 500 Internal Server Error: Database operation failed

Handler Process:

  1. Validates request body and path parameters
  2. Creates product variant in database with auto-generated ID and timestamps
  3. Retrieves the created variant to confirm successful creation
  4. Normalizes response by removing MongoDB _id field
  5. 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 productId and title

Error Responses:

  • 400 Bad Request: Invalid request body, missing required fields, or constraint violations
  • 401 Unauthorized: Authentication failed
  • 403 Forbidden: Non-admin user attempting bulk creation
  • 500 Internal Server Error: Database operation failed or bulk write error

Handler Process:

  1. Validates authentication, path parameters, and request body array
  2. Creates multiple product variants in bulk database operation with product association
  3. Retrieves created variants by their generated IDs
  4. Normalizes response by removing MongoDB _id fields
  5. 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 violations
  • 401 Unauthorized: Authentication failed
  • 403 Forbidden: Non-admin user attempting bulk update
  • 404 Not Found: One or more product variants not found
  • 500 Internal Server Error: Database operation failed

Handler Process:

  1. Validates authentication, path parameters, and request body structure
  2. Updates all specified variants in bulk database operation
  3. Retrieves updated variants by their IDs
  4. Normalizes response by removing MongoDB _id fields
  5. 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 violations
  • 401 Unauthorized: Authentication failed
  • 403 Forbidden: Non-admin user attempting bulk deletion
  • 500 Internal Server Error: Database operation failed

Handler Process:

  1. Validates authentication, path parameters, and request body structure
  2. Deletes all specified variants in bulk database operation
  3. Validates that at least one variant was deleted
  4. 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 failed
  • 404 Not Found: Product variant not found or doesn't belong to the specified product
  • 500 Internal Server Error: Database operation failed

Handler Process:

  1. Validates authentication and path parameters
  2. Retrieves product variant from database with product scoping
  3. Normalizes response by removing MongoDB _id field
  4. 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 properties
  • 401 Unauthorized: Authentication failed
  • 403 Forbidden: Non-admin user attempting update
  • 404 Not Found: Product variant not found
  • 500 Internal Server Error: Database operation failed

Handler Process:

  1. Validates authentication and path parameters
  2. Updates product variant in database with optional constraints
  3. Retrieves updated variant to confirm successful modification
  4. Normalizes response by removing MongoDB _id field
  5. 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 failed
  • 403 Forbidden: Non-admin user attempting deletion
  • 500 Internal Server Error: Database operation failed or variant not found

Handler Process:

  1. Validates authentication and path parameters
  2. Deletes product variant from database by ID
  3. Normalizes empty response body
  4. 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 by
  • order?: "asc" | "desc" - Sort order direction

Error Responses:

  • 500 Internal Server Error: Database operation failed

Handler Process:

  1. Builds filter to get product variants by product ID
  2. Queries database for product variants with pagination
  3. Normalizes documents by removing MongoDB _id fields
  4. Formats response with data and pagination metadata
  5. 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 by
  • order?: "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 failed
  • 403 Forbidden: User doesn't have access to the organization
  • 500 Internal Server Error: Database operation failed or file storage error

Handler Process:

  1. Validates authentication and organization access permissions
  2. Builds organization-specific filter for product queries
  3. Configures MongoDB find options without _id field projection
  4. Queries products using paginated resource retrieval
  5. Normalizes product images with signed URLs
  6. Formats and normalizes product data for API response
  7. 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 by
  • order?: "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 failed
  • 403 Forbidden: Non-admin user attempting to view likers
  • 404 Not Found: Product not found
  • 500 Internal Server Error: Database operation failed or file storage error

Handler Process:

  1. Validates authentication and admin authorization
  2. Verifies product existence in database
  3. Builds query filter for users who liked the product
  4. Configures MongoDB find options without _id field projection
  5. Queries user profiles with pagination support
  6. Normalizes user avatars with signed URLs
  7. Formats response with user data and pagination metadata
  8. 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