メインコンテンツまでスキップ
バージョン: 🚧 Canary

📦 Product Service

Testing Status

The Product Service provides a complete REST API for managing product entities with comprehensive CRUD operations and powerful batch processing capabilities. It's built using the Nodeblocks functional composition approach and integrates seamlessly with MongoDB.


🚀 Quickstart

import express from 'express';
import { middlewares, services, drivers } from '@nodeblocks/backend-sdk';

const { nodeBlocksErrorMiddleware } = middlewares;
const { productService } = services;
const { getMongoClient, createFileStorageDriver } = drivers;

const client = getMongoClient('mongodb://localhost:27017', 'dev');

// Required for image upload URL endpoint:
// Ensure GOOGLE_APPLICATION_CREDENTIALS is set to your GCP service account JSON.
const fileStorageDriver = createFileStorageDriver(
'your-gcp-project-id',
'your-bucket-name'
);

express()
.use(
productService(
{
products: client.collection('products'),
identities: client.collection('identities'),
},
{
authSecrets: {
authEncSecret: 'your-encryption-secret',
authSignSecret: 'your-signing-secret',
},
identity: {
typeIds: {
admin: '100',
guest: '000',
regular: '001',
},
},
},
{ fileStorageDriver }
)
)
.use(nodeBlocksErrorMiddleware())
.listen(8089, () => console.log('Server running'));

📋 Endpoint Summary

Individual Product Operations

MethodPathDescriptionAuthorization
POST/productsCreate a new productBearer token required (admin only)
GET/products/:productIdRetrieve a product by IDNone required
GET/productsList/filter productsNone required
PATCH/products/:productIdUpdate a productBearer token required (admin only)
DELETE/products/:productIdDelete a productBearer token required (admin only)
POST/products/:productId/copyCopy an existing productBearer token required (admin only)

File Upload Operations

MethodPathDescriptionAuthorization
GET/products/:productId/image-upload-urlGet signed URL to upload a product imageBearer token required (admin only)

Batch Product Operations

MethodPathDescriptionAuthorization
POST/products/batchCreate multiple productsBearer token required (admin only)
PATCH/products/batchUpdate multiple productsBearer token required (admin only)
DELETE/products/batchDelete multiple productsBearer token required (admin only)
POST/products/batch/copyCopy multiple productsBearer token required (admin only)

🗄️ Entity Schema

The product entity combines base fields (auto-generated) with product-specific data:

{
"name": "string",
"description": "string",
"createdAt": "string (datetime)",
"id": "string",
"updatedAt": "string (datetime)"
}

Field Details

FieldTypeAuto-GeneratedRequiredDescription
namestringProduct name
descriptionstringProduct description
createdAtdatetimeCreation timestamp
idstringUnique identifier (UUID)
updatedAtdatetimeLast modification timestamp

📝 Note: Auto-generated fields are set by the service and should not be included in create/update requests. Field order in responses matches the actual API output.


🔐 Authentication Headers

For protected endpoints, include the following headers:

Authorization: Bearer <admin_access_token>
x-nb-fingerprint: <device_fingerprint>

⚠️ Important: The x-nb-fingerprint header is required for all authenticated requests if fingerprint was specified during authorization. Without it, requests will return 401 Unauthorized.


🔧 API Endpoints

1. Create Product

Creates a new product with the provided information.

Request:

  • Method: POST
  • Path: /products
  • Headers: Content-Type: application/json, Authorization: Bearer <access-token>
  • Authorization: Bearer token required (admin only)

Request Body:

FieldTypeRequiredDescription
namestringProduct name
descriptionstringProduct description

Response Body:

FieldTypeDescription
idstringUnique product identifier
namestringProduct name
descriptionstringProduct description
createdAtstringCreation timestamp
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: Enforced automatically (name, description required)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X POST {{host}}/products \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '{
"name": "Premium Widget",
"description": "High-quality widget for enterprise use"
}'

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"id": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"name": "Premium Widget",
"description": "High-quality widget for enterprise use",
"createdAt": "2024-05-28T09:41:22.552Z",
"updatedAt": "2024-05-28T09:41:22.552Z"
}

Error Responses:

When request body is missing required fields:

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
"error": {
"message": "Validation Error",
"data": [
"request body must have required property 'name'",
"request body must have required property 'description'"
]
}
}

When database insert operation fails:

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
"error": {
"message": "Failed to create product"
}
}

2. Get Product by ID

Retrieves a specific product by their unique ID.

Request:

  • Method: GET
  • Path: /products/:productId
  • Authorization: None required

URL Parameters:

ParameterTypeRequiredDescription
productIdstringUnique product identifier

Response Body:

FieldTypeDescription
idstringUnique product identifier
namestringProduct name
descriptionstringProduct description
createdAtstringCreation timestamp
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: Path parameter validation (productId required)
  • Route Validators: None

