@sequentialos/core
v1.0.1
Published
Core utilities package consolidating error-handling, param-validation, and response-formatting
Maintainers
Readme
@sequential/core
Core utilities package consolidating error-handling, param-validation, and response-formatting for the Sequential Ecosystem.
Status: Production-ready Version: 1.0.0 Type: ES Module
Overview
@sequential/core provides three main modules:
- Error Handling - Error serialization, categorization, logging, and detailed error responses
- Validation - Parameter validation, schema validation, file path security, and metadata validation
- Response Formatting - Standardized response formatting for success, errors, pagination, metrics, and batches
All modules follow consistent patterns and integrate seamlessly with Express.js applications.
Installation
npm install @sequential/coreModules
Error Handling (./error)
Error categorization, serialization, logging, and formatting.
Classes
SerializedError
Serializable error container that preserves error information across process boundaries.
import { SerializedError, serializeError } from '@sequential/core';
const err = new Error('Something went wrong');
const serialized = serializeError(err);
console.log(serialized.toJSON()); // { message, name, stack, code }Functions
serializeError(error)
Convert an Error to a SerializedError (idempotent).
const serialized = serializeError(error);
// Returns same instance if already SerializedErrornormalizeError(error)
Normalize any error-like value to SerializedError.
normalizeError(null) // returns null
normalizeError('string') // returns SerializedError
normalizeError({message: 'x'}) // returns SerializedError
normalizeError(new Error('x')) // returns SerializedErrorlogFileOperation(operation, filePath, error, context = {})
Log a file operation error with categorization and context.
import { logFileOperation, ErrorCategories } from '@sequential/core';
try {
await fs.readFile(path);
} catch (err) {
const log = logFileOperation('read', path, err, { userId: 123 });
// Returns: { timestamp, operation, category, filePath, error, context, severity }
}logFileSuccess(operation, filePath, duration = 0, metadata = {})
Log successful file operations with timing.
import { logFileSuccess } from '@sequential/core';
const startTime = Date.now();
await fs.writeFile(path, data);
const duration = Date.now() - startTime;
logFileSuccess('write', path, duration, { size: data.length });logBatchFileOperation(operation, fileCount, error, duration = 0)
Log batch operations affecting multiple files.
import { logBatchFileOperation } from '@sequential/core';
const startTime = Date.now();
try {
for (const file of files) {
await fs.unlink(file);
}
logBatchFileOperation('delete', files.length, null, Date.now() - startTime);
} catch (err) {
logBatchFileOperation('delete', files.length, err, Date.now() - startTime);
}createDetailedErrorResponse(operation, filePath, error, statusCode = 500)
Create detailed error response for API clients.
import { createDetailedErrorResponse } from '@sequential/core';
try {
await fileOperation(path);
} catch (err) {
const response = createDetailedErrorResponse('operation', path, err, 500);
// Returns: { error: { code, message, operation, filePath, timestamp, details } }
}ErrorCategories
Error categorization constants.
import { ErrorCategories } from '@sequential/core';
// FILE_NOT_FOUND, PERMISSION_DENIED, PATH_TRAVERSAL, INVALID_INPUT,
// FILE_TOO_LARGE, ENCODING_ERROR, DISK_SPACE, OPERATION_FAILED, UNKNOWNValidation (./validation)
Parameter and schema validation with security checks.
Functions
validateFilePath(filePath)
Validate file path with symlink protection and path traversal detection.
import { validation } from '@sequential/core';
const safePath = validation.validateFilePath(userProvidedPath);
// Throws if:
// - Path is invalid
// - Path traversal detected
// - Access deniedvalidateTaskName(taskName)
Validate task names (alphanumeric, dot, dash, underscore; max 100 chars).
import { validation } from '@sequential/core';
const name = validation.validateTaskName('my-task_v1.0');
// Throws if: invalid characters, too long, not a stringvalidateFileName(fileName)
Validate file names (no slashes, no leading dot; max 255 chars).
import { validation } from '@sequential/core';
const name = validation.validateFileName('document.pdf');
// Throws if: contains path separators, starts with dot, too longvalidateParam(value, name, type)
Simple parameter validation.
import { validation } from '@sequential/core';
const userId = validation.validateParam(req.params.userId, 'userId', 'string');
// Throws if required or wrong typevalidateRequired(...params)
Check multiple required parameters.
import { validation } from '@sequential/core';
validation.validateRequired(
{ name: 'email', value: req.body.email },
{ name: 'password', value: req.body.password }
);
// Throws if any are missingvalidateType(value, name, expectedType)
Type validation with error message.
import { validation } from '@sequential/core';
const age = validation.validateType(input.age, 'age', 'number');
// Throws: "age must be a number, got string"validateInputSchema(input, schema)
Validate input against schema definition.
import { validation } from '@sequential/core';
const schema = [
{ name: 'email', type: 'string', required: true },
{ name: 'age', type: 'number', required: false },
{ name: 'tags', type: 'array', required: false }
];
const errors = validation.validateInputSchema(input, schema);
if (errors) {
// errors is array of error messages
}validateAndSanitizeMetadata(metadata, maxSize = 10 * 1024 * 1024)
Validate metadata is JSON-serializable and within size limits.
import { validation } from '@sequential/core';
const safe = validation.validateAndSanitizeMetadata(metadata, 5 * 1024 * 1024);
// Throws if not an object, not serializable, or exceeds max sizeResponse Formatting (./response)
Standardized response formatting for APIs.
Functions
createErrorResponse(code, message, extra = {})
Format error response.
import { response } from '@sequential/core';
res.status(400).json(
response.createErrorResponse('INVALID_INPUT', 'Email is required', { field: 'email' })
);
// Returns: { error: { code, message, timestamp, ...extra } }createSuccessResponse(data, meta = {})
Format success response.
import { response } from '@sequential/core';
res.json(
response.createSuccessResponse({ id: 123, name: 'Alice' })
);
// Returns: { success: true, data, timestamp, ...meta }createPaginatedResponse(items, page, pageSize, total)
Format paginated response.
import { response } from '@sequential/core';
res.json(
response.createPaginatedResponse(items, 1, 10, 100)
);
// Returns: { success: true, data: items, pagination: { page, pageSize, total, pages }, timestamp }createMetricsResponse(metrics)
Format metrics response.
import { response } from '@sequential/core';
res.json(
response.createMetricsResponse({
requestCount: 1234,
avgResponseTime: 45.2,
errorRate: 0.02
})
);
// Returns: { success: true, metrics, timestamp }createListResponse(items, count = null)
Format list response.
import { response } from '@sequential/core';
res.json(
response.createListResponse(tasks)
);
// Returns: { success: true, data: items, count, timestamp }createBatchResponse(results, failed = [])
Format batch operation response.
import { response } from '@sequential/core';
res.json(
response.createBatchResponse(
[{ id: 1, ok: true }, { id: 2, ok: true }],
[{ id: 3, error: 'Not found' }]
)
);
// Returns: { success: true, processed, failed, results, failedItems, timestamp }formatErrorForResponse(error, statusCode = 500)
Format error with status code for Express responses.
import { response } from '@sequential/core';
try {
await operation();
} catch (err) {
const { statusCode, body } = response.formatErrorForResponse(err, 400);
res.status(statusCode).json(body);
}Common Patterns
Express Error Middleware
import { response } from '@sequential/core';
app.use((err, req, res, next) => {
const { statusCode, body } = response.formatErrorForResponse(err);
res.status(statusCode).json(body);
});File Operation with Logging
import { logFileSuccess, logFileOperation, createDetailedErrorResponse } from '@sequential/core';
import { validation } from '@sequential/core';
app.post('/api/files/upload', (req, res) => {
try {
const filePath = validation.validateFilePath(req.body.path);
const startTime = Date.now();
fs.writeFileSync(filePath, req.body.content);
logFileSuccess('upload', filePath, Date.now() - startTime);
res.json({ success: true, path: filePath });
} catch (err) {
const log = logFileOperation('upload', req.body.path, err);
const response = createDetailedErrorResponse('upload', req.body.path, err);
res.status(400).json(response);
}
});Input Validation
import { validation, response } from '@sequential/core';
app.post('/api/users', (req, res) => {
try {
validation.validateRequired(
{ name: 'email', value: req.body.email },
{ name: 'password', value: req.body.password }
);
const schema = [
{ name: 'email', type: 'string', required: true },
{ name: 'age', type: 'number', required: false }
];
const errors = validation.validateInputSchema(req.body, schema);
if (errors) {
return res.status(400).json(
response.createErrorResponse('VALIDATION_ERROR', 'Validation failed', { errors })
);
}
// Process valid input
res.json(response.createSuccessResponse(user));
} catch (err) {
res.status(400).json(response.createErrorResponse('INVALID_INPUT', err.message));
}
});Import Patterns
Root imports (error handling only)
import {
SerializedError,
serializeError,
normalizeError,
logFileOperation,
createDetailedErrorResponse,
ErrorCategories
} from '@sequential/core';Namespace imports (recommended)
import { validation, response } from '@sequential/core';
validation.validateFilePath(path);
response.createSuccessResponse(data);Submodule imports (for specific needs)
import * as errorHandling from '@sequential/core/error';
import * as validation from '@sequential/core/validation';
import * as response from '@sequential/core/response';API Stability
All exports are stable and production-ready:
- Error Handling: Stable - actively used in error-logging.test.js
- Validation: Stable - actively used across desktop-server routes
- Response Formatting: Stable - standardized HTTP response format
Dependencies
fs-extra: ^11.1.1 (for file system operations)
License
MIT
Contributing
When extending @sequential/core:
- Add new functions to appropriate module (error, validation, response)
- Export from module index.js
- Re-export from root src/index.js if top-level (error handling only)
- Add test cases and documentation
- Follow existing code style (no comments, explicit names, type validation)
Related Packages
@sequential/data-access-layer- Repository pattern with validation integration@sequential/task-execution-service- Task service using error and response utilities@sequential/dependency-injection- DI container for managing core utilities
