@@ -21,6 +21,7 @@ import type {
2121 ActionShape ,
2222 PlayerID ,
2323} from '../types' ;
24+ import { error } from '../core/logger' ;
2425
2526interface 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