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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@bernierllc/openapi-schema-builder

v1.0.1

Published

Pure atomic OpenAPI schema construction utilities with type safety for OpenAPI 3.0.x and 3.1.0

Downloads

107

Readme

@bernierllc/openapi-schema-builder

Pure atomic OpenAPI schema construction utilities with type safety for OpenAPI 3.0.x and 3.1.0.

Features

  • Type-Safe Schema Building - Full TypeScript support with strict typing
  • OpenAPI 3.0.x & 3.1.0 Support - Compatible with modern OpenAPI specifications
  • Zero Dependencies - Pure atomic package with no external dependencies
  • Comprehensive Validation - Built-in schema and component validation
  • Schema Type Builders - Convenient helpers for creating schema objects
  • Flexible API - Clean, intuitive builder pattern

Installation

npm install @bernierllc/openapi-schema-builder

Usage

Quick Start

import { OpenAPISchemaBuilder, SchemaTypes } from '@bernierllc/openapi-schema-builder';

const builder = new OpenAPISchemaBuilder();

// Create basic components
const info = builder.createInfo('My API', '1.0.0', 'A sample API');
const server = builder.createServer('https://api.example.com');

// Create a schema
const userSchema = SchemaTypes.object({
  id: SchemaTypes.integer({ minimum: 1 }),
  email: SchemaTypes.string({ format: 'email' }),
  name: SchemaTypes.string({ minLength: 1, maxLength: 100 })
}, ['id', 'email']); // Required fields

// Create an operation
const getUser = builder.createOperation('get', {
  summary: 'Get user by ID',
  parameters: [
    builder.createParameter('id', 'path', SchemaTypes.integer())
  ],
  responses: builder.createResponses({
    '200': builder.createResponse(
      'Success',
      builder.createJsonContent(userSchema)
    )
  })
});

API Reference

Core API

OpenAPISchemaBuilder

The main builder class for constructing OpenAPI components.

Constructor

const builder = new OpenAPISchemaBuilder({
  version: '3.0.3', // Optional: OpenAPI version (default: '3.0.3')
  strictValidation: true // Optional: Enable strict validation (default: true)
});

Info Object

const info = builder.createInfo(
  'Pet Store API',
  '1.0.0',
  'A sample API for pet store operations',
  {
    contact: {
      name: 'API Support',
      email: '[email protected]',
      url: 'https://example.com/support'
    },
    license: {
      name: 'MIT',
      url: 'https://opensource.org/licenses/MIT'
    },
    termsOfService: 'https://example.com/terms'
  }
);

Server Objects

// Simple server
const server = builder.createServer('https://api.example.com', 'Production server');

// Server with variables
const dynamicServer = builder.createServer(
  'https://{environment}.example.com',
  'Environment-specific server',
  {
    environment: {
      default: 'api',
      enum: ['api', 'staging', 'dev'],
      description: 'Server environment'
    }
  }
);

Path and Operation Objects

// Create a path with operations
const userPath = builder.createPath({
  get: builder.createOperation('get', {
    summary: 'Get user',
    operationId: 'getUser',
    tags: ['users'],
    parameters: [
      builder.createParameter('id', 'path', SchemaTypes.string(), {
        description: 'User ID',
        required: true
      })
    ],
    responses: builder.createResponses({
      '200': builder.createResponse('Success', builder.createJsonContent(userSchema)),
      '404': builder.createResponse('Not Found')
    })
  }),

  put: builder.createOperation('put', {
    summary: 'Update user',
    operationId: 'updateUser',
    requestBody: builder.createRequestBody(
      builder.createJsonContent(userSchema),
      true, // required
      'User object to update'
    ),
    responses: builder.createResponses({
      '200': builder.createResponse('Success'),
      '404': builder.createResponse('Not Found')
    })
  })
});

Parameters

// Path parameter
const pathParam = builder.createParameter('id', 'path', SchemaTypes.string(), {
  description: 'Resource ID',
  required: true // Path parameters are always required
});

// Query parameter
const queryParam = builder.createParameter('limit', 'query', SchemaTypes.integer(), {
  description: 'Maximum number of results',
  example: 10
});

// Header parameter
const headerParam = builder.createParameter('X-API-Key', 'header', SchemaTypes.string(), {
  description: 'API key for authentication'
});

Responses

// Simple response
const response = builder.createResponse('Success');

// Response with content
const jsonResponse = builder.createResponse(
  'User object',
  builder.createJsonContent(userSchema, { id: 1, email: '[email protected]', name: 'John' })
);

// Response with headers
const responseWithHeaders = builder.createResponse(
  'Success',
  builder.createJsonContent(userSchema),
  {
    'X-Rate-Limit': {
      name: 'X-Rate-Limit',
      in: 'header',
      schema: SchemaTypes.integer()
    }
  }
);

Security Schemes

// API Key
const apiKey = builder.createApiKeyScheme('X-API-Key', 'header', 'API key authentication');

// Bearer Token
const bearer = builder.createBearerScheme('JWT', 'JWT bearer token authentication');

// HTTP Basic
const basic = builder.createBasicScheme('HTTP basic authentication');

