@v4fire/client
Version:
V4Fire client core library
349 lines (303 loc) • 7.95 kB
text/typescript
/*!
* V4Fire Client Core
* https://github.com/V4Fire/Client
*
* Released under the MIT license
* https://github.com/V4Fire/Client/blob/master/LICENSE
*/
import type {
Hook,
ComponentInterface,
WatchPath,
WatchOptions,
WatchHandlerParams,
MethodWatcher
} from 'core/component/interface';
export type Prop<T = unknown> =
{(): T} |
{new(...args: any[]): T & object} |
{new(...args: string[]): Function};
export type PropType<T = unknown> = CanArray<
Prop<T>
>;
export interface PropOptions<T = unknown> {
/**
* Constructor of a property type or a list of constructors
*
* @example
* ```typescript
* @component()
* class Foo extends iBlock {
* @prop({type: Number})
* bla!: number;
*
* @prop({type: [Number, String]})
* baz!: number | string;
* }
* ```
*/
type?: PropType<T>;
/**
* If false, then the property isn't required
* @default `true`
*
* @example
* ```typescript
* @component()
* class Foo extends iBlock {
* @prop({required: false})
* bla?: number;
*
* @prop()
* baz: number = 0;
* }
* ```
*/
required?: boolean;
/**
* Default value for the property
*
* @example
* ```typescript
* @component()
* class Foo extends iBlock {
* @prop({default: 1})
* bla!: number;
*
* @prop()
* baz: number = 0;
* }
* ```
*/
default?: T | null | undefined | (() => T | null | undefined);
/**
* If false, the property can't work within functional or flyweight components
* @default `true`
*/
functional?: boolean;
/**
* Property validator
*
* @param value
*
* @example
* ```typescript
* @component()
* class Foo extends iBlock {
* @prop({type: Number, validator: (v) => v > 0}})
* bla!: number;
* }
* ```
*/
validator?(value: T): boolean;
}
export interface InitFieldFn<CTX extends ComponentInterface = ComponentInterface> {
(ctx: CTX['unsafe'], data: Dictionary): unknown;
}
export interface MergeFieldFn<CTX extends ComponentInterface = ComponentInterface> {
(ctx: CTX['unsafe'], oldCtx: CTX, field: string, link?: string): unknown;
}
export interface UniqueFieldFn<CTX extends ComponentInterface = ComponentInterface> {
(ctx: CTX['unsafe'], oldCtx: CTX): unknown;
}
export interface DecoratorWatchHandler<CTX extends ComponentInterface = ComponentInterface, A = unknown, B = A> {
(ctx: CTX['unsafe'], a: A, b: B, params?: WatchHandlerParams): unknown;
(ctx: CTX['unsafe'], ...args: A[]): unknown;
}
export interface DecoratorFieldWatcherObject<
CTX extends ComponentInterface = ComponentInterface,
A = unknown,
B = A
> extends WatchOptions {
/**
* Handler (or a name of a component method) that is invoked on watcher events
*/
handler: string | DecoratorWatchHandler<CTX, A, B>;
/** @deprecated */
fn?: string | DecoratorWatchHandler<CTX, A, B>;
/**
* If false, then the handler that is invoked on watcher events does not take any arguments from an event
* @default `true`
*/
provideArgs?: boolean;
}
export type DecoratorFieldWatcher<CTX extends ComponentInterface = ComponentInterface, A = unknown, B = A> =
string |
DecoratorFieldWatcherObject<CTX, A, B> |
DecoratorWatchHandler<CTX, A, B> |
Array<string | DecoratorFieldWatcherObject<CTX, A, B> | DecoratorWatchHandler<CTX, A, B>>;
export interface DecoratorProp<
CTX extends ComponentInterface = ComponentInterface,
A = unknown,
B = A
> extends PropOptions {
/**
* If true, then the property always uses own default property when it is necessary
* @default `false`
*/
forceDefault?: boolean;
/**
* Watcher for changes of the property
*/
watch?: DecoratorFieldWatcher<CTX, A, B>;
/**
* Additional information about the property
*/
meta?: Dictionary;
}
export interface DecoratorSystem<
CTX extends ComponentInterface = ComponentInterface
> extends DecoratorFunctionalOptions {
/**
* If true, the property will be initialized before all non-atom properties
* @default `false`
*/
atom?: boolean;
/**
* Default value for the property
*/
default?: unknown;
/**
* If true, then the property is unique for a component.
* Also, the parameter can take a function that returns a boolean value.
* @default `false`
*/
unique?: boolean | UniqueFieldFn<CTX>;
/**
* If false, the property can't be watched within a functional component
* @default `true`
*/
functionalWatching?: boolean;
/**
* Name or list of names after which this property should be initialized
*/
after?: CanArray<string>;
/**
* Initializer (constructor) of a value.
* This property is useful for complex values.
*
* @example
* ```
* @component()
* class Foo extends iBlock {
* @field({init: () => Math.random()})
* bla!: number;
* }
* ```
*/
init?: InitFieldFn<CTX>;
/**
* If true, then if a component will restore own state from an old component
* (it occurs when you use a functional component), the actual value will be merged with the previous.
* Also, this parameter can take a function to merge.
*
* @default `false`
*/
merge?: MergeFieldFn<CTX> | boolean;
/**
* Additional information about the property
*/
meta?: Dictionary;
}
export interface DecoratorField<
CTX extends ComponentInterface = ComponentInterface,
A = unknown,
B = A
> extends DecoratorSystem<CTX> {
/**
* Watcher for changes of the property
*/
watch?: DecoratorFieldWatcher<CTX, A, B>;
/**
* If false, then changes of the property don't force direct re-render
* @default `true`
*/
forceUpdate?: boolean;
}
export interface DecoratorFunctionalOptions {
/**
* If false, the instance won't be borrowed from a parent when the owner component is a flyweight
* @default `true`
*/
replace?: boolean;
/**
* If false, the instance can't be used with functional components
* @default `true`
*/
functional?: boolean;
}
export interface DecoratorComponentAccessor extends DecoratorFunctionalOptions {
/**
* If true, a value of the accessor can be watched
*/
watchable?: boolean;
/**
* If true, a value of the accessor will be cached
*/
cache?: boolean;
/**
* List of dependencies for the accessor.
* The dependencies are needed to watch for changes of the accessor or to invalidate the cache.
*
* Also, when the accessor has a logically connected prop/field
* (by using a name convention "${property} -> ${property}Prop | ${property}Store"),
* we don't need to add additional dependencies.
*
* @example
* ```typescript
* @component()
* class Foo extends iBlock {
* @field()
* blaStore: number = 0;
*
* @computed({cache: true, dependencies: ['blaStore']})
* get bar(): number {
* return this.blaStore * 2;
* }
*
* @computed({cache: true})
* get bla(): number {
* return blaStore * 3;
* }
* }
* ```
*/
dependencies?: WatchPath[];
}
export type DecoratorHookOptions = {
[hook in Hook]?: DecoratorFunctionalOptions & {
/**
* Method name or list of method names after which the method should be invoked on a hook event
*/
after?: CanArray<string>;
}
};
export type DecoratorHook =
Hook |
Hook[] |
DecoratorHookOptions |
DecoratorHookOptions[];
export type DecoratorMethodWatcher<CTX extends ComponentInterface = ComponentInterface, A = unknown, B = A> =
string |
MethodWatcher<CTX, A, B> |
Array<string | MethodWatcher<CTX, A, B>>;
export interface DecoratorMethod<CTX extends ComponentInterface = ComponentInterface, A = unknown, B = A> {
/**
* Watcher for changes of some properties
*/
watch?: DecoratorMethodWatcher<CTX, A, B>;
/**
* Parameters for watcher
*/
watchParams?: MethodWatcher<CTX, A, B>;
/**
* Hook or a list of hooks after which the method should be invoked
*/
hook?: DecoratorHook;
}
export interface ParamsFactoryTransformer {
(params: object, cluster: string): Dictionary<any>;
}
export interface FactoryTransformer<T = object> {
(params?: T): Function;
}