npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

openapi-police

v5.0.1

Published

OpenAPI v3 validators and utilities

Readme

openapi-police

A powerful JavaScript library providing OpenAPI v3 validators and utilities for comprehensive API validation and compliance checking. Built on top of jsonpolice, it extends JSON Schema validation with OpenAPI-specific features like parameter style parsing and discriminator validation.

npm version CI Coverage Status

Features

  • OpenAPI v3 Compliance: Full support for OpenAPI 3.0+ and 3.1 specifications
  • Parameter Validation: Handle path, query, header, and cookie parameters with style parsing
  • Schema Extensions: OpenAPI-specific schema enhancements (discriminator, nullable, etc.)
  • Style Parsing: Support for parameter serialization styles (matrix, label, form, simple, etc.)
  • Format Validation: Extended format validation for OpenAPI types
  • TypeScript Support: Full TypeScript definitions included
  • Modern ES Modules: Supports both ESM and CommonJS
  • Built on jsonpolice: Leverages proven JSON Schema validation foundation with JSON Schema 2020-12 support

Installation

# npm
npm install openapi-police

# pnpm
pnpm add openapi-police

# yarn
yarn add openapi-police

Quick Start

Basic Schema Validation

import { SchemaObject } from 'openapi-police';

const schema = new SchemaObject({
  type: 'object',
  properties: {
    id: { type: 'string', format: 'uuid' },
    name: { type: 'string', nullable: true },
    tags: { 
      type: 'array', 
      items: { type: 'string' },
      uniqueItems: true 
    }
  },
  required: ['id']
});

try {
  const data = {
    id: '123e4567-e89b-12d3-a456-426614174000',
    name: null, // nullable is allowed
    tags: ['api', 'validation']
  };
  
  const validated = await schema.validate(data);
  console.log('Valid data:', validated);
} catch (error) {
  console.error('Validation failed:', error.message);
}

Parameter Validation with Style Parsing

import { ParameterObject } from 'openapi-police';

// Query parameter with simple style (comma-separated)
const queryParam = new ParameterObject({
  name: 'tags',
  in: 'query',
  required: true,
  schema: {
    type: 'array',
    items: { type: 'string' }
  },
  style: 'simple',
  explode: false
});

// Validate automatically parses the parameter style: ?tags=api,validation
const validated = await queryParam.validate('api,validation');
console.log(validated); // ['api', 'validation']

// Path parameter with simple style
const pathParam = new ParameterObject({
  name: 'userId',
  in: 'path',
  required: true,
  schema: { type: 'string', format: 'uuid' }
});

// Direct validation - parsing happens internally
await pathParam.validate('123e4567-e89b-12d3-a456-426614174000');

API Reference

SchemaObject / StaticSchemaObject

Extends standard JSON Schema with OpenAPI-specific features.

Constructors:

// For simple schemas without $ref
import { StaticSchemaObject } from 'openapi-police';
new StaticSchemaObject(schema)

// For schemas with $ref - requires jsonref
import { StaticSchemaObject } from 'openapi-police';
import * as refs from 'jsonref';
new StaticSchemaObject(await refs.parse(schema, options))

Parameters:

  • schema (object): OpenAPI Schema Object

Validation Options:

  • coerceTypes (boolean): Convert string values to the target type (default: false for SchemaObject, true for ParameterObject)
  • setDefault (boolean): Apply default values from schema
  • removeAdditional (boolean): Remove properties not in schema
  • context ('read' | 'write'): Validation context for readOnly/writeOnly

Features:

  • nullable: Allow null values in addition to specified type
  • discriminator: Polymorphism support with discriminator mapping
  • format: Extended format validation for OpenAPI types
  • readOnly/writeOnly: Context-aware validation

Example:

import { StaticSchemaObject } from 'openapi-police';

const schema = new StaticSchemaObject({
  type: 'string',
  nullable: true,
  format: 'email'
});

await schema.validate(null); // Valid (nullable)
await schema.validate('[email protected]'); // Valid (email format)
await schema.validate('invalid-email'); // Throws ValidationError

ParameterObject

Handles OpenAPI parameter validation with automatic style parsing.

Constructor:

new ParameterObject(parameter)

Parameters:

  • parameter (object): OpenAPI Parameter Object

