@darlean/valueobjects
Version:
Library for DDD-like value objects that can be validated, serialized and represented in other programming languages as native objects with native naming.
100 lines (99 loc) • 5.76 kB
TypeScript
import { ICanonical, ICanonicalSource } from '@darlean/canonical';
import { CanonicalFieldName, Class } from './valueobject';
import { NoInfer } from './utils';
import { IFromCanonicalOptions, IValueOptions, MethodKeys, Value, ValueClassLike } from './base';
export type UnknownFieldAction = 'ignore' | 'error';
export interface ISlotDef<TValue extends Value> {
name: string;
required: boolean;
clazz: ValueClassLike<TValue>;
}
type StructMap = Map<CanonicalFieldName, Value & ICanonicalSource>;
export interface IStructValueOptions {
unknownFieldAction?: UnknownFieldAction;
}
export declare function structvalue(logicalName?: string, options?: IStructValueOptions): (constructor: Function) => void;
export declare class StructDef {
private _slots;
private _requiredSlots;
private _unknownFieldAction;
constructor(parentDef?: StructDef);
withRequiredField(name: CanonicalFieldName, def: ValueClassLike<Value>): StructDef;
withOptionalField<TFieldValue extends Value>(name: CanonicalFieldName, def: ValueClassLike<TFieldValue>): StructDef;
withUnknownFieldAction(action: UnknownFieldAction): this;
getSlotDef<TSlotValue extends Value>(name: string): ISlotDef<TSlotValue> | undefined;
getRequiredSlots(): string[];
getSlots(): IterableIterator<ISlotDef<Value>>;
get unknownFieldAction(): UnknownFieldAction;
}
export interface StructValueUnderscore {
extractSlots(): StructMap;
req<T>(name: CanonicalFieldName): T;
opt<T>(name: CanonicalFieldName): T | undefined;
checkSlots(): Map<CanonicalFieldName, Value>;
get(slot: CanonicalFieldName): (Value & ICanonicalSource) | undefined;
keys(): IterableIterator<CanonicalFieldName>;
values(): IterableIterator<Value & ICanonicalSource>;
entries(): IterableIterator<[CanonicalFieldName, Value & ICanonicalSource]>;
get size(): number;
}
export declare class StructValue extends Value implements ICanonicalSource {
private _slots?;
private _canonical?;
static required<T>(this: Class<T>): T;
static optional<T>(this: Class<T>): T | undefined;
/**
* Creates a new struct value from a value that contains all of the fields of T. The fields
* should be in the exact (native) casing as used in T. They are internally converted into the canonical field names.
* Their values must be value objects (like StringValue or derived classes); not native types (like string).
*/
static from<T extends StructValue, T2 = NoInfer<T>>(this: Class<T>, value: Omit<T2, keyof StructValue | MethodKeys<T2>>): T;
/**
* Creates a new struct value from a value that is a partial (subset of the fields) of T. The fields
* should be in the exact casing as used in T. They are internally converted into the canonical field names.
* Their values must be value objects (like StringValue or derived classes); not native types (like string).
*/
static fromPartial<T extends StructValue, T2 = NoInfer<T>>(this: Class<T>, value: Partial<Omit<T2, keyof StructValue>>): T;
/**
* Creates a new struct value from a base value (of the same type) that is enricheded with a partial
* (subset of the fields) of T. The fields should be in the exact casing as used in T. They are internally converted into
* the canonical field names.
* Their values must be value objects (like StringValue or derived classes); not native types (like string). Defined values
* (that is, not having the value `undefined`) override the corresponding value in the output struct; values that are explicitly
* undefined remove cause the corresponding key not to be present in the output struct.
*/
static fromBase<T extends StructValue>(this: Class<T>, base: NoInfer<T>, value: Partial<Omit<NoInfer<T>, keyof StructValue>>): T;
static fromCanonical<T extends StructValue>(this: Class<T>, value: ICanonical, options?: IFromCanonicalOptions): T;
static fromSlots<T extends StructValue>(this: Class<T>, value: StructMap): T;
/**
* Creates a new struct value instance using the provided value. Regardless of whether the value is an ICanonical or
* a Map, the field names must already be canonicalized. That also counts for field names of nested
* values. When value is an object (`{..}`), the field names must *not* yet be canonicalized.
* @param value
*/
constructor(options: IValueOptions);
_peekCanonicalRepresentation(): ICanonical<this>;
get _(): StructValueUnderscore;
equals(other: unknown): boolean;
private _keys;
private _values;
private _entries;
get _size(): number;
get _logicalTypes(): string[];
protected _deriveCanonicalRepresentation(): ICanonical;
protected _get(slot: string): (Value & ICanonicalSource) | undefined;
protected _fromCanonical(canonical: ICanonical, options?: IFromCanonicalOptions): StructMap;
protected _toCanonical(value: StructMap, logicalTypes: string[]): ICanonical<this>;
protected _validate(v: StructMap, fail: (msg: string) => void): StructMap | void;
/**
* Extracts the current slots and their values. Slot names are returned as canonicalized names.
*/
private _extractSlots;
private _req;
private _opt;
private _checkSlots;
}
export declare function ensureStructDefForConstructor(constructor: Function, extensions?: UnknownFieldAction): StructDef;
export declare function validateStrictFieldName(name: CanonicalFieldName): void;
export declare const structvalidation: (validator: (value: StructMap) => string | boolean | void, description?: string | undefined) => (constructor: Function) => void;
export {};