5.3 KiB
Wave A — @suaveplan/game-server core foundation
Package: @suaveplan/game-server
Status: PROPOSED
Type: extends existing genesis package (0.1.0)
Design: ./design.md (inline below)
Spec delta: ./specs/game-server/spec.md
Why
Wave A ships the core foundation of @suaveplan/game-server that every
later wave (engine, session, state, matchmaking, transport) depends on:
the four core interfaces (IGameLogic, IPlayerManager,
ISessionManager, IStateManager) with runtime conformance harnesses,
the GameEvents typed payload map plus its GAME_EVENT_KEYS registry,
the GameEventEmitter typed pub/sub with ergonomic helpers
(safeEmit, waitFor, onN, onMultiple), and the
AbstractGameLogic Template-Method base class for concrete games. The
package already shipped DIContainer, the GameServerError registry,
and the Zod-validated core types in the prior change
enterprise-game-server-core; Wave A is an additive extension that
fills the interfaces / events / abstract-base layer behind a single
0.1.0 publish.
Without this Wave the downstream waves (B: session manager + player manager, C: state manager + replay, D: matchmaking + transport plugins) have no contract to implement against. Shipping it as one isolated wave keeps the surface reviewable, the coverage gate enforceable on the whole package, and the dependent slices unblocked.
What changes
- ADDED:
core/types/core.types.ts—ConnectionStatus,PlayerConnection,SessionNode,SessionData,StateChangeEvent,GameEventsmap. - ADDED:
core/interfaces/i-game-logic/—IGameLogic<TState, TMove>interface andrunIGameLogicConformanceharness. - ADDED:
core/interfaces/i-player-manager/—IPlayerManagerandrunIPlayerManagerConformance. - ADDED:
core/interfaces/i-session-manager/—ISessionManagerandrunISessionManagerConformance. - ADDED:
core/interfaces/i-state-manager/—IStateManager<TState>andrunIStateManagerConformance. - ADDED:
core/events/game-events/—GAME_EVENT_KEYSarray +isGameEventKeypredicate. - ADDED:
core/events/game-event-emitter/—GameEventEmittertyped pub/sub withsafeEmit/waitFor/onN/onMultiple/ per-key listener cap. - ADDED:
core/abstract-game-logic/—AbstractGameLogic<TState, TMove>Template-Method base class with injectedClock+IdGeneratorand OTel instrumentation. - EXTENDED:
errors/game-server-error.ts— six new codes (INVALID_MOVE,PLAYER_ALREADY_EXISTS,PLAYER_NOT_FOUND,LISTENER_LIMIT_EXCEEDED,INVALID_LISTENER_COUNT,EVENT_WAIT_TIMEOUT) raised by the new core surface. - EXTENDED: root
src/index.ts— additive named re-exports for the new Wave A surface. - EXTENDED:
package.jsonexports map — 8 new subpath entries, one per feature module.
Impact
Affected dependents
bunx turbo ls --filter=...@suaveplan/game-server enumerates dependents
of this package. As of Wave A landing, no genesis package consumes
@suaveplan/game-server yet — this is a foundation wave for
@suaveplan/game-loop, @suaveplan/game-state-schemas, and the
api-plugin-game-server family that will land in Waves B–D.
@suaveplan/game-server(self) — [x] tests run / [x] docs reviewed / [ ] no action needed.- No external dependents — verified by
bunx turbo ls --filter=...@suaveplan/game-server.
Parity Checklist
| Capability | Upstream | Migrated | Notes |
|---|---|---|---|
IGameLogic interface |
YES | YES | Genesis tightens any → generic TState/TMove. |
Inline AbstractGameLogic in IGameLogic.ts |
YES | UP | Genesis splits to its own feature dir. |
IPlayerManager interface |
YES | YES | Returns ReadonlyArray<PlayerConnection>. |
ISessionManager interface |
YES | YES | Returns ReadonlyArray<SessionNode>. |
IStateManager interface |
YES | YES | Readonly<TState> instead of DeepReadonly. |
GameEvents map |
YES | UP | Variadic tuples collapsed to single-payload objects. |
GameEventEmitter extending Node EventEmitter |
YES | UP | Self-contained typed emitter; same surface +typed errors. |
Wildcard [key: string]: any[] index signature |
YES | NO | Scoped out: closed map keeps lint/type safety; downstream needing wildcard analytics can subscribe to GAME_EVENT_KEYS directly. |
AbstractGameLogic Template Method |
YES | UP | Adds injected Clock + IdGenerator, typed errors, OTel instruments. |
cloneState JSON round-trip |
YES | YES | |
Hook methods (beforeMoveProcessing, etc.) |
YES | YES | |
Player roster (addPlayer / removePlayer) |
YES | UP | Throws GameServerError not plain Error. |
| Conformance harnesses | NO | UP | Genesis-original — makes interfaces runtime-testable. |
Rationale for the single scope-out (wildcard analytics:*): the
upstream signature [key: symbol]: any[] defeats type safety and is
unused inside the core/ slice; downstream analytics packages can
extend GameEvents via module augmentation if needed.
Migration
Wave A is additive — no existing public-surface item is renamed or
removed. Consumers of the prior 0.1.0 surface (DIContainer,
GameServerError, Zod parsers, types) keep working unchanged. The new
error codes extend the registry; pattern-match consumers should not
care because none of the new codes were thrown previously.