Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
miDeb committed Jun 22, 2020
1 parent 33bef12 commit 9c0932e
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 80 deletions.
50 changes: 32 additions & 18 deletions lib/src/middleware.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,24 @@ class MiddlewareBuilder<

void add<Payload>(ActionName<Payload> aMgr,
MiddlewareHandler<State, StateBuilder, Actions, Payload> handler) {
_map[aMgr.name] = (api, next, action) {
_add(aMgr.name, handler);
}

void _add<Payload>(String name,
MiddlewareHandler<State, StateBuilder, Actions, Payload> handler) {
final oldMiddlware = _map[name];
_map[name] = (api, next, action) {
if (oldMiddlware != null) oldMiddlware(api, next, action);
handler(api, next, action as Action<Payload>);
};
}

/// [combine] combines this MiddlewareBuilder with another MiddlewareBuilder
/// for the same type
void combine(MiddlewareBuilder<State, StateBuilder, Actions> other) {
_map.addAll(other._map);
for (final entry in other._map.entries) {
_add<dynamic>(entry.key, entry.value);
}
}

@pragma('dart2js:noInline')
Expand All @@ -57,7 +66,9 @@ class MiddlewareBuilder<
NestedMiddlewareBuilder<State, StateBuilder, Actions, NestedState,
NestedStateBuilder, NestedActions>
other) {
_map.addAll(other._map);
for (final entry in other._map.entries) {
_add<dynamic>(entry.key, entry.value);
}
}

/// [build] returns a [Middleware] function that handles all actions added with [add]
Expand Down Expand Up @@ -93,12 +104,22 @@ class NestedMiddlewareBuilder<
ActionName<Payload> aMgr,
MiddlewareHandler<NestedState, NestedStateBuilder, NestedActions, Payload>
handler) {
_map[aMgr.name] = (api, next, action) {
_add(aMgr.name, handler);
}

void _add<Payload>(
String name,
MiddlewareHandler<NestedState, NestedStateBuilder, NestedActions, Payload>
handler) {
final oldMiddlware = _map[name];
_map[name] = (api, next, action) {
if (oldMiddlware != null) oldMiddlware(api, next, action);
handler(
MiddlewareApi._(
() => _stateMapper(api.state), () => _actionsMapper(api.actions)),
next,
action as Action<Payload>);
MiddlewareApi._(
() => _stateMapper(api.state), () => _actionsMapper(api.actions)),
next,
action as Action<Payload>,
);
};
}

Expand All @@ -107,16 +128,9 @@ class NestedMiddlewareBuilder<
/// this `NestedMiddlewareBuilder`.
void combineMiddlewareBuilder(
MiddlewareBuilder<NestedState, NestedStateBuilder, NestedActions> other) {
var adapted = other._map.map((name, handler) => MapEntry(
name,
(MiddlewareApi<State, StateBuilder, Actions> api, ActionHandler next,
Action action) =>
handler(
MiddlewareApi._(() => _stateMapper(api.state),
() => _actionsMapper(api.actions)),
next,
action)));
_map.addAll(adapted);
for (final entry in other._map.entries) {
_add<dynamic>(entry.key, entry.value);
}
}
}

