@my-swu/simulator-client 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/connection.js +2 -3
- package/dist/generated/index.d.ts +10 -0
- package/dist/generated/schemas.d.ts +1 -1
- package/dist/generated/schemas.js +466 -59
- package/dist/generated/types/admin-match-debug-bundle.d.ts +1 -0
- package/dist/generated/types/admin-match-debug-bundle.js +2 -0
- package/dist/generated/types/admin-match-list-response.d.ts +1 -0
- package/dist/generated/types/admin-match-list-response.js +2 -0
- package/dist/generated/types/admin-match-replay-response.d.ts +1 -0
- package/dist/generated/types/admin-match-replay-response.js +2 -0
- package/dist/generated/types/common.d.ts +143 -15
- package/dist/generated/types/create-match-history-replay-share-request.d.ts +1 -0
- package/dist/generated/types/create-match-history-replay-share-request.js +2 -0
- package/dist/generated/types/create-match-history-replay-share-response.d.ts +1 -0
- package/dist/generated/types/create-match-history-replay-share-response.js +2 -0
- package/dist/generated/types/inactive-match-recovery-request.d.ts +1 -0
- package/dist/generated/types/inactive-match-recovery-request.js +2 -0
- package/dist/generated/types/inactive-match-recovery-response.d.ts +1 -0
- package/dist/generated/types/inactive-match-recovery-response.js +2 -0
- package/dist/generated/types/match-access-recovery-request.d.ts +1 -0
- package/dist/generated/types/match-access-recovery-request.js +2 -0
- package/dist/generated/types/match-access-recovery-response.d.ts +1 -0
- package/dist/generated/types/match-access-recovery-response.js +2 -0
- package/dist/generated/types/match-recovery-request.d.ts +1 -0
- package/dist/generated/types/match-recovery-request.js +2 -0
- package/dist/generated/types/match-recovery-response.d.ts +1 -0
- package/dist/generated/types/match-recovery-response.js +2 -0
- package/dist/generated/types/shared-match-history-replay-response.d.ts +1 -0
- package/dist/generated/types/shared-match-history-replay-response.js +2 -0
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/internal/match-history.d.ts +5 -0
- package/dist/internal/match-history.js +8 -0
- package/dist/local/engine.d.ts +2 -0
- package/dist/local/server/http-router.js +10 -0
- package/dist/local/wasm-engine.d.ts +1 -0
- package/dist/local/wasm-engine.js +1 -0
- package/dist/match-session/controller.d.ts +1 -0
- package/dist/match-session/controller.js +56 -17
- package/dist/match-session/methods.d.ts +8 -0
- package/dist/match-session/session-state.d.ts +5 -1
- package/dist/match-session/types.d.ts +1 -1
- package/dist/match-session.d.ts +1 -1
- package/dist/resources/admin.d.ts +14 -1
- package/dist/resources/admin.js +21 -0
- package/dist/resources/lobby-types.d.ts +4 -4
- package/dist/resources/match-history.d.ts +14 -1
- package/dist/resources/match-history.js +16 -0
- package/dist/resources/match-types.d.ts +11 -2
- package/dist/resources/matches.js +10 -0
- package/dist/validators.d.ts +11 -1
- package/package.json +1 -1
- package/schema/add-lobby-ai-player-request.schema.json +7 -0
- package/schema/admin-match-debug-bundle.schema.json +48 -0
- package/schema/admin-match-list-response.schema.json +23 -0
- package/schema/admin-match-replay-response.schema.json +14 -0
- package/schema/common.schema.json +176 -27
- package/schema/create-limited-event-request.schema.json +2 -4
- package/schema/create-lobby-request.schema.json +4 -8
- package/schema/create-match-history-replay-share-request.schema.json +22 -0
- package/schema/create-match-history-replay-share-response.schema.json +15 -0
- package/schema/create-match-request.schema.json +2 -3
- package/schema/create-tournament-room-request.schema.json +4 -8
- package/schema/limited-event-preflight-response.schema.json +1 -3
- package/schema/manifest.json +11 -1
- package/schema/match-access-recovery-request.schema.json +17 -0
- package/schema/match-access-recovery-response.schema.json +36 -0
- package/schema/match-access-response.schema.json +1 -3
- package/schema/match-history-entry.schema.json +1 -3
- package/schema/match-recovery-request.schema.json +33 -0
- package/schema/match-recovery-response.schema.json +36 -0
- package/schema/route-manifest.json +92 -0
- package/schema/shared-match-history-replay-response.schema.json +14 -0
|
@@ -2,6 +2,7 @@ import { MatchConnection } from '../connection.js';
|
|
|
2
2
|
import { TypedEmitter } from '../internal/emitter.js';
|
|
3
3
|
import { formatErrorMessages } from '../internal/errors.js';
|
|
4
4
|
import { DEFAULT_ERROR_HISTORY_LIMIT, DEFAULT_MATCH_HISTORY_LIMIT } from '../internal/limits.js';
|
|
5
|
+
import { upsertMatchHistoryEntry } from '../internal/match-history.js';
|
|
5
6
|
import { nonNegativeNumber, normalizeReconnectBackoff, reconnectDelayMs, } from '../internal/reconnect-backoff.js';
|
|
6
7
|
import { createMatchSessionHeartbeat } from './heartbeat.js';
|
|
7
8
|
import { hasAccessSnapshot, matchReferenceFrom } from './access.js';
|
|
@@ -207,6 +208,21 @@ export class MatchSessionController {
|
|
|
207
208
|
reconnect(options = {}) {
|
|
208
209
|
return this.connect(undefined, options);
|
|
209
210
|
}
|
|
211
|
+
recoverNow() {
|
|
212
|
+
if (this.#manualClose || !this.#autoReconnect.enabled || this.#access == null) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
this.#reconnectGeneration += 1;
|
|
216
|
+
if (this.#reconnectTimer != null) {
|
|
217
|
+
clearTimeout(this.#reconnectTimer);
|
|
218
|
+
this.#reconnectTimer = undefined;
|
|
219
|
+
}
|
|
220
|
+
// Detach before close so this intentional foreground replacement cannot
|
|
221
|
+
// schedule a duplicate close-driven retry.
|
|
222
|
+
this.#closeActiveConnection();
|
|
223
|
+
this.#setConnectionState('closed');
|
|
224
|
+
void this.#runAutoReconnectAttempt(1, this.#reconnectGeneration);
|
|
225
|
+
}
|
|
210
226
|
ready() {
|
|
211
227
|
this.#activeConnection().ready();
|
|
212
228
|
}
|
|
@@ -333,8 +349,7 @@ export class MatchSessionController {
|
|
|
333
349
|
this.#emitChange();
|
|
334
350
|
}
|
|
335
351
|
#recordHistoryEntry(entry) {
|
|
336
|
-
|
|
337
|
-
this.#history = [...withoutDuplicate, entry].slice(-DEFAULT_MATCH_HISTORY_LIMIT);
|
|
352
|
+
this.#history = upsertMatchHistoryEntry(this.#history, entry);
|
|
338
353
|
this.#emitter.emit('historyEntry', entry);
|
|
339
354
|
this.#emitChange();
|
|
340
355
|
}
|
|
@@ -368,15 +383,18 @@ export class MatchSessionController {
|
|
|
368
383
|
}
|
|
369
384
|
#scheduleAutoReconnect(attempt, generation) {
|
|
370
385
|
if (attempt > this.#autoReconnect.maxRetries) {
|
|
386
|
+
const error = {
|
|
387
|
+
code: 'sdk_session_error',
|
|
388
|
+
message: 'automatic reconnect exhausted',
|
|
389
|
+
};
|
|
371
390
|
this.#setReconnectState({
|
|
372
|
-
phase: '
|
|
391
|
+
phase: 'terminal',
|
|
373
392
|
attempts: this.#autoReconnect.maxRetries,
|
|
374
393
|
maxAttempts: this.#autoReconnect.maxRetries,
|
|
394
|
+
cause: 'retriesExhausted',
|
|
395
|
+
error,
|
|
375
396
|
});
|
|
376
|
-
this.#recordError(
|
|
377
|
-
code: 'sdk_session_error',
|
|
378
|
-
message: 'automatic reconnect exhausted',
|
|
379
|
-
});
|
|
397
|
+
this.#recordError(error);
|
|
380
398
|
return;
|
|
381
399
|
}
|
|
382
400
|
const delayMs = reconnectDelayMs(this.#autoReconnect, attempt);
|
|
@@ -418,17 +436,23 @@ export class MatchSessionController {
|
|
|
418
436
|
if (generation !== this.#reconnectGeneration || this.#manualClose) {
|
|
419
437
|
return;
|
|
420
438
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
439
|
+
const payload = errorPayloadFromUnknown(error);
|
|
440
|
+
const cause = terminalCauseForError(payload);
|
|
441
|
+
if (cause != null || attempt >= this.#autoReconnect.maxRetries) {
|
|
442
|
+
const terminalError = cause == null
|
|
443
|
+
? {
|
|
444
|
+
code: 'sdk_session_error',
|
|
445
|
+
message: 'automatic reconnect exhausted',
|
|
446
|
+
}
|
|
447
|
+
: payload;
|
|
427
448
|
this.#setReconnectState({
|
|
428
|
-
phase: '
|
|
449
|
+
phase: 'terminal',
|
|
429
450
|
attempts: attempt,
|
|
430
451
|
maxAttempts: this.#autoReconnect.maxRetries,
|
|
452
|
+
cause: cause ?? 'retriesExhausted',
|
|
453
|
+
error: terminalError,
|
|
431
454
|
});
|
|
455
|
+
this.#recordError(terminalError);
|
|
432
456
|
this.#setConnectionState('closed');
|
|
433
457
|
return;
|
|
434
458
|
}
|
|
@@ -556,9 +580,24 @@ function sameReconnectState(left, right) {
|
|
|
556
580
|
return right.phase === 'connecting'
|
|
557
581
|
&& left.attempt === right.attempt
|
|
558
582
|
&& left.maxAttempts === right.maxAttempts;
|
|
559
|
-
case '
|
|
560
|
-
return right.phase === '
|
|
583
|
+
case 'terminal':
|
|
584
|
+
return right.phase === 'terminal'
|
|
561
585
|
&& left.attempts === right.attempts
|
|
562
|
-
&& left.maxAttempts === right.maxAttempts
|
|
586
|
+
&& left.maxAttempts === right.maxAttempts
|
|
587
|
+
&& left.cause === right.cause
|
|
588
|
+
&& left.error.code === right.error.code
|
|
589
|
+
&& left.error.message === right.error.message;
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
/** Maps definitive server rejections to terminal causes without parsing text. */
|
|
593
|
+
function terminalCauseForError(error) {
|
|
594
|
+
switch (error.code) {
|
|
595
|
+
case 'match_not_found':
|
|
596
|
+
return 'matchNotFound';
|
|
597
|
+
case 'invalid_seat_token':
|
|
598
|
+
case 'invalid_spectator_token':
|
|
599
|
+
return 'invalidCredentials';
|
|
600
|
+
default:
|
|
601
|
+
return undefined;
|
|
563
602
|
}
|
|
564
603
|
}
|
|
@@ -159,6 +159,14 @@ export interface MatchSessionMethods {
|
|
|
159
159
|
* @see https://simulator-sdk.my-swu.com/guide/reconnect
|
|
160
160
|
*/
|
|
161
161
|
reconnect(options?: MatchSessionConnectOptions): Promise<MatchSession>;
|
|
162
|
+
/**
|
|
163
|
+
* Immediately starts session-owned automatic recovery using stored access.
|
|
164
|
+
*
|
|
165
|
+
* This is intended for foreground restoration: it preserves automatic
|
|
166
|
+
* backoff after a failed dial instead of turning recovery into a one-shot
|
|
167
|
+
* manual reconnect.
|
|
168
|
+
*/
|
|
169
|
+
recoverNow(): void;
|
|
162
170
|
/**
|
|
163
171
|
* Sends one ready message for the current seat.
|
|
164
172
|
*
|
|
@@ -132,10 +132,14 @@ export type MatchSessionReconnectState = {
|
|
|
132
132
|
attempt: number;
|
|
133
133
|
maxAttempts: number;
|
|
134
134
|
} | {
|
|
135
|
-
phase: '
|
|
135
|
+
phase: 'terminal';
|
|
136
136
|
attempts: number;
|
|
137
137
|
maxAttempts: number;
|
|
138
|
+
cause: MatchSessionTerminalCause;
|
|
139
|
+
error: ErrorPayload;
|
|
138
140
|
};
|
|
141
|
+
/** Server or transport condition which stopped automatic reconnect retries. */
|
|
142
|
+
export type MatchSessionTerminalCause = 'matchNotFound' | 'invalidCredentials' | 'retriesExhausted';
|
|
139
143
|
/**
|
|
140
144
|
* Options for creating one SDK-owned match session.
|
|
141
145
|
*
|
|
@@ -3,7 +3,7 @@ import type { MatchHistoryFeedEntry } from '../generated/types/server-message.js
|
|
|
3
3
|
import type { ConnectionState } from '../session.js';
|
|
4
4
|
import type { MatchSessionMethods } from './methods.js';
|
|
5
5
|
import type { MatchSeat, MatchSessionReconnectState, MatchSessionState } from './session-state.js';
|
|
6
|
-
export type { MatchSeat, MatchSessionAccess, MatchSessionAutoReconnectOptions, MatchSessionAutoReconnectPolicy, MatchSessionConnectOptions, MatchSessionEvents, MatchSessionHeartbeatOptions, MatchSessionHeartbeatPolicy, MatchSessionOptions, MatchSessionReconnectState, MatchSessionSnapshotPredicate, MatchSessionState, MatchSessionWaitOptions, } from './session-state.js';
|
|
6
|
+
export type { MatchSeat, MatchSessionAccess, MatchSessionAutoReconnectOptions, MatchSessionAutoReconnectPolicy, MatchSessionConnectOptions, MatchSessionEvents, MatchSessionHeartbeatOptions, MatchSessionHeartbeatPolicy, MatchSessionOptions, MatchSessionReconnectState, MatchSessionSnapshotPredicate, MatchSessionState, MatchSessionTerminalCause, MatchSessionWaitOptions, } from './session-state.js';
|
|
7
7
|
/**
|
|
8
8
|
* Main ergonomic SDK API for interacting with one live match.
|
|
9
9
|
*
|
package/dist/match-session.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { MatchSessionController } from './match-session/controller.js';
|
|
2
2
|
export type { MatchSessionControllerOptions } from './match-session/controller.js';
|
|
3
|
-
export type { MatchSeat, MatchSession, MatchSessionAccess, MatchSessionAutoReconnectOptions, MatchSessionAutoReconnectPolicy, MatchSessionConnectOptions, MatchSessionEvents, MatchSessionHeartbeatOptions, MatchSessionHeartbeatPolicy, MatchSessionOptions, MatchSessionReconnectState, MatchSessionSnapshotPredicate, MatchSessionState, MatchSessionWaitOptions, } from './match-session/types.js';
|
|
3
|
+
export type { MatchSeat, MatchSession, MatchSessionAccess, MatchSessionAutoReconnectOptions, MatchSessionAutoReconnectPolicy, MatchSessionConnectOptions, MatchSessionEvents, MatchSessionHeartbeatOptions, MatchSessionHeartbeatPolicy, MatchSessionOptions, MatchSessionReconnectState, MatchSessionTerminalCause, MatchSessionSnapshotPredicate, MatchSessionState, MatchSessionWaitOptions, } from './match-session/types.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SimulatorReportListResponse, SimulatorReportResponse, CardCatalogRefreshResponse, CreateMetaWindowRequest, MatchChatLookupResponse, MetaWindowsResponse, RankedLeaderboardQuery, RankedLeaderboardResponse, RankedProfileRequest, RankedProfileResponse, SetRankedAdmissionRequest, SetSimulatorMaintenanceRequest, SimulatorAdminStatusResponse } from '../generated/index.js';
|
|
1
|
+
import type { AdminMatchDebugBundle, AdminMatchListResponse, AdminMatchReplayResponse, SimulatorReportListResponse, SimulatorReportResponse, CardCatalogRefreshResponse, CreateMetaWindowRequest, MatchChatLookupResponse, MetaWindowsResponse, RankedLeaderboardQuery, RankedLeaderboardResponse, RankedProfileRequest, RankedProfileResponse, SetRankedAdmissionRequest, SetSimulatorMaintenanceRequest, SimulatorAdminStatusResponse } from '../generated/index.js';
|
|
2
2
|
import type { SimulatorRequestOptions } from '../http/options.js';
|
|
3
3
|
import type { EngineHttpRequester } from '../http/request.js';
|
|
4
4
|
/**
|
|
@@ -10,6 +10,13 @@ export interface SimulatorReportListOptions {
|
|
|
10
10
|
cursor?: string;
|
|
11
11
|
limit?: number;
|
|
12
12
|
}
|
|
13
|
+
/** Filters and cursor pagination controls for durable simulator admin games. */
|
|
14
|
+
export interface AdminGameListOptions {
|
|
15
|
+
matchId?: string;
|
|
16
|
+
playerSearch?: string;
|
|
17
|
+
cursor?: string;
|
|
18
|
+
limit?: number;
|
|
19
|
+
}
|
|
13
20
|
/**
|
|
14
21
|
* Bearer-token credentials for simulator admin calls.
|
|
15
22
|
*/
|
|
@@ -23,6 +30,12 @@ export interface SimulatorAdminAuth {
|
|
|
23
30
|
* Simulator administration API methods.
|
|
24
31
|
*/
|
|
25
32
|
export interface AdminResource {
|
|
33
|
+
/** Lists durable saved and completed matches for simulator support work. */
|
|
34
|
+
listGames(auth: SimulatorAdminAuth, query?: AdminGameListOptions, options?: SimulatorRequestOptions): Promise<AdminMatchListResponse>;
|
|
35
|
+
/** Returns all durable diagnostics for one match with restore credentials removed. */
|
|
36
|
+
getGameDebugBundle(auth: SimulatorAdminAuth, historyId: string, options?: SimulatorRequestOptions): Promise<AdminMatchDebugBundle>;
|
|
37
|
+
/** Returns a completed replay archive for one match. */
|
|
38
|
+
getGameReplay(auth: SimulatorAdminAuth, historyId: string, options?: SimulatorRequestOptions): Promise<AdminMatchReplayResponse>;
|
|
26
39
|
/** Lists safe metadata for retained simulator diagnostic reports. */
|
|
27
40
|
listSimulatorReports(auth: SimulatorAdminAuth, query?: SimulatorReportListOptions, options?: SimulatorRequestOptions): Promise<SimulatorReportListResponse>;
|
|
28
41
|
/** Returns one full sanitized simulator support bundle. */
|
package/dist/resources/admin.js
CHANGED
|
@@ -4,6 +4,9 @@ import { jsonBody, jsonHeaders } from '../http/json.js';
|
|
|
4
4
|
*/
|
|
5
5
|
export function createAdminResource(requester) {
|
|
6
6
|
return {
|
|
7
|
+
listGames: (auth, query, options) => requester.request('admin-match-list-response', adminGamesPath(query ?? {}), { headers: authHeaders(auth) }, options),
|
|
8
|
+
getGameDebugBundle: (auth, historyId, options) => requester.request('admin-match-debug-bundle', `/api/admin/games/${encodeURIComponent(historyId)}/debug`, { headers: authHeaders(auth) }, options),
|
|
9
|
+
getGameReplay: (auth, historyId, options) => requester.request('admin-match-replay-response', `/api/admin/games/${encodeURIComponent(historyId)}/replay`, { headers: authHeaders(auth) }, options),
|
|
7
10
|
listSimulatorReports: (auth, query, options) => requester.request('simulator-report-list-response', simulatorReportsPath(query ?? {}), { headers: authHeaders(auth) }, options),
|
|
8
11
|
getSimulatorReport: (auth, reportId, options) => requester.request('simulator-report-response', `/api/admin/reports/${encodeURIComponent(reportId)}`, { headers: authHeaders(auth) }, options),
|
|
9
12
|
refreshCardCatalog: (auth, options) => requester.request('card-catalog-refresh-response', '/api/admin/card-catalog/refresh', { headers: authHeaders(auth), method: 'POST' }, options),
|
|
@@ -34,6 +37,24 @@ export function createAdminResource(requester) {
|
|
|
34
37
|
rankedLeaderboard: (auth, windowId, query, options) => requester.request('ranked-leaderboard-response', leaderboardPath(requester, windowId, query ?? {}), { headers: authHeaders(auth) }, options),
|
|
35
38
|
};
|
|
36
39
|
}
|
|
40
|
+
/** Builds an encoded durable-game query without exposing the route shape. */
|
|
41
|
+
function adminGamesPath(options) {
|
|
42
|
+
const parameters = new URLSearchParams();
|
|
43
|
+
if (options.matchId) {
|
|
44
|
+
parameters.set('matchId', options.matchId);
|
|
45
|
+
}
|
|
46
|
+
if (options.playerSearch) {
|
|
47
|
+
parameters.set('playerSearch', options.playerSearch);
|
|
48
|
+
}
|
|
49
|
+
if (options.cursor) {
|
|
50
|
+
parameters.set('cursor', options.cursor);
|
|
51
|
+
}
|
|
52
|
+
if (options.limit != null) {
|
|
53
|
+
parameters.set('limit', String(options.limit));
|
|
54
|
+
}
|
|
55
|
+
const suffix = parameters.size === 0 ? '' : `?${parameters.toString()}`;
|
|
56
|
+
return `/api/admin/games${suffix}`;
|
|
57
|
+
}
|
|
37
58
|
/** Builds a report-list path without exposing pagination implementation. */
|
|
38
59
|
function simulatorReportsPath(options) {
|
|
39
60
|
const parameters = new URLSearchParams();
|
|
@@ -62,9 +62,9 @@ export type LobbyConfig = {
|
|
|
62
62
|
export interface CreateLobbyRequest {
|
|
63
63
|
config: LobbyConfig;
|
|
64
64
|
/** Fixed limited pack/leader seed. */
|
|
65
|
-
packSeed?:
|
|
65
|
+
packSeed?: string | null;
|
|
66
66
|
/** Fixed match seed reused for limited duel matches. */
|
|
67
|
-
matchSeed?:
|
|
67
|
+
matchSeed?: string | null;
|
|
68
68
|
/** Whether the lobby should appear in public browsing surfaces. */
|
|
69
69
|
visibility: LobbyVisibility;
|
|
70
70
|
hostName: string;
|
|
@@ -183,9 +183,9 @@ export interface LobbySnapshot {
|
|
|
183
183
|
visibility: LobbyVisibility;
|
|
184
184
|
config: LobbyConfig;
|
|
185
185
|
/** Fixed limited pack/leader seed when configured. */
|
|
186
|
-
packSeed?:
|
|
186
|
+
packSeed?: string | null;
|
|
187
187
|
/** Fixed match seed when configured. */
|
|
188
|
-
matchSeed?:
|
|
188
|
+
matchSeed?: string | null;
|
|
189
189
|
hostPlayerId: string;
|
|
190
190
|
requiredPlayerCount: number;
|
|
191
191
|
/** Absolute server deadline for the ready-lobby auto-start countdown. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MatchHistoryDeckStatsRequest, MatchHistoryDeckStatsResponse, MatchHistoryListRequest, MatchHistoryListResponse, MatchHistoryReplayRequest, MatchHistoryReplayResponse, MatchHistoryRestoreRequest, RestoreHistoryResponse } from '../generated/index.js';
|
|
1
|
+
import type { CreateMatchHistoryReplayShareRequest, CreateMatchHistoryReplayShareResponse, MatchRecoveryRequest, MatchRecoveryResponse, MatchHistoryDeckStatsRequest, MatchHistoryDeckStatsResponse, MatchHistoryListRequest, MatchHistoryListResponse, MatchHistoryReplayRequest, MatchHistoryReplayResponse, MatchHistoryRestoreRequest, RestoreHistoryResponse, SharedMatchHistoryReplayResponse } from '../generated/index.js';
|
|
2
2
|
import type { SimulatorRequestOptions } from '../http/options.js';
|
|
3
3
|
import type { EngineHttpRequester } from '../http/request.js';
|
|
4
4
|
/**
|
|
@@ -10,11 +10,18 @@ export interface MatchHistoryRestoreInput extends MatchHistoryRestoreRequest {
|
|
|
10
10
|
*/
|
|
11
11
|
historyId: string;
|
|
12
12
|
}
|
|
13
|
+
/** Recovery request for a source runtime that is no longer available. */
|
|
14
|
+
export type MatchRecoveryInput = MatchRecoveryRequest;
|
|
13
15
|
/** Request used to load a completed server-side replay archive. */
|
|
14
16
|
export interface MatchHistoryReplayInput extends MatchHistoryReplayRequest {
|
|
15
17
|
/** Durable history row id returned by {@link MatchHistoryResource.list}. */
|
|
16
18
|
historyId: string;
|
|
17
19
|
}
|
|
20
|
+
/** Participant-authorized request that creates one scoped replay-share link. */
|
|
21
|
+
export interface CreateMatchHistoryReplayShareInput extends CreateMatchHistoryReplayShareRequest {
|
|
22
|
+
/** Durable history row id returned by {@link MatchHistoryResource.list}. */
|
|
23
|
+
historyId: string;
|
|
24
|
+
}
|
|
18
25
|
/**
|
|
19
26
|
* Server-owned simulator history APIs.
|
|
20
27
|
*/
|
|
@@ -29,10 +36,16 @@ export interface MatchHistoryResource {
|
|
|
29
36
|
list(request: MatchHistoryListRequest, options?: SimulatorRequestOptions): Promise<MatchHistoryListResponse>;
|
|
30
37
|
/** Loads public and post-game reveal-all frames for an authorized result. */
|
|
31
38
|
replay(request: MatchHistoryReplayInput, options?: SimulatorRequestOptions): Promise<MatchHistoryReplayResponse>;
|
|
39
|
+
/** Creates or returns a stable opaque replay link for one disclosure scope. */
|
|
40
|
+
createReplayShare(request: CreateMatchHistoryReplayShareInput, options?: SimulatorRequestOptions): Promise<CreateMatchHistoryReplayShareResponse>;
|
|
41
|
+
/** Loads a replay through an opaque link without participant identities. */
|
|
42
|
+
loadReplayShare(shareToken: string, options?: SimulatorRequestOptions): Promise<SharedMatchHistoryReplayResponse>;
|
|
32
43
|
/**
|
|
33
44
|
* Restores one authorized row whose eligibility is `available`.
|
|
34
45
|
*/
|
|
35
46
|
restore(request: MatchHistoryRestoreInput, options?: SimulatorRequestOptions): Promise<RestoreHistoryResponse>;
|
|
47
|
+
/** Restores an owned Solo-versus-AI source after its runtime is lost. */
|
|
48
|
+
recover(request: MatchRecoveryInput, options?: SimulatorRequestOptions): Promise<MatchRecoveryResponse>;
|
|
36
49
|
}
|
|
37
50
|
/**
|
|
38
51
|
* Dependencies needed by the match-history resource.
|
|
@@ -22,6 +22,17 @@ export function createMatchHistoryResource(options) {
|
|
|
22
22
|
headers: jsonHeaders(),
|
|
23
23
|
method: 'POST',
|
|
24
24
|
}, options),
|
|
25
|
+
createReplayShare: (request, options) => requester.request('create-match-history-replay-share-response', `/api/match-history/${request.historyId}/replay-shares`, {
|
|
26
|
+
body: jsonBody(requester.validate('create-match-history-replay-share-request', {
|
|
27
|
+
identities: request.identities,
|
|
28
|
+
includeHiddenInformation: request.includeHiddenInformation,
|
|
29
|
+
})),
|
|
30
|
+
headers: jsonHeaders(),
|
|
31
|
+
method: 'POST',
|
|
32
|
+
}, options),
|
|
33
|
+
loadReplayShare: (shareToken, options) => requester.request('shared-match-history-replay-response', `/api/match-history/replay-shares/${shareToken}`, {
|
|
34
|
+
method: 'GET',
|
|
35
|
+
}, options),
|
|
25
36
|
restore: (request, options) => requester.request('restore-history-response', `/api/match-history/${request.historyId}/restore`, {
|
|
26
37
|
body: jsonBody(requester.validate('match-history-restore-request', {
|
|
27
38
|
identities: request.identities,
|
|
@@ -30,5 +41,10 @@ export function createMatchHistoryResource(options) {
|
|
|
30
41
|
headers: jsonHeaders(),
|
|
31
42
|
method: 'POST',
|
|
32
43
|
}, options),
|
|
44
|
+
recover: (request, options) => requester.request('match-recovery-response', '/api/match-history/recover', {
|
|
45
|
+
body: jsonBody(requester.validate('match-recovery-request', request)),
|
|
46
|
+
headers: jsonHeaders(),
|
|
47
|
+
method: 'POST',
|
|
48
|
+
}, options),
|
|
33
49
|
};
|
|
34
50
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AiStatusPayload, CreateMatchRequest, GameState, JoinMatchRequest, ListActiveAiMatchesRequest, ListActiveAiMatchesResponse, MatchAccessResponse, MatchSpectatorAccessResponse, MatchSavePayload, RematchMatchResponse, RestoreMatchSaveResponse, SpectateMatchRequest, SubmitMatchDeckRequest } from '../generated/index.js';
|
|
1
|
+
import type { AiStatusPayload, CreateMatchRequest, GameState, JoinMatchRequest, ListActiveAiMatchesRequest, ListActiveAiMatchesResponse, MatchAccessRecoveryRequest, MatchAccessRecoveryResponse, MatchAccessResponse, MatchSpectatorAccessResponse, MatchSavePayload, RematchMatchResponse, RestoreMatchSaveResponse, SpectateMatchRequest, SubmitMatchDeckRequest } from '../generated/index.js';
|
|
2
2
|
import type { FormatEventCommand } from '../generated/types/format-event-request.js';
|
|
3
3
|
import type { SimulatorRequestOptions } from '../http/options.js';
|
|
4
4
|
/**
|
|
@@ -87,7 +87,7 @@ export interface MatchAccessInput extends MatchReference {
|
|
|
87
87
|
/**
|
|
88
88
|
* Resolved seed for a private solo-vs-AI match, retained across reconnects.
|
|
89
89
|
*/
|
|
90
|
-
replaySeed?:
|
|
90
|
+
replaySeed?: string;
|
|
91
91
|
}
|
|
92
92
|
export interface MatchSpectatorAccessInput extends MatchReference {
|
|
93
93
|
/**
|
|
@@ -134,6 +134,15 @@ export type MatchConnectionAccessInput = MatchAccessInput | MatchSpectatorAccess
|
|
|
134
134
|
* @see https://simulator-sdk.my-swu.com/guide/match-session
|
|
135
135
|
*/
|
|
136
136
|
export interface MatchesResource {
|
|
137
|
+
/** Refreshes private seat access after validating its existing seat token. */
|
|
138
|
+
refreshAccess(access: MatchAccessInput, options?: SimulatorRequestOptions): Promise<MatchAccess>;
|
|
139
|
+
/**
|
|
140
|
+
* Recovers current host access for an owned remote Solo-versus-AI match.
|
|
141
|
+
*
|
|
142
|
+
* `unavailable` intentionally hides whether the match is absent, no longer
|
|
143
|
+
* resumable, or not owned by the supplied history identities.
|
|
144
|
+
*/
|
|
145
|
+
recoverAccess(match: MatchReference, request: MatchAccessRecoveryRequest, options?: SimulatorRequestOptions): Promise<MatchAccessRecoveryResponse>;
|
|
137
146
|
/** Records an intentional player departure without conceding the match. */
|
|
138
147
|
leave(access: MatchAccessInput, options?: SimulatorRequestOptions): Promise<void>;
|
|
139
148
|
/**
|
|
@@ -5,6 +5,16 @@ import { jsonBody, jsonHeaders } from '../http/json.js';
|
|
|
5
5
|
export function createMatchesResource(options) {
|
|
6
6
|
const { requester } = options;
|
|
7
7
|
return {
|
|
8
|
+
refreshAccess: (access, requestOptions) => requester.request('match-access-response', `/api/matches/${matchIdFrom(access)}/access`, {
|
|
9
|
+
body: jsonBody(requester.validate('save-match-request', { seatToken: access.seatToken })),
|
|
10
|
+
headers: jsonHeaders(),
|
|
11
|
+
method: 'POST',
|
|
12
|
+
}, requestOptions),
|
|
13
|
+
recoverAccess: (match, request, options) => requester.request('match-access-recovery-response', `/api/matches/${matchIdFrom(match)}/recover-access`, {
|
|
14
|
+
body: jsonBody(requester.validate('match-access-recovery-request', request)),
|
|
15
|
+
headers: jsonHeaders(),
|
|
16
|
+
method: 'POST',
|
|
17
|
+
}, options),
|
|
8
18
|
leave: (access, options) => requester.request('leave-match-response', `/api/matches/${matchIdFrom(access)}/leave`, {
|
|
9
19
|
body: jsonBody(requester.validate('leave-match-request', { seatToken: access.seatToken })),
|
|
10
20
|
headers: jsonHeaders(),
|
package/dist/validators.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SimulatorReportListResponse, SimulatorReportResponse, CloseTournamentRoomRequest, AbandonMatchRequest, AbandonMatchResponse, AddLobbyAiPlayerRequest, ApiErrorResponse, CardCatalogRefreshResponse, CardsResponse, ClientMessage, CreateLimitedEventRequest, CreateLobbyRequest, CreateMetaWindowRequest, CreateMatchRequest, CreateTournamentRoomRequest, CreateTournamentTableRequest, ErrorPayload, FormatEventRequest, FormatEventResponse, GameCommand, GameEvent, GameState, GetMatchResponse, HealthResponse, JoinLimitedEventRequest, JoinLobbyRequest, JoinMatchRequest, JoinTournamentRoomRequest, JoinTournamentTableRequest, KickLobbyPlayerRequest, KickLobbySpectatorRequest, LeaveLobbyRequest, LeaveMatchRequest, LeaveMatchResponse, LeaveTournamentRoomRequest, LimitedEventAccessResponse, LimitedEventCommandRequest, LimitedEventPreflightResponse, LimitedEventResponse, LobbyAccessResponse, LobbyChatRequest, LobbyChatResponse, LobbyListResponse, LobbyListServerMessage, LobbyMatchmakingDecisionRequest, PrepareLobbyLimitedAiDecksRequest, LobbyResponse, LobbyServerMessage, LobbySyncRequest, ListActiveAiMatchesRequest, ListActiveAiMatchesResponse, MatchAccessResponse, MatchChatLookupResponse, MatchConnectionRole, MatchHistoryDeckStatsRequest, MatchHistoryDeckStatsResponse, MatchHistoryEntry, MatchHistoryListRequest, MatchHistoryListResponse, MatchHistoryReplayRequest, MatchHistoryReplayResponse, MatchHistoryRestoreRequest, RestoreHistoryResponse, MatchSavePayload, MatchSpectatorAccessResponse, MetaWindow, MetaWindowsResponse, LobbyMatchmakingRequest, ResolveCardIdsRequest, ResolveCardIdsResponse, RankedAdminStatus, RankedLeaderboardEntry, RankedLeaderboardQuery, RankedLeaderboardResponse, RankedMatchmakingView, RankedProfileRequest, RankedProfileResponse, RankedQueue, RematchMatchRequest, RematchMatchResponse, SaveMatchRequest, ReturnLobbyMatchRequest, ReturnTournamentMatchRequest, RestoreMatchSaveRequest, RestoreMatchSaveResponse, ServerMessage, AiStatusPayload, SetRankedAdmissionRequest, SetSimulatorMaintenanceRequest, SetAiPausedRequest, SimulatorAdminStatusResponse, SimulatorAvailabilityResponse, SpectateLobbyRequest, SpectateMatchRequest, StartLobbyLimitedMatchRequest, StartLobbyRequest, StartTournamentEventRequest, SubmitLobbyLimitedDeckRequest, SubmitMatchDeckRequest, SubmitMatchDeckResponse, SubmitTournamentDeckRequest, TournamentEventCommandRequest, TournamentRoomAccessResponse, TournamentRoomChatRequest, TournamentRoomChatResponse, TournamentRoomListResponse, TournamentRoomResponse, TournamentRoomServerMessage, TournamentRoomSyncRequest, UndoMatchRequest, UndoMatchResponse, UndoRespondMatchRequest, UpdateLobbyAiPlayerRequest, UpdateLobbyPlayerRequest, UpdateLobbySettingsRequest, UpdateTournamentRoomPlayerRequest, UpdateTournamentRoomSettingsRequest, WelcomePayload } from './generated/index.js';
|
|
1
|
+
import type { AdminMatchDebugBundle, AdminMatchListResponse, AdminMatchReplayResponse, SimulatorReportListResponse, SimulatorReportResponse, CloseTournamentRoomRequest, AbandonMatchRequest, AbandonMatchResponse, AddLobbyAiPlayerRequest, ApiErrorResponse, CardCatalogRefreshResponse, CardsResponse, ClientMessage, CreateMatchHistoryReplayShareRequest, CreateMatchHistoryReplayShareResponse, CreateLimitedEventRequest, CreateLobbyRequest, CreateMetaWindowRequest, CreateMatchRequest, CreateTournamentRoomRequest, CreateTournamentTableRequest, ErrorPayload, FormatEventRequest, FormatEventResponse, GameCommand, GameEvent, GameState, GetMatchResponse, HealthResponse, JoinLimitedEventRequest, JoinLobbyRequest, JoinMatchRequest, JoinTournamentRoomRequest, JoinTournamentTableRequest, KickLobbyPlayerRequest, KickLobbySpectatorRequest, LeaveLobbyRequest, LeaveMatchRequest, LeaveMatchResponse, LeaveTournamentRoomRequest, LimitedEventAccessResponse, LimitedEventCommandRequest, LimitedEventPreflightResponse, LimitedEventResponse, LobbyAccessResponse, LobbyChatRequest, LobbyChatResponse, LobbyListResponse, LobbyListServerMessage, LobbyMatchmakingDecisionRequest, PrepareLobbyLimitedAiDecksRequest, LobbyResponse, LobbyServerMessage, LobbySyncRequest, ListActiveAiMatchesRequest, ListActiveAiMatchesResponse, MatchAccessRecoveryRequest, MatchAccessRecoveryResponse, MatchAccessResponse, MatchChatLookupResponse, MatchConnectionRole, MatchHistoryDeckStatsRequest, MatchHistoryDeckStatsResponse, MatchHistoryEntry, MatchHistoryListRequest, MatchHistoryListResponse, MatchHistoryReplayRequest, MatchHistoryReplayResponse, MatchHistoryRestoreRequest, MatchRecoveryRequest, MatchRecoveryResponse, RestoreHistoryResponse, MatchSavePayload, MatchSpectatorAccessResponse, MetaWindow, MetaWindowsResponse, LobbyMatchmakingRequest, ResolveCardIdsRequest, ResolveCardIdsResponse, RankedAdminStatus, RankedLeaderboardEntry, RankedLeaderboardQuery, RankedLeaderboardResponse, RankedMatchmakingView, RankedProfileRequest, RankedProfileResponse, RankedQueue, RematchMatchRequest, RematchMatchResponse, SaveMatchRequest, ReturnLobbyMatchRequest, ReturnTournamentMatchRequest, RestoreMatchSaveRequest, RestoreMatchSaveResponse, ServerMessage, AiStatusPayload, SetRankedAdmissionRequest, SetSimulatorMaintenanceRequest, SetAiPausedRequest, SharedMatchHistoryReplayResponse, SimulatorAdminStatusResponse, SimulatorAvailabilityResponse, SpectateLobbyRequest, SpectateMatchRequest, StartLobbyLimitedMatchRequest, StartLobbyRequest, StartTournamentEventRequest, SubmitLobbyLimitedDeckRequest, SubmitMatchDeckRequest, SubmitMatchDeckResponse, SubmitTournamentDeckRequest, TournamentEventCommandRequest, TournamentRoomAccessResponse, TournamentRoomChatRequest, TournamentRoomChatResponse, TournamentRoomListResponse, TournamentRoomResponse, TournamentRoomServerMessage, TournamentRoomSyncRequest, UndoMatchRequest, UndoMatchResponse, UndoRespondMatchRequest, UpdateLobbyAiPlayerRequest, UpdateLobbyPlayerRequest, UpdateLobbySettingsRequest, UpdateTournamentRoomPlayerRequest, UpdateTournamentRoomSettingsRequest, WelcomePayload } from './generated/index.js';
|
|
2
2
|
import type { SchemaValidator } from './validators/validator.js';
|
|
3
3
|
/**
|
|
4
4
|
* Exact schema-to-type map generated from Rust public wire contracts.
|
|
@@ -9,6 +9,9 @@ import type { SchemaValidator } from './validators/validator.js';
|
|
|
9
9
|
* @see https://simulator-sdk.my-swu.com/guide/versioning
|
|
10
10
|
*/
|
|
11
11
|
export interface SchemaTypeMap {
|
|
12
|
+
'admin-match-list-response': AdminMatchListResponse;
|
|
13
|
+
'admin-match-debug-bundle': AdminMatchDebugBundle;
|
|
14
|
+
'admin-match-replay-response': AdminMatchReplayResponse;
|
|
12
15
|
'simulator-report-list-response': SimulatorReportListResponse;
|
|
13
16
|
'simulator-report-response': SimulatorReportResponse;
|
|
14
17
|
'close-tournament-room-request': CloseTournamentRoomRequest;
|
|
@@ -69,8 +72,15 @@ export interface SchemaTypeMap {
|
|
|
69
72
|
'match-history-list-response': MatchHistoryListResponse;
|
|
70
73
|
'match-history-replay-request': MatchHistoryReplayRequest;
|
|
71
74
|
'match-history-replay-response': MatchHistoryReplayResponse;
|
|
75
|
+
'create-match-history-replay-share-request': CreateMatchHistoryReplayShareRequest;
|
|
76
|
+
'create-match-history-replay-share-response': CreateMatchHistoryReplayShareResponse;
|
|
77
|
+
'shared-match-history-replay-response': SharedMatchHistoryReplayResponse;
|
|
72
78
|
'match-history-restore-request': MatchHistoryRestoreRequest;
|
|
73
79
|
'restore-history-response': RestoreHistoryResponse;
|
|
80
|
+
'match-recovery-request': MatchRecoveryRequest;
|
|
81
|
+
'match-recovery-response': MatchRecoveryResponse;
|
|
82
|
+
'match-access-recovery-request': MatchAccessRecoveryRequest;
|
|
83
|
+
'match-access-recovery-response': MatchAccessRecoveryResponse;
|
|
74
84
|
'match-save-payload': MatchSavePayload;
|
|
75
85
|
'save-match-request': SaveMatchRequest;
|
|
76
86
|
'match-spectator-access-response': MatchSpectatorAccessResponse;
|
package/package.json
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
"title": "AddLobbyAiPlayerRequest",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
6
|
+
"accountToken": {
|
|
7
|
+
"description": "Signed app account proof required to create a server-controlled AI.",
|
|
8
|
+
"type": [
|
|
9
|
+
"string",
|
|
10
|
+
"null"
|
|
11
|
+
]
|
|
12
|
+
},
|
|
6
13
|
"deck": {
|
|
7
14
|
"$ref": "https://simulator-sdk.my-swu.com/schema/common.json#/$defs/DeckInput"
|
|
8
15
|
},
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "AdminMatchDebugBundle",
|
|
4
|
+
"description": "Complete durable diagnostics for one match, excluding restore credentials.",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"exportVersion": {
|
|
8
|
+
"type": "integer",
|
|
9
|
+
"format": "uint8",
|
|
10
|
+
"maximum": 255,
|
|
11
|
+
"minimum": 0
|
|
12
|
+
},
|
|
13
|
+
"exportedAtMs": {
|
|
14
|
+
"type": "integer",
|
|
15
|
+
"format": "uint64",
|
|
16
|
+
"minimum": 0
|
|
17
|
+
},
|
|
18
|
+
"game": {
|
|
19
|
+
"$ref": "https://simulator-sdk.my-swu.com/schema/common.json#/$defs/AdminMatchSummary"
|
|
20
|
+
},
|
|
21
|
+
"replay": {
|
|
22
|
+
"anyOf": [
|
|
23
|
+
{
|
|
24
|
+
"$ref": "https://simulator-sdk.my-swu.com/schema/common.json#/$defs/MatchHistoryReplayArchive"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"type": "null"
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
"reports": {
|
|
32
|
+
"type": "array",
|
|
33
|
+
"items": {
|
|
34
|
+
"$ref": "https://simulator-sdk.my-swu.com/schema/common.json#/$defs/SimulatorReportResponse"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"save": {
|
|
38
|
+
"$ref": "https://simulator-sdk.my-swu.com/schema/common.json#/$defs/MatchSavePayload"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"required": [
|
|
42
|
+
"exportVersion",
|
|
43
|
+
"exportedAtMs",
|
|
44
|
+
"game",
|
|
45
|
+
"save",
|
|
46
|
+
"reports"
|
|
47
|
+
]
|
|
48
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "AdminMatchListResponse",
|
|
4
|
+
"description": "Cursor-paginated durable match list for simulator administrators.",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"games": {
|
|
8
|
+
"type": "array",
|
|
9
|
+
"items": {
|
|
10
|
+
"$ref": "https://simulator-sdk.my-swu.com/schema/common.json#/$defs/AdminMatchSummary"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"nextCursor": {
|
|
14
|
+
"type": [
|
|
15
|
+
"string",
|
|
16
|
+
"null"
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"required": [
|
|
21
|
+
"games"
|
|
22
|
+
]
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "AdminMatchReplayResponse",
|
|
4
|
+
"description": "Completed replay archive returned to an authenticated simulator administrator.",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"archive": {
|
|
8
|
+
"$ref": "https://simulator-sdk.my-swu.com/schema/common.json#/$defs/MatchHistoryReplayArchive"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"required": [
|
|
12
|
+
"archive"
|
|
13
|
+
]
|
|
14
|
+
}
|