Key Methods:

  • validate(data, options?, path?): Validates data and automatically parses parameter style
    • Automatically enables coerceTypes by default
    • Automatically parses style-encoded strings based on parameter schema type
    • Returns the validated and parsed data

Important Note: ⚠️ Do not call parseStyle() directly - it's an internal method. Use validate() which handles parsing automatically.

Supported Locations:

  • path - Path parameters (e.g., /users/{id})
  • query - Query string parameters (e.g., ?name=value)
  • header - HTTP header parameters
  • cookie - Cookie parameters

Style Support:

| Location | Supported Styles | Default | |----------|------------------|---------| | path | matrix, label, simple | simple | | query | simple, spaceDelimited, pipeDelimited, deepObject | simple | | header | simple, form, spaceDelimited, pipeDelimited | simple | | cookie | form, simple, spaceDelimited, pipeDelimited | form |

Note: The implementation differs from OpenAPI spec which specifies form as default for query parameters. This library uses simple for query arrays and deepObject for query objects.

Example:

import { ParameterObject } from 'openapi-police';

const param = new ParameterObject({
  name: 'filter',
  in: 'query',
  schema: {
    type: 'object',
    properties: {
      status: { type: 'string' },
      priority: { type: 'string' }
    }
  },
  style: 'deepObject',
  explode: true
});

// Validate: ?filter[status]=active&filter[priority]=high
const parsed = await param.validate('filter[status]=active&filter[priority]=high');
console.log(parsed); // { status: 'active', priority: 'high' }

MediaTypeObject

Handles validation for OpenAPI MediaType objects with content-type aware validation.

Constructor:

new MediaTypeObject(mediaType, contentType)

Parameters:

  • mediaType (object): OpenAPI MediaType Object
  • contentType (string): The content type (e.g., 'application/json')

Example:

import { MediaTypeObject } from 'openapi-police';

const mediaType = new MediaTypeObject({
  schema: {
    type: 'object',
    properties: {
      message: { type: 'string' }
    }
  }
}, 'application/json');

await mediaType.validate({ message: 'Hello' });

Usage Examples

Complex Schema with Discriminator

import { SchemaObject } from 'openapi-police';

const petSchema = new SchemaObject({
  discriminator: {
    propertyName: 'petType',
    mapping: {
      cat: '#/components/schemas/Cat',
      dog: '#/components/schemas/Dog'
    }
  },
  oneOf: [
    { $ref: '#/components/schemas/Cat' },
    { $ref: '#/components/schemas/Dog' }
  ]
});

// The discriminator will automatically select the correct schema
// based on the petType property value
const catData = {
  petType: 'cat',
  name: 'Fluffy',
  huntingSkill: 'excellent'
};

const validated = await petSchema.validate(catData);

Advanced Parameter Styles

import { ParameterObject } from 'openapi-police';

// Matrix style for path parameters
const matrixParam = new ParameterObject({
  name: 'coordinates',
  in: 'path',
  required: true,
  schema: {
    type: 'object',
    properties: {
      lat: { type: 'number' },
      lng: { type: 'number' }
    }
  },
  style: 'matrix',
  explode: true
});

// Validate with type coercion (strings → numbers)
// Input: ;lat=50.1;lng=8.7
const coords = await matrixParam.validate(';lat=50.1;lng=8.7');
console.log(coords); // { lat: 50.1, lng: 8.7 }
// Note: ParameterObject automatically enables coerceTypes

// Label style for path parameters
const labelParam = new ParameterObject({
  name: 'tags',
  in: 'path',
  required: true,
  schema: {
    type: 'array',
    items: { type: 'string' }
  },
  style: 'label',
  explode: false
});

// Validate with label style: .red.green.blue
const tags = await labelParam.validate('.red.green.blue');
console.log(tags); // ['red', 'green', 'blue']

Working with Headers and Cookies

import { ParameterObject } from 'openapi-police';

// Header parameter
const headerParam = new ParameterObject({
  name: 'X-API-Version',
  in: 'header',
  required: true,
  schema: {
    type: 'string',
    pattern: '^v\\d+$'
  }
});

await headerParam.validate('v1'); // Valid
await headerParam.validate('invalid'); // Throws ValidationError

// Cookie parameter with form style (default)
const cookieParam = new ParameterObject({
  name: 'session',
  in: 'cookie',
  schema: {
    type: 'object',
    properties: {
      userId: { type: 'string' },
      token: { type: 'string' }
    }
  },
  style: 'form',
  explode: false
});

