Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | 1x 1x 1x 1x 1x 123x 123x 123x 123x 123x 123x 123x 123x 123x 123x 123x 110x 293x 293x 110x 123x 123x 75x 2x 2x 2x 2x 2x 73x 75x 123x 53x 1x 1x 1x 1x 1x 52x 53x 123x 360x 3x 3x 3x 3x 360x 47x 2x 2x 2x 2x 2x 45x 47x 1x 1x 1x 1x 1x 47x 360x 360x 328x 3x 328x 325x 325x 360x 26x 26x 354x 360x 123x 193x 78x 78x 78x 11x 11x 11x 11x 11x 11x 11x 11x 11x 11x 78x 193x 123x 130x 129x 129x 130x 130x 123x 47x 67x 67x 47x 123x 65x 65x 65x 64x 64x 65x 65x 4x 4x 65x 50x 50x 11x 65x 123x 6x 2x 2x 2x 2x 2x 4x 6x 123x 134x 134x 123x 69x 69x 123x 68x 68x 123x 137x 137x 123x 1x 94x 94x | import { Action, ACTION_MODE_SINGLE, ActionCreator, ActionMode, ActionModeMulti, ActionModeSingle } from './action';
import { FlowfulError } from './error';
import { ActionHandler } from './action-handler';
import { getGlobalMode, MODE, MODE_DEV } from './mode';
import { devMessages } from './dev';
export interface ActionMapBasic {
has(actionCreator: ActionCreator): boolean;
add(...actions: Action[]): void;
get<P, M extends ActionModeSingle, A extends Action<P, M>>(
actionCreator: ActionCreator<P, M, any[], A>
): A | undefined;
get<P, M extends ActionModeMulti, A extends Action<P, M>>(
actionCreator: ActionCreator<P, M, any[], A>
): A[] | undefined;
delete(actionCreator: ActionCreator): boolean;
readonly size: number;
}
export interface ActionMapExtended extends ActionMapBasic {
getActionCreators(): Iterable<ActionCreator>;
getActions(): Iterable<Action>;
}
export interface ActionMapInternal extends ActionMapExtended {
_attachHandler(handler: ActionHandler): void;
_detachHandler(): void;
_setIsHandlerExecuted(invoked: boolean): void;
}
export interface ActionMapOptions {
mode?: MODE;
}
export class ActionMap implements ActionMapInternal {
protected _map: Map<ActionCreator, Action[]>;
protected _attachedHandler?: ActionHandler;
protected _isHandlerExecuted?: boolean = false;
protected _options: Required<ActionMapOptions>;
protected _errorPrefix = '[Flowful][ActionMap]';
constructor(actions?: Action[], options?: ActionMapOptions) {
this._map = new Map<ActionCreator, Action[]>();
this._options = {
mode: options?.mode ?? getGlobalMode(),
};
if (actions) {
for (let i = 0, len = actions.length; i < len; i++) {
this._add(actions[i]);
}
}
}
getActionCreators() {
if (this._isHandlerExecuted) {
throw new FlowfulError(
`${this._errorPrefix} The handler is trying to obtain action creators from the action map. This is not allowed. Use the middleware.`,
{ handler: this._attachedHandler }
);
}
return this._map.keys();
}
getActions() {
if (this._isHandlerExecuted) {
throw new FlowfulError(
`${this._errorPrefix} The action handler is trying to obtain actions from the action map. This is not allowed. Use the middleware instead.`,
{ handler: this._attachedHandler }
);
}
return [...this._map.values()].flat();
}
protected _add(action: Action) {
if (!action.creator) {
throw new FlowfulError(`${this._errorPrefix} Invalid action - action creator is missing.`, {
action,
});
}
if (this._attachedHandler) {
// middlewares can do anything but handlers should not
if (this._map.has(action.creator) && this._isHandlerExecuted && action.mode === ACTION_MODE_SINGLE) {
throw new FlowfulError(
`${this._errorPrefix} Action "${action.type}" already exists in ActionMap. To dispatch the same action multiple times in a single cycle, use a action of type "multi" (e.g., actionCreatorMulti).`,
{ action: action, actionMap: this }
);
}
// the attached action handler is here because we want to know exactly where the error was raised
const handlerOutputSet = this._attachedHandler.getOutputSet();
if (!handlerOutputSet || !handlerOutputSet.has(action.creator)) {
throw new FlowfulError(
`${this._errorPrefix} The action handler (or action handler middleware) should not add actions that are not defined in the action handler outputs.`,
{ handler: this._attachedHandler, action: action }
);
}
}
const currentActions = this._map.get(action.creator) || [];
if (action.mode === ACTION_MODE_SINGLE) {
// overwrite the action if it is a single action
if (currentActions.length) {
currentActions[0] = action;
} else {
currentActions.push(action);
}
} else {
currentActions.push(action);
}
this._map.set(action.creator, currentActions);
}
protected _warnAboutHandlerAction(actionCreator: ActionCreator) {
if (this._attachedHandler && this._isHandlerExecuted) {
const handlerInputSet = this._attachedHandler.getInputSet();
const handlerOutputSet = this._attachedHandler.getOutputSet();
if (!handlerInputSet.has(actionCreator) && (!handlerOutputSet || !handlerOutputSet.has(actionCreator))) {
devMessages.warn(
`${this._errorPrefix} The action handler is trying to obtain action${
actionCreator.type ? ` "${actionCreator.type}"` : ''
} that is not defined in either the inputs or outputs.`,
{
handler: this._attachedHandler,
actionCreator,
}
);
}
}
}
has(actionCreator: ActionCreator) {
if (this._options.mode === MODE_DEV) {
this._warnAboutHandlerAction(actionCreator);
}
return this._map.has(actionCreator);
}
add(...actions: Action[]) {
for (let i = 0, len = actions.length; i < len; i++) {
this._add(actions[i]);
}
}
get<P, M extends ActionModeSingle, A extends Action<P, M>>(
actionCreator: ActionCreator<P, M, any[], A>
): A | undefined;
get<P, M extends ActionModeMulti, A extends Action<P, M>>(
actionCreator: ActionCreator<P, M, any[], A>
): A[] | undefined;
get<P, M extends ActionMode, A extends Action<P, M>>(
actionCreator: ActionCreator<P, M, any[], A>
): M extends ActionModeSingle ? A | undefined : A[] | undefined {
if (this._options.mode === MODE_DEV) {
this._warnAboutHandlerAction(actionCreator);
}
const result = this._map.get(actionCreator);
if (!result) {
return undefined;
}
if (actionCreator.mode === ACTION_MODE_SINGLE) {
return result[0] as A as M extends ActionModeSingle ? A | undefined : A[] | undefined;
}
return result as A[] as M extends ActionModeSingle ? A | undefined : A[] | undefined;
}
delete(actionCreator: ActionCreator) {
if (this._attachedHandler && this._isHandlerExecuted) {
throw new FlowfulError(
`${this._errorPrefix} Deleting actions from the action handler is not allowed. Use middleware or delete actions before dispatch.`,
{ actionCreator: actionCreator, actionMap: this }
);
}
return this._map.delete(actionCreator);
}
get size() {
return this._map.size;
}
_attachHandler(handler: ActionHandler) {
this._attachedHandler = handler;
}
_detachHandler() {
this._attachedHandler = undefined;
}
_setIsHandlerExecuted(triggered: boolean) {
this._isHandlerExecuted = triggered;
}
}
export function createActionMap(...actions: Action[]) {
return new ActionMap(actions);
}
|