zod-to-x
Version:
Multi language types generation from Zod schemas.
385 lines (384 loc) • 16.2 kB
TypeScript
import { ASTAliasedTypes, ASTEnum, ASTIntersection, ASTNode, ASTObject, ASTUnion, Zod2X } from "../../core";
import { IZod2CppOpt } from "./options";
/**
* @description Transpiler for Zod schemas to C++11 code.
*/
export declare class Zod2Cpp extends Zod2X<IZod2CppOpt> {
protected readonly commentKey = "//";
protected serializers: string[];
protected useBoost: boolean;
protected lib: {
exceptions: string;
integers: string;
map: string;
nlohmann: string;
set: string;
string: string;
tuple: string;
vector: string;
optional: string;
variant: string;
};
constructor(opt?: IZod2CppOpt);
protected getIntersectionType: () => string;
protected runBefore(): void;
protected addImportFromFile(filename: string, _: string): string;
protected getTypeFromExternalNamespace(namespace: string, typeName: string): string;
protected addExtendedType(name: string, parentNamespace: string, aliasOf: string, opt?: {
type?: "union" | "alias";
isInternal?: boolean;
templates?: string;
templateDefinition?: string;
templateList?: string;
}): void;
protected getGenericTemplatesTranslation(data: ASTNode): string | undefined;
/**
* Emits an alias/extension declaration early for layered references.
* It keeps concrete template translations and falls back to declared templates (e.g. <T>)
* for aliases of generic templates.
*/
protected checkExtendedTypeInclusion(data: ASTNode, type?: "union" | "alias"): boolean;
protected runAfter(): void;
protected getDateType: () => string;
protected getBooleanType: () => string;
protected getStringType: () => string;
/** Ex: std::tuple<TypeA, TypeB, ...> */
protected getTupleType: (itemsType: string[]) => string;
protected getAnyType: () => string;
/** Ex: std::set<TypeA> */
protected getSetType: (itemType: string) => string;
/** Ex: boost::variant<TypeA, TypeB> */
protected getUnionType: (itemsType: string[]) => string;
/** Ex: depends on number range (if any). One of:
* - std::uint32_t
* - std::uint64_t
* - std::int32_t
* - std::int64_t
* - double
*/
protected getNumberType: (isInt: boolean, range: {
min?: number;
max?: number;
}) => string;
/** Ex: std::vector<std::vector<TypeA>> */
protected getArrayType(arrayType: string, arrayDeep: number): string;
protected getLiteralStringType(value: string | number | boolean, parentEnumNameKey?: [string, string]): string;
/** Ex: std::unordered_map<TypeA> */
protected getMapType(keyType: string, valueType: string): string;
protected getRecordType(keyType: string, valueType: string): string;
protected _getOptional(type: string): string;
protected _addExtendedTypeSerializer(typeName: string, parentNamespace: string, opt?: {
templateDefinition?: string;
templateList?: string;
}): void;
protected _addExtendedTypeDeserializer(typeName: string, parentNamespace: string, opt?: {
templateDefinition?: string;
templateList?: string;
}): void;
protected transpileAliasedType(data: ASTAliasedTypes): void;
/** Ex:
* enum class EnumA: int {
* Item1,
* Item2
* }
*/
protected transpileEnum(data: ASTEnum): void;
/** Ex:
* - Case of using classes:
* class MyClassC: public MyClassA, public MyClassB {
* public:
* MyClassC() = default;
* virtual ~MyClass() = default;
* }
*
* - Case of using structs
* struct MyStructC: public MyStructA, public MyStructB {
*
* }
*/
protected transpileIntersection(data: ASTIntersection): void;
/** Ex: using TypeC = boost::variant<TypeA, TypeB> */
protected transpileUnion(data: ASTUnion): void;
protected transpileStruct(data: ASTObject): void;
private _getTemplates;
/** Ex:
* struct MyStruct {
* TypeA attribute1;
* TypeB attribute2;
* }
*/
private _transpileStructAsStruct;
/** Ex:
* class MyClass {
* private:
* TypeA attribute1;
* TypeB attribute2;
*
* public:
* MyClass() = default;
* virtual ~MyClass() = default;
*
* const TypeA& get_attribute1() const { return this->attribute1; }
* TypeA& get_mut attribute1() { return this->attribute1; }
* void set_attribute1(TypeA& value) { this->attribute1 = value; }
* [...]
* }
*/
private _transpileStructAsClass;
/**
* @description Transpiles an individual member of a C++ class based on the provided ASTNode.
*
* @param memberName - The name of the member variable to transpile.
* @param memberNode - The ASTNode defining the member's type, description, and other
* attributes.
*
* @returns - The original C++ type of the member, without optional modifier.
*/
private _transpileMember;
/**
* @description Creates getter and setter enumHelpers for a C++ class member variable.
*
* @param memberName - The name of the member variable.
* @param memberType - The C++ type of the member variable.
* @param [required] - Whether the member is required (default is `false`).
*
* @returns - An array of strings representing the C++ getter and setter enumHelpers.
*/
private _createSetterGetter;
/**
* @description Generates a JSON serializer for a struct. Each required field is serialized
* directly, and optional fields are checked for existence before serialization.
* Ex:
* inline void to_json(nlohmann::json& j, const MyStruct& x) {
* j["requiredField"] = x.required_field;
* if (x.optional_field) {
* j["optionalField"] = x.optional_field;
* }
* }
* @param parent - Name of the serialized structure
* @param childs - Structure attributes data.
* @param templates - Generic templates string (if any)
*/
private _createStructSerializer;
/**
* @description Generates a JSON deserializer for a struct. Each required field is deserialized
* using at, while optional fields are handled with get_opt.
* Ex:
* inline void from_json(const nlohmann::json& j, MyStruct& x) {
* x.required_field(j.at("requiredField").get<int>());
* x.optional_field(get_opt<std::string>(j, "optionalField"));
* }
* @param parent - Name of the deserialized structure
* @param childs - Structure attributes data.
* @param templates - Generic templates string (if any)
*/
private _createStructDeserializer;
/**
* @description Generates a JSON serializer for a class. The serializer uses getter methods to
* access class attributes. Optional fields are checked for existence before
* serialization.
* Ex:
* inline void to_json(nlohmann::json& j, const MyClass& x) {
* j["requiredField"] = x.get_required_field();
* if (x.get_optional_field()) {
* j["optionalField"] = x.get_optional_field();
* }
* }
* @param parent - Name of the serialized structure
* @param childs - Structure attributes data.
* @param templates - Generic templates string (if any)
*/
private _createClassSerializer;
/**
* @description Generates a JSON deserializer for a class. The deserializer uses setter methods
* to populate class attributes.
* Ex:
* inline void from_json(const nlohmann::json& j, MyClass& x) {
* x.set_required_field(j.at("requiredField").get<int>());
* x.set_optional_field(get_opt<std::string>(j, "optionalField"));
* }
* @param parent - Name of the deserialized structure
* @param childs - Structure attributes data.
* @param templates - Generic templates string (if any)
*/
private _createClassDeserializer;
/**
* @description Generates a JSON serializer for an enum. Maps enum values to strings for
* serialization, with a default case for unexpected values.
* Ex:
* inline void to_json(nlohmann::json& j, const MyEnum& x) {
* switch (x) {
* case MyEnum::Value1: j = "VALUE_1"; break;
* case MyEnum::Value2: j = "VALUE_2"; break;
* default: throw std::runtime_error("Unexpected value serializing enum MyEnum: " +
* std::to_string(static_cast<int>(x)));
* }
* }
* @param parent - Name of the serialized enumerate
* @param childs - Enumerate values data.
*/
private _createEnumSerializer;
/**
* @description Generates a JSON deserializer for an enum. Maps strings to enum values, with an
* error for unexpected strings.
* Ex:
* inline void from_json(const nlohmann::json& j, MyEnum& x) {
* if (j == "VALUE_1") x = MyEnum::Value1;
* else if (j == "VALUE_2") x = MyEnum::Value2;
* else {
* throw std::runtime_error("Unexpected value deserializing enum MyEnum.");
* }
* }
* @param parent - Name of the deserialized enumerate
* @param childs - Enumerate values data.
*/
private _createEnumDeserializer;
/**
* @description Creates a JSON serializer for a class or struct that is the intersection of
* multiple types.
*
* @example
* // inline void to_json(nlohmann::json& j, const DerivedType& x) {
* // to_json(j, static_cast<const BaseType1&>(x));
* // to_json(j, static_cast<const BaseType2&>(x));
* // }
*
* @param intersectName - The name of the intersected class or struct.
* @param itemsType - An array of strings representing the names of the base types to serialize.
*/
private _createIntersectionSerializer;
/**
* @description Creates a JSON deserializer for a class or struct that is the intersection of
* multiple types.
*
* @example
* // inline void from_json(const nlohmann::json& j, DerivedType& x) {
* // from_json(j, static_cast<BaseType1&>(x));
* // from_json(j, static_cast<BaseType2&>(x));
* // }
*
* @param intersectName - The name of the intersected class or struct.
* @param itemsType - An array of strings representing the names of the base types to deserialize.
*/
private _createIntersectionDeserializer;
/**
* @description Generates a `to_json` function for a specified union type, allowing the JSON
* library to correctly serialize any variant within the union.
*
* @param unionName The name of the union type.
* @param itemsType A list of all variant types contained in the union.
*
* @example
* // Given: unionName = "MyUnion", itemsType = {"int", "std::string"}
* // The generated output might look like:
* //
* // inline void to_json(nlohmann::json& j, const MyUnion& x) {
* // if (x.type() == typeid(int)) {
* // j = boost::get<int>(x);
* // } else if (x.type() == typeid(std::string)) {
* // j = boost::get<std::string>(x);
* // } else {
* // throw std::runtime_error("Unknown MyUnion type.");
* // }
* // }
*/
protected _createUnionSerializer(unionName: string, itemsType: string[]): void;
/**
* @description Generates a `from_json` function for a specified union type, attempting to
* deserialize the provided JSON into one of the known variant types. If no match
* is found, it throws an error.
*
* @param unionName The name of the union type.
* @param items A list of possible variant types. Each item includes:
* - `type`: The C++ type for deserialization (e.g., `int`, `std::string`).
* - `discriminantValue` (optional): The value in the discriminator field
* that maps to the respective type.
* @param discriminator (optional) The JSON field name that acts as a type discriminator.
* Required for discriminator-based deserialization.
*
* @example
* // Discriminator-based deserialization:
* // Given: unionName = "MyUnion", discriminator = "type"
* // items = { {"type": "EmailContact", "discriminantValue": "email"},
* // {"type": "PhoneContact", "discriminantValue": "phone"} }
* //
* // The generated output might look like:
* // inline void from_json(const nlohmann::json& j, MyUnion& x) {
* // const auto& k = j.at("type").get<std::string>();
* // if (k == "email") {
* // x = j.get<EmailContact>();
* // } else if (k == "phone") {
* // x = j.get<PhoneContact>();
* // } else {
* // throw std::runtime_error("Failed to deserialize MyUnion: unknown type");
* // }
* // }
*
* @example
* // Fallback matching without a discriminator:
* // Given: unionName = "MyUnion", items = { {"type": "int"}, {"type": "std::string"} }
* //
* // The generated output might look like:
* // inline void from_json(const nlohmann::json& j, MyUnion& x) {
* // try {
* // // Try to deserialize as int
* // x = j.get<int>();
* // return;
* // } catch (const std::exception&) {
* // // Fall through to try the next type
* // }
* //
* // try {
* // // Try to deserialize as std::string
* // x = j.get<std::string>();
* // return;
* // } catch (const std::exception&) {
* // // None of the types matched. Error
* // throw std::runtime_error("Failed to deserialize MyUnion: unknown format");
* // }
* // }
*/
private _createUnionDeserializer;
protected _push0: (item: string[], data: string) => number;
protected _push1: (item: string[], data: string) => number;
protected _push2: (item: string[], data: string) => number;
protected _push3: (item: string[], data: string) => number;
protected _push4: (item: string[], data: string) => number;
}
/**
* @description Transpiler for Zod schemas to C++17 code.
*/
export declare class Zod2Cpp17 extends Zod2Cpp {
constructor(opt?: IZod2CppOpt);
/** Ex: std::variant<TypeA, TypeB> */
protected getUnionType: (itemsType: string[]) => string;
protected _getOptional(type: string): string;
/**
* @description Generates a `to_json` function for a specified union type, allowing the JSON
* library to correctly serialize any variant within the union.
*
* @param unionName The name of the union type.
* @param itemsType A list of all variant types contained in the union.
*
* @example
* // Given: unionName = "MyUnion", itemsType = {"int", "std::string"}
* // The generated output might look like:
* //
* // inline void to_json(nlohmann::json& j, const MyUnion& x) {
* // std::visit(
* // [&j](auto&& arg) {
* // using T = std::decay_t<decltype(arg)>;
* // if constexpr (std::is_same_v<T, int>) {
* // j = arg;
* // } else if constexpr (std::is_same_v<T, std::string>) {
* // j = arg;
* // } else {
* // throw std::runtime_error("Unknown MyUnion type.");
* // }
* // },
* // x
* // );
* // }
*/
protected _createUnionSerializer(unionName: string, itemsType: string[]): void;
}