{"id":51319241,"url":"https://github.com/echecsjs/fen","last_synced_at":"2026-07-01T11:02:11.741Z","repository":{"id":345554132,"uuid":"1184706668","full_name":"echecsjs/fen","owner":"echecsjs","description":"Parse and stringify FEN (Forsyth–Edwards Notation) chess positions. Strict TypeScript, no-throw API.","archived":false,"fork":false,"pushed_at":"2026-06-29T14:11:32.000Z","size":585,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-29T15:26:11.711Z","etag":null,"topics":["chess","fen","parser","typescript"],"latest_commit_sha":null,"homepage":"https://github.com/echecsjs/fen#readme","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/echecsjs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-03-17T21:17:17.000Z","updated_at":"2026-06-29T14:13:23.000Z","dependencies_parsed_at":null,"dependency_job_id":"5a55144e-2fe8-47df-b29e-a37e8d5eb391","html_url":"https://github.com/echecsjs/fen","commit_stats":null,"previous_names":["mormubis/fen","echecsjs/fen"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/echecsjs/fen","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/echecsjs%2Ffen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/echecsjs%2Ffen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/echecsjs%2Ffen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/echecsjs%2Ffen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/echecsjs","download_url":"https://codeload.github.com/echecsjs/fen/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/echecsjs%2Ffen/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35003464,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-01T02:00:05.325Z","response_time":130,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chess","fen","parser","typescript"],"created_at":"2026-07-01T11:02:10.934Z","updated_at":"2026-07-01T11:02:11.736Z","avatar_url":"https://github.com/echecsjs.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @echecs/fen\n\n[![Spec](https://img.shields.io/badge/Spec-FIDE-green.svg)](SPEC.md)\n\nParse and stringify\n[FEN](https://www.chessprogramming.org/Forsyth-Edwards_Notation)\n(Forsyth-Edwards Notation) chess positions. Strict TypeScript, no-throw API.\n\n## Install\n\n```bash\nnpm install @echecs/fen\n```\n\n## Usage\n\n### Parsing\n\n```typescript\nimport { parse } from '@echecs/fen';\n\nconst position = parse(\n  'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1',\n);\n// =\u003e { board, turn, castlingRights, enPassantSquare, halfmoveClock, fullmoveNumber }\n\nparse('invalid');\n// =\u003e null\n```\n\n`parse` never throws. It returns `null` when the input is not a valid FEN\nstring. The result can be passed directly to the `Position` constructor from\n`@echecs/position`:\n\n```typescript\nimport { Position } from '@echecs/position';\n\nconst position = new Position(parse(fen));\n```\n\n#### Error and warning callbacks\n\nErrors indicate invalid FEN syntax — the string cannot be parsed. Warnings\nindicate a successfully parsed position that is suspicious (e.g. missing king).\n\n```typescript\nconst position = parse(fen, {\n  onError(error) {\n    // FEN is malformed — parse returns null.\n    console.error(`[${error.offset}] ${error.message}`);\n  },\n  onWarning(warning) {\n    // FEN is valid but the position is suspicious.\n    console.warn(warning.message);\n  },\n});\n```\n\nErrors are reported for:\n\n- Wrong number of fields\n- Invalid piece placement (bad piece type, wrong rank length)\n- Invalid active color\n- Invalid castling availability\n- Invalid en passant target square\n- Invalid halfmove clock (non-numeric or negative)\n- Invalid fullmove number (non-numeric or less than 1)\n\nWarnings are reported for:\n\n- Missing king for either side\n- Pawn on rank 1 or 8\n- More than 8 pawns per side\n- More than 16 pieces per side\n\n### Stringifying\n\n```typescript\nimport { stringify } from '@echecs/fen';\n\nstringify(position);\n// =\u003e 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'\n```\n\n`stringify` always succeeds.\n\n### Constants\n\n```typescript\nimport { STARTING_FEN } from '@echecs/fen';\n\nSTARTING_FEN;\n// =\u003e 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'\n```\n\n## API\n\n### `parse(input: string, options?: ParseOptions): PositionData | null`\n\nParses a FEN string into a `PositionData` object. Returns `null` if the input is\nnot a valid FEN string.\n\n### `stringify(position: PositionData): string`\n\nSerializes a `PositionData` object into a FEN string. Omitted fields use\ndefaults (empty board, white to move, all castling rights, no en passant,\nhalfmove clock 0, fullmove number 1).\n\n### `STARTING_FEN`\n\nThe FEN string for the standard starting position.\n\n### Types\n\nChess types (`Color`, `Square`, `Piece`, `CastlingRights`, `PositionData`, etc.)\nare re-exported from `@echecs/position`. Parse/stringify types are defined\nlocally:\n\n```typescript\nimport type {\n  CastlingRights,\n  Color,\n  EnPassantSquare,\n  File,\n  ParseError,\n  ParseOptions,\n  ParseWarning,\n  Piece,\n  PieceType,\n  PositionData,\n  Rank,\n  SideCastlingRights,\n  Square,\n} from '@echecs/fen';\n```\n\n```typescript\ninterface ParseOptions {\n  onError?: (error: ParseError) =\u003e void;\n  onWarning?: (warning: ParseWarning) =\u003e void;\n}\n\ninterface ParseError {\n  column: number; // 1-indexed column in the FEN string\n  line: number; // Always 1 (FEN is single-line)\n  message: string;\n  offset: number; // 0-indexed offset into the FEN string\n}\n\ninterface ParseWarning {\n  column: number;\n  line: number;\n  message: string;\n  offset: number;\n}\n```\n\nSee `@echecs/position` for the full type definitions of `PositionData`, `Color`,\n`Square`, `Piece`, and other chess types.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fechecsjs%2Ffen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fechecsjs%2Ffen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fechecsjs%2Ffen/lists"}