
Security News
Agent Baseline Publishes Security Reference Architecture for Software Factories
Agent Baseline’s new reference architecture shows how to secure software factories with four boundaries enforced outside the AI agent.
Vite plugin for ata-validator: schemas become validators and TypeScript types at build time, with no compiler in the bundle.
Vite plugin that compiles schema files into self-contained ata-validator modules plus TypeScript declarations. Build time instead of runtime, a few KB gzipped per schema (1.4 KB for a small one, 4.8 KB for a ten-field one with full error detail), full type narrowing via isValid.
Schemas can be authored as .json, .js, or .ts.
Since 0.5.0 this package is the Vite entry of @ata-project/unplugin, which does the same for Webpack, Rollup, Rolldown, esbuild and Rspack from one implementation. Nothing changes for Vite users; projects on another bundler install @ata-project/unplugin directly.
npm install --save-dev ata-vite ata-validator
ata-validator is a peer dependency.
.schema.json conventionName a schema user.schema.json and import a typed, zero-dependency validator
by its name:
import validate, { type User, isValid } from './user.schema'
const r = validate(input)
if (r.valid) {
// input matched the schema
}
if (isValid(input)) {
input.id // narrowed to User
}
The plugin generates user.schema.js (the zero-dependency validator) and
user.schema.d.ts (the types) next to the schema. The default export is the
validate function; validate, isValid, and the inferred type are also named
exports. The type name comes from the schema's title, then its $id, then the
file name.
The function default applies to ESM output. With format: 'cjs' the convention emits .cjs / .d.cts and the default stays the { validate, isValid } object.
moduleResolution: bundler and classic node resolve ./user.schema
directly. With node16/nodenext, import ./user.schema.js.
The default glob is **/*.schema.json (excluding node_modules). Other source
extensions (.json without the .schema suffix, .js, .ts) keep the
<name>.validator.mjs output.
Add the generated files to .gitignore:
*.schema.js
*.schema.d.ts
A schema with additionalProperties: false produces a strict, closed type;
otherwise the type carries an index signature, matching JSON Schema's default
that extra keys are allowed.
// vite.config.ts
import { defineConfig } from 'vite'
import ata from 'ata-vite'
export default defineConfig({
plugins: [
ata({
schemas: 'schemas/**/*.json',
// outDir: 'src/generated', // optional; defaults to next to each input
}),
],
})
For every matched <name>.json the plugin writes:
<name>.validator.mjs - self-contained validator, no runtime dependency on ata-validator<name>.validator.d.mts - TypeScript declaration with an isValid type predicateImport from your app:
import { isValid, validate, type User } from './schemas/user.validator.mjs'
export function handle(input: unknown) {
if (isValid(input)) {
// TypeScript narrows `input` to User here
return { ok: true, id: input.id, role: input.role }
}
return { ok: false, errors: validate(input).valid ? [] : validate(input).errors }
}
Point schemas at any mix of .json, .js, and .ts files:
ata({ schemas: 'schemas/**/*.{json,js,ts}' })
JSON stays the default and is read as inert text. JS and TS modules export the
schema as the default export (a named schema export also works):
// schemas/user.ts
export default {
type: 'object',
properties: {
id: { type: 'integer', minimum: 1 },
role: { type: 'string', enum: ['admin', 'user'] },
},
required: ['id'],
} as const
On ata-validator 0.16.0 or newer you can wrap the object in defineSchema for
keyword autocomplete and value checking while authoring, instead of as const:
// schemas/user.ts
import { defineSchema } from 'ata-validator'
export default defineSchema({
type: 'object',
properties: { id: { type: 'integer', minimum: 1 } },
required: ['id'],
})
Authoring in JS or TS lets you add comments, share constants across schemas, and
compose with plain code, which JSON cannot do. TS is loaded through
jiti so it works without a separate build step
on every supported Node version. jiti ships as a dependency and is loaded only
when a .ts file is actually compiled, so JSON- and JS-only projects pay nothing
for it.
A .ts schema can import shared fragments through path aliases. Both your
tsconfig compilerOptions.paths and your Vite resolve.alias entries are
resolved:
// schemas/user.ts
import { idField } from '#shared/fields' // tsconfig paths
import { email } from '@/schemas/common' // vite resolve.alias
export default {
type: 'object',
properties: { id: idField, email },
required: ['id'],
}
Aliases apply to .ts only. .js schemas are loaded by native import, which has
no notion of aliases, so use relative paths there. Vite aliases defined with a
RegExp find are skipped, since only string aliases map to the loader.
You can also extend a base JSON schema from a JS or TS file, which is handy for sharing one shape across several variants:
// schemas/admin.ts
import user from './user.json' with { type: 'json' }
user.properties.role = { type: 'string', const: 'admin' }
export default user
One thing to know: JS and TS schemas execute at build time, the same as your
vite.config. JSON does not run code, so keep using it when a schema is fully
static and untrusted.
ata({
schemas: 'schemas/**/*.json', // glob or array of globs, relative to Vite root
outDir: null, // null = alongside each input; or a folder like 'src/generated'
format: 'esm', // 'esm' | 'cjs'
abortEarly: false, // true = stub errors, smallest output
types: true, // false to skip .d.mts / .d.cts
nameFromFile: (file) => string // customize the TS type name derived from filename
})
abortEarlyReplaces the detailed error collector in the generated validator with a shared stub. Output drops from 2.3 KB gzipped to 1.7 KB gzipped on a typical 10-field schema, measured on ata-validator 1.36.0. Use it when the caller only needs a boolean reject/accept decision.
compileAwayOn by default; compileAway: false turns it off. A new Validator(schema) in your code whose schema is known at build time is replaced with a validator compiled at build time, and the runtime compiler leaves the bundle while the code keeps calling validate(), isValidObject(), validateJSON() and isValidJSON() with the same answers. Code that only calls isValidObject() or isValidJSON() gets a smaller wrapper without the error machinery, and withKeywords(new Validator(schema)) from @ata-project/keywords is compiled too, as are schemas written with the t builder from ata-validator/t. A small app bundles to 2.6 KB gzipped when it only asks for a boolean and 12.1 KB when it reads errors, against 102.0 KB with the runtime, on ata-validator 1.40.0. The rules for which calls are replaced are in the @ata-project/unplugin README.
outDirBy default the output lands next to each input file. Pass a directory to relocate everything to <outDir>/<mirrored input path>/<base>.validator.*. Easier to .gitignore when you do not want generated files checked in.
If the generated content matches what is already on disk, the file is not rewritten. TypeScript watch and Vite HMR stay quiet during no-op rebuilds.
Useful in custom build scripts outside Vite.
import { compile } from 'ata-vite'
await compile({
schemas: 'schemas/**/*.json',
outDir: 'src/generated',
abortEarly: true,
root: process.cwd(),
})
Returns { files, results } where results[i].changed indicates whether the output file was actually rewritten.
Each matched schema is compiled via new Validator(schema).toStandaloneModule(...) and toTypeScript(schema, { name }) from ata-validator. No subprocess, no CLI wrapper. The plugin hooks:
configResolved - resolve Vite root and loggerbuildStart - compile every matched schemahandleHotUpdate - recompile on file change in dev modewatchChange - same, for rollup-style watch contexts outside a dev serverMIT
FAQs
Vite plugin for ata-validator: schemas become validators and TypeScript types at build time, with no compiler in the bundle.
We found that ata-vite 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.

Security News
Agent Baseline’s new reference architecture shows how to secure software factories with four boundaries enforced outside the AI agent.

Security News
arXiv now limits authors to two submissions a month as AI slop overwhelms moderators, delays good papers, and sparks debate over applying the limit to everyone.

Research
/Security News
A new GhostAction wave hits hundreds of GitHub repos, expanding CI/CD secret theft to cloud and AI credentials in source code and git history.