// Validate cookie value: "session=userId,123,token,abc123"
const session = await cookieParam.validate('session=userId,123,token,abc123');
console.log(session); // { userId: '123', token: 'abc123' }

Type Validation with nullable

import { SchemaObject } from 'openapi-police';

const schema = new SchemaObject({
  type: 'integer',
  nullable: true,
  minimum: 0,
  maximum: 100
});

await schema.validate(null); // Valid (nullable)
await schema.validate(50); // Valid (integer in range)
await schema.validate(150); // Throws ValidationError (exceeds maximum)
await schema.validate('50'); // Throws ValidationError (wrong type)

Error Handling

openapi-police provides detailed validation errors:

import { SchemaObject, ParameterObject } from 'openapi-police';

try {
  const schema = new SchemaObject({
    type: 'object',
    properties: {
      email: { type: 'string', format: 'email' }
    },
    required: ['email']
  });
  
  await schema.validate({ email: 'invalid-email' });
} catch (error) {
  console.log(error.name); // 'ValidationError'
  console.log(error.message); // Detailed error description
  console.log(error.path); // JSON Pointer to invalid property
}

TypeScript Support

Full TypeScript definitions are included:

import { SchemaObject, ParameterObject } from 'openapi-police';

interface APIResponse {
  id: string;
  data: any;
  nullable?: string | null;
}

const responseSchema = new SchemaObject({
  type: 'object',
  properties: {
    id: { type: 'string', format: 'uuid' },
    data: {},
    nullable: { type: 'string', nullable: true }
  },
  required: ['id', 'data']
});

const validated: APIResponse = await responseSchema.validate(responseData);

Integration with OpenAPI Specifications

openapi-police is designed to work seamlessly with OpenAPI specifications:

import { SchemaObject, ParameterObject } from 'openapi-police';

// From OpenAPI spec
const openApiSpec = {
  paths: {
    '/users/{userId}': {
      get: {
        parameters: [
          {
            name: 'userId',
            in: 'path',
            required: true,
            schema: { type: 'string', format: 'uuid' }
          },
          {
            name: 'include',
            in: 'query',
            schema: {
              type: 'array',
              items: { type: 'string' }
            },
            style: 'simple',
            explode: false
          }
        ]
      }
    }
  }
};

// Create validators from spec
const pathParam = new ParameterObject(openApiSpec.paths['/users/{userId}'].get.parameters[0]);
const queryParam = new ParameterObject(openApiSpec.paths['/users/{userId}'].get.parameters[1]);

// Use in request validation
await pathParam.validate('123e4567-e89b-12d3-a456-426614174000');
await queryParam.validate('profile,settings,preferences');  // simple style: comma-separated

OpenAPI 3.1 Features

openapi-police now supports OpenAPI 3.1 specification features:

JSON Schema 2020-12 Support

OpenAPI 3.1 aligns with JSON Schema Draft 2020-12, providing enhanced validation capabilities:

import { SchemaObject } from 'openapi-police';

const schema = new SchemaObject({
  type: 'object',
  properties: {
    // OpenAPI 3.1 can specify the JSON Schema dialect
    name: { type: 'string' },
    tags: { 
      type: 'array',
      items: { type: 'string' },
      prefixItems: [{ const: 'primary' }] // JSON Schema 2020-12 feature
    }
  }
});

Webhooks Support

OpenAPI 3.1 introduces webhooks for describing incoming HTTP requests:

const openApiDoc = {
  openapi: '3.1.0',
  info: { title: 'Webhook API', version: '1.0.0' },
  paths: {},
  webhooks: {
    'newPet': {
      post: {
        requestBody: {
          content: {
            'application/json': {
              schema: {
                type: 'object',
                properties: {
                  id: { type: 'integer' },
                  name: { type: 'string' }
                }
              }
            }
          }
        },
        responses: {
          '200': { description: 'Webhook processed' }
        }
      }
    }
  }
};

Deep Object Parameter Style

Now supports the deepObject style for complex query parameters:

import { ParameterObject } from 'openapi-police';

const deepParam = new ParameterObject({
  name: 'filter',
  in: 'query',
  style: 'deepObject',
  explode: true,
  schema: {
    type: 'object',
    properties: {
      status: { type: 'string' },
      priority: { type: 'string' },
      category: { type: 'string' }
    }
  }
});