Example Request:

curl {{host}}/products/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"id": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"name": "Premium Widget",
"description": "High-quality widget for enterprise use",
"createdAt": "2024-05-28T09:41:22.552Z",
"updatedAt": "2024-05-28T09:41:22.552Z"
}

Error Responses:

When no product exists with the provided ID:

HTTP/1.1 404 Not Found
Content-Type: application/json

{
"error": {
"message": "Product not found"
}
}

3. List Products

Retrieves a list of products with optional filtering and pagination.

Request:

  • Method: GET
  • Path: /products
  • Authorization: None required

Query Parameters:

ParameterTypeRequiredDescription
namestringFilter by product name
descriptionstringFilter by product description
pagenumberPage number for pagination
limitnumberNumber of items per page

Response Body:

FieldTypeDescription
idstringUnique product identifier
namestringProduct name
descriptionstringProduct description
createdAtstringCreation timestamp
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: Query parameter validation (optional name, description, page, limit)
  • Route Validators: None

Example Requests:

List all products:

curl {{host}}/products

Filter by name:

curl "{{host}}/products?name=Premium%20Widget"

With pagination:

curl "{{host}}/products?page=1&limit=10"

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

[
{
"name": "Premium Widget",
"description": "Updated high-quality widget for enterprise use",
"createdAt": "2025-06-24T06:39:17.101Z",
"id": "3d0e4b74-398c-43e2-a7b4-c9a180477322",
"updatedAt": "2025-06-24T06:39:17.101Z"
},
{
"name": "Product A",
"description": "Updated batch description",
"createdAt": "2025-06-24T06:39:45.378Z",
"id": "0e0dd6c7-c3d5-49e5-a1d8-20daa34d380a",
"updatedAt": "2025-06-24T06:39:55.720Z"
},
{
"name": "Product B",
"description": "Updated batch description",
"createdAt": "2025-06-24T06:39:45.378Z",
"id": "d5a60fdf-2a22-4fcc-8e40-a68cb89cce72",
"updatedAt": "2025-06-24T06:39:55.720Z"
}
]

4. Update Product

Updates an existing product with partial data.

Request:

  • Method: PATCH
  • Path: /products/:productId
  • Headers: Content-Type: application/json, Authorization: Bearer <access-token>
  • Authorization: Bearer token required (admin only)

URL Parameters:

ParameterTypeRequiredDescription
productIdstringUnique product identifier

Request Body (all fields optional):

FieldTypeRequiredDescription
namestringProduct name
descriptionstringProduct description

Response Body:

FieldTypeDescription
idstringUnique product identifier
namestringUpdated product name
descriptionstringUpdated product description
createdAtstringCreation timestamp
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: Enforced automatically (partial updates, all fields optional, no additional properties allowed)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X PATCH {{host}}/products/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '{"description": "Updated high-quality widget for enterprise use"}'

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"id": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"name": "Premium Widget",
"description": "Updated high-quality widget for enterprise use",
"createdAt": "2024-05-28T09:41:22.552Z",
"updatedAt": "2024-05-28T14:22:15.789Z"
}

Error Responses:

When no product exists with the provided ID:

HTTP/1.1 404 Not Found
Content-Type: application/json

{
"error": {
"message": "Product not found"
}
}

5. Delete Product

Permanently deletes a product from the system.

Request:

  • Method: DELETE
  • Path: /products/:productId
  • Headers: Authorization: Bearer <access-token>
  • Authorization: Bearer token required (admin only)

URL Parameters:

ParameterTypeRequiredDescription
productIdstringUnique product identifier

Response Body:

FieldTypeDescription
No response body-Delete endpoint returns no response body on success

Validation:

  • Schema Validation: Path parameter validation (productId required)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X DELETE {{host}}/products/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2 \
-H "Authorization: Bearer <access-token>"

Success Response:

HTTP/1.1 204 No Content

Error Responses:

When no product exists with the provided ID:

HTTP/1.1 404 Not Found
Content-Type: application/json

{
"error": {
"message": "Product not found"
}
}

6. Copy Product

Creates a copy of an existing product with a new ID.

Request:

  • Method: POST
  • Path: /products/:productId/copy
  • Headers: Authorization: Bearer <access-token>
  • Authorization: Bearer token required (admin only)

URL Parameters:

ParameterTypeRequiredDescription
productIdstringID of product to copy

Response Body:

FieldTypeDescription
idstringUnique identifier for the copied product
namestringProduct name (copied from original)
descriptionstringProduct description (copied from original)
createdAtstringCreation timestamp
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: Path parameter validation (productId required)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X POST {{host}}/products/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/copy \
-H "Authorization: Bearer <access-token>"

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"id": "9abc123f-1cd8-4def-b123-456789abcdef",
"name": "Premium Widget",
"description": "High-quality widget for enterprise use",
"createdAt": "2024-05-28T15:30:45.123Z",
"updatedAt": "2024-05-28T15:30:45.123Z"
}

