UNPKG

mod-engine

Version:

A TypeScript library for typed attributes and modifiers with deterministic evaluation

405 lines (395 loc) 14.1 kB
interface EnumAttributeSchema { readonly key: string; readonly kind: "enum"; readonly values: readonly string[]; readonly cardinality?: "single" | "multi"; } interface BooleanAttributeSchema { readonly key: string; readonly kind: "boolean"; } interface NumberAttributeSchema { readonly key: string; readonly kind: "number"; readonly min?: number; readonly max?: number; readonly integer?: boolean; } interface StringAttributeSchema { readonly key: string; readonly kind: "string"; readonly pattern?: string; readonly minLen?: number; readonly maxLen?: number; } type AttributeSchema = EnumAttributeSchema | BooleanAttributeSchema | NumberAttributeSchema | StringAttributeSchema; interface ConfigSpec { readonly metrics: readonly string[]; readonly operations: readonly string[]; readonly attributes: readonly AttributeSchema[]; } type MetricOf<C extends ConfigSpec> = C["metrics"][number]; type OperationOf<C extends ConfigSpec> = C["operations"][number]; type AttrKeyOf<C extends ConfigSpec> = C["attributes"][number]["key"]; type ExtractAttr<C extends ConfigSpec, K extends AttrKeyOf<C>> = Extract<C["attributes"][number], { key: K; }>; type AttrValueOf<C extends ConfigSpec, K extends AttrKeyOf<C>> = ExtractAttr<C, K> extends EnumAttributeSchema ? ExtractAttr<C, K>["cardinality"] extends "multi" ? readonly ExtractAttr<C, K>["values"][number][] : ExtractAttr<C, K>["values"][number] : ExtractAttr<C, K> extends BooleanAttributeSchema ? boolean : ExtractAttr<C, K> extends NumberAttributeSchema ? number : ExtractAttr<C, K> extends StringAttributeSchema ? string : never; type Attributes<C extends ConfigSpec> = { [K in AttrKeyOf<C>]?: AttrValueOf<C, K>; }; type Condition<C extends ConfigSpec> = { op: "and"; clauses: Condition<C>[]; } | { op: "or"; clauses: Condition<C>[]; } | { op: "not"; clause: Condition<C>; } | { op: "eq"; attr: AttrKeyOf<C>; value: AttrValueOf<C, AttrKeyOf<C>>; } | { op: "in"; attr: AttrKeyOf<C>; values: AttrValueOf<C, AttrKeyOf<C>>[]; } | { op: "includes"; attr: AttrKeyOf<C>; value: AttrValueOf<C, AttrKeyOf<C>>; } | { op: "gt" | "gte" | "lt" | "lte"; attr: AttrKeyOf<C>; value: number; }; type Stacking = "stack" | "unique" | { uniqueBy: string; }; interface Modifier<C extends ConfigSpec> { readonly metric: MetricOf<C>; readonly operation: OperationOf<C>; readonly value: number; readonly conditions?: Condition<C>; readonly stacking?: Stacking; readonly priority?: number; readonly source?: string; } interface ItemSpec<C extends ConfigSpec> { readonly name?: string; readonly attributes: Attributes<C>; readonly modifiers: readonly Modifier<C>[]; } interface ModifierApplication<C extends ConfigSpec> { readonly modifier: Modifier<C>; readonly appliedValue: number; readonly resultingValue: number; } interface EvaluationResult<C extends ConfigSpec> { readonly metrics: Record<MetricOf<C>, number>; readonly applied: readonly ModifierApplication<C>[]; } interface EvalContext<C extends ConfigSpec> { readonly item: ItemSpec<C>; readonly modifier: Modifier<C>; readonly currentMetrics: Record<MetricOf<C>, number>; } type OperationImpl<C extends ConfigSpec> = (current: number, value: number, context: EvalContext<C>) => number; interface ValidationError$1 { readonly path: string; readonly message: string; readonly code: string; } interface ValidationResult { readonly ok: boolean; readonly errors?: readonly ValidationError$1[]; } interface SerializedData<T = unknown> { readonly version: number; readonly data: T; } /** * Fluent builder for creating item specifications */ declare class Builder<C extends ConfigSpec> { private config; private itemName?; private attributes; private modifiers; private currentCondition?; private currentStacking?; private currentPriority?; private currentSource?; constructor(config: C, name?: string); /** * Sets an attribute value with type safety */ set<K extends AttrKeyOf<C>>(key: K, value: AttrValueOf<C, K>): Builder<C>; /** * Sets a condition for subsequent modifiers */ when(condition: Condition<C>): Builder<C>; /** * Sets metadata for subsequent modifiers */ with(metadata: { stacking?: Stacking; priority?: number; source?: string; }): Builder<C>; /** * Adds an increase modifier (sum operation) */ increase<M extends MetricOf<C>>(metric: M): { by(value: number): Builder<C>; }; /** * Adds a decrease modifier (subtract operation) */ decrease<M extends MetricOf<C>>(metric: M): { by(value: number): Builder<C>; }; /** * Adds a multiply modifier */ multiply<M extends MetricOf<C>>(metric: M): { by(value: number): Builder<C>; }; /** * Adds a generic modifier with specified operation */ apply<M extends MetricOf<C>, O extends OperationOf<C>>(metric: M, operation: O): { by(value: number): Builder<C>; }; /** * Internal method to add a modifier */ private addModifier; /** * Resets the current context (condition, stacking, etc.) */ private resetCurrentContext; /** * Builds and returns the immutable item specification */ build(): ItemSpec<C>; /** * Creates a copy of the builder with the same state */ clone(): Builder<C>; /** * Gets the current number of modifiers */ get modifierCount(): number; /** * Gets the current number of attributes set */ get attributeCount(): number; /** * Clears all modifiers */ clearModifiers(): Builder<C>; /** * Clears all attributes */ clearAttributes(): Builder<C>; /** * Resets the builder to initial state */ reset(): Builder<C>; } /** * Helper type for condition builders */ interface ConditionBuilder<C extends ConfigSpec> { /** * Creates an equality condition */ eq<K extends AttrKeyOf<C>>(attr: K, value: AttrValueOf<C, K>): Condition<C>; /** * Creates an inclusion condition (value in array) */ in<K extends AttrKeyOf<C>>(attr: K, values: AttrValueOf<C, K>[]): Condition<C>; /** * Creates a contains condition (array contains value) */ includes<K extends AttrKeyOf<C>>(attr: K, value: AttrValueOf<C, K>): Condition<C>; /** * Creates comparison conditions */ gt(attr: AttrKeyOf<C>, value: number): Condition<C>; gte(attr: AttrKeyOf<C>, value: number): Condition<C>; lt(attr: AttrKeyOf<C>, value: number): Condition<C>; lte(attr: AttrKeyOf<C>, value: number): Condition<C>; /** * Creates logical conditions */ and(...conditions: Condition<C>[]): Condition<C>; or(...conditions: Condition<C>[]): Condition<C>; not(condition: Condition<C>): Condition<C>; } /** * Creates a condition builder for type-safe condition construction */ declare function createConditionBuilder<C extends ConfigSpec>(): ConditionBuilder<C>; /** * Defines a configuration and returns it with strong typing */ declare function defineConfig<const C extends ConfigSpec>(config: C): C; /** * Engine interface that provides all core functionality */ interface Engine<C extends ConfigSpec> { builder(name?: string): Builder<C>; evaluate(item: ItemSpec<C>, options?: { base?: Partial<Record<MetricOf<C>, number>>; }): EvaluationResult<C>; validateItem(item: ItemSpec<C>): ValidationResult; registerOperation?(name: string, impl: OperationImpl<C>, options?: { precedence?: number; }): void; } /** * Creates an engine instance from a configuration */ declare function createEngine<const C extends ConfigSpec>(config: C): Engine<C>; /** * Validates an item specification against the config */ declare function validateItem<C extends ConfigSpec>(item: ItemSpec<C>, config: C): ValidationResult; /** * Validates a configuration specification */ declare function validateConfig<C extends ConfigSpec>(config: C): void; /** * Serializes an item specification to JSON-compatible format */ declare function serializeItem<C extends ConfigSpec>(item: ItemSpec<C>): SerializedData<ItemSpec<C>>; /** * Deserializes an item specification from JSON-compatible format */ declare function deserializeItem<C extends ConfigSpec>(serialized: SerializedData<ItemSpec<C>>): ItemSpec<C>; /** * Serializes an array of modifiers to JSON-compatible format */ declare function serializeModifiers<C extends ConfigSpec>(modifiers: readonly Modifier<C>[]): SerializedData<readonly Modifier<C>[]>; /** * Deserializes an array of modifiers from JSON-compatible format */ declare function deserializeModifiers<C extends ConfigSpec>(serialized: SerializedData<readonly Modifier<C>[]>): readonly Modifier<C>[]; /** * Serializes an evaluation result to JSON-compatible format */ declare function serializeEvaluationResult<C extends ConfigSpec>(result: EvaluationResult<C>): SerializedData<EvaluationResult<C>>; /** * Deserializes an evaluation result from JSON-compatible format */ declare function deserializeEvaluationResult<C extends ConfigSpec>(serialized: SerializedData<EvaluationResult<C>>): EvaluationResult<C>; /** * Converts data to JSON string with proper error handling */ declare function toJSON(data: unknown): string; /** * Parses JSON string with proper error handling */ declare function fromJSON<T>(json: string): T; /** * Creates a deep clone of serializable data */ declare function deepClone<T>(data: T): T; /** * Evaluates a condition against the given attributes */ declare function evaluateCondition<C extends ConfigSpec>(condition: Condition<C>, attributes: Attributes<C>, path?: string): boolean; /** * Validates that a condition is well-formed */ declare function validateCondition<C extends ConfigSpec>(condition: Condition<C>, config: C, path?: string): void; /** * Built-in operation: sum * Adds the modifier value to the current metric value */ declare function sumOperation<C extends ConfigSpec>(): OperationImpl<C>; /** * Built-in operation: subtract * Subtracts the modifier value from the current metric value */ declare function subtractOperation<C extends ConfigSpec>(): OperationImpl<C>; /** * Built-in operation: multiply * Multiplies the current metric value by the modifier value */ declare function multiplyOperation<C extends ConfigSpec>(): OperationImpl<C>; /** * Registry of built-in operations with their precedence values */ interface OperationInfo<C extends ConfigSpec> { impl: OperationImpl<C>; precedence: number; } /** * Creates a map of built-in operations */ declare function createBuiltInOperations<C extends ConfigSpec>(): Map<string, OperationInfo<C>>; /** * Validates that a numeric result is safe (not NaN, Infinity, etc.) */ declare function validateNumericResult(value: number, path: string): number; /** * Evaluates an item specification and returns the computed metrics */ declare function evaluateItem<C extends ConfigSpec>(item: ItemSpec<C>, operations: Map<string, OperationInfo<C>>, config: C, baseMetrics?: Partial<Record<MetricOf<C>, number>>): EvaluationResult<C>; /** * Creates a snapshot of current metrics for immutability */ declare function createMetricsSnapshot<C extends ConfigSpec>(metrics: Record<MetricOf<C>, number>): Record<MetricOf<C>, number>; /** * Validates that all metrics in the config are present in the result */ declare function validateMetricsCompleteness<C extends ConfigSpec>(metrics: Record<string, number>, config: C): void; /** * Base error class for all mod engine errors */ declare abstract class ModEngineError extends Error { readonly code: string; readonly path: string | undefined; constructor(message: string, code: string, path?: string); } /** * Error thrown when schema configuration is invalid */ declare class SchemaError extends ModEngineError { constructor(message: string, path?: string); } /** * Error thrown when validation fails */ declare class ValidationError extends ModEngineError { constructor(message: string, path?: string); } /** * Error thrown when an operation fails */ declare class OperationError extends ModEngineError { constructor(message: string, path?: string); } /** * Error thrown when condition evaluation fails */ declare class ConditionError extends ModEngineError { constructor(message: string, path?: string); } /** * Error thrown when evaluation fails */ declare class EvaluationError extends ModEngineError { constructor(message: string, path?: string); } /** * Error thrown when serialization/deserialization fails */ declare class SerializationError extends ModEngineError { constructor(message: string, path?: string); } export { type AttrKeyOf, type AttrValueOf, type AttributeSchema, type Attributes, type BooleanAttributeSchema, Builder, type Condition, type ConditionBuilder, ConditionError, type ConfigSpec, type Engine, type EnumAttributeSchema, type EvalContext, EvaluationError, type EvaluationResult, type ItemSpec, type MetricOf, ModEngineError, type Modifier, type ModifierApplication, type NumberAttributeSchema, OperationError, type OperationImpl, type OperationInfo, type OperationOf, SchemaError, SerializationError, type SerializedData, type Stacking, type StringAttributeSchema, ValidationError, type ValidationError$1 as ValidationErrorType, type ValidationResult, createBuiltInOperations, createConditionBuilder, createEngine, createMetricsSnapshot, deepClone, defineConfig, deserializeEvaluationResult, deserializeItem, deserializeModifiers, evaluateCondition, evaluateItem, fromJSON, multiplyOperation, serializeEvaluationResult, serializeItem, serializeModifiers, subtractOperation, sumOperation, toJSON, validateCondition, validateConfig, validateItem, validateMetricsCompleteness, validateNumericResult };