πŸš€ Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more β†’
Sign In

@cerios/cerios-builder

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cerios/cerios-builder - npm Package Compare versions

Comparing version
1.4.0
to
1.5.0
+218
-21
dist/index.d.mts
/**
* Helper type to extract the builder type from a builder instance.
* This is useful when you want to accept a builder with some fields already set
* without manually specifying which fields are set.
*
* @template B - A builder instance type
*
* @example
* ```typescript
* // Instead of:
* function withAddress(
* builder: AddressBuilder & CeriosBrand<Pick<Address, "city" | "country">>
* ) { ... }
*
* // You can write:
* function withAddress(builder: BuilderType<ReturnType<typeof AddressBuilder.createWithDefaults>>) { ... }
* ```
*/
type BuilderType<B> = B;
/**
* Recursively makes all properties readonly for deep immutability.
* Handles arrays, objects, and primitive types.
*
* @template T - The type to make deeply readonly
*/
type DeepReadonly<T> = T extends (infer R)[] ? DeepReadonlyArray<R> : T extends (...args: any[]) => any ? T : T extends object ? DeepReadonlyObject<T> : T;
/**
* Helper type for deep readonly arrays
* @internal
*/
interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {
}
/**
* Helper type for deep readonly objects
* @internal
*/
type DeepReadonlyObject<T> = {
readonly [P in keyof T]: DeepReadonly<T[P]>;
};
/**
* Unique symbol used internally to brand types and track which properties have been set in the builder's type.

@@ -33,22 +73,2 @@ *

/**
* Recursively makes all properties readonly for deep immutability.
* Handles arrays, objects, and primitive types.
*
* @template T - The type to make deeply readonly
*/
type DeepReadonly<T> = T extends (infer R)[] ? DeepReadonlyArray<R> : T extends (...args: any[]) => any ? T : T extends object ? DeepReadonlyObject<T> : T;
/**
* Helper type for deep readonly arrays
* @internal
*/
interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {
}
/**
* Helper type for deep readonly objects
* @internal
*/
type DeepReadonlyObject<T> = {
readonly [P in keyof T]: DeepReadonly<T[P]>;
};
/**
* Cache the root key extraction to avoid repeated computation

@@ -291,2 +311,179 @@ * Handles optional properties by ensuring the key is valid for T

export { type CeriosBrand, CeriosBuilder, type RequiredFieldsTemplate };
/**
* Type representing a class constructor that can be instantiated with optional partial data.
* @template T - The type that the constructor creates
*/
type ClassConstructor<T> = new (data?: Partial<T>) => T;
/**
* Helper to extract only data properties (exclude methods) from a class type.
* This allows compile-time validation to work properly with classes.
*/
type DataPropertiesOnly<T> = {
[K in keyof T as T[K] extends (...args: any[]) => any ? never : K]: T[K];
};
/**
* Brand type specifically for class builders that only tracks data properties.
*/
type CeriosClassBrand<T> = {
readonly __classBuilderBrand: T;
};
/**
* Type-safe builder specifically designed for classes.
* This builder automatically instantiates the target class and provides:
* - Compile-time validation that works with class methods
* - Automatic runtime validation of nested class instances
* - Preservation of decorators and class methods
*
* Example usage:
* ```typescript
* class Person {
* name!: string;
* age!: number;
* email?: string;
*
* constructor(data?: Partial<Person>) {
* if (data) Object.assign(this, data);
* }
*
* greet() { return `Hello, I'm ${this.name}`; }
* }
*
* const builder = new CeriosClassBuilder(Person);
* const person = builder
* .setProperty('name', 'John')
* .setProperty('age', 30)
* .build();
* ```
*
* @template T - The class type being built
*/
declare class CeriosClassBuilder<T extends object> {
/**
* The class constructor to instantiate when building.
* @private
*/
private readonly _classConstructor;
/**
* The current partial state of the object being built.
* @private
*/
protected readonly _actual: Partial<T>;
/**
* Creates a new class builder instance.
* @param classConstructor - The class constructor to use for building
* @param data - Optional initial data
*/
protected constructor(classConstructor: ClassConstructor<T>, data?: Partial<T>);
/**
* Gets the class constructor for this builder.
* @private
*/
private getClassConstructor;
/**
* Creates a new instance of the builder with updated data.
* Subclasses can override this to return the correct subclass type.
* @private
*/
private createBuilder;
/**
* Sets a property value and returns a new builder instance with updated type state.
* @template K - The property key being set
* @param key - The property key to set
* @param value - The value to assign to the property
* @returns A new builder instance with the property set
*/
setProperty<K extends keyof DataPropertiesOnly<T>>(key: K, value: DataPropertiesOnly<T>[K]): this & CeriosClassBrand<Pick<DataPropertiesOnly<T>, K>>;
/**
* Sets multiple properties at once.
* @template K - The property keys being set
* @param props - Object with properties to set
* @returns A new builder instance with the properties set
*/
setProperties<K extends keyof DataPropertiesOnly<T>>(props: Pick<DataPropertiesOnly<T>, K>): this & CeriosClassBrand<Pick<DataPropertiesOnly<T>, K>>;
/**
* Adds a value to an array property.
* @template K - The array property key
* @template V - The array element type
* @param key - The array property key
* @param value - The value to add to the array
* @returns A new builder instance with the value added
*/
addToArrayProperty<K extends {
[P in keyof DataPropertiesOnly<T>]: NonNullable<DataPropertiesOnly<T>[P]> extends Array<any> ? P : never;
}[keyof DataPropertiesOnly<T>], V extends DataPropertiesOnly<T>[K] extends Array<infer U> ? U : DataPropertiesOnly<T>[K] extends Array<infer U> | undefined ? U : never>(key: K, value: V): this & CeriosClassBrand<Pick<DataPropertiesOnly<T>, K>>;
/**
* Builds the final class instance with compile-time and runtime validation.
* - Compile-time: TypeScript enforces all data properties are set
* - Runtime: Validates nested class instances are properly instantiated
*
* @returns The fully built and validated class instance
* @throws {Error} If nested validation fails
*/
build(this: this & CeriosClassBrand<DataPropertiesOnly<T>>): T;
/**
* Builds the class instance with runtime validation only (no compile-time).
* Use this when building from external/dynamic data.
*
* @returns The built class instance
* @throws {Error} If validation fails
*/
buildWithoutCompileTimeValidation(): T;
/**
* Builds the class instance without any validation.
* Use only when you're certain the object is valid.
*
* @returns The built class instance (may be incomplete)
*/
buildUnsafe(): T;
/**
* Builds a partial object (may not have all required fields).
*
* @returns The partially built object
*/
buildPartial(): Partial<T>;
/**
* Builds and freezes the class instance (shallow freeze).
*
* @returns The frozen class instance
* @throws {Error} If validation fails
*/
buildFrozen(this: this & CeriosClassBrand<DataPropertiesOnly<T>>): Readonly<T>;
/**
* Builds and deeply freezes the class instance.
*
* @returns The deeply frozen class instance
* @throws {Error} If validation fails
*/
buildDeepFrozen(this: this & CeriosClassBrand<DataPropertiesOnly<T>>): DeepReadonly<T>;
/**
* Builds and seals the class instance (shallow freeze).
*
* @returns The sealed class instance
* @throws {Error} If validation fails
*/
buildSealed(this: this & CeriosClassBrand<DataPropertiesOnly<T>>): T;
/**
* Builds and deeply seals the class instance.
*
* @returns The deeply sealed class instance
* @throws {Error} If validation fails
*/
buildDeepSealed(this: this & CeriosClassBrand<DataPropertiesOnly<T>>): T;
/**
* Deep freeze helper.
* @private
*/
private deepFreeze;
/**
* Deep seal helper.
* @private
*/
private deepSeal;
/**
* Deep clone helper for nested objects.
* @private
*/
private deepClone;
}
export { type BuilderType, type CeriosBrand, CeriosBuilder, CeriosClassBuilder, type ClassConstructor, type DeepReadonly, type RequiredFieldsTemplate };
/**
* Helper type to extract the builder type from a builder instance.
* This is useful when you want to accept a builder with some fields already set
* without manually specifying which fields are set.
*
* @template B - A builder instance type
*
* @example
* ```typescript
* // Instead of:
* function withAddress(
* builder: AddressBuilder & CeriosBrand<Pick<Address, "city" | "country">>
* ) { ... }
*
* // You can write:
* function withAddress(builder: BuilderType<ReturnType<typeof AddressBuilder.createWithDefaults>>) { ... }
* ```
*/
type BuilderType<B> = B;
/**
* Recursively makes all properties readonly for deep immutability.
* Handles arrays, objects, and primitive types.
*
* @template T - The type to make deeply readonly
*/
type DeepReadonly<T> = T extends (infer R)[] ? DeepReadonlyArray<R> : T extends (...args: any[]) => any ? T : T extends object ? DeepReadonlyObject<T> : T;
/**
* Helper type for deep readonly arrays
* @internal
*/
interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {
}
/**
* Helper type for deep readonly objects
* @internal
*/
type DeepReadonlyObject<T> = {
readonly [P in keyof T]: DeepReadonly<T[P]>;
};
/**
* Unique symbol used internally to brand types and track which properties have been set in the builder's type.

@@ -33,22 +73,2 @@ *

/**
* Recursively makes all properties readonly for deep immutability.
* Handles arrays, objects, and primitive types.
*
* @template T - The type to make deeply readonly
*/
type DeepReadonly<T> = T extends (infer R)[] ? DeepReadonlyArray<R> : T extends (...args: any[]) => any ? T : T extends object ? DeepReadonlyObject<T> : T;
/**
* Helper type for deep readonly arrays
* @internal
*/
interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {
}
/**
* Helper type for deep readonly objects
* @internal
*/
type DeepReadonlyObject<T> = {
readonly [P in keyof T]: DeepReadonly<T[P]>;
};
/**
* Cache the root key extraction to avoid repeated computation

@@ -291,2 +311,179 @@ * Handles optional properties by ensuring the key is valid for T

export { type CeriosBrand, CeriosBuilder, type RequiredFieldsTemplate };
/**
* Type representing a class constructor that can be instantiated with optional partial data.
* @template T - The type that the constructor creates
*/
type ClassConstructor<T> = new (data?: Partial<T>) => T;
/**
* Helper to extract only data properties (exclude methods) from a class type.
* This allows compile-time validation to work properly with classes.
*/
type DataPropertiesOnly<T> = {
[K in keyof T as T[K] extends (...args: any[]) => any ? never : K]: T[K];
};
/**
* Brand type specifically for class builders that only tracks data properties.
*/
type CeriosClassBrand<T> = {
readonly __classBuilderBrand: T;
};
/**
* Type-safe builder specifically designed for classes.
* This builder automatically instantiates the target class and provides:
* - Compile-time validation that works with class methods
* - Automatic runtime validation of nested class instances
* - Preservation of decorators and class methods
*
* Example usage:
* ```typescript
* class Person {
* name!: string;
* age!: number;
* email?: string;
*
* constructor(data?: Partial<Person>) {
* if (data) Object.assign(this, data);
* }
*
* greet() { return `Hello, I'm ${this.name}`; }
* }
*
* const builder = new CeriosClassBuilder(Person);
* const person = builder
* .setProperty('name', 'John')
* .setProperty('age', 30)
* .build();
* ```
*
* @template T - The class type being built
*/
declare class CeriosClassBuilder<T extends object> {
/**
* The class constructor to instantiate when building.
* @private
*/
private readonly _classConstructor;
/**
* The current partial state of the object being built.
* @private
*/
protected readonly _actual: Partial<T>;
/**
* Creates a new class builder instance.
* @param classConstructor - The class constructor to use for building
* @param data - Optional initial data
*/
protected constructor(classConstructor: ClassConstructor<T>, data?: Partial<T>);
/**
* Gets the class constructor for this builder.
* @private
*/
private getClassConstructor;
/**
* Creates a new instance of the builder with updated data.
* Subclasses can override this to return the correct subclass type.
* @private
*/
private createBuilder;
/**
* Sets a property value and returns a new builder instance with updated type state.
* @template K - The property key being set
* @param key - The property key to set
* @param value - The value to assign to the property
* @returns A new builder instance with the property set
*/
setProperty<K extends keyof DataPropertiesOnly<T>>(key: K, value: DataPropertiesOnly<T>[K]): this & CeriosClassBrand<Pick<DataPropertiesOnly<T>, K>>;
/**
* Sets multiple properties at once.
* @template K - The property keys being set
* @param props - Object with properties to set
* @returns A new builder instance with the properties set
*/
setProperties<K extends keyof DataPropertiesOnly<T>>(props: Pick<DataPropertiesOnly<T>, K>): this & CeriosClassBrand<Pick<DataPropertiesOnly<T>, K>>;
/**
* Adds a value to an array property.
* @template K - The array property key
* @template V - The array element type
* @param key - The array property key
* @param value - The value to add to the array
* @returns A new builder instance with the value added
*/
addToArrayProperty<K extends {
[P in keyof DataPropertiesOnly<T>]: NonNullable<DataPropertiesOnly<T>[P]> extends Array<any> ? P : never;
}[keyof DataPropertiesOnly<T>], V extends DataPropertiesOnly<T>[K] extends Array<infer U> ? U : DataPropertiesOnly<T>[K] extends Array<infer U> | undefined ? U : never>(key: K, value: V): this & CeriosClassBrand<Pick<DataPropertiesOnly<T>, K>>;
/**
* Builds the final class instance with compile-time and runtime validation.
* - Compile-time: TypeScript enforces all data properties are set
* - Runtime: Validates nested class instances are properly instantiated
*
* @returns The fully built and validated class instance
* @throws {Error} If nested validation fails
*/
build(this: this & CeriosClassBrand<DataPropertiesOnly<T>>): T;
/**
* Builds the class instance with runtime validation only (no compile-time).
* Use this when building from external/dynamic data.
*
* @returns The built class instance
* @throws {Error} If validation fails
*/
buildWithoutCompileTimeValidation(): T;
/**
* Builds the class instance without any validation.
* Use only when you're certain the object is valid.
*
* @returns The built class instance (may be incomplete)
*/
buildUnsafe(): T;
/**
* Builds a partial object (may not have all required fields).
*
* @returns The partially built object
*/
buildPartial(): Partial<T>;
/**
* Builds and freezes the class instance (shallow freeze).
*
* @returns The frozen class instance
* @throws {Error} If validation fails
*/
buildFrozen(this: this & CeriosClassBrand<DataPropertiesOnly<T>>): Readonly<T>;
/**
* Builds and deeply freezes the class instance.
*
* @returns The deeply frozen class instance
* @throws {Error} If validation fails
*/
buildDeepFrozen(this: this & CeriosClassBrand<DataPropertiesOnly<T>>): DeepReadonly<T>;
/**
* Builds and seals the class instance (shallow freeze).
*
* @returns The sealed class instance
* @throws {Error} If validation fails
*/
buildSealed(this: this & CeriosClassBrand<DataPropertiesOnly<T>>): T;
/**
* Builds and deeply seals the class instance.
*
* @returns The deeply sealed class instance
* @throws {Error} If validation fails
*/
buildDeepSealed(this: this & CeriosClassBrand<DataPropertiesOnly<T>>): T;
/**
* Deep freeze helper.
* @private
*/
private deepFreeze;
/**
* Deep seal helper.
* @private
*/
private deepSeal;
/**
* Deep clone helper for nested objects.
* @private
*/
private deepClone;
}
export { type BuilderType, type CeriosBrand, CeriosBuilder, CeriosClassBuilder, type ClassConstructor, type DeepReadonly, type RequiredFieldsTemplate };

@@ -23,3 +23,4 @@ "use strict";

__export(index_exports, {
CeriosBuilder: () => CeriosBuilder
CeriosBuilder: () => CeriosBuilder,
CeriosClassBuilder: () => CeriosClassBuilder
});