// OAuth2
const oauth2 = builder.createSecurityScheme('oauth2', {
  flows: {
    authorizationCode: {
      authorizationUrl: 'https://auth.example.com/authorize',
      tokenUrl: 'https://auth.example.com/token',
      scopes: {
        'read': 'Read access',
        'write': 'Write access',
        'admin': 'Admin access'
      }
    }
  }
});

Tags

const tag = builder.createTag(
  'users',
  'User management endpoints',
  builder.createExternalDocs('https://docs.example.com/users', 'User API Documentation')
);

Schema Type Builders

The SchemaTypes utility provides convenient methods for creating schema objects:

Primitive Types

import { SchemaTypes } from '@bernierllc/openapi-schema-builder';

// String
const name = SchemaTypes.string({
  minLength: 1,
  maxLength: 100,
  pattern: '^[a-zA-Z ]+$'
});

const email = SchemaTypes.string({
  format: 'email'
});

// Number
const price = SchemaTypes.number({
  minimum: 0,
  maximum: 99999.99,
  multipleOf: 0.01
});

// Integer
const age = SchemaTypes.integer({
  minimum: 0,
  maximum: 150
});

// Boolean
const isActive = SchemaTypes.boolean();

Complex Types

// Array
const tags = SchemaTypes.array(
  SchemaTypes.string(),
  { minItems: 1, maxItems: 10, uniqueItems: true }
);

// Object
const address = SchemaTypes.object({
  street: SchemaTypes.string(),
  city: SchemaTypes.string(),
  zipCode: SchemaTypes.string({ pattern: '^\\d{5}$' })
}, ['street', 'city']); // Required fields

// Nested objects
const user = SchemaTypes.object({
  id: SchemaTypes.integer({ minimum: 1 }),
  name: SchemaTypes.string({ minLength: 1 }),
  email: SchemaTypes.string({ format: 'email' }),
  address: address,
  tags: tags
}, ['id', 'name', 'email']);

Composition

// oneOf
const petType = SchemaTypes.oneOf([
  SchemaTypes.ref('Dog'),
  SchemaTypes.ref('Cat')
]);

// anyOf
const flexible = SchemaTypes.anyOf([
  SchemaTypes.string(),
  SchemaTypes.number()
]);

// allOf (inheritance)
const extendedUser = SchemaTypes.allOf([
  SchemaTypes.ref('BaseUser'),
  SchemaTypes.object({
    role: SchemaTypes.string({ enum: ['admin', 'user'] })
  })
]);

Enums and Nullability

// Enum
const status = SchemaTypes.enum(['active', 'inactive', 'pending'], 'string');

// Nullable
const optionalName = SchemaTypes.nullable(SchemaTypes.string());

References

// Short form (automatically prefixes with #/components/schemas/)
const userRef = SchemaTypes.ref('User');
// Results in: { $ref: '#/components/schemas/User' }

// Full path form
const customRef = SchemaTypes.ref('#/components/schemas/User');

Schema Utilities

import { schemaUtils } from '@bernierllc/openapi-schema-builder';

// Check if object is a reference
const isRef = schemaUtils.isReference({ $ref: '#/components/schemas/User' }); // true

// Merge schemas
const merged = schemaUtils.mergeSchemas(baseSchema, extensionSchema);

// Normalize reference
const normalized = schemaUtils.normalizeRef('#/components/schemas/User');

// Validate reference
const isValid = schemaUtils.validateReference('#/components/schemas/User', components);

// Generate example from schema
const example = schemaUtils.generateExample(userSchema);

// Get property names
const properties = schemaUtils.getPropertyNames(schema);

Validation

import { OpenAPISchemaBuilder } from '@bernierllc/openapi-schema-builder';

const builder = new OpenAPISchemaBuilder();

// Validate complete OpenAPI schema
const schema = {
  openapi: '3.0.3',
  info: { title: 'API', version: '1.0.0' },
  paths: {}
};

const result = builder.validateSchema(schema);
if (!result.valid) {
  console.error('Validation errors:', result.errors);
}

// Validate individual components
const componentResult = builder.validateComponent(userSchema, 'schemas');

Complete Example

import {
  OpenAPISchemaBuilder,
  SchemaTypes,
  type OpenAPIObject
} from '@bernierllc/openapi-schema-builder';

const builder = new OpenAPISchemaBuilder({ version: '3.0.3' });

// Define schemas
const userSchema = SchemaTypes.object({
  id: SchemaTypes.integer({ minimum: 1 }),
  username: SchemaTypes.string({ minLength: 3, maxLength: 20 }),
  email: SchemaTypes.string({ format: 'email' }),
  createdAt: SchemaTypes.string({ format: 'date-time' }),
  roles: SchemaTypes.array(SchemaTypes.string({ enum: ['admin', 'user', 'guest'] }))
}, ['id', 'username', 'email']);

const errorSchema = SchemaTypes.object({
  code: SchemaTypes.integer(),
  message: SchemaTypes.string()
}, ['code', 'message']);

