Bridge Training

Schemas

Zod schemas and inferred types exported from @workspace/bridge/schemas/*, one file per concern.

Schemas are exported per file through the ./schemas/* wildcard: import @workspace/bridge/schemas/<file>. There is no aggregate entry point. Each file exports its Zod objects and a z.infer type for each one. The same modules are reachable at runtime through engine.schemas.

schemas.ts
playerSchema.parse("N"); // "N"
cardSchema.parse("SA"); // "SA"
bidSchema.parse("3NT"); // "3NT"
bidSchema.safeParse("8NT").success; // false
contractSchema.parse({ level: 4, suit: "H", declarer: "S", doubled: "none" });

bid

@workspace/bridge/schemas/bid. regularBidSchema and bidSchema are z.custom guards built on the bid parser, so they infer RegularBid and Bid rather than string.

SchemaInferred typeValidates
bidLevelSchemaBidLevelSchema1 | 2 | 3 | 4 | 5 | 6 | 7
denominationSchemaDenominationSchema"C" | "D" | "H" | "S" | "NT"
specialBidSchemaSpecialBidSchema"Pass" | "X" | "XX" | "Alert"
counterStatusSchemaCounterStatusSchema"none" | "X" | "XX"
regularBidSchemaRegularBidSchemaLevel plus denomination, "1C" to "7NT"
bidSchemaBidSchemaAny regular or special bid
regularBidCompositeSchemaRegularBidCompositeSchema{ player, level, suit, type: "regular", index }
specialBidCompositeSchemaSpecialBidCompositeSchema{ player, value, type: "special", index }
bidCompositeSchemaBidCompositeSchemaUnion of the two composites
contractSchemaContractSchema{ level, suit, declarer, doubled }

card

@workspace/bridge/schemas/card. cardSchema is a z.custom guard and infers Card.

SchemaInferred typeValidates
suitSchemaSuitSchema"S" | "H" | "D" | "C"
rankSchemaRankSchema"A" to "2", with "T" for ten
cardSchemaCardSchemaSuit then rank, "SA"

deal

@workspace/bridge/schemas/deal validates the stored Deal shape (rank strings per suit, flat move lists). playMoveSchema.card is a plain string, not a cardSchema.

SchemaInferred typeValidates
handSchemaHandSchema{ S, H, D, C } rank strings, 16 characters max each
handsSchemaHandsSchemaFour handSchema keyed by seat
auctionMoveSchemaAuctionMoveSchema{ bid, isAlerted?, comment? }
auctionSchemaAuctionSchema{ first, moves: AuctionMove[] }
playMoveSchemaPlayMoveSchema{ card: string, comment? }
playSchemaPlaySchema{ first, moves: PlayMove[] }
suitCountSchemaSuitCountSchema{ S, H, D, C } numbers
handAnalysisSchemaHandAnalysisSchema{ points, suitCount }
dealAnalysisSchemaDealAnalysisSchemaFour handAnalysisSchema keyed by seat
schemas.ts
const deal = makeDeal();
const cards = handsSchema.parse(deal.cards);
const auction = auctionSchema.parse(new AuctionBuilder().fromCompact("S / 1NT pass 3NT AP").build());

game-params

@workspace/bridge/schemas/game-params

SchemaInferred typeValidates
gameParamsSchemaGameParams{ vulnerability, scoringMode, resultExpected }, defaults "UNSET", "UNSET", null

hands

@workspace/bridge/schemas/hands validates the in-memory HandsData shape, one string per card. The stored rank-string shape (Hand / Hands) is validated by handSchema / handsSchema in deal.

SchemaInferred typeValidates
handDataSchemaHandDataSchemaRecord<Suit, string[]>
handsDataSchemaHandsDataSchemaRecord<Player, HandDataSchema>
schemas.ts
const hands = handsDataSchema.parse({
  N: { S: ["SA", "SK"], H: [], D: [], C: [] },
  E: { S: [], H: ["HA"], D: [], C: [] },
  S: { S: [], H: [], D: ["DA"], C: [] },
  W: { S: [], H: [], D: [], C: ["CA"] },
});

play

@workspace/bridge/schemas/play parses form data into the Trick shape that buildTricks returns.

SchemaInferred typeValidates
playEntrySchemaPlayEntrySchema{ card: Card, player }, the card checked by cardSchema
trickSchemaTrickSchema{ lead, cards, winner }, winner is null on an incomplete trick
schemas.ts
const trick = trickSchema.parse({ lead: "W", cards: [{ player: "W", card: "S9" }], winner: null });

player

@workspace/bridge/schemas/player

SchemaInferred typeValidates
playerSchemaPlayerSchema"N" | "E" | "S" | "W"
partnershipSchemaPartnershipSchema"NS" | "EW"

scoring

@workspace/bridge/schemas/scoring

SchemaInferred typeValidates
scoringModeSchemaScoringModeSchema"UNSET" | "TPP" | "IMP"

teach-params

@workspace/bridge/schemas/teach-params. Two mode schemas coexist: auctionModeSchema is built from the auction-picker groups and infers a plain string; teachingModeSchema matches the TeachingMode union exactly and is the one to use for stored or transported deal modes.

SchemaInferred typeValidates
auctionModeSchemaAuctionMode (a string)Picker mode values
teachingModeSchemanone exportedThe 12 TeachingMode values
teachParamsSchemaTeachParams{ auctionMode, teachDummy }, defaults "auction", true
schemas.ts
const gameParams = gameParamsSchema.parse({});
// => { vulnerability: "UNSET", scoringMode: "UNSET", resultExpected: null }
const teachParams = teachParamsSchema.parse({});
// => { auctionMode: "auction", teachDummy: true }
teachingModeSchema.parse("petit-bridge");

vulnerability

@workspace/bridge/schemas/vulnerability. No inferred type is exported; use Vulnerability from @workspace/bridge/types.

SchemaValidates
vulnerabilitySchema"UNSET" | "NONE" | "NS" | "EW" | "ALL"

engine.schemas

The engine exposes the same modules as namespaces, keyed player, card, bid, hands, auction, play, scoring, vulnerability, gameParams and teachParams. The deal file is not part of engine.schemas.

schemas.ts
const engine = createBridgeEngine(createBridgeContext({ teachingMode: "auction" }));
engine.schemas.bid.bidSchema.parse("1C");
engine.schemas.hands.handsDataSchema.safeParse(new HandsBuilder().fromCompact("AKQ2.KQ3.A54.K32 JT98.JT9.KQJ.QJ9 7654.A87.T98.AT8 3.6542.7632.7654").build());