Skip to content

Commit

Permalink
rename plugin.wrapper to plugin.fnWrap
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolodavis committed Jan 4, 2019
1 parent ca5da32 commit d2d44f9
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 34 deletions.
12 changes: 7 additions & 5 deletions docs/plugins.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
# Plugins

The Plugin API allows you to create custom interfaces in
`G`. These can be small helpers or entire game systems that
target a genre of games.
The Plugin API allows you to provide off-the-shelf objects
that add custom functionality to [boardgame.io](https://boardgame.io/).
You can create wrappers around moves, provide custom interfaces
in `G` and much more.

#### Creating a Plugin

A plugin is an object that contains the following fields:
A plugin is an object that contains the following fields.

```js
{
// Optional.
// Function that accepts a move / trigger function
// and returns another function that wraps it. This
// wrapper can modify G before passing it down to
// the wrapped function. It is a good practice to
// undo the change at the end of the call.
wrapper: (fn) => (G, ctx, ...args) => {
fnWrap: (fn) => (G, ctx, ...args) => {
G = preprocess(G);
G = fn(G, ctx, ...args);
G = postprocess(G);
Expand Down
2 changes: 1 addition & 1 deletion src/core/flow.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
UpdateTurnOrderState,
TurnOrder,
} from './turn-order';
import { ApplyPlugins } from './plugins/apply';
import { ApplyPlugins } from './plugins/main';
import { automaticGameEvent } from './action-creators';
import { ContextEnhancer } from './reducer';
import * as logging from './logger';
Expand Down
6 changes: 3 additions & 3 deletions src/core/game.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* https://opensource.org/licenses/MIT.
*/

import { ApplyPlugins } from './plugins/apply';
import { ApplyPlugins } from './plugins/main';
import { FlowWithPhases } from './flow';

/**
Expand Down Expand Up @@ -75,10 +75,10 @@ import { FlowWithPhases } from './flow';
*
* @param {Array} plugins - List of plugins. Each plugin is an object like the following:
* {
* // Wraps a move / trigger function and returns
* // Optional: Wraps a move / trigger function and returns
* // the wrapped function. The wrapper can do anything
* // it wants, but will typically be used to customize G.
* wrapper: (fn) => {
* fnWrap: (fn) => {
* return (G, ctx, ...args) => {
* G = preprocess(G);
* G = fn(G, ctx, ...args);
Expand Down
22 changes: 1 addition & 21 deletions src/core/game.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import Game from './game';
import { CreateGameReducer } from './reducer';
import { makeMove, gameEvent } from './action-creators';
import { gameEvent } from './action-creators';

const game = Game({
moves: {
Expand All @@ -22,26 +22,6 @@ test('basic', () => {
expect(typeof game.processMove).toEqual('function');
});

describe('plugins', () => {
let game;
beforeAll(() => {
game = Game({
moves: {
A: G => G,
},

plugins: [{ wrapper: () => () => ({ plugin: true }) }],
});
});

test('plugin is invoked', () => {
const reducer = CreateGameReducer({ game });
let state = reducer(undefined, { type: 'init' });
state = reducer(state, makeMove('A'));
expect(state.G).toEqual({ plugin: true });
});
});

test('processMove', () => {
const testObj = { test: true };
expect(game.processMove(testObj, { type: 'A' })).toEqual(testObj);
Expand Down
6 changes: 4 additions & 2 deletions src/core/plugins/apply.js → src/core/plugins/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import PluginImmer from './plugin-immer';
* @param {Array} plugins - Array of plugins.
*/
export const ApplyPlugins = (fn, plugins) => {
const reducer = (acc, { wrapper }) => wrapper(acc);
return [PluginImmer, ...plugins].reduce(reducer, fn);
const reducer = (acc, { fnWrap }) => fnWrap(acc);
return [PluginImmer, ...plugins]
.filter(plugin => plugin.fnWrap !== undefined)
.reduce(reducer, fn);
};
31 changes: 31 additions & 0 deletions src/core/plugins/main.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2019 The boardgame.io Authors
*
* Use of this source code is governed by a MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/

import Game from '../game';
import { CreateGameReducer } from '../reducer';
import { makeMove } from '../action-creators';

describe('plugins', () => {
let game;
beforeAll(() => {
game = Game({
moves: {
A: G => G,
},

plugins: [{ fnWrap: () => () => ({ plugin: true }) }],
});
});

test('plugin is invoked', () => {
const reducer = CreateGameReducer({ game });
let state = reducer(undefined, { type: 'init' });
state = reducer(state, makeMove('A'));
expect(state.G).toEqual({ plugin: true });
});
});
2 changes: 1 addition & 1 deletion src/core/plugins/plugin-immer.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ import produce from 'immer';
* to G by just mutating it.
*/
export default {
wrapper: move => produce(move),
fnWrap: move => produce(move),
};
2 changes: 1 addition & 1 deletion src/core/plugins/plugin-player.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* @param {function} initPlayerState - Function of type (playerID) => playerState.
*/
export default initPlayerState => ({
wrapper: moveFn => {
fnWrap: moveFn => {
return (G, ctx, ...args) => {
const current = ctx.currentPlayer;
const player = G.players[current];
Expand Down

0 comments on commit d2d44f9

Please sign in to comment.