API @deepkit/type
npm install @deepkit/type
Make sure to change the id when a custom naming strategy is implemented, since caches are based on it. internal: The jit stack cache is used in both serializer and guards, so its cache key needs to be aware of it Default serializer that can convert JS data structures to the target type.
It coerces types, converts object literals to class instances, and has type guards for JS types. JSONSerializer has the same but for JSON data structures. Used in validator functions. The structure of a validation error. Path defines the shallow or deep path (using dots).
Message is an arbitrary message in english. In validators please use and return All raw data from When using Buffer.from() node is using a buffer from the buffer pool.
This makes it necessary to create the given TypedArray using byteOffset and byteLength accordingly. Note: The created TypedArray.buffer is pointing probably to a larger Buffer. Make sure
to use byteLength/byeOffset correctly or use typedArrayToArrayBuffer() if you want to use
a raw ArrayBuffer that represents the actual data correctly. Creates a new fresh ArrayBuffer with given data.
Note: Regular Buffer.from(base64, 'base64) creates in Node a shared buffer, this function makes
sure a copy happens and the ArrayBuffer is not shared. When using Buffer.from() node is using a buffer from the buffer pool.
This makes it necessary to create the a new ArrayType using slice to make a copy. This makes a copy. In node environment the TypedArray.buffer is probably a larger buffer from the buffer pool.
This makes it necessary to create a Buffer with offset & length so that it accurately represents
the given TypedArray. Same as Buffer.from() but creates a ArrayBuffer that is not shared. Same as Buffer.from(arrayBuffer).toString(encoding), but more in line with the current API. Creates a (cached) Partial Returns a (cached) serializer function for the given registry (serialize or deserialize). Just sets the state.setter to state.accessor without any modification. To avoid circular builds, class/object literal code is extract to its own function.
if this returns true, code is put into state to call an already existing function. Sort, so the order is literal, number, string, symbol. literal comes first as its the most specific type.
We need to do that for numbers since all keys are string|symbol in runtime, and we need to check if a string is numeric first before falling back to string. Casts/coerces a given data structure to the target data type and validates all attached validators. Same as validatedDeserialize(). Same as cast but returns a ready to use function. Used to improve performance. Deserialize given data structure from JSON data objects to JavaScript objects, without running any validators. Types that are already correct will be used as-is. Same as deserialize but returns a ready to use function. Used to improve performance. Patch serialization for deep dot paths, e.g. Create a serializer/deserializer function including validator for the given type for a patch structure.
This is handy for deep patch structures like e.g '{user.address.street: "new street"}'. Serialize given data structure to JSON data objects (not a JSON string). The resulting JSON object can be stringified using JSON.stringify(). Same as serialize but returns a ready to use function. Used to improve performance. Clones a class instance deeply. Tries to deserialize given data as T, and throws an error if it's not possible or validation after conversion fails. Returns a new UUID v4 as string. Writes a new uuid v4 into an existing buffer, and returns the same buffer. Stringify an exising Uint8Array buffer. Returns empty array when valid, or ValidationErrorItem[] with detailed error messages if not valid. Returns validation error items when failed. If successful returns an empty array. Returns true when valid, and false if not. Creates a new JIT compiled function to convert the class instance to a snapshot.
A snapshot is essentially the class instance as Generated function is cached. Creates a snapshot using getConverterForSnapshot(). Extracts the primary key of a snapshot and converts to class type. Creates a primary key hash generator that takes an item from any format
converts it to class format, then to plain, then uses the primitive values to create a string hash. This function is designed to work on the plain values (db records or json values) This is a comparator function for the snapshots. They are either string, number, boolean, array, or objects.
No date, moment, or custom classes involved here. Converts a (possibly circular/nested) type into a JSON.stringify'able structure suited to be transmitted over the wire and deserialized back to the correct Type object. Returns a sensible default value for a given type.
Sensible means it satisfies the type checker, but not necessarily attached validators. Function to mixin multiple classes together and create a new class, which can be extended from. The first entry of the mixin() call will be used as base class. Returns true if the type is TypePropertySignature | TypeProperty and not a static member. Return all properties created in the constructor (via If a non-property parameter is in the constructor, the type is given instead, e.g. Checks if the structure of a and b are identical. Flatten nested union types. empty union => never
union with one member => member
otherwise the union is returned Query a container type and return the result. container[index] e.g. {a: string}['a'] => string
e.g. {a: string, b: number}[keyof T] => string | number
e.g. [string, number][0] => string
e.g. [string, number][number] => string | number This function does not do a deep copy, only shallow. A deep copy makes it way to inefficient, so much that router.spec.ts takes up to 20-30seconds
to complete instead of barely 30ms. Checks whether Whether a property has an initializer/default value. Checks whether Get the key type of a Map or object literal with index signatures. Get the value type of a Map or object literal with index signatures. Type annotations are object literals with a single optional __meta in it
that has as type a tuple with the name of the annotation as first entry.
The tuple is intersected with the The processor has currently implemented to not resolve Returns true if the given type is Date, ArrayBuffer, Uint8Array, etc. Returns true if the given type is TypeClass and references a custom (non-global) class. Returns a type predicate that checks if the given type is a class and is of the given classType.
If withInheritance is true, it also checks if the type is a subclass of the given classType. Returns the members of a class or object literal. Returns all (including inherited) constructor properties of a class. Returns the index to Pack a pack structure (op instructions + pre-defined stack) and create a encoded version of it. Computes a type of given object. This function caches the result on the object itself.
This is the slow path, using the full type virtual machine to resolve the type.
If you want to handle some fast paths (including cache), try using resolveReceiveType() instead. The check of See https://www.typescriptlang.org/docs/handbook/type-compatibility.html#any-unknown-object-void-undefined-null-and-never-assignability
This algo follows strict mode. Warning: If you do not pass Type objects, typeInfer() is used which does not use cache (it is designed to be called withing type processor) We don't want to embed in each and every file the type definition of Promise Resolved the class/object ReflectionClass of the given TypeClass|TypeObjectLiteral A dual decorator is a decorator that can be used on a class and class property. Options that can be passed to the serialization/deserialization functions
and change the behavior in runtime (not embedded in JIT). Includes 0. Use PositiveNoZero to exclude 0. Includes 0. Use NegativeNoZero to exclude 0. Object to hold runtime jit data. Object literals or interfaces. Merge dynamic runtime types with static types. In the type-system resolves as any, in runtime as the correct type. Integer Integer 8 bit.
Min value -127, max value 128 Unsigned integer 8 bit.
Min value 0, max value 255 Integer 16 bit.
Min value -32768, max value 32767 Unsigned integer 16 bit.
Min value 0, max value 65535 Integer 8 bit.
Min value -2147483648, max value 2147483647 Unsigned integer 32 bit.
Min value 0, max value 4294967295 Float (same as number, but different semantic for databases). Float 32 bit. Float 64 bit. note: if this is adjusted, make sure to adjust ReflectionClass, entityAnnotation, and type serializer accordingly. Type to decorate an interface/object literal with entity information. Marks a property as primary key. Marks a primary property key as auto-increment. UUID v4, as string, serialized as string in JSON, and binary in database.
Use MongoDB's ObjectID type. serialized as string in JSON, ObjectID in database. Same as Same as Assigns one or multiple groups to a type. Excludes the type from serialization of all kind. Assigns arbitrary data to a type that can be read in runtime. Resets an already set decorator to undefined. The required Name is the name of the type decorator (its first tuple entry). Receives the runtime type of template argument or runtime symbols like
class references, functions, or packed types. UseClasses
export class Changes<T extends object> {
$set?: DeepPartial<T> | T;
$unset?: {
[path: string]: number;
};
$inc?: Partial<Pick<T, NumberFields<T>>>;
empty;
fieldNames: string[];
constructor(changes?: ChangesInterface<T>);
clear(): void;
getReturning(): string[];
replaceSet($set: DeepPartial<T> | T);
mergeSet($set: Partial<T> | T);
increase(property: NumberFields<T>, increase: number = );
set(property: keyof T & string, value: any);
unset(property: keyof T & string, unset = true);
has(name: keyof T & string): boolean;
}
export class ItemChanges<T extends object> extends Changes<T> {
constructor(changes: ChangesInterface<T> = {}, protected item: T);
increase(property: NumberFields<T>, increase: number = );
set(property: keyof T & string, value: any);
unset(property: keyof T & string, unset: boolean = true);
}
export class AtomicChangeInstance<T extends object> {
readonly changeSet: Changes<T>;
constructor(protected object: any);
increase(property: NumberFields<T>, increase: number = );
}
export class NamingStrategy {
constructor(public id: string = );
getPropertyName(type: TypeProperty | TypePropertySignature, forSerializer: string): string | undefined;
}
export class RuntimeCode {
constructor(public code: string);
}
export class JitStack {
getStack(registry?: TemplateRegistry);
has(registry: TemplateRegistry, type: Type): boolean;
get(registry: TemplateRegistry, type: Type);
prepare(registry: TemplateRegistry, type: Type): {
id: number;
prepare: (fn: Function) => {
fn: Function | undefined;
};
};
getOrCreate(registry: TemplateRegistry | undefined, type: Type, create: () => Function): {
fn: Function | undefined;
id: number;
};
}
export class ContainerAccessor {
constructor(public container: string | ContainerAccessor, public property: string);
toString();
}
export class TemplateState {
/**
* Before and after template content is rendered before/after all other templates.
* When a template is put into its own function, before/after templates are run outside of this function.
*/
template;
ended;
setter: string | ContainerAccessor;
accessor: string | ContainerAccessor;
/**
* Strict means only use type guards of specificality of 1 (used for is()/validation()).
* For deserialization loose is used.
*/
validation?: | ;
/**
* When this is set all specificalities are used (used in union type guards to detect which member to pick).
*/
allSpecificalities?: TypeGuardRegistry;
propertyName?: string | RuntimeCode;
setterDisabled: boolean;
parentTypes: Type[];
target: | ;
constructor(public originalSetter: string | ContainerAccessor, public originalAccessor: string | ContainerAccessor, public compilerContext: CompilerContext, public registry: TemplateRegistry, public namingStrategy: NamingStrategy = new NamingStrategy, public jitStack: JitStack = new JitStack(), public path: (string | RuntimeCode)[] = []);
isValidation(): boolean;
withValidation(validation: this[]): this;
includeAllSpecificalities(guardRegistry: TypeGuardRegistry): this;
replaceTemplate(template: string);
/**
* Forks as state, with an empty propertyName.
*/
fork(setter?: string | ContainerAccessor, accessor?: string | ContainerAccessor, path?: (string | RuntimeCode)[]): TemplateState;
fullFork();
forRegistry(registry: TemplateRegistry);
forPropertyName(name?: string | number | symbol | RuntimeCode): this;
disableSetter(): this;
enableSetter(): this;
/**
* Can be used to track which annotation was already handled. Necessary to use with `isAnnotationHandled` to avoid infinite recursive loops
* when a serializer template issues sub calls depending on annotation data.
*/
annotationHandled(annotation: AnnotationDefinition<any>): void;
isAnnotationHandled(annotation: AnnotationDefinition<any>): boolean;
get isSerialization(): boolean;
get isDeserialization(): boolean;
extendPath(path: string | RuntimeCode | number | symbol): this;
assignValidationError(code: string, message: string);
throwCode(type: Type | string, error?: string, accessor: string | ContainerAccessor = this.originalAccessor);
/**
* Adds template code for setting the `this.setter` variable. The expression evaluated in `code` is assigned to `this.setter`.
* `this.accessor` will point now to `this.setter`.
*/
addSetter(code: string | {
toString(): string;
});
addSetterAndReportErrorIfInvalid(errorCode: string, message: string, code: string);
/**
* Adds a converter function that is executed on the current `this.accessor` value.
*
* @example
* ```typescript
* serializer.deserializeRegistry.registerClass(Date, (type, state) => {
* // make sure to check `v` as it is any!
* state.convert((v: any) => {
* if ('number' !== typeof v) throw new SerializationError('Expected number');
* return new Date(v);
* });
* });
*
* serializer.serializeRegistry.registerClass(Date, (type, state) => {
* // in serialization `v` is always the specific type
* state.convert((v: Date) => v.getTime());
* });
* ```
*/
convert(callback: (value: any) => any);
/**
* Allows to add a custom code that is executed on the current `this.accessor` value.
*
* @example
* ```typescript
* serializer.deserializeRegistry.addDecorator(
* isCustomTypeClass,
* (type, state) => {
* state.touch((value) => {
* if ('onLoad' in value) value.onLoad();
* });
* }
* );
* ```
*/
touch(callback: (value: any) => void);
/**
* Stop executing next templates.
*/
stop();
setVariable(name: string, value?: any): string;
setContext(values: {
[name: string]: any;
});
addCode(code: string);
/**
* Adds template code for setting the `this.setter` variable manually, so use `${state.setter} = value`.
* `this.accessor` will point now to `this.setter`.
*/
addCodeForSetter(code: string);
hasSetterCode(): boolean;
}
export class TemplateRegistry {
id: number;
preHooks: TemplateHook[];
postHooks: TemplateHook[];
classTemplates;
constructor(public serializer: Serializer = new EmptySerializer());
clear();
get(type: Type): Template<Type>[];
getDecorator(type: Type): Template<Type>[];
/**
* Registers a template for all binary classes: ArrayBuffer, Uint8Array, Int8Array, etc.
*/
registerBinary(template: Template<TypeClass>);
/**
* Registers a template for a given class type.
*
* As soon as a single template has registered for the given classType the template registry
* only returns templates for this particular classType and omits all general purpose ReflectionKind.class templates for this particular classType.
*/
registerClass(classType: ClassType, template: Template<TypeClass>);
prependClass(classType: ClassType, template: Template<TypeClass>);
appendClass(classType: ClassType, template: Template<TypeClass>);
addPreHook(callback: TemplateHook);
addPostHook(callback: TemplateHook);
/**
* Removes all registered templates.
*/
unregister(kind: ReflectionKind);
/**
* Registers a new template and replaces all existing (added via register,prepend,append).
*/
register<T extends ReflectionKind>(kind: T, template: Template<FindType<Type, T>>);
/**
* Registers additional templates that handle type decorators/annotations. The templates can safely assume that the given type in `state.accessor`
* is already type-checked to be `T`.
*
* Decorator templates run last (after normal templates and postHook).
*
* This split between register and registerForDecorator is made to have a distinction between native type templates and additional user-made templates.
* This allows to fetch only decorator templates and decide upon the result whether additional code is necessary or not. (this would not be possible
* if everything is added to the `register` call that does always the basic checks).
*/
addDecorator(predicate: (type: Type) => boolean, template: Template<Type>);
/**
* Removes all registered decorators for a certain type.
*/
removeDecorator(type: Type);
prepend<T extends ReflectionKind>(kind: T, template: Template<FindType<Type, T>>);
append<T extends ReflectionKind>(kind: T, template: Template<FindType<Type, T>>);
}
export class TypeGuardRegistry {
registry: {
[specificality: number]: TemplateRegistry;
};
/**
* Lowest specificality first
*/
getSortedTemplateRegistries();
constructor(public serializer: Serializer);
clear();
/**
*
* @see register() for specificality explanation.
*/
getRegistry(specificality: number): TemplateRegistry;
/**
* Registers a new template and replaces all existing (added via register,prepend,append).
*
* Specificality defines when the given template guard is executed.
*
* - 1 means its used for JS types - exact types. For example for type string `'string' ==== typeof v` is used. Same for number, bigint, and boolean.
* Guards of this specificality are used for the `is()` function.
*
* - >1 means it acts as a fallback. For example in a union `number | Date`, when a string is given, the Date can allow `string` type as well, so it gets converted to a Date.
*
* - >0 && <1 means its acts as a priority guard. For example in a `string | Date`, a string of date-format is converted to a Date instead of a string. This is necessary
* to support regular JSON.
*
* - <0, anything below 0 means it can optionally be used for loosely types. This is handy when data comes from a string-only encoding like URL query strings.
* In this specificality a numeric string is converted to a number or bigint, a 1|0|true|false string converted to boolean .
*/
register<T extends ReflectionKind>(specificality: number, kind: T, template: Template<FindType<Type, T>>);
/**
* @see register
*/
registerClass(specificality: number, classType: ClassType, template: Template<TypeClass>);
/**
* @see register
*/
registerBinary(specificality: number, template: Template<TypeClass>);
}
export class Serializer {
serializeRegistry;
deserializeRegistry;
typeGuards;
validators;
constructor(public name: string = );
setExplicitUndefined(type: Type, state: TemplateState): boolean;
clear();
}
export class EmptySerializer extends Serializer {
constructor(name: string = );
}
export class ValidatorError {
constructor(public readonly code: string, public readonly message: string, public readonly path?: string);
}
export class ValidationErrorItem {
/**
* The path to the property. Might be a deep path separated by dot.
*/
constructor(public readonly path: string, public readonly code: string, public readonly message: string, public readonly value?: any);
toString(prefix: string = );
}
new ValidatorError('code', 'message')
instead.export class TypeRegistry<T> {
classes;
clear(): void;
get(type: Type): T | undefined;
decorator(predicate: (type: Type) => boolean, v: T): void;
/**
* Registers a template for all binary classes: ArrayBuffer, Uint8Array, Int8Array, etc.
*/
setBinary(v: T): void;
setNumeric(v: T): void;
/**
* Registers a template for a given class type.
*
* As soon as a single template has registered for the given classType the template registry
* only returns templates for this particular classType and omits all general purpose ReflectionKind.class templates for this particular classType.
*/
setClass(classType: ClassType, v: T): void;
/**
* Removes all registered templates.
*/
remove(kind: ReflectionKind): void;
/**
* Registers a new template and replaces all existing (added via register,prepend,append).
*/
set(kind: ReflectionKind | ReflectionKind[] | ((type: Type) => boolean), v: T): void;
}
export class CartesianProduct {
toGroup(type: Type): Type[];
add(item: Type);
calculate(): Type[][];
}
export class AnnotationDefinition<T = true> {
symbol: symbol;
constructor(public readonly id: string);
register(annotations: Annotations, data: T);
reset(annotations: Annotations);
registerType<TType extends Type>(type: TType, data: T): TType;
replace(annotations: Annotations, annotation: T[]);
replaceType(type: Type, annotation: T[]);
getAnnotations(type: Type): T[];
getFirst(type: Type): T | undefined;
hasAnnotations(type: Type): boolean;
}
export class PackStruct {
constructor(public ops: ReflectionOp[] = [], public stack: RuntimeStackEntry[] = []);
}
export class Processor {
static typeProcessor?: Processor;
static get(): Processor;
reflect(object: ClassType | Function | Packed | any, inputs: RuntimeStackEntry[] = [], options: ReflectOptions = {}): Type;
_reflect(object: ClassType | Function | Packed | any, inputs: RuntimeStackEntry[] = [], options: ReflectOptions = {}): Type;
run(ops: ReflectionOp[], initialStack: RuntimeStackEntry[], inputs: RuntimeStackEntry[] = [], object?: ClassType | Function | Packed | any): Type;
runProgram(program: Program): Type;
}
export class ReflectionParameter {
type: Type;
constructor(public readonly parameter: TypeParameter, public readonly reflectionFunction: ReflectionMethod | ReflectionFunction);
getType(): Type;
getName(): string;
get name(): string;
isOptional(): boolean;
hasDefault(): boolean;
isValueRequired(): boolean;
getDefaultValue(): any;
hasDefaultFunctionExpression(): boolean;
applyDecorator(t: TData);
getVisibility(): ReflectionVisibility | undefined;
isPublic(): boolean;
isProtected(): boolean;
isPrivate(): boolean;
isReadonly(): boolean;
/**
* True if the parameter becomes a property in the class.
* This is the case for parameters in constructors with visibility or readonly.
*
* ```typescript
* class User {
* constructor(public name: string) {}
* }
*/
isProperty(): boolean;
}
export class ReflectionFunction {
parameters: ReflectionParameter[];
description: string;
constructor(public readonly type: TypeMethod | TypeMethodSignature | TypeFunction);
static from(fn: Function): ReflectionFunction;
getParameterNames(): (string)[];
hasParameter(name: string | number | symbol): boolean;
getParameterOrUndefined(name: string | number | symbol): ReflectionParameter | undefined;
getParameter(name: string | number | symbol): ReflectionParameter;
getParameterType(name: string | number | symbol): Type | undefined;
getParameters(): ReflectionParameter[];
getReturnType(): Type;
getName(): number | string | symbol;
getDescription(): string;
get name(): string;
}
export class ReflectionMethod extends ReflectionFunction {
/**
* Whether this method acts as validator.
*/
validator: boolean;
constructor(public type: TypeMethod | TypeMethodSignature, public reflectionClass: ReflectionClass<any>);
setType(method: TypeMethod | TypeMethodSignature);
applyDecorator(data: TData);
clone(reflectionClass?: ReflectionClass<any>, method?: TypeMethod | TypeMethodSignature): ReflectionMethod;
isOptional(): boolean;
}
export class ReflectionProperty {
jsonType?: Type;
serializer?: SerializerFn;
deserializer?: SerializerFn;
data: {
[name: string]: any;
};
/**
* The type of the property, not the property itself.
*
* Note: If the property is optional via `property?: T`, this information
* is not available here. It's on `property`.
* Use `isOptional()` instead, which handles this case plus the case
* where optionality is given via union of T and undefined.
*/
type: Type;
symbol: symbol;
constructor(public property: TypeProperty | TypePropertySignature, public reflectionClass: ReflectionClass<any>);
setType(type: Type);
isPrimaryKey(): boolean;
isEmbedded(): boolean;
/**
* Returns the sub type if available (for arrays for example).
*
* @throws Error if the property type does not support sub types.
*/
getSubType(): Type;
/**
* If undefined, it's not an embedded class.
*/
getEmbedded(): {
prefix?: string;
} | undefined;
isBackReference(): boolean;
isDatabaseSkipped(database: string): boolean;
isDatabaseMigrationSkipped(database: string): boolean;
getBackReference(): BackReferenceOptionsResolved;
isAutoIncrement(): boolean;
isReference(): boolean;
isArray(): boolean;
isDate(): boolean;
isNumber(): boolean;
getForeignKeyName(): string;
getReference(): ReferenceOptions | undefined;
getGroups(): string[];
isInGroup(...group: string[]): boolean;
getExcluded(): string[];
isSerializerExcluded(name: string): boolean;
getData(): {
[name: string]: any;
};
/**
* Returns the ReflectionClass of the reference class/object literal.
*
* @throws Error if the property is not from type TypeClass or TypeObjectLiteral
*/
getResolvedReflectionClass(): ReflectionClass<any>;
/**
* If undefined the property is not an index.
* A unique property is defined as index with IndexOptions.unique=true.
*/
getIndex(): IndexOptions | undefined;
/**
* Returns database specific options, if defined
*
* ```typescript
* interface User {
* logins: number & DatabaseField<{type: 'integer(8)'}>;
*
* //of for a specific db engine
* logins: number & Sqlite<{type: 'integer(8)'}>;
* }
*
* ```
*/
getDatabase<T extends DatabaseFieldOptions>(name: string): T | undefined;
clone(reflectionClass?: ReflectionClass<any>, property?: TypeProperty | TypePropertySignature): ReflectionProperty;
applyDecorator(data: TData);
getName(): number | string | symbol;
getNameAsString(): string;
get name(): string;
getKind(): ReflectionKind;
getType(): Type;
getDescription(): string;
/**
* Whether a value is required from serialization point of view.
* If this property has for example a default value (set via constructor or manually via t.default),
* then the value is not required to instantiate the property value.
*/
isValueRequired(): boolean;
/**
* Returns true when `undefined` or a missing value is allowed at the class itself.
* This is now only true when `optional` is set, but also when type is `any`.
*/
isActualOptional(): boolean;
/**
* If the property is actual optional or is an union with undefined in it.
*/
isOptional(): boolean;
setOptional(v: boolean): void;
isNullable(): boolean;
isReadonly(): boolean;
isAbstract(): boolean;
hasDefault(): boolean;
getDefaultValue(): any;
hasDefaultFunctionExpression(): boolean;
getDefaultValueFunction(): (() => any) | undefined;
getVisibility(): ReflectionVisibility | undefined;
isPublic(): boolean;
isProtected(): boolean;
isPrivate(): boolean;
}
export class TData {
validator: boolean;
validators: ValidateFunction[];
type?: Packed | Type | ClassType;
data: {
[name: string]: any;
};
serializer?: SerializerFn;
deserializer?: SerializerFn;
}
export class EntityData {
name?: string;
collectionName?: string;
databaseSchemaName?: string;
disableConstructor: boolean;
data: {
[name: string]: any;
};
indexes: {
names: string[];
options: IndexOptions;
}[];
singleTableInheritance?: true;
}
export class ReflectionClass<T> {
/**
* The description, extracted from the class JSDoc @description.
*/
description: string;
/**
* A place where arbitrary data is stored, usually set via decorator t.data.
*/
data: {
[name: string]: any;
};
/**
* The unique entity name.
*
* ```typescript
* @entity.name('user')
* class User {
*
* }
* ```
*/
name?: string;
databaseSchemaName?: string;
disableConstructor: boolean;
/**
* The collection name, used in database context (also known as table name).
*
* Usually, if this is not set, `name` will be used.
*
* ```typescript
* @entity.collection('users').name('user')
* class User {
*
* }
* ```
*/
collectionName?: string;
/**
* True when @entity.singleTableInheritance was set.
*/
singleTableInheritance: boolean;
/**
* Contains all indexed, multi-field using entity.index and all indexes from properties.
*
* ```typescript
* @entity
* .collection('users')
* .name('user')
* .index(['username', 'email'])
* .index(['email', 'region'], {unique: true})
* class User {
* username: string;
* email: string;
* }
* ```
*/
indexes: {
names: string[];
options: IndexOptions;
}[];
/**
* If a custom validator method was set via @t.validator, then this is the method name.
*/
validationMethod?: string | symbol | number | TypeTemplateLiteral;
/**
* A class using @t.singleTableInheritance registers itself in this array in its super class.
*/
subClasses: ReflectionClass<any>[];
constructor(public readonly type: TypeClass | TypeObjectLiteral, public readonly parent?: ReflectionClass<any>);
clone(): ReflectionClass<any>;
toString(): string;
getPropertiesDeclaredInConstructor(): ReflectionProperty[];
clearJitContainer();
getJitContainer();
getClassType(): ClassType;
getClassName(): string;
createDefaultObject(): object;
getName(): string;
getDescription(): string;
getCollectionName(): string;
hasProperty(name: string | symbol | number): boolean;
hasMethod(name: string | symbol | number): boolean;
getPrimary(): ReflectionProperty;
getAutoIncrement(): ReflectionProperty | undefined;
isSchemaOf(classType: ClassType): boolean;
hasPrimary(): boolean;
getPrimaries(): ReflectionProperty[];
/**
* Returns the ReflectionClass object from parent/super class, if available.
*/
getSuperReflectionClass(): ReflectionClass<any> | undefined;
removeProperty(name: string | number | symbol);
registerProperty(property: ReflectionProperty);
addProperty(prop: {
name: number | string | symbol;
optional?: true;
readonly?: true;
description?: string;
visibility?: ReflectionVisibility;
type: Type;
}): ReflectionProperty;
registerMethod(method: ReflectionMethod);
add(member: Type);
assignedSingleTableInheritanceSubClassesByIdentifier?: {
[id: string]: ReflectionClass<any>;
};
getAssignedSingleTableInheritanceSubClassesByIdentifier(): {
[id: string]: ReflectionClass<any>;
} | undefined;
hasSingleTableInheritanceSubClasses(): boolean;
getSingleTableInheritanceDiscriminantName(): string;
applyDecorator(data: EntityData);
static from<T>(classTypeIn?: ReceiveType<T> | AbstractClassType<T> | TypeClass | TypeObjectLiteral | ReflectionClass<any>, args: any[] = []): ReflectionClass<T>;
getIndexSignatures();
getPropertyNames(): (string | number | symbol)[];
getProperties(): ReflectionProperty[];
getPropertiesInGroup(...group: string[]): ReflectionProperty[];
getMethodNames(): (string | number | symbol)[];
getMethods(): ReflectionMethod[];
/**
* Returns references and back references.
*/
getReferences(): ReflectionProperty[];
getConstructorOrUndefined(): ReflectionMethod | undefined;
getPropertyOrUndefined(name: string | number | symbol | TypeTemplateLiteral): ReflectionProperty | undefined;
getProperty(name: string | number | symbol): ReflectionProperty;
getMethodParameters(name: string | number | symbol): ReflectionParameter[];
getMethodOrUndefined(name: string | number | symbol | TypeTemplateLiteral): ReflectionMethod | undefined;
getMethod(name: string | number | symbol): ReflectionMethod;
hasCircularReference(): boolean;
serializeType(): SerializedTypes;
/**
* All references have a counter-part. This methods finds it and errors if not possible.
*
* If the given reference is a owning reference it finds the correct backReference,
* which can be found by checking all reference options.mappedBy.
*
* If the given reference is a back reference it finds the owning reference,
* which can be found by using its options.mappedBy.
*
* Alternatively we simply check for resolvedClassType to be given `classType`, and if only one
* found, we return it. When more than one found, we throw an error saying the user he
* should make its relation mapping not ambiguous.
*/
findReverseReference(toClassType: ClassType, fromReference: ReflectionProperty): ReflectionProperty;
extractPrimaryKey(item: object): Partial<T>;
}
Errors
export class SerializationError extends CustomError {
constructor(public originalMessage: string, public code: string = , public path: string = );
}
export class NoTypeReceived extends Error {
constructor(message: string = );
}
@entity.name()
export class ValidationError extends CustomError {
constructor(public readonly errors: ValidationErrorItem[], type?: Type);
static from(errors: {
path: string;
message: string;
code?: string;
value?: any;
}[]);
}
Const
unique symbol
TypeSettings
unique symbol
unique symbol
unique symbol
(Anonymous class)
ReflectionKind[]
Serializer
RegExp
{ [x: string]: (...args: any[]) => (value: any) => ValidatorError; }
SnapshotSerializer
AnnotationDefinition<ReferenceOptions>
(Anonymous class)
AnnotationDefinition<{ name: string; serializer?: string; }>
AnnotationDefinition<true>
(Anonymous class)
AnnotationDefinition<BackReferenceOptionsResolved>
AnnotationDefinition<{ name: string; args: Type[]; }>
AnnotationDefinition<true>
AnnotationDefinition<true>
AnnotationDefinition<true>
AnnotationDefinition<Type>
AnnotationDefinition<EmbeddedOptions>
AnnotationDefinition<BinaryBigIntType>
AnnotationDefinition<string>
(Anonymous class)
(Anonymous class)
(Anonymous class)
TypeAnnotation<Name, Options>
types.AnnotationDefinition<IndexOptions>
(Anonymous class)
TypeDecorator[]
ClassType<any>[]
unique symbol
Functions
<K>(buf: Buffer, type: TypedArrayClassType<K>): K
<K>(base64: string, type: TypedArrayClassType<K>): K
(base64: string): ArrayBuffer
<K>(buf: Uint8Array | ArrayBuffer): ArrayBuffer
<K>(typedArray: TypedArray): Buffer
(arrayBuffer: ArrayBuffer): string
(typedArray: TypedArray): string
(data: string, encoding?: string): ArrayBuffer
(arrayBuffer: ArrayBuffer, encoding?: string | "utf8" | "base64" | "ascii"): string
<T extends object>(object: T): AtomicChangeInstance<T>
(obj: any): obj is { __decorators: DeferredDecorator[]; }
PropertyDecoratorResult<typeof TDecorator>
ClassDecoratorResult<typeof EntityDecorator>
<API extends APIClass<any> | APIProperty<any>, D extends Function>(api: API, modifier: { name: string; args?: any; Ω?: any; }[], collapse: (modifier: { name: string; args?: any; }[], target: any, property?: string, parameterIndexOrDescriptor?: any) => void, returnCollapse?: boolean, fluidFunctionSymbol?: symbol): FluidDecorator<ExtractClass<API>, D>
<T extends any[]>(...args: T): Merge<Omit<UnionToIntersection<T[number]>, "_fetch" | "t">>
<API extends APIClass<any>, T = ExtractApiDataType<API>>(apiType: API): ClassDecoratorResult<API>
<API extends APIProperty<any>>(apiType: API): PropertyDecoratorResult<API>
<API extends APIClass<any>, T = ExtractApiDataType<API>>(apiType: API): FreeDecoratorResult<API>
<API extends APIClass<any>>(context: FreeDecoratorResult<API>, fn: Function): fn is FreeFluidDecorator<API>
(obj: any): boolean
<T>(obj: T): ReferenceInfo<T> | undefined
<T>(obj: T): ReferenceItemInfo<T> | undefined
<T>(obj: T): ReferenceItemInfo<T>
(obj: any): boolean
(item: any): void
<T>(type: ClassType<T> | Type | ReflectionClass<any>, pk: { [name: string]: any; }): T
<T>(reflection: ReflectionClass<any>): ClassType<T>
(type: TypeClass | TypeObjectLiteral): any
(type: TypeClass | TypeObjectLiteral, registry: TemplateRegistry, namingStrategy?: NamingStrategy): SerializeFunction<any, any>
(type: Type, registry: TemplateRegistry, namingStrategy?: NamingStrategy, path?: string, jitStack?: JitStack): SerializeFunction
(type: Type, registry: TemplateRegistry, namingStrategy?: NamingStrategy, path?: string | RuntimeCode | (string | RuntimeCode)[], jitStack?: JitStack): SerializeFunction
(type: Type, stateIn?: Partial<TemplateState>, serializerToUse?: Serializer, withLoose?: boolean): undefined | Guard<any>
(path: (string | RuntimeCode)[], prefix?: string): string
(propertyName?: string | RuntimeCode): string
(type: Type, state: TemplateState): void
(state: TemplateState, type: Type): boolean
(state: TemplateState, type: Type): { setFunction: (fn: Function) => { fn: Function | undefined; }; id: number; state: TemplateState; }
(state: TemplateState, type: Type): Function
(state: TemplateState, type: Type, withLoose?: boolean, withCache?: boolean): string
(property: ReflectionProperty | TypeProperty | TypePropertySignature | TypeIndexSignature, state: TemplateState, undefinedSetterCode?: string, nullSetterCode?: string): string
(accessor: ContainerAccessor | string): string
(type: TypeClass | TypeObjectLiteral, state: TemplateState, container?: string): string
(context: CompilerContext, i: string, type: Type): string
(signatures: TypeIndexSignature[]): void
(member: TypeProperty | TypePropertySignature, setter: string | ContainerAccessor, state: TemplateState): string
(type: TypeClass | TypeObjectLiteral): TypeProperty | TypePropertySignature | undefined
(type: TypeObjectLiteral | TypeClass, state: TemplateState): void
(type: TypeClass | TypeObjectLiteral, state: TemplateState, embedded: EmbeddedOptions): void
(type: TypeObjectLiteral | TypeClass, state: TemplateState): void
(type: TypeArray, state: TemplateState): void
(elementType: Type, state: TemplateState): void
(type: TypeClass): TypeArray
(type: TypeClass): TypeArray
(type: TypeClass, n: number): TypeArray
(type: TypeClass, typeIndex: number, state: TemplateState): void
(type: TypeClass, state: TemplateState): void
(type: TypeClass, state: TemplateState): void
(type: TypePropertySignature | TypeProperty | TypeParameter, state: TemplateState): void
(type: TypePropertySignature | TypeProperty | TypeParameter, state: TemplateState): void
(type: TypeUnion, state: TemplateState): void
(name: string | number | symbol | undefined, state: TemplateState): string
<T>(data: JSONPartial<T> | unknown, options?: SerializationOptions, serializerToUse?: Serializer, namingStrategy?: NamingStrategy, type?: ReceiveType<T>): T
<T>(serializerToUse?: Serializer, namingStrategy?: NamingStrategy, type?: ReceiveType<T>): (data: JSONPartial<T> | unknown, options?: SerializationOptions) => T
<T>(data: JSONPartial<T> | unknown, options?: SerializationOptions, serializerToUse?: Serializer, namingStrategy?: NamingStrategy, type?: ReceiveType<T>): T
interface Data {
created: Date;
}
const data = deserialize<Data>({created: '2009-02-13T23:31:30.123Z'});
//data is {created: Date(2009-02-13T23:31:30.123Z)}
<T>(serializerToUse?: Serializer, namingStrategy?: NamingStrategy, type?: ReceiveType<T>): SerializeFunction<any, T>
<T>(data: DeepPartial<T>, options?: SerializationOptions, serializerToUse?: Serializer, namingStrategy?: NamingStrategy, type?: ReceiveType<T>): (data: JSONPartial<T> | unknown) => T
{'user.shippingAddress.street': 'abc'}
If a naming strategy is used, it could be converted to {'user.shipping_address.street': 'abc'}
.(type: TypeClass | TypeObjectLiteral, registry: TemplateRegistry, namingStrategy?: NamingStrategy): (data: any, state?: SerializationOptions, patch?: { normalizeArrayIndex: boolean; }) => any
<T>(data: T, options?: SerializationOptions, serializerToUse?: Serializer, namingStrategy?: NamingStrategy, type?: ReceiveType<T>): JSONSingle<T>
interface Data {
created: Date;
}
const json = serialize<Data>({created: new Date(1234567890123)});
//json is {created: '2009-02-13T23:31:30.123Z'}
const jsonString = JSON.stringify(json);
//jsonString is '{"created":"2009-02-13T23:31:30.123Z"}'
<T>(serializerToUse?: Serializer, namingStrategy?: NamingStrategy, type?: ReceiveType<T>): SerializeFunction<T>
<T>(target: T, options?: SerializationOptions): T
<T>(data: any, options?: SerializationOptions, serializerToUse?: Serializer, namingStrategy?: NamingStrategy, type?: ReceiveType<T>): T
<T>(serializerToUse?: Serializer, receiveType?: ReceiveType<T>): Guard<T>
const validator = getValidatorFunction<MyType>();
const errors: ValidationErrorItem[] = [];
const valid = validator(data, {errors})
if (errors.length) console.log(errors); //validation failed if not empty
<T>(data: any, serializerToUse?: Serializer, errors?: ValidationErrorItem[], receiveType?: ReceiveType<T>): data is T
<T>(serializerToUse?: Serializer, receiveType?: ReceiveType<T>): Guard<T>
<T>(data: any, serializerToUse?: Serializer, receiveType?: ReceiveType<T>): asserts data is T
(): string
(buffer: Uint8Array, offset?: number): Uint8Array
(buffer: Uint8Array, offset?: number): string
(v: string): RegExp
<T>(data: any, type?: ReceiveType<T>): ValidationErrorItem[]
<T>(serializerToUse?: Serializer, type?: ReceiveType<T>): (data: T) => ValidationErrorItem[]
<T>(data: any, type?: ReceiveType<T>): boolean
(reflectionClass: ReflectionClass<any>): (value: any) => any
plain
serialization while references are
stored only as their primary keys.<T>(reflectionClass: ReflectionClass<T>, item: T): any
<T>(reflectionClass: ReflectionClass<T>): (value: any) => Partial<T>
(reflectionClass: ReflectionClass<any>, serializerToUse?: Serializer): (value: any) => string
(reflectionClass: ReflectionClass<any>): (data: PrimaryKeyFields<any>) => string
(a: any, b: any): boolean
<T extends object>(classSchema: ReflectionClass<T>): (last: any, current: any, item: T) => ItemChanges<T> | undefined
<T extends object>(classSchema: ReflectionClass<T>, lastSnapshot: any, item: T): Changes<T>
<T>(path: string, type?: ReceiveType<T>): Type
<T>(type?: ReceiveType<T>, jitStack?: JitStack): Resolver
(type: Type, state?: Partial<SerializerState>): SerializedTypes
(types?: SerializedTypes, state?: Partial<DeserializeState>): Type
(type: Type): any
<T extends AbstractClassType[]>(...classTypes: T): ClassType<UnionToIntersection<ExtractClassType<T[number]>>>
(type: Type): void
(object: ClassType | Function): boolean
(type: Type): JitContainer
(type: Type): void
(type: Type): type is TypeNumber
(entry: any): entry is Type
(type: Type): boolean
<T extends Type>(type: T): boolean
(type: Type): type is TypePropertySignature | TypeProperty
(type: Type): type is TypePropertySignature | TypeProperty
(type: TypeClass | TypeObjectLiteral): { parameters: (TypeProperty | Type)[]; properties: TypeProperty[]; }
constructor(public title: string)
)constructor(public title: string, anotherOne:number)
=> [TypeProperty, TypeNumber](type: ParentLessType): type is WithAnnotations
(type: WithAnnotations): Annotations
(a: Type, b: Type, stack?: StackEntry[]): boolean
<T extends Type>(container: T, type: Type): T
(types: Type[], type: Type, stack?: StackEntry[]): boolean
<T extends Type>(type: T): T
true | (string | number)
=> true | string | number
(types: Type[]): Type[]
(union: TypeUnion): Type
(index: string | number | symbol | TypeTemplateLiteral, types: Type[]): TypePropertySignature | TypeMethodSignature | TypeMethod | TypeProperty | TypeIndexSignature | undefined
(type: Type): boolean
(container: Type, index: Type): Type
(types: (TypeObjectLiteral | TypeClass)[]): TypeObjectLiteral
(type: Type): Type
<T extends ParentLessType>(inc: T, parent?: Type): FindType<Type, T["kind"]>
(type: Type): Type
<K extends ReflectionKind, T>(t: Type | undefined, kind: K): asserts t is FindType<Type, K>
(type: Type): ClassType
(type: Type): type is TypePropertySignature | TypeProperty | TypeMethodSignature | TypeMethod
(type: TypeObjectLiteral | TypeClass, memberName: number | string | symbol, memberType?: Type): boolean
(type: TypeObjectLiteral | TypeClass, memberName: number | string | symbol): TypeMethodSignature | TypeMethod | TypePropertySignature | TypeProperty | void
<T extends Type>(type: T): T extends TypeClass ? TypeObjectLiteral : T
(type: Type): boolean
undefined
is allowed as type.(type: Type): boolean
(type: Type): boolean
null
is allowed as type.(type: Type): boolean
(type: Type): boolean
(type: Type): boolean
(type: Type): boolean
(type: Type): boolean
(type: Type): boolean
(type: Type): ReferenceOptions | undefined
(type: Type): boolean
(type: Type): Type
(type: Type): BackReferenceOptionsResolved
(type: Type): boolean
(type: Type): boolean
(type: Type): boolean
(type: Type): Type
(type: Type): Type
(type: Type): boolean
(decorator: TypeDecorator): void
(type: TypeObjectLiteral): { id: string; options: Type; } | undefined
never
type to make sure it does not
interfere with type checking.never & x
to never
,
so we still have the intersection type in runtime to resolve __meta correctly.type MyAnnotation1 = TypeAnnotation<'myAnnotation'>
type MyAnnotation1<T> = TypeAnnotation<'myAnnotation', T>
//under the hood it is:
type lowLevel1 = { __meta?: never & ['myAnnotation'] }
type lowLevel2<T> = { __meta?: never & ['myAnnotation', T] }
(type?: Type, state?: { stack: Type[]; }): any
(name: number | string | symbol): string
(type: Type): type is TypeClass
(type: Type): type is TypeClass
(classType: ClassType, withInheritance?: boolean): (type: Type) => boolean
(type: TypeClass | TypeObjectLiteral): (TypeProperty | TypePropertySignature | TypeMethodSignature | TypeMethod | TypeIndexSignature | TypeCallSignature)[]
(type: Type): string
(type: Type, stateIn?: Partial<StringifyTypeOptions>): string
(type: TypeClass): TypeParameter[]
(type: TypeEnum): (value: string | number | undefined | null) => number
type.values
if the given value is part of the enum, exactly or case-insensitive.
Returns -1 if not found.(type: Type, stateIn?: Partial<StringifyTypeOptions>): string
<T>(clazz: ClassType | AbstractClassType, type?: ReceiveType<T>): void
(ops: ReflectionOp[]): string
(packOrOps: PackStruct | ReflectionOp[]): Packed
(pack: Packed): PackStruct
(type: Packed, args?: any[], options?: ReflectOptions): Type
(o: ClassType | Function | Packed | any, args?: any[], options?: ReflectOptions): Type
(value: any): Type
(values: any[]): Type
(leftValue: AssignableType, rightValue: AssignableType, extendStack?: StackEntry[]): boolean
extends
in Typescript. This function can be read as left extends right
.(left: Type, right: Type, extendStack?: StackEntry[]): boolean
(type: TypePromise): TypeObjectLiteral
(parameters: TypeParameter[]): TypeTuple
(left: TypeLiteral | TypeTemplateLiteral, right: TypeTemplateLiteral): boolean
(type?: Packed | Type | Function | ClassType | AbstractClassType | ReflectionClass<any>): Type
(o: any, ...args: any[]): Type
(o: any, ...args: any[]): Type | undefined
<T>(args?: any[], p?: ReceiveType<T>): (string | number | symbol | Type)[]
<T>(args?: any[], p?: ReceiveType<T>): (string | number | symbol | Type)[]
<T>(args?: any[], p?: ReceiveType<T>): number | undefined
<T>(args?: any[], p?: ReceiveType<T>): Type
<T extends Type>(type: T): T
<T extends Type | undefined | Type[]>(type: T): T
(type: TypeObjectLiteral | TypeClass, memberName: number | string | symbol): TypeProperty | TypePropertySignature | undefined
(type: TypeProperty | TypeMethod | TypePropertySignature | TypeMethodSignature): TypePropertySignature | TypeMethodSignature
(type: Type): any
(type: Type, visitor: (type: Type, path: string) => false | void, onCircular?: () => void): void
(property: ReflectionProperty): ReflectionClass<any>
(type: Type): ReflectionClass<any>
Types
interface TypeSettings {
registeredEntities: { [name: string]: ClassType };
unpopulatedCheck: UnpopulatedCheck;
}
interface TypedArrayClassType<T> {
new(...args: any[]): T;
readonly BYTES_PER_ELEMENT: number;
}
interface TypedArray {
/**
* The size in bytes of each element in the array.
*/
readonly BYTES_PER_ELEMENT: number;
/**
* The ArrayBuffer instance referenced by the array.
*/
readonly buffer: ArrayBufferLike;
/**
* The length of the array.
*/
readonly length: number;
/**
* The length in bytes of the array.
*/
readonly byteLength: number;
/**
* The offset in bytes of the array.
*/
readonly byteOffset: number;
}
type NumberFields<T> = { [K in keyof T]: T[K] extends number | bigint ? K : never }[keyof T]
type Expression<T> = { [P in keyof T & string]?: string; }
type Partial<T> = { [P in keyof T & string]?: T[P] }
type DeepPartial<T> = {
[P in keyof T]?: T[P]
} & { [deepPath: string]: any };
interface ChangesInterface<T> {
$set?: DeepPartial<T> | T;
$unset?: { [path: string]: number };
$inc?: Partial<Pick<T, NumberFields<T>>>;
}
type ClassDecoratorFn = (classType: AbstractClassType, property?: string, parameterIndexOrDescriptor?: any) => void;
type PropertyDecoratorFn = (prototype: object, property?: number | string | symbol, parameterIndexOrDescriptor?: any) => void;
type FluidDecorator<T, D extends Function> = {
[name in keyof T]: T[name] extends (...args: infer K) => any ? (...args: K) => D & FluidDecorator<T, D>
: D & FluidDecorator<T, D>
& { _data: ExtractApiDataType<T> };
};
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
type Merge<U> = { [K in keyof U]: U[K] extends ((...a: infer A) => infer R) ? R extends DualDecorator ? (...a: A) => PropertyDecoratorFn & R & U : (...a: A) => R : never };
type DualDecorator = void & { __DualDecorator?: true };
interface ClassApiTypeInterface<T> {
t: T,
onDecorator?: (classType: ClassType, property?: string, parameterIndexOrDescriptor?: any) => void
}
type APIClass<T> = ClassType<ClassApiTypeInterface<T>>;
type ExtractClass<T> = T extends ClassType<infer K> ? K : never;
type ExtractApiDataType<T> = T extends AbstractClassType<infer K> ? K extends { t: infer P } ? P : never : (T extends { t: infer P } ? P : never);
type ClassDecoratorResult<API extends APIClass<any>> = FluidDecorator<ExtractClass<API>, ClassDecoratorFn> & DecoratorAndFetchSignature<API, ClassDecoratorFn>;
interface PropertyApiTypeInterface<T> {
t: T,
onDecorator?: (target: ClassType, property: string | undefined, parameterIndexOrDescriptor?: any) => void
}
type APIProperty<T> = ClassType<PropertyApiTypeInterface<T>>;
type DecoratorAndFetchSignature<API extends APIProperty<any>, FN extends (...args: any[]) => any> = & FN
& { _fetch: (...args: Parameters<FN>) => ExtractApiDataType<API> | undefined };
type PropertyDecoratorResult<API extends APIProperty<any>> = FluidDecorator<ExtractClass<API>, PropertyDecoratorFn> & DecoratorAndFetchSignature<API, PropertyDecoratorFn>;
type FreeDecoratorFn<API> =
{ (target?: any, property?: number | string | symbol, parameterIndexOrDescriptor?: any): ExtractApiDataType<API> }
& { _data: ExtractApiDataType<API> };
type FreeFluidDecorator<API> = {
[name in keyof ExtractClass<API>]: ExtractClass<API>[name] extends (...args: infer K) => any
? (...args: K) => FreeFluidDecorator<API>
: FreeFluidDecorator<API>
} & FreeDecoratorFn<API>;
type FreeDecoratorResult<API extends APIClass<any>> = FreeFluidDecorator<API> & { _fluidFunctionSymbol: symbol };
interface ReferenceInfo<T> {
hydrator?: (item: T) => Promise<void>;
}
interface ReferenceItemInfo<T> {
hydrated: boolean,
}
interface SerializationOptions {
/**
* Which groups to include. If a property is not assigned to
* a given group, it will be excluded.
* Use an empty array to include only non-grouped properties.
*/
groups?: string[];
/**
* Which groups to exclude. If a property is assigned to at least
* one given group, it will be excluded. Basically the opposite of
* `groups`, but you can combine both.
* Use an empty array to exclude only non-grouped properties.
*/
groupsExclude?: string[];
/**
* Allows more loosely data for certain types. e.g.
*
* - '1', '0', 'true', 'false' will be converted to true|false for boolean type.
* - '1' will be converted to number for number type.
* - 1 will be converted to string for string type.
*
* This will activate all registered type guards with negative specifically.
*
* This is enabled by default.
*/
loosely?: boolean;
}
type SerializeFunction<T = any, R = any> = (data: T, state?: SerializationOptions) => R;
type Guard<T> = (data: any, state?: { errors?: ValidationErrorItem[] }) => data is T;
type Template<T extends Type> = (type: T, state: TemplateState) => void;
type TemplateHook = (type: Type, state: TemplateState) => void;
type AutoId = number & PrimaryKey & AutoIncrement & Positive;
type Binary = ArrayBuffer | Uint8Array | Int8Array | Uint8ClampedArray | Uint16Array | Int16Array | Uint32Array | Int32Array | Float32Array | Float64Array;
type JSONPartial<T> = T extends Date ? string :
T extends Array<infer K> ? Array<JSONPartial<K>> :
// T extends TypedArrays ? string :
T extends Binary ? string :
T extends object ? JSONPartialObject<T> :
T extends string ? number | T :
T extends boolean ? number | string | T :
T extends bigint ? number | string | T :
T extends number ? bigint | string | T :
T;
type JSONPartialObject<T> = { [name in keyof T]?: T[name] | null };
type JSONSingle<T> = T extends Date ? string | Date :
T extends Array<infer K> ? Array<JSONSingle<K>> :
T extends Binary ? string :
T extends object ? JSONEntity<T> :
T extends string ? string | number | boolean | undefined :
T extends boolean ? T | number | string :
T extends number ? T | string : T;
type JSONEntity<T> = { [name in keyof T]: JSONSingle<T[name]> };
type ValidatorMeta<Name extends string, Args extends [...args: any[]] = []> = TypeAnnotation<'validator', [Name, Args]>;
type ValidateFunction = (value: any, type: Type, options: any) => ValidatorError | void;
type Validate<T extends ValidateFunction, Options extends Parameters<T>[2] = unknown> = ValidatorMeta<'function', [T, Options]>;
type Pattern<T extends RegExp> = ValidatorMeta<'pattern', [T]>;
type Alpha = ValidatorMeta<'alpha'>;
type Alphanumeric = ValidatorMeta<'alphanumeric'>;
type Ascii = ValidatorMeta<'ascii'>;
type Decimal<MinDigits extends number = 1, MaxDigits extends number = 100> = ValidatorMeta<'decimal', [MinDigits, MaxDigits]>;
type MultipleOf<Num extends number> = ValidatorMeta<'multipleOf', [Num]>;
type MinLength<Length extends number> = ValidatorMeta<'minLength', [Length]>;
type MaxLength<Length extends number> = ValidatorMeta<'maxLength', [Length]>;
type Includes<T extends string | number | boolean> = ValidatorMeta<'includes', [T]>;
type Excludes<T extends string | number | boolean> = ValidatorMeta<'excludes', [T]>;
type Minimum<T extends number | bigint> = ValidatorMeta<'minimum', [T]>;
type Maximum<T extends number | bigint> = ValidatorMeta<'maximum', [T]>;
type Positive = ValidatorMeta<'positive', unknown & [true]>;
type Negative = ValidatorMeta<'negative', [true]>;
type PositiveNoZero = ValidatorMeta<'positive', [false]>;
type NegativeNoZero = ValidatorMeta<'negative', [false]>;
type ExclusiveMinimum<T extends number | bigint> = ValidatorMeta<'exclusiveMinimum', [T]>;
type ExclusiveMaximum<T extends number | bigint> = ValidatorMeta<'exclusiveMaximum', [T]>;
type BeforeDate<T extends number> = ValidatorMeta<'beforeDate', [T]>;
type AfterDate<T extends number> = ValidatorMeta<'afterDate', [T]>;
type BeforeNow = ValidatorMeta<'beforeNow'>;
type AfterNow = ValidatorMeta<'afterNow'>;
type Email = string & Pattern<typeof EMAIL_REGEX>;
type Resolver = (path: string) => Type | undefined;
interface SerializedTypeAnnotations {
entityOptions?: EntityOptions;
typeName?: string;
typeArguments?: SerializedTypeReference[];
indexAccessOrigin?: { container: SerializedTypeReference, index: SerializedTypeReference };
// annotations will be generated on deserialization from the decorators
// annotations?: Annotations; //parsed decorator types as annotations
decorators?: SerializedTypeReference[]; //original decorator type
}
interface SerializedTypeBaseMember extends SerializedTypeAnnotations {
visibility: ReflectionVisibility,
abstract?: true;
optional?: true,
readonly?: true;
}
interface SerializedTypeMethod extends SerializedTypeBaseMember {
kind: ReflectionKind.method,
visibility: ReflectionVisibility,
name: number | string | symbol;
parameters: SerializedTypeParameter[];
optional?: true,
abstract?: true;
return: SerializedTypeReference;
}
interface SerializedTypeUnion extends SerializedTypeAnnotations {
kind: ReflectionKind.union,
types: SerializedTypeReference[];
}
interface SerializedTypeIntersection extends SerializedTypeAnnotations {
kind: ReflectionKind.intersection,
types: SerializedTypeReference[];
}
interface SerializedTypeTypeParameter extends SerializedTypeAnnotations {
kind: ReflectionKind.typeParameter,
name: string,
}
type SerializedType =
SimpleSerializedType
| SerializedTypeLiteral
| SerializedTypeTemplateLiteral
| SerializedTypeParameter
| SerializedTypeFunction
| SerializedTypeMethod
| SerializedTypeProperty
| SerializedTypePromise
| SerializedTypeClassType
| SerializedTypeEnum
| SerializedTypeUnion
| SerializedTypeIntersection
| SerializedTypeArray
| SerializedTypeObjectLiteral
| SerializedTypeIndexSignature
| SerializedTypePropertySignature
| SerializedTypeMethodSignature
| SerializedTypeTypeParameter
| SerializedTypeInfer
| SerializedTypeTuple
| SerializedTypeTupleMember
| SerializedTypeRest;
type SerializedTypes = SerializedType[];
interface SerializerState {
types: SerializedTypes;
disableMethods?: true;
refs: Map<Type, number>;
}
type TypeDecorator = (annotations: Annotations, decorator: TypeObjectLiteral) => boolean;
type Annotations = any;
interface TypeAnnotations {
// if defined, it is a nominal type. the number is unique for each nominal type.
id?: number;
origin?: Type;
/**
* True when this type comes from an inline type, e.g.
*
* `type A = T;`. Type of `T` is inlined.
* `type A = {}`. Type of `{}` is not inlined.
*
* If the type is not inlined and the result of a type function, then we assign parents of members accordingly. This is not the caee when a type was inlined.
*/
inlined?: true;
/**
* If the type was created by a type function, this contains the alias name.
*/
typeName?: string;
/**
* If the type was created by a type function, this contains the arguments passed the function.
*/
typeArguments?: Type[];
/**
* Set for index access expressions, e.g. Config['property'].
*/
indexAccessOrigin?: { container: TypeClass | TypeObjectLiteral, index: Type };
/**
* type User = {id: number, user: string};
* type UserCreate = Pick<User, 'user'>;
* typeOf<UserCreate>().originTypes[0].typeName = 'Pick'
* typeOf<UserCreate>().originTypes[0].typeArguments = [User, 'user']
*/
originTypes?: { typeName: string, typeArguments?: Type[] }[];
annotations?: Annotations; //parsed decorator types as annotations
decorators?: Type[]; //original decorator type
scheduleDecorators?: TypeObjectLiteral[];
/**
* A place where arbitrary jit functions and its cache data is stored.
*/
jit?: JitContainer;
}
type JitContainer = any;
interface TypeNever extends TypeAnnotations {
kind: ReflectionKind.never,
parent?: Type;
}
interface TypeAny extends TypeAnnotations {
kind: ReflectionKind.any,
parent?: Type;
}
interface TypeUnknown extends TypeAnnotations {
kind: ReflectionKind.unknown,
parent?: Type;
}
interface TypeVoid extends TypeAnnotations {
kind: ReflectionKind.void,
parent?: Type;
}
interface TypeObject extends TypeAnnotations {
kind: ReflectionKind.object,
parent?: Type;
}
interface TypeString extends TypeAnnotations {
kind: ReflectionKind.string,
parent?: Type;
}
interface TypeNumber extends TypeAnnotations {
kind: ReflectionKind.number,
brand?: TypeNumberBrand; //built in brand
parent?: Type;
}
interface TypeBoolean extends TypeAnnotations {
kind: ReflectionKind.boolean,
parent?: Type;
}
interface TypeBigInt extends TypeAnnotations {
kind: ReflectionKind.bigint,
parent?: Type;
}
interface TypeSymbol extends TypeAnnotations {
kind: ReflectionKind.symbol,
parent?: Type;
}
interface TypeNull extends TypeAnnotations {
kind: ReflectionKind.null,
parent?: Type;
}
interface TypeUndefined extends TypeAnnotations {
kind: ReflectionKind.undefined,
parent?: Type;
}
interface TypeLiteral extends TypeAnnotations {
kind: ReflectionKind.literal,
literal: symbol | string | number | boolean | bigint | RegExp;
parent?: Type;
}
interface TypeTemplateLiteral extends TypeAnnotations {
kind: ReflectionKind.templateLiteral,
types: (TypeString | TypeAny | TypeNumber | TypeLiteral | TypeInfer)[]
parent?: Type;
}
interface TypeRegexp extends TypeAnnotations {
kind: ReflectionKind.regexp;
parent?: Type;
}
interface TypeBaseMember extends TypeAnnotations {
visibility: ReflectionVisibility,
abstract?: true;
static?: true;
optional?: true,
readonly?: true;
}
interface TypeParameter extends TypeAnnotations {
kind: ReflectionKind.parameter,
name: string;
type: Type;
parent: TypeFunction | TypeMethod | TypeMethodSignature | TypeCallSignature;
//parameter could be a property as well if visibility is set
visibility?: ReflectionVisibility,
readonly?: true;
optional?: true,
description?: string;
/**
* Set when the parameter has a default value aka initializer.
*/
default?: () => any
}
interface TypeMethod extends TypeBaseMember {
kind: ReflectionKind.method,
parent: TypeClass;
name: number | string | symbol;
description?: string;
parameters: TypeParameter[];
return: Type;
}
interface TypeProperty extends TypeBaseMember {
kind: ReflectionKind.property,
parent: TypeClass;
visibility: ReflectionVisibility,
name: number | string | symbol;
description?: string;
type: Type;
/**
* Set when the property has a default value aka initializer.
*/
default?: () => any
}
interface TypeFunction extends TypeAnnotations {
kind: ReflectionKind.function,
parent?: Type;
name?: number | string | symbol,
description?: string;
function?: Function; //reference to the real function if available
parameters: TypeParameter[];
return: Type;
}
interface TypeCallSignature extends TypeAnnotations {
kind: ReflectionKind.callSignature,
parent?: Type;
parameters: TypeParameter[];
return: Type;
}
interface TypePromise extends TypeAnnotations {
kind: ReflectionKind.promise,
parent?: Type;
type: Type;
}
interface TypeClass extends TypeAnnotations {
kind: ReflectionKind.class,
parent?: Type;
classType: ClassType;
description?: string;
/**
* When the class extends another class and uses on it generic type arguments, then those arguments
* are in this array.
* For example `class A extends B<string, boolean> {}` then extendsArguments = [string, boolean].
* The reference to `B` is not part of TypeClass since this information is available in JavaScript runtime
* by using `Object.getPrototypeOf(type.classType)`.
*/
extendsArguments?: Type[];
/**
* When the class implements another interface/type, then those types are in this array.
*
* For example `class A implements B<string, boolean> {}` then implements = [B<string, boolean>].
*/
implements?: Type[];
/**
* When class has generic type arguments, e.g. MyClass<string>, it contains
* all type arguments. If no type arguments are given, it's undefined.
*/
arguments?: Type[];
/**
* properties/methods.
*/
types: (TypeIndexSignature | TypeProperty | TypeMethod)[];
}
interface TypeEnum extends TypeAnnotations {
kind: ReflectionKind.enum,
parent?: Type;
enum: { [name: string]: string | number | undefined | null };
values: (string | number | undefined | null)[];
indexType: Type;
description?: string;
}
interface TypeEnumMember extends TypeAnnotations {
kind: ReflectionKind.enumMember,
parent: TypeEnum;
name: string;
default?: () => string | number;
}
interface TypeTypeParameter extends TypeAnnotations {
kind: ReflectionKind.typeParameter,
parent?: Type;
name: string,
}
interface TypeUnion extends TypeAnnotations {
kind: ReflectionKind.union,
parent?: Type;
types: Type[];
}
interface TypeIntersection extends TypeAnnotations {
kind: ReflectionKind.intersection,
parent?: Type;
types: Type[];
}
interface TypeArray extends TypeAnnotations {
kind: ReflectionKind.array,
parent?: Type;
type: Type;
}
interface TypePropertySignature extends TypeAnnotations {
kind: ReflectionKind.propertySignature,
parent: TypeObjectLiteral;
name: number | string | symbol;
optional?: true;
readonly?: true;
description?: string;
type: Type;
}
interface TypeMethodSignature extends TypeAnnotations {
kind: ReflectionKind.methodSignature,
parent: TypeObjectLiteral;
name: number | string | symbol;
optional?: true;
description?: string;
parameters: TypeParameter[];
return: Type;
}
interface TypeObjectLiteral extends TypeAnnotations {
kind: ReflectionKind.objectLiteral,
parent?: Type;
description?: string;
types: (TypeIndexSignature | TypePropertySignature | TypeMethodSignature | TypeCallSignature)[];
/**
* When the interface extends another interface/type, then those types are in this array.
*
* For example `interface A extends B<string, boolean> {}` then implements = [B<string, boolean>].
*/
implements?: Type[];
}
interface TypeIndexSignature extends TypeAnnotations {
kind: ReflectionKind.indexSignature,
parent: TypeClass | TypeObjectLiteral;
index: Type;
type: Type;
}
interface TypeInfer extends TypeAnnotations {
kind: ReflectionKind.infer,
parent?: Type;
set(type: Type): void;
}
interface TypeTupleMember extends TypeAnnotations {
kind: ReflectionKind.tupleMember,
parent: TypeTuple;
type: Type;
optional?: true;
name?: string;
}
interface TypeTuple extends TypeAnnotations {
kind: ReflectionKind.tuple,
parent?: Type;
types: TypeTupleMember[]
}
interface TypeRest extends TypeAnnotations {
kind: ReflectionKind.rest,
parent: TypeTypeParameter | TypeTupleMember;
type: Type
}
type Type =
TypeNever
| TypeAny
| TypeUnknown
| TypeVoid
| TypeObject
| TypeString
| TypeNumber
| TypeBoolean
| TypeBigInt
| TypeSymbol
| TypeNull
| TypeUndefined
| TypeLiteral
| TypeTemplateLiteral
| TypeParameter
| TypeFunction
| TypeMethod
| TypeProperty
| TypePromise
| TypeClass
| TypeEnum
| TypeEnumMember
| TypeUnion
| TypeIntersection
| TypeArray
| TypeObjectLiteral
| TypeIndexSignature
| TypePropertySignature
| TypeMethodSignature
| TypeTypeParameter
| TypeInfer
| TypeTuple
| TypeTupleMember
| TypeRest
| TypeRegexp
| TypeCallSignature
;
type Widen<T> =
T extends string ? string
: T extends number ? number
: T extends bigint ? bigint
: T extends boolean ? boolean
: T extends symbol ? symbol : T;
type FindType<T extends Type, LOOKUP extends ReflectionKind> = T extends {
kind: infer K
} ? K extends LOOKUP ? T : never : never;
type InlineRuntimeType<T extends ReceiveType<unknown> | undefined | ReflectionClass<any> | Type | number | string | boolean | bigint, R = any> = T extends ReflectionClass<infer K>
? K : T extends ReceiveType<unknown>
? R : T extends Type ? R
: T extends undefined
? never : T;
const stringType = {kind: ReflectionKind.string};
type t = {a: InlineRuntimeType<typeof stringType>}
const value = 34;
type t = {a: InlineRuntimeType<typeof value>}
type WithAnnotations =
TypeAny
| TypeUnknown
| TypeString
| TypeNumber
| TypeBigInt
| TypeBoolean
| TypeArray
| TypeTuple
| TypeLiteral
| TypeNull
| TypeUndefined
| TypeClass
| TypeObjectLiteral
| TypeObject
| TypeTemplateLiteral
| TypeRegexp
| TypeSymbol;
type ParentLessType = RemoveDeepParent<Type>;
type integer = number;
type int8 = number;
type uint8 = number;
type int16 = number;
type uint16 = number;
type int32 = number;
type uint32 = number;
type float = number;
type float32 = number;
type float64 = number;
type AnnotationType<T extends AnnotationDefinition<any>> = T extends AnnotationDefinition<infer K> ? K : never;
type ReferenceActions = 'RESTRICT' | 'NO ACTION' | 'CASCADE' | 'SET NULL' | 'SET DEFAULT';
interface ReferenceOptions {
/**
* Default is CASCADE.
*/
onDelete?: ReferenceActions,
/**
* Default is CASCADE.
*/
onUpdate?: ReferenceActions
}
interface EntityOptions {
name?: string;
description?: string;
collection?: string;
database?: string;
singleTableInheritance?: boolean;
indexes?: { names: string[], options: IndexOptions }[];
}
type Entity<T extends EntityOptions> = {} & TypeAnnotation<'entity', T>
interface User extends Entity<{name: 'user'}> {
id: number & PrimaryKey & AutoIncrement;
username: string & Unique;
}
type PrimaryKey = TypeAnnotation<'primaryKey'>;
class Entity {
id: number & Primary = 0;
}
type PrimaryKeyFields<T> = any extends T ? any : { [P in keyof T]: Required<T[P]> extends Required<PrimaryKey> ? T[P] : never };
type PrimaryKeyType<T> = any extends T ? any : TypeKeyOf<PrimaryKeyFields<T>>;
type ReferenceFields<T> = { [P in keyof T]: Required<T[P]> extends Required<Reference> | Required<BackReference> ? T[P] : never };
type AutoIncrement = TypeAnnotation<'autoIncrement'>;
class Entity {
id: number & Primary & AutoIncrement = 0;
}
type UUID = string & TypeAnnotation<'UUIDv4'>;
uuid()
as handy initializer.class Entity {
id: UUID = uuid();
}
type MongoId = string & TypeAnnotation<'mongoId'>;
type BinaryBigInt = bigint & TypeAnnotation<'binaryBigInt'>;
bigint
but serializes to unsigned binary with unlimited size (instead of 8 bytes in most databases).
Negative values will be converted to positive (abs(x)).class Entity {
id: BinaryBigInt = 0n;
}
type SignedBinaryBigInt = bigint & TypeAnnotation<'signedBinaryBigInt'>;
bigint
but serializes to signed binary with unlimited size (instead of 8 bytes in most databases).
The binary has an additional leading sign byte and is represented as an uint: 255 for negative, 0 for zero, or 1 for positive.class Entity {
id: SignedBinaryBigInt = 0n;
}
interface BackReferenceOptions {
/**
* Necessary for normalised many-to-many relations. This defines the class of the pivot table/collection.
*/
via?: ClassType | {};
/**
* A reference/backReference can define which reference on the other side
* reference back. This is necessary when there are multiple outgoing references
* to the same entity.
*/
mappedBy?: string,
}
type Reference<Options extends ReferenceOptions = {}> = TypeAnnotation<'reference', Options>;
type BackReference<Options extends BackReferenceOptions = {}> = TypeAnnotation<'backReference', Options>;
type EmbeddedMeta<Options> = TypeAnnotation<'embedded', Options>;
type Embedded<T, Options extends { prefix?: string } = {}> = T & EmbeddedMeta<Options>;
type MapName<Alias extends string, ForSerializer extends string = ''> = TypeAnnotation<'mapName', [Alias, ForSerializer]>;
interface BackReferenceOptionsResolved {
/**
* Necessary for normalised many-to-many relations. This defines the class of the pivot table/collection.
*/
via?: TypeClass | TypeObjectLiteral;
/**
* A reference/backReference can define which reference on the other side
* reference back. This is necessary when there are multiple outgoing references
* to the same entity.
*/
mappedBy?: string,
}
interface EmbeddedOptions {
prefix?: string;
}
/**
* Assigns one or multiple groups to a type.
*
* @example
* ```typescript
* interface User {
* username: string;
* password: string & Group<'credentials'>;
* }
* ```
*/
export type Group<Name extends string> = TypeAnnotation<'group', Name>;
type Excluded<Name extends string = '*'> = TypeAnnotation<'excluded', Name>;
type Data<Name extends string, Value> = TypeAnnotation<'data', [Name, Value]>;
type ResetAnnotation<Name extends string> = TypeAnnotation<'reset', Name>;
type Password = string & MinLength<6> & Excluded;
interface UserCreationPayload {
password: Password & ResetAnnotation<'excluded'>
}
type IndexOptions = {
name?: string;
//index size. Necessary for blob/longtext, etc.
size?: number,
unique?: boolean,
spatial?: boolean,
sparse?: boolean,
//only in mongodb
fulltext?: boolean,
where?: string,
expireAfterSeconds?: number,
};
type Unique<Options extends IndexOptions = {}> = TypeAnnotation<'index', Options & { unique: true }>;
type Index<Options extends IndexOptions = {}> = TypeAnnotation<'index', Options>;
interface DatabaseFieldOptions {
/**
* The name of the column in the database.
* e.g. `userName: string & DatabaseField<{name: 'user_name'}>`
*
* Can alternatively also be configured by using a different NamingStrategy.
*/
name?: string;
/**
*
* e.g. `field: string & MySQL<{type: 'VARCHAR(255)'}>`
*/
type?: string;
/**
* If the property is on a class, its initializer/default value is per default used.
* This can be overridden using this option.
* e.g. `field: string & MySQL<{default: 'abc'}>`
*/
default?: any;
/**
* e.g. `field: string & MySQL<{defaultExpr: 'NOW()'}>`
*/
defaultExpr?: any;
/**
* If true no default column value is inferred from the property initializer/default value.
* e.g. `field: string & MySQL<{noDefault: true}> = ''`
*/
noDefault?: true;
/**
* Skip this property in all queries and database migration files.
*/
skip?: true;
/**
* Skip this property in database migration files. This excludes the property from the database, but
* keeps it in the queries.
*/
skipMigration?: true;
}
interface MySQLOptions extends DatabaseFieldOptions {
}
interface PostgresOptions extends DatabaseFieldOptions {
}
interface SqliteOptions extends DatabaseFieldOptions {
}
type MySQL<Options extends MySQLOptions> = Database<'mysql', Options>;
type Postgres<Options extends PostgresOptions> = Database<'postgres', Options>;
type SQLite<Options extends SqliteOptions> = Database<'sqlite', Options>;
type DatabaseField<Options extends DatabaseFieldOptions, Name extends string = '*'> = Database<Name, Options>;
type RuntimeStackEntry = Type | Object | (() => ClassType | Object) | string | number | boolean | bigint;
type Packed<T = any> = (RuntimeStackEntry | string)[] & { __is?: (data: any) => boolean } & { __type?: Type } & { __unpack?: PackStruct };
interface ReflectOptions {
/**
*
*/
reuseCached?: boolean;
inline?: boolean;
typeName?: string;
}
type ReceiveType<T> = Packed<T> | ClassType<T> | Type;
function f<T>(type?: ReceiveType<T>): Type {
return resolveReceiveType(type);
}
interface SerializerFn {
(value: any, property: ReflectionProperty): any;
}