@axarai/axar
Version:
TypeScript-based agent framework for building agentic applications powered by LLMs
304 lines (303 loc) • 9.99 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.uniqueItems = exports.maxItems = exports.minItems = exports.integer = exports.exclusiveMaximum = exports.exclusiveMinimum = exports.multipleOf = exports.maximum = exports.minimum = exports.min = exports.max = exports.ip = exports.datetime = exports.cuid = exports.uuid = exports.pattern = exports.url = exports.email = exports.zodify = void 0;
exports.schema = schema;
exports.property = property;
exports.optional = optional;
exports.enumValues = enumValues;
exports.arrayItems = arrayItems;
const meta_keys_1 = require("./meta-keys");
const utils_1 = require("./utils");
const generator_1 = require("./generator");
/**
* Decorates a class for automatic schema generation using Zod.
* When applied, it generates and stores a Zod schema based on the class properties
* and their decorators.
*
* @param descriptionOrOptions - Either a description string or a SchemaOptions object
* @returns A class decorator
*
* @example
* ```typescript
* // Using string description
* @schema("User profile information")
* class UserProfile {
* @property("User's full name")
* name: string;
* }
*
* // Using SchemaOptions object
* @schema({
* description: "User profile information"
* })
* class UserProfile {
* @property("User's full name")
* name: string;
* }
* ```
*/
function schema(descriptionOrOptions = {}) {
return function (target) {
let options;
if (typeof descriptionOrOptions === 'string') {
options = { description: descriptionOrOptions };
}
else {
options = descriptionOrOptions;
}
Reflect.defineMetadata(meta_keys_1.META_KEYS.SCHEMA, options, target);
// Generate and store the Zod schema
const zodSchema = (0, generator_1.toZodSchema)(target);
Reflect.defineMetadata(meta_keys_1.META_KEYS.SCHEMA_DEF, zodSchema, target);
return target;
};
}
/** Alias for {@link schema} decorator, use if conflicts with Zod */
exports.zodify = schema;
/**
* Adds metadata to a class property. This can include descriptions and examples
* that will be included in the generated schema.
*
* @param descriptionOrOptions - Either a description string or a PropertyOptions object
* @returns A property decorator
*
* @example
* ```typescript
* class User {
* // Using string description
* @property("User's full name")
* name: string;
*
* // Using PropertyOptions object
* @property({
* description: "User's age in years",
* example: 25
* })
* age: number;
* }
* ```
*/
function property(descriptionOrOptions) {
return function (target, propertyKey) {
(0, utils_1.registerProperty)(target, propertyKey);
let options;
if (typeof descriptionOrOptions === 'string') {
options = { description: descriptionOrOptions };
}
else {
options = descriptionOrOptions;
}
Reflect.defineMetadata(meta_keys_1.META_KEYS.PROPERTY, options, target, propertyKey);
};
}
/**
* Marks a class property as optional in the generated schema.
* Optional properties can be undefined or omitted when creating instances.
*
* @returns A property decorator
*
* @example
* ```typescript
* class UserSettings {
* @optional()
* @description("Preferred theme (defaults to system)")
* theme?: 'light' | 'dark';
*
* @optional()
* @example("en-US")
* language?: string;
* }
* ```
*/
function optional() {
return function (target, propertyKey) {
(0, utils_1.registerProperty)(target, propertyKey);
Reflect.defineMetadata(meta_keys_1.META_KEYS.OPTIONAL, true, target, propertyKey);
};
}
/**
* Creates a validation decorator with proper type checking
* @param type - The type of validation rule
* @param params - Optional parameters for the validation rule
*/
function createValidationDecorator(type, params) {
return function (target, propertyKey) {
(0, utils_1.registerProperty)(target, propertyKey);
(0, utils_1.addValidationRule)(target, propertyKey, {
type,
params,
});
};
}
/**
* Decorates a property with enum validation
* @param values - Array of valid enum values
*
* @example
* ```typescript
* class User {
* @enumValues(['admin', 'user', 'guest'])
* role: string;
* }
* ```
*/
function enumValues(values) {
return function (target, propertyKey) {
if (!Array.isArray(values) || values.length === 0) {
throw new Error('Enum values must be a non-empty array');
}
(0, utils_1.registerProperty)(target, propertyKey);
Reflect.defineMetadata(meta_keys_1.META_KEYS.ENUM_VALUES, values, target, propertyKey);
(0, utils_1.addValidationRule)(target, propertyKey, {
type: 'enum',
params: [values],
});
};
}
/**
* Decorates an array property with item type information
* @param itemType - Function returning the item type
*
* @example
* ```typescript
* class PostList {
* @arrayItems(() => Post)
* items: Post[];
* }
* ```
*/
function arrayItems(itemType) {
return function (target, propertyKey) {
if (typeof itemType !== 'function') {
throw new Error('Item type must be a function returning a constructor');
}
(0, utils_1.registerProperty)(target, propertyKey);
Reflect.defineMetadata(meta_keys_1.META_KEYS.ARRAY_ITEM_TYPE, itemType, target, propertyKey);
};
}
/**
* Validates that a string property is a valid email address.
* @example
* ```ts
* class User {
* @email()
* email: string;
* }
* ```
*/
const email = () => createValidationDecorator('email');
exports.email = email;
/**
* Validates that a string property is a valid URL.
* @example `@url() website: string;`
*/
const url = () => createValidationDecorator('url');
exports.url = url;
/**
* Validates that a string property matches the given regular expression pattern.
* @param regex - The regular expression to test against
* @example `@pattern(/^[A-Z]{2}\d{3}$/) code: string;`
*/
const pattern = (regex) => createValidationDecorator('pattern', [regex]);
exports.pattern = pattern;
/**
* Validates that a string property is a valid UUID.
* @example `@uuid() id: string;`
*/
const uuid = () => createValidationDecorator('uuid');
exports.uuid = uuid;
/**
* Validates that a string property is a valid CUID.
* @example `@cuid() id: string;`
*/
const cuid = () => createValidationDecorator('cuid');
exports.cuid = cuid;
/**
* Validates that a string property is a valid ISO datetime string.
* @example `@datetime() createdAt: string;`
*/
const datetime = () => createValidationDecorator('datetime');
exports.datetime = datetime;
/**
* Validates that a string property is a valid IP address.
* @example `@ip() serverAddress: string;`
*/
const ip = () => createValidationDecorator('ip');
exports.ip = ip;
/**
* Validates that a string's length is at most the specified value.
* @param value - Maximum length allowed
* @example `@max(100) description: string;`
*/
const max = (value) => createValidationDecorator('max', [value]);
exports.max = max;
/**
* Validates that a string's length is at least the specified value.
* @param value - Minimum length required
* @example `@min(3) username: string;`
*/
const min = (value) => createValidationDecorator('min', [value]);
exports.min = min;
// Number validation decorators
/**
* Validates that a number is greater than or equal to the specified value.
* @param value - Minimum value allowed (inclusive)
* @example `@minimum(0) price: number;`
*/
const minimum = (value) => createValidationDecorator('minimum', [value]);
exports.minimum = minimum;
/**
* Validates that a number is less than or equal to the specified value.
* @param value - Maximum value allowed (inclusive)
* @example `@maximum(100) percentage: number;`
*/
const maximum = (value) => createValidationDecorator('maximum', [value]);
exports.maximum = maximum;
/**
* Validates that a number is a multiple of the specified value.
* @param value - The number must be divisible by this value
* @example `@multipleOf(5) quantity: number;`
*/
const multipleOf = (value) => createValidationDecorator('multipleOf', [value]);
exports.multipleOf = multipleOf;
/**
* Validates that a number is strictly greater than the specified value.
* @param value - Minimum value allowed (exclusive)
* @example `@exclusiveMinimum(0) positiveNumber: number;`
*/
const exclusiveMinimum = (value) => createValidationDecorator('exclusiveMinimum', [value]);
exports.exclusiveMinimum = exclusiveMinimum;
/**
* Validates that a number is strictly less than the specified value.
* @param value - Maximum value allowed (exclusive)
* @example `@exclusiveMaximum(100) score: number;`
*/
const exclusiveMaximum = (value) => createValidationDecorator('exclusiveMaximum', [value]);
exports.exclusiveMaximum = exclusiveMaximum;
/**
* Validates that a number is an integer (no decimal places).
* @example `@integer() age: number;`
*/
const integer = () => createValidationDecorator('integer');
exports.integer = integer;
// Array validation decorators
/**
* Validates that an array has at least the specified number of items.
* @param min - Minimum number of items required
* @example `@minItems(1) tags: string[];`
*/
const minItems = (min) => createValidationDecorator('minItems', [min]);
exports.minItems = minItems;
/**
* Validates that an array has at most the specified number of items.
* @param max - Maximum number of items allowed
* @example `@maxItems(10) selections: string[];`
*/
const maxItems = (max) => createValidationDecorator('maxItems', [max]);
exports.maxItems = maxItems;
/**
* Validates that all items in an array are unique.
* @example `@uniqueItems() categories: string[];`
*/
const uniqueItems = () => createValidationDecorator('uniqueItems');
exports.uniqueItems = uniqueItems;