@@ -387,6 +388,252 @@ module.exports = __toCommonJS(index_exports);

};
// src/cerios-class-builder.ts
var CeriosClassBuilder = class {
/**
* Creates a new class builder instance.
* @param classConstructor - The class constructor to use for building
* @param data - Optional initial data
*/
constructor(classConstructor, data = {}) {
this._classConstructor = classConstructor;
this._actual = data;
}
/**
* Gets the class constructor for this builder.
* @private
*/
getClassConstructor() {
return this._classConstructor;
}
/**
* Creates a new instance of the builder with updated data.
* Subclasses can override this to return the correct subclass type.
* @private
*/
createBuilder(data) {
const BuilderClass = this.constructor;
return new BuilderClass(this._classConstructor, data);
}
/**
* Sets a property value and returns a new builder instance with updated type state.
* @template K - The property key being set
* @param key - The property key to set
* @param value - The value to assign to the property
* @returns A new builder instance with the property set
*/
setProperty(key, value) {
const newBuilder = this.createBuilder({
...this._actual,
[key]: value
});
return newBuilder;
}
/**
* Sets multiple properties at once.
* @template K - The property keys being set
* @param props - Object with properties to set
* @returns A new builder instance with the properties set
*/
setProperties(props) {
const newBuilder = this.createBuilder({
...this._actual,
...props
});
return newBuilder;
}
/**
* Adds a value to an array property.
* @template K - The array property key
* @template V - The array element type
* @param key - The array property key
* @param value - The value to add to the array
* @returns A new builder instance with the value added
*/
addToArrayProperty(key, value) {
var _a;
const currentArray = (_a = this._actual[key]) != null ? _a : [];
const newBuilder = this.createBuilder({
...this._actual,
[key]: [...currentArray, value]
});
return newBuilder;
}
/**
* Builds the final class instance with compile-time and runtime validation.
* - Compile-time: TypeScript enforces all data properties are set
* - Runtime: Validates nested class instances are properly instantiated
*
* @returns The fully built and validated class instance
* @throws {Error} If nested validation fails
*/
build() {
const ctor = this.getClassConstructor();
const instance = new ctor(this._actual);
const dataKeys = Object.keys(this._actual);
const needsAssign = dataKeys.some((key) => instance[key] === void 0 && this._actual[key] !== void 0);
if (needsAssign) {
Object.assign(instance, this._actual);
}
return instance;
}
/**
* Builds the class instance with runtime validation only (no compile-time).
* Use this when building from external/dynamic data.
*
* @returns The built class instance
* @throws {Error} If validation fails
*/
buildWithoutCompileTimeValidation() {
const ctor = this.getClassConstructor();
const instance = new ctor(this._actual);
const dataKeys = Object.keys(this._actual);
const needsAssign = dataKeys.some((key) => instance[key] === void 0 && this._actual[key] !== void 0);
if (needsAssign) {
Object.assign(instance, this._actual);
}
return instance;
}
/**
* Builds the class instance without any validation.
* Use only when you're certain the object is valid.
*
* @returns The built class instance (may be incomplete)
*/
buildUnsafe() {
const ctor = this.getClassConstructor();
const instance = new ctor(this._actual);
const dataKeys = Object.keys(this._actual);
const needsAssign = dataKeys.some((key) => instance[key] === void 0 && this._actual[key] !== void 0);
if (needsAssign) {
Object.assign(instance, this._actual);
}
return instance;
}
/**
* Builds a partial object (may not have all required fields).
*
* @returns The partially built object
*/
buildPartial() {
return { ...this._actual };
}
/**
* Builds and freezes the class instance (shallow freeze).
*
* @returns The frozen class instance
* @throws {Error} If validation fails
*/
buildFrozen() {
const ctor = this.getClassConstructor();
const instance = new ctor(this._actual);
const dataKeys = Object.keys(this._actual);
const needsAssign = dataKeys.some((key) => instance[key] === void 0 && this._actual[key] !== void 0);
if (needsAssign) {
Object.assign(instance, this._actual);
}
return Object.freeze(instance);
}
/**
* Builds and deeply freezes the class instance.
*
* @returns The deeply frozen class instance
* @throws {Error} If validation fails
*/
buildDeepFrozen() {
const ctor = this.getClassConstructor();
const instance = new ctor(this._actual);
const dataKeys = Object.keys(this._actual);
const needsAssign = dataKeys.some((key) => instance[key] === void 0 && this._actual[key] !== void 0);
if (needsAssign) {
Object.assign(instance, this._actual);
}
return this.deepFreeze(instance);
}
/**
* Builds and seals the class instance (shallow freeze).
*
* @returns The sealed class instance
* @throws {Error} If validation fails
*/
buildSealed() {
const ctor = this.getClassConstructor();
const instance = new ctor(this._actual);
const dataKeys = Object.keys(this._actual);
const needsAssign = dataKeys.some((key) => instance[key] === void 0 && this._actual[key] !== void 0);
if (needsAssign) {
Object.assign(instance, this._actual);
}
return Object.seal(instance);
}
/**
* Builds and deeply seals the class instance.
*
* @returns The deeply sealed class instance
* @throws {Error} If validation fails
*/
buildDeepSealed() {
const ctor = this.getClassConstructor();
const instance = new ctor(this._actual);
const dataKeys = Object.keys(this._actual);
const needsAssign = dataKeys.some((key) => instance[key] === void 0 && this._actual[key] !== void 0);
if (needsAssign) {
Object.assign(instance, this._actual);
}
return this.deepSeal(instance);
}
/**
* Deep freeze helper.
* @private
*/
deepFreeze(obj) {
if (obj === null || typeof obj !== "object") {
return obj;
}
Object.getOwnPropertyNames(obj).forEach((prop) => {
const value = obj[prop];
if (value !== null && (typeof value === "object" || typeof value === "function")) {
this.deepFreeze(value);
}
});
return Object.freeze(obj);
}
/**
* Deep seal helper.
* @private
*/
deepSeal(obj) {
if (obj === null || typeof obj !== "object") {
return obj;
}
Object.getOwnPropertyNames(obj).forEach((prop) => {
const value = obj[prop];
if (value !== null && (typeof value === "object" || typeof value === "function")) {
this.deepSeal(value);
}
});
return Object.seal(obj);
}
/**
* Deep clone helper for nested objects.
* @private
*/
deepClone(obj) {
if (obj === null || typeof obj !== "object") {
return obj;
}
if (Array.isArray(obj)) {
return obj.map((item) => this.deepClone(item));
}
const cloned = {};
for (const key of Object.keys(obj)) {
cloned[key] = this.deepClone(obj[key]);
}
return cloned;
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
CeriosBuilder
CeriosBuilder,
CeriosClassBuilder
});
//# sourceMappingURL=index.js.map
+1
-1

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/index.ts","../src/cerios-builder.ts"],"sourcesContent":["export { CeriosBrand, CeriosBuilder, RequiredFieldsTemplate } from \"./cerios-builder.js\";\n","/**\n * Unique symbol used internally to brand types and track which properties have been set in the builder's type.\n *\n * @internal\n */\ndeclare const __brand: unique symbol;\n\n/**\n * Type utility for branding builder types with information about which properties have been set.\n * This is used to enforce compile-time safety for required fields in the builder pattern.\n *\n * @template T - The type representing the set of properties that have been set\n * @internal\n */\nexport type CeriosBrand<T> = { [__brand]: T };\n\n/**\n * Helper type to represent a path through an object structure\n * Handles optional properties by unwrapping them with NonNullable\n */\ntype PathImpl<T, K extends keyof T = keyof T> = K extends string | number\n\t? NonNullable<T[K]> extends Record<string, any>\n\t\t? NonNullable<T[K]> extends Array<any>\n\t\t\t? K\n\t\t\t: K | `${K}.${PathImpl<NonNullable<T[K]>> & string}`\n\t\t: K\n\t: never;\n\nexport type Path<T> = PathImpl<T>;\n\n/**\n * Helper type to get the value at a specific path, handling optional properties\n */\ntype PathValue<T, P> = P extends keyof T\n\t? T[P]\n\t: P extends `${infer K}.${infer Rest}`\n\t\t? K extends keyof T\n\t\t\t? PathValue<NonNullable<T[K]>, Rest>\n\t\t\t: never\n\t\t: never;\n\n/**\n * Type-safe template for defining required fields using an array of paths.\n * Simply list the paths that are required.\n */\nexport type RequiredFieldsTemplate<T> = ReadonlyArray<Path<T>>;\n\n/**\n * Recursively makes all properties readonly for deep immutability.\n * Handles arrays, objects, and primitive types.\n *\n * @template T - The type to make deeply readonly\n */\nexport type DeepReadonly<T> = T extends (infer R)[]\n\t? DeepReadonlyArray<R>\n\t: T extends (...args: any[]) => any\n\t\t? T\n\t\t: T extends object\n\t\t\t? DeepReadonlyObject<T>\n\t\t\t: T;\n\n/**\n * Helper type for deep readonly arrays\n * @internal\n */\ninterface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {}\n\n/**\n * Helper type for deep readonly objects\n * @internal\n */\ntype DeepReadonlyObject<T> = {\n\treadonly [P in keyof T]: DeepReadonly<T[P]>;\n};\n\n/**\n * Cache the root key extraction to avoid repeated computation\n * Handles optional properties by ensuring the key is valid for T\n * @internal\n */\ntype RootKey<P extends string, T = any> = P extends `${infer K}.${string}`\n\t? K extends keyof T\n\t\t? K\n\t\t: never\n\t: P extends keyof T\n\t\t? P\n\t\t: never;\n\n/**\n * Recursively freezes an object and all its nested properties.\n * @param obj - The object to freeze\n * @returns The frozen object\n * @internal\n */\nfunction deepFreeze<T>(obj: T): T {\n\t// Retrieve the property names defined on obj\n\tObject.getOwnPropertyNames(obj).forEach(prop => {\n\t\tconst value = (obj as any)[prop];\n\n\t\t// Freeze properties before freezing self\n\t\tif (value !== null && (typeof value === \"object\" || typeof value === \"function\")) {\n\t\t\tdeepFreeze(value);\n\t\t}\n\t});\n\n\treturn Object.freeze(obj);\n}\n\n/**\n * Recursively seals an object and all its nested properties.\n * @param obj - The object to seal\n * @returns The sealed object\n * @internal\n */\nfunction deepSeal<T>(obj: T): T {\n\t// Retrieve the property names defined on obj\n\tObject.getOwnPropertyNames(obj).forEach(prop => {\n\t\tconst value = (obj as any)[prop];\n\n\t\t// Seal properties before sealing self\n\t\tif (value !== null && (typeof value === \"object\" || typeof value === \"function\")) {\n\t\t\tdeepSeal(value);\n\t\t}\n\t});\n\n\treturn Object.seal(obj);\n}\n\n/**\n * Abstract base class for creating type-safe builders with automatic property setters and compile-time validation of required fields.\n *\n * This class is intended to be extended by concrete builder implementations for your own types.\n * It provides utility methods for setting properties and building the final object, ensuring that all required fields are set at compile time.\n *\n * Example usage:\n * ```typescript\n * interface MyType { foo: string; bar: number[]; }\n * class MyTypeBuilder extends CeriosBuilder<MyType> {\n * static requiredTemplate: RequiredFieldsTemplate<MyType> = ['foo'];\n * setFoo(value: string) { return this.setProperty('foo', value); }\n * addBar(value: number) { return this.addToArrayProperty('bar', value); }\n * }\n * // Usage:\n * const obj = new MyTypeBuilder({})\n * .setFoo('hello')\n * .addBar(42)\n * .buildSafe(); // Validates that 'foo' is set\n * ```\n *\n * @template T - The complete type being built\n */\nexport abstract class CeriosBuilder<T extends object> {\n\t/**\n\t * Template defining which fields are required for this builder.\n\t * Subclasses should override this to specify their required fields as an array of paths.\n\t * The template is type-safe - only valid paths from type T can be used.\n\t */\n\tstatic requiredTemplate?: ReadonlyArray<string>;\n\n\t/**\n\t * Instance-level required fields that can be populated dynamically.\n\t * This allows adding required fields at runtime via the setRequiredFields method.\n\t * @private\n\t */\n\tprivate _requiredFields: Set<string> = new Set();\n\n\t/**\n\t * Sets the required fields for this builder instance.\n\t * This allows you to dynamically define which fields are required.\n\t *\n\t * @param fields - Array of dot-notation paths to required fields\n\t * @returns The builder instance for chaining\n\t *\n\t * @example\n\t * ```typescript\n\t * const builder = new MyBuilder({})\n\t * .setRequiredFields(['path.to.field1', 'path.to.field2'])\n\t * .setField1('value1')\n\t * .setField2('value2')\n\t * .buildSafe();\n\t * ```\n\t */\n\tsetRequiredFields(fields: ReadonlyArray<Path<T>>): this {\n\t\tthis._requiredFields = new Set([...fields] as string[]);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Gets the combined required fields from both the static template and instance-level fields.\n\t * @private\n\t */\n\tprivate getRequiredTemplate(): ReadonlyArray<string> {\n\t\tconst ctor = this.constructor as typeof CeriosBuilder;\n\t\tconst staticFields = ctor.requiredTemplate || [];\n\t\tconst instanceFields = Array.from(this._requiredFields);\n\n\t\t// Combine and deduplicate\n\t\treturn [...new Set([...staticFields, ...instanceFields])];\n\t}\n\n\t/**\n\t * Validates that all fields in the required template have been set.\n\t * @private\n\t */\n\tprivate validateRequiredFields(): string[] {\n\t\tconst requiredPaths = this.getRequiredTemplate();\n\t\tconst missing: string[] = [];\n\n\t\tfor (const path of requiredPaths) {\n\t\t\tconst keys = path.split(\".\");\n\t\t\tlet current: any = this._actual;\n\n\t\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\t\tconst key = keys[i];\n\t\t\t\tif (current === null || current === undefined || !(key in current)) {\n\t\t\t\t\tmissing.push(path);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcurrent = current[key];\n\t\t\t}\n\n\t\t\t// Check if the final value is null or undefined\n\t\t\tif (current === null || current === undefined) {\n\t\t\t\tif (!missing.includes(path)) {\n\t\t\t\t\tmissing.push(path);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn missing;\n\t}\n\n\t/**\n\t * Creates a new builder instance. Intended to be called by subclasses.\n\t *\n\t * @param _actual - The current partial state of the object being built\n\t * @param _requiredFields - Optional array of required field paths to preserve across instances\n\t * @protected\n\t */\n\tprotected constructor(\n\t\tprotected readonly _actual: Partial<T>,\n\t\t_requiredFields?: RequiredFieldsTemplate<T>\n\t) {\n\t\tif (_requiredFields) {\n\t\t\tthis._requiredFields = new Set([..._requiredFields] as string[]);\n\t\t}\n\t}\n\n\t/**\n\t * Sets a property value and returns a new builder instance with updated type state.\n\t * This method is intended to be wrapped by concrete builder methods in subclasses.\n\t *\n\t * @template K - The property key being set\n\t * @param key - The property key to set\n\t * @param value - The value to assign to the property\n\t * @returns A new builder instance with the property set and type state updated\n\t * @protected\n\t */\n\tprotected setProperty<K extends keyof T>(key: K, value: T[K]): this & CeriosBrand<Pick<T, K>> {\n\t\tconst BuilderClass = this.constructor as new (data: any, requiredFields?: RequiredFieldsTemplate<T>) => any;\n\t\treturn new BuilderClass(\n\t\t\t{\n\t\t\t\t...this._actual,\n\t\t\t\t[key]: value,\n\t\t\t},\n\t\t\tArray.from(this._requiredFields) as unknown as RequiredFieldsTemplate<T>\n\t\t) as this & CeriosBrand<Pick<T, K>>;\n\t}\n\n\t/**\n\t * Sets multiple property values at once and returns a new builder instance with updated type state.\n\t * @param props - An object with one or more properties to set.\n\t * @returns A new builder instance with the properties set and type state updated.\n\t * @protected\n\t */\n\tprotected setProperties<K extends keyof T>(props: Pick<T, K>): this & CeriosBrand<Pick<T, K>> {\n\t\tconst BuilderClass = this.constructor as new (data: any, requiredFields?: RequiredFieldsTemplate<T>) => any;\n\t\treturn new BuilderClass(\n\t\t\t{\n\t\t\t\t...this._actual,\n\t\t\t\t...props,\n\t\t\t},\n\t\t\tArray.from(this._requiredFields) as unknown as RequiredFieldsTemplate<T>\n\t\t) as this & CeriosBrand<Pick<T, K>>;\n\t}\n\n\t/**\n\t * Sets a deeply nested property value and returns a new builder instance with updated type state.\n\t * This method uses dot notation to set nested properties in a type-safe way.\n\t *\n\t * @template P - The property path (e.g., \"parent.child.grandchild\")\n\t * @param path - The dot-notation path to the property\n\t * @param value - The value to assign to the nested property\n\t * @returns A new builder instance with the nested property set\n\t * @protected\n\t *\n\t * @example\n\t * ```typescript\n\t * builder.setNestedProperty('Order.Details.CustomerId', 'value')\n\t * ```\n\t */\n\tprotected setNestedProperty<P extends Path<T>>(\n\t\tpath: P,\n\t\tvalue: PathValue<T, P>\n\t): this & CeriosBrand<Pick<T, RootKey<P & string, T> extends never ? keyof T : RootKey<P & string, T>>> {\n\t\tconst BuilderClass = this.constructor as new (data: any, requiredFields?: RequiredFieldsTemplate<T>) => any;\n\t\tconst keys = (path as string).split(\".\");\n\t\tconst newActual = this.deepClone(this._actual);\n\n\t\tlet current: any = newActual;\n\t\tfor (let i = 0; i < keys.length - 1; i++) {\n\t\t\tconst key = keys[i];\n\t\t\tif (!(key in current) || typeof current[key] !== \"object\" || current[key] === null) {\n\t\t\t\tcurrent[key] = {};\n\t\t\t} else {\n\t\t\t\tcurrent[key] = this.deepClone(current[key]);\n\t\t\t}\n\t\t\tcurrent = current[key];\n\t\t}\n\n\t\tcurrent[keys[keys.length - 1]] = value;\n\n\t\treturn new BuilderClass(\n\t\t\tnewActual,\n\t\t\tArray.from(this._requiredFields) as unknown as RequiredFieldsTemplate<T>\n\t\t) as this & CeriosBrand<Pick<T, RootKey<P & string, T> extends never ? keyof T : RootKey<P & string, T>>>;\n\t}\n\n\t/**\n\t * Deep clone helper for nested objects\n\t * @private\n\t */\n\tprivate deepClone<V>(obj: V): V {\n\t\tif (obj === null || typeof obj !== \"object\") {\n\t\t\treturn obj;\n\t\t}\n\t\tif (Array.isArray(obj)) {\n\t\t\treturn obj.map(item => this.deepClone(item)) as any;\n\t\t}\n\t\tconst cloned: any = {};\n\t\tconst hasOwn = Object.prototype.hasOwnProperty;\n\t\tfor (const key in obj) {\n\t\t\tif (hasOwn.call(obj, key)) {\n\t\t\t\tcloned[key] = this.deepClone(obj[key]);\n\t\t\t}\n\t\t}\n\t\treturn cloned;\n\t}\n\n\t/**\n\t * Adds a value to an array property and returns a new builder instance with updated type state.\n\t * This method is intended to be wrapped by concrete builder methods in subclasses for array properties.\n\t *\n\t * @template K - The property key (must be an array property)\n\t * @template V - The type of the array element\n\t * @param key - The array property key to add to\n\t * @param value - The value to add to the array\n\t * @returns A new builder instance with the array property updated and type state updated\n\t * @protected\n\t */\n\tprotected addToArrayProperty<\n\t\tK extends { [P in keyof T]: NonNullable<T[P]> extends Array<any> ? P : never }[keyof T],\n\t\tV extends T[K] extends Array<infer U> ? U : T[K] extends Array<infer U> | undefined ? U : never,\n\t>(key: K, value: V): this & CeriosBrand<Pick<T, K>> {\n\t\tconst BuilderClass = this.constructor as new (data: any, requiredFields?: RequiredFieldsTemplate<T>) => any;\n\t\tconst currentArray = (this._actual[key] as Array<V> | undefined) ?? [];\n\t\treturn new BuilderClass(\n\t\t\t{\n\t\t\t\t...this._actual,\n\t\t\t\t[key]: [...currentArray, value],\n\t\t\t},\n\t\t\tArray.from(this._requiredFields) as unknown as RequiredFieldsTemplate<T>\n\t\t) as this & CeriosBrand<Pick<T, K>>;\n\t}\n\n\t/**\n\t * Builds the final object with both compile-time and runtime validation.\n\t * This is the recommended and safest way to build objects.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: Validates all fields in the requiredTemplate\n\t *\n\t * @returns The fully built object of type T\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuild(this: this & CeriosBrand<T>): T {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn this._actual as T;\n\t}\n\n\t/**\n\t * Builds the final object with only compile-time validation, skipping runtime checks.\n\t * Use this when you want TypeScript safety but need to skip runtime validation for performance.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: No validation\n\t *\n\t * @returns The fully built object of type T\n\t */\n\tbuildWithoutRuntimeValidation(this: this & CeriosBrand<T>): T {\n\t\treturn this._actual as T;\n\t}\n\n\t/**\n\t * Builds the final object with only runtime validation, skipping compile-time checks.\n\t * Use this when building from external data where compile-time checks aren't possible.\n\t *\n\t * - Compile-time: No TypeScript enforcement\n\t * - Runtime: Validates all fields in the requiredTemplate\n\t *\n\t * @returns The fully built object of type T\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildWithoutCompileTimeValidation(): T {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn this._actual as T;\n\t}\n\n\t/**\n\t * Builds the final object without any validation (neither compile-time nor runtime).\n\t * Use this only when you're certain the object is valid and need maximum performance.\n\t *\n\t * - Compile-time: No TypeScript enforcement\n\t * - Runtime: No validation\n\t *\n\t * @returns The object of type T (may be incomplete)\n\t */\n\tbuildUnsafe(): T {\n\t\treturn this._actual as T;\n\t}\n\n\t/**\n\t * Builds a partial object, which may not have all required fields set.\n\t * This is useful for scenarios where you want to inspect or validate the current state before finalizing.\n\t *\n\t * @returns The partially built object\n\t */\n\tbuildPartial(): Partial<T> {\n\t\treturn this._actual as Partial<T>;\n\t}\n\n\t/**\n\t * @deprecated Use build() instead. buildSafe() is now an alias for build().\n\t * Builds the final object with runtime validation using the requiredTemplate.\n\t * This method validates that all fields in the requiredTemplate array are present.\n\t *\n\t * @returns The fully built object of type T\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildSafe(): T {\n\t\treturn this.buildWithoutCompileTimeValidation();\n\t}\n\n\t/**\n\t * Builds and freezes the final object with both compile-time and runtime validation.\n\t * The returned object is shallowly frozen - top-level properties cannot be modified,\n\t * but nested objects remain mutable.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: Validates all fields in the requiredTemplate and applies Object.freeze()\n\t *\n\t * @returns The frozen object of type Readonly<T>\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildFrozen(this: this & CeriosBrand<T>): Readonly<T> {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn Object.freeze(this._actual as T);\n\t}\n\n\t/**\n\t * Builds and deeply freezes the final object with both compile-time and runtime validation.\n\t * The returned object is recursively frozen - all nested objects and arrays are also frozen.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: Validates all fields in the requiredTemplate and recursively applies Object.freeze()\n\t *\n\t * @returns The deeply frozen object of type DeepReadonly<T>\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildDeepFrozen(this: this & CeriosBrand<T>): DeepReadonly<T> {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn deepFreeze(this._actual as T) as DeepReadonly<T>;\n\t}\n\n\t/**\n\t * Builds and seals the final object with both compile-time and runtime validation.\n\t * The returned object is shallowly sealed - properties cannot be added or removed,\n\t * but existing properties can still be modified. Nested objects remain unsealed.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: Validates all fields in the requiredTemplate and applies Object.seal()\n\t *\n\t * @returns The sealed object of type T\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildSealed(this: this & CeriosBrand<T>): T {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn Object.seal(this._actual as T);\n\t}\n\n\t/**\n\t * Builds and deeply seals the final object with both compile-time and runtime validation.\n\t * The returned object is recursively sealed - properties cannot be added or removed at any level,\n\t * but existing properties can still be modified.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: Validates all fields in the requiredTemplate and recursively applies Object.seal()\n\t *\n\t * @returns The deeply sealed object of type T\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildDeepSealed(this: this & CeriosBrand<T>): T {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn deepSeal(this._actual as T);\n\t}\n}\n"],"mappings":"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","names":[]}
{"version":3,"sources":["../src/index.ts","../src/cerios-builder.ts","../src/cerios-class-builder.ts"],"sourcesContent":["export { CeriosBrand, CeriosBuilder, RequiredFieldsTemplate } from \"./cerios-builder.js\";\nexport { CeriosClassBuilder, ClassConstructor } from \"./cerios-class-builder.js\";\nexport { BuilderType, DeepReadonly } from \"./types.js\";\n","import { DeepReadonly } from \"./types\";\n\n/**\n * Unique symbol used internally to brand types and track which properties have been set in the builder's type.\n *\n * @internal\n */\ndeclare const __brand: unique symbol;\n\n/**\n * Type utility for branding builder types with information about which properties have been set.\n * This is used to enforce compile-time safety for required fields in the builder pattern.\n *\n * @template T - The type representing the set of properties that have been set\n * @internal\n */\nexport type CeriosBrand<T> = { [__brand]: T };\n\n/**\n * Helper type to represent a path through an object structure\n * Handles optional properties by unwrapping them with NonNullable\n */\ntype PathImpl<T, K extends keyof T = keyof T> = K extends string | number\n\t? NonNullable<T[K]> extends Record<string, any>\n\t\t? NonNullable<T[K]> extends Array<any>\n\t\t\t? K\n\t\t\t: K | `${K}.${PathImpl<NonNullable<T[K]>> & string}`\n\t\t: K\n\t: never;\n\nexport type Path<T> = PathImpl<T>;\n\n/**\n * Helper type to get the value at a specific path, handling optional properties\n */\ntype PathValue<T, P> = P extends keyof T\n\t? T[P]\n\t: P extends `${infer K}.${infer Rest}`\n\t\t? K extends keyof T\n\t\t\t? PathValue<NonNullable<T[K]>, Rest>\n\t\t\t: never\n\t\t: never;\n\n/**\n * Type-safe template for defining required fields using an array of paths.\n * Simply list the paths that are required.\n */\nexport type RequiredFieldsTemplate<T> = ReadonlyArray<Path<T>>;\n\n/**\n * Cache the root key extraction to avoid repeated computation\n * Handles optional properties by ensuring the key is valid for T\n * @internal\n */\ntype RootKey<P extends string, T = any> = P extends `${infer K}.${string}`\n\t? K extends keyof T\n\t\t? K\n\t\t: never\n\t: P extends keyof T\n\t\t? P\n\t\t: never;\n\n/**\n * Recursively freezes an object and all its nested properties.\n * @param obj - The object to freeze\n * @returns The frozen object\n * @internal\n */\nfunction deepFreeze<T>(obj: T): T {\n\t// Retrieve the property names defined on obj\n\tObject.getOwnPropertyNames(obj).forEach(prop => {\n\t\tconst value = (obj as any)[prop];\n\n\t\t// Freeze properties before freezing self\n\t\tif (value !== null && (typeof value === \"object\" || typeof value === \"function\")) {\n\t\t\tdeepFreeze(value);\n\t\t}\n\t});\n\n\treturn Object.freeze(obj);\n}\n\n/**\n * Recursively seals an object and all its nested properties.\n * @param obj - The object to seal\n * @returns The sealed object\n * @internal\n */\nfunction deepSeal<T>(obj: T): T {\n\t// Retrieve the property names defined on obj\n\tObject.getOwnPropertyNames(obj).forEach(prop => {\n\t\tconst value = (obj as any)[prop];\n\n\t\t// Seal properties before sealing self\n\t\tif (value !== null && (typeof value === \"object\" || typeof value === \"function\")) {\n\t\t\tdeepSeal(value);\n\t\t}\n\t});\n\n\treturn Object.seal(obj);\n}\n\n/**\n * Abstract base class for creating type-safe builders with automatic property setters and compile-time validation of required fields.\n *\n * This class is intended to be extended by concrete builder implementations for your own types.\n * It provides utility methods for setting properties and building the final object, ensuring that all required fields are set at compile time.\n *\n * Example usage:\n * ```typescript\n * interface MyType { foo: string; bar: number[]; }\n * class MyTypeBuilder extends CeriosBuilder<MyType> {\n * static requiredTemplate: RequiredFieldsTemplate<MyType> = ['foo'];\n * setFoo(value: string) { return this.setProperty('foo', value); }\n * addBar(value: number) { return this.addToArrayProperty('bar', value); }\n * }\n * // Usage:\n * const obj = new MyTypeBuilder({})\n * .setFoo('hello')\n * .addBar(42)\n * .buildSafe(); // Validates that 'foo' is set\n * ```\n *\n * @template T - The complete type being built\n */\nexport abstract class CeriosBuilder<T extends object> {\n\t/**\n\t * Template defining which fields are required for this builder.\n\t * Subclasses should override this to specify their required fields as an array of paths.\n\t * The template is type-safe - only valid paths from type T can be used.\n\t */\n\tstatic requiredTemplate?: ReadonlyArray<string>;\n\n\t/**\n\t * Instance-level required fields that can be populated dynamically.\n\t * This allows adding required fields at runtime via the setRequiredFields method.\n\t * @private\n\t */\n\tprivate _requiredFields: Set<string> = new Set();\n\n\t/**\n\t * Sets the required fields for this builder instance.\n\t * This allows you to dynamically define which fields are required.\n\t *\n\t * @param fields - Array of dot-notation paths to required fields\n\t * @returns The builder instance for chaining\n\t *\n\t * @example\n\t * ```typescript\n\t * const builder = new MyBuilder({})\n\t * .setRequiredFields(['path.to.field1', 'path.to.field2'])\n\t * .setField1('value1')\n\t * .setField2('value2')\n\t * .buildSafe();\n\t * ```\n\t */\n\tsetRequiredFields(fields: ReadonlyArray<Path<T>>): this {\n\t\tthis._requiredFields = new Set([...fields] as string[]);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Gets the combined required fields from both the static template and instance-level fields.\n\t * @private\n\t */\n\tprivate getRequiredTemplate(): ReadonlyArray<string> {\n\t\tconst ctor = this.constructor as typeof CeriosBuilder;\n\t\tconst staticFields = ctor.requiredTemplate || [];\n\t\tconst instanceFields = Array.from(this._requiredFields);\n\n\t\t// Combine and deduplicate\n\t\treturn [...new Set([...staticFields, ...instanceFields])];\n\t}\n\n\t/**\n\t * Validates that all fields in the required template have been set.\n\t * @private\n\t */\n\tprivate validateRequiredFields(): string[] {\n\t\tconst requiredPaths = this.getRequiredTemplate();\n\t\tconst missing: string[] = [];\n\n\t\tfor (const path of requiredPaths) {\n\t\t\tconst keys = path.split(\".\");\n\t\t\tlet current: any = this._actual;\n\n\t\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\t\tconst key = keys[i];\n\t\t\t\tif (current === null || current === undefined || !(key in current)) {\n\t\t\t\t\tmissing.push(path);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcurrent = current[key];\n\t\t\t}\n\n\t\t\t// Check if the final value is null or undefined\n\t\t\tif (current === null || current === undefined) {\n\t\t\t\tif (!missing.includes(path)) {\n\t\t\t\t\tmissing.push(path);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn missing;\n\t}\n\n\t/**\n\t * Creates a new builder instance. Intended to be called by subclasses.\n\t *\n\t * @param _actual - The current partial state of the object being built\n\t * @param _requiredFields - Optional array of required field paths to preserve across instances\n\t * @protected\n\t */\n\tprotected constructor(\n\t\tprotected readonly _actual: Partial<T>,\n\t\t_requiredFields?: RequiredFieldsTemplate<T>\n\t) {\n\t\tif (_requiredFields) {\n\t\t\tthis._requiredFields = new Set([..._requiredFields] as string[]);\n\t\t}\n\t}\n\n\t/**\n\t * Sets a property value and returns a new builder instance with updated type state.\n\t * This method is intended to be wrapped by concrete builder methods in subclasses.\n\t *\n\t * @template K - The property key being set\n\t * @param key - The property key to set\n\t * @param value - The value to assign to the property\n\t * @returns A new builder instance with the property set and type state updated\n\t * @protected\n\t */\n\tprotected setProperty<K extends keyof T>(key: K, value: T[K]): this & CeriosBrand<Pick<T, K>> {\n\t\tconst BuilderClass = this.constructor as new (data: any, requiredFields?: RequiredFieldsTemplate<T>) => any;\n\t\treturn new BuilderClass(\n\t\t\t{\n\t\t\t\t...this._actual,\n\t\t\t\t[key]: value,\n\t\t\t},\n\t\t\tArray.from(this._requiredFields) as unknown as RequiredFieldsTemplate<T>\n\t\t) as this & CeriosBrand<Pick<T, K>>;\n\t}\n\n\t/**\n\t * Sets multiple property values at once and returns a new builder instance with updated type state.\n\t * @param props - An object with one or more properties to set.\n\t * @returns A new builder instance with the properties set and type state updated.\n\t * @protected\n\t */\n\tprotected setProperties<K extends keyof T>(props: Pick<T, K>): this & CeriosBrand<Pick<T, K>> {\n\t\tconst BuilderClass = this.constructor as new (data: any, requiredFields?: RequiredFieldsTemplate<T>) => any;\n\t\treturn new BuilderClass(\n\t\t\t{\n\t\t\t\t...this._actual,\n\t\t\t\t...props,\n\t\t\t},\n\t\t\tArray.from(this._requiredFields) as unknown as RequiredFieldsTemplate<T>\n\t\t) as this & CeriosBrand<Pick<T, K>>;\n\t}\n\n\t/**\n\t * Sets a deeply nested property value and returns a new builder instance with updated type state.\n\t * This method uses dot notation to set nested properties in a type-safe way.\n\t *\n\t * @template P - The property path (e.g., \"parent.child.grandchild\")\n\t * @param path - The dot-notation path to the property\n\t * @param value - The value to assign to the nested property\n\t * @returns A new builder instance with the nested property set\n\t * @protected\n\t *\n\t * @example\n\t * ```typescript\n\t * builder.setNestedProperty('Order.Details.CustomerId', 'value')\n\t * ```\n\t */\n\tprotected setNestedProperty<P extends Path<T>>(\n\t\tpath: P,\n\t\tvalue: PathValue<T, P>\n\t): this & CeriosBrand<Pick<T, RootKey<P & string, T> extends never ? keyof T : RootKey<P & string, T>>> {\n\t\tconst BuilderClass = this.constructor as new (data: any, requiredFields?: RequiredFieldsTemplate<T>) => any;\n\t\tconst keys = (path as string).split(\".\");\n\t\tconst newActual = this.deepClone(this._actual);\n\n\t\tlet current: any = newActual;\n\t\tfor (let i = 0; i < keys.length - 1; i++) {\n\t\t\tconst key = keys[i];\n\t\t\tif (!(key in current) || typeof current[key] !== \"object\" || current[key] === null) {\n\t\t\t\tcurrent[key] = {};\n\t\t\t} else {\n\t\t\t\tcurrent[key] = this.deepClone(current[key]);\n\t\t\t}\n\t\t\tcurrent = current[key];\n\t\t}\n\n\t\tcurrent[keys[keys.length - 1]] = value;\n\n\t\treturn new BuilderClass(\n\t\t\tnewActual,\n\t\t\tArray.from(this._requiredFields) as unknown as RequiredFieldsTemplate<T>\n\t\t) as this & CeriosBrand<Pick<T, RootKey<P & string, T> extends never ? keyof T : RootKey<P & string, T>>>;\n\t}\n\n\t/**\n\t * Deep clone helper for nested objects\n\t * @private\n\t */\n\tprivate deepClone<V>(obj: V): V {\n\t\tif (obj === null || typeof obj !== \"object\") {\n\t\t\treturn obj;\n\t\t}\n\t\tif (Array.isArray(obj)) {\n\t\t\treturn obj.map(item => this.deepClone(item)) as any;\n\t\t}\n\t\tconst cloned: any = {};\n\t\tconst hasOwn = Object.prototype.hasOwnProperty;\n\t\tfor (const key in obj) {\n\t\t\tif (hasOwn.call(obj, key)) {\n\t\t\t\tcloned[key] = this.deepClone(obj[key]);\n\t\t\t}\n\t\t}\n\t\treturn cloned;\n\t}\n\n\t/**\n\t * Adds a value to an array property and returns a new builder instance with updated type state.\n\t * This method is intended to be wrapped by concrete builder methods in subclasses for array properties.\n\t *\n\t * @template K - The property key (must be an array property)\n\t * @template V - The type of the array element\n\t * @param key - The array property key to add to\n\t * @param value - The value to add to the array\n\t * @returns A new builder instance with the array property updated and type state updated\n\t * @protected\n\t */\n\tprotected addToArrayProperty<\n\t\tK extends { [P in keyof T]: NonNullable<T[P]> extends Array<any> ? P : never }[keyof T],\n\t\tV extends T[K] extends Array<infer U> ? U : T[K] extends Array<infer U> | undefined ? U : never,\n\t>(key: K, value: V): this & CeriosBrand<Pick<T, K>> {\n\t\tconst BuilderClass = this.constructor as new (data: any, requiredFields?: RequiredFieldsTemplate<T>) => any;\n\t\tconst currentArray = (this._actual[key] as Array<V> | undefined) ?? [];\n\t\treturn new BuilderClass(\n\t\t\t{\n\t\t\t\t...this._actual,\n\t\t\t\t[key]: [...currentArray, value],\n\t\t\t},\n\t\t\tArray.from(this._requiredFields) as unknown as RequiredFieldsTemplate<T>\n\t\t) as this & CeriosBrand<Pick<T, K>>;\n\t}\n\n\t/**\n\t * Builds the final object with both compile-time and runtime validation.\n\t * This is the recommended and safest way to build objects.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: Validates all fields in the requiredTemplate\n\t *\n\t * @returns The fully built object of type T\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuild(this: this & CeriosBrand<T>): T {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn this._actual as T;\n\t}\n\n\t/**\n\t * Builds the final object with only compile-time validation, skipping runtime checks.\n\t * Use this when you want TypeScript safety but need to skip runtime validation for performance.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: No validation\n\t *\n\t * @returns The fully built object of type T\n\t */\n\tbuildWithoutRuntimeValidation(this: this & CeriosBrand<T>): T {\n\t\treturn this._actual as T;\n\t}\n\n\t/**\n\t * Builds the final object with only runtime validation, skipping compile-time checks.\n\t * Use this when building from external data where compile-time checks aren't possible.\n\t *\n\t * - Compile-time: No TypeScript enforcement\n\t * - Runtime: Validates all fields in the requiredTemplate\n\t *\n\t * @returns The fully built object of type T\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildWithoutCompileTimeValidation(): T {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn this._actual as T;\n\t}\n\n\t/**\n\t * Builds the final object without any validation (neither compile-time nor runtime).\n\t * Use this only when you're certain the object is valid and need maximum performance.\n\t *\n\t * - Compile-time: No TypeScript enforcement\n\t * - Runtime: No validation\n\t *\n\t * @returns The object of type T (may be incomplete)\n\t */\n\tbuildUnsafe(): T {\n\t\treturn this._actual as T;\n\t}\n\n\t/**\n\t * Builds a partial object, which may not have all required fields set.\n\t * This is useful for scenarios where you want to inspect or validate the current state before finalizing.\n\t *\n\t * @returns The partially built object\n\t */\n\tbuildPartial(): Partial<T> {\n\t\treturn this._actual as Partial<T>;\n\t}\n\n\t/**\n\t * @deprecated Use build() instead. buildSafe() is now an alias for build().\n\t * Builds the final object with runtime validation using the requiredTemplate.\n\t * This method validates that all fields in the requiredTemplate array are present.\n\t *\n\t * @returns The fully built object of type T\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildSafe(): T {\n\t\treturn this.buildWithoutCompileTimeValidation();\n\t}\n\n\t/**\n\t * Builds and freezes the final object with both compile-time and runtime validation.\n\t * The returned object is shallowly frozen - top-level properties cannot be modified,\n\t * but nested objects remain mutable.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: Validates all fields in the requiredTemplate and applies Object.freeze()\n\t *\n\t * @returns The frozen object of type Readonly<T>\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildFrozen(this: this & CeriosBrand<T>): Readonly<T> {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn Object.freeze(this._actual as T);\n\t}\n\n\t/**\n\t * Builds and deeply freezes the final object with both compile-time and runtime validation.\n\t * The returned object is recursively frozen - all nested objects and arrays are also frozen.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: Validates all fields in the requiredTemplate and recursively applies Object.freeze()\n\t *\n\t * @returns The deeply frozen object of type DeepReadonly<T>\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildDeepFrozen(this: this & CeriosBrand<T>): DeepReadonly<T> {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn deepFreeze(this._actual as T) as DeepReadonly<T>;\n\t}\n\n\t/**\n\t * Builds and seals the final object with both compile-time and runtime validation.\n\t * The returned object is shallowly sealed - properties cannot be added or removed,\n\t * but existing properties can still be modified. Nested objects remain unsealed.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: Validates all fields in the requiredTemplate and applies Object.seal()\n\t *\n\t * @returns The sealed object of type T\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildSealed(this: this & CeriosBrand<T>): T {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn Object.seal(this._actual as T);\n\t}\n\n\t/**\n\t * Builds and deeply seals the final object with both compile-time and runtime validation.\n\t * The returned object is recursively sealed - properties cannot be added or removed at any level,\n\t * but existing properties can still be modified.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: Validates all fields in the requiredTemplate and recursively applies Object.seal()\n\t *\n\t * @returns The deeply sealed object of type T\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildDeepSealed(this: this & CeriosBrand<T>): T {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn deepSeal(this._actual as T);\n\t}\n}\n","import type { DeepReadonly } from \"./types\";\n\n/**\n * Type representing a class constructor that can be instantiated with optional partial data.\n * @template T - The type that the constructor creates\n */\nexport type ClassConstructor<T> = new (data?: Partial<T>) => T;\n\n/**\n * Helper to extract only data properties (exclude methods) from a class type.\n * This allows compile-time validation to work properly with classes.\n */\ntype DataPropertiesOnly<T> = {\n\t[K in keyof T as T[K] extends (...args: any[]) => any ? never : K]: T[K];\n};\n\n/**\n * Brand type specifically for class builders that only tracks data properties.\n */\nexport type CeriosClassBrand<T> = {\n\treadonly __classBuilderBrand: T;\n};\n\n/**\n * Type-safe builder specifically designed for classes.\n * This builder automatically instantiates the target class and provides:\n * - Compile-time validation that works with class methods\n * - Automatic runtime validation of nested class instances\n * - Preservation of decorators and class methods\n *\n * Example usage:\n * ```typescript\n * class Person {\n * name!: string;\n * age!: number;\n * email?: string;\n *\n * constructor(data?: Partial<Person>) {\n * if (data) Object.assign(this, data);\n * }\n *\n * greet() { return `Hello, I'm ${this.name}`; }\n * }\n *\n * const builder = new CeriosClassBuilder(Person);\n * const person = builder\n * .setProperty('name', 'John')\n * .setProperty('age', 30)\n * .build();\n * ```\n *\n * @template T - The class type being built\n */\nexport class CeriosClassBuilder<T extends object> {\n\t/**\n\t * The class constructor to instantiate when building.\n\t * @private\n\t */\n\tprivate readonly _classConstructor: ClassConstructor<T>;\n\n\t/**\n\t * The current partial state of the object being built.\n\t * @private\n\t */\n\tprotected readonly _actual: Partial<T>;\n\n\t/**\n\t * Creates a new class builder instance.\n\t * @param classConstructor - The class constructor to use for building\n\t * @param data - Optional initial data\n\t */\n\tprotected constructor(classConstructor: ClassConstructor<T>, data: Partial<T> = {}) {\n\t\tthis._classConstructor = classConstructor;\n\t\tthis._actual = data;\n\t}\n\n\t/**\n\t * Gets the class constructor for this builder.\n\t * @private\n\t */\n\tprivate getClassConstructor(): ClassConstructor<T> {\n\t\treturn this._classConstructor;\n\t}\n\n\t/**\n\t * Creates a new instance of the builder with updated data.\n\t * Subclasses can override this to return the correct subclass type.\n\t * @private\n\t */\n\tprivate createBuilder(data: Partial<T>): this {\n\t\tconst BuilderClass = this.constructor as new (classConstructor: ClassConstructor<T>, data: Partial<T>) => this;\n\t\treturn new BuilderClass(this._classConstructor, data);\n\t}\n\n\t/**\n\t * Sets a property value and returns a new builder instance with updated type state.\n\t * @template K - The property key being set\n\t * @param key - The property key to set\n\t * @param value - The value to assign to the property\n\t * @returns A new builder instance with the property set\n\t */\n\tsetProperty<K extends keyof DataPropertiesOnly<T>>(\n\t\tkey: K,\n\t\tvalue: DataPropertiesOnly<T>[K]\n\t): this & CeriosClassBrand<Pick<DataPropertiesOnly<T>, K>> {\n\t\tconst newBuilder = this.createBuilder({\n\t\t\t...this._actual,\n\t\t\t[key]: value,\n\t\t} as Partial<T>);\n\t\treturn newBuilder as this & CeriosClassBrand<Pick<DataPropertiesOnly<T>, K>>;\n\t}\n\n\t/**\n\t * Sets multiple properties at once.\n\t * @template K - The property keys being set\n\t * @param props - Object with properties to set\n\t * @returns A new builder instance with the properties set\n\t */\n\tsetProperties<K extends keyof DataPropertiesOnly<T>>(\n\t\tprops: Pick<DataPropertiesOnly<T>, K>\n\t): this & CeriosClassBrand<Pick<DataPropertiesOnly<T>, K>> {\n\t\tconst newBuilder = this.createBuilder({\n\t\t\t...this._actual,\n\t\t\t...props,\n\t\t} as Partial<T>);\n\t\treturn newBuilder as this & CeriosClassBrand<Pick<DataPropertiesOnly<T>, K>>;\n\t}\n\n\t/**\n\t * Adds a value to an array property.\n\t * @template K - The array property key\n\t * @template V - The array element type\n\t * @param key - The array property key\n\t * @param value - The value to add to the array\n\t * @returns A new builder instance with the value added\n\t */\n\taddToArrayProperty<\n\t\tK extends {\n\t\t\t[P in keyof DataPropertiesOnly<T>]: NonNullable<DataPropertiesOnly<T>[P]> extends Array<any> ? P : never;\n\t\t}[keyof DataPropertiesOnly<T>],\n\t\tV extends DataPropertiesOnly<T>[K] extends Array<infer U>\n\t\t\t? U\n\t\t\t: DataPropertiesOnly<T>[K] extends Array<infer U> | undefined\n\t\t\t\t? U\n\t\t\t\t: never,\n\t>(key: K, value: V): this & CeriosClassBrand<Pick<DataPropertiesOnly<T>, K>> {\n\t\tconst currentArray = (this._actual[key as keyof T] as Array<V> | undefined) ?? [];\n\t\tconst newBuilder = this.createBuilder({\n\t\t\t...this._actual,\n\t\t\t[key]: [...currentArray, value],\n\t\t} as Partial<T>);\n\t\treturn newBuilder as this & CeriosClassBrand<Pick<DataPropertiesOnly<T>, K>>;\n\t}\n\n\t/**\n\t * Builds the final class instance with compile-time and runtime validation.\n\t * - Compile-time: TypeScript enforces all data properties are set\n\t * - Runtime: Validates nested class instances are properly instantiated\n\t *\n\t * @returns The fully built and validated class instance\n\t * @throws {Error} If nested validation fails\n\t */\n\tbuild(this: this & CeriosClassBrand<DataPropertiesOnly<T>>): T {\n\t\tconst ctor = this.getClassConstructor();\n\t\tconst instance: T = new ctor(this._actual as T);\n\t\t// If the class does not assign properties in the constructor, assign them manually\n\t\tconst dataKeys = Object.keys(this._actual) as (keyof T)[];\n\t\tconst needsAssign = dataKeys.some(key => instance[key] === undefined && this._actual[key] !== undefined);\n\t\tif (needsAssign) {\n\t\t\tObject.assign(instance, this._actual);\n\t\t}\n\t\treturn instance;\n\t}\n\n\t/**\n\t * Builds the class instance with runtime validation only (no compile-time).\n\t * Use this when building from external/dynamic data.\n\t *\n\t * @returns The built class instance\n\t * @throws {Error} If validation fails\n\t */\n\tbuildWithoutCompileTimeValidation(): T {\n\t\tconst ctor = this.getClassConstructor();\n\t\tconst instance: T = new ctor(this._actual as T);\n\t\tconst dataKeys = Object.keys(this._actual) as (keyof T)[];\n\t\tconst needsAssign = dataKeys.some(key => instance[key] === undefined && this._actual[key] !== undefined);\n\t\tif (needsAssign) {\n\t\t\tObject.assign(instance, this._actual);\n\t\t}\n\t\treturn instance;\n\t}\n\n\t/**\n\t * Builds the class instance without any validation.\n\t * Use only when you're certain the object is valid.\n\t *\n\t * @returns The built class instance (may be incomplete)\n\t */\n\tbuildUnsafe(): T {\n\t\tconst ctor = this.getClassConstructor();\n\t\tconst instance: T = new ctor(this._actual as T);\n\t\tconst dataKeys = Object.keys(this._actual) as (keyof T)[];\n\t\tconst needsAssign = dataKeys.some(key => instance[key] === undefined && this._actual[key] !== undefined);\n\t\tif (needsAssign) {\n\t\t\tObject.assign(instance, this._actual);\n\t\t}\n\t\treturn instance;\n\t}\n\n\t/**\n\t * Builds a partial object (may not have all required fields).\n\t *\n\t * @returns The partially built object\n\t */\n\tbuildPartial(): Partial<T> {\n\t\treturn { ...this._actual };\n\t}\n\n\t/**\n\t * Builds and freezes the class instance (shallow freeze).\n\t *\n\t * @returns The frozen class instance\n\t * @throws {Error} If validation fails\n\t */\n\tbuildFrozen(this: this & CeriosClassBrand<DataPropertiesOnly<T>>): Readonly<T> {\n\t\tconst ctor = this.getClassConstructor();\n\t\tconst instance: T = new ctor(this._actual as T);\n\t\t// If the class does not assign properties in the constructor, assign them manually\n\t\tconst dataKeys = Object.keys(this._actual) as (keyof T)[];\n\t\tconst needsAssign = dataKeys.some(key => instance[key] === undefined && this._actual[key] !== undefined);\n\t\tif (needsAssign) {\n\t\t\tObject.assign(instance, this._actual);\n\t\t}\n\t\treturn Object.freeze(instance);\n\t}\n\n\t/**\n\t * Builds and deeply freezes the class instance.\n\t *\n\t * @returns The deeply frozen class instance\n\t * @throws {Error} If validation fails\n\t */\n\tbuildDeepFrozen(this: this & CeriosClassBrand<DataPropertiesOnly<T>>): DeepReadonly<T> {\n\t\tconst ctor = this.getClassConstructor();\n\t\tconst instance: T = new ctor(this._actual as T);\n\t\t// If the class does not assign properties in the constructor, assign them manually\n\t\tconst dataKeys = Object.keys(this._actual) as (keyof T)[];\n\t\tconst needsAssign = dataKeys.some(key => instance[key] === undefined && this._actual[key] !== undefined);\n\t\tif (needsAssign) {\n\t\t\tObject.assign(instance, this._actual);\n\t\t}\n\t\treturn this.deepFreeze(instance) as DeepReadonly<T>;\n\t}\n\n\t/**\n\t * Builds and seals the class instance (shallow freeze).\n\t *\n\t * @returns The sealed class instance\n\t * @throws {Error} If validation fails\n\t */\n\tbuildSealed(this: this & CeriosClassBrand<DataPropertiesOnly<T>>): T {\n\t\tconst ctor = this.getClassConstructor();\n\t\tconst instance: T = new ctor(this._actual as T);\n\t\t// If the class does not assign properties in the constructor, assign them manually\n\t\tconst dataKeys = Object.keys(this._actual) as (keyof T)[];\n\t\tconst needsAssign = dataKeys.some(key => instance[key] === undefined && this._actual[key] !== undefined);\n\t\tif (needsAssign) {\n\t\t\tObject.assign(instance, this._actual);\n\t\t}\n\t\treturn Object.seal(instance);\n\t}\n\n\t/**\n\t * Builds and deeply seals the class instance.\n\t *\n\t * @returns The deeply sealed class instance\n\t * @throws {Error} If validation fails\n\t */\n\tbuildDeepSealed(this: this & CeriosClassBrand<DataPropertiesOnly<T>>): T {\n\t\tconst ctor = this.getClassConstructor();\n\t\tconst instance: T = new ctor(this._actual as T);\n\t\t// If the class does not assign properties in the constructor, assign them manually\n\t\tconst dataKeys = Object.keys(this._actual) as (keyof T)[];\n\t\tconst needsAssign = dataKeys.some(key => instance[key] === undefined && this._actual[key] !== undefined);\n\t\tif (needsAssign) {\n\t\t\tObject.assign(instance, this._actual);\n\t\t}\n\t\treturn this.deepSeal(instance);\n\t}\n\n\t/**\n\t * Deep freeze helper.\n\t * @private\n\t */\n\tprivate deepFreeze<V>(obj: V): V {\n\t\tif (obj === null || typeof obj !== \"object\") {\n\t\t\treturn obj;\n\t\t}\n\t\tObject.getOwnPropertyNames(obj).forEach(prop => {\n\t\t\tconst value = (obj as any)[prop];\n\t\t\tif (value !== null && (typeof value === \"object\" || typeof value === \"function\")) {\n\t\t\t\tthis.deepFreeze(value);\n\t\t\t}\n\t\t});\n\t\treturn Object.freeze(obj);\n\t}\n\n\t/**\n\t * Deep seal helper.\n\t * @private\n\t */\n\tprivate deepSeal<V>(obj: V): V {\n\t\tif (obj === null || typeof obj !== \"object\") {\n\t\t\treturn obj;\n\t\t}\n\t\tObject.getOwnPropertyNames(obj).forEach(prop => {\n\t\t\tconst value = (obj as any)[prop];\n\t\t\tif (value !== null && (typeof value === \"object\" || typeof value === \"function\")) {\n\t\t\t\tthis.deepSeal(value);\n\t\t\t}\n\t\t});\n\t\treturn Object.seal(obj);\n\t}\n\n\t/**\n\t * Deep clone helper for nested objects.\n\t * @private\n\t */\n\tprivate deepClone<V>(obj: V): V {\n\t\tif (obj === null || typeof obj !== \"object\") {\n\t\t\treturn obj;\n\t\t}\n\t\tif (Array.isArray(obj)) {\n\t\t\treturn obj.map(item => this.deepClone(item)) as any;\n\t\t}\n\t\tconst cloned: any = {};\n\t\tfor (const key of Object.keys(obj)) {\n\t\t\tcloned[key] = this.deepClone((obj as any)[key]);\n\t\t}\n\t\treturn cloned;\n\t}\n}\n"],"mappings":"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","names":[]}

