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

@davidgoli/openapi-server-gen

v0.1.0

Published

Generate type-safe Effect HttpServer implementations from OpenAPI 3.1 specifications

Readme

@davidgoli/openapi-server-gen

Generate type-safe Effect HttpServer implementations from OpenAPI 3.1 specifications.

Features

  • Type Safe: Full TypeScript inference from OpenAPI spec to handler implementation
  • 🔧 Runtime Validation: Request/response validation powered by Effect Schema
  • 🎯 Clean Generated Code: Single file output, no manual editing required
  • 📦 OpenAPI 3.1: Full support for modern OpenAPI specifications
  • 🚀 Production Ready: Comprehensive test coverage with real-world API validation

What Gets Generated

From your OpenAPI spec, the generator creates:

  • Schema Definitions: Effect Schema representations of all your models
  • HTTP Endpoints: Fully typed HttpApiEndpoint definitions
  • API Groups: Organized by OpenAPI tags
  • Complete API: Single HttpApi export ready to implement

Installation

You can use the generator without installing via npx, or install it globally/locally:

# Use directly with npx (recommended)
npx @davidgoli/openapi-server-gen ./api-spec.yaml ./generated/api.ts

# Or install globally
pnpm add -g @davidgoli/openapi-server-gen

# Or add to project
pnpm add -D @davidgoli/openapi-server-gen

Quick Start

1. Generate Server Code

Run the generator with your OpenAPI spec:

# Using npx (no installation needed)
npx @davidgoli/openapi-server-gen ./api-spec.yaml ./generated/api.ts

# Or if installed globally
openapi-server-gen ./api-spec.yaml ./generated/api.ts

# Or via package.json script
pnpm openapi-server-gen ./api-spec.yaml ./generated/api.ts

This will generate a single TypeScript file with all your API definitions.

2. Implement Handlers

import { Effect, Layer } from "effect"
import { HttpApiBuilder } from "@effect/platform"
import { MyApi } from "./generated/api"

// Implement your handlers with full type safety
const UsersLive = HttpApiBuilder.group(MyApi, "users", (handlers) =>
  handlers
    // TypeScript knows the exact shape of path params, query params, body, etc.
    .handle("getUser", ({ path }) =>
      Effect.succeed({
        id: path.userId,
        name: "Alice",
        email: "[email protected]"
      })
    )
    .handle("createUser", ({ payload }) =>
      Effect.succeed({
        id: crypto.randomUUID(),
        name: payload.name,
        email: payload.email
      })
    )
)

const MyApiLive = HttpApiBuilder.api(MyApi).pipe(
  Layer.provide(UsersLive)
)

Examples

Check out the examples directory for complete, working examples:

  • Todo API - Full CRUD API with in-memory store, showing:
    • Path and query parameters
    • Request validation
    • Multiple status codes
    • Effect Services and Layers
    • Complete type safety

Each example includes a detailed README with code walkthrough and testing instructions.

Supported OpenAPI Features

HTTP Operations

  • All standard methods: GET, POST, PUT, PATCH, DELETE
  • Path parameters with type validation
  • Query parameters with validation rules
  • Header parameters with proper quoting
  • Request bodies (application/json)
  • Response schemas with multiple status codes

Schema Support

  • Components: Reusable schemas with $ref resolution
  • Nested Objects: Deep nesting and complex hierarchies
  • Arrays: Typed arrays with item validation
  • Circular References: Automatic detection and handling
  • Enums & Literals: Schema.Literal and Schema.Union generation
  • Nullable Types: Both OpenAPI 3.0 and 3.1 syntax
  • Schema Combinators:
    • allOfSchema.extend()
    • oneOf / anyOfSchema.Union()

Validation Rules

  • Strings: minLength, maxLength, pattern (regex), format (email, uuid, date-time, etc.)
  • Numbers: minimum, maximum, multipleOf, exclusive bounds
  • Arrays: minItems, maxItems
  • Objects: required fields, optional fields

API Organization

  • Tag-based grouping into HttpApiGroup
  • Server URL prefixes
  • operationId as endpoint identifiers
  • Deprecation annotations