Error Responses:

When no product exists with the provided ID:

HTTP/1.1 404 Not Found
Content-Type: application/json

{
"error": {
"message": "Product not found"
}
}

🔄 Batch Product Operations

The Product Service provides powerful batch operations for managing multiple products efficiently.

7. Create Multiple Products

Creates multiple products in a single request.

Request:

  • Method: POST
  • Path: /products/batch
  • Headers: Content-Type: application/json, Authorization: Bearer <access-token>
  • Authorization: Bearer token required (admin only)

Request Body: Array of product objects, each requiring name and description.

Response Body:

FieldTypeDescription
idstringUnique product identifier
namestringProduct name
descriptionstringProduct description
createdAtstringCreation timestamp
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: Enforced automatically (array of product objects with required name and description)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X POST {{host}}/products/batch \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '[
{
"name": "Product A",
"description": "Description for Product A"
},
{
"name": "Product B",
"description": "Description for Product B"
}
]'

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

[
{
"name": "Product A",
"description": "Description for Product A",
"createdAt": "2025-06-24T06:39:45.378Z",
"id": "0e0dd6c7-c3d5-49e5-a1d8-20daa34d380a",
"updatedAt": "2025-06-24T06:39:45.378Z"
},
{
"name": "Product B",
"description": "Description for Product B",
"createdAt": "2025-06-24T06:39:45.378Z",
"id": "d5a60fdf-2a22-4fcc-8e40-a68cb89cce72",
"updatedAt": "2025-06-24T06:39:45.378Z"
}
]

8. Update Multiple Products

Updates multiple products with the same data in a single request.

Request:

  • Method: PATCH
  • Path: /products/batch
  • Headers: Content-Type: application/json, Authorization: Bearer <access-token>
  • Authorization: Bearer token required (admin only)

Request Body:

FieldTypeRequiredDescription
idsarray of stringsArray of product IDs to update
dataobjectUpdate data to apply to all products
data.namestringNew product name
data.descriptionstringNew product description

Response Body:

FieldTypeDescription
idstringUnique product identifier
namestringUpdated product name
descriptionstringUpdated product description
createdAtstringCreation timestamp
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: Enforced automatically (ids array and data object required)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X PATCH {{host}}/products/batch \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '{
"ids": [
"7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"8fec096b-1bc7-5bfe-c827-3600e8fe2790"
],
"data": {
"description": "Updated batch description"
}
}'

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

[
{
"id": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"name": "Product A",
"description": "Updated batch description",
"createdAt": "2024-05-28T09:41:22.552Z",
"updatedAt": "2024-05-28T15:45:12.789Z"
},
{
"id": "8fec096b-1bc7-5bfe-c827-3600e8fe2790",
"name": "Product B",
"description": "Updated batch description",
"createdAt": "2024-05-28T09:41:23.123Z",
"updatedAt": "2024-05-28T15:45:12.789Z"
}
]

9. Delete Multiple Products

Deletes multiple products in a single request.

Request:

  • Method: DELETE
  • Path: /products/batch
  • Headers: Content-Type: application/json, Authorization: Bearer <access-token>
  • Authorization: Bearer token required (admin only)

Request Body: Array of product IDs to delete.

Response Body:

FieldTypeDescription
No response body-Delete endpoint returns no response body on success

Validation:

  • Schema Validation: Enforced automatically (array of strings)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X DELETE {{host}}/products/batch \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '[
"7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"8fec096b-1bc7-5bfe-c827-3600e8fe2790"
]'

Success Response:

HTTP/1.1 204 No Content

10. Copy Multiple Products

Creates copies of multiple products in a single request.

Request:

  • Method: POST
  • Path: /products/batch/copy
  • Headers: Content-Type: application/json, Authorization: Bearer <access-token>
  • Authorization: Bearer token required (admin only)

Request Body: Array of product IDs to copy.

Response Body:

FieldTypeDescription
idstringUnique identifier for the copied product
namestringProduct name (copied from original)
descriptionstringProduct description (copied from original)
createdAtstringCreation timestamp
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: Enforced automatically (array of strings)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl -X POST {{host}}/products/batch/copy \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '[
"7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"8fec096b-1bc7-5bfe-c827-3600e8fe2790"
]'

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

[
{
"id": "9abc123f-1cd8-4def-b123-456789abcdef",
"name": "Product A",
"description": "Description for Product A",
"createdAt": "2024-05-28T16:00:00.000Z",
"updatedAt": "2024-05-28T16:00:00.000Z"
},
{
"id": "def456a1-2e3f-4567-8901-23456789bcde",
"name": "Product B",
"description": "Description for Product B",
"createdAt": "2024-05-28T16:00:00.100Z",
"updatedAt": "2024-05-28T16:00:00.100Z"
}
]

