API validation - composite validator for REST APIs combining JSON structure, schema, pagination, and temporal consistency
npm install @bernierllc/validators-apiAPI validation - composite domain validator for REST APIs combining JSON structure, schema, pagination, and temporal consistency.
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.
- 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.
``bash`
npm install @bernierllc/validators-api
`typescript
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);
}
`
Create a reusable validator with specific options:
`typescript
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);
`
`typescript
const api = {
json: '{"name": "test", "value": 123}'
};
const result = await validateApi(api, {
validateJsonStructure: true
}, utils);
`
`typescript
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);
`
`typescript
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);
`
`typescript
// 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);
`
`typescript
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);
`
`typescript
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);
`
Validates API content using configured primitive validators.
Parameters:
- api (ApiContent) - API content to validateoptions
- (ApiValidationOptions) - Validation optionsutils
- (SharedUtils) - Shared validation utilities
Returns: Promise
Creates a configured API validator instance.
Parameters:
- options (ApiValidationOptions) - Validator configuration
Returns: Validator object with validate() and getMeta() methods
`typescript`
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
}
`typescript`
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
headerOptions?: Partial
}
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.
- 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.
`typescript
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...
});
`
`typescript
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);
});
});
`
`bashInstall dependencies
npm install
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.