Expand Down
144 changes: 97 additions & 47 deletions lib/src/reducer_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,57 +17,70 @@ class ReducerBuilder<State extends Built<State, StateBuilder>,
/// Registers [reducer] function to the given [actionName]
void add<Payload>(ActionName<Payload> actionName,
Reducer<State, StateBuilder, Payload> reducer) {
_map[actionName.name] = (state, action, builder) {
_add(actionName.name, reducer);
}

void _add<Payload>(
String name, Reducer<State, StateBuilder, Payload> reducer) {
final oldReducer = _map[name];
_map[name] = (state, action, builder) {
if (oldReducer != null) oldReducer(state, action, builder);
reducer(state, action as Action<Payload>, builder);
};
}

void _addAll(Map<String, Reducer<State, StateBuilder, dynamic>> map) {
for (final entry in map.entries) {
_add<dynamic>(entry.key, entry.value);
}
}

/// [combine] combines this ReducerBuilder with another ReducerBuilder
/// for the same type
void combine(ReducerBuilder<State, StateBuilder> other) {
_map.addAll(other._map);
_addAll(other._map);
}

/// [combineNested] combines this ReducerBuilder with a NestedReducerBuilder
@pragma('dart2js:noInline')
void combineNested<N extends Built<N, NB>, NB extends Builder<N, NB>>(
NestedReducerBuilder<State, StateBuilder, N, NB> nested) {
_map.addAll(nested._map);
_addAll(nested._map);
}

/// [combineAbstract] combines this ReducerBuilder with an AbstractReducerBuilder.
/// This function takes the result of AbstractReducerBuilder's .build() function,
/// which is a map. It does not take an AbstractReducerBuilder directly.
void combineAbstract(
Map<String, Reducer<State, StateBuilder, dynamic>> other) {
_map.addAll(other);
_addAll(other);
}

/// [combineList] combines this ReducerBuilder with a ListReducerBuilder
void combineList<T>(ListReducerBuilder<State, StateBuilder, T> other) {
_map.addAll(other._map);
_addAll(other._map);
}

/// [combineListMultimap] combines this ReducerBuilder with a ListMultimapReducerBuilder
void combineListMultimap<K, V>(
ListMultimapReducerBuilder<State, StateBuilder, K, V> other) {
_map.addAll(other._map);
_addAll(other._map);
}

/// [combineMap] combines this ReducerBuilder with a MapReducerBuilder
void combineMap<K, V>(MapReducerBuilder<State, StateBuilder, K, V> other) {
_map.addAll(other._map);
_addAll(other._map);
}

/// [combineSet] combines this ReducerBuilder with a SetReducerBuilder
void combineSet<T>(SetReducerBuilder<State, StateBuilder, T> other) {
_map.addAll(other._map);
_addAll(other._map);
}

/// [combineSetMultimap] combines this ReducerBuilder with a SetMultimapReducerBuilder
void combineSetMultimap<K, V>(
SetMultimapReducerBuilder<State, StateBuilder, K, V> other) {
_map.addAll(other._map);
_addAll(other._map);
}

/// [build] returns a reducer function that can be passed to a [Store].
Expand Down Expand Up @@ -128,25 +141,29 @@ class NestedReducerBuilder<
/// Registers [reducer] function to the given [actionName]
void add<Payload>(ActionName<Payload> actionName,
Reducer<NestedState, NestedStateBuilder, Payload> reducer) {
_map[actionName.name] = (state, action, builder) => reducer(
_stateMapper(state),
action as Action<Payload>,
_builderMapper(builder),
);
_add(actionName.name, reducer);
}

void _add<Payload>(
String name, Reducer<NestedState, NestedStateBuilder, Payload> reducer) {
final oldReducer = _map[name];
_map[name] = (state, action, builder) {
if (oldReducer != null) oldReducer(state, action, builder);
reducer(
_stateMapper(state),
action as Action<Payload>,
_builderMapper(builder),
);
};
}

/// [combineReducerBuilder] takes a `ReducerBuilder` with the type arguments
/// `NestedState`, `NestedStateBuilder`, and combines it with this `NestedReducerBuilder`.
void combineReducerBuilder(
ReducerBuilder<NestedState, NestedStateBuilder> other) {
final adapted = other._map.map((name, reducer) => MapEntry(
name,
(State state, Action<dynamic> action, StateBuilder builder) => reducer(
_stateMapper(state),
action,
_builderMapper(builder),
)));
_map.addAll(adapted);
for (final entry in other._map.entries) {
_add<dynamic>(entry.key, entry.value);
}
}
}

Expand All @@ -161,7 +178,9 @@ class AbstractReducerBuilder<AState, AStateBuilder> {
/// Registers [reducer] function to the given [actionName]
void add<Payload>(ActionName<Payload> actionName,
CReducer<AState, AStateBuilder, Payload> reducer) {
final oldReducer = _map[actionName.name];
_map[actionName.name] = (state, action, builder) {
if (oldReducer != null) oldReducer(state, action, builder);
reducer(state, action as Action<Payload>, builder);
};
}
Expand All @@ -188,11 +207,17 @@ class ListReducerBuilder<State extends Built<State, StateBuilder>,
/// Registers [reducer] function to the given [actionName]
void add<Payload>(ActionName<Payload> actionName,
CReducer<BuiltList<T>, ListBuilder<T>, Payload> reducer) {
_map[actionName.name] = (state, action, builder) => reducer(
_stateMapper(state),
action as Action<Payload>,
_builderMapper(builder),
);
final oldReducer = _map[actionName.name];
_map[actionName.name] = (state, action, builder) {
if (oldReducer != null) {
oldReducer(state, action, builder);
}
reducer(
_stateMapper(state),
action as Action<Payload>,
_builderMapper(builder),
);
};
}
}

