@bernierllc/validators-api
v0.3.0
Published
API validation - composite validator for REST APIs combining JSON structure, schema, pagination, and temporal consistency
Readme
@bernierllc/validators-api
API validation - composite domain validator for REST APIs combining JSON structure, schema, pagination, and temporal consistency.
Overview
The @bernierllc/validators-api package is a domain-level composite validator that orchestrates multiple primitive validators to provide comprehensive REST API validation. It follows the MECE (Mutually Exclusive, Collectively Exhaustive) architecture principles of the BernierLLC validators ecosystem.
Validation Coverage
- JSON Structure - Syntax, encoding, formatting, duplicate keys
- Schema Shape - Types, required fields, constraints, patterns
- Referential Integrity - Foreign keys, orphaned records, circular references
- Pagination Contract - Offset/cursor parameters, response structure
- Temporal Consistency - Timestamps, date ranges, ordering
- Security Headers - CSP, HSTS, X-Frame-Options, etc.
Installation
npm install @bernierllc/validators-apiUsage
Basic Validation
import { validateApi } from '@bernierllc/validators-api';
import { createSharedUtils } from '@bernierllc/validators-utils';
const utils = createSharedUtils();
const api = {
json: '{"users": [{"id": 1, "name": "Alice"}]}',
data: { users: [{ id: 1, name: 'Alice' }] },
schema: {
properties: {
users: {
type: 'array',
items: {
type: 'object',
properties: {
id: { type: 'number', required: true },
name: { type: 'string', required: true }
}
}
}
}
},
pagination: { limit: 10, offset: 0 },
headers: {
'Content-Security-Policy': "default-src 'self'",
'X-Frame-Options': 'DENY'
}
};
const result = await validateApi(api, {}, utils);
if (result.problems.length === 0) {
console.log('API is valid!');
} else {
console.log('Validation issues:', result.problems);
}Configured Validator
Create a reusable validator with specific options:
import { createApiValidator } from '@bernierllc/validators-api';
import { createSharedUtils } from '@bernierllc/validators-utils';
const utils = createSharedUtils();
const validator = createApiValidator({
validateJsonStructure: true,
validateSchema: true,
validatePagination: true,
validateHeaders: false, // Skip headers validation
paginationOptions: {
paginationType: 'cursor',
maxLimit: 100
}
});
const result = await validator.validate(api, utils);
console.log('Validation result:', result);
// Get validator metadata
const meta = validator.getMeta();
console.log('Validator:', meta.name);
console.log('Enabled rules:', meta.enabledRules);JSON Structure Validation
const api = {
json: '{"name": "test", "value": 123}'
};
const result = await validateApi(api, {
validateJsonStructure: true
}, utils);Schema Validation
const api = {
data: { name: 'Alice', age: 30 },
schema: {
properties: {
name: { type: 'string', required: true, min: 1 },
age: { type: 'number', min: 0, max: 150 }
}
}
};
const result = await validateApi(api, {
validateSchema: true
}, utils);Referential Integrity Validation
const api = {
referentialIntegrity: {
schemas: [
{
collection: 'users',
primaryKey: 'id',
foreignKeys: []
},
{
collection: 'posts',
primaryKey: 'id',
foreignKeys: [
{
sourceField: 'userId',
targetCollection: 'users',
targetField: 'id',
required: true,
onDelete: 'CASCADE'
}
]
}
],
documents: {
users: [{ id: 1, name: 'Alice' }],
posts: [{ id: 1, userId: 1, title: 'Hello' }]
}
}
};
const result = await validateApi(api, {
validateReferentialIntegrity: true
}, utils);Pagination Validation
// Offset-based pagination
const api = {
pagination: { limit: 20, offset: 0 }
};
const result = await validateApi(api, {
validatePagination: true,
paginationOptions: { paginationType: 'offset' }
}, utils);
// Cursor-based pagination
const api2 = {
pagination: { limit: 20, cursor: 'abc123' }
};
const result2 = await validateApi(api2, {
validatePagination: true,
paginationOptions: { paginationType: 'cursor' }
}, utils);Temporal Consistency Validation
const api = {
temporal: {
created_at: '2025-01-15T10:30:00Z',
updated_at: '2025-01-15T10:35:00Z',
start_date: '2025-01-15',
end_date: '2025-01-20'
}
};
const result = await validateApi(api, {
validateTemporal: true
}, utils);Security Headers Validation
const api = {
headers: {
'Content-Security-Policy': "default-src 'self'",
'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
'X-Frame-Options': 'DENY',
'X-Content-Type-Options': 'nosniff',
'Referrer-Policy': 'no-referrer'
}
};
const result = await validateApi(api, {
validateHeaders: true,
headerOptions: { strictMode: true }
}, utils);API
validateApi(api, options, utils)
Validates API content using configured primitive validators.
Parameters:
api(ApiContent) - API content to validateoptions(ApiValidationOptions) - Validation optionsutils(SharedUtils) - Shared validation utilities
Returns: Promise<ValidationResult>
createApiValidator(options)
Creates a configured API validator instance.
Parameters:
options(ApiValidationOptions) - Validator configuration
Returns: Validator object with validate() and getMeta() methods
Types
ApiContent
interface ApiContent {
json?: string; // Raw JSON string
data?: unknown; // Parsed data
schema?: Schema; // Schema definition
referentialIntegrity?: ReferentialIntegrityData;
pagination?: unknown; // Pagination params/response
temporal?: unknown; // Temporal data
headers?: Record<string, string | string[]>;
}ApiValidationOptions
interface ApiValidationOptions {
validateJsonStructure?: boolean; // Default: true
validateSchema?: boolean; // Default: true
validateReferentialIntegrity?: boolean; // Default: true
validatePagination?: boolean; // Default: true
validateTemporal?: boolean; // Default: true
validateHeaders?: boolean; // Default: true
severity?: 'error' | 'warn' | 'info'; // Default: 'error'
paginationOptions?: Partial<PaginationContractOptions>;
headerOptions?: Partial<HeaderPolicyOptions>;
}Architecture
This package is a domain-level composite validator that composes the following primitive validators:
@bernierllc/validators-json-structure- JSON syntax and structure@bernierllc/validators-schema-shape- Schema type validation@bernierllc/validators-referential-integrity- Data integrity@bernierllc/validators-pagination-contract- Pagination rules@bernierllc/validators-temporal-consistency- Temporal validation@bernierllc/validators-header-policy- Security headers
Following MECE principles, each primitive validator handles a specific concern, and this domain validator orchestrates them for complete API validation.
Integration Status
- Logger Integration: not-applicable - Validators are pure functions without side effects
- Docs-Suite: ready - Full markdown documentation with code examples
- NeverHub Integration: not-applicable - Validators operate in stateless validation mode with graceful degradation
This package follows the validators ecosystem pattern of pure validation functions that integrate seamlessly with any application architecture through explicit utility injection.
Integration
With Express.js
import express from 'express';
import { validateApi } from '@bernierllc/validators-api';
import { createSharedUtils } from '@bernierllc/validators-utils';
const app = express();
const utils = createSharedUtils();
app.get('/api/users', async (req, res) => {
const api = {
pagination: {
limit: parseInt(req.query.limit as string) || 10,
offset: parseInt(req.query.offset as string) || 0
}
};
const result = await validateApi(api, {
validatePagination: true
}, utils);
if (result.problems.length > 0) {
return res.status(400).json({ errors: result.problems });
}
// Proceed with request...
});With API Testing
import { validateApi } from '@bernierllc/validators-api';
import { createSharedUtils } from '@bernierllc/validators-utils';
describe('API Tests', () => {
const utils = createSharedUtils();
it('should validate API response', async () => {
const response = await fetch('/api/users?limit=10&offset=0');
const json = await response.text();
const data = JSON.parse(json);
const result = await validateApi({
json,
data,
pagination: { limit: 10, offset: 0 },
headers: Object.fromEntries(response.headers.entries())
}, {}, utils);
expect(result.problems).toHaveLength(0);
});
});Development
# Install dependencies
npm install
# Build
npm run build
# Test
npm test
# Lint
npm run lintLicense
Copyright (c) 2025 Bernier LLC. All rights reserved.
This package is part of the BernierLLC validators ecosystem following MECE architecture principles for composable, maintainable validation logic.
