@mnbroatch/boardgame.io 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (296) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +102 -0
  3. package/ai/package.json +7 -0
  4. package/client/package.json +7 -0
  5. package/core/package.json +7 -0
  6. package/debug/package.json +7 -0
  7. package/dist/boardgameio.es.js +14238 -0
  8. package/dist/boardgameio.js +14277 -0
  9. package/dist/boardgameio.min.js +16 -0
  10. package/dist/cjs/Debug-9d141c06.js +9586 -0
  11. package/dist/cjs/ai-e0e8a768.js +377 -0
  12. package/dist/cjs/ai.js +20 -0
  13. package/dist/cjs/client-76dec77b.js +258 -0
  14. package/dist/cjs/client-a22d7500.js +524 -0
  15. package/dist/cjs/client.js +26 -0
  16. package/dist/cjs/core.js +52 -0
  17. package/dist/cjs/debug.js +18 -0
  18. package/dist/cjs/filter-player-view-bb02e2f6.js +89 -0
  19. package/dist/cjs/initialize-267fcd69.js +61 -0
  20. package/dist/cjs/internal.js +25 -0
  21. package/dist/cjs/master-2904879d.js +320 -0
  22. package/dist/cjs/master.js +18 -0
  23. package/dist/cjs/multiplayer.js +23 -0
  24. package/dist/cjs/plugin-random-7425844d.js +229 -0
  25. package/dist/cjs/plugins.js +59 -0
  26. package/dist/cjs/react-native.js +182 -0
  27. package/dist/cjs/react.js +727 -0
  28. package/dist/cjs/reducer-16eec232.js +1203 -0
  29. package/dist/cjs/server.js +4087 -0
  30. package/dist/cjs/socketio-7a0837eb.js +478 -0
  31. package/dist/cjs/testing.js +30 -0
  32. package/dist/cjs/transport-b1874dfa.js +37 -0
  33. package/dist/cjs/turn-order-b2ff8740.js +1136 -0
  34. package/dist/cjs/util-fcfd8fb8.js +140 -0
  35. package/dist/esm/Debug-0141fe2d.js +9577 -0
  36. package/dist/esm/ai-5c06e761.js +371 -0
  37. package/dist/esm/ai.js +8 -0
  38. package/dist/esm/client-2e653027.js +522 -0
  39. package/dist/esm/client-5f57c3f2.js +255 -0
  40. package/dist/esm/client.js +16 -0
  41. package/dist/esm/core.js +40 -0
  42. package/dist/esm/debug.js +10 -0
  43. package/dist/esm/filter-player-view-2c6cc96f.js +87 -0
  44. package/dist/esm/initialize-11d626ca.js +59 -0
  45. package/dist/esm/internal.js +10 -0
  46. package/dist/esm/master-fa8f2e43.js +318 -0
  47. package/dist/esm/master.js +10 -0
  48. package/dist/esm/multiplayer.js +14 -0
  49. package/dist/esm/plugin-random-087f861e.js +226 -0
  50. package/dist/esm/plugins.js +55 -0
  51. package/dist/esm/react-native.js +173 -0
  52. package/dist/esm/react.js +716 -0
  53. package/dist/esm/reducer-c46da7e5.js +1198 -0
  54. package/dist/esm/socketio-c22ffa65.js +455 -0
  55. package/dist/esm/testing.js +26 -0
  56. package/dist/esm/transport-ce07b771.js +35 -0
  57. package/dist/esm/turn-order-376d315e.js +1091 -0
  58. package/dist/esm/util-b6147cef.js +135 -0
  59. package/dist/types/packages/ai.d.ts +5 -0
  60. package/dist/types/packages/client.d.ts +3 -0
  61. package/dist/types/packages/core.d.ts +5 -0
  62. package/dist/types/packages/debug.d.ts +2 -0
  63. package/dist/types/packages/internal.d.ts +8 -0
  64. package/dist/types/packages/master.d.ts +2 -0
  65. package/dist/types/packages/multiplayer.d.ts +3 -0
  66. package/dist/types/packages/plugins.d.ts +3 -0
  67. package/dist/types/packages/react-native.d.ts +2 -0
  68. package/dist/types/packages/react.d.ts +3 -0
  69. package/dist/types/packages/server.d.ts +6 -0
  70. package/dist/types/packages/testing.d.ts +1 -0
  71. package/dist/types/src/ai/ai.d.ts +53 -0
  72. package/dist/types/src/ai/ai.test.d.ts +1 -0
  73. package/dist/types/src/ai/bot.d.ts +40 -0
  74. package/dist/types/src/ai/mcts-bot.d.ts +60 -0
  75. package/dist/types/src/ai/random-bot.d.ts +27 -0
  76. package/dist/types/src/client/client.d.ts +104 -0
  77. package/dist/types/src/client/client.test.d.ts +1 -0
  78. package/dist/types/src/client/debug/tests/debug.test.d.ts +1 -0
  79. package/dist/types/src/client/manager.d.ts +61 -0
  80. package/dist/types/src/client/react.d.ts +75 -0
  81. package/dist/types/src/client/react.ssr.test.d.ts +4 -0
  82. package/dist/types/src/client/react.test.d.ts +1 -0
  83. package/dist/types/src/client/transport/dummy.d.ts +18 -0
  84. package/dist/types/src/client/transport/local.d.ts +59 -0
  85. package/dist/types/src/client/transport/local.test.d.ts +1 -0
  86. package/dist/types/src/client/transport/socketio.d.ts +45 -0
  87. package/dist/types/src/client/transport/socketio.test.d.ts +1 -0
  88. package/dist/types/src/client/transport/transport.d.ts +50 -0
  89. package/dist/types/src/client/transport/transport.test.d.ts +1 -0
  90. package/dist/types/src/core/action-creators.d.ts +144 -0
  91. package/dist/types/src/core/action-types.d.ts +10 -0
  92. package/dist/types/src/core/backwards-compatibility.d.ts +12 -0
  93. package/dist/types/src/core/constants.d.ts +6 -0
  94. package/dist/types/src/core/errors.d.ts +15 -0
  95. package/dist/types/src/core/flow.d.ts +28 -0
  96. package/dist/types/src/core/flow.test.d.ts +1 -0
  97. package/dist/types/src/core/game-methods.d.ts +9 -0
  98. package/dist/types/src/core/game.d.ts +26 -0
  99. package/dist/types/src/core/game.test.d.ts +1 -0
  100. package/dist/types/src/core/initialize.d.ts +9 -0
  101. package/dist/types/src/core/logger.d.ts +2 -0
  102. package/dist/types/src/core/player-view.d.ts +7 -0
  103. package/dist/types/src/core/player-view.test.d.ts +1 -0
  104. package/dist/types/src/core/reducer.d.ts +155 -0
  105. package/dist/types/src/core/reducer.test.d.ts +1 -0
  106. package/dist/types/src/core/turn-order.d.ts +179 -0
  107. package/dist/types/src/core/turn-order.test.d.ts +8 -0
  108. package/dist/types/src/lobby/client.d.ts +194 -0
  109. package/dist/types/src/lobby/client.test.d.ts +1 -0
  110. package/dist/types/src/lobby/connection.d.ts +44 -0
  111. package/dist/types/src/lobby/connection.test.d.ts +1 -0
  112. package/dist/types/src/lobby/create-match-form.d.ts +26 -0
  113. package/dist/types/src/lobby/login-form.d.ts +23 -0
  114. package/dist/types/src/lobby/match-instance.d.ts +31 -0
  115. package/dist/types/src/lobby/react.d.ts +113 -0
  116. package/dist/types/src/lobby/react.ssr.test.d.ts +4 -0
  117. package/dist/types/src/lobby/react.test.d.ts +1 -0
  118. package/dist/types/src/master/filter-player-view.d.ts +96 -0
  119. package/dist/types/src/master/filter-player-view.test.d.ts +1 -0
  120. package/dist/types/src/master/master.d.ts +94 -0
  121. package/dist/types/src/master/master.test.d.ts +1 -0
  122. package/dist/types/src/plugins/events/events.d.ts +54 -0
  123. package/dist/types/src/plugins/events/events.test.d.ts +1 -0
  124. package/dist/types/src/plugins/main.d.ts +75 -0
  125. package/dist/types/src/plugins/main.test.d.ts +1 -0
  126. package/dist/types/src/plugins/plugin-events.d.ts +5 -0
  127. package/dist/types/src/plugins/plugin-immer.d.ts +7 -0
  128. package/dist/types/src/plugins/plugin-immer.test.d.ts +1 -0
  129. package/dist/types/src/plugins/plugin-log.d.ts +14 -0
  130. package/dist/types/src/plugins/plugin-log.test.d.ts +1 -0
  131. package/dist/types/src/plugins/plugin-player.d.ts +29 -0
  132. package/dist/types/src/plugins/plugin-player.test.d.ts +1 -0
  133. package/dist/types/src/plugins/plugin-random.d.ts +4 -0
  134. package/dist/types/src/plugins/plugin-serializable.d.ts +7 -0
  135. package/dist/types/src/plugins/plugin-serializable.test.d.ts +1 -0
  136. package/dist/types/src/plugins/random/random.alea.d.ts +19 -0
  137. package/dist/types/src/plugins/random/random.d.ts +54 -0
  138. package/dist/types/src/plugins/random/random.test.d.ts +1 -0
  139. package/dist/types/src/server/api.d.ts +13 -0
  140. package/dist/types/src/server/api.test.d.ts +1 -0
  141. package/dist/types/src/server/auth.d.ts +38 -0
  142. package/dist/types/src/server/auth.test.d.ts +1 -0
  143. package/dist/types/src/server/cors.d.ts +4 -0
  144. package/dist/types/src/server/cors.test.d.ts +1 -0
  145. package/dist/types/src/server/db/base.d.ts +192 -0
  146. package/dist/types/src/server/db/flatfile.d.ts +44 -0
  147. package/dist/types/src/server/db/flatfile.test.d.ts +1 -0
  148. package/dist/types/src/server/db/index.d.ts +4 -0
  149. package/dist/types/src/server/db/index.test.d.ts +1 -0
  150. package/dist/types/src/server/db/inmemory.d.ts +43 -0
  151. package/dist/types/src/server/db/inmemory.test.d.ts +1 -0
  152. package/dist/types/src/server/db/localstorage.d.ts +7 -0
  153. package/dist/types/src/server/db/localstorage.test.d.ts +1 -0
  154. package/dist/types/src/server/index.d.ts +68 -0
  155. package/dist/types/src/server/index.test.d.ts +1 -0
  156. package/dist/types/src/server/transport/pubsub/generic-pub-sub.d.ts +6 -0
  157. package/dist/types/src/server/transport/pubsub/in-memory-pub-sub.d.ts +7 -0
  158. package/dist/types/src/server/transport/pubsub/in-memory-pub-sub.test.d.ts +1 -0
  159. package/dist/types/src/server/transport/socketio-simultaneous.test.d.ts +1 -0
  160. package/dist/types/src/server/transport/socketio.d.ts +65 -0
  161. package/dist/types/src/server/transport/socketio.test.d.ts +1 -0
  162. package/dist/types/src/server/util.d.ts +35 -0
  163. package/dist/types/src/testing/mock-random.d.ts +15 -0
  164. package/dist/types/src/testing/mock-random.test.d.ts +1 -0
  165. package/dist/types/src/types.d.ts +387 -0
  166. package/internal/package.json +7 -0
  167. package/master/package.json +7 -0
  168. package/multiplayer/package.json +7 -0
  169. package/package.json +211 -0
  170. package/plugins/package.json +7 -0
  171. package/react/package.json +7 -0
  172. package/react-native/package.json +7 -0
  173. package/server/package.json +6 -0
  174. package/src/ai/ai.test.ts +433 -0
  175. package/src/ai/ai.ts +84 -0
  176. package/src/ai/bot.ts +122 -0
  177. package/src/ai/mcts-bot.ts +331 -0
  178. package/src/ai/random-bot.ts +20 -0
  179. package/src/client/client.test.ts +993 -0
  180. package/src/client/client.ts +588 -0
  181. package/src/client/debug/Debug.svelte +239 -0
  182. package/src/client/debug/Menu.svelte +65 -0
  183. package/src/client/debug/ai/AI.svelte +215 -0
  184. package/src/client/debug/ai/Options.svelte +48 -0
  185. package/src/client/debug/info/Info.svelte +22 -0
  186. package/src/client/debug/info/Item.svelte +24 -0
  187. package/src/client/debug/log/Log.svelte +157 -0
  188. package/src/client/debug/log/LogEvent.svelte +149 -0
  189. package/src/client/debug/log/LogMetadata.svelte +7 -0
  190. package/src/client/debug/log/PhaseMarker.svelte +27 -0
  191. package/src/client/debug/log/TurnMarker.svelte +23 -0
  192. package/src/client/debug/main/ClientSwitcher.svelte +59 -0
  193. package/src/client/debug/main/Controls.svelte +58 -0
  194. package/src/client/debug/main/Hotkey.svelte +84 -0
  195. package/src/client/debug/main/InteractiveFunction.svelte +85 -0
  196. package/src/client/debug/main/Main.svelte +121 -0
  197. package/src/client/debug/main/Move.svelte +68 -0
  198. package/src/client/debug/main/PlayerInfo.svelte +70 -0
  199. package/src/client/debug/mcts/Action.svelte +22 -0
  200. package/src/client/debug/mcts/MCTS.svelte +78 -0
  201. package/src/client/debug/mcts/Table.svelte +98 -0
  202. package/src/client/debug/tests/JSONTree.mock.svelte +3 -0
  203. package/src/client/debug/tests/debug.test.ts +183 -0
  204. package/src/client/debug/utils/shortcuts.js +50 -0
  205. package/src/client/debug/utils/shortcuts.test.js +49 -0
  206. package/src/client/manager.ts +177 -0
  207. package/src/client/react-native.js +136 -0
  208. package/src/client/react-native.test.js +229 -0
  209. package/src/client/react.ssr.test.tsx +24 -0
  210. package/src/client/react.test.tsx +213 -0
  211. package/src/client/react.tsx +192 -0
  212. package/src/client/transport/dummy.ts +19 -0
  213. package/src/client/transport/local.test.ts +353 -0
  214. package/src/client/transport/local.ts +230 -0
  215. package/src/client/transport/socketio.test.ts +328 -0
  216. package/src/client/transport/socketio.ts +210 -0
  217. package/src/client/transport/transport.test.ts +27 -0
  218. package/src/client/transport/transport.ts +95 -0
  219. package/src/core/action-creators.ts +159 -0
  220. package/src/core/action-types.ts +18 -0
  221. package/src/core/backwards-compatibility.ts +23 -0
  222. package/src/core/constants.ts +6 -0
  223. package/src/core/errors.ts +35 -0
  224. package/src/core/flow.test.ts +2433 -0
  225. package/src/core/flow.ts +897 -0
  226. package/src/core/game-methods.ts +9 -0
  227. package/src/core/game.test.ts +286 -0
  228. package/src/core/game.ts +114 -0
  229. package/src/core/initialize.ts +77 -0
  230. package/src/core/logger.test.js +90 -0
  231. package/src/core/logger.ts +18 -0
  232. package/src/core/player-view.test.ts +50 -0
  233. package/src/core/player-view.ts +39 -0
  234. package/src/core/reducer.test.ts +991 -0
  235. package/src/core/reducer.ts +532 -0
  236. package/src/core/turn-order.test.ts +1123 -0
  237. package/src/core/turn-order.ts +473 -0
  238. package/src/lobby/client.test.ts +385 -0
  239. package/src/lobby/client.ts +358 -0
  240. package/src/lobby/connection.test.ts +207 -0
  241. package/src/lobby/connection.ts +162 -0
  242. package/src/lobby/create-match-form.tsx +122 -0
  243. package/src/lobby/login-form.tsx +75 -0
  244. package/src/lobby/match-instance.tsx +135 -0
  245. package/src/lobby/react.ssr.test.tsx +22 -0
  246. package/src/lobby/react.test.tsx +594 -0
  247. package/src/lobby/react.tsx +402 -0
  248. package/src/master/filter-player-view.test.ts +381 -0
  249. package/src/master/filter-player-view.ts +102 -0
  250. package/src/master/master.test.ts +1068 -0
  251. package/src/master/master.ts +492 -0
  252. package/src/plugins/events/events.test.ts +108 -0
  253. package/src/plugins/events/events.ts +209 -0
  254. package/src/plugins/main.test.ts +411 -0
  255. package/src/plugins/main.ts +314 -0
  256. package/src/plugins/plugin-events.ts +40 -0
  257. package/src/plugins/plugin-immer.test.ts +86 -0
  258. package/src/plugins/plugin-immer.ts +37 -0
  259. package/src/plugins/plugin-log.test.ts +37 -0
  260. package/src/plugins/plugin-log.ts +40 -0
  261. package/src/plugins/plugin-player.test.ts +172 -0
  262. package/src/plugins/plugin-player.ts +100 -0
  263. package/src/plugins/plugin-random.ts +40 -0
  264. package/src/plugins/plugin-serializable.test.ts +40 -0
  265. package/src/plugins/plugin-serializable.ts +55 -0
  266. package/src/plugins/random/random.alea.ts +109 -0
  267. package/src/plugins/random/random.test.ts +167 -0
  268. package/src/plugins/random/random.ts +198 -0
  269. package/src/server/api.test.ts +1699 -0
  270. package/src/server/api.ts +527 -0
  271. package/src/server/auth.test.ts +275 -0
  272. package/src/server/auth.ts +89 -0
  273. package/src/server/cors.test.ts +121 -0
  274. package/src/server/cors.ts +7 -0
  275. package/src/server/db/base.ts +296 -0
  276. package/src/server/db/flatfile.test.ts +221 -0
  277. package/src/server/db/flatfile.ts +228 -0
  278. package/src/server/db/index.test.ts +8 -0
  279. package/src/server/db/index.ts +12 -0
  280. package/src/server/db/inmemory.test.ts +143 -0
  281. package/src/server/db/inmemory.ts +143 -0
  282. package/src/server/db/localstorage.test.ts +73 -0
  283. package/src/server/db/localstorage.ts +44 -0
  284. package/src/server/index.test.ts +265 -0
  285. package/src/server/index.ts +175 -0
  286. package/src/server/transport/pubsub/generic-pub-sub.ts +11 -0
  287. package/src/server/transport/pubsub/in-memory-pub-sub.test.ts +47 -0
  288. package/src/server/transport/pubsub/in-memory-pub-sub.ts +28 -0
  289. package/src/server/transport/socketio-simultaneous.test.ts +603 -0
  290. package/src/server/transport/socketio.test.ts +303 -0
  291. package/src/server/transport/socketio.ts +279 -0
  292. package/src/server/util.ts +85 -0
  293. package/src/testing/mock-random.test.ts +45 -0
  294. package/src/testing/mock-random.ts +27 -0
  295. package/src/types.ts +511 -0
  296. package/testing/package.json +7 -0
@@ -0,0 +1,296 @@
1
+ import type { Object } from 'ts-toolbelt';
2
+ import type { State, Server, LogEntry } from '../../types';
3
+
4
+ export enum Type {
5
+ SYNC = 0,
6
+ ASYNC = 1,
7
+ }
8
+
9
+ /**
10
+ * Type guard that checks if a storage implementation is synchronous.
11
+ */
12
+ export function isSynchronous(storageAPI: Sync | Async): storageAPI is Sync {
13
+ return storageAPI.type() === Type.SYNC;
14
+ }
15
+
16
+ /**
17
+ * Indicates which fields the fetch operation should return.
18
+ */
19
+ export interface FetchOpts {
20
+ state?: boolean;
21
+ log?: boolean;
22
+ metadata?: boolean;
23
+ initialState?: boolean;
24
+ }
25
+
26
+ /**
27
+ * Data that can be retrieved from a database fetch query
28
+ */
29
+ export interface FetchFields {
30
+ state: State;
31
+ log: LogEntry[];
32
+ metadata: Server.MatchData;
33
+ initialState: State;
34
+ }
35
+
36
+ /**
37
+ * The result of the fetch operation.
38
+ */
39
+ export type FetchResult<O extends FetchOpts> = Object.Pick<
40
+ FetchFields,
41
+ Object.SelectKeys<O, true>
42
+ >;
43
+
44
+ /**
45
+ * Options passed when listing matches.
46
+ */
47
+ export interface ListMatchesOpts {
48
+ gameName?: string;
49
+ where?: {
50
+ isGameover?: boolean;
51
+ updatedBefore?: number;
52
+ updatedAfter?: number;
53
+ };
54
+ }
55
+
56
+ /**
57
+ * @deprecated Use ListMatchesOpts instead
58
+ */
59
+ export interface ListGamesOpts {
60
+ gameName?: string;
61
+ where?: {
62
+ isGameover?: boolean;
63
+ updatedBefore?: number;
64
+ updatedAfter?: number;
65
+ };
66
+ }
67
+
68
+ /**
69
+ * Options passed when creating a new match.
70
+ */
71
+ export interface CreateMatchOpts {
72
+ initialState: State;
73
+ metadata: Server.MatchData;
74
+ }
75
+
76
+ /**
77
+ * @deprecated Use CreateMatchOpts instead
78
+ */
79
+ export interface CreateGameOpts {
80
+ initialState: State;
81
+ metadata: Server.MatchData;
82
+ }
83
+
84
+ export abstract class Async {
85
+ /* istanbul ignore next */
86
+ type() {
87
+ /* istanbul ignore next */
88
+ return Type.ASYNC;
89
+ }
90
+
91
+ /**
92
+ * Connect.
93
+ */
94
+ abstract connect();
95
+
96
+ /**
97
+ * Create a new match.
98
+ *
99
+ * This might just need to call setState and setMetadata in
100
+ * most implementations.
101
+ *
102
+ * However, it exists as a separate call so that the
103
+ * implementation can provision things differently when
104
+ * a match is created. For example, it might stow away the
105
+ * initial match state in a separate field for easier retrieval.
106
+ */
107
+ /* istanbul ignore next */
108
+ async createMatch(matchID: string, opts: CreateMatchOpts): Promise<void> {
109
+ if (this.createGame) {
110
+ console.warn(
111
+ 'The database connector does not implement a createMatch method.',
112
+ '\nUsing the deprecated createGame method instead.'
113
+ );
114
+ return this.createGame(matchID, opts);
115
+ } else {
116
+ console.error(
117
+ 'The database connector does not implement a createMatch method.'
118
+ );
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Create a new game.
124
+ *
125
+ * This might just need to call setState and setMetadata in
126
+ * most implementations.
127
+ *
128
+ * However, it exists as a separate call so that the
129
+ * implementation can provision things differently when
130
+ * a game is created. For example, it might stow away the
131
+ * initial game state in a separate field for easier retrieval.
132
+ *
133
+ * @deprecated Use createMatch instead, if implemented
134
+ */
135
+ async createGame?(matchID: string, opts: CreateGameOpts): Promise<void>;
136
+
137
+ /**
138
+ * Update the game state.
139
+ *
140
+ * If passed a deltalog array, setState should append its contents to the
141
+ * existing log for this game.
142
+ */
143
+ abstract setState(
144
+ matchID: string,
145
+ state: State,
146
+ deltalog?: LogEntry[]
147
+ ): Promise<void>;
148
+
149
+ /**
150
+ * Update the game metadata.
151
+ */
152
+ abstract setMetadata(
153
+ matchID: string,
154
+ metadata: Server.MatchData
155
+ ): Promise<void>;
156
+
157
+ /**
158
+ * Fetch the game state.
159
+ */
160
+ abstract fetch<O extends FetchOpts>(
161
+ matchID: string,
162
+ opts: O
163
+ ): Promise<FetchResult<O>>;
164
+
165
+ /**
166
+ * Remove the game state.
167
+ */
168
+ abstract wipe(matchID: string): Promise<void>;
169
+
170
+ /**
171
+ * Return all matches.
172
+ */
173
+ /* istanbul ignore next */
174
+ async listMatches(opts?: ListMatchesOpts): Promise<string[]> {
175
+ if (this.listGames) {
176
+ console.warn(
177
+ 'The database connector does not implement a listMatches method.',
178
+ '\nUsing the deprecated listGames method instead.'
179
+ );
180
+ return this.listGames(opts);
181
+ } else {
182
+ console.error(
183
+ 'The database connector does not implement a listMatches method.'
184
+ );
185
+ }
186
+ }
187
+
188
+ /**
189
+ * Return all games.
190
+ *
191
+ * @deprecated Use listMatches instead, if implemented
192
+ */
193
+ async listGames?(opts?: ListGamesOpts): Promise<string[]>;
194
+ }
195
+
196
+ export abstract class Sync {
197
+ type() {
198
+ return Type.SYNC;
199
+ }
200
+
201
+ /**
202
+ * Connect.
203
+ */
204
+ connect() {
205
+ return;
206
+ }
207
+
208
+ /**
209
+ * Create a new match.
210
+ *
211
+ * This might just need to call setState and setMetadata in
212
+ * most implementations.
213
+ *
214
+ * However, it exists as a separate call so that the
215
+ * implementation can provision things differently when
216
+ * a match is created. For example, it might stow away the
217
+ * initial match state in a separate field for easier retrieval.
218
+ */
219
+ /* istanbul ignore next */
220
+ createMatch(matchID: string, opts: CreateMatchOpts): void {
221
+ if (this.createGame) {
222
+ console.warn(
223
+ 'The database connector does not implement a createMatch method.',
224
+ '\nUsing the deprecated createGame method instead.'
225
+ );
226
+ return this.createGame(matchID, opts);
227
+ } else {
228
+ console.error(
229
+ 'The database connector does not implement a createMatch method.'
230
+ );
231
+ }
232
+ }
233
+
234
+ /**
235
+ * Create a new game.
236
+ *
237
+ * This might just need to call setState and setMetadata in
238
+ * most implementations.
239
+ *
240
+ * However, it exists as a separate call so that the
241
+ * implementation can provision things differently when
242
+ * a game is created. For example, it might stow away the
243
+ * initial game state in a separate field for easier retrieval.
244
+ *
245
+ * @deprecated Use createMatch instead, if implemented
246
+ */
247
+ createGame?(matchID: string, opts: CreateGameOpts): void;
248
+
249
+ /**
250
+ * Update the match state.
251
+ *
252
+ * If passed a deltalog array, setState should append its contents to the
253
+ * existing log for this match.
254
+ */
255
+ abstract setState(matchID: string, state: State, deltalog?: LogEntry[]): void;
256
+
257
+ /**
258
+ * Update the match metadata.
259
+ */
260
+ abstract setMetadata(matchID: string, metadata: Server.MatchData): void;
261
+
262
+ /**
263
+ * Fetch the match state.
264
+ */
265
+ abstract fetch<O extends FetchOpts>(matchID: string, opts: O): FetchResult<O>;
266
+
267
+ /**
268
+ * Remove the match state.
269
+ */
270
+ abstract wipe(matchID: string): void;
271
+
272
+ /**
273
+ * Return all matches.
274
+ */
275
+ /* istanbul ignore next */
276
+ listMatches(opts?: ListMatchesOpts): string[] {
277
+ if (this.listGames) {
278
+ console.warn(
279
+ 'The database connector does not implement a listMatches method.',
280
+ '\nUsing the deprecated listGames method instead.'
281
+ );
282
+ return this.listGames(opts);
283
+ } else {
284
+ console.error(
285
+ 'The database connector does not implement a listMatches method.'
286
+ );
287
+ }
288
+ }
289
+
290
+ /**
291
+ * Return all games.
292
+ *
293
+ * @deprecated Use listMatches instead, if implemented
294
+ */
295
+ listGames?(opts?: ListGamesOpts): string[];
296
+ }
@@ -0,0 +1,221 @@
1
+ /*
2
+ * Copyright 2017 The boardgame.io Authors
3
+ *
4
+ * Use of this source code is governed by a MIT-style
5
+ * license that can be found in the LICENSE file or at
6
+ * https://opensource.org/licenses/MIT.
7
+ */
8
+
9
+ import { FlatFile } from './flatfile';
10
+ import type { State, Server, LogEntry } from '../../types';
11
+
12
+ describe('FlatFile', () => {
13
+ let db: FlatFile;
14
+
15
+ beforeAll(async () => {
16
+ db = new FlatFile({ dir: './tmp', logging: false });
17
+ await db.connect();
18
+ });
19
+
20
+ afterEach(async () => {
21
+ await db.clear();
22
+ });
23
+
24
+ test('basic', async () => {
25
+ // Must return undefined when no game exists.
26
+ const result = await db.fetch('matchID', { state: true });
27
+ expect(result.state).toEqual(undefined);
28
+
29
+ // Create game.
30
+ const state: unknown = { a: 1 };
31
+ const metadata: unknown = { metadata: true };
32
+
33
+ await db.createMatch('matchID', {
34
+ initialState: state as State,
35
+ metadata: metadata as Server.MatchData,
36
+ });
37
+
38
+ // Must return created game.
39
+ {
40
+ const result = await db.fetch('matchID', {
41
+ state: true,
42
+ metadata: true,
43
+ initialState: true,
44
+ });
45
+ expect(result.state).toEqual({ a: 1 });
46
+ expect(result.initialState).toEqual(result.state);
47
+ expect(result.metadata).toEqual({ metadata: true });
48
+ }
49
+
50
+ // Must return all keys
51
+ const keys = await db.listMatches();
52
+ expect(keys).toEqual(['matchID']);
53
+
54
+ // Must remove match from DB
55
+ await db.wipe('matchID');
56
+ expect(
57
+ await db.fetch('matchID', { metadata: true, state: true, log: true })
58
+ ).toEqual({});
59
+
60
+ // Shall not return error
61
+ await db.wipe('matchID');
62
+
63
+ // Shall create match, then clear DB, then check whether DB is cleared
64
+ await db.setState('game2', state as State);
65
+ await db.clear();
66
+ const keys2 = await db.listMatches();
67
+ expect(keys2).toHaveLength(0);
68
+ });
69
+
70
+ test('log', async () => {
71
+ const logEntry1: LogEntry = {
72
+ _stateID: 0,
73
+ action: {
74
+ type: 'MAKE_MOVE',
75
+ payload: { type: '', playerID: '0', args: [] },
76
+ },
77
+ turn: 0,
78
+ phase: '',
79
+ };
80
+
81
+ const logEntry2: LogEntry = {
82
+ _stateID: 1,
83
+ action: {
84
+ type: 'MAKE_MOVE',
85
+ payload: { type: '', playerID: '0', args: [] },
86
+ },
87
+ turn: 1,
88
+ phase: '',
89
+ };
90
+
91
+ await db.setState('matchID', null, [logEntry1]);
92
+ await db.setState('matchID', null, [logEntry2]);
93
+
94
+ const result = await db.fetch('matchID', { log: true });
95
+ expect(result.log).toEqual([logEntry1, logEntry2]);
96
+ });
97
+
98
+ describe('listMatches', () => {
99
+ beforeEach(async () => {
100
+ const state: unknown = { a: 1 };
101
+
102
+ await db.createMatch('matchID', {
103
+ initialState: state as State,
104
+ metadata: {
105
+ gameName: 'game1',
106
+ updatedAt: new Date(2020, 3).getTime(),
107
+ } as Server.MatchData,
108
+ });
109
+
110
+ await db.createMatch('matchID2', {
111
+ initialState: state as State,
112
+ metadata: {
113
+ gameName: 'game1',
114
+ gameover: 'gameover',
115
+ updatedAt: new Date(2020, 5).getTime(),
116
+ } as Server.MatchData,
117
+ });
118
+
119
+ await db.createMatch('matchID3', {
120
+ initialState: state as State,
121
+ metadata: {
122
+ gameName: 'game2',
123
+ updatedAt: new Date(2020, 4).getTime(),
124
+ } as Server.MatchData,
125
+ });
126
+ });
127
+
128
+ test('filter by gameName', async () => {
129
+ let keys = await db.listMatches();
130
+ expect(keys).toEqual(
131
+ expect.arrayContaining(['matchID', 'matchID2', 'matchID3'])
132
+ );
133
+
134
+ keys = await db.listMatches({ gameName: 'game1' });
135
+ expect(keys).toEqual(expect.arrayContaining(['matchID', 'matchID2']));
136
+
137
+ keys = await db.listMatches({ gameName: 'game2' });
138
+ expect(keys).toEqual(['matchID3']);
139
+ });
140
+
141
+ test('filter by isGameover', async () => {
142
+ let keys = await db.listMatches({});
143
+
144
+ expect(keys).toEqual(
145
+ expect.arrayContaining(['matchID', 'matchID2', 'matchID3'])
146
+ );
147
+
148
+ keys = await db.listMatches({ where: { isGameover: true } });
149
+ expect(keys).toEqual(['matchID2']);
150
+
151
+ keys = await db.listMatches({ where: { isGameover: false } });
152
+ expect(keys).toEqual(expect.arrayContaining(['matchID', 'matchID3']));
153
+ });
154
+
155
+ test('filter by updatedBefore', async () => {
156
+ const timestamp = new Date(2020, 4);
157
+
158
+ let keys = await db.listMatches({});
159
+ expect(keys).toEqual(
160
+ expect.arrayContaining(['matchID', 'matchID2', 'matchID3'])
161
+ );
162
+
163
+ keys = await db.listMatches({
164
+ where: { updatedBefore: timestamp.getTime() },
165
+ });
166
+ expect(keys).toEqual(expect.arrayContaining(['matchID']));
167
+ });
168
+
169
+ test('filter by updatedAfter', async () => {
170
+ const timestamp = new Date(2020, 4);
171
+
172
+ let keys = await db.listMatches({});
173
+ expect(keys).toEqual(
174
+ expect.arrayContaining(['matchID', 'matchID2', 'matchID3'])
175
+ );
176
+
177
+ keys = await db.listMatches({
178
+ where: { updatedAfter: timestamp.getTime() },
179
+ });
180
+ expect(keys).toEqual(['matchID2']);
181
+ });
182
+
183
+ test('filter combined', async () => {
184
+ const timestamp = new Date(2020, 4);
185
+ const timestamp2 = new Date(2020, 2, 15);
186
+ let keys = await db.listMatches({
187
+ gameName: 'chess',
188
+ where: { isGameover: true },
189
+ });
190
+ expect(keys).toEqual([]);
191
+
192
+ keys = await db.listMatches({
193
+ where: { isGameover: true, updatedBefore: timestamp.getTime() },
194
+ });
195
+ expect(keys).toEqual([]);
196
+
197
+ keys = await db.listMatches({
198
+ where: { isGameover: false, updatedBefore: timestamp.getTime() },
199
+ });
200
+ expect(keys).toEqual(['matchID']);
201
+
202
+ keys = await db.listMatches({
203
+ where: { isGameover: true, updatedAfter: timestamp.getTime() },
204
+ });
205
+ expect(keys).toEqual(['matchID2']);
206
+
207
+ keys = await db.listMatches({
208
+ where: { isGameover: false, updatedAfter: timestamp.getTime() },
209
+ });
210
+ expect(keys).toEqual([]);
211
+
212
+ keys = await db.listMatches({
213
+ where: {
214
+ updatedBefore: timestamp.getTime(),
215
+ updatedAfter: timestamp2.getTime(),
216
+ },
217
+ });
218
+ expect(keys).toEqual(['matchID']);
219
+ });
220
+ });
221
+ });