UNPKG

@v4fire/client

Version:

V4Fire client core library

349 lines (303 loc) • 7.95 kB
/*! * 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; }