// Validate: ?filter[status]=active&filter[priority]=high&filter[category]=api
const parsed = await deepParam.validate('filter[status]=active&filter[priority]=high&filter[category]=api');
console.log(parsed); // { status: 'active', priority: 'high', category: 'api' }

// Note: deepObject style does not support array values - each key can only have one value
// If the same key appears multiple times, the last value overwrites previous ones

Parameter Content Validation

Enhanced support for parameter content validation:

import { ParameterObject } from 'openapi-police';

const contentParam = new ParameterObject({
  name: 'data',
  in: 'query',
  content: {
    'application/json': {
      schema: {
        type: 'object',
        properties: {
          filters: {
            type: 'array',
            items: { type: 'string' }
          },
          options: {
            type: 'object',
            properties: {
              limit: { type: 'integer', minimum: 1 },
              offset: { type: 'integer', minimum: 0 }
            }
          }
        }
      }
    },
    'application/xml': {
      schema: { type: 'string' }
    }
  }
});

// Validate with content type
const jsonData = { 
  filters: ['active', 'verified'],
  options: { limit: 10, offset: 0 }
};

await contentParam.validate(jsonData, { contentType: 'application/json' });

JSON Schema Dialect

OpenAPI 3.1 documents can specify their JSON Schema dialect:

const openApi31Doc = {
  openapi: '3.1.0',
  info: { title: 'Modern API', version: '2.0.0' },
  jsonSchemaDialect: 'https://json-schema.org/draft/2020-12/schema',
  paths: {
    '/items': {
      get: {
        parameters: [{
          name: 'search',
          in: 'query',
          schema: {
            type: 'object',
            patternProperties: {
              '^[a-zA-Z]+$': { type: 'string' }
            }
          }
        }]
      }
    }
  }
};

Validation Options

All validate methods accept an optional options parameter with the following properties:

Common Options:

  • coerceTypes (boolean): Automatically convert strings to target types (numbers, booleans, integers)
    • Default: false for SchemaObject, true for ParameterObject
  • setDefault (boolean): Apply default values from the schema
  • removeAdditional (boolean): Remove properties not defined in the schema
  • context ('read' | 'write'): Validation context for readOnly/writeOnly properties

ParameterObject Specific:

  • parseStyle (boolean): Enable/disable automatic parameter style parsing (default: true)
  • contentType (string): Specify content type for parameter content validation

Example:

import { StaticSchemaObject } from 'openapi-police';

const schema = new StaticSchemaObject({
  type: 'object',
  properties: {
    age: { type: 'integer' },
    name: { type: 'string', default: 'Anonymous' }
  }
});

// With type coercion and defaults
const data = await schema.validate(
  { age: '25' },
  { coerceTypes: true, setDefault: true }
);
console.log(data); // { age: 25, name: 'Anonymous' }

Troubleshooting

Common Issues

"style" Error with ParameterObject

  • This typically means you're using an incompatible style/type combination
  • Check the Style Support table to see which styles are supported for your parameter location
  • Verify your parameter schema type matches what the style expects

Type Validation Errors

  • By default, SchemaObject does NOT coerce types
  • For ParameterObject, set coerceTypes: true in options if you need string→number conversion
  • Remember: ParameterObject automatically enables coerceTypes by default

"Cannot find module" Errors

  • Make sure you're importing from 'openapi-police' not './dist/index.js'
  • Check that you're using ESM imports (import) not CommonJS (require)

Discriminator Validation Fails

  • Ensure your discriminator propertyName exists in the data
  • Verify the discriminator value matches one of the mapped schemas
  • For $ref resolution, consider using jsonref to parse your schemas first

Performance Tips

  1. Reuse validator instances - Create validators once and reuse them
  2. Leverage caching - Use shared registries for external schema references
  3. Validate early - Validate parameters and request bodies before processing
  4. Use appropriate styles - Choose the most efficient parameter style for your use case

Browser Support

openapi-police works in all modern browsers and Node.js environments. It requires:

  • ES2015+ support
  • Promise support
  • JSON.parse/JSON.stringify

License

MIT License - see the LICENSE file for details.

Contributing

Contributions are welcome! Please ensure all tests pass:

pnpm install
pnpm test
pnpm run coverage