// Build OpenAPI specification
const spec: OpenAPIObject = {
  openapi: '3.0.3',
  info: builder.createInfo(
    'User API',
    '1.0.0',
    'RESTful API for user management'
  ),
  servers: [
    builder.createServer('https://api.example.com', 'Production'),
    builder.createServer('https://staging-api.example.com', 'Staging')
  ],
  paths: {
    '/users': {
      get: builder.createOperation('get', {
        summary: 'List users',
        operationId: 'listUsers',
        tags: ['users'],
        parameters: [
          builder.createParameter('limit', 'query', SchemaTypes.integer({ minimum: 1, maximum: 100 }), {
            description: 'Maximum number of users to return'
          }),
          builder.createParameter('offset', 'query', SchemaTypes.integer({ minimum: 0 }), {
            description: 'Number of users to skip'
          })
        ],
        responses: builder.createResponses({
          '200': builder.createResponse(
            'Success',
            builder.createJsonContent(
              SchemaTypes.array(userSchema)
            )
          ),
          'default': builder.createResponse(
            'Error',
            builder.createJsonContent(errorSchema)
          )
        })
      }),
      post: builder.createOperation('post', {
        summary: 'Create user',
        operationId: 'createUser',
        tags: ['users'],
        requestBody: builder.createRequestBody(
          builder.createJsonContent(userSchema),
          true,
          'User to create'
        ),
        responses: builder.createResponses({
          '201': builder.createResponse(
            'Created',
            builder.createJsonContent(userSchema)
          ),
          '400': builder.createResponse(
            'Bad Request',
            builder.createJsonContent(errorSchema)
          )
        })
      })
    },
    '/users/{id}': {
      get: builder.createOperation('get', {
        summary: 'Get user by ID',
        operationId: 'getUserById',
        tags: ['users'],
        parameters: [
          builder.createParameter('id', 'path', SchemaTypes.integer({ minimum: 1 }))
        ],
        responses: builder.createResponses({
          '200': builder.createResponse(
            'Success',
            builder.createJsonContent(userSchema)
          ),
          '404': builder.createResponse('Not Found')
        })
      })
    }
  },
  components: {
    schemas: {
      User: userSchema,
      Error: errorSchema
    },
    securitySchemes: {
      bearerAuth: builder.createBearerScheme('JWT')
    }
  },
  security: [
    { bearerAuth: [] }
  ],
  tags: [
    builder.createTag('users', 'User management operations')
  ]
};

// Validate the specification
const validation = builder.validateSchema(spec);
if (validation.valid) {
  console.log('OpenAPI specification is valid!');
  console.log(JSON.stringify(spec, null, 2));
} else {
  console.error('Validation errors:', validation.errors);
}

TypeScript Support

This package is written in TypeScript and provides full type definitions:

import type {
  OpenAPIObject,
  InfoObject,
  PathItemObject,
  OperationObject,
  SchemaObject,
  ParameterObject,
  ResponseObject,
  SecuritySchemeObject
} from '@bernierllc/openapi-schema-builder';

Best Practices

1. Use Schema References

For reusable schemas, use the components section and references:

const userRef = SchemaTypes.ref('User');

// In operations
responses: builder.createResponses({
  '200': builder.createResponse(
    'Success',
    builder.createJsonContent(userRef)
  )
})

2. Validate Early

Validate your schemas during development:

const validation = builder.validateSchema(spec);
if (!validation.valid) {
  throw new Error(`Invalid OpenAPI spec: ${validation.errors.map(e => e.message).join(', ')}`);
}

3. Use Type Builders

Prefer SchemaTypes helpers over manual schema construction:

// Good
const email = SchemaTypes.string({ format: 'email' });

// Less ideal
const email = { type: 'string', format: 'email' };

4. Document Your API

Always provide descriptions for operations, parameters, and schemas:

const operation = builder.createOperation('get', {
  summary: 'Get user by ID',
  description: 'Retrieves a single user by their unique identifier',
  // ...
});

Error Handling

import { OpenAPISchemaError, ValidationError, ReferenceError } from '@bernierllc/openapi-schema-builder';

try {
  const normalized = schemaUtils.normalizeRef('invalid-ref');
} catch (error) {
  if (error instanceof ReferenceError) {
    console.error('Invalid reference:', error.reference);
  }
}

Integration Status

  • Logger Integration: Not applicable - This is a pure atomic utility package with no runtime behavior requiring logging. As a foundational schema builder with zero dependencies, logger integration is not needed.
  • Docs-Suite: Ready - TypeScript types and JSDoc documentation
  • NeverHub Integration: Not applicable - This is a pure atomic utility package providing schema construction functions. As a foundational package with no runtime orchestration or service communication, NeverHub integration via @bernierllc/neverhub-adapter is not needed.

Related Packages

This package is the foundation for:

  • @bernierllc/jsdoc-openapi-parser - Parse JSDoc to OpenAPI
  • @bernierllc/zod-openapi-converter - Convert Zod schemas to OpenAPI
  • @bernierllc/openapi-merger - Merge multiple OpenAPI specifications
  • @bernierllc/openapi-generator - Generate OpenAPI from code

License

Copyright (c) 2025 Bernier LLC. All rights reserved.

This package is proprietary software licensed for use only within the scope of the project it was delivered for.