11. Get Product Image Upload URL

Generates a pre-signed URL for securely uploading a product image. Returns an object ID and a temporary signed URL.

Request:

  • Method: GET
  • Path: /products/:productId/image-upload-url
  • Headers: Authorization: Bearer <token>
  • Authorization: Bearer token required (admin only)

URL Parameters:

ParameterTypeRequiredDescription
productIdstringTarget product ID

Query Parameters:

ParameterTypeRequiredDescription
contentTypestringImage MIME type (e.g., image/png)
contentLengthnumberFile size in bytes (max 10MB)

Response Body:

FieldTypeDescription
objectIdstringGenerated storage object ID for the product image
urlstringPre-signed URL for uploading the file

Validation:

  • Schema Validation: Uses image upload schema (content type and size constraints)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role

Example Request:

curl "{{host}}/products/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/image-upload-url?contentType=image/webp&contentLength=2097152" \
-H "Authorization: Bearer <access-token>"

Success Response:

{
"objectId": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"url": "https://storage.googleapis.com/bucket/products/...&X-Goog-Expires=900&X-Goog-Signature=..."
}

⚙️ Configuration Options

Service Configuration

interface ProductServiceConfiguration {
authSecrets: {
authEncSecret: string; // JWT encryption secret
authSignSecret: string; // JWT signing secret
};
identity?: {
typeIds?: {
admin: string; // Admin user type identifier
guest: string; // Guest user type identifier
regular: string; // Regular user type identifier
};
};
}

Configuration Details

The product service configuration is organized into logical groups for security and user type management.

🔐 Security Settings

authSecrets - JWT token security secrets

  • Type: { authEncSecret: string; authSignSecret: string }
  • Description: Secret keys for JWT encryption and signing (used for token validation)
  • Required: Yes (for production)
  • Child Properties:
    • authEncSecret: Secret key for JWT payload encryption
    • authSignSecret: Secret key for JWT signature verification

👥 User Type Settings

identity.typeIds - User type identifier configuration

  • Type: { admin?: string; guest?: string; regular?: string }
  • Description: Custom user type identifiers for role-based access control
  • Default: undefined (uses default type validation)
  • Child Properties:
    • admin: Admin user type identifier
      • Type: string
      • Description: Custom identifier for admin users
      • Use Case: Role-based access control for administrative operations
      • Example: "admin", "administrator", "superuser"
    • guest: Guest user type identifier
      • Type: string
      • Description: Custom identifier for guest users
      • Use Case: Limited access for unauthenticated or temporary users
      • Example: "guest", "visitor", "anonymous"
    • regular: Regular user type identifier
      • Type: string
      • Description: Custom identifier for regular users
      • Use Case: Standard user access permissions
      • Example: "user", "member", "customer"

Example Configuration

const productConfig = {
authSecrets: {
authEncSecret: process.env.AUTH_ENC_SECRET || 'your-enc-secret',
authSignSecret: process.env.AUTH_SIGN_SECRET || 'your-sign-secret'
},
identity: {
typeIds: {
admin: '100',
guest: '000',
regular: '001'
}
}
};

🚨 Error Handling

All product service errors return JSON format with appropriate HTTP status codes:

Common Error Codes

StatusError MessageDescription
400Validation ErrorInvalid request body format or missing required fields
400Failed to create productDatabase insert operation failed to return an inserted ID
400Failed to update productUpdate operation doesn't modify any data (no changes detected)
400Failed to create productsBatch creation operation failed
400Failed to update productsBatch update operation failed
400Failed to delete productsBatch deletion operation failed
400Failed to copy productProduct copy operation failed
400Failed to copy productsBatch copy operation failed
401token could not be verifiedMissing or invalid authorization token
403User is not authorized to access this resourceUser lacks required permissions (admin access)
404Product not foundProduct doesn't exist for the requested operation
500Failed to create productDatabase connection issues or unexpected failures during creation
500Failed to get productDatabase connection issues or unexpected failures during retrieval
500Failed to find productsDatabase connection issues, invalid filter syntax, or unexpected failures during listing
500Failed to update productDatabase connection issues or unexpected failures during update
500Failed to delete productDatabase connection issues or unexpected failures during deletion
500Failed to copy productDatabase connection issues or unexpected failures during copying

Error Response Format

{
"error": {
"message": "Error message description",
"data": ["Additional error details"]
}
}

Validation Errors include additional details:

{
"error": {
"message": "Validation Error",
"data": [
"request body must have required property 'name'",
"request body must have required property 'description'"
]
}
}