Expand All @@ -211,11 +236,17 @@ class ListMultimapReducerBuilder<State extends Built<State, StateBuilder>,
ActionName<Payload> actionName,
CReducer<BuiltListMultimap<K, V>, ListMultimapBuilder<K, V>, Payload>
reducer) {
_map[actionName.name] = (state, action, builder) => reducer(
_stateMapper(state),
action as Action<Payload>,
_builderMapper(builder),
);
final oldReducer = _map[actionName.name];
_map[actionName.name] = (state, action, builder) {
if (oldReducer != null) {
oldReducer(state, action, builder);
}
reducer(
_stateMapper(state),
action as Action<Payload>,
_builderMapper(builder),
);
};
}
}

Expand All @@ -232,11 +263,18 @@ class MapReducerBuilder<State extends Built<State, StateBuilder>,
/// Registers [reducer] function to the given [actionName]
void add<Payload>(ActionName<Payload> actionName,
CReducer<BuiltMap<K, V>, MapBuilder<K, V>, Payload> reducer) {
_map[actionName.name] = (state, action, builder) => reducer(
_stateMapper(state),
action as Action<Payload>,
_builderMapper(builder),
);
final oldReducer = _map[actionName.name];

_map[actionName.name] = (state, action, builder) {
if (oldReducer != null) {
oldReducer(state, action, builder);
}
reducer(
_stateMapper(state),
action as Action<Payload>,
_builderMapper(builder),
);
};
}
}

Expand All @@ -253,11 +291,17 @@ class SetReducerBuilder<State extends Built<State, StateBuilder>,
/// Registers [reducer] function to the given [actionName]
void add<Payload>(ActionName<Payload> actionName,
CReducer<BuiltSet<T>, SetBuilder<T>, Payload> reducer) {
_map[actionName.name] = (state, action, builder) => reducer(
_stateMapper(state),
action as Action<Payload>,
_builderMapper(builder),
);
final oldReducer = _map[actionName.name];
_map[actionName.name] = (state, action, builder) {
if (oldReducer != null) {
oldReducer(state, action, builder);
}
reducer(
_stateMapper(state),
action as Action<Payload>,
_builderMapper(builder),
);
};
}
}

Expand All @@ -276,10 +320,16 @@ class SetMultimapReducerBuilder<State extends Built<State, StateBuilder>,
ActionName<Payload> actionName,
CReducer<BuiltSetMultimap<K, V>, SetMultimapBuilder<K, V>, Payload>
reducer) {
_map[actionName.name] = (state, action, builder) => reducer(
_stateMapper(state),
action as Action<Payload>,
_builderMapper(builder),
);
final oldReducer = _map[actionName.name];
_map[actionName.name] = (state, action, builder) {
if (oldReducer != null) {
oldReducer(state, action, builder);
}
reducer(
_stateMapper(state),
action as Action<Payload>,
_builderMapper(builder),
);
};
}
}
15 changes: 11 additions & 4 deletions test/unit/middleware_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ void main() {
test('1 middleware doubles count and updates state', () async {
setup();
expect(store.state.count, 1);
store.actions.middlewareActions.doubleIt(0);
store.actions.middlewareActions.doubleIt();
expect(store.state.count, 3);
});

Expand All @@ -52,7 +52,7 @@ void main() {
});

// should add double the current state twice
store.actions.middlewareActions.doubleIt(0);
store.actions.middlewareActions.doubleIt();
var stateChange = await onStateChangeCompleter.future;
expect(stateChange.prev.count, 1);
expect(stateChange.next.count, 3);
Expand All @@ -64,14 +64,21 @@ void main() {
test('combine works with tripleIt', () async {
setup();
expect(store.state.count, 1);
store.actions.middlewareActions.tripleIt(0);
store.actions.middlewareActions.tripleIt();
expect(store.state.count, 4);
});

test('adding multiple middleware for the same action works', () async {
setup();
expect(store.state.count, 1);
store.actions.middlewareActions.timesSix();
expect(store.state.count, 6);
});

test('combineNested works with SubCounter doubleIt', () async {
setup();
expect(store.state.subCounter.subCount, 1);
store.actions.subCounterActions.doubleIt(0);
store.actions.subCounterActions.doubleIt();
expect(store.state.subCounter.subCount, 3);
});
});
Expand Down
Loading

0 comments on commit 9c0932e

Please sign in to comment.