@@ -360,5 +360,251 @@ // src/cerios-builder.ts

};
// src/cerios-class-builder.ts
var CeriosClassBuilder = class {
/**
* Creates a new class builder instance.
* @param classConstructor - The class constructor to use for building
* @param data - Optional initial data
*/
constructor(classConstructor, data = {}) {
this._classConstructor = classConstructor;
this._actual = data;
}
/**
* Gets the class constructor for this builder.
* @private
*/
getClassConstructor() {
return this._classConstructor;
}
/**
* Creates a new instance of the builder with updated data.
* Subclasses can override this to return the correct subclass type.
* @private
*/
createBuilder(data) {
const BuilderClass = this.constructor;
return new BuilderClass(this._classConstructor, data);
}
/**
* Sets a property value and returns a new builder instance with updated type state.
* @template K - The property key being set
* @param key - The property key to set
* @param value - The value to assign to the property
* @returns A new builder instance with the property set
*/
setProperty(key, value) {
const newBuilder = this.createBuilder({
...this._actual,
[key]: value
});
return newBuilder;
}
/**
* Sets multiple properties at once.
* @template K - The property keys being set
* @param props - Object with properties to set
* @returns A new builder instance with the properties set
*/
setProperties(props) {
const newBuilder = this.createBuilder({
...this._actual,
...props
});
return newBuilder;
}
/**
* Adds a value to an array property.
* @template K - The array property key
* @template V - The array element type
* @param key - The array property key
* @param value - The value to add to the array
* @returns A new builder instance with the value added
*/
addToArrayProperty(key, value) {
var _a;
const currentArray = (_a = this._actual[key]) != null ? _a : [];
const newBuilder = this.createBuilder({
...this._actual,
[key]: [...currentArray, value]
});
return newBuilder;
}
/**
* Builds the final class instance with compile-time and runtime validation.
* - Compile-time: TypeScript enforces all data properties are set
* - Runtime: Validates nested class instances are properly instantiated
*
* @returns The fully built and validated class instance
* @throws {Error} If nested validation fails
*/
build() {
const ctor = this.getClassConstructor();
const instance = new ctor(this._actual);
const dataKeys = Object.keys(this._actual);
const needsAssign = dataKeys.some((key) => instance[key] === void 0 && this._actual[key] !== void 0);
if (needsAssign) {
Object.assign(instance, this._actual);
}
return instance;
}
/**
* Builds the class instance with runtime validation only (no compile-time).
* Use this when building from external/dynamic data.
*
* @returns The built class instance
* @throws {Error} If validation fails
*/
buildWithoutCompileTimeValidation() {
const ctor = this.getClassConstructor();
const instance = new ctor(this._actual);
const dataKeys = Object.keys(this._actual);
const needsAssign = dataKeys.some((key) => instance[key] === void 0 && this._actual[key] !== void 0);
if (needsAssign) {
Object.assign(instance, this._actual);
}
return instance;
}
/**
* Builds the class instance without any validation.
* Use only when you're certain the object is valid.
*
* @returns The built class instance (may be incomplete)
*/
buildUnsafe() {
const ctor = this.getClassConstructor();
const instance = new ctor(this._actual);
const dataKeys = Object.keys(this._actual);
const needsAssign = dataKeys.some((key) => instance[key] === void 0 && this._actual[key] !== void 0);
if (needsAssign) {
Object.assign(instance, this._actual);
}
return instance;
}
/**
* Builds a partial object (may not have all required fields).
*
* @returns The partially built object
*/
buildPartial() {
return { ...this._actual };
}
/**
* Builds and freezes the class instance (shallow freeze).
*
* @returns The frozen class instance
* @throws {Error} If validation fails
*/
buildFrozen() {
const ctor = this.getClassConstructor();
const instance = new ctor(this._actual);
const dataKeys = Object.keys(this._actual);
const needsAssign = dataKeys.some((key) => instance[key] === void 0 && this._actual[key] !== void 0);
if (needsAssign) {
Object.assign(instance, this._actual);
}
return Object.freeze(instance);
}
/**
* Builds and deeply freezes the class instance.
*
* @returns The deeply frozen class instance
* @throws {Error} If validation fails
*/
buildDeepFrozen() {
const ctor = this.getClassConstructor();
const instance = new ctor(this._actual);
const dataKeys = Object.keys(this._actual);
const needsAssign = dataKeys.some((key) => instance[key] === void 0 && this._actual[key] !== void 0);
if (needsAssign) {
Object.assign(instance, this._actual);
}
return this.deepFreeze(instance);
}
/**
* Builds and seals the class instance (shallow freeze).
*
* @returns The sealed class instance
* @throws {Error} If validation fails
*/
buildSealed() {
const ctor = this.getClassConstructor();
const instance = new ctor(this._actual);
const dataKeys = Object.keys(this._actual);
const needsAssign = dataKeys.some((key) => instance[key] === void 0 && this._actual[key] !== void 0);
if (needsAssign) {
Object.assign(instance, this._actual);
}
return Object.seal(instance);
}
/**
* Builds and deeply seals the class instance.
*
* @returns The deeply sealed class instance
* @throws {Error} If validation fails
*/
buildDeepSealed() {
const ctor = this.getClassConstructor();
const instance = new ctor(this._actual);
const dataKeys = Object.keys(this._actual);
const needsAssign = dataKeys.some((key) => instance[key] === void 0 && this._actual[key] !== void 0);
if (needsAssign) {
Object.assign(instance, this._actual);
}
return this.deepSeal(instance);
}
/**
* Deep freeze helper.
* @private
*/
deepFreeze(obj) {
if (obj === null || typeof obj !== "object") {
return obj;
}
Object.getOwnPropertyNames(obj).forEach((prop) => {
const value = obj[prop];
if (value !== null && (typeof value === "object" || typeof value === "function")) {
this.deepFreeze(value);
}
});
return Object.freeze(obj);
}
/**
* Deep seal helper.
* @private
*/
deepSeal(obj) {
if (obj === null || typeof obj !== "object") {
return obj;
}
Object.getOwnPropertyNames(obj).forEach((prop) => {
const value = obj[prop];
if (value !== null && (typeof value === "object" || typeof value === "function")) {
this.deepSeal(value);
}
});
return Object.seal(obj);
}
/**
* Deep clone helper for nested objects.
* @private
*/
deepClone(obj) {
if (obj === null || typeof obj !== "object") {
return obj;
}
if (Array.isArray(obj)) {
return obj.map((item) => this.deepClone(item));
}
const cloned = {};
for (const key of Object.keys(obj)) {
cloned[key] = this.deepClone(obj[key]);
}
return cloned;
}
};
export {
CeriosBuilder
CeriosBuilder,
CeriosClassBuilder
};
//# sourceMappingURL=index.mjs.map

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/cerios-builder.ts"],"sourcesContent":["/**\n * Unique symbol used internally to brand types and track which properties have been set in the builder's type.\n *\n * @internal\n */\ndeclare const __brand: unique symbol;\n\n/**\n * Type utility for branding builder types with information about which properties have been set.\n * This is used to enforce compile-time safety for required fields in the builder pattern.\n *\n * @template T - The type representing the set of properties that have been set\n * @internal\n */\nexport type CeriosBrand<T> = { [__brand]: T };\n\n/**\n * Helper type to represent a path through an object structure\n * Handles optional properties by unwrapping them with NonNullable\n */\ntype PathImpl<T, K extends keyof T = keyof T> = K extends string | number\n\t? NonNullable<T[K]> extends Record<string, any>\n\t\t? NonNullable<T[K]> extends Array<any>\n\t\t\t? K\n\t\t\t: K | `${K}.${PathImpl<NonNullable<T[K]>> & string}`\n\t\t: K\n\t: never;\n\nexport type Path<T> = PathImpl<T>;\n\n/**\n * Helper type to get the value at a specific path, handling optional properties\n */\ntype PathValue<T, P> = P extends keyof T\n\t? T[P]\n\t: P extends `${infer K}.${infer Rest}`\n\t\t? K extends keyof T\n\t\t\t? PathValue<NonNullable<T[K]>, Rest>\n\t\t\t: never\n\t\t: never;\n\n/**\n * Type-safe template for defining required fields using an array of paths.\n * Simply list the paths that are required.\n */\nexport type RequiredFieldsTemplate<T> = ReadonlyArray<Path<T>>;\n\n/**\n * Recursively makes all properties readonly for deep immutability.\n * Handles arrays, objects, and primitive types.\n *\n * @template T - The type to make deeply readonly\n */\nexport type DeepReadonly<T> = T extends (infer R)[]\n\t? DeepReadonlyArray<R>\n\t: T extends (...args: any[]) => any\n\t\t? T\n\t\t: T extends object\n\t\t\t? DeepReadonlyObject<T>\n\t\t\t: T;\n\n/**\n * Helper type for deep readonly arrays\n * @internal\n */\ninterface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {}\n\n/**\n * Helper type for deep readonly objects\n * @internal\n */\ntype DeepReadonlyObject<T> = {\n\treadonly [P in keyof T]: DeepReadonly<T[P]>;\n};\n\n/**\n * Cache the root key extraction to avoid repeated computation\n * Handles optional properties by ensuring the key is valid for T\n * @internal\n */\ntype RootKey<P extends string, T = any> = P extends `${infer K}.${string}`\n\t? K extends keyof T\n\t\t? K\n\t\t: never\n\t: P extends keyof T\n\t\t? P\n\t\t: never;\n\n/**\n * Recursively freezes an object and all its nested properties.\n * @param obj - The object to freeze\n * @returns The frozen object\n * @internal\n */\nfunction deepFreeze<T>(obj: T): T {\n\t// Retrieve the property names defined on obj\n\tObject.getOwnPropertyNames(obj).forEach(prop => {\n\t\tconst value = (obj as any)[prop];\n\n\t\t// Freeze properties before freezing self\n\t\tif (value !== null && (typeof value === \"object\" || typeof value === \"function\")) {\n\t\t\tdeepFreeze(value);\n\t\t}\n\t});\n\n\treturn Object.freeze(obj);\n}\n\n/**\n * Recursively seals an object and all its nested properties.\n * @param obj - The object to seal\n * @returns The sealed object\n * @internal\n */\nfunction deepSeal<T>(obj: T): T {\n\t// Retrieve the property names defined on obj\n\tObject.getOwnPropertyNames(obj).forEach(prop => {\n\t\tconst value = (obj as any)[prop];\n\n\t\t// Seal properties before sealing self\n\t\tif (value !== null && (typeof value === \"object\" || typeof value === \"function\")) {\n\t\t\tdeepSeal(value);\n\t\t}\n\t});\n\n\treturn Object.seal(obj);\n}\n\n/**\n * Abstract base class for creating type-safe builders with automatic property setters and compile-time validation of required fields.\n *\n * This class is intended to be extended by concrete builder implementations for your own types.\n * It provides utility methods for setting properties and building the final object, ensuring that all required fields are set at compile time.\n *\n * Example usage:\n * ```typescript\n * interface MyType { foo: string; bar: number[]; }\n * class MyTypeBuilder extends CeriosBuilder<MyType> {\n * static requiredTemplate: RequiredFieldsTemplate<MyType> = ['foo'];\n * setFoo(value: string) { return this.setProperty('foo', value); }\n * addBar(value: number) { return this.addToArrayProperty('bar', value); }\n * }\n * // Usage:\n * const obj = new MyTypeBuilder({})\n * .setFoo('hello')\n * .addBar(42)\n * .buildSafe(); // Validates that 'foo' is set\n * ```\n *\n * @template T - The complete type being built\n */\nexport abstract class CeriosBuilder<T extends object> {\n\t/**\n\t * Template defining which fields are required for this builder.\n\t * Subclasses should override this to specify their required fields as an array of paths.\n\t * The template is type-safe - only valid paths from type T can be used.\n\t */\n\tstatic requiredTemplate?: ReadonlyArray<string>;\n\n\t/**\n\t * Instance-level required fields that can be populated dynamically.\n\t * This allows adding required fields at runtime via the setRequiredFields method.\n\t * @private\n\t */\n\tprivate _requiredFields: Set<string> = new Set();\n\n\t/**\n\t * Sets the required fields for this builder instance.\n\t * This allows you to dynamically define which fields are required.\n\t *\n\t * @param fields - Array of dot-notation paths to required fields\n\t * @returns The builder instance for chaining\n\t *\n\t * @example\n\t * ```typescript\n\t * const builder = new MyBuilder({})\n\t * .setRequiredFields(['path.to.field1', 'path.to.field2'])\n\t * .setField1('value1')\n\t * .setField2('value2')\n\t * .buildSafe();\n\t * ```\n\t */\n\tsetRequiredFields(fields: ReadonlyArray<Path<T>>): this {\n\t\tthis._requiredFields = new Set([...fields] as string[]);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Gets the combined required fields from both the static template and instance-level fields.\n\t * @private\n\t */\n\tprivate getRequiredTemplate(): ReadonlyArray<string> {\n\t\tconst ctor = this.constructor as typeof CeriosBuilder;\n\t\tconst staticFields = ctor.requiredTemplate || [];\n\t\tconst instanceFields = Array.from(this._requiredFields);\n\n\t\t// Combine and deduplicate\n\t\treturn [...new Set([...staticFields, ...instanceFields])];\n\t}\n\n\t/**\n\t * Validates that all fields in the required template have been set.\n\t * @private\n\t */\n\tprivate validateRequiredFields(): string[] {\n\t\tconst requiredPaths = this.getRequiredTemplate();\n\t\tconst missing: string[] = [];\n\n\t\tfor (const path of requiredPaths) {\n\t\t\tconst keys = path.split(\".\");\n\t\t\tlet current: any = this._actual;\n\n\t\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\t\tconst key = keys[i];\n\t\t\t\tif (current === null || current === undefined || !(key in current)) {\n\t\t\t\t\tmissing.push(path);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcurrent = current[key];\n\t\t\t}\n\n\t\t\t// Check if the final value is null or undefined\n\t\t\tif (current === null || current === undefined) {\n\t\t\t\tif (!missing.includes(path)) {\n\t\t\t\t\tmissing.push(path);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn missing;\n\t}\n\n\t/**\n\t * Creates a new builder instance. Intended to be called by subclasses.\n\t *\n\t * @param _actual - The current partial state of the object being built\n\t * @param _requiredFields - Optional array of required field paths to preserve across instances\n\t * @protected\n\t */\n\tprotected constructor(\n\t\tprotected readonly _actual: Partial<T>,\n\t\t_requiredFields?: RequiredFieldsTemplate<T>\n\t) {\n\t\tif (_requiredFields) {\n\t\t\tthis._requiredFields = new Set([..._requiredFields] as string[]);\n\t\t}\n\t}\n\n\t/**\n\t * Sets a property value and returns a new builder instance with updated type state.\n\t * This method is intended to be wrapped by concrete builder methods in subclasses.\n\t *\n\t * @template K - The property key being set\n\t * @param key - The property key to set\n\t * @param value - The value to assign to the property\n\t * @returns A new builder instance with the property set and type state updated\n\t * @protected\n\t */\n\tprotected setProperty<K extends keyof T>(key: K, value: T[K]): this & CeriosBrand<Pick<T, K>> {\n\t\tconst BuilderClass = this.constructor as new (data: any, requiredFields?: RequiredFieldsTemplate<T>) => any;\n\t\treturn new BuilderClass(\n\t\t\t{\n\t\t\t\t...this._actual,\n\t\t\t\t[key]: value,\n\t\t\t},\n\t\t\tArray.from(this._requiredFields) as unknown as RequiredFieldsTemplate<T>\n\t\t) as this & CeriosBrand<Pick<T, K>>;\n\t}\n\n\t/**\n\t * Sets multiple property values at once and returns a new builder instance with updated type state.\n\t * @param props - An object with one or more properties to set.\n\t * @returns A new builder instance with the properties set and type state updated.\n\t * @protected\n\t */\n\tprotected setProperties<K extends keyof T>(props: Pick<T, K>): this & CeriosBrand<Pick<T, K>> {\n\t\tconst BuilderClass = this.constructor as new (data: any, requiredFields?: RequiredFieldsTemplate<T>) => any;\n\t\treturn new BuilderClass(\n\t\t\t{\n\t\t\t\t...this._actual,\n\t\t\t\t...props,\n\t\t\t},\n\t\t\tArray.from(this._requiredFields) as unknown as RequiredFieldsTemplate<T>\n\t\t) as this & CeriosBrand<Pick<T, K>>;\n\t}\n\n\t/**\n\t * Sets a deeply nested property value and returns a new builder instance with updated type state.\n\t * This method uses dot notation to set nested properties in a type-safe way.\n\t *\n\t * @template P - The property path (e.g., \"parent.child.grandchild\")\n\t * @param path - The dot-notation path to the property\n\t * @param value - The value to assign to the nested property\n\t * @returns A new builder instance with the nested property set\n\t * @protected\n\t *\n\t * @example\n\t * ```typescript\n\t * builder.setNestedProperty('Order.Details.CustomerId', 'value')\n\t * ```\n\t */\n\tprotected setNestedProperty<P extends Path<T>>(\n\t\tpath: P,\n\t\tvalue: PathValue<T, P>\n\t): this & CeriosBrand<Pick<T, RootKey<P & string, T> extends never ? keyof T : RootKey<P & string, T>>> {\n\t\tconst BuilderClass = this.constructor as new (data: any, requiredFields?: RequiredFieldsTemplate<T>) => any;\n\t\tconst keys = (path as string).split(\".\");\n\t\tconst newActual = this.deepClone(this._actual);\n\n\t\tlet current: any = newActual;\n\t\tfor (let i = 0; i < keys.length - 1; i++) {\n\t\t\tconst key = keys[i];\n\t\t\tif (!(key in current) || typeof current[key] !== \"object\" || current[key] === null) {\n\t\t\t\tcurrent[key] = {};\n\t\t\t} else {\n\t\t\t\tcurrent[key] = this.deepClone(current[key]);\n\t\t\t}\n\t\t\tcurrent = current[key];\n\t\t}\n\n\t\tcurrent[keys[keys.length - 1]] = value;\n\n\t\treturn new BuilderClass(\n\t\t\tnewActual,\n\t\t\tArray.from(this._requiredFields) as unknown as RequiredFieldsTemplate<T>\n\t\t) as this & CeriosBrand<Pick<T, RootKey<P & string, T> extends never ? keyof T : RootKey<P & string, T>>>;\n\t}\n\n\t/**\n\t * Deep clone helper for nested objects\n\t * @private\n\t */\n\tprivate deepClone<V>(obj: V): V {\n\t\tif (obj === null || typeof obj !== \"object\") {\n\t\t\treturn obj;\n\t\t}\n\t\tif (Array.isArray(obj)) {\n\t\t\treturn obj.map(item => this.deepClone(item)) as any;\n\t\t}\n\t\tconst cloned: any = {};\n\t\tconst hasOwn = Object.prototype.hasOwnProperty;\n\t\tfor (const key in obj) {\n\t\t\tif (hasOwn.call(obj, key)) {\n\t\t\t\tcloned[key] = this.deepClone(obj[key]);\n\t\t\t}\n\t\t}\n\t\treturn cloned;\n\t}\n\n\t/**\n\t * Adds a value to an array property and returns a new builder instance with updated type state.\n\t * This method is intended to be wrapped by concrete builder methods in subclasses for array properties.\n\t *\n\t * @template K - The property key (must be an array property)\n\t * @template V - The type of the array element\n\t * @param key - The array property key to add to\n\t * @param value - The value to add to the array\n\t * @returns A new builder instance with the array property updated and type state updated\n\t * @protected\n\t */\n\tprotected addToArrayProperty<\n\t\tK extends { [P in keyof T]: NonNullable<T[P]> extends Array<any> ? P : never }[keyof T],\n\t\tV extends T[K] extends Array<infer U> ? U : T[K] extends Array<infer U> | undefined ? U : never,\n\t>(key: K, value: V): this & CeriosBrand<Pick<T, K>> {\n\t\tconst BuilderClass = this.constructor as new (data: any, requiredFields?: RequiredFieldsTemplate<T>) => any;\n\t\tconst currentArray = (this._actual[key] as Array<V> | undefined) ?? [];\n\t\treturn new BuilderClass(\n\t\t\t{\n\t\t\t\t...this._actual,\n\t\t\t\t[key]: [...currentArray, value],\n\t\t\t},\n\t\t\tArray.from(this._requiredFields) as unknown as RequiredFieldsTemplate<T>\n\t\t) as this & CeriosBrand<Pick<T, K>>;\n\t}\n\n\t/**\n\t * Builds the final object with both compile-time and runtime validation.\n\t * This is the recommended and safest way to build objects.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: Validates all fields in the requiredTemplate\n\t *\n\t * @returns The fully built object of type T\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuild(this: this & CeriosBrand<T>): T {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn this._actual as T;\n\t}\n\n\t/**\n\t * Builds the final object with only compile-time validation, skipping runtime checks.\n\t * Use this when you want TypeScript safety but need to skip runtime validation for performance.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: No validation\n\t *\n\t * @returns The fully built object of type T\n\t */\n\tbuildWithoutRuntimeValidation(this: this & CeriosBrand<T>): T {\n\t\treturn this._actual as T;\n\t}\n\n\t/**\n\t * Builds the final object with only runtime validation, skipping compile-time checks.\n\t * Use this when building from external data where compile-time checks aren't possible.\n\t *\n\t * - Compile-time: No TypeScript enforcement\n\t * - Runtime: Validates all fields in the requiredTemplate\n\t *\n\t * @returns The fully built object of type T\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildWithoutCompileTimeValidation(): T {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn this._actual as T;\n\t}\n\n\t/**\n\t * Builds the final object without any validation (neither compile-time nor runtime).\n\t * Use this only when you're certain the object is valid and need maximum performance.\n\t *\n\t * - Compile-time: No TypeScript enforcement\n\t * - Runtime: No validation\n\t *\n\t * @returns The object of type T (may be incomplete)\n\t */\n\tbuildUnsafe(): T {\n\t\treturn this._actual as T;\n\t}\n\n\t/**\n\t * Builds a partial object, which may not have all required fields set.\n\t * This is useful for scenarios where you want to inspect or validate the current state before finalizing.\n\t *\n\t * @returns The partially built object\n\t */\n\tbuildPartial(): Partial<T> {\n\t\treturn this._actual as Partial<T>;\n\t}\n\n\t/**\n\t * @deprecated Use build() instead. buildSafe() is now an alias for build().\n\t * Builds the final object with runtime validation using the requiredTemplate.\n\t * This method validates that all fields in the requiredTemplate array are present.\n\t *\n\t * @returns The fully built object of type T\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildSafe(): T {\n\t\treturn this.buildWithoutCompileTimeValidation();\n\t}\n\n\t/**\n\t * Builds and freezes the final object with both compile-time and runtime validation.\n\t * The returned object is shallowly frozen - top-level properties cannot be modified,\n\t * but nested objects remain mutable.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: Validates all fields in the requiredTemplate and applies Object.freeze()\n\t *\n\t * @returns The frozen object of type Readonly<T>\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildFrozen(this: this & CeriosBrand<T>): Readonly<T> {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn Object.freeze(this._actual as T);\n\t}\n\n\t/**\n\t * Builds and deeply freezes the final object with both compile-time and runtime validation.\n\t * The returned object is recursively frozen - all nested objects and arrays are also frozen.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: Validates all fields in the requiredTemplate and recursively applies Object.freeze()\n\t *\n\t * @returns The deeply frozen object of type DeepReadonly<T>\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildDeepFrozen(this: this & CeriosBrand<T>): DeepReadonly<T> {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn deepFreeze(this._actual as T) as DeepReadonly<T>;\n\t}\n\n\t/**\n\t * Builds and seals the final object with both compile-time and runtime validation.\n\t * The returned object is shallowly sealed - properties cannot be added or removed,\n\t * but existing properties can still be modified. Nested objects remain unsealed.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: Validates all fields in the requiredTemplate and applies Object.seal()\n\t *\n\t * @returns The sealed object of type T\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildSealed(this: this & CeriosBrand<T>): T {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn Object.seal(this._actual as T);\n\t}\n\n\t/**\n\t * Builds and deeply seals the final object with both compile-time and runtime validation.\n\t * The returned object is recursively sealed - properties cannot be added or removed at any level,\n\t * but existing properties can still be modified.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: Validates all fields in the requiredTemplate and recursively applies Object.seal()\n\t *\n\t * @returns The deeply sealed object of type T\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildDeepSealed(this: this & CeriosBrand<T>): T {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn deepSeal(this._actual as T);\n\t}\n}\n"],"mappings":"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","names":[]}
{"version":3,"sources":["../src/cerios-builder.ts","../src/cerios-class-builder.ts"],"sourcesContent":["import { DeepReadonly } from \"./types\";\n\n/**\n * Unique symbol used internally to brand types and track which properties have been set in the builder's type.\n *\n * @internal\n */\ndeclare const __brand: unique symbol;\n\n/**\n * Type utility for branding builder types with information about which properties have been set.\n * This is used to enforce compile-time safety for required fields in the builder pattern.\n *\n * @template T - The type representing the set of properties that have been set\n * @internal\n */\nexport type CeriosBrand<T> = { [__brand]: T };\n\n/**\n * Helper type to represent a path through an object structure\n * Handles optional properties by unwrapping them with NonNullable\n */\ntype PathImpl<T, K extends keyof T = keyof T> = K extends string | number\n\t? NonNullable<T[K]> extends Record<string, any>\n\t\t? NonNullable<T[K]> extends Array<any>\n\t\t\t? K\n\t\t\t: K | `${K}.${PathImpl<NonNullable<T[K]>> & string}`\n\t\t: K\n\t: never;\n\nexport type Path<T> = PathImpl<T>;\n\n/**\n * Helper type to get the value at a specific path, handling optional properties\n */\ntype PathValue<T, P> = P extends keyof T\n\t? T[P]\n\t: P extends `${infer K}.${infer Rest}`\n\t\t? K extends keyof T\n\t\t\t? PathValue<NonNullable<T[K]>, Rest>\n\t\t\t: never\n\t\t: never;\n\n/**\n * Type-safe template for defining required fields using an array of paths.\n * Simply list the paths that are required.\n */\nexport type RequiredFieldsTemplate<T> = ReadonlyArray<Path<T>>;\n\n/**\n * Cache the root key extraction to avoid repeated computation\n * Handles optional properties by ensuring the key is valid for T\n * @internal\n */\ntype RootKey<P extends string, T = any> = P extends `${infer K}.${string}`\n\t? K extends keyof T\n\t\t? K\n\t\t: never\n\t: P extends keyof T\n\t\t? P\n\t\t: never;\n\n/**\n * Recursively freezes an object and all its nested properties.\n * @param obj - The object to freeze\n * @returns The frozen object\n * @internal\n */\nfunction deepFreeze<T>(obj: T): T {\n\t// Retrieve the property names defined on obj\n\tObject.getOwnPropertyNames(obj).forEach(prop => {\n\t\tconst value = (obj as any)[prop];\n\n\t\t// Freeze properties before freezing self\n\t\tif (value !== null && (typeof value === \"object\" || typeof value === \"function\")) {\n\t\t\tdeepFreeze(value);\n\t\t}\n\t});\n\n\treturn Object.freeze(obj);\n}\n\n/**\n * Recursively seals an object and all its nested properties.\n * @param obj - The object to seal\n * @returns The sealed object\n * @internal\n */\nfunction deepSeal<T>(obj: T): T {\n\t// Retrieve the property names defined on obj\n\tObject.getOwnPropertyNames(obj).forEach(prop => {\n\t\tconst value = (obj as any)[prop];\n\n\t\t// Seal properties before sealing self\n\t\tif (value !== null && (typeof value === \"object\" || typeof value === \"function\")) {\n\t\t\tdeepSeal(value);\n\t\t}\n\t});\n\n\treturn Object.seal(obj);\n}\n\n/**\n * Abstract base class for creating type-safe builders with automatic property setters and compile-time validation of required fields.\n *\n * This class is intended to be extended by concrete builder implementations for your own types.\n * It provides utility methods for setting properties and building the final object, ensuring that all required fields are set at compile time.\n *\n * Example usage:\n * ```typescript\n * interface MyType { foo: string; bar: number[]; }\n * class MyTypeBuilder extends CeriosBuilder<MyType> {\n * static requiredTemplate: RequiredFieldsTemplate<MyType> = ['foo'];\n * setFoo(value: string) { return this.setProperty('foo', value); }\n * addBar(value: number) { return this.addToArrayProperty('bar', value); }\n * }\n * // Usage:\n * const obj = new MyTypeBuilder({})\n * .setFoo('hello')\n * .addBar(42)\n * .buildSafe(); // Validates that 'foo' is set\n * ```\n *\n * @template T - The complete type being built\n */\nexport abstract class CeriosBuilder<T extends object> {\n\t/**\n\t * Template defining which fields are required for this builder.\n\t * Subclasses should override this to specify their required fields as an array of paths.\n\t * The template is type-safe - only valid paths from type T can be used.\n\t */\n\tstatic requiredTemplate?: ReadonlyArray<string>;\n\n\t/**\n\t * Instance-level required fields that can be populated dynamically.\n\t * This allows adding required fields at runtime via the setRequiredFields method.\n\t * @private\n\t */\n\tprivate _requiredFields: Set<string> = new Set();\n\n\t/**\n\t * Sets the required fields for this builder instance.\n\t * This allows you to dynamically define which fields are required.\n\t *\n\t * @param fields - Array of dot-notation paths to required fields\n\t * @returns The builder instance for chaining\n\t *\n\t * @example\n\t * ```typescript\n\t * const builder = new MyBuilder({})\n\t * .setRequiredFields(['path.to.field1', 'path.to.field2'])\n\t * .setField1('value1')\n\t * .setField2('value2')\n\t * .buildSafe();\n\t * ```\n\t */\n\tsetRequiredFields(fields: ReadonlyArray<Path<T>>): this {\n\t\tthis._requiredFields = new Set([...fields] as string[]);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Gets the combined required fields from both the static template and instance-level fields.\n\t * @private\n\t */\n\tprivate getRequiredTemplate(): ReadonlyArray<string> {\n\t\tconst ctor = this.constructor as typeof CeriosBuilder;\n\t\tconst staticFields = ctor.requiredTemplate || [];\n\t\tconst instanceFields = Array.from(this._requiredFields);\n\n\t\t// Combine and deduplicate\n\t\treturn [...new Set([...staticFields, ...instanceFields])];\n\t}\n\n\t/**\n\t * Validates that all fields in the required template have been set.\n\t * @private\n\t */\n\tprivate validateRequiredFields(): string[] {\n\t\tconst requiredPaths = this.getRequiredTemplate();\n\t\tconst missing: string[] = [];\n\n\t\tfor (const path of requiredPaths) {\n\t\t\tconst keys = path.split(\".\");\n\t\t\tlet current: any = this._actual;\n\n\t\t\tfor (let i = 0; i < keys.length; i++) {\n\t\t\t\tconst key = keys[i];\n\t\t\t\tif (current === null || current === undefined || !(key in current)) {\n\t\t\t\t\tmissing.push(path);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcurrent = current[key];\n\t\t\t}\n\n\t\t\t// Check if the final value is null or undefined\n\t\t\tif (current === null || current === undefined) {\n\t\t\t\tif (!missing.includes(path)) {\n\t\t\t\t\tmissing.push(path);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn missing;\n\t}\n\n\t/**\n\t * Creates a new builder instance. Intended to be called by subclasses.\n\t *\n\t * @param _actual - The current partial state of the object being built\n\t * @param _requiredFields - Optional array of required field paths to preserve across instances\n\t * @protected\n\t */\n\tprotected constructor(\n\t\tprotected readonly _actual: Partial<T>,\n\t\t_requiredFields?: RequiredFieldsTemplate<T>\n\t) {\n\t\tif (_requiredFields) {\n\t\t\tthis._requiredFields = new Set([..._requiredFields] as string[]);\n\t\t}\n\t}\n\n\t/**\n\t * Sets a property value and returns a new builder instance with updated type state.\n\t * This method is intended to be wrapped by concrete builder methods in subclasses.\n\t *\n\t * @template K - The property key being set\n\t * @param key - The property key to set\n\t * @param value - The value to assign to the property\n\t * @returns A new builder instance with the property set and type state updated\n\t * @protected\n\t */\n\tprotected setProperty<K extends keyof T>(key: K, value: T[K]): this & CeriosBrand<Pick<T, K>> {\n\t\tconst BuilderClass = this.constructor as new (data: any, requiredFields?: RequiredFieldsTemplate<T>) => any;\n\t\treturn new BuilderClass(\n\t\t\t{\n\t\t\t\t...this._actual,\n\t\t\t\t[key]: value,\n\t\t\t},\n\t\t\tArray.from(this._requiredFields) as unknown as RequiredFieldsTemplate<T>\n\t\t) as this & CeriosBrand<Pick<T, K>>;\n\t}\n\n\t/**\n\t * Sets multiple property values at once and returns a new builder instance with updated type state.\n\t * @param props - An object with one or more properties to set.\n\t * @returns A new builder instance with the properties set and type state updated.\n\t * @protected\n\t */\n\tprotected setProperties<K extends keyof T>(props: Pick<T, K>): this & CeriosBrand<Pick<T, K>> {\n\t\tconst BuilderClass = this.constructor as new (data: any, requiredFields?: RequiredFieldsTemplate<T>) => any;\n\t\treturn new BuilderClass(\n\t\t\t{\n\t\t\t\t...this._actual,\n\t\t\t\t...props,\n\t\t\t},\n\t\t\tArray.from(this._requiredFields) as unknown as RequiredFieldsTemplate<T>\n\t\t) as this & CeriosBrand<Pick<T, K>>;\n\t}\n\n\t/**\n\t * Sets a deeply nested property value and returns a new builder instance with updated type state.\n\t * This method uses dot notation to set nested properties in a type-safe way.\n\t *\n\t * @template P - The property path (e.g., \"parent.child.grandchild\")\n\t * @param path - The dot-notation path to the property\n\t * @param value - The value to assign to the nested property\n\t * @returns A new builder instance with the nested property set\n\t * @protected\n\t *\n\t * @example\n\t * ```typescript\n\t * builder.setNestedProperty('Order.Details.CustomerId', 'value')\n\t * ```\n\t */\n\tprotected setNestedProperty<P extends Path<T>>(\n\t\tpath: P,\n\t\tvalue: PathValue<T, P>\n\t): this & CeriosBrand<Pick<T, RootKey<P & string, T> extends never ? keyof T : RootKey<P & string, T>>> {\n\t\tconst BuilderClass = this.constructor as new (data: any, requiredFields?: RequiredFieldsTemplate<T>) => any;\n\t\tconst keys = (path as string).split(\".\");\n\t\tconst newActual = this.deepClone(this._actual);\n\n\t\tlet current: any = newActual;\n\t\tfor (let i = 0; i < keys.length - 1; i++) {\n\t\t\tconst key = keys[i];\n\t\t\tif (!(key in current) || typeof current[key] !== \"object\" || current[key] === null) {\n\t\t\t\tcurrent[key] = {};\n\t\t\t} else {\n\t\t\t\tcurrent[key] = this.deepClone(current[key]);\n\t\t\t}\n\t\t\tcurrent = current[key];\n\t\t}\n\n\t\tcurrent[keys[keys.length - 1]] = value;\n\n\t\treturn new BuilderClass(\n\t\t\tnewActual,\n\t\t\tArray.from(this._requiredFields) as unknown as RequiredFieldsTemplate<T>\n\t\t) as this & CeriosBrand<Pick<T, RootKey<P & string, T> extends never ? keyof T : RootKey<P & string, T>>>;\n\t}\n\n\t/**\n\t * Deep clone helper for nested objects\n\t * @private\n\t */\n\tprivate deepClone<V>(obj: V): V {\n\t\tif (obj === null || typeof obj !== \"object\") {\n\t\t\treturn obj;\n\t\t}\n\t\tif (Array.isArray(obj)) {\n\t\t\treturn obj.map(item => this.deepClone(item)) as any;\n\t\t}\n\t\tconst cloned: any = {};\n\t\tconst hasOwn = Object.prototype.hasOwnProperty;\n\t\tfor (const key in obj) {\n\t\t\tif (hasOwn.call(obj, key)) {\n\t\t\t\tcloned[key] = this.deepClone(obj[key]);\n\t\t\t}\n\t\t}\n\t\treturn cloned;\n\t}\n\n\t/**\n\t * Adds a value to an array property and returns a new builder instance with updated type state.\n\t * This method is intended to be wrapped by concrete builder methods in subclasses for array properties.\n\t *\n\t * @template K - The property key (must be an array property)\n\t * @template V - The type of the array element\n\t * @param key - The array property key to add to\n\t * @param value - The value to add to the array\n\t * @returns A new builder instance with the array property updated and type state updated\n\t * @protected\n\t */\n\tprotected addToArrayProperty<\n\t\tK extends { [P in keyof T]: NonNullable<T[P]> extends Array<any> ? P : never }[keyof T],\n\t\tV extends T[K] extends Array<infer U> ? U : T[K] extends Array<infer U> | undefined ? U : never,\n\t>(key: K, value: V): this & CeriosBrand<Pick<T, K>> {\n\t\tconst BuilderClass = this.constructor as new (data: any, requiredFields?: RequiredFieldsTemplate<T>) => any;\n\t\tconst currentArray = (this._actual[key] as Array<V> | undefined) ?? [];\n\t\treturn new BuilderClass(\n\t\t\t{\n\t\t\t\t...this._actual,\n\t\t\t\t[key]: [...currentArray, value],\n\t\t\t},\n\t\t\tArray.from(this._requiredFields) as unknown as RequiredFieldsTemplate<T>\n\t\t) as this & CeriosBrand<Pick<T, K>>;\n\t}\n\n\t/**\n\t * Builds the final object with both compile-time and runtime validation.\n\t * This is the recommended and safest way to build objects.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: Validates all fields in the requiredTemplate\n\t *\n\t * @returns The fully built object of type T\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuild(this: this & CeriosBrand<T>): T {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn this._actual as T;\n\t}\n\n\t/**\n\t * Builds the final object with only compile-time validation, skipping runtime checks.\n\t * Use this when you want TypeScript safety but need to skip runtime validation for performance.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: No validation\n\t *\n\t * @returns The fully built object of type T\n\t */\n\tbuildWithoutRuntimeValidation(this: this & CeriosBrand<T>): T {\n\t\treturn this._actual as T;\n\t}\n\n\t/**\n\t * Builds the final object with only runtime validation, skipping compile-time checks.\n\t * Use this when building from external data where compile-time checks aren't possible.\n\t *\n\t * - Compile-time: No TypeScript enforcement\n\t * - Runtime: Validates all fields in the requiredTemplate\n\t *\n\t * @returns The fully built object of type T\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildWithoutCompileTimeValidation(): T {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn this._actual as T;\n\t}\n\n\t/**\n\t * Builds the final object without any validation (neither compile-time nor runtime).\n\t * Use this only when you're certain the object is valid and need maximum performance.\n\t *\n\t * - Compile-time: No TypeScript enforcement\n\t * - Runtime: No validation\n\t *\n\t * @returns The object of type T (may be incomplete)\n\t */\n\tbuildUnsafe(): T {\n\t\treturn this._actual as T;\n\t}\n\n\t/**\n\t * Builds a partial object, which may not have all required fields set.\n\t * This is useful for scenarios where you want to inspect or validate the current state before finalizing.\n\t *\n\t * @returns The partially built object\n\t */\n\tbuildPartial(): Partial<T> {\n\t\treturn this._actual as Partial<T>;\n\t}\n\n\t/**\n\t * @deprecated Use build() instead. buildSafe() is now an alias for build().\n\t * Builds the final object with runtime validation using the requiredTemplate.\n\t * This method validates that all fields in the requiredTemplate array are present.\n\t *\n\t * @returns The fully built object of type T\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildSafe(): T {\n\t\treturn this.buildWithoutCompileTimeValidation();\n\t}\n\n\t/**\n\t * Builds and freezes the final object with both compile-time and runtime validation.\n\t * The returned object is shallowly frozen - top-level properties cannot be modified,\n\t * but nested objects remain mutable.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: Validates all fields in the requiredTemplate and applies Object.freeze()\n\t *\n\t * @returns The frozen object of type Readonly<T>\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildFrozen(this: this & CeriosBrand<T>): Readonly<T> {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn Object.freeze(this._actual as T);\n\t}\n\n\t/**\n\t * Builds and deeply freezes the final object with both compile-time and runtime validation.\n\t * The returned object is recursively frozen - all nested objects and arrays are also frozen.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: Validates all fields in the requiredTemplate and recursively applies Object.freeze()\n\t *\n\t * @returns The deeply frozen object of type DeepReadonly<T>\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildDeepFrozen(this: this & CeriosBrand<T>): DeepReadonly<T> {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn deepFreeze(this._actual as T) as DeepReadonly<T>;\n\t}\n\n\t/**\n\t * Builds and seals the final object with both compile-time and runtime validation.\n\t * The returned object is shallowly sealed - properties cannot be added or removed,\n\t * but existing properties can still be modified. Nested objects remain unsealed.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: Validates all fields in the requiredTemplate and applies Object.seal()\n\t *\n\t * @returns The sealed object of type T\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildSealed(this: this & CeriosBrand<T>): T {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn Object.seal(this._actual as T);\n\t}\n\n\t/**\n\t * Builds and deeply seals the final object with both compile-time and runtime validation.\n\t * The returned object is recursively sealed - properties cannot be added or removed at any level,\n\t * but existing properties can still be modified.\n\t *\n\t * - Compile-time: TypeScript enforces all required properties are set\n\t * - Runtime: Validates all fields in the requiredTemplate and recursively applies Object.seal()\n\t *\n\t * @returns The deeply sealed object of type T\n\t * @throws {Error} If any required field is missing at runtime\n\t */\n\tbuildDeepSealed(this: this & CeriosBrand<T>): T {\n\t\tconst missing = this.validateRequiredFields();\n\n\t\tif (missing.length > 0) {\n\t\t\tthrow new Error(`Missing required fields: ${missing.join(\", \")}. Please set these fields before calling build.`);\n\t\t}\n\n\t\treturn deepSeal(this._actual as T);\n\t}\n}\n","import type { DeepReadonly } from \"./types\";\n\n/**\n * Type representing a class constructor that can be instantiated with optional partial data.\n * @template T - The type that the constructor creates\n */\nexport type ClassConstructor<T> = new (data?: Partial<T>) => T;\n\n/**\n * Helper to extract only data properties (exclude methods) from a class type.\n * This allows compile-time validation to work properly with classes.\n */\ntype DataPropertiesOnly<T> = {\n\t[K in keyof T as T[K] extends (...args: any[]) => any ? never : K]: T[K];\n};\n\n/**\n * Brand type specifically for class builders that only tracks data properties.\n */\nexport type CeriosClassBrand<T> = {\n\treadonly __classBuilderBrand: T;\n};\n\n/**\n * Type-safe builder specifically designed for classes.\n * This builder automatically instantiates the target class and provides:\n * - Compile-time validation that works with class methods\n * - Automatic runtime validation of nested class instances\n * - Preservation of decorators and class methods\n *\n * Example usage:\n * ```typescript\n * class Person {\n * name!: string;\n * age!: number;\n * email?: string;\n *\n * constructor(data?: Partial<Person>) {\n * if (data) Object.assign(this, data);\n * }\n *\n * greet() { return `Hello, I'm ${this.name}`; }\n * }\n *\n * const builder = new CeriosClassBuilder(Person);\n * const person = builder\n * .setProperty('name', 'John')\n * .setProperty('age', 30)\n * .build();\n * ```\n *\n * @template T - The class type being built\n */\nexport class CeriosClassBuilder<T extends object> {\n\t/**\n\t * The class constructor to instantiate when building.\n\t * @private\n\t */\n\tprivate readonly _classConstructor: ClassConstructor<T>;\n\n\t/**\n\t * The current partial state of the object being built.\n\t * @private\n\t */\n\tprotected readonly _actual: Partial<T>;\n\n\t/**\n\t * Creates a new class builder instance.\n\t * @param classConstructor - The class constructor to use for building\n\t * @param data - Optional initial data\n\t */\n\tprotected constructor(classConstructor: ClassConstructor<T>, data: Partial<T> = {}) {\n\t\tthis._classConstructor = classConstructor;\n\t\tthis._actual = data;\n\t}\n\n\t/**\n\t * Gets the class constructor for this builder.\n\t * @private\n\t */\n\tprivate getClassConstructor(): ClassConstructor<T> {\n\t\treturn this._classConstructor;\n\t}\n\n\t/**\n\t * Creates a new instance of the builder with updated data.\n\t * Subclasses can override this to return the correct subclass type.\n\t * @private\n\t */\n\tprivate createBuilder(data: Partial<T>): this {\n\t\tconst BuilderClass = this.constructor as new (classConstructor: ClassConstructor<T>, data: Partial<T>) => this;\n\t\treturn new BuilderClass(this._classConstructor, data);\n\t}\n\n\t/**\n\t * Sets a property value and returns a new builder instance with updated type state.\n\t * @template K - The property key being set\n\t * @param key - The property key to set\n\t * @param value - The value to assign to the property\n\t * @returns A new builder instance with the property set\n\t */\n\tsetProperty<K extends keyof DataPropertiesOnly<T>>(\n\t\tkey: K,\n\t\tvalue: DataPropertiesOnly<T>[K]\n\t): this & CeriosClassBrand<Pick<DataPropertiesOnly<T>, K>> {\n\t\tconst newBuilder = this.createBuilder({\n\t\t\t...this._actual,\n\t\t\t[key]: value,\n\t\t} as Partial<T>);\n\t\treturn newBuilder as this & CeriosClassBrand<Pick<DataPropertiesOnly<T>, K>>;\n\t}\n\n\t/**\n\t * Sets multiple properties at once.\n\t * @template K - The property keys being set\n\t * @param props - Object with properties to set\n\t * @returns A new builder instance with the properties set\n\t */\n\tsetProperties<K extends keyof DataPropertiesOnly<T>>(\n\t\tprops: Pick<DataPropertiesOnly<T>, K>\n\t): this & CeriosClassBrand<Pick<DataPropertiesOnly<T>, K>> {\n\t\tconst newBuilder = this.createBuilder({\n\t\t\t...this._actual,\n\t\t\t...props,\n\t\t} as Partial<T>);\n\t\treturn newBuilder as this & CeriosClassBrand<Pick<DataPropertiesOnly<T>, K>>;\n\t}\n\n\t/**\n\t * Adds a value to an array property.\n\t * @template K - The array property key\n\t * @template V - The array element type\n\t * @param key - The array property key\n\t * @param value - The value to add to the array\n\t * @returns A new builder instance with the value added\n\t */\n\taddToArrayProperty<\n\t\tK extends {\n\t\t\t[P in keyof DataPropertiesOnly<T>]: NonNullable<DataPropertiesOnly<T>[P]> extends Array<any> ? P : never;\n\t\t}[keyof DataPropertiesOnly<T>],\n\t\tV extends DataPropertiesOnly<T>[K] extends Array<infer U>\n\t\t\t? U\n\t\t\t: DataPropertiesOnly<T>[K] extends Array<infer U> | undefined\n\t\t\t\t? U\n\t\t\t\t: never,\n\t>(key: K, value: V): this & CeriosClassBrand<Pick<DataPropertiesOnly<T>, K>> {\n\t\tconst currentArray = (this._actual[key as keyof T] as Array<V> | undefined) ?? [];\n\t\tconst newBuilder = this.createBuilder({\n\t\t\t...this._actual,\n\t\t\t[key]: [...currentArray, value],\n\t\t} as Partial<T>);\n\t\treturn newBuilder as this & CeriosClassBrand<Pick<DataPropertiesOnly<T>, K>>;\n\t}\n\n\t/**\n\t * Builds the final class instance with compile-time and runtime validation.\n\t * - Compile-time: TypeScript enforces all data properties are set\n\t * - Runtime: Validates nested class instances are properly instantiated\n\t *\n\t * @returns The fully built and validated class instance\n\t * @throws {Error} If nested validation fails\n\t */\n\tbuild(this: this & CeriosClassBrand<DataPropertiesOnly<T>>): T {\n\t\tconst ctor = this.getClassConstructor();\n\t\tconst instance: T = new ctor(this._actual as T);\n\t\t// If the class does not assign properties in the constructor, assign them manually\n\t\tconst dataKeys = Object.keys(this._actual) as (keyof T)[];\n\t\tconst needsAssign = dataKeys.some(key => instance[key] === undefined && this._actual[key] !== undefined);\n\t\tif (needsAssign) {\n\t\t\tObject.assign(instance, this._actual);\n\t\t}\n\t\treturn instance;\n\t}\n\n\t/**\n\t * Builds the class instance with runtime validation only (no compile-time).\n\t * Use this when building from external/dynamic data.\n\t *\n\t * @returns The built class instance\n\t * @throws {Error} If validation fails\n\t */\n\tbuildWithoutCompileTimeValidation(): T {\n\t\tconst ctor = this.getClassConstructor();\n\t\tconst instance: T = new ctor(this._actual as T);\n\t\tconst dataKeys = Object.keys(this._actual) as (keyof T)[];\n\t\tconst needsAssign = dataKeys.some(key => instance[key] === undefined && this._actual[key] !== undefined);\n\t\tif (needsAssign) {\n\t\t\tObject.assign(instance, this._actual);\n\t\t}\n\t\treturn instance;\n\t}\n\n\t/**\n\t * Builds the class instance without any validation.\n\t * Use only when you're certain the object is valid.\n\t *\n\t * @returns The built class instance (may be incomplete)\n\t */\n\tbuildUnsafe(): T {\n\t\tconst ctor = this.getClassConstructor();\n\t\tconst instance: T = new ctor(this._actual as T);\n\t\tconst dataKeys = Object.keys(this._actual) as (keyof T)[];\n\t\tconst needsAssign = dataKeys.some(key => instance[key] === undefined && this._actual[key] !== undefined);\n\t\tif (needsAssign) {\n\t\t\tObject.assign(instance, this._actual);\n\t\t}\n\t\treturn instance;\n\t}\n\n\t/**\n\t * Builds a partial object (may not have all required fields).\n\t *\n\t * @returns The partially built object\n\t */\n\tbuildPartial(): Partial<T> {\n\t\treturn { ...this._actual };\n\t}\n\n\t/**\n\t * Builds and freezes the class instance (shallow freeze).\n\t *\n\t * @returns The frozen class instance\n\t * @throws {Error} If validation fails\n\t */\n\tbuildFrozen(this: this & CeriosClassBrand<DataPropertiesOnly<T>>): Readonly<T> {\n\t\tconst ctor = this.getClassConstructor();\n\t\tconst instance: T = new ctor(this._actual as T);\n\t\t// If the class does not assign properties in the constructor, assign them manually\n\t\tconst dataKeys = Object.keys(this._actual) as (keyof T)[];\n\t\tconst needsAssign = dataKeys.some(key => instance[key] === undefined && this._actual[key] !== undefined);\n\t\tif (needsAssign) {\n\t\t\tObject.assign(instance, this._actual);\n\t\t}\n\t\treturn Object.freeze(instance);\n\t}\n\n\t/**\n\t * Builds and deeply freezes the class instance.\n\t *\n\t * @returns The deeply frozen class instance\n\t * @throws {Error} If validation fails\n\t */\n\tbuildDeepFrozen(this: this & CeriosClassBrand<DataPropertiesOnly<T>>): DeepReadonly<T> {\n\t\tconst ctor = this.getClassConstructor();\n\t\tconst instance: T = new ctor(this._actual as T);\n\t\t// If the class does not assign properties in the constructor, assign them manually\n\t\tconst dataKeys = Object.keys(this._actual) as (keyof T)[];\n\t\tconst needsAssign = dataKeys.some(key => instance[key] === undefined && this._actual[key] !== undefined);\n\t\tif (needsAssign) {\n\t\t\tObject.assign(instance, this._actual);\n\t\t}\n\t\treturn this.deepFreeze(instance) as DeepReadonly<T>;\n\t}\n\n\t/**\n\t * Builds and seals the class instance (shallow freeze).\n\t *\n\t * @returns The sealed class instance\n\t * @throws {Error} If validation fails\n\t */\n\tbuildSealed(this: this & CeriosClassBrand<DataPropertiesOnly<T>>): T {\n\t\tconst ctor = this.getClassConstructor();\n\t\tconst instance: T = new ctor(this._actual as T);\n\t\t// If the class does not assign properties in the constructor, assign them manually\n\t\tconst dataKeys = Object.keys(this._actual) as (keyof T)[];\n\t\tconst needsAssign = dataKeys.some(key => instance[key] === undefined && this._actual[key] !== undefined);\n\t\tif (needsAssign) {\n\t\t\tObject.assign(instance, this._actual);\n\t\t}\n\t\treturn Object.seal(instance);\n\t}\n\n\t/**\n\t * Builds and deeply seals the class instance.\n\t *\n\t * @returns The deeply sealed class instance\n\t * @throws {Error} If validation fails\n\t */\n\tbuildDeepSealed(this: this & CeriosClassBrand<DataPropertiesOnly<T>>): T {\n\t\tconst ctor = this.getClassConstructor();\n\t\tconst instance: T = new ctor(this._actual as T);\n\t\t// If the class does not assign properties in the constructor, assign them manually\n\t\tconst dataKeys = Object.keys(this._actual) as (keyof T)[];\n\t\tconst needsAssign = dataKeys.some(key => instance[key] === undefined && this._actual[key] !== undefined);\n\t\tif (needsAssign) {\n\t\t\tObject.assign(instance, this._actual);\n\t\t}\n\t\treturn this.deepSeal(instance);\n\t}\n\n\t/**\n\t * Deep freeze helper.\n\t * @private\n\t */\n\tprivate deepFreeze<V>(obj: V): V {\n\t\tif (obj === null || typeof obj !== \"object\") {\n\t\t\treturn obj;\n\t\t}\n\t\tObject.getOwnPropertyNames(obj).forEach(prop => {\n\t\t\tconst value = (obj as any)[prop];\n\t\t\tif (value !== null && (typeof value === \"object\" || typeof value === \"function\")) {\n\t\t\t\tthis.deepFreeze(value);\n\t\t\t}\n\t\t});\n\t\treturn Object.freeze(obj);\n\t}\n\n\t/**\n\t * Deep seal helper.\n\t * @private\n\t */\n\tprivate deepSeal<V>(obj: V): V {\n\t\tif (obj === null || typeof obj !== \"object\") {\n\t\t\treturn obj;\n\t\t}\n\t\tObject.getOwnPropertyNames(obj).forEach(prop => {\n\t\t\tconst value = (obj as any)[prop];\n\t\t\tif (value !== null && (typeof value === \"object\" || typeof value === \"function\")) {\n\t\t\t\tthis.deepSeal(value);\n\t\t\t}\n\t\t});\n\t\treturn Object.seal(obj);\n\t}\n\n\t/**\n\t * Deep clone helper for nested objects.\n\t * @private\n\t */\n\tprivate deepClone<V>(obj: V): V {\n\t\tif (obj === null || typeof obj !== \"object\") {\n\t\t\treturn obj;\n\t\t}\n\t\tif (Array.isArray(obj)) {\n\t\t\treturn obj.map(item => this.deepClone(item)) as any;\n\t\t}\n\t\tconst cloned: any = {};\n\t\tfor (const key of Object.keys(obj)) {\n\t\t\tcloned[key] = this.deepClone((obj as any)[key]);\n\t\t}\n\t\treturn cloned;\n\t}\n}\n"],"mappings":";AAoEA,SAAS,WAAc,KAAW;AAEjC,SAAO,oBAAoB,GAAG,EAAE,QAAQ,UAAQ;AAC/C,UAAM,QAAS,IAAY,IAAI;AAG/B,QAAI,UAAU,SAAS,OAAO,UAAU,YAAY,OAAO,UAAU,aAAa;AACjF,iBAAW,KAAK;AAAA,IACjB;AAAA,EACD,CAAC;AAED,SAAO,OAAO,OAAO,GAAG;AACzB;AAQA,SAAS,SAAY,KAAW;AAE/B,SAAO,oBAAoB,GAAG,EAAE,QAAQ,UAAQ;AAC/C,UAAM,QAAS,IAAY,IAAI;AAG/B,QAAI,UAAU,SAAS,OAAO,UAAU,YAAY,OAAO,UAAU,aAAa;AACjF,eAAS,KAAK;AAAA,IACf;AAAA,EACD,CAAC;AAED,SAAO,OAAO,KAAK,GAAG;AACvB;AAyBO,IAAe,gBAAf,MAA+C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwF3C,YACU,SACnB,iBACC;AAFkB;AA5EpB;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,kBAA+B,oBAAI,IAAI;AA+E9C,QAAI,iBAAiB;AACpB,WAAK,kBAAkB,oBAAI,IAAI,CAAC,GAAG,eAAe,CAAa;AAAA,IAChE;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAhEA,kBAAkB,QAAsC;AACvD,SAAK,kBAAkB,oBAAI,IAAI,CAAC,GAAG,MAAM,CAAa;AACtD,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,sBAA6C;AACpD,UAAM,OAAO,KAAK;AAClB,UAAM,eAAe,KAAK,oBAAoB,CAAC;AAC/C,UAAM,iBAAiB,MAAM,KAAK,KAAK,eAAe;AAGtD,WAAO,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,cAAc,GAAG,cAAc,CAAC,CAAC;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,yBAAmC;AAC1C,UAAM,gBAAgB,KAAK,oBAAoB;AAC/C,UAAM,UAAoB,CAAC;AAE3B,eAAW,QAAQ,eAAe;AACjC,YAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,UAAI,UAAe,KAAK;AAExB,eAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACrC,cAAM,MAAM,KAAK,CAAC;AAClB,YAAI,YAAY,QAAQ,YAAY,UAAa,EAAE,OAAO,UAAU;AACnE,kBAAQ,KAAK,IAAI;AACjB;AAAA,QACD;AACA,kBAAU,QAAQ,GAAG;AAAA,MACtB;AAGA,UAAI,YAAY,QAAQ,YAAY,QAAW;AAC9C,YAAI,CAAC,QAAQ,SAAS,IAAI,GAAG;AAC5B,kBAAQ,KAAK,IAAI;AAAA,QAClB;AAAA,MACD;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA4BU,YAA+B,KAAQ,OAA6C;AAC7F,UAAM,eAAe,KAAK;AAC1B,WAAO,IAAI;AAAA,MACV;AAAA,QACC,GAAG,KAAK;AAAA,QACR,CAAC,GAAG,GAAG;AAAA,MACR;AAAA,MACA,MAAM,KAAK,KAAK,eAAe;AAAA,IAChC;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQU,cAAiC,OAAmD;AAC7F,UAAM,eAAe,KAAK;AAC1B,WAAO,IAAI;AAAA,MACV;AAAA,QACC,GAAG,KAAK;AAAA,QACR,GAAG;AAAA,MACJ;AAAA,MACA,MAAM,KAAK,KAAK,eAAe;AAAA,IAChC;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBU,kBACT,MACA,OACuG;AACvG,UAAM,eAAe,KAAK;AAC1B,UAAM,OAAQ,KAAgB,MAAM,GAAG;AACvC,UAAM,YAAY,KAAK,UAAU,KAAK,OAAO;AAE7C,QAAI,UAAe;AACnB,aAAS,IAAI,GAAG,IAAI,KAAK,SAAS,GAAG,KAAK;AACzC,YAAM,MAAM,KAAK,CAAC;AAClB,UAAI,EAAE,OAAO,YAAY,OAAO,QAAQ,GAAG,MAAM,YAAY,QAAQ,GAAG,MAAM,MAAM;AACnF,gBAAQ,GAAG,IAAI,CAAC;AAAA,MACjB,OAAO;AACN,gBAAQ,GAAG,IAAI,KAAK,UAAU,QAAQ,GAAG,CAAC;AAAA,MAC3C;AACA,gBAAU,QAAQ,GAAG;AAAA,IACtB;AAEA,YAAQ,KAAK,KAAK,SAAS,CAAC,CAAC,IAAI;AAEjC,WAAO,IAAI;AAAA,MACV;AAAA,MACA,MAAM,KAAK,KAAK,eAAe;AAAA,IAChC;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,UAAa,KAAW;AAC/B,QAAI,QAAQ,QAAQ,OAAO,QAAQ,UAAU;AAC5C,aAAO;AAAA,IACR;AACA,QAAI,MAAM,QAAQ,GAAG,GAAG;AACvB,aAAO,IAAI,IAAI,UAAQ,KAAK,UAAU,IAAI,CAAC;AAAA,IAC5C;AACA,UAAM,SAAc,CAAC;AACrB,UAAM,SAAS,OAAO,UAAU;AAChC,eAAW,OAAO,KAAK;AACtB,UAAI,OAAO,KAAK,KAAK,GAAG,GAAG;AAC1B,eAAO,GAAG,IAAI,KAAK,UAAU,IAAI,GAAG,CAAC;AAAA,MACtC;AAAA,IACD;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaU,mBAGR,KAAQ,OAA0C;AAjVrD;AAkVE,UAAM,eAAe,KAAK;AAC1B,UAAM,gBAAgB,UAAK,QAAQ,GAAG,MAAhB,YAA8C,CAAC;AACrE,WAAO,IAAI;AAAA,MACV;AAAA,QACC,GAAG,KAAK;AAAA,QACR,CAAC,GAAG,GAAG,CAAC,GAAG,cAAc,KAAK;AAAA,MAC/B;AAAA,MACA,MAAM,KAAK,KAAK,eAAe;AAAA,IAChC;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,QAAsC;AACrC,UAAM,UAAU,KAAK,uBAAuB;AAE5C,QAAI,QAAQ,SAAS,GAAG;AACvB,YAAM,IAAI,MAAM,4BAA4B,QAAQ,KAAK,IAAI,CAAC,iDAAiD;AAAA,IAChH;AAEA,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,gCAA8D;AAC7D,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,oCAAuC;AACtC,UAAM,UAAU,KAAK,uBAAuB;AAE5C,QAAI,QAAQ,SAAS,GAAG;AACvB,YAAM,IAAI,MAAM,4BAA4B,QAAQ,KAAK,IAAI,CAAC,iDAAiD;AAAA,IAChH;AAEA,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,cAAiB;AAChB,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,eAA2B;AAC1B,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,YAAe;AACd,WAAO,KAAK,kCAAkC;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,cAAsD;AACrD,UAAM,UAAU,KAAK,uBAAuB;AAE5C,QAAI,QAAQ,SAAS,GAAG;AACvB,YAAM,IAAI,MAAM,4BAA4B,QAAQ,KAAK,IAAI,CAAC,iDAAiD;AAAA,IAChH;AAEA,WAAO,OAAO,OAAO,KAAK,OAAY;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,kBAA8D;AAC7D,UAAM,UAAU,KAAK,uBAAuB;AAE5C,QAAI,QAAQ,SAAS,GAAG;AACvB,YAAM,IAAI,MAAM,4BAA4B,QAAQ,KAAK,IAAI,CAAC,iDAAiD;AAAA,IAChH;AAEA,WAAO,WAAW,KAAK,OAAY;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,cAA4C;AAC3C,UAAM,UAAU,KAAK,uBAAuB;AAE5C,QAAI,QAAQ,SAAS,GAAG;AACvB,YAAM,IAAI,MAAM,4BAA4B,QAAQ,KAAK,IAAI,CAAC,iDAAiD;AAAA,IAChH;AAEA,WAAO,OAAO,KAAK,KAAK,OAAY;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,kBAAgD;AAC/C,UAAM,UAAU,KAAK,uBAAuB;AAE5C,QAAI,QAAQ,SAAS,GAAG;AACvB,YAAM,IAAI,MAAM,4BAA4B,QAAQ,KAAK,IAAI,CAAC,iDAAiD;AAAA,IAChH;AAEA,WAAO,SAAS,KAAK,OAAY;AAAA,EAClC;AACD;;;ACldO,IAAM,qBAAN,MAA2C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBvC,YAAY,kBAAuC,OAAmB,CAAC,GAAG;AACnF,SAAK,oBAAoB;AACzB,SAAK,UAAU;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,sBAA2C;AAClD,WAAO,KAAK;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,cAAc,MAAwB;AAC7C,UAAM,eAAe,KAAK;AAC1B,WAAO,IAAI,aAAa,KAAK,mBAAmB,IAAI;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,YACC,KACA,OAC0D;AAC1D,UAAM,aAAa,KAAK,cAAc;AAAA,MACrC,GAAG,KAAK;AAAA,MACR,CAAC,GAAG,GAAG;AAAA,IACR,CAAe;AACf,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,cACC,OAC0D;AAC1D,UAAM,aAAa,KAAK,cAAc;AAAA,MACrC,GAAG,KAAK;AAAA,MACR,GAAG;AAAA,IACJ,CAAe;AACf,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,mBASE,KAAQ,OAAmE;AAjJ9E;AAkJE,UAAM,gBAAgB,UAAK,QAAQ,GAAc,MAA3B,YAAyD,CAAC;AAChF,UAAM,aAAa,KAAK,cAAc;AAAA,MACrC,GAAG,KAAK;AAAA,MACR,CAAC,GAAG,GAAG,CAAC,GAAG,cAAc,KAAK;AAAA,IAC/B,CAAe;AACf,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,QAA+D;AAC9D,UAAM,OAAO,KAAK,oBAAoB;AACtC,UAAM,WAAc,IAAI,KAAK,KAAK,OAAY;AAE9C,UAAM,WAAW,OAAO,KAAK,KAAK,OAAO;AACzC,UAAM,cAAc,SAAS,KAAK,SAAO,SAAS,GAAG,MAAM,UAAa,KAAK,QAAQ,GAAG,MAAM,MAAS;AACvG,QAAI,aAAa;AAChB,aAAO,OAAO,UAAU,KAAK,OAAO;AAAA,IACrC;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,oCAAuC;AACtC,UAAM,OAAO,KAAK,oBAAoB;AACtC,UAAM,WAAc,IAAI,KAAK,KAAK,OAAY;AAC9C,UAAM,WAAW,OAAO,KAAK,KAAK,OAAO;AACzC,UAAM,cAAc,SAAS,KAAK,SAAO,SAAS,GAAG,MAAM,UAAa,KAAK,QAAQ,GAAG,MAAM,MAAS;AACvG,QAAI,aAAa;AAChB,aAAO,OAAO,UAAU,KAAK,OAAO;AAAA,IACrC;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,cAAiB;AAChB,UAAM,OAAO,KAAK,oBAAoB;AACtC,UAAM,WAAc,IAAI,KAAK,KAAK,OAAY;AAC9C,UAAM,WAAW,OAAO,KAAK,KAAK,OAAO;AACzC,UAAM,cAAc,SAAS,KAAK,SAAO,SAAS,GAAG,MAAM,UAAa,KAAK,QAAQ,GAAG,MAAM,MAAS;AACvG,QAAI,aAAa;AAChB,aAAO,OAAO,UAAU,KAAK,OAAO;AAAA,IACrC;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,eAA2B;AAC1B,WAAO,EAAE,GAAG,KAAK,QAAQ;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,cAA+E;AAC9E,UAAM,OAAO,KAAK,oBAAoB;AACtC,UAAM,WAAc,IAAI,KAAK,KAAK,OAAY;AAE9C,UAAM,WAAW,OAAO,KAAK,KAAK,OAAO;AACzC,UAAM,cAAc,SAAS,KAAK,SAAO,SAAS,GAAG,MAAM,UAAa,KAAK,QAAQ,GAAG,MAAM,MAAS;AACvG,QAAI,aAAa;AAChB,aAAO,OAAO,UAAU,KAAK,OAAO;AAAA,IACrC;AACA,WAAO,OAAO,OAAO,QAAQ;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,kBAAuF;AACtF,UAAM,OAAO,KAAK,oBAAoB;AACtC,UAAM,WAAc,IAAI,KAAK,KAAK,OAAY;AAE9C,UAAM,WAAW,OAAO,KAAK,KAAK,OAAO;AACzC,UAAM,cAAc,SAAS,KAAK,SAAO,SAAS,GAAG,MAAM,UAAa,KAAK,QAAQ,GAAG,MAAM,MAAS;AACvG,QAAI,aAAa;AAChB,aAAO,OAAO,UAAU,KAAK,OAAO;AAAA,IACrC;AACA,WAAO,KAAK,WAAW,QAAQ;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,cAAqE;AACpE,UAAM,OAAO,KAAK,oBAAoB;AACtC,UAAM,WAAc,IAAI,KAAK,KAAK,OAAY;AAE9C,UAAM,WAAW,OAAO,KAAK,KAAK,OAAO;AACzC,UAAM,cAAc,SAAS,KAAK,SAAO,SAAS,GAAG,MAAM,UAAa,KAAK,QAAQ,GAAG,MAAM,MAAS;AACvG,QAAI,aAAa;AAChB,aAAO,OAAO,UAAU,KAAK,OAAO;AAAA,IACrC;AACA,WAAO,OAAO,KAAK,QAAQ;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,kBAAyE;AACxE,UAAM,OAAO,KAAK,oBAAoB;AACtC,UAAM,WAAc,IAAI,KAAK,KAAK,OAAY;AAE9C,UAAM,WAAW,OAAO,KAAK,KAAK,OAAO;AACzC,UAAM,cAAc,SAAS,KAAK,SAAO,SAAS,GAAG,MAAM,UAAa,KAAK,QAAQ,GAAG,MAAM,MAAS;AACvG,QAAI,aAAa;AAChB,aAAO,OAAO,UAAU,KAAK,OAAO;AAAA,IACrC;AACA,WAAO,KAAK,SAAS,QAAQ;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,WAAc,KAAW;AAChC,QAAI,QAAQ,QAAQ,OAAO,QAAQ,UAAU;AAC5C,aAAO;AAAA,IACR;AACA,WAAO,oBAAoB,GAAG,EAAE,QAAQ,UAAQ;AAC/C,YAAM,QAAS,IAAY,IAAI;AAC/B,UAAI,UAAU,SAAS,OAAO,UAAU,YAAY,OAAO,UAAU,aAAa;AACjF,aAAK,WAAW,KAAK;AAAA,MACtB;AAAA,IACD,CAAC;AACD,WAAO,OAAO,OAAO,GAAG;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,SAAY,KAAW;AAC9B,QAAI,QAAQ,QAAQ,OAAO,QAAQ,UAAU;AAC5C,aAAO;AAAA,IACR;AACA,WAAO,oBAAoB,GAAG,EAAE,QAAQ,UAAQ;AAC/C,YAAM,QAAS,IAAY,IAAI;AAC/B,UAAI,UAAU,SAAS,OAAO,UAAU,YAAY,OAAO,UAAU,aAAa;AACjF,aAAK,SAAS,KAAK;AAAA,MACpB;AAAA,IACD,CAAC;AACD,WAAO,OAAO,KAAK,GAAG;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,UAAa,KAAW;AAC/B,QAAI,QAAQ,QAAQ,OAAO,QAAQ,UAAU;AAC5C,aAAO;AAAA,IACR;AACA,QAAI,MAAM,QAAQ,GAAG,GAAG;AACvB,aAAO,IAAI,IAAI,UAAQ,KAAK,UAAU,IAAI,CAAC;AAAA,IAC5C;AACA,UAAM,SAAc,CAAC;AACrB,eAAW,OAAO,OAAO,KAAK,GAAG,GAAG;AACnC,aAAO,GAAG,IAAI,KAAK,UAAW,IAAY,GAAG,CAAC;AAAA,IAC/C;AACA,WAAO;AAAA,EACR;AACD;","names":[]}
{
"name": "@cerios/cerios-builder",
"version": "1.4.0",
"version": "1.5.0",
"author": "Ronald Veth - Cerios",

@@ -5,0 +5,0 @@ "description": "A TypeScript builder pattern library providing compile-time type safety for object construction with method chaining and required field validation",

+293
-2

@@ -604,2 +604,202 @@ # @cerios/cerios-builder

#### 3. Constructor Parameter (For Instance-Specific Requirements)
```typescript
class OrderBuilder extends CeriosBuilder<Order> {
// Base template with common required fields
static requiredTemplate: RequiredFieldsTemplate<Order> = [
'Details.CustomerId',
'Details.TotalAmount',
];
// Constructor accepts additional required fields
constructor(
initial: Partial<Order>,
additionalRequiredFields?: RequiredFieldsTemplate<Order>
) {
super(initial, additionalRequiredFields);
}
static create() {
return new OrderBuilder({});
}
// Factory method for orders with shipping requirements
static createWithShipping() {
return new OrderBuilder({}, [
'Details.ShippingAddress.Street',
'Details.ShippingAddress.City',
'Details.ShippingAddress.Country',
]);
}
customerId(value: string) {
return this.setNestedProperty('Details.CustomerId', value);
}
totalAmount(value: number) {
return this.setNestedProperty('Details.TotalAmount', value);
}
shippingStreet(value: string) {
return this.setNestedProperty('Details.ShippingAddress.Street', value);
}
shippingCity(value: string) {
return this.setNestedProperty('Details.ShippingAddress.City', value);
}
shippingCountry(value: string) {
return this.setNestedProperty('Details.ShippingAddress.Country', value);
}
}
// Order without shipping (only validates base required fields)
const digitalOrder = OrderBuilder.create()
.customerId('CUST-001')
.totalAmount(49.99)
.buildWithoutCompileTimeValidation(); // βœ… Valid - shipping not required
// Order with shipping (validates base + shipping fields)
const physicalOrder = OrderBuilder.createWithShipping()
.customerId('CUST-002')
.totalAmount(99.99)
.shippingStreet('123 Main St')
.shippingCity('New York')
.shippingCountry('USA')
.buildWithoutCompileTimeValidation(); // βœ… All required fields validated
// ❌ This will fail - missing shipping address
try {
const invalidOrder = OrderBuilder.createWithShipping()
.customerId('CUST-003')
.totalAmount(75.00)
.buildWithoutCompileTimeValidation(); // Missing shipping fields
} catch (error) {
console.error(error.message);
// "Missing required fields: Details.ShippingAddress.Street, ..."
}
```
#### 4. Hybrid Approach (Static + Dynamic Combined)
```typescript
class OrderBuilder extends CeriosBuilder<Order> {
// Static template for always-required fields
static requiredTemplate: RequiredFieldsTemplate<Order> = [
'Details.CustomerId',
'Details.TotalAmount',
];
static create() {
return new OrderBuilder({});
}
// Factory with static template + additional dynamic fields
static createPriorityOrder() {
return this.create()
.setRequiredFields([
'Details.ShippingAddress.Street',
'Details.ShippingAddress.City',
'Details.ShippingAddress.Country',
'Details.ShippingAddress.PostalCode',
'Details.Priority', // Extra field for priority orders
]);
}
// Another factory combining different requirements
static createGiftOrder() {
return this.create()
.setRequiredFields([
'Details.ShippingAddress.Street',
'Details.ShippingAddress.City',
'Details.ShippingAddress.Country',
'Details.GiftMessage', // Required for gift orders
'Details.RecipientName', // Required for gift orders
]);
}
customerId(value: string) {
return this.setNestedProperty('Details.CustomerId', value);
}
totalAmount(value: number) {
return this.setNestedProperty('Details.TotalAmount', value);
}
priority(value: string) {
return this.setNestedProperty('Details.Priority', value);
}
giftMessage(value: string) {
return this.setNestedProperty('Details.GiftMessage', value);
}
recipientName(value: string) {
return this.setNestedProperty('Details.RecipientName', value);
}
shippingStreet(value: string) {
return this.setNestedProperty('Details.ShippingAddress.Street', value);
}
shippingCity(value: string) {
return this.setNestedProperty('Details.ShippingAddress.City', value);
}
shippingCountry(value: string) {
return this.setNestedProperty('Details.ShippingAddress.Country', value);
}
shippingPostalCode(value: string) {
return this.setNestedProperty('Details.ShippingAddress.PostalCode', value);
}
}
// Priority order: requires shipping + priority + base fields
const priorityOrder = OrderBuilder.createPriorityOrder()
.customerId('CUST-001')
.totalAmount(299.99)
.priority('express')
.shippingStreet('123 Main St')
.shippingCity('New York')
.shippingCountry('USA')
.shippingPostalCode('10001')
.buildWithoutCompileTimeValidation(); // βœ… All priority order fields validated
// Gift order: requires shipping + gift fields + base fields
const giftOrder = OrderBuilder.createGiftOrder()
.customerId('CUST-002')
.totalAmount(149.99)
.giftMessage('Happy Birthday!')
.recipientName('John Doe')
.shippingStreet('456 Oak Ave')
.shippingCity('Boston')
.shippingCountry('USA')
.buildWithoutCompileTimeValidation(); // βœ… All gift order fields validated
// ❌ This will fail - missing gift-specific fields
try {
const invalidGiftOrder = OrderBuilder.createGiftOrder()
.customerId('CUST-003')
.totalAmount(99.99)
.shippingStreet('789 Elm St')
.shippingCity('Chicago')
.shippingCountry('USA')
.buildWithoutCompileTimeValidation(); // Missing GiftMessage and RecipientName
} catch (error) {
console.error(error.message);
// "Missing required fields: Details.GiftMessage, Details.RecipientName"
}
```
**Summary of the Four Approaches:**
| Approach | When to Use | Flexibility | Complexity |
|----------|-------------|-------------|------------|
| **1. Static Template** | Fixed requirements that never change | Low | Low |
| **2. Dynamic via `setRequiredFields()`** | Requirements change based on runtime conditions | High | Medium |
| **3. Constructor Parameter** | Requirements known at builder creation time | Medium | Medium |
| **4. Hybrid (Static + Dynamic)** | Common base requirements + context-specific additions | High | Higher |
### Building Test Data

@@ -773,3 +973,36 @@

}
```
#### Using `BuilderType<>` for Simpler Type Signatures
When accepting builders with defaults already set, you can use the `BuilderType<>` helper to avoid manually specifying which fields are set:
```typescript
import { BuilderType, CeriosBuilder, CeriosBrand } from '@cerios/cerios-builder';
class CustomerBuilder extends CeriosBuilder<Customer> {
// Instead of manually picking fields:
// withAddressDefaults(
// builderFn: (builder: AddressBuilder & CeriosBrand<Pick<Address, "city" | "country">>) => ...
// ) { ... }
// Use BuilderType with ReturnType:
withAddressDefaults(
builderFn: (builder: BuilderType<ReturnType<typeof AddressBuilder.createWithDefaults>>) => AddressBuilder & CeriosBrand<Address>
) {
const address = builderFn(AddressBuilder.createWithDefaults()).build();
return this.setProperty('address', address);
}
}
```
**Benefits:**
- βœ… No need to manually track which fields are set with `Pick<>`
- βœ… Automatically infers the correct type from your factory method
- βœ… Changes to `createWithDefaults()` automatically update the type
- βœ… Much cleaner and more maintainable
**Usage examples:**
```typescript
// Pattern 1: No defaults - must set all required fields

@@ -1186,3 +1419,3 @@ const customer1 = CustomerBuilder.create()

## οΏ½ Immutable Build Methods
## 🧊 Immutable Build Methods

@@ -1431,3 +1664,3 @@ In addition to the standard build methods, `@cerios/cerios-builder` provides **frozen** and **sealed** variants that create immutable objects. These methods help prevent accidental mutations and enforce data integrity.

## οΏ½πŸ’‘ Best Practices
## πŸ’‘ Best Practices

@@ -1472,1 +1705,59 @@ 1. **Use `setNestedProperty()` for deep structures**: Instead of building nested objects separately, use dot notation for better type safety and cleaner code.

```
## 🧩 CeriosClassBuilder (Work in Progress)
`CeriosClassBuilder` is an experimental builder base class for **TypeScript classes** (not just types/interfaces). It provides the same fluent, type-safe builder API as `CeriosBuilder`, but returns actual class instancesβ€”preserving methods, decorators, and prototype chains.
### Key Features
- **Class Instance Output**: Returns real class instances, not plain objects.
- **Decorator Support**: Works with classes using decorators (e.g., for serialization).
- **Type-Safe Chaining**: Same compile-time safety and method chaining as `CeriosBuilder`.
- **Nested Property Support**: Supports `setNestedProperty` for deep class graphs.
### Example
```typescript
import { CeriosClassBuilder } from '@cerios/cerios-builder';
class Person {
name!: string;
age!: number;
greet() { return `Hello, I'm ${this.name}`; }
}
class PersonBuilder extends CeriosClassBuilder<Person> {
constructor(classConstructor: ClassConstructor<Person> = Person, data: Partial<Person> = {}) {
super(classConstructor, data);
}
static create() {
return new PersonBuilder(Person);
}
name(value: string) { return this.setProperty('name', value); }
age(value: number) { return this.setProperty('age', value); }
}
const person = PersonBuilder.create().name('Alice').age(30).build();
console.log(person.greet()); // "Hello, I'm Alice"
console.log(person instanceof Person); // true
```
### Status
- ⚠️ **Work in progress:** API and features may change.
- Feature parity with `CeriosBuilder` is the goal.
- Please report issues or suggestions!
## 🀝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## πŸ“„ License
MIT Β© Ronald Veth - Cerios
## πŸ”— Links
- [GitHub Repository](https://github.com/CeriosTesting/cerios-builder)
- [Issue Tracker](https://github.com/CeriosTesting/cerios-builder/issues)
- [NPM Package](https://www.npmjs.com/package/@cerios/cerios-builder)