# Configuration

### mapReduxToConfig

You need to provide a `mapReduxToConfig` function to Aquaman middleware to handle some special cases.

```typescript
function mapReduxToConfig(store: Store, dispatch: Dispatch<AnyAction>): AquamanConfig;
```

`mapReduxToConfig` has two parameters, your Redux store, and the store's dispatch function. This will allow it to access the current state of the application and dispatch new actions.

`mapReduxToConfig` needs to return an object that implements five methods:

1. onEndFlow
2. onStep
3. shouldStartFlow
4. onWillChooseFlow
5. functionMap

### onEndFlow

```typescript
function onEndFlow(flowId: string): Promise<void>;
```

`onEndFlow` gets triggered when a flow is completed or closed.&#x20;

You can make the function `async` so that you can wait on persistent storage updates before Aquaman starts checking for flows again.

Aquaman will ensure the same flow is not shown again during the same app lifecycle, but you'll likely want to persist that the user has seen this flow so that it doesn't get shown again in future sessions. You should use the flowId to persist that to prevent the flow from being shown again.

### onStep

```typescript
function onStep(): void;
```

`onStep` is called after each `aquamanNext` dispatch. It can be useful to close all modals/tooltips if they're open, so that logic does not need to be included in your action series.

### shouldStartFlow

```typescript
function shouldStartFlow(): boolean | void;
```

`shouldStartFlow` is useful to prevent flows from starting until some condition has been met, such as your application being fully loaded and rendered. Defaults to `true`.

### onWillChooseFlow

```typescript
function onWillChooseFlow(flow: FlowObj): FlowObj | false | void;
```

`onWillChooseFlow` provides you with an opportunity to override flows, probably with data from a separate service. This will be called once a condition for a flow is met. That selected flow object will be passed to the function, allowing you to use its id to find a corresponding action series to override it with.

### functionMap

```typescript
const functionMap: { [functionName: string]: Function };
```

Action series are meant to be fully serializable so that you can define them on separate services. Since functions are not serializable, you cannot pass them via a JSON object. `functionMap` allows you to use functions in your web application that will get called from a serialized action series.

### mutuallyExclusiveFlows

```typescript
const mutuallyExclusiveFlows: string[][] | undefined;
```

An array of arrays of flowIds. If a flow is shown during the lifecycle of an app, none of the other flows in the same "mutually exclusive" array will be shown.

In the example below, if a flow with `flowId5` is shown, then flows with `flowId6` can't be shown until the app restarts.

### Example

```typescript
export function mapConfigToRedux(
  store: Store,
  dispatch: Dispatch<AnyAction>
): AquamanConfig {
  async function onEndFlow(flowId: string): void {
    await webService.viewedFlow(flowId);
    dispatch(anyOtherCleanup());
  }
  
  function onStep(): void {
    const state = store.getState();
    
    const isTooltipOpen = isTooltipOpenSelector(state);
    
    if (isTooltipOpen) {
      dispatch(closeTooltip());
    }
  }
  
  function shouldStartFlow(): boolean {
    const state = store.getState();
    
    const isAppReady = isAppReadySelector(state);
    
    return isAppReady;
  }
  
  function onWillChooseFlow(flowObj: FlowObj): FlowObj | flase {
    const state = store.getState();
    
    const overridingActionSeriesMap: OverrideType = aquamanOverridesSelector(state);
    const overridingActionSeries = overridingActionSeriesMap[flow.flowId];
    const shouldUseActionSeriesOverride =
      overridingActionSeries && overridingActionSeries.length;

    if (shouldUseActionSeriesOverride) {
      return {
        actionSeries: overridingActionSeries,
        flowId: flow.flowId,
        persist: flow.persist,
      };
    }

    return false;
  }
  
  const functionMap = {
    track: analyticsTrackingFunction,
  }
  
  const mutuallyExclusiveFlows = [
    ['flow1', 'flow2', 'flow8'],
    ['flow2', 'flow7'],
    ['flow5', 'flow6']
  ];
  
  return {
    onEndFlow,
    onStep,
    shouldStartFlow,
    onWillChooseFlow,
    functionMap,
  }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://evernote.gitbook.io/aquaman/configuration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
