common
Tramvai tokens for integration and extension @tramvai/module-common
.
Action tokens
import { createToken } from '@tinkoff/dippy';
import type { Action } from '@tramvai/tokens-core';
import type { TramvaiAction, PageAction } from '@tramvai/types-actions-state-context';
import type { ExecutionContext } from './execution';
/**
* @description
* Registry for storing actions based on their type
*/
export const ACTION_REGISTRY_TOKEN = createToken<ActionsRegistry>('actionRegistry');
/**
* @description
* Instance that executes actions
*/
export const ACTION_EXECUTION_TOKEN = createToken<ActionExecution>('actionExecution');
/**
* @description
* Instance that executes actions on navigations
*/
export const ACTION_PAGE_RUNNER_TOKEN = createToken<ActionPageRunner>('actionPageRunner');
/**
* @description
* Conditions that specify should action be executing or not
*/
export const ACTION_CONDITIONALS = createToken<ActionCondition | ActionCondition[]>(
'actionConditionals',
{
multi: true,
}
);
/**
* @description
* Limit global and page actions execution time on server-side
*/
export const LIMIT_ACTION_GLOBAL_TIME_RUN = createToken<number>('limitActionGlobalTimeRun');
export interface ActionsRegistry {
add(type: string, actions: PageAction | PageAction[]): void;
get(type: string, addingActions?: PageAction[]): PageAction[];
getGlobal(): PageAction[] | undefined;
remove(type: string, actions?: PageAction[]): void;
}
export interface ActionPageRunner {
runActions(
actions: (Action | TramvaiAction<any, any, any>)[],
stopRunAtError?: (error: Error) => boolean
): Promise<any>;
}
export interface ActionExecution {
run<Params extends any[], Result, Deps>(
action: TramvaiAction<Params, Result, Deps>,
...params: Params
): Result extends Promise<any> ? Result : Promise<Result>;
run<Payload, Result, Deps>(
action: Action<Payload, Result, Deps>,
payload: Payload
): Result extends Promise<any> ? Result : Promise<Result>;
runInContext<Params extends any[], Result, Deps>(
context: ExecutionContext | null,
action: TramvaiAction<Params, Result, Deps>,
...params: Params
): Result extends Promise<any> ? Result : Promise<Result>;
runInContext<Payload, Result, Deps>(
context: ExecutionContext | null,
action: Action<Payload, Result, Deps>,
payload: Payload
): Result extends Promise<any> ? Result : Promise<Result>;
execution: Map<string, Record<string, any>>;
canExecute<Params extends any[], Result, Deps>(
action: TramvaiAction<Params, Result, Deps>
): boolean;
canExecute<Payload, Result, Deps>(action: Action<Payload, Result, Deps>): boolean;
}
export interface ActionConditionChecker<State = any> {
parameters: any;
conditions: Record<string, any>;
type: 'global' | 'local';
allow(): void;
setState(value: State): void;
getState(): State;
forbid(): void;
}
export type ActionCondition = {
key: string;
fn: (checker: ActionConditionChecker) => void;
};
export interface Deferred<Data = any> {
promise: Promise<Data>;
resolve: (data: Data) => void;
reject: (reason: Error) => void;
resolveData?: Data;
rejectReason?: Error;
isResolved: () => boolean;
isRejected: () => boolean;
reset: () => void;
}
export interface DeferredActionsMap {
get(key: string): Deferred | undefined;
set(key: string, value: Deferred): void;
has(key: string): boolean;
forEach(callback: (value: Deferred, key: string) => void): void;
}
export const DEFERRED_ACTIONS_MAP_TOKEN = createToken<DeferredActionsMap>(
'tramvai deferred actions map'
);
Bundle tokens
import { createToken } from '@tinkoff/dippy';
import type { Bundle } from '@tramvai/tokens-core';
/**
* @description
* Bundle Storage. When getting bundle additionally adds actions and components from bundle to according storages
*/
export const BUNDLE_MANAGER_TOKEN = createToken<BundleManager>('bundleManager');
/**
* @description
* Provides additional bundles to the app.
* Important! This token doesn't overrides already existing bundles.
*/
export const ADDITIONAL_BUNDLE_TOKEN = createToken<{ [key: string]: Bundle }>('additional bundle', {
multi: true,
});
export interface BundleManager {
bundles: Record<string, any>;
get(name: string, pageComponent: string): Promise<Bundle | undefined>;
has(name: string, pageComponent: string): boolean;
}
ComponentRegistry tokens
import { createToken } from '@tinkoff/dippy';
import type { TramvaiComponentDecl } from '@tramvai/react';
/**
* @description
* React components storage.
* Components in the repository are divided into groups, e.g. you can specify a bundle or a page component as a group key.
* The entity also allows you to get static component parameters through the `getComponentParam` method (will not work with `lazy` components)
*/
export const COMPONENT_REGISTRY_TOKEN = createToken<ComponentRegistry>('componentRegistry');
export interface ComponentRegistry {
components: Record<string, TramvaiComponentDecl>;
add(name: string, component: TramvaiComponentDecl, group?: string): void;
get(name: string, group?: string): TramvaiComponentDecl | undefined;
getComponentParam<T>(param: string, defaultValue: T, component: string, group?: string): T;
}
Env tokens
import { Scope, createToken } from '@tinkoff/dippy';
export interface EnvironmentManager {
get(name: string): string | undefined;
getInt(name: string, def: number): number;
getAll(): Record<string, string | undefined>;
update(result: Record<string, string>): void;
/**
* @deprecated use CLIENT_ENV_MANAGER_TOKEN
*/
clientUsed(): Record<string, string | undefined>;
/**
* @deprecated use CLIENT_ENV_MANAGER_TOKEN
*/
updateClientUsed(result: Record<string, string>): void;
}
export interface ClientEnvironmentRepository {
get(name: string): string | undefined;
set(name: string, value: string): void;
getAll(): Record<string, string | undefined>;
update(result: Record<string, string>): void;
}
/**
* @description
* Instance that used for managing environment variables
*/
export const ENV_MANAGER_TOKEN = createToken<EnvironmentManager>('environmentManager', {
scope: Scope.SINGLETON,
});
/**
* @description
* Instance that used for store and manage environment variables map, which are passed to the client.
* Use only server-side for client env values modification depending on the specific request conditions.
*/
export const CLIENT_ENV_REPOSITORY_TOKEN = createToken<ClientEnvironmentRepository>(
'clientEnvironmentManager',
{
scope: Scope.REQUEST,
}
);
/**
* @description
* List of envs that are used by the module or the app.
* All of the envs specified by that token will be accessible in the code through `environmentManager`
* ENV_USED_TOKEN format:
- `key` - id of the env. At that id the value of the env will be accessible through `environmentManager` and will be loaded from the external sources.
- `value` - default low-priority value for env `key`
- `optional` - is current env is optional. If `true` the app can work as usual event if the env value were not provided, if `false` - the app will fail to run without env value
- `validator` - validation function for passed env value. In case this function returns string it will be used as error message and validation will fail
- `dehydrate` - if `false` then env value will not be passed to client and this env can be used only on server
*
* @example
```tsx
interface EnvParameter {
key: string;
value?: string;
optional?: boolean;
validator?: (value: string) => boolean | string;
dehydrate?: boolean;
}
```
*/
export interface EnvParameter {
key: string;
value?: string;
optional?: boolean;
validator?: (value: string) => boolean | string;
dehydrate?: boolean;
}
export const ENV_USED_TOKEN = createToken<EnvParameter[]>('envUsed', { multi: true });
export type EnvTemplate = {
key: string;
fn: (...args: any[]) => string;
validator?: (key: string, value: string) => void;
};
export const ENV_TEMPLATE_TOKEN = createToken<EnvTemplate>('env template token', {
multi: true,
scope: Scope.SINGLETON,
});
Context tokens
import type { Container } from '@tinkoff/dippy';
import { createToken } from '@tinkoff/dippy';
import type { ConsumerContext as BaseConsumerContext } from '@tramvai/types-actions-state-context';
import type { PUBSUB_TOKEN } from './pubsub';
export { PlatformAction } from '@tramvai/types-actions-state-context';
/**
* @description
* Context implementation
*/
export const CONTEXT_TOKEN = createToken<ConsumerContext>('context');
export interface ConsumerContext extends BaseConsumerContext {
readonly di: Container;
readonly pubsub: typeof PUBSUB_TOKEN;
dehydrate: () => {
dispatcher: {
stores: Record<string, any>;
};
};
}
Hook tokens
import { createToken } from '@tinkoff/dippy';
/**
* @description
* [Hooks documentation](https://tramvai.dev/docs/references/libs/hooks)
*/
export const HOOK_TOKEN = createToken<Hooks>('hooks');
type Hook<TPayload> = (context: any, payload?: TPayload, options?: any) => TPayload;
export interface Hooks {
/**
* Register hooks
*/
registerHooks<TPayload>(name: string, list: Hook<TPayload>[] | Hook<TPayload>): void;
/**
* Run sync hook
*/
runHooks<TPayload>(
name: string,
context: any,
payload?: TPayload,
options?: any
): TPayload | undefined;
/**
* Run async hooksЗапуск ассихронных хуков
*/
runAsyncHooks<TPayload>(name: string, context: any, payload: TPayload, options?: any): TPayload;
/**
* Run promise hooks
*/
runPromiseHooks(
name: string,
context: any,
options?: any
): <TPayload>(payload: TPayload) => Promise<TPayload> | Promise<never>;
}
Logger tokens
import type { Logger, Reporter } from '@tinkoff/logger';
import { createToken } from '@tinkoff/dippy';
/**
* @description
* Logger implementation
*/
export const LOGGER_TOKEN = createToken<LoggerFactory>('logger');
/**
* @description
* Hook to be able to modify logger on initialization
*/
export const LOGGER_INIT_HOOK = createToken<LoggerInitHook>('loggerHook', { multi: true });
/**
* @description
* Remote reporter for client logs
*/
export const LOGGER_REMOTE_REPORTER = createToken<Reporter>('remoteReporter');
/**
* @description
* Storage for dynamic log object properties
*/
export const LOGGER_SHARED_CONTEXT = createToken<LoggerSharedContext>(
'tramvai logger shared context'
);
type Config = {
name: string;
[key: string]: any;
};
export type LoggerFactory = Logger & ((configOrName: string | Config) => Logger);
type LoggerInitHook = (logger: LoggerFactory) => void;
export type { Logger, LogFn, LogArg } from '@tinkoff/logger';
export interface LoggerSharedContext {
get(key: string): any;
set(key: string, value: any): void;
}
Pubsub tokens
import { createToken } from '@tinkoff/dippy';
/**
* @description
* Factory for creating pubsub instances
*/
export const PUBSUB_FACTORY_TOKEN = createToken<() => PubSub>('pubsubFactory');
/**
* @description
* Singleton pubsub instance
*/
export const PUBSUB_TOKEN = createToken<PubSub>('pubsub');
/**
* @description
* Request pubsub instance that is created for every client
*/
export const ROOT_PUBSUB_TOKEN = createToken<PubSub>('rootPubsub');
export interface PubSub {
subscribe(event: string, fn: (payload?: any) => void): () => boolean;
publish(event: string, ...args: unknown[]): any;
}
RequestManager tokens
import { createToken } from '@tinkoff/dippy';
import type { Url } from '@tinkoff/url';
/**
* @description
* Instance for managing client requests (request headers, query-parameters, cookies etc).
* Mostly used on server, but has partial functional for browser for simplification build isomorphic app
*/
export const REQUEST_MANAGER_TOKEN = createToken<RequestManager>('requestManager');
export interface RequestManager {
getBody(): unknown;
getUrl(): string;
getParsedUrl(): Url;
getMethod(): string;
getCookie(key: string): string;
getCookies(): Record<string, string>;
getHeader(key: string): string | string[] | undefined;
getHeaders(): Record<string, string | string[] | undefined>;
getClientIp(): string;
getHost(): string;
}
ResponseManager tokens
import { createToken } from '@tinkoff/dippy';
/**
* @description
* Instance for managing client response (response headers, cookies, response body).
* Mostly used on server, but has partial functional for browser for simplification build isomorphic app
*/
export const RESPONSE_MANAGER_TOKEN = createToken<ResponseManager>('responseManager');
export interface ResponseManager {
getBody(): unknown;
setBody(value: unknown): void;
getHeader(key: string): string | string[];
getHeaders(): Record<string, string | string[]>;
setHeader(key: string, value: string): void;
getCookie(key: string): string;
getCookies(): Record<string, string>;
setCookie(key: string, value: string): void;
getStatus(): number;
setStatus(status: number): void;
}
State tokens
import { Scope, createToken } from '@tinkoff/dippy';
import type {
DispatcherContext,
Event,
Middleware,
Reducer,
} from '@tramvai/types-actions-state-context';
/**
* @description
* dispatcher implementation
* Реализация dispatcher
*/
export const DISPATCHER_TOKEN = createToken('dispatcher');
/**
* @description
* dispatcher context implementation
*/
export const DISPATCHER_CONTEXT_TOKEN = createToken<DispatcherContext<any>>('dispatcherContext');
/**
* @description
* Token for adding stores that were created with createReducer
*/
export const COMBINE_REDUCERS = createToken('combineReducers', {
multi: true,
scope: Scope.SINGLETON,
});
/**
* @description
* Common app store
*/
export const STORE_TOKEN = createToken<Store>('store');
/**
* @description
* Custom middlewares for working with store state
*/
export const STORE_MIDDLEWARE = createToken<Middleware>('storeMiddleware', { multi: true });
/**
* @description
* Начальное состояние для клиента
*/
export const INITIAL_APP_STATE_TOKEN = createToken<{ stores: Record<string, any> }>(
'initialAppState'
);
export interface Store<State = Record<string, any>> {
dispatch<Payload>(event: Event<Payload>): Payload;
dispatch<Payload>(actionOrNameEvent: string | Event<Payload>, payload?: Payload): Payload;
subscribe(callback: (state: Record<string, any>) => void): () => void;
subscribe<S>(reducer: Reducer<S>, callback: (state: S) => void): () => void;
getState(): State;
getState<S>(reducer: Reducer<S>): S;
}
Execution tokens
import { createToken } from '@tinkoff/dippy';
export interface ExecutionContextValues {
[key: string]: any | undefined;
}
export interface ExecutionContext {
name: string;
abortSignal: AbortSignal;
values: ExecutionContextValues;
}
export interface ExecutionContextOptions {
name: string;
values?: ExecutionContextValues;
}
export interface ExecutionContextManager {
withContext<T>(
parentContext: ExecutionContext | null,
nameOrOptions: string | ExecutionContextOptions,
cb: (context: ExecutionContext, abortController: AbortController) => Promise<T>
): Promise<T>;
}
export const EXECUTION_CONTEXT_MANAGER_TOKEN = createToken<ExecutionContextManager>(
'common ExecutionContextManager'
);
export const ROOT_EXECUTION_CONTEXT_TOKEN = createToken<ExecutionContext | null>(
'common rootExecutionContext'
);
export const COMMAND_LINE_EXECUTION_CONTEXT_TOKEN = createToken<() => ExecutionContext | null>(
'common commandLineExecutionContext'
);