Skip to content

@my-swu/simulator-client


@my-swu/simulator-client / SchemaValidator

Interface: SchemaValidator ​

Defined in: packages/ts-sdk/src/validators/validator.ts:26

Validates SDK payloads at the network boundary.

Pass one as validate to createSimulatorClient to turn boundary validation on. Custom implementations are supported: anything that narrows an unknown payload to the generated type — or throws — satisfies the contract.

Example:

ts
import { createSchemaValidator } from '@my-swu/simulator-client'
import type { SchemaValidator } from '@my-swu/simulator-client'

// Pass one as `validate` to turn boundary validation on.
const schemaValidator: SchemaValidator = createSchemaValidator()

console.log(schemaValidator)

Properties ​

hasUnknownDiscriminant? ​

Example:

ts
import { createSchemaValidator } from '@my-swu/simulator-client'
import type { SchemaValidator } from '@my-swu/simulator-client'

// Pass one as `validate` to turn boundary validation on.
const schemaValidator: SchemaValidator = createSchemaValidator()

const { hasUnknownDiscriminant } = schemaValidator

console.log(hasUnknownDiscriminant)

optional hasUnknownDiscriminant?: (name, value) => boolean

Defined in: packages/ts-sdk/src/validators/validator.ts:46

Whether one payload carries a type discriminant this build does not know.

Tagged-union socket frames answering true here are dropped before parse, so a server that grows a message variant does not break older clients. Leave it undefined when the implementation cannot enumerate the known discriminants: frames then reach the dispatcher, which ignores any type it has no case for.

Parameters ​

name ​

"admin-match-list-response" | "admin-match-debug-bundle" | "admin-match-replay-response" | "simulator-report-list-response" | "simulator-report-response" | "health-response" | "simulator-availability-response" | "simulator-admin-status-response" | "card-catalog-refresh-response" | "set-simulator-maintenance-request" | "set-ranked-admission-request" | "api-error-response" | "meta-window" | "ranked-queue" | "ranked-admin-status" | "ranked-matchmaking-view" | "ranked-leaderboard-entry" | "create-meta-window-request" | "meta-windows-response" | "ranked-profile-request" | "ranked-profile-response" | "ranked-leaderboard-query" | "ranked-leaderboard-response" | "create-match-request" | "create-lobby-request" | "join-lobby-request" | "spectate-lobby-request" | "lobby-matchmaking-request" | "lobby-sync-request" | "lobby-matchmaking-decision-request" | "update-lobby-player-request" | "update-lobby-ai-player-request" | "add-lobby-ai-player-request" | "lobby-chat-request" | "start-lobby-request" | "return-lobby-match-request" | "submit-lobby-limited-deck-request" | "prepare-lobby-limited-ai-decks-request" | "start-lobby-limited-match-request" | "leave-lobby-request" | "become-lobby-spectator-request" | "kick-lobby-player-request" | "kick-lobby-spectator-request" | "update-lobby-settings-request" | "lobby-response" | "lobby-list-response" | "lobby-access-response" | "lobby-chat-response" | "lobby-server-message" | "lobby-error-code" | "lobby-list-server-message" | "create-tournament-room-request" | "join-tournament-room-request" | "tournament-room-sync-request" | "update-tournament-room-player-request" | "update-tournament-room-settings-request" | "tournament-room-chat-request" | "start-tournament-event-request" | "tournament-event-command-request" | "submit-tournament-deck-request" | "create-tournament-table-request" | "join-tournament-table-request" | "return-tournament-match-request" | "leave-tournament-room-request" | "close-tournament-room-request" | "tournament-room-response" | "tournament-room-list-response" | "tournament-room-access-response" | "tournament-room-chat-response" | "tournament-room-server-message" | "create-limited-event-request" | "limited-event-access-response" | "limited-event-preflight-response" | "limited-event-response" | "limited-event-command-request" | "join-limited-event-request" | "leave-limited-event-request" | "limited-event-server-message" | "match-access-response" | "abandon-match-request" | "abandon-match-response" | "list-active-ai-matches-request" | "list-active-ai-matches-response" | "leave-match-request" | "leave-match-response" | "match-spectator-access-response" | "join-match-request" | "spectate-match-request" | "submit-match-deck-request" | "submit-match-deck-response" | "format-event-request" | "format-event-response" | "undo-match-request" | "undo-match-response" | "undo-respond-match-request" | "rematch-match-request" | "rematch-match-response" | "set-ai-paused-request" | "set-ai-paused-response" | "set-playground-ai-seat-request" | "playground-export-payload" | "create-playground-share-response" | "get-match-response" | "match-history-list-request" | "match-history-list-response" | "match-history-deck-stats-request" | "match-history-deck-stats-response" | "match-history-entry" | "match-history-replay-request" | "match-history-replay-response" | "submit-ai-game-feedback-request" | "submit-ai-game-feedback-response" | "create-match-history-replay-share-request" | "create-match-history-replay-share-response" | "shared-match-history-replay-response" | "match-chat-lookup-response" | "match-history-restore-request" | "restore-history-response" | "match-recovery-request" | "match-recovery-response" | "match-access-recovery-request" | "match-access-recovery-response" | "cards-response" | "resolve-card-ids-request" | "resolve-card-ids-response" | "client-message" | "server-message" | "game-command" | "game-event" | "game-state" | "match-connection-role" | "welcome-payload" | "error-payload" | "match-save-payload" | "save-match-request" | "restore-match-save-request" | "restore-match-save-response"

Generated schema name the payload is destined for.

value ​

unknown

Parsed payload from the wire.

Returns ​

boolean


parse ​

Example:

ts
import { createSchemaValidator } from '@my-swu/simulator-client'
import type { SchemaValidator } from '@my-swu/simulator-client'