Example Generated Code

Input: OpenAPI Spec

openapi: 3.1.0
info:
  title: Users API
  version: 1.0.0
paths:
  /users/{userId}:
    get:
      operationId: getUser
      tags: [users]
      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: User found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '404':
          description: User not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    User:
      type: object
      required: [id, name, email]
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
          minLength: 1
          maxLength: 100
        email:
          type: string
          format: email
    Error:
      type: object
      required: [code, message]
      properties:
        code:
          type: string
        message:
          type: string

Output: Generated TypeScript

import * as HttpApi from "@effect/platform/HttpApi"
import * as HttpApiEndpoint from "@effect/platform/HttpApiEndpoint"
import * as HttpApiGroup from "@effect/platform/HttpApiGroup"
import * as HttpApiSchema from "@effect/platform/HttpApiSchema"
import * as Schema from "effect/Schema"

// Schema definitions from components/schemas
const UserSchema = Schema.Struct({
  id: Schema.String,
  name: Schema.String.pipe(Schema.minLength(1), Schema.maxLength(100)),
  email: Schema.String
})

const ErrorSchema = Schema.Struct({
  code: Schema.String,
  message: Schema.String
})

// Endpoints
const userIdParam = HttpApiSchema.param("userId", Schema.String)
const getUser = HttpApiEndpoint.get("getUser")`/users/${userIdParam}`
  .addSuccess(UserSchema)
  .addError(ErrorSchema, { status: 404 })

const usersGroup = HttpApiGroup.make("users")
  .add(getUser)

const UsersAPI = HttpApi.make("UsersAPI")
  .add(usersGroup)

export { UsersAPI }

CLI Reference

# Basic usage
openapi-server-gen <spec-file> <output-file>

# Examples
openapi-server-gen ./api-spec.yaml ./generated/api.ts
openapi-server-gen ./petstore.json ./src/generated/petstore-api.ts

# With npx (no installation)
npx @davidgoli/openapi-server-gen ./api-spec.yaml ./generated/api.ts

Validation Features

The generator automatically creates validation rules from your OpenAPI schema:

String Validation

username:
  type: string
  minLength: 3
  maxLength: 20
  pattern: "^[a-zA-Z0-9_]+$"

username: Schema.String.pipe(
  Schema.minLength(3),
  Schema.maxLength(20),
  Schema.pattern(new RegExp("^[a-zA-Z0-9_]+$"))
)

Number Validation

age:
  type: integer
  minimum: 0
  maximum: 120

age: Schema.Number.pipe(
  Schema.greaterThanOrEqualTo(0),
  Schema.lessThanOrEqualTo(120)
)

Enum Types

status:
  type: string
  enum: [active, inactive, pending]

status: Schema.Union(
  Schema.Literal("active"),
  Schema.Literal("inactive"),
  Schema.Literal("pending")
)

Design Principles

  1. Generated Code is Read-Only: Never edit generated files manually - regenerate instead
  2. Single Source of Truth: Your OpenAPI spec is the source of truth
  3. Full Type Safety: TypeScript enforces correctness at compile time
  4. Effect-First: Leverages Effect's type system and error handling
  5. Validation Everywhere: Runtime validation powered by Effect Schema

Requirements

Your project needs:

  • Node.js 18+
  • TypeScript 5.0+

Generated code depends on:

  • effect ^3.17.0
  • @effect/platform ^0.87.0
  • @effect/platform-node ^0.82.0 (for NodeHttpServer)

Current Limitations

  • Content Types: Only application/json is currently supported
  • Security: Security schemes are parsed but authentication handlers must be implemented manually
  • Advanced Features: Webhooks, multipart/form-data, and cookie parameters are not yet supported

These features may be added in future versions based on user demand.

Contributing

Contributions are welcome! This project follows test-driven development:

  1. Write tests for new features first
  2. Implement the feature to make tests pass
  3. Ensure all existing tests still pass
  4. Run pnpm lint-fix and pnpm format before committing

Run tests with pnpm test or generate coverage with pnpm coverage.

License

MIT

Resources

See Also