Skip to content

Commit 1e435c2

Browse files
authored
feat(plugins): Consolidate flush and validate plugins (#970)
1 parent d559866 commit 1e435c2

3 files changed

Lines changed: 22 additions & 12 deletions

File tree

src/core/initialize.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@
77
*/
88

99
import { ProcessGameConfig } from './game';
10-
import type { Game } from '../types';
1110
import * as plugins from '../plugins/main';
12-
import type { PartialGameState, State, Ctx } from '../types';
11+
import type { Ctx, Game, PartialGameState, State } from '../types';
1312

1413
/**
1514
* Creates the initial game state.
@@ -61,7 +60,7 @@ export function InitializeGame({
6160
};
6261

6362
initial = game.flow.init(initial);
64-
initial = plugins.Flush(initial, { game });
63+
[initial] = plugins.FlushAndValidate(initial, { game });
6564

6665
// Initialize undo stack.
6766
if (!game.disableUndo) {

src/core/reducer.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,22 +130,19 @@ function initializeDeltalog(
130130

131131
/**
132132
* Update plugin state after move/event & check if plugins consider the action to be valid.
133-
* @param newState Latest version of state in the reducer.
134-
* @param oldState Initial value of state when reducer started its work.
133+
* @param state Current version of state in the reducer.
134+
* @param oldState State to revert to in case of error.
135135
* @param pluginOpts Plugin configuration options.
136136
* @returns Tuple of the new state updated after flushing plugins and the old
137137
* state augmented with an error if a plugin declared the action invalid.
138138
*/
139139
function flushAndValidatePlugins(
140-
newState: State,
140+
state: State,
141141
oldState: State,
142142
pluginOpts: { game: Game; isClient?: boolean }
143143
): [State, TransientState?] {
144-
newState = plugins.Flush(newState, pluginOpts);
145-
const isInvalid = plugins.IsInvalid(newState, pluginOpts);
144+
const [newState, isInvalid] = plugins.FlushAndValidate(state, pluginOpts);
146145
if (!isInvalid) return [newState];
147-
const { plugin, message } = isInvalid;
148-
error(`plugin declared action invalid: ${plugin} - ${message}`);
149146
return [
150147
newState,
151148
WithError(oldState, ActionErrorType.PluginActionInvalid, isInvalid),

src/plugins/main.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import type {
2121
ActionShape,
2222
PlayerID,
2323
} from '../types';
24+
import { error } from '../core/logger';
2425

2526
interface PluginOpts {
2627
game: Game;
@@ -166,7 +167,7 @@ export const Enhance = (
166167
/**
167168
* Allows plugins to update their state after a move / event.
168169
*/
169-
export const Flush = (state: State, opts: PluginOpts): State => {
170+
const Flush = (state: State, opts: PluginOpts): State => {
170171
// We flush the events plugin first, then custom plugins and the core plugins.
171172
// This means custom plugins cannot use the events API but will be available in event hooks.
172173
// Note that plugins are flushed in reverse, to allow custom plugins calling each other.
@@ -246,7 +247,7 @@ export const NoClient = (state: State, opts: PluginOpts): boolean => {
246247
* Allows plugins to indicate if the entire action should be thrown out
247248
* as invalid. This will cancel the entire state update.
248249
*/
249-
export const IsInvalid = (
250+
const IsInvalid = (
250251
state: State,
251252
opts: PluginOpts
252253
): false | { plugin: string; message: string } => {
@@ -270,6 +271,19 @@ export const IsInvalid = (
270271
return firstInvalidReturn || false;
271272
};
272273

274+
/**
275+
* Update plugin state after move/event & check if plugins consider the update to be valid.
276+
* @returns Tuple of `[updatedState]` or `[originalState, invalidError]`.
277+
*/
278+
export const FlushAndValidate = (state: State, opts: PluginOpts) => {
279+
const updatedState = Flush(state, opts);
280+
const isInvalid = IsInvalid(updatedState, opts);
281+
if (!isInvalid) return [updatedState] as const;
282+
const { plugin, message } = isInvalid;
283+
error(`${plugin} plugin declared action invalid:\n${message}`);
284+
return [state, isInvalid] as const;
285+
};
286+
273287
/**
274288
* Allows plugins to customize their data for specific players.
275289
* For example, a plugin may want to share no data with the client, or

0 commit comments

Comments
 (0)