// Pass one as `validate` to turn boundary validation on.
const schemaValidator: SchemaValidator = createSchemaValidator()

const { parse } = schemaValidator

console.log(parse)

parse: <TName>(name, value) => SchemaTypeMap[TName]

Defined in: packages/ts-sdk/src/validators/validator.ts:33

Narrows one payload to its generated type, throwing when it does not match.

Type Parameters ​

TName ​

TName extends keyof SchemaTypeMap

Parameters ​

name ​

TName

Generated schema name.

value ​

unknown

Payload arriving from (or heading to) the wire.

Returns ​

SchemaTypeMap[TName]


warmUp? ​

Example:

ts
import { createSchemaValidator } from '@my-swu/simulator-client'
import type { SchemaValidator } from '@my-swu/simulator-client'

// Pass one as `validate` to turn boundary validation on.
const schemaValidator: SchemaValidator = createSchemaValidator()

const { warmUp } = schemaValidator

console.log(warmUp)

optional warmUp?: (names?) => void

Defined in: packages/ts-sdk/src/validators/validator.ts:64

Compiles the named schemas now, instead of when a payload first needs them.

Schema-backed validation compiles lazily, and the first compile is by far the most expensive one because it pulls in the whole shared definition pool. Left alone that cost lands on the first frame a socket receives — during connect, on the browser's main thread. createSimulatorClient therefore calls this on an idle callback right after construction; call it yourself to warm a different set, or at a moment you choose.

Implementations must be synchronous and safe to call repeatedly: a schema already compiled is a no-op. Leave it undefined when there is nothing to compile — the pass-through does, which is what makes warm-up free when validation is off.

Parameters ​

names? ​

readonly ("admin-match-list-response" | "admin-match-debug-bundle" | "admin-match-replay-response" | "simulator-report-list-response" | "simulator-report-response" | "health-response" | "simulator-availability-response" | "simulator-admin-status-response" | "card-catalog-refresh-response" | "set-simulator-maintenance-request" | "set-ranked-admission-request" | "api-error-response" | "meta-window" | "ranked-queue" | "ranked-admin-status" | "ranked-matchmaking-view" | "ranked-leaderboard-entry" | "create-meta-window-request" | "meta-windows-response" | "ranked-profile-request" | "ranked-profile-response" | "ranked-leaderboard-query" | "ranked-leaderboard-response" | "create-match-request" | "create-lobby-request" | "join-lobby-request" | "spectate-lobby-request" | "lobby-matchmaking-request" | "lobby-sync-request" | "lobby-matchmaking-decision-request" | "update-lobby-player-request" | "update-lobby-ai-player-request" | "add-lobby-ai-player-request" | "lobby-chat-request" | "start-lobby-request" | "return-lobby-match-request" | "submit-lobby-limited-deck-request" | "prepare-lobby-limited-ai-decks-request" | "start-lobby-limited-match-request" | "leave-lobby-request" | "become-lobby-spectator-request" | "kick-lobby-player-request" | "kick-lobby-spectator-request" | "update-lobby-settings-request" | "lobby-response" | "lobby-list-response" | "lobby-access-response" | "lobby-chat-response" | "lobby-server-message" | "lobby-error-code" | "lobby-list-server-message" | "create-tournament-room-request" | "join-tournament-room-request" | "tournament-room-sync-request" | "update-tournament-room-player-request" | "update-tournament-room-settings-request" | "tournament-room-chat-request" | "start-tournament-event-request" | "tournament-event-command-request" | "submit-tournament-deck-request" | "create-tournament-table-request" | "join-tournament-table-request" | "return-tournament-match-request" | "leave-tournament-room-request" | "close-tournament-room-request" | "tournament-room-response" | "tournament-room-list-response" | "tournament-room-access-response" | "tournament-room-chat-response" | "tournament-room-server-message" | "create-limited-event-request" | "limited-event-access-response" | "limited-event-preflight-response" | "limited-event-response" | "limited-event-command-request" | "join-limited-event-request" | "leave-limited-event-request" | "limited-event-server-message" | "match-access-response" | "abandon-match-request" | "abandon-match-response" | "list-active-ai-matches-request" | "list-active-ai-matches-response" | "leave-match-request" | "leave-match-response" | "match-spectator-access-response" | "join-match-request" | "spectate-match-request" | "submit-match-deck-request" | "submit-match-deck-response" | "format-event-request" | "format-event-response" | "undo-match-request" | "undo-match-response" | "undo-respond-match-request" | "rematch-match-request" | "rematch-match-response" | "set-ai-paused-request" | "set-ai-paused-response" | "set-playground-ai-seat-request" | "playground-export-payload" | "create-playground-share-response" | "get-match-response" | "match-history-list-request" | "match-history-list-response" | "match-history-deck-stats-request" | "match-history-deck-stats-response" | "match-history-entry" | "match-history-replay-request" | "match-history-replay-response" | "submit-ai-game-feedback-request" | "submit-ai-game-feedback-response" | "create-match-history-replay-share-request" | "create-match-history-replay-share-response" | "shared-match-history-replay-response" | "match-chat-lookup-response" | "match-history-restore-request" | "restore-history-response" | "match-recovery-request" | "match-recovery-response" | "match-access-recovery-request" | "match-access-recovery-response" | "cards-response" | "resolve-card-ids-request" | "resolve-card-ids-response" | "client-message" | "server-message" | "game-command" | "game-event" | "game-state" | "match-connection-role" | "welcome-payload" | "error-payload" | "match-save-payload" | "save-match-request" | "restore-match-save-request" | "restore-match-save-response")[]

Schemas to compile; defaults to the SDK's connect-path roots.

Returns ​

void

Released under the MIT License.