boardgame-core/AGENTS.md

2.8 KiB

AGENTS.md - boardgame-core

Commands

Prefer bash.exe(C:\Users\Administrator\AppData\Local\Microsoft\WindowsApps\bash.exe) over Powershell.

npm run build        # Build ESM bundle + declarations to dist/
npm run test         # Run vitest in watch mode
npm run test:run     # Run vitest once (no watch)
npm run typecheck    # Type-check without emitting (tsc --noEmit)

Running a single test file

npx vitest run tests/samples/tic-tac-toe.test.ts

Running a single test by name

npx vitest run -t "should detect horizontal win for X"

Code Style

Imports

  • Use double quotes for local imports, single quotes for npm packages
  • Use @/**/* for ./src/**/* import alias
  • Use @/index for code in samples

Formatting

  • 4-space indentation
  • Semicolons at statement ends
  • Arrow functions for callbacks; function keyword for methods needing this (e.g. command handlers)
  • No trailing whitespace

Naming Conventions

  • Types/Interfaces: PascalCasePart, Region, Command, IGameContext
  • Classes: PascalCaseEntity, AsyncQueue, Mulberry32RNG
  • Functions: camelCase, verb-first — createGameContext, parseCommand, isValidMove
  • Variables: camelCase
  • Constants: UPPER_SNAKE_CASEBOARD_SIZE, WINNING_LINES
  • Test files: *.test.ts mirroring src/ structure under tests/

Types

  • Strict TypeScript is enabled — no any
  • Use generics heavily: Entity<T>, CommandRunner<TContext, TResult>
  • Use type aliases for object shapes (not interfaces)
  • Use discriminated unions for results: { success: true; result: T } | { success: false; error: string }
  • Use unknown for untyped values, narrow with type guards or as

Error Handling

  • Prefer result objects over throwing: return { success, result/error }
  • When catching: const error = e as Error; then use error.message
  • Use throw new Error(...) only for truly exceptional cases
  • Validation error messages are in Chinese (e.g. "参数不足")

Testing

  • Vitest with globals enabled (describe, it, expect available without import)
  • Use async/await for async tests
  • Narrow result types with if (result.success) before accessing result.result
  • Define inline helper functions in test files when needed
  • No mocking — use real implementations
  • Test helpers: createTestContext(), createTestRegion()

Architecture Notes

  • Reactivity: Entity<T> extends Preact Signal — access state via .value, mutate via .produce(draft => ...)
  • Command system: CLI-style parsing with schema validation via inline-schema
  • Prompt system: Commands prompt for input via PromptEvent with resolve/reject
  • Barrel exports: src/index.ts is the single public API surface