
Product
Introducing Repository Access Permissions and Custom Roles
Socket now supports Custom Roles and Repository Access Permissions so organizations can control who can access specific repositories and actions.
@janus-validator/core
Advanced tools
A combinator library for defining validators that validate objects and provide examples
Core validation library for Janus Validator - composable validators that can both validate data and generate valid examples. Perfect for testing, API validation, and form handling.
# Core + DSL package (recommended)
npm install @janus-validator/core @janus-validator/dsl
# Or just core (no DSL)
npm install @janus-validator/core
This demonstrates usage without the DSL, although usable, it's generally recommended you use the DSL. They are functionally equivalent, just the syntax is shorter and cleaner.
import { Generator } from '@janus-validator/core';
import {
Struct,
UnicodeString,
Integer,
Boolean,
Regex,
} from '@janus-validator/core/combinators';
// Define a validator (core API)
const userValidator = Struct({
name: UnicodeString(1, 100),
age: Integer(0, 150),
email: Regex(/^[\w.]+@[\w.]+\.\w+$/),
active: Boolean(),
});
// Validate data
const result = userValidator.validate({
name: 'Alice',
age: 30,
email: 'alice@example.com',
active: true,
});
if (result.valid) {
console.log('Valid:', result.value);
} else {
console.log('Error:', result.error);
console.log('Example:', result.example); // Auto-generated valid example
}
// Generate test data
const generator = new Generator({ random: Math.random });
const testUser = generator.generate(userValidator.domain);
// { name: 'Alice', age: 42, email: 'test@example.com', active: true }
Janus validators can be used in both directions:
validator.validate(unknown) → ValidationResult<T>generator.generate(validator.domain) → TThis enables “round-trip” testing: anything generated by a validator should validate.
import { Generator } from '@janus-validator/core';
import { Struct, UnicodeString, Integer } from '@janus-validator/core/combinators';
const User = Struct({ name: UnicodeString(1, 50), age: Integer(0, 150) });
const generator = new Generator({ random: Math.random });
const sample = generator.generate(User.domain);
const result = User.validate(sample);
// result.valid === true
When validation fails, you get:
error: a path-based summary (e.g. profile.age: Value 999 is greater than maximum 150)results: a recursive structure showing which parts passed/failedexample: an auto-generated valid value for the failing validatorimport { Struct, UnicodeString, Integer } from '@janus-validator/core/combinators';
const Profile = Struct({ name: UnicodeString(1, 50), age: Integer(0, 150) });
const result = Profile.validate({ name: 'Alice', age: 999 });
if (!result.valid) {
result.error;
result.results; // per-field ValidationResult
result.example; // generated valid Profile
}
The DSL lives in a separate package: @janus-validator/dsl.
It provides short aliases (O, U, I, B, Or, Seq, …) plus primitive/enum auto-wrapping.
Generate realistic test data:
import {
FirstName, LastName, FullName,
RealisticEmail, CorporateEmailPreset,
RealisticUSPhone,
RealisticStreetAddress, RealisticCity, RealisticState, RealisticZipCode,
CompanyName, ProductName,
RecentDate, FutureDate,
RealisticPrice,
} from '@janus-validator/core/lib';
import { O } from '@janus-validator/dsl';
import { Generator } from '@janus-validator/core';
const generator = new Generator({ random: Math.random });
const customer = O({
name: FullName(), // "Alice Smith"
email: RealisticEmail(), // "alice.smith@gmail.com"
phone: RealisticUSPhone(), // "(555) 123-4567"
address: O({
street: RealisticStreetAddress(), // "1234 Oak St"
city: RealisticCity(), // "New York"
state: RealisticState(), // "NY"
zip: RealisticZipCode(), // "10001"
}),
});
const testCustomer = generator.generate(customer.domain);
Override default generation with custom logic:
import { fromValues, templateGenerator, withGenerator } from '@janus-validator/core/combinators';
import { U, I, R } from '@janus-validator/dsl';
// Generate from a fixed list
const country = fromValues(R(/^[A-Z]{2}$/), ['US', 'CA', 'GB', 'DE', 'FR']);
// Template-based generation
const sku = templateGenerator(U(10, 20), (pick, rng) => {
const categories = ['ELEC', 'FURN', 'CLTH'];
const num = Math.floor(rng.random() * 10000).toString().padStart(4, '0');
return `${pick(categories)}-${num}`;
});
// Generates: "ELEC-0042", "FURN-1337", etc.
// Custom generation function
const userId = withGenerator(I(1, 1000000), (rng) => {
return Math.floor(rng.random() * 1000000) + 1;
});
All DSL validators automatically include valid examples in error messages:
import { I } from '@janus-validator/dsl';
const age = I(18, 100);
const result = age.validate('not a number');
// result = {
// valid: false,
// error: 'Expected number, got string',
// example: 42 // Auto-generated valid example
// }
import { O, U, I, R, Or, Null } from '@janus-validator/dsl';
const createUserRequest = O({
username: R(/^[a-zA-Z][a-zA-Z0-9_]{2,19}$/),
email: R(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/),
password: U(8, 128),
profile: O({
firstName: U(1, 50),
lastName: U(1, 50),
age: Or(I(13, 150), Null()),
}),
});
// In your API handler
const result = createUserRequest.validate(req.body);
if (!result.valid) {
return res.status(400).json({ error: result.error });
}
import { O, U, R, createCaptureGroup } from '@janus-validator/dsl';
const { capture, ref, context } = createCaptureGroup();
const signupForm = O({
email: R(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/),
password: capture('pwd', U(8, 100)),
confirmPassword: ref('pwd'),
acceptTerms: true, // Must be true (auto-wrapped)
});
function validateForm(data: unknown) {
context.clear();
return signupForm.validate(data);
}
import { O, U, I, N, R, Or, oneOrMore } from '@janus-validator/dsl';
const orderItem = O({
productId: U(10, 50),
name: U(1, 200),
quantity: I(1, 100),
unitPrice: N(0.01, 100000),
});
const order = O({
orderId: R(/^ORD-\d{8}$/),
customerId: I(1, 1000000),
items: oneOrMore(orderItem),
subtotal: N(0, 1000000),
tax: N(0, 100000),
total: N(0, 1100000),
status: Or('pending', 'processing', 'shipped', 'delivered'), // Auto-wrapped!
createdAt: R(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/),
});
import { Generator } from '@janus-validator/core';
const rng = { random: Math.random };
const generator = new Generator(rng);
// Generate 100 test users
const testUsers = Array.from({ length: 100 }, () =>
generator.generate(userValidator.domain)
);
// Use in tests
describe('UserService', () => {
it('should create users', () => {
const user = generator.generate(userValidator.domain);
const created = userService.create(user);
expect(created.id).toBeDefined();
});
});
interface Validator<T> {
validate(input: unknown): ValidationResult<T>;
domain: Domain<T>;
}
type ValidationResult<T> =
| { valid: true; value: T }
| {
valid: false;
error: string;
example?: T;
results?: { [key: string]: ValidationResult<any> } | ValidationResult<any>[];
};
Helper types for working with validators:
import {
InferValidatorType, // Extract T from Validator<T>
UnionOfValidators, // [Validator<A>, Validator<B>] => A | B
TupleOfValidators, // [Validator<A>, Validator<B>] => [A, B]
ValidatorSchema, // { [key: string]: Validator<any> }
InferSchemaType, // { a: Validator<A> } => { a: A }
} from '@janus-validator/core';
// Example: Infer type from any validator
type UserType = InferValidatorType<typeof userValidator>;
class Generator {
constructor(rng: RNG);
generate<T>(validator: Validator<T>): T;
}
interface RNG {
random(): number; // Returns 0-1
}
MIT
FAQs
A combinator library for defining validators that validate objects and provide examples
The npm package @janus-validator/core receives a total of 3 weekly downloads. As such, @janus-validator/core popularity was classified as not popular.
We found that @janus-validator/core 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.

Product
Socket now supports Custom Roles and Repository Access Permissions so organizations can control who can access specific repositories and actions.

Product
Socket MCP now lets AI assistants review org alerts, investigate threats using the Socket threat feed, and inspect package files in addition to dependency scoring.

Product
Socket Firewall blocks malicious VS Code and Open VSX extensions before install, protecting developers from compromised editor marketplaces.