Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

adaptate

Package Overview
Dependencies
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

adaptate

Dynamic and Adaptable Model Validator Using Zod, Interoperable with OpenAPI

Source
npmnpm
Version
2.0.0
Version published
Weekly downloads
583
111.23%
Maintainers
1
Weekly downloads
 
Created
Source

Adaptate

Dynamic and Adaptable Model Validator Using Zod, Interoperable with OpenAPI

Coverage Badge

Overview

adaptate is a dynamic and adaptable model validator that leverages Zod for schema validation and is interoperable with OpenAPI. Define a single optional Zod schema for your data model, then use configuration objects to declare which fields each consumer requires — at runtime.

Packages

PackageDescription
@adaptate/coreSchema transformation engine — make fields required based on config
@adaptate/utilsOpenAPI ↔ Zod conversion, YAML spec loading with $ref resolution

Installation

pnpm add @adaptate/core
# or
npm install @adaptate/core

For OpenAPI utilities:

pnpm add @adaptate/utils
# or
npm install @adaptate/utils

Peer dependency: zod@^3.23.8

The Problem

In component-oriented applications, different components consume different subsets of the same data model. One component needs name and age, another needs address.city, and a third needs everything. The data often comes from different API endpoints with varying completeness.

Without runtime validation per consumer, you either:

  • Make everything optional (no safety)
  • Make everything required (breaks partial views)
  • Maintain separate schemas per component (duplication nightmare)

Adaptate solves this: define one schema with all fields optional, then use a config object to declare what each consumer requires.

Usage

Make Fields Required by Configuration

import { z } from 'zod';
import { transformSchema } from '@adaptate/core';

const schema = z.object({
  name: z.string().optional(),
  age: z.number().optional(),
  address: z.object({
    street: z.string().optional(),
    city: z.string().optional(),
  }).optional(),
});

const config = {
  name: true,
  age: true,
  address: {
    city: true,
  },
};

const updatedSchema = transformSchema(schema, config);

updatedSchema.parse({
  name: 'Davin',
  age: 30,
  address: { city: 'Pettit' },
}); // passes

updatedSchema.parse({
  name: 'Davin',
  age: 30,
  address: { street: 'First Avenue' },
}); // throws — required city is missing

Conditional Requirements

Make fields required based on runtime data
import { z } from 'zod';
import { makeConditionalSchemaTransformer } from '@adaptate/core';

const schema = z.object({
  firstName: z.string().optional(),
  secondName: z.string().optional(),
  parentContactNumber: z.number().optional(),
  age: z.number().optional(),
  address: z.object({
    street: z.string().optional(),
    city: z.string().optional(),
  }).optional(),
  title: z.string().optional(),
});

const config = {
  parentContactNumber: {
    requiredIf: (data: any) => data.age < 18,
  },
  age: true,
  secondName: (data: any) => !!data.firstName,
};

const data = { firstName: 'Mario', age: 17 };
const conditionalTransformer = makeConditionalSchemaTransformer(data);
const transformer = conditionalTransformer(schema, config);

transformer.run(); // throws — parentContactNumber is required (age < 18)

OpenAPI ↔ Zod Conversion

Convert OpenAPI schemas to Zod and back

Load and dereference an OpenAPI spec:

import { getDereferencedOpenAPIDocument } from '@adaptate/utils';

const doc = await getDereferencedOpenAPIDocument({
  location: 'filesystem',
  callSiteURL: import.meta.url,
  relativePathToSpecFile: './api-spec.yml',
});

Convert OpenAPI schema to Zod:

import { incomplete_openAPISchemaToZod } from '@adaptate/utils';

const zodSchema = incomplete_openAPISchemaToZod({
  type: 'object',
  required: ['age'],
  properties: {
    name: { type: 'string' },
    age: { type: 'number' },
  },
});

Convert Zod to OpenAPI schema:

import { z } from 'zod';
import { incomplete_zodToOpenAPISchema } from '@adaptate/utils';

const openAPISchema = incomplete_zodToOpenAPISchema(
  z.object({ name: z.string(), age: z.number() })
);

See @adaptate/utils README for full documentation.

Development

This is a pnpm monorepo orchestrated with Turborepo.

Requirements: Node.js ≥ 20, pnpm 9.12.3

pnpm install          # Install dependencies
pnpm build            # Full pipeline: check-types → test → build
pnpm test             # Run Vitest in watch mode
npx vitest run        # Single test run
npx turbo run check-types  # TypeScript type checking

Project Structure

├── packages/
│   ├── core/         # @adaptate/core — schema transformation
│   └── utils/        # @adaptate/utils — OpenAPI utilities
├── skills/           # Tool-agnostic agent SOPs
├── AGENTS.md         # Agent guidelines
├── CODING_STYLE.md   # Coding conventions
└── turbo.json        # Turborepo task graph

See AGENTS.md for full development guidelines and skills/ for operational procedures.

Credits

Background and motivation

This library recreates and generalizes a pattern from Oneflow AB, where a component used on two different pages received data from different endpoints. The same model had different required fields depending on context. A runtime validation layer with component-specific configs prevented breakage without duplicating schemas.

The initial implementation was prototyped with ChatGPT Canvas — an exercise in testing code generators on recursive Zod schema traversal. The key insight: generators initially used .required() (a ZodObject method) instead of .unwrap() (strips optionality) — a subtle bug in recursive contexts.

Full conversation with ChatGPT Canvas

License

MIT

Keywords

Zod

FAQs

Package last updated on 05 May 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts