pgn-manager 1.0.0 → 1.1.0

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.
package/README.md CHANGED
@@ -1 +1,101 @@
1
- # pgn-manager
1
+ # PGN Manager 📦♟️
2
+
3
+ A powerful TypeScript/JavaScript library for managing chess PGN (Portable Game Notation) files with support for variations and game traversal.
4
+
5
+ [![NPM Package](https://img.shields.io/npm/v/pgn-manager.svg)](https://www.npmjs.com/package/pgn-manager)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
8
+ [![npm downloads](https://img.shields.io/npm/dm/pgn-manager.svg)](https://www.npmjs.com/package/pgn-manager)
9
+
10
+
11
+ ## Features ✨
12
+ - Parse PGN strings into manageable objects
13
+ - Navigate through main lines and variations
14
+ - Access FEN positions for any move
15
+ - Handle game headers
16
+ - Traverse moves forward and backward
17
+ - Full TypeScript support
18
+
19
+ ## Installation 🚀
20
+
21
+ ```console
22
+ npm install pgn-manager
23
+ ```
24
+
25
+ ## Usage 💻
26
+
27
+ ```typescript
28
+ import PGNManager from 'pgn-manager';
29
+
30
+ // Initialize with a PGN string
31
+ const pgn = `1. e4 e5 2. Nf3 Nc6 (2... d6 3. d4) 3. Bb5 *`;
32
+ const manager = new PGNManager(pgn);
33
+
34
+ // Get the first move
35
+ const firstMove = manager.getFirstMove();
36
+
37
+ // Navigate through moves
38
+ const nextMove = manager.nextMove(firstMove);
39
+ const prevMove = manager.previousMove(nextMove);
40
+
41
+ // Get FEN position for a move
42
+ const fen = manager.getMoveFen(firstMove);
43
+
44
+ // Access game headers
45
+ const headers = manager.headers;
46
+ ```
47
+
48
+ ## API Reference 📚
49
+
50
+ ### Constructor
51
+ - `new PGNManager(pgn: string)`: Creates a new PGN manager instance
52
+
53
+ ### Properties
54
+ - `pgn`: Get the raw PGN string
55
+ - `parsedPGN`: Get the parsed PGN object
56
+ - `headers`: Get game headers array
57
+
58
+ ### Methods
59
+ - `getMove(moveNumber: number)`: Get move by number
60
+ - `getMoveNumber(moveOrMoveId: Move | number)`: Get number for a move
61
+ - `nextMove(moveOrMoveId: Move | number)`: Get next move in the sequence
62
+ - `previousMove(moveOrMoveId: Move | number)`: Get previous move
63
+ - `hasNextMove(moveOrMoveId: Move | number)`: Check if move has a next move
64
+ - `getFirstMove()`: Get the first move of the game
65
+ - `getLastMove()`: Get the last move of the game
66
+ - `getMoveFen(moveOrMoveId: Move | number)`: Get FEN position after move
67
+ - `getParentRav(moveOrMoveId: Move | number)`: Get parent variation for move
68
+ - `getChessJSInstance(moveOrMoveId: Move | number)`: Get or create a ChessJS instance for the position after the specified move
69
+ - `getMoveColor(moveOrMoveId: Move | number)`: Gets the color of the player who made the move ("w" for white or "b" for black)
70
+
71
+ ## Examples 🎯
72
+
73
+ ### Traversing Main Line
74
+
75
+ ```typescript
76
+ const manager = new PGNManager("1. e4 e5 2. Nf3 Nc6 3. Bb5 *");
77
+ let move = manager.getFirstMove();
78
+
79
+ while (manager.hasNextMove(move)) {
80
+ console.log(move.move);
81
+ move = manager.nextMove(move);
82
+ }
83
+ ```
84
+
85
+ ### Working with Variations
86
+
87
+ ```typescript
88
+ const manager = new PGNManager("1. e4 e5 2. Nf3 Nc6 (2... d6 3. d4) 3. Bb5 *");
89
+ const move = manager.getMove(2); // Get second move
90
+ const variation = manager.getParentRav(move);
91
+
92
+ if (variation) {
93
+ console.log("Move is part of a variation!");
94
+ }
95
+ ```
96
+
97
+ ## Contributing 🤝
98
+ Contributions are welcome! Feel free to submit issues and pull requests.
99
+
100
+ ## License 📄
101
+ MIT License - feel free to use this in your projects!
package/dist/index.d.ts CHANGED
@@ -2,26 +2,116 @@ import { ParsedPGN, Move, Rav, Header } from "pgn-parser";
2
2
  export declare const FEN_START_POSITION = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
3
3
  export declare const FEN_EMPTY_POSITION = "8/8/8/8/8/8/8/8";
4
4
  declare class PGNManager {
5
+ /** The raw PGN string input */
5
6
  private rawPGN;
7
+ /** The parsed PGN game object */
6
8
  private game;
9
+ /** Array of moves in traversal order */
7
10
  private sortedMoves;
11
+ /** Map of moves to their FEN position strings */
8
12
  private moveFen;
13
+ /** Map of moves to their parent variations (or null for mainline) */
9
14
  private moveParent;
15
+ /** Map of variations to their parent moves */
10
16
  private ravParent;
17
+ /** Map of moves to the color of the player who made the move */
18
+ private moveColor;
19
+ /**
20
+ * Creates a new PGNManager instance
21
+ * @param pgn - The PGN string to parse and manage
22
+ */
11
23
  constructor(pgn: string);
24
+ /**
25
+ * Initializes the game traversal starting from the initial position
26
+ * @param game - The parsed PGN game object
27
+ */
12
28
  private dfOnGame;
29
+ /**
30
+ * Performs depth-first traversal of the game moves and variations
31
+ * @param move - The current move being processed
32
+ * @param parent - The parent RAV (variation) containing the move
33
+ * @param chessGame - The chess instance for the current position
34
+ */
13
35
  private dfsOnGame;
36
+ /**
37
+ * Gets the raw PGN string
38
+ * @returns The original PGN string
39
+ */
14
40
  get pgn(): string;
41
+ /**
42
+ * Gets the parsed PGN object
43
+ * @returns The parsed PGN game object
44
+ */
15
45
  get parsedPGN(): ParsedPGN;
46
+ /**
47
+ * Gets the game headers
48
+ * @returns Array of game headers
49
+ */
16
50
  get headers(): Array<Header>;
51
+ /**
52
+ * Gets a move by its number in the sequence
53
+ * @param moveNumber - The 1-based index of the move
54
+ * @returns The move object at the specified position
55
+ */
17
56
  getMove: (moveNumber: number) => Move;
57
+ /**
58
+ * Gets the number of a move in the sequence
59
+ * @param move - The move object
60
+ * @returns The 1-based index of the move
61
+ */
18
62
  getMoveNumber: (move: Move) => number;
19
- nextMove: (move: Move | undefined) => Move;
20
- hasNextMove: (move: Move) => boolean;
21
- previousMove: (move: Move) => Move | undefined;
63
+ /**
64
+ * Gets the next move in the sequence
65
+ * @param moveOrId - The current move object or move number
66
+ * @returns The next move in the sequence
67
+ * @throws Error if there are no moves in the game
68
+ */
69
+ nextMove: (moveOrId: Move | number | undefined) => Move;
70
+ /**
71
+ * Checks if there is a next move available
72
+ * @param moveOrId - The current move object or move number
73
+ * @returns True if there is a next move, false otherwise
74
+ */
75
+ hasNextMove: (moveOrId: Move | number) => boolean;
76
+ /**
77
+ * Gets the previous move in the sequence
78
+ * @param moveOrId - The current move object or move number
79
+ * @returns The previous move or undefined if at the start
80
+ * @throws Error if there are no moves or if the move parameter is invalid
81
+ */
82
+ previousMove: (moveOrId: Move | number) => Move | undefined;
83
+ /**
84
+ * Gets the first move in the game
85
+ * @returns The first move
86
+ * @throws Error if there are no moves in the game
87
+ */
22
88
  getFirstMove: () => Move;
89
+ /**
90
+ * Gets the last move in the game
91
+ * @returns The last move
92
+ * @throws Error if there are no moves in the game
93
+ */
23
94
  getLastMove: () => any;
24
- getMoveFen: (move: Move) => string;
25
- getParentRav: (move: Move) => Rav | null;
95
+ /**
96
+ * Gets the FEN string for a specific move
97
+ * @param moveOrId - The move object or move number
98
+ * @returns The FEN string representing the position after the move
99
+ * @throws Error if the move parameter is invalid
100
+ */
101
+ getMoveFen: (moveOrId: Move | number) => string;
102
+ /**
103
+ * Gets the parent RAV (variation) for a move
104
+ * @param moveOrId - The move object or move number
105
+ * @returns The parent RAV or null if the move is in the main line
106
+ * @throws Error if the move parameter is invalid
107
+ */
108
+ getParentRav: (moveOrId: Move | number) => Rav | null;
109
+ /**
110
+ * Gets the color of the player who made the move
111
+ * @param moveOrId - The move object or move ID number
112
+ * @returns "w" for white or "b" for black
113
+ * @throws Error if the move parameter is invalid
114
+ */
115
+ getMoveColor: (moveOrId: Move | number) => "w" | "b";
26
116
  }
27
117
  export default PGNManager;
package/dist/index.js CHANGED
@@ -7,12 +7,24 @@ const pgn_parser_1 = require("pgn-parser");
7
7
  exports.FEN_START_POSITION = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
8
8
  exports.FEN_EMPTY_POSITION = "8/8/8/8/8/8/8/8";
9
9
  class PGNManager {
10
+ /** The raw PGN string input */
10
11
  rawPGN;
12
+ /** The parsed PGN game object */
11
13
  game;
14
+ /** Array of moves in traversal order */
12
15
  sortedMoves;
16
+ /** Map of moves to their FEN position strings */
13
17
  moveFen;
18
+ /** Map of moves to their parent variations (or null for mainline) */
14
19
  moveParent;
20
+ /** Map of variations to their parent moves */
15
21
  ravParent;
22
+ /** Map of moves to the color of the player who made the move */
23
+ moveColor;
24
+ /**
25
+ * Creates a new PGNManager instance
26
+ * @param pgn - The PGN string to parse and manage
27
+ */
16
28
  constructor(pgn) {
17
29
  this.rawPGN = pgn;
18
30
  this.game = pgn_parser_1.default.parse(pgn + " *")[0];
@@ -20,8 +32,13 @@ class PGNManager {
20
32
  this.moveParent = new Map();
21
33
  this.ravParent = new Map();
22
34
  this.moveFen = new Map();
35
+ this.moveColor = new Map();
23
36
  this.dfOnGame(this.game);
24
37
  }
38
+ /**
39
+ * Initializes the game traversal starting from the initial position
40
+ * @param game - The parsed PGN game object
41
+ */
25
42
  dfOnGame = (game) => {
26
43
  this.sortedMoves = [];
27
44
  var chessGame = new Chess(exports.FEN_START_POSITION);
@@ -29,6 +46,12 @@ class PGNManager {
29
46
  this.dfsOnGame(move, game, chessGame);
30
47
  }
31
48
  };
49
+ /**
50
+ * Performs depth-first traversal of the game moves and variations
51
+ * @param move - The current move being processed
52
+ * @param parent - The parent RAV (variation) containing the move
53
+ * @param chessGame - The chess instance for the current position
54
+ */
32
55
  dfsOnGame = (move, parent, chessGame) => {
33
56
  this.sortedMoves.push(move);
34
57
  this.moveParent.set(move, parent);
@@ -46,26 +69,62 @@ class PGNManager {
46
69
  !chessGame.move(move.move, { sloppy: true }))
47
70
  console.log("Invalid move: " + move.move);
48
71
  this.moveFen.set(move, chessGame.fen());
72
+ this.moveColor.set(move, chessGame.turn() === "w" ? "b" : "w");
49
73
  };
74
+ /**
75
+ * Gets the raw PGN string
76
+ * @returns The original PGN string
77
+ */
50
78
  get pgn() {
51
79
  return this.rawPGN;
52
80
  }
81
+ /**
82
+ * Gets the parsed PGN object
83
+ * @returns The parsed PGN game object
84
+ */
53
85
  get parsedPGN() {
54
86
  return this.game;
55
87
  }
88
+ /**
89
+ * Gets the game headers
90
+ * @returns Array of game headers
91
+ */
56
92
  get headers() {
57
93
  if (!this.game || !this.game.headers)
58
94
  return [];
59
95
  return this.game.headers;
60
96
  }
97
+ /**
98
+ * Gets a move by its number in the sequence
99
+ * @param moveNumber - The 1-based index of the move
100
+ * @returns The move object at the specified position
101
+ */
61
102
  getMove = (moveNumber) => {
62
103
  let move = this.sortedMoves[moveNumber - 1];
63
104
  return move;
64
105
  };
106
+ /**
107
+ * Gets the number of a move in the sequence
108
+ * @param move - The move object
109
+ * @returns The 1-based index of the move
110
+ */
65
111
  getMoveNumber = (move) => {
66
112
  return this.sortedMoves.indexOf(move) + 1;
67
113
  };
68
- nextMove = (move) => {
114
+ /**
115
+ * Gets the next move in the sequence
116
+ * @param moveOrId - The current move object or move number
117
+ * @returns The next move in the sequence
118
+ * @throws Error if there are no moves in the game
119
+ */
120
+ nextMove = (moveOrId) => {
121
+ let move;
122
+ if (typeof moveOrId === "number") {
123
+ move = this.getMove(moveOrId);
124
+ }
125
+ else {
126
+ move = moveOrId;
127
+ }
69
128
  if (!move) {
70
129
  if (this.sortedMoves.length == 0) {
71
130
  throw Error("No moves in game");
@@ -92,10 +151,23 @@ class PGNManager {
92
151
  }
93
152
  return tempNextMove;
94
153
  };
95
- hasNextMove = (move) => {
154
+ /**
155
+ * Checks if there is a next move available
156
+ * @param moveOrId - The current move object or move number
157
+ * @returns True if there is a next move, false otherwise
158
+ */
159
+ hasNextMove = (moveOrId) => {
160
+ const move = typeof moveOrId === "number" ? this.getMove(moveOrId) : moveOrId;
96
161
  return !move || this.nextMove(move) !== move;
97
162
  };
98
- previousMove = (move) => {
163
+ /**
164
+ * Gets the previous move in the sequence
165
+ * @param moveOrId - The current move object or move number
166
+ * @returns The previous move or undefined if at the start
167
+ * @throws Error if there are no moves or if the move parameter is invalid
168
+ */
169
+ previousMove = (moveOrId) => {
170
+ const move = typeof moveOrId === "number" ? this.getMove(moveOrId) : moveOrId;
99
171
  if (!move) {
100
172
  if (this.sortedMoves.length == 0) {
101
173
  throw Error("No moves in game");
@@ -122,31 +194,68 @@ class PGNManager {
122
194
  }
123
195
  return tempPrevMove;
124
196
  };
197
+ /**
198
+ * Gets the first move in the game
199
+ * @returns The first move
200
+ * @throws Error if there are no moves in the game
201
+ */
125
202
  getFirstMove = () => {
126
203
  if (this.sortedMoves.length == 0) {
127
204
  throw Error("No moves in game");
128
205
  }
129
206
  return this.sortedMoves[0];
130
207
  };
208
+ /**
209
+ * Gets the last move in the game
210
+ * @returns The last move
211
+ * @throws Error if there are no moves in the game
212
+ */
131
213
  getLastMove = () => {
132
214
  if (this.sortedMoves.length == 0) {
133
215
  throw Error("No moves in game");
134
216
  }
135
217
  return this.game.moves[this.game.moves.length - 1];
136
218
  };
137
- getMoveFen = (move) => {
219
+ /**
220
+ * Gets the FEN string for a specific move
221
+ * @param moveOrId - The move object or move number
222
+ * @returns The FEN string representing the position after the move
223
+ * @throws Error if the move parameter is invalid
224
+ */
225
+ getMoveFen = (moveOrId) => {
226
+ const move = typeof moveOrId === "number" ? this.getMove(moveOrId) : moveOrId;
138
227
  if (!move) {
139
228
  throw Error("Invalid 'move' parameter while getting fen");
140
229
  }
141
230
  let moveFen = this.moveFen.get(move);
142
231
  return moveFen ? moveFen : exports.FEN_EMPTY_POSITION;
143
232
  };
144
- getParentRav = (move) => {
233
+ /**
234
+ * Gets the parent RAV (variation) for a move
235
+ * @param moveOrId - The move object or move number
236
+ * @returns The parent RAV or null if the move is in the main line
237
+ * @throws Error if the move parameter is invalid
238
+ */
239
+ getParentRav = (moveOrId) => {
240
+ const move = typeof moveOrId === "number" ? this.getMove(moveOrId) : moveOrId;
145
241
  if (!move) {
146
242
  throw Error("Invalid 'move' parameter while getting parent rav");
147
243
  }
148
244
  let parentRav = this.moveParent.get(move);
149
245
  return parentRav ? parentRav : null;
150
246
  };
247
+ /**
248
+ * Gets the color of the player who made the move
249
+ * @param moveOrId - The move object or move ID number
250
+ * @returns "w" for white or "b" for black
251
+ * @throws Error if the move parameter is invalid
252
+ */
253
+ getMoveColor = (moveOrId) => {
254
+ const move = typeof moveOrId === "number" ? this.getMove(moveOrId) : moveOrId;
255
+ if (!move) {
256
+ throw Error("Invalid 'move' parameter while getting move color");
257
+ }
258
+ return this.moveColor.get(move);
259
+ };
151
260
  }
152
261
  exports.default = PGNManager;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pgn-manager",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Libraray built on top of chess.js and pgn-parser to load and process PGN files in typescript.",
5
5
  "main": "dist/index",
6
6
  "typings": "dist/index",
@@ -18,9 +18,7 @@
18
18
  "keywords": [
19
19
  "Chess",
20
20
  "PGN",
21
- "Portal",
22
- "Game",
23
- "Notation"
21
+ "Portal Game Notation"
24
22
  ],
25
23
  "author": "Harsh Kumar <hadron43@yahoo.com>",
26
24
  "license": "MIT",
@@ -28,9 +26,12 @@
28
26
  "url": "https://github.com/hadron43/pgn-manager/issues"
29
27
  },
30
28
  "homepage": "https://github.com/hadron43/pgn-manager#readme",
31
- "devDependencies": {
29
+ "dependencies": {
32
30
  "chess.js": "0.12.0",
33
- "pgn-parser": "2.1.0",
31
+ "pgn-parser": "2.1.0"
32
+ },
33
+ "devDependencies": {
34
+ "@types/chess.js": "^0.11.2",
34
35
  "typescript": "4.5.2"
35
36
  },
36
37
  "files": [