
Research
/Security News
Popular Go Decimal Library Targeted by Long-Running Typosquat with DNS Backdoor
A long-running Go typosquat impersonated the popular shopspring/decimal library and used DNS TXT records to execute commands.
Dynamic and Adaptable Model Validator Using Zod, Interoperable with OpenAPI
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.
| Package | Description |
|---|---|
@adaptate/core | Schema transformation engine — make fields required based on config |
@adaptate/utils | OpenAPI ↔ Zod conversion, YAML spec loading with $ref resolution |
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 || ^4.0.0
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:
Adaptate solves this: define one schema with all fields optional, then use a config object to declare what each consumer requires.
There are two common ways to create a fully optional schema:
1. Using .deepPartial() (recommended)
import { z } from 'zod';
import { transformSchema, type Config } from '@adaptate/core';
const schema = z.object({
name: z.string(),
age: z.number(),
address: z.object({
street: z.string(),
city: z.string(),
}),
}).deepPartial();
const config = {
name: true,
age: true,
address: { city: true },
} satisfies Config<z.infer<typeof schema>>;
const updatedSchema = transformSchema(schema, config);
updatedSchema.parse({ name: 'Davin', age: 30, address: { city: 'Pettit' } }); // passes
updatedSchema.parse({ name: 'Davin', age: 30, address: { street: 'Main St' } }); // throws
2. Manual .optional() (still works)
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(),
});
// ... same config and usage as above
import { z } from 'zod';
import { makeConditionalSchemaTransformer } from '@adaptate/core';
const schema = z.object({
parentContactNumber: z.number().optional(),
age: z.number().optional(),
});
const config = {
parentContactNumber: { requiredIf: (data: any) => data.age < 18 },
age: true,
};
const data = { age: 17 };
const transformer = makeConditionalSchemaTransformer(data)(schema, config);
transformer.run(); // throws — parentContactNumber required because age < 18
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 { openAPISchemaToZod } from '@adaptate/utils';
const zodSchema = openAPISchemaToZod({
type: 'object',
required: ['age'],
properties: {
name: { type: 'string', minLength: 2 },
age: { type: 'integer', minimum: 0 },
},
});
Convert Zod to OpenAPI schema:
import { z } from 'zod';
import { zodToOpenAPISchema } from '@adaptate/utils';
const openAPISchema = zodToOpenAPISchema(
z.object({ name: z.string().min(2), age: z.number().int() })
);
See @adaptate/utils README for full documentation.
Compact & Powerful: The core transformation logic is intentionally compact — fewer than 100 lines of code. Complex nested transformations (deep objects, arrays with wildcards, conditional requirements) are handled elegantly through recursion. This keeps the API surface small while delivering sophisticated behavior with minimal cognitive overhead.
For a deeper dive, see DESIGN.md which covers:
This is a pnpm monorepo orchestrated with Turborepo.
Package manager: Use pnpm only when working in this repository (pnpm install). This repo’s install/build safety posture is defined for pnpm (.npmrc, pnpm-workspace.yaml: lifecycle restrictions, store integrity, release-age gates, etc.). npm install at the root is unsupported — npm ignores or mishandles several of those controls and may resolve dependencies differently than CI, weakening protections against supply-chain attacks that the config is meant to mitigate. Root package.json pins packageManager. The Installation section above (pnpm add / npm install for @adaptate/*) applies to consumers installing published packages from the npm registry.
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
├── .devcontainer/ # optional Dev Container (Node 24 + pnpm)
├── 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 and skills/ for development guidelines and operational procedures. Optional dev container: .devcontainer/README.md, .devcontainer/devcontainer.json.
This library recreates and generalizes a pattern originally observed at Oneflow AB, where the same data model was consumed by different components with varying required fields depending on context.
Development note: Initial prototype was created with ChatGPT Canvas. All important caveats and refinements were manually corrected by the author. The PR (#21) marks the first use of AI coding agents (Grok) in the project. Cursor Cloud Agent prepared the repo for agentic development workflows.
MIT
FAQs
Dynamic and Adaptable Model Validator Using Zod, Interoperable with OpenAPI
The npm package adaptate receives a total of 574 weekly downloads. As such, adaptate popularity was classified as not popular.
We found that adaptate demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

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.

Research
/Security News
A long-running Go typosquat impersonated the popular shopspring/decimal library and used DNS TXT records to execute commands.

Research
Active npm supply chain attack compromises @antv packages in a fast-moving malicious publish wave tied to Mini Shai-Hulud.

Security News
/Research
Socket detected malicious node-ipc versions with obfuscated stealer/backdoor behavior in a developing npm supply chain attack.