@diffenderfer-games/hub 2.0.0-next.4 → 2.0.0-next.5
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/CHANGELOG.md +8 -0
- package/dist/auto.d.ts +2 -2
- package/dist/auto.js +2 -2
- package/dist/doctor/cli.mjs +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/shared/client-version.gen.js +1 -1
- package/dist/shared/daily.js +1 -1
- package/dist/shared/index.d.ts +36 -5
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/src.js +167 -25
- package/dist/shared/src.js.map +1 -1
- package/package.json +2 -2
- package/src/core/connection.ts +1 -0
- package/src/core/errors.ts +8 -1
- package/src/core/hub-progress.ts +44 -8
- package/src/core/offline/cloud-saves.ts +62 -0
- package/src/core/offline/hub-kinds/index.ts +5 -3
- package/src/core/offline/hub-kinds/progress-kinds.ts +21 -4
- package/src/core/offline/local-store.ts +46 -1
- package/src/core/version/client-version.gen.ts +1 -1
- package/src/index.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @diffenderfer-games/hub
|
|
2
2
|
|
|
3
|
+
## 2.0.0-next.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7585522: Saves offline no longer risk the cloud copy. Offline, `getSave(slot)` rejects with a `HubError` whose `code` is `save_unknown` (new export `SAVE_UNKNOWN_CODE`; `isOffline` is `true`) when the device has never seen the hub's copy of that slot, instead of answering `save: null`; it still answers from the device's copy after a snapshot (`prefetchAll`), an online read, a landed write, or for a slot the device wrote and has queued. A `putSave` replayed from the offline queue now sends `base`, the slot's `updatedAt` on the hub as the device last saw it, and the hub refuses it with 409 `save_conflict` when another device saved since (dropped and reported in the `hub:sync` conflicts); writes sent at once while online are unchanged. The client also remembers the signed-in user from `login`, `signup`, `claim` and `ensureGuest` replies, and forgets it on `logout`. Contract: `writeSave` takes an optional `base` and may answer 409; new error code `save_conflict`. Older clients (no `base`) behave as before. See docs/hub.md "Saves offline".
|
|
8
|
+
- Updated dependencies [7585522]
|
|
9
|
+
- @diffenderfer-games/hub-contract@2.0.0-next.5
|
|
10
|
+
|
|
3
11
|
## 2.0.0-next.4
|
|
4
12
|
|
|
5
13
|
### Minor Changes
|
package/dist/auto.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { a as RaceHistoryQuery, c as RaceRuntimeApi, i as RaceEvents, l as RaceS
|
|
|
8
8
|
import { f as raceForwarder } from "./shared/race.js";
|
|
9
9
|
import { n as roomsForwarder } from "./shared/rooms.js";
|
|
10
10
|
import { $ as HubNotifyApi, A as RacerState, B as SuggestionStatus, C as RaceRecord, D as RaceStats, E as RaceState, F as ReportReason, G as REALTIME_READY_EVENT, H as isRealtimeApi, I as RoomInfo, J as RealtimeHubLink, K as REALTIME_SINGLETON_API, L as SocialConfig, M as Relation, N as ReportInput, O as Racer, P as ReportKind, Q as socialForwarder, R as SocialMe, S as RaceParams, T as RaceStatValue, U as REALTIME_FAILED_EVENT, V as findRealtimeApi, W as REALTIME_FEATURE_VERSION, X as notifyForwarder, Y as linkRealtimeToHub, Z as presenceForwarder, _ as PlayerLite, a as ErrorBody, at as SocialCounts, b as PresenceKind, c as JoinInfo, d as Message, et as HubPresenceApi, f as MessagesPage, g as PlayerCard, h as Party, i as Counts, it as PlayerRef, j as RecentPlayer, k as RacerResult, l as Launch, m as NotifyPrefs, n as ChatMode, nt as OpenInviteOptions, o as FriendEntry, ot as SocialEvents, p as NotifyChange, q as RealtimeApi, r as Conversation, rt as PlayOnlineMethods, s as Invite, t as Audience, tt as HubSocialApi, u as LaunchTicket, v as Presence, w as RaceResult, x as RaceOutcome, y as PresenceInput, z as Suggestion } from "./shared/social.js";
|
|
11
|
-
import { $ as
|
|
11
|
+
import { $ as GameInfo, A as StatResult, B as OUTBOX_MAX_ENTRIES, C as GrantBundle, Ct as EndpointName, D as TradeNoteOptions, E as TradeListOptions, F as OfflineEventDetails, G as ProfilePatch, H as OfflineKindDefinition, I as OfflineEventName, J as QueuedScoreOptions, K as QueueOp, L as OfflineListener, M as SyncResult, N as OfflineApi, O as AuthResponse, P as OUTBOX_FULL_CODE, Q as GameAnalytics, R as OfflineOp, S as HubMenuControl, St as EndpointFields, T as TradeId, Tt as GamePayload, U as ReplayContext, V as OfflineHandler, W as CLIENT_VERSION_HEADER, X as Board, Y as BufferedEvent, Z as BoardWithTop, _ as ResumeEntry, _t as SortDir, a as HubErrorDetails, at as Inventory, b as ResumeRun, bt as SubmitScoreResult, c as UNSUPPORTED_BY_HUB, ct as LeaderboardEntry, d as hub, dt as Metrics, et as GameLeaderboards, f as ClientSupport, ft as Profile, g as ResumeBlocker, gt as SnapshotResponse, h as RESUME_MAX_STATE_BYTES, ht as SaveMeta, i as HubErrorCode, it as HubStatus, j as SyncConflict, k as ProfileUpdate, l as Hub, lt as LeaderboardResult, m as RESUME_DEBOUNCE_MS, mt as Save, n as ContentRejectedError, nt as GlobalAnalytics, o as OfflineError, ot as InventorySnapshot, p as HubResume, pt as ProfileSummary, q as QueueOpInput, r as HubError, rt as HubOptions, s as SAVE_UNKNOWN_CODE, st as Json, t as HUB_CLIENT_VERSION, tt as GameRecords, u as createHub, ut as MeResponse, v as ResumeLoadOptions, vt as Stats, w as TradeBundle, wt as EndpointReply, x as ResumeSaveInput, xt as User, y as ResumeProgress, yt as SubmitScoreOptions, z as OUTBOX_MAX_CHARS } from "./shared/index.js";
|
|
12
12
|
//#region src/auto.d.ts
|
|
13
13
|
/** What `window.HubSDK` holds. */
|
|
14
14
|
export interface HubSdkGlobal {
|
|
@@ -32,5 +32,5 @@ declare global {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
//#endregion
|
|
35
|
-
export { type Anchor, type Audience, type AuthResponse, type AutoPauseOptions, type AxisDef, type AxisSide, type Board, type BoardWithTop, type BufferedEvent, type BusyOptions, CLIENT_VERSION_HEADER, type ChatMode, type ClientSupport, ContentRejectedError, type Conversation, type Counts, DAILY_SINGLETON_API, DAILY_START_EVENT, type DailyAll, type DailyChallenge, type DailyCompleteResponse, type DailyCompletion, type DailyCompletionMeta, type DailyCompletions, type DailyDefinition, type DailyEventDetail, type DailyGameStatus, type DailyHost, type DailyStartResponse, type DailyStatus, DailySystem, type DraggedSpot, type EdgeOffsets, type EndpointFields, type EndpointName, type EndpointReply, type ErrorBody, FOCUS_RING_SHADOW, type FriendEntry, type GameAnalytics, type GameInfo, type GameLeaderboards, type GamePayload, type GameRecords, type GamepadMapping, type GlobalAnalytics, type GrantBundle, type GroupDef, HUB_CLIENT_VERSION, Hub, HubError, type HubErrorCode, type HubErrorDetails, type HubMenuControl, type HubMpApi, type HubNotifyApi, type HubOptions, type HubPresenceApi, type HubRaceApi, HubResume, type HubRoom, type HubRoomsApi, type HubSocialApi, type HubStatus, INPUT_SINGLETON_API, type InputConfig, type InputDef, type InputEvents, type InputHost, type InputModality, type InputOptions, type InputOverrides, type InputReading, type InputSource, InputSystem, type InputSystemOptions, type Insets, type Inventory, type InventorySnapshot, type Invite, type InviteCreated, type InviteLink, type InviteLinkMethods, type InviteOptions, type InviteResult, type JoinInfo, type JoinInfoEvent, type JoinOptions, type Json, type Launch, type LaunchTicket, type LayoutBox, type LayoutItem, type LayoutOptions, type LeaderboardEntry, type LeaderboardResult, MODALITY_ATTRIBUTE, type MeResponse, type MenuBridge, type Message, type MessagesPage, type Metrics, type MouseMapping, type NavBlurEvent, type NavElement, type NavElementKind, type NavFocusEvent, type NavTarget, type NavigableDef, type Notice, type NotifyChange, type NotifyPrefs, OUTBOX_FULL_CODE, OUTBOX_MAX_CHARS, OUTBOX_MAX_ENTRIES, OfflineApi, OfflineError, type OfflineEventDetails, type OfflineEventName, type OfflineHandler, type OfflineKindDefinition, type OfflineListener, type OfflineOp, type OpenInviteOptions, Overlay, type OverlayEdge, type OverlayEvent, type OverlayListener, type OverlayReason, type PageInputControl, type Party, type PlayOnlineMethods, type PlayerCard, type PlayerLite, type PlayerRef, type Presence, type PresenceInput, type PresenceKind, type Profile, type ProfilePatch, type ProfileSummary, type ProfileUpdate, type QueueOp, type QueueOpInput, type QueuedScoreOptions, type REALTIME_FAILED_EVENT, type REALTIME_FEATURE_VERSION, type REALTIME_READY_EVENT, type REALTIME_SINGLETON_API, RESUME_DEBOUNCE_MS, RESUME_MAX_STATE_BYTES, type RaceCreateOptions, type RaceDefinition, type RaceEvents, type RaceHistory, type RaceHistoryQuery, type RaceHistoryViewOptions, type RaceHudPlace, type RaceOutcome, type RaceParams, type RaceRecord, type RaceRecordPlayer, type RaceResult, type RaceResultPlayer, type RaceRuntimeApi, type RaceStart, type RaceStatValue, type RaceState, type RaceStats, type RaceStatusEvent, type Racer, type RacerResult, type RacerState, type RealtimeApi, type RealtimeErrorShape, type RealtimeHubLink, type RecentPlayer, type Rect, type Relation, type ReplayContext, type ReportInput, type ReportKind, type ReportReason, type ResumeBlocker, type ResumeEntry, type ResumeLoadOptions, type ResumeProgress, type ResumeRun, type ResumeSaveInput, type RoomChatLine, type RoomCreateOptions, type RoomEvents, type RoomInfo, type RoomListOptions, type RoomMessage, type RoomReclaimMethods, type RoomSeat, type RoomSeatChange, type RoomSelf, type RoomSendOptions, type RoomState, type RoomStateChange, type RoomStateOptions, type Save, type SaveMeta, type SchemaOutput, type ServerEvents, type Snapshot, type SnapshotResponse, type SocialConfig, type SocialCounts, type SocialEvents, type SocialMe, type SortDir, type StatResult, type Stats, type SubmitScoreOptions, type SubmitScoreResult, type Suggestion, type SuggestionStatus, type SyncConflict, type SyncResult, type TouchMapping, type TradeBundle, type TradeId, type TradeListOptions, type TradeNoteOptions, UI_STACK_VERSION, UNSUPPORTED_BY_HUB, type UiStack, type UiStackHandoff, type User, type Vector, type VirtualControlType, type VirtualDef, type VirtualInputs, type VirtualOverride, boxesTouch, controlSize, createHub, type findRealtimeApi, getDaily, getInput, getUiStack, hub, isDailySystem, isInputSystem, isPageInputControl, type isRealtimeApi, isUiStack, layoutControls, type linkRealtimeToHub, type multiplayerForwarder as mp, type notifyForwarder as notify, parseInputOverrides, type presenceForwarder as presence, type raceForwarder as race, type roomsForwarder as rooms, type socialForwarder as social, trackInputModality };
|
|
35
|
+
export { type Anchor, type Audience, type AuthResponse, type AutoPauseOptions, type AxisDef, type AxisSide, type Board, type BoardWithTop, type BufferedEvent, type BusyOptions, CLIENT_VERSION_HEADER, type ChatMode, type ClientSupport, ContentRejectedError, type Conversation, type Counts, DAILY_SINGLETON_API, DAILY_START_EVENT, type DailyAll, type DailyChallenge, type DailyCompleteResponse, type DailyCompletion, type DailyCompletionMeta, type DailyCompletions, type DailyDefinition, type DailyEventDetail, type DailyGameStatus, type DailyHost, type DailyStartResponse, type DailyStatus, DailySystem, type DraggedSpot, type EdgeOffsets, type EndpointFields, type EndpointName, type EndpointReply, type ErrorBody, FOCUS_RING_SHADOW, type FriendEntry, type GameAnalytics, type GameInfo, type GameLeaderboards, type GamePayload, type GameRecords, type GamepadMapping, type GlobalAnalytics, type GrantBundle, type GroupDef, HUB_CLIENT_VERSION, Hub, HubError, type HubErrorCode, type HubErrorDetails, type HubMenuControl, type HubMpApi, type HubNotifyApi, type HubOptions, type HubPresenceApi, type HubRaceApi, HubResume, type HubRoom, type HubRoomsApi, type HubSocialApi, type HubStatus, INPUT_SINGLETON_API, type InputConfig, type InputDef, type InputEvents, type InputHost, type InputModality, type InputOptions, type InputOverrides, type InputReading, type InputSource, InputSystem, type InputSystemOptions, type Insets, type Inventory, type InventorySnapshot, type Invite, type InviteCreated, type InviteLink, type InviteLinkMethods, type InviteOptions, type InviteResult, type JoinInfo, type JoinInfoEvent, type JoinOptions, type Json, type Launch, type LaunchTicket, type LayoutBox, type LayoutItem, type LayoutOptions, type LeaderboardEntry, type LeaderboardResult, MODALITY_ATTRIBUTE, type MeResponse, type MenuBridge, type Message, type MessagesPage, type Metrics, type MouseMapping, type NavBlurEvent, type NavElement, type NavElementKind, type NavFocusEvent, type NavTarget, type NavigableDef, type Notice, type NotifyChange, type NotifyPrefs, OUTBOX_FULL_CODE, OUTBOX_MAX_CHARS, OUTBOX_MAX_ENTRIES, OfflineApi, OfflineError, type OfflineEventDetails, type OfflineEventName, type OfflineHandler, type OfflineKindDefinition, type OfflineListener, type OfflineOp, type OpenInviteOptions, Overlay, type OverlayEdge, type OverlayEvent, type OverlayListener, type OverlayReason, type PageInputControl, type Party, type PlayOnlineMethods, type PlayerCard, type PlayerLite, type PlayerRef, type Presence, type PresenceInput, type PresenceKind, type Profile, type ProfilePatch, type ProfileSummary, type ProfileUpdate, type QueueOp, type QueueOpInput, type QueuedScoreOptions, type REALTIME_FAILED_EVENT, type REALTIME_FEATURE_VERSION, type REALTIME_READY_EVENT, type REALTIME_SINGLETON_API, RESUME_DEBOUNCE_MS, RESUME_MAX_STATE_BYTES, type RaceCreateOptions, type RaceDefinition, type RaceEvents, type RaceHistory, type RaceHistoryQuery, type RaceHistoryViewOptions, type RaceHudPlace, type RaceOutcome, type RaceParams, type RaceRecord, type RaceRecordPlayer, type RaceResult, type RaceResultPlayer, type RaceRuntimeApi, type RaceStart, type RaceStatValue, type RaceState, type RaceStats, type RaceStatusEvent, type Racer, type RacerResult, type RacerState, type RealtimeApi, type RealtimeErrorShape, type RealtimeHubLink, type RecentPlayer, type Rect, type Relation, type ReplayContext, type ReportInput, type ReportKind, type ReportReason, type ResumeBlocker, type ResumeEntry, type ResumeLoadOptions, type ResumeProgress, type ResumeRun, type ResumeSaveInput, type RoomChatLine, type RoomCreateOptions, type RoomEvents, type RoomInfo, type RoomListOptions, type RoomMessage, type RoomReclaimMethods, type RoomSeat, type RoomSeatChange, type RoomSelf, type RoomSendOptions, type RoomState, type RoomStateChange, type RoomStateOptions, SAVE_UNKNOWN_CODE, type Save, type SaveMeta, type SchemaOutput, type ServerEvents, type Snapshot, type SnapshotResponse, type SocialConfig, type SocialCounts, type SocialEvents, type SocialMe, type SortDir, type StatResult, type Stats, type SubmitScoreOptions, type SubmitScoreResult, type Suggestion, type SuggestionStatus, type SyncConflict, type SyncResult, type TouchMapping, type TradeBundle, type TradeId, type TradeListOptions, type TradeNoteOptions, UI_STACK_VERSION, UNSUPPORTED_BY_HUB, type UiStack, type UiStackHandoff, type User, type Vector, type VirtualControlType, type VirtualDef, type VirtualInputs, type VirtualOverride, boxesTouch, controlSize, createHub, type findRealtimeApi, getDaily, getInput, getUiStack, hub, isDailySystem, isInputSystem, isPageInputControl, type isRealtimeApi, isUiStack, layoutControls, type linkRealtimeToHub, type multiplayerForwarder as mp, type notifyForwarder as notify, parseInputOverrides, type presenceForwarder as presence, type raceForwarder as race, type roomsForwarder as rooms, type socialForwarder as social, trackInputModality };
|
|
36
36
|
//# sourceMappingURL=auto.d.ts.map
|
package/dist/auto.js
CHANGED
|
@@ -2,7 +2,7 @@ import { a as DailySystem, i as DAILY_START_EVENT, n as getDaily, r as isDailySy
|
|
|
2
2
|
import { t as HUB_CLIENT_VERSION } from "./shared/client-version.gen.js";
|
|
3
3
|
import { a as isPageInputControl, c as layoutControls, d as MODALITY_ATTRIBUTE, f as trackInputModality, i as parseInputOverrides, l as boxesTouch, n as getInput, o as InputSystem, p as FOCUS_RING_SHADOW, r as isInputSystem, s as Overlay, t as INPUT_SINGLETON_API, u as controlSize } from "./shared/input.js";
|
|
4
4
|
import { n as isUiStack, r as UI_STACK_VERSION, t as getUiStack } from "./shared/page-stack.js";
|
|
5
|
-
import { a as RESUME_DEBOUNCE_MS, c as OUTBOX_FULL_CODE, d as OfflineApi, f as ContentRejectedError,
|
|
5
|
+
import { a as RESUME_DEBOUNCE_MS, c as OUTBOX_FULL_CODE, d as OfflineApi, f as ContentRejectedError, g as UNSUPPORTED_BY_HUB, h as SAVE_UNKNOWN_CODE, i as HubResume, l as OUTBOX_MAX_CHARS, m as OfflineError, n as createHub, o as RESUME_MAX_STATE_BYTES, p as HubError, r as hub, s as CLIENT_VERSION_HEADER, t as Hub, u as OUTBOX_MAX_ENTRIES } from "./shared/src.js";
|
|
6
6
|
//#region src/auto.ts
|
|
7
7
|
/**
|
|
8
8
|
* `@diffenderfer-games/hub/auto`: everything the main entry exports, plus a
|
|
@@ -22,6 +22,6 @@ if (typeof window !== "undefined") window.HubSDK = {
|
|
|
22
22
|
ContentRejectedError
|
|
23
23
|
};
|
|
24
24
|
//#endregion
|
|
25
|
-
export { CLIENT_VERSION_HEADER, ContentRejectedError, DAILY_SINGLETON_API, DAILY_START_EVENT, DailySystem, FOCUS_RING_SHADOW, HUB_CLIENT_VERSION, Hub, HubError, HubResume, INPUT_SINGLETON_API, InputSystem, MODALITY_ATTRIBUTE, OUTBOX_FULL_CODE, OUTBOX_MAX_CHARS, OUTBOX_MAX_ENTRIES, OfflineApi, OfflineError, Overlay, RESUME_DEBOUNCE_MS, RESUME_MAX_STATE_BYTES, UI_STACK_VERSION, UNSUPPORTED_BY_HUB, boxesTouch, controlSize, createHub, getDaily, getInput, getUiStack, hub, isDailySystem, isInputSystem, isPageInputControl, isUiStack, layoutControls, parseInputOverrides, trackInputModality };
|
|
25
|
+
export { CLIENT_VERSION_HEADER, ContentRejectedError, DAILY_SINGLETON_API, DAILY_START_EVENT, DailySystem, FOCUS_RING_SHADOW, HUB_CLIENT_VERSION, Hub, HubError, HubResume, INPUT_SINGLETON_API, InputSystem, MODALITY_ATTRIBUTE, OUTBOX_FULL_CODE, OUTBOX_MAX_CHARS, OUTBOX_MAX_ENTRIES, OfflineApi, OfflineError, Overlay, RESUME_DEBOUNCE_MS, RESUME_MAX_STATE_BYTES, SAVE_UNKNOWN_CODE, UI_STACK_VERSION, UNSUPPORTED_BY_HUB, boxesTouch, controlSize, createHub, getDaily, getInput, getUiStack, hub, isDailySystem, isInputSystem, isPageInputControl, isUiStack, layoutControls, parseInputOverrides, trackInputModality };
|
|
26
26
|
|
|
27
27
|
//# sourceMappingURL=auto.js.map
|
package/dist/doctor/cli.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { parseArgs } from "node:util";
|
|
|
5
5
|
import { GAME_LABELS, GamePackageJson, HubVersion, splitGameLabels } from "@diffenderfer-games/hub-contract";
|
|
6
6
|
//#region src/core/version/client-version.gen.ts
|
|
7
7
|
/** This client's package version, sent as `x-hub-client` on REST calls and `client` in `hello`. */
|
|
8
|
-
const HUB_CLIENT_VERSION = "2.0.0-next.
|
|
8
|
+
const HUB_CLIENT_VERSION = "2.0.0-next.5";
|
|
9
9
|
//#endregion
|
|
10
10
|
//#region src/core/version/semver.ts
|
|
11
11
|
const VERSION_PATTERN = /^v?(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
|
package/dist/index.d.ts
CHANGED
|
@@ -8,5 +8,5 @@ import { a as RaceHistoryQuery, c as RaceRuntimeApi, i as RaceEvents, l as RaceS
|
|
|
8
8
|
import { f as raceForwarder } from "./shared/race.js";
|
|
9
9
|
import { n as roomsForwarder } from "./shared/rooms.js";
|
|
10
10
|
import { $ as HubNotifyApi, A as RacerState, B as SuggestionStatus, C as RaceRecord, D as RaceStats, E as RaceState, F as ReportReason, G as REALTIME_READY_EVENT, H as isRealtimeApi, I as RoomInfo, J as RealtimeHubLink, K as REALTIME_SINGLETON_API, L as SocialConfig, M as Relation, N as ReportInput, O as Racer, P as ReportKind, Q as socialForwarder, R as SocialMe, S as RaceParams, T as RaceStatValue, U as REALTIME_FAILED_EVENT, V as findRealtimeApi, W as REALTIME_FEATURE_VERSION, X as notifyForwarder, Y as linkRealtimeToHub, Z as presenceForwarder, _ as PlayerLite, a as ErrorBody, at as SocialCounts, b as PresenceKind, c as JoinInfo, d as Message, et as HubPresenceApi, f as MessagesPage, g as PlayerCard, h as Party, i as Counts, it as PlayerRef, j as RecentPlayer, k as RacerResult, l as Launch, m as NotifyPrefs, n as ChatMode, nt as OpenInviteOptions, o as FriendEntry, ot as SocialEvents, p as NotifyChange, q as RealtimeApi, r as Conversation, rt as PlayOnlineMethods, s as Invite, t as Audience, tt as HubSocialApi, u as LaunchTicket, v as Presence, w as RaceResult, x as RaceOutcome, y as PresenceInput, z as Suggestion } from "./shared/social.js";
|
|
11
|
-
import { $ as
|
|
12
|
-
export { type Anchor, type Audience, type AuthResponse, type AutoPauseOptions, type AxisDef, type AxisSide, type Board, type BoardWithTop, type BufferedEvent, type BusyOptions, CLIENT_VERSION_HEADER, type ChatMode, type ClientSupport, ContentRejectedError, type Conversation, type Counts, DAILY_SINGLETON_API, DAILY_START_EVENT, type DailyAll, type DailyChallenge, type DailyCompleteResponse, type DailyCompletion, type DailyCompletionMeta, type DailyCompletions, type DailyDefinition, type DailyEventDetail, type DailyGameStatus, type DailyHost, type DailyStartResponse, type DailyStatus, DailySystem, type DraggedSpot, type EdgeOffsets, type EndpointFields, type EndpointName, type EndpointReply, type ErrorBody, FOCUS_RING_SHADOW, type FriendEntry, type GameAnalytics, type GameInfo, type GameLeaderboards, type GamePayload, type GameRecords, type GamepadMapping, type GlobalAnalytics, type GrantBundle, type GroupDef, HUB_CLIENT_VERSION, Hub, HubError, type HubErrorCode, type HubErrorDetails, type HubMenuControl, type HubMpApi, type HubNotifyApi, type HubOptions, type HubPresenceApi, type HubRaceApi, HubResume, type HubRoom, type HubRoomsApi, type HubSocialApi, type HubStatus, INPUT_SINGLETON_API, type InputConfig, type InputDef, type InputEvents, type InputHost, type InputModality, type InputOptions, type InputOverrides, type InputReading, type InputSource, InputSystem, type InputSystemOptions, type Insets, type Inventory, type InventorySnapshot, type Invite, type InviteCreated, type InviteLink, type InviteLinkMethods, type InviteOptions, type InviteResult, type JoinInfo, type JoinInfoEvent, type JoinOptions, type Json, type Launch, type LaunchTicket, type LayoutBox, type LayoutItem, type LayoutOptions, type LeaderboardEntry, type LeaderboardResult, MODALITY_ATTRIBUTE, type MeResponse, type MenuBridge, type Message, type MessagesPage, type Metrics, type MouseMapping, type NavBlurEvent, type NavElement, type NavElementKind, type NavFocusEvent, type NavTarget, type NavigableDef, type Notice, type NotifyChange, type NotifyPrefs, OUTBOX_FULL_CODE, OUTBOX_MAX_CHARS, OUTBOX_MAX_ENTRIES, OfflineApi, OfflineError, type OfflineEventDetails, type OfflineEventName, type OfflineHandler, type OfflineKindDefinition, type OfflineListener, type OfflineOp, type OpenInviteOptions, Overlay, type OverlayEdge, type OverlayEvent, type OverlayListener, type OverlayReason, type PageInputControl, type Party, type PlayOnlineMethods, type PlayerCard, type PlayerLite, type PlayerRef, type Presence, type PresenceInput, type PresenceKind, type Profile, type ProfilePatch, type ProfileSummary, type ProfileUpdate, type QueueOp, type QueueOpInput, type QueuedScoreOptions, type REALTIME_FAILED_EVENT, type REALTIME_FEATURE_VERSION, type REALTIME_READY_EVENT, type REALTIME_SINGLETON_API, RESUME_DEBOUNCE_MS, RESUME_MAX_STATE_BYTES, type RaceCreateOptions, type RaceDefinition, type RaceEvents, type RaceHistory, type RaceHistoryQuery, type RaceHistoryViewOptions, type RaceHudPlace, type RaceOutcome, type RaceParams, type RaceRecord, type RaceRecordPlayer, type RaceResult, type RaceResultPlayer, type RaceRuntimeApi, type RaceStart, type RaceStatValue, type RaceState, type RaceStats, type RaceStatusEvent, type Racer, type RacerResult, type RacerState, type RealtimeApi, type RealtimeErrorShape, type RealtimeHubLink, type RecentPlayer, type Rect, type Relation, type ReplayContext, type ReportInput, type ReportKind, type ReportReason, type ResumeBlocker, type ResumeEntry, type ResumeLoadOptions, type ResumeProgress, type ResumeRun, type ResumeSaveInput, type RoomChatLine, type RoomCreateOptions, type RoomEvents, type RoomInfo, type RoomListOptions, type RoomMessage, type RoomReclaimMethods, type RoomSeat, type RoomSeatChange, type RoomSelf, type RoomSendOptions, type RoomState, type RoomStateChange, type RoomStateOptions, type Save, type SaveMeta, type SchemaOutput, type ServerEvents, type Snapshot, type SnapshotResponse, type SocialConfig, type SocialCounts, type SocialEvents, type SocialMe, type SortDir, type StatResult, type Stats, type SubmitScoreOptions, type SubmitScoreResult, type Suggestion, type SuggestionStatus, type SyncConflict, type SyncResult, type TouchMapping, type TradeBundle, type TradeId, type TradeListOptions, type TradeNoteOptions, UI_STACK_VERSION, UNSUPPORTED_BY_HUB, type UiStack, type UiStackHandoff, type User, type Vector, type VirtualControlType, type VirtualDef, type VirtualInputs, type VirtualOverride, boxesTouch, controlSize, createHub, type findRealtimeApi, getDaily, getInput, getUiStack, hub, isDailySystem, isInputSystem, isPageInputControl, type isRealtimeApi, isUiStack, layoutControls, type linkRealtimeToHub, type multiplayerForwarder as mp, type notifyForwarder as notify, parseInputOverrides, type presenceForwarder as presence, type raceForwarder as race, type roomsForwarder as rooms, type socialForwarder as social, trackInputModality };
|
|
11
|
+
import { $ as GameInfo, A as StatResult, B as OUTBOX_MAX_ENTRIES, C as GrantBundle, Ct as EndpointName, D as TradeNoteOptions, E as TradeListOptions, F as OfflineEventDetails, G as ProfilePatch, H as OfflineKindDefinition, I as OfflineEventName, J as QueuedScoreOptions, K as QueueOp, L as OfflineListener, M as SyncResult, N as OfflineApi, O as AuthResponse, P as OUTBOX_FULL_CODE, Q as GameAnalytics, R as OfflineOp, S as HubMenuControl, St as EndpointFields, T as TradeId, Tt as GamePayload, U as ReplayContext, V as OfflineHandler, W as CLIENT_VERSION_HEADER, X as Board, Y as BufferedEvent, Z as BoardWithTop, _ as ResumeEntry, _t as SortDir, a as HubErrorDetails, at as Inventory, b as ResumeRun, bt as SubmitScoreResult, c as UNSUPPORTED_BY_HUB, ct as LeaderboardEntry, d as hub, dt as Metrics, et as GameLeaderboards, f as ClientSupport, ft as Profile, g as ResumeBlocker, gt as SnapshotResponse, h as RESUME_MAX_STATE_BYTES, ht as SaveMeta, i as HubErrorCode, it as HubStatus, j as SyncConflict, k as ProfileUpdate, l as Hub, lt as LeaderboardResult, m as RESUME_DEBOUNCE_MS, mt as Save, n as ContentRejectedError, nt as GlobalAnalytics, o as OfflineError, ot as InventorySnapshot, p as HubResume, pt as ProfileSummary, q as QueueOpInput, r as HubError, rt as HubOptions, s as SAVE_UNKNOWN_CODE, st as Json, t as HUB_CLIENT_VERSION, tt as GameRecords, u as createHub, ut as MeResponse, v as ResumeLoadOptions, vt as Stats, w as TradeBundle, wt as EndpointReply, x as ResumeSaveInput, xt as User, y as ResumeProgress, yt as SubmitScoreOptions, z as OUTBOX_MAX_CHARS } from "./shared/index.js";
|
|
12
|
+
export { type Anchor, type Audience, type AuthResponse, type AutoPauseOptions, type AxisDef, type AxisSide, type Board, type BoardWithTop, type BufferedEvent, type BusyOptions, CLIENT_VERSION_HEADER, type ChatMode, type ClientSupport, ContentRejectedError, type Conversation, type Counts, DAILY_SINGLETON_API, DAILY_START_EVENT, type DailyAll, type DailyChallenge, type DailyCompleteResponse, type DailyCompletion, type DailyCompletionMeta, type DailyCompletions, type DailyDefinition, type DailyEventDetail, type DailyGameStatus, type DailyHost, type DailyStartResponse, type DailyStatus, DailySystem, type DraggedSpot, type EdgeOffsets, type EndpointFields, type EndpointName, type EndpointReply, type ErrorBody, FOCUS_RING_SHADOW, type FriendEntry, type GameAnalytics, type GameInfo, type GameLeaderboards, type GamePayload, type GameRecords, type GamepadMapping, type GlobalAnalytics, type GrantBundle, type GroupDef, HUB_CLIENT_VERSION, Hub, HubError, type HubErrorCode, type HubErrorDetails, type HubMenuControl, type HubMpApi, type HubNotifyApi, type HubOptions, type HubPresenceApi, type HubRaceApi, HubResume, type HubRoom, type HubRoomsApi, type HubSocialApi, type HubStatus, INPUT_SINGLETON_API, type InputConfig, type InputDef, type InputEvents, type InputHost, type InputModality, type InputOptions, type InputOverrides, type InputReading, type InputSource, InputSystem, type InputSystemOptions, type Insets, type Inventory, type InventorySnapshot, type Invite, type InviteCreated, type InviteLink, type InviteLinkMethods, type InviteOptions, type InviteResult, type JoinInfo, type JoinInfoEvent, type JoinOptions, type Json, type Launch, type LaunchTicket, type LayoutBox, type LayoutItem, type LayoutOptions, type LeaderboardEntry, type LeaderboardResult, MODALITY_ATTRIBUTE, type MeResponse, type MenuBridge, type Message, type MessagesPage, type Metrics, type MouseMapping, type NavBlurEvent, type NavElement, type NavElementKind, type NavFocusEvent, type NavTarget, type NavigableDef, type Notice, type NotifyChange, type NotifyPrefs, OUTBOX_FULL_CODE, OUTBOX_MAX_CHARS, OUTBOX_MAX_ENTRIES, OfflineApi, OfflineError, type OfflineEventDetails, type OfflineEventName, type OfflineHandler, type OfflineKindDefinition, type OfflineListener, type OfflineOp, type OpenInviteOptions, Overlay, type OverlayEdge, type OverlayEvent, type OverlayListener, type OverlayReason, type PageInputControl, type Party, type PlayOnlineMethods, type PlayerCard, type PlayerLite, type PlayerRef, type Presence, type PresenceInput, type PresenceKind, type Profile, type ProfilePatch, type ProfileSummary, type ProfileUpdate, type QueueOp, type QueueOpInput, type QueuedScoreOptions, type REALTIME_FAILED_EVENT, type REALTIME_FEATURE_VERSION, type REALTIME_READY_EVENT, type REALTIME_SINGLETON_API, RESUME_DEBOUNCE_MS, RESUME_MAX_STATE_BYTES, type RaceCreateOptions, type RaceDefinition, type RaceEvents, type RaceHistory, type RaceHistoryQuery, type RaceHistoryViewOptions, type RaceHudPlace, type RaceOutcome, type RaceParams, type RaceRecord, type RaceRecordPlayer, type RaceResult, type RaceResultPlayer, type RaceRuntimeApi, type RaceStart, type RaceStatValue, type RaceState, type RaceStats, type RaceStatusEvent, type Racer, type RacerResult, type RacerState, type RealtimeApi, type RealtimeErrorShape, type RealtimeHubLink, type RecentPlayer, type Rect, type Relation, type ReplayContext, type ReportInput, type ReportKind, type ReportReason, type ResumeBlocker, type ResumeEntry, type ResumeLoadOptions, type ResumeProgress, type ResumeRun, type ResumeSaveInput, type RoomChatLine, type RoomCreateOptions, type RoomEvents, type RoomInfo, type RoomListOptions, type RoomMessage, type RoomReclaimMethods, type RoomSeat, type RoomSeatChange, type RoomSelf, type RoomSendOptions, type RoomState, type RoomStateChange, type RoomStateOptions, SAVE_UNKNOWN_CODE, type Save, type SaveMeta, type SchemaOutput, type ServerEvents, type Snapshot, type SnapshotResponse, type SocialConfig, type SocialCounts, type SocialEvents, type SocialMe, type SortDir, type StatResult, type Stats, type SubmitScoreOptions, type SubmitScoreResult, type Suggestion, type SuggestionStatus, type SyncConflict, type SyncResult, type TouchMapping, type TradeBundle, type TradeId, type TradeListOptions, type TradeNoteOptions, UI_STACK_VERSION, UNSUPPORTED_BY_HUB, type UiStack, type UiStackHandoff, type User, type Vector, type VirtualControlType, type VirtualDef, type VirtualInputs, type VirtualOverride, boxesTouch, controlSize, createHub, type findRealtimeApi, getDaily, getInput, getUiStack, hub, isDailySystem, isInputSystem, isPageInputControl, type isRealtimeApi, isUiStack, layoutControls, type linkRealtimeToHub, type multiplayerForwarder as mp, type notifyForwarder as notify, parseInputOverrides, type presenceForwarder as presence, type raceForwarder as race, type roomsForwarder as rooms, type socialForwarder as social, trackInputModality };
|
package/dist/index.js
CHANGED
|
@@ -2,5 +2,5 @@ import { a as DailySystem, i as DAILY_START_EVENT, n as getDaily, r as isDailySy
|
|
|
2
2
|
import { t as HUB_CLIENT_VERSION } from "./shared/client-version.gen.js";
|
|
3
3
|
import { a as isPageInputControl, c as layoutControls, d as MODALITY_ATTRIBUTE, f as trackInputModality, i as parseInputOverrides, l as boxesTouch, n as getInput, o as InputSystem, p as FOCUS_RING_SHADOW, r as isInputSystem, s as Overlay, t as INPUT_SINGLETON_API, u as controlSize } from "./shared/input.js";
|
|
4
4
|
import { n as isUiStack, r as UI_STACK_VERSION, t as getUiStack } from "./shared/page-stack.js";
|
|
5
|
-
import { a as RESUME_DEBOUNCE_MS, c as OUTBOX_FULL_CODE, d as OfflineApi, f as ContentRejectedError,
|
|
6
|
-
export { CLIENT_VERSION_HEADER, ContentRejectedError, DAILY_SINGLETON_API, DAILY_START_EVENT, DailySystem, FOCUS_RING_SHADOW, HUB_CLIENT_VERSION, Hub, HubError, HubResume, INPUT_SINGLETON_API, InputSystem, MODALITY_ATTRIBUTE, OUTBOX_FULL_CODE, OUTBOX_MAX_CHARS, OUTBOX_MAX_ENTRIES, OfflineApi, OfflineError, Overlay, RESUME_DEBOUNCE_MS, RESUME_MAX_STATE_BYTES, UI_STACK_VERSION, UNSUPPORTED_BY_HUB, boxesTouch, controlSize, createHub, getDaily, getInput, getUiStack, hub, isDailySystem, isInputSystem, isPageInputControl, isUiStack, layoutControls, parseInputOverrides, trackInputModality };
|
|
5
|
+
import { a as RESUME_DEBOUNCE_MS, c as OUTBOX_FULL_CODE, d as OfflineApi, f as ContentRejectedError, g as UNSUPPORTED_BY_HUB, h as SAVE_UNKNOWN_CODE, i as HubResume, l as OUTBOX_MAX_CHARS, m as OfflineError, n as createHub, o as RESUME_MAX_STATE_BYTES, p as HubError, r as hub, s as CLIENT_VERSION_HEADER, t as Hub, u as OUTBOX_MAX_ENTRIES } from "./shared/src.js";
|
|
6
|
+
export { CLIENT_VERSION_HEADER, ContentRejectedError, DAILY_SINGLETON_API, DAILY_START_EVENT, DailySystem, FOCUS_RING_SHADOW, HUB_CLIENT_VERSION, Hub, HubError, HubResume, INPUT_SINGLETON_API, InputSystem, MODALITY_ATTRIBUTE, OUTBOX_FULL_CODE, OUTBOX_MAX_CHARS, OUTBOX_MAX_ENTRIES, OfflineApi, OfflineError, Overlay, RESUME_DEBOUNCE_MS, RESUME_MAX_STATE_BYTES, SAVE_UNKNOWN_CODE, UI_STACK_VERSION, UNSUPPORTED_BY_HUB, boxesTouch, controlSize, createHub, getDaily, getInput, getUiStack, hub, isDailySystem, isInputSystem, isPageInputControl, isUiStack, layoutControls, parseInputOverrides, trackInputModality };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/core/version/client-version.gen.ts
|
|
2
2
|
/** This client's package version, sent as `x-hub-client` on REST calls and `client` in `hello`. */
|
|
3
|
-
const HUB_CLIENT_VERSION = "2.0.0-next.
|
|
3
|
+
const HUB_CLIENT_VERSION = "2.0.0-next.5";
|
|
4
4
|
//#endregion
|
|
5
5
|
export { HUB_CLIENT_VERSION as t };
|
|
6
6
|
|
package/dist/shared/daily.js
CHANGED
|
@@ -197,7 +197,7 @@ let claimedDaily = null;
|
|
|
197
197
|
function getDaily(host) {
|
|
198
198
|
claimedDaily ?? (claimedDaily = claimSingleton({
|
|
199
199
|
name: "daily",
|
|
200
|
-
version: "2.0.0-next.
|
|
200
|
+
version: "2.0.0-next.5",
|
|
201
201
|
api: 1,
|
|
202
202
|
create: () => new DailySystem(host),
|
|
203
203
|
isInstance: isDailySystem
|
package/dist/shared/index.d.ts
CHANGED
|
@@ -256,6 +256,16 @@ declare class LocalStore {
|
|
|
256
256
|
putSave(slot: string, saveData: Json, label: string | null): number;
|
|
257
257
|
/** Forget a save. */
|
|
258
258
|
deleteSave(slot: string): void;
|
|
259
|
+
/**
|
|
260
|
+
* The hub's `updatedAt` for `slot` as the current user last saw it (`null`:
|
|
261
|
+
* the slot was empty), or `undefined` when this device doesn't know.
|
|
262
|
+
*/
|
|
263
|
+
cloudSave(slot: string): number | null | undefined;
|
|
264
|
+
/** Note the hub's copy of `slot` (just read or written) for the current user: its `updatedAt`, or `null` when empty. */
|
|
265
|
+
rememberCloudSave(slot: string, updatedAt: number | null): void;
|
|
266
|
+
/** Cache a slot as read from the hub (forgetting it when the hub has none), and note the hub's copy. */
|
|
267
|
+
cacheCloudSave(slot: string, save: Save | null): void;
|
|
268
|
+
private readCloudSaves;
|
|
259
269
|
/** This game's cached stats. */
|
|
260
270
|
getStats(): Stats;
|
|
261
271
|
/** Apply one stat update and return the stat's new value. */
|
|
@@ -278,7 +288,12 @@ declare class LocalStore {
|
|
|
278
288
|
setEvents(events: readonly BufferedEvent[]): void;
|
|
279
289
|
/** Buffer one event (capped; heartbeats are dropped first). */
|
|
280
290
|
bufferEvent(type: string): void;
|
|
281
|
-
/**
|
|
291
|
+
/**
|
|
292
|
+
* Fan a `/me/snapshot` reply out across every game's cache keys. It lists
|
|
293
|
+
* every save slot of every game the player has played, so each game's
|
|
294
|
+
* slots on the hub become known (and this game's are all empty when it
|
|
295
|
+
* isn't listed).
|
|
296
|
+
*/
|
|
282
297
|
hydrate(snapshot: SnapshotResponse): void;
|
|
283
298
|
}
|
|
284
299
|
//#endregion
|
|
@@ -740,6 +755,8 @@ declare class HubProgress extends HubConnection {
|
|
|
740
755
|
ok: true;
|
|
741
756
|
}>;
|
|
742
757
|
private signInLocally;
|
|
758
|
+
/** Remember who the hub signed in, so the cache's notes about the hub's copies are read for the right player. */
|
|
759
|
+
private signedIn;
|
|
743
760
|
/** This game's profile for the current user, or `profile: null`. `TData` is the game's own data type. */
|
|
744
761
|
getProfile<TData = Json>(): Promise<{
|
|
745
762
|
profile: Profile<TData> | null;
|
|
@@ -752,10 +769,18 @@ declare class HubProgress extends HubConnection {
|
|
|
752
769
|
listSaves(): Promise<{
|
|
753
770
|
saves: SaveMeta[];
|
|
754
771
|
}>;
|
|
755
|
-
/**
|
|
772
|
+
/**
|
|
773
|
+
* One slot's contents, or `save: null` when the slot is empty. `TData` is
|
|
774
|
+
* the game's own save type. Offline it answers from the device's copy, but
|
|
775
|
+
* only when the device knows the hub's copy of the slot; otherwise (a fresh
|
|
776
|
+
* device or cleared browser) it rejects with a {@link HubError} whose
|
|
777
|
+
* `code` is `save_unknown` (`isOffline` is `true`), never a false "empty".
|
|
778
|
+
*/
|
|
756
779
|
getSave<TData = Json>(slot: string): Promise<{
|
|
757
780
|
save: Save<TData> | null;
|
|
758
781
|
}>;
|
|
782
|
+
/** The device's copy of `slot`, when it can be trusted offline (see {@link getSave}). */
|
|
783
|
+
private offlineSave;
|
|
759
784
|
/** Create or overwrite a save slot. `saveData` is any JSON up to 64 KB. */
|
|
760
785
|
putSave<TData extends GamePayload = Json>(slot: string, saveData: TData, label?: string): Promise<{
|
|
761
786
|
ok: true;
|
|
@@ -1119,12 +1144,18 @@ declare function createHub(options?: HubOptions): Hub;
|
|
|
1119
1144
|
declare const UNSUPPORTED_BY_HUB = "unsupported_by_hub";
|
|
1120
1145
|
/** The code the social runtime gives a call it could not send (no connection). */
|
|
1121
1146
|
declare const OFFLINE_CODE = "offline";
|
|
1147
|
+
/**
|
|
1148
|
+
* The code `getSave` rejects with when the hub can't be reached and this
|
|
1149
|
+
* device has no copy of the slot it can trust (a fresh device or cleared
|
|
1150
|
+
* browser): the slot may well hold a save, so it is not reported empty.
|
|
1151
|
+
*/
|
|
1152
|
+
declare const SAVE_UNKNOWN_CODE = "save_unknown";
|
|
1122
1153
|
/**
|
|
1123
1154
|
* A machine-readable error code: one of the contract's public codes
|
|
1124
1155
|
* (`content_rejected`, `rate_limited`, `suspended`, `claim_required`, ...),
|
|
1125
1156
|
* {@link UNSUPPORTED_BY_HUB}, or a code a newer hub added.
|
|
1126
1157
|
*/
|
|
1127
|
-
type HubErrorCode = ErrorCode | typeof UNSUPPORTED_BY_HUB | typeof OFFLINE_CODE | (string & Record<never, never>);
|
|
1158
|
+
type HubErrorCode = ErrorCode | typeof UNSUPPORTED_BY_HUB | typeof OFFLINE_CODE | typeof SAVE_UNKNOWN_CODE | (string & Record<never, never>);
|
|
1128
1159
|
/** The machine-readable extras the hub attaches to an error body. */
|
|
1129
1160
|
interface HubErrorDetails {
|
|
1130
1161
|
/** A stable error code, for code to branch on. */
|
|
@@ -1179,7 +1210,7 @@ declare class ContentRejectedError extends HubError {
|
|
|
1179
1210
|
//#endregion
|
|
1180
1211
|
//#region src/core/version/client-version.gen.d.ts
|
|
1181
1212
|
/** This client's package version, sent as `x-hub-client` on REST calls and `client` in `hello`. */
|
|
1182
|
-
declare const HUB_CLIENT_VERSION = "2.0.0-next.
|
|
1213
|
+
declare const HUB_CLIENT_VERSION = "2.0.0-next.5";
|
|
1183
1214
|
//#endregion
|
|
1184
|
-
export {
|
|
1215
|
+
export { GameInfo$1 as $, StatResult as A, OUTBOX_MAX_ENTRIES as B, GrantBundle as C, EndpointName as Ct, TradeNoteOptions as D, TradeListOptions as E, OfflineEventDetails as F, ProfilePatch as G, OfflineKindDefinition as H, OfflineEventName as I, QueuedScoreOptions as J, QueueOp as K, OfflineListener as L, SyncResult as M, OfflineApi as N, AuthResponse as O, OUTBOX_FULL_CODE as P, GameAnalytics as Q, OfflineOp as R, HubMenuControl as S, EndpointFields as St, TradeId as T, GamePayload as Tt, ReplayContext as U, OfflineHandler as V, CLIENT_VERSION_HEADER as W, Board$1 as X, BufferedEvent as Y, BoardWithTop as Z, ResumeEntry as _, SortDir$1 as _t, HubErrorDetails as a, Inventory$1 as at, ResumeRun as b, SubmitScoreResult as bt, UNSUPPORTED_BY_HUB as c, LeaderboardEntry as ct, hub as d, Metrics$1 as dt, GameLeaderboards as et, ClientSupport as f, Profile as ft, ResumeBlocker as g, SnapshotResponse as gt, RESUME_MAX_STATE_BYTES as h, SaveMeta as ht, HubErrorCode as i, HubStatus as it, SyncConflict as j, ProfileUpdate as k, Hub as l, LeaderboardResult as lt, RESUME_DEBOUNCE_MS as m, Save as mt, ContentRejectedError as n, GlobalAnalytics as nt, OfflineError as o, InventorySnapshot as ot, HubResume as p, ProfileSummary as pt, QueueOpInput as q, HubError as r, HubOptions as rt, SAVE_UNKNOWN_CODE as s, Json$1 as st, HUB_CLIENT_VERSION as t, GameRecords as tt, createHub as u, MeResponse as ut, ResumeLoadOptions as v, Stats$1 as vt, TradeBundle as w, EndpointReply as wt, ResumeSaveInput as x, User as xt, ResumeProgress as y, SubmitScoreOptions as yt, OUTBOX_MAX_CHARS as z };
|
|
1185
1216
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":["GameInfo","ContractGameInfo","GameInfo","presence","social","mp","rooms","notify","race"],"sources":["../../src/core/storage/key-value.ts","../../src/core/game-data.ts","../../src/core/rest/endpoint-types.ts","../../src/core/types.ts","../../src/core/offline/events.ts","../../src/core/offline/queue.ts","../../src/core/offline/local-store.ts","../../src/core/rest/rest-client.ts","../../src/core/offline/outbox-entry.ts","../../src/core/offline/outbox-kinds.ts","../../src/core/offline/outbox-store.ts","../../src/core/offline/outbox-replayer.ts","../../src/core/offline/outbox.ts","../../src/core/offline/offline-api.ts","../../src/core/resume/local-resume.ts","../../src/core/connection.ts","../../src/core/hub-progress.ts","../../src/core/hub-economy.ts","../../src/core/menu-control.ts","../../src/core/offline/hub-kinds/resume-kind.ts","../../src/core/resume/resume-types.ts","../../src/core/resume/hub-resume.ts","../../src/core/version/hub-version.ts","../../src/core/hub.ts","../../src/core/errors.ts","../../src/core/version/client-version.gen.ts"],"mappings":";;;;;;;;;;;;;;;;UAQiB;;EAEf,KAAK;;EAEL,MAAM,aAAa;;EAEnB,OAAO;;EAEP;;;;;KCLU;;;;KCFA,qBAAqB;;KAGrB,eAAe,UAAU,gBAAgB,WAAW,gBAAgB;;;;;KAM3E,UAAU,SAAS;WAAyB;WAAyB,YAAY;IAAS,OAAO;;KAG1F,cAAc,UAAU,gBAAgB,UAAU,QAAQ,WAAW,gBAAgB;;;;KCNrF,OAAO,KAAK,kCAAkC,QAAQ,KAAK;;UAGtD;;WAEN;;WAEA;;;UAIM;;WAEN,MAAM;;WAEN,UAAU;;;UAIJ,QAAQ,QAAQ;;WAEtB;;WAEA;;WAEA,MAAM;;WAEN;;;UAIM;;WAEN;;WAEA;;WAEA;;;UAIM,KAAK,QAAQ,cAAc;;WAEjC,MAAM;;;UAIA,mBAAmB,cAAc,cAAc;;WAErD;;WAEA,OAAO;;WAEP,OAAO;;;UAID;;WAEN,OAAO;;WAEP;;WAEA;;;KAIC,oBAAoB;;KAGpB,eAAe;;KAGf,gBAAgB;;UAGX;;WAEN,QAAQ;;WAER,QAAQ;aAAqB;aAAuB;;;;KAInDA,aAAWC;;KAGX,mBAAmB;;KAGnB,oBAAoB;;UAGf;;WAEN;;WAEA;;WAEA;;;UAIM;;WAEN;;WAEA;;WAEA,eAAe;;;;;;;;WAQf;;;;;UCzHM;;WAEN;;WAEA;;;;;UCJM;;WAEN;;WAEA,OAAO;;WAEP,OAAO;;;UAID;;EAEf;;EAEA,OAAO;;;UAIC;;WAEC;;WAEA;;;KAIC;WACG;WAA0B;WAAuB,MAAM;WAAe;;WACtE;WAA6B;;WAC7B;WAA0B;WAAsB;;WAChD;WAA0B;WAAsB;;WAChD;WAA2B;WAAsB;;WACjD;WAA8B;WAAsB;WAAwB,MAAM;;WAClF;WAA6B,OAAO;;;KAGvC,UAAU,eAAe;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":["GameInfo","ContractGameInfo","GameInfo","presence","social","mp","rooms","notify","race"],"sources":["../../src/core/storage/key-value.ts","../../src/core/game-data.ts","../../src/core/rest/endpoint-types.ts","../../src/core/types.ts","../../src/core/offline/events.ts","../../src/core/offline/queue.ts","../../src/core/offline/local-store.ts","../../src/core/rest/rest-client.ts","../../src/core/offline/outbox-entry.ts","../../src/core/offline/outbox-kinds.ts","../../src/core/offline/outbox-store.ts","../../src/core/offline/outbox-replayer.ts","../../src/core/offline/outbox.ts","../../src/core/offline/offline-api.ts","../../src/core/resume/local-resume.ts","../../src/core/connection.ts","../../src/core/hub-progress.ts","../../src/core/hub-economy.ts","../../src/core/menu-control.ts","../../src/core/offline/hub-kinds/resume-kind.ts","../../src/core/resume/resume-types.ts","../../src/core/resume/hub-resume.ts","../../src/core/version/hub-version.ts","../../src/core/hub.ts","../../src/core/errors.ts","../../src/core/version/client-version.gen.ts"],"mappings":"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"}
|
package/dist/shared/src.js
CHANGED
|
@@ -60,6 +60,12 @@ function isJsonObject(candidate) {
|
|
|
60
60
|
*/
|
|
61
61
|
const UNSUPPORTED_BY_HUB = "unsupported_by_hub";
|
|
62
62
|
/**
|
|
63
|
+
* The code `getSave` rejects with when the hub can't be reached and this
|
|
64
|
+
* device has no copy of the slot it can trust (a fresh device or cleared
|
|
65
|
+
* browser): the slot may well hold a save, so it is not reported empty.
|
|
66
|
+
*/
|
|
67
|
+
const SAVE_UNKNOWN_CODE = "save_unknown";
|
|
68
|
+
/**
|
|
63
69
|
* Thrown by every hub call that fails. `status` is the HTTP status when the
|
|
64
70
|
* hub answered (401 = not signed in, 404 = unknown game or board, 413 = too
|
|
65
71
|
* large), or `undefined` for a transport failure (offline, no host). Social
|
|
@@ -555,23 +561,36 @@ function mergeStats(waiting, incoming) {
|
|
|
555
561
|
case "set": return incoming;
|
|
556
562
|
}
|
|
557
563
|
}
|
|
558
|
-
/**
|
|
559
|
-
|
|
564
|
+
/**
|
|
565
|
+
* The progress kinds, by name. A save write replayed from the queue sends
|
|
566
|
+
* the hub's `updatedAt` this device last saw for the slot (`null` when it
|
|
567
|
+
* saw it empty or never saw it), so the hub refuses it (409 `save_conflict`,
|
|
568
|
+
* dropped and reported as a conflict) when another device saved since. A
|
|
569
|
+
* write sent at once, online, always lands, as before.
|
|
570
|
+
*/
|
|
571
|
+
function progressKinds(game, cloudSaves) {
|
|
560
572
|
return {
|
|
561
573
|
[PROGRESS_KINDS.save]: checkedKind(readSave$1, {
|
|
562
574
|
mergeKey: (save) => save.slot,
|
|
563
575
|
replaces: true,
|
|
564
576
|
run: async (save, context) => {
|
|
565
|
-
if ("deleted" in save)
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
577
|
+
if ("deleted" in save) {
|
|
578
|
+
await context.call("deleteSave", {
|
|
579
|
+
...game(),
|
|
580
|
+
slot: save.slot
|
|
581
|
+
});
|
|
582
|
+
cloudSaves.rememberCloudSave(save.slot, null);
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
const base = context.isReplay ? { base: cloudSaves.cloudSave(save.slot) ?? null } : {};
|
|
586
|
+
const written = await context.call("writeSave", {
|
|
570
587
|
...game(),
|
|
571
588
|
slot: save.slot,
|
|
572
589
|
data: save.data,
|
|
573
|
-
label: save.label
|
|
590
|
+
label: save.label,
|
|
591
|
+
...base
|
|
574
592
|
});
|
|
593
|
+
cloudSaves.rememberCloudSave(save.slot, written.updatedAt);
|
|
575
594
|
}
|
|
576
595
|
}),
|
|
577
596
|
[PROGRESS_KINDS.stat]: checkedKind(readStat, {
|
|
@@ -774,13 +793,68 @@ function legacyOperation(op) {
|
|
|
774
793
|
/** Register every hub kind on `outbox`. */
|
|
775
794
|
function registerHubKinds(outbox, hooks) {
|
|
776
795
|
const kinds = {
|
|
777
|
-
...progressKinds(hooks.game),
|
|
796
|
+
...progressKinds(hooks.game, hooks.cloudSaves),
|
|
778
797
|
...dailyKinds(hooks.game, hooks.onDailyComplete),
|
|
779
798
|
...economyKinds(hooks.game, writeLocalFavorites),
|
|
780
799
|
...resumeKinds(hooks.game, hooks.resume)
|
|
781
800
|
};
|
|
782
801
|
for (const [kind, definition] of Object.entries(kinds)) outbox.define(kind, definition);
|
|
783
802
|
}
|
|
803
|
+
//#endregion
|
|
804
|
+
//#region src/core/offline/cloud-saves.ts
|
|
805
|
+
/**
|
|
806
|
+
* What this device last saw of a game's save slots on the hub, per player:
|
|
807
|
+
* each slot's `updatedAt` there, or `null` for a slot known to be empty. It
|
|
808
|
+
* decides two things offline. `getSave` answers from the cache only when
|
|
809
|
+
* the device knows the hub's copy of that slot (so a fresh device or cleared
|
|
810
|
+
* browser never reports "no save" for a slot it simply hasn't seen), and a
|
|
811
|
+
* queued save write sends the hub's `updatedAt` it was built on, so the hub
|
|
812
|
+
* refuses it when the slot has changed since.
|
|
813
|
+
*
|
|
814
|
+
* A snapshot gives the full list (`complete`: any other slot is empty); a
|
|
815
|
+
* single read or write adds that slot to a partial list.
|
|
816
|
+
*/
|
|
817
|
+
/** A stored index, or `null` when missing or malformed. */
|
|
818
|
+
function readCloudSaveIndex(stored) {
|
|
819
|
+
if (!isRecord(stored) || typeof stored.complete !== "boolean" || !isRecord(stored.saves)) return null;
|
|
820
|
+
const userId = optionalNumber(stored.userId);
|
|
821
|
+
if (userId === void 0) return null;
|
|
822
|
+
const saves = {};
|
|
823
|
+
for (const [slot, updatedAt] of Object.entries(stored.saves)) {
|
|
824
|
+
const known = updatedAt === null ? null : optionalNumber(updatedAt);
|
|
825
|
+
if (known === void 0) return null;
|
|
826
|
+
saves[slot] = known;
|
|
827
|
+
}
|
|
828
|
+
return {
|
|
829
|
+
userId,
|
|
830
|
+
complete: stored.complete,
|
|
831
|
+
saves
|
|
832
|
+
};
|
|
833
|
+
}
|
|
834
|
+
/**
|
|
835
|
+
* The hub's `updatedAt` for `slot` as `userId` last saw it: a number, `null`
|
|
836
|
+
* when the slot was empty, or `undefined` when this device doesn't know.
|
|
837
|
+
*/
|
|
838
|
+
function cloudSaveOf(index, userId, slot) {
|
|
839
|
+
if (index?.userId !== userId) return;
|
|
840
|
+
const updatedAt = index.saves[slot];
|
|
841
|
+
return updatedAt === void 0 && index.complete ? null : updatedAt;
|
|
842
|
+
}
|
|
843
|
+
/** `index` with `slot` seen at `updatedAt` (`null`: empty) by `userId`; another player's index starts over. */
|
|
844
|
+
function withCloudSave(index, userId, slot, updatedAt) {
|
|
845
|
+
const base = index?.userId === userId ? index : {
|
|
846
|
+
userId,
|
|
847
|
+
complete: false,
|
|
848
|
+
saves: {}
|
|
849
|
+
};
|
|
850
|
+
return {
|
|
851
|
+
...base,
|
|
852
|
+
saves: {
|
|
853
|
+
...base.saves,
|
|
854
|
+
[slot]: updatedAt
|
|
855
|
+
}
|
|
856
|
+
};
|
|
857
|
+
}
|
|
784
858
|
/** The well-formed events of a stored buffer. */
|
|
785
859
|
function readEvents(stored) {
|
|
786
860
|
if (!Array.isArray(stored)) return [];
|
|
@@ -994,6 +1068,28 @@ var LocalStore = class {
|
|
|
994
1068
|
deleteSave(slot) {
|
|
995
1069
|
this.store.remove(`${this.prefix}save:${slot}`);
|
|
996
1070
|
}
|
|
1071
|
+
/**
|
|
1072
|
+
* The hub's `updatedAt` for `slot` as the current user last saw it (`null`:
|
|
1073
|
+
* the slot was empty), or `undefined` when this device doesn't know.
|
|
1074
|
+
*/
|
|
1075
|
+
cloudSave(slot) {
|
|
1076
|
+
const user = this.getUser();
|
|
1077
|
+
return user === null ? void 0 : cloudSaveOf(this.readCloudSaves(this.prefix), user.id, slot);
|
|
1078
|
+
}
|
|
1079
|
+
/** Note the hub's copy of `slot` (just read or written) for the current user: its `updatedAt`, or `null` when empty. */
|
|
1080
|
+
rememberCloudSave(slot, updatedAt) {
|
|
1081
|
+
const user = this.getUser();
|
|
1082
|
+
if (user !== null) this.writeStored(`${this.prefix}cloud-saves`, withCloudSave(this.readCloudSaves(this.prefix), user.id, slot, updatedAt));
|
|
1083
|
+
}
|
|
1084
|
+
/** Cache a slot as read from the hub (forgetting it when the hub has none), and note the hub's copy. */
|
|
1085
|
+
cacheCloudSave(slot, save) {
|
|
1086
|
+
if (save === null) this.deleteSave(slot);
|
|
1087
|
+
else this.writeStored(`${this.prefix}save:${slot}`, save);
|
|
1088
|
+
this.rememberCloudSave(slot, save?.updatedAt ?? null);
|
|
1089
|
+
}
|
|
1090
|
+
readCloudSaves(gamePrefix) {
|
|
1091
|
+
return readCloudSaveIndex(this.readStored(`${gamePrefix}cloud-saves`));
|
|
1092
|
+
}
|
|
997
1093
|
/** This game's cached stats. */
|
|
998
1094
|
getStats() {
|
|
999
1095
|
const stored = this.readStored(`${this.prefix}stats`);
|
|
@@ -1070,13 +1166,32 @@ var LocalStore = class {
|
|
|
1070
1166
|
ts: Date.now()
|
|
1071
1167
|
}));
|
|
1072
1168
|
}
|
|
1073
|
-
/**
|
|
1169
|
+
/**
|
|
1170
|
+
* Fan a `/me/snapshot` reply out across every game's cache keys. It lists
|
|
1171
|
+
* every save slot of every game the player has played, so each game's
|
|
1172
|
+
* slots on the hub become known (and this game's are all empty when it
|
|
1173
|
+
* isn't listed).
|
|
1174
|
+
*/
|
|
1074
1175
|
hydrate(snapshot) {
|
|
1075
1176
|
if (snapshot.user !== null) this.writeStored(USER_KEY, snapshot.user);
|
|
1177
|
+
const userId = snapshot.user?.id;
|
|
1178
|
+
if (userId !== void 0 && !Object.keys(snapshot.games).some((slug) => `hub:${slug}:` === this.prefix)) this.writeStored(`${this.prefix}cloud-saves`, {
|
|
1179
|
+
userId,
|
|
1180
|
+
complete: true,
|
|
1181
|
+
saves: {}
|
|
1182
|
+
});
|
|
1076
1183
|
for (const [slug, game] of Object.entries(snapshot.games)) {
|
|
1077
1184
|
const gamePrefix = `hub:${slug}:`;
|
|
1078
1185
|
if (game.profile !== null) this.writeStored(`${gamePrefix}profile`, game.profile);
|
|
1079
1186
|
for (const save of game.saves) this.writeStored(`${gamePrefix}save:${save.slot}`, save);
|
|
1187
|
+
if (userId !== void 0) {
|
|
1188
|
+
const saves = Object.fromEntries(game.saves.map((save) => [save.slot, save.updatedAt]));
|
|
1189
|
+
this.writeStored(`${gamePrefix}cloud-saves`, {
|
|
1190
|
+
userId,
|
|
1191
|
+
complete: true,
|
|
1192
|
+
saves
|
|
1193
|
+
});
|
|
1194
|
+
}
|
|
1080
1195
|
this.writeStored(`${gamePrefix}stats`, game.stats);
|
|
1081
1196
|
this.writeStored(`${gamePrefix}inventory`, game.inventory);
|
|
1082
1197
|
}
|
|
@@ -2612,7 +2727,8 @@ var HubConnection = class {
|
|
|
2612
2727
|
meta: payload.meta
|
|
2613
2728
|
});
|
|
2614
2729
|
},
|
|
2615
|
-
resume: this.resumeStore
|
|
2730
|
+
resume: this.resumeStore,
|
|
2731
|
+
cloudSaves: this.store
|
|
2616
2732
|
});
|
|
2617
2733
|
this.importLegacyQueue();
|
|
2618
2734
|
if (typeof navigator !== "undefined" && "onLine" in navigator) this.isReachable = navigator.onLine;
|
|
@@ -2880,7 +2996,7 @@ var HubProgress = class extends HubConnection {
|
|
|
2880
2996
|
* sign-in. Idempotent. Offline, a local guest is used.
|
|
2881
2997
|
*/
|
|
2882
2998
|
ensureGuest() {
|
|
2883
|
-
return this.withFallback(() => this.rest.call("ensureGuestSession"), () => {
|
|
2999
|
+
return this.withFallback(async () => this.signedIn(await this.rest.call("ensureGuestSession")), () => {
|
|
2884
3000
|
const known = this.store.getUser();
|
|
2885
3001
|
if (known !== null) return { user: known };
|
|
2886
3002
|
const guest = {
|
|
@@ -2898,10 +3014,10 @@ var HubProgress = class extends HubConnection {
|
|
|
2898
3014
|
* the name is taken; the player should `login` instead.
|
|
2899
3015
|
*/
|
|
2900
3016
|
claim(username, password) {
|
|
2901
|
-
return this.withFallback(() => this.rest.call("claimGuestAccount", {
|
|
3017
|
+
return this.withFallback(async () => this.signedIn(await this.rest.call("claimGuestAccount", {
|
|
2902
3018
|
username,
|
|
2903
3019
|
password
|
|
2904
|
-
}), () => this.signInLocally({
|
|
3020
|
+
})), () => this.signInLocally({
|
|
2905
3021
|
id: 0,
|
|
2906
3022
|
username,
|
|
2907
3023
|
guest: false
|
|
@@ -2909,27 +3025,31 @@ var HubProgress = class extends HubConnection {
|
|
|
2909
3025
|
}
|
|
2910
3026
|
/** Create an account and sign in. (Offline: a local user is stored.) */
|
|
2911
3027
|
signup(username, password) {
|
|
2912
|
-
return this.withFallback(() => this.rest.call("signUpWithPassword", {
|
|
3028
|
+
return this.withFallback(async () => this.signedIn(await this.rest.call("signUpWithPassword", {
|
|
2913
3029
|
username,
|
|
2914
3030
|
password
|
|
2915
|
-
}), () => this.signInLocally({
|
|
3031
|
+
})), () => this.signInLocally({
|
|
2916
3032
|
id: 0,
|
|
2917
3033
|
username
|
|
2918
3034
|
}));
|
|
2919
3035
|
}
|
|
2920
3036
|
/** Sign in. (Offline: a local user is stored so signed-in flows work.) */
|
|
2921
3037
|
login(username, password) {
|
|
2922
|
-
return this.withFallback(() => this.rest.call("logInWithPassword", {
|
|
3038
|
+
return this.withFallback(async () => this.signedIn(await this.rest.call("logInWithPassword", {
|
|
2923
3039
|
username,
|
|
2924
3040
|
password
|
|
2925
|
-
}), () => this.signInLocally({
|
|
3041
|
+
})), () => this.signInLocally({
|
|
2926
3042
|
id: 0,
|
|
2927
3043
|
username
|
|
2928
3044
|
}));
|
|
2929
3045
|
}
|
|
2930
3046
|
/** Sign out (ends the session shared by every game). */
|
|
2931
3047
|
logout() {
|
|
2932
|
-
return this.withFallback(
|
|
3048
|
+
return this.withFallback(async () => {
|
|
3049
|
+
const reply = await this.rest.call("logOut");
|
|
3050
|
+
this.store.clearUser();
|
|
3051
|
+
return reply;
|
|
3052
|
+
}, () => {
|
|
2933
3053
|
this.store.clearUser();
|
|
2934
3054
|
return { ok: true };
|
|
2935
3055
|
});
|
|
@@ -2938,6 +3058,11 @@ var HubProgress = class extends HubConnection {
|
|
|
2938
3058
|
this.store.setUser(user);
|
|
2939
3059
|
return { user };
|
|
2940
3060
|
}
|
|
3061
|
+
/** Remember who the hub signed in, so the cache's notes about the hub's copies are read for the right player. */
|
|
3062
|
+
signedIn(reply) {
|
|
3063
|
+
this.store.setUser(reply.user);
|
|
3064
|
+
return reply;
|
|
3065
|
+
}
|
|
2941
3066
|
/** This game's profile for the current user, or `profile: null`. `TData` is the game's own data type. */
|
|
2942
3067
|
getProfile() {
|
|
2943
3068
|
return this.withFallback(async () => ({ profile: typedProfile((await this.rest.call("getGameProfile", this.gameFields())).profile) }), () => ({ profile: typedProfile(this.store.getProfile()) }));
|
|
@@ -2960,12 +3085,29 @@ var HubProgress = class extends HubConnection {
|
|
|
2960
3085
|
listSaves() {
|
|
2961
3086
|
return this.withFallback(() => this.rest.call("listSaves", this.gameFields()), () => ({ saves: this.store.listSaves() }));
|
|
2962
3087
|
}
|
|
2963
|
-
/**
|
|
3088
|
+
/**
|
|
3089
|
+
* One slot's contents, or `save: null` when the slot is empty. `TData` is
|
|
3090
|
+
* the game's own save type. Offline it answers from the device's copy, but
|
|
3091
|
+
* only when the device knows the hub's copy of the slot; otherwise (a fresh
|
|
3092
|
+
* device or cleared browser) it rejects with a {@link HubError} whose
|
|
3093
|
+
* `code` is `save_unknown` (`isOffline` is `true`), never a false "empty".
|
|
3094
|
+
*/
|
|
2964
3095
|
getSave(slot) {
|
|
2965
|
-
return this.withFallback(async () =>
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
3096
|
+
return this.withFallback(async () => {
|
|
3097
|
+
const { save } = await this.rest.call("getSave", {
|
|
3098
|
+
...this.gameFields(),
|
|
3099
|
+
slot
|
|
3100
|
+
});
|
|
3101
|
+
if (this.outbox.count() === 0) this.store.cacheCloudSave(slot, save);
|
|
3102
|
+
return { save: typedSave(save) };
|
|
3103
|
+
}, () => ({ save: typedSave(this.offlineSave(slot)) }));
|
|
3104
|
+
}
|
|
3105
|
+
/** The device's copy of `slot`, when it can be trusted offline (see {@link getSave}). */
|
|
3106
|
+
offlineSave(slot) {
|
|
3107
|
+
const isLocalOnly = this.store.getUser()?.id === 0;
|
|
3108
|
+
const hasQueuedWrite = this.outbox.pending().some((op) => op.kind === PROGRESS_KINDS.save && isRecord(op.payload) && op.payload.slot === slot);
|
|
3109
|
+
if (!isLocalOnly && !hasQueuedWrite && this.store.cloudSave(slot) === void 0) throw new HubError(`Hub: offline, and this device hasn't seen save "${slot}" yet.`, void 0, { code: SAVE_UNKNOWN_CODE });
|
|
3110
|
+
return this.store.getSave(slot);
|
|
2969
3111
|
}
|
|
2970
3112
|
/** Create or overwrite a save slot. `saveData` is any JSON up to 64 KB. */
|
|
2971
3113
|
putSave(slot, saveData, label) {
|
|
@@ -3882,6 +4024,6 @@ function createHub(options = {}) {
|
|
|
3882
4024
|
return new Hub(options);
|
|
3883
4025
|
}
|
|
3884
4026
|
//#endregion
|
|
3885
|
-
export { RESUME_DEBOUNCE_MS as a, OUTBOX_FULL_CODE as c, OfflineApi as d, ContentRejectedError as f, UNSUPPORTED_BY_HUB as h, HubResume as i, OUTBOX_MAX_CHARS as l, OfflineError as m, createHub as n, RESUME_MAX_STATE_BYTES as o, HubError as p, hub as r, CLIENT_VERSION_HEADER as s, Hub as t, OUTBOX_MAX_ENTRIES as u };
|
|
4027
|
+
export { RESUME_DEBOUNCE_MS as a, OUTBOX_FULL_CODE as c, OfflineApi as d, ContentRejectedError as f, UNSUPPORTED_BY_HUB as g, SAVE_UNKNOWN_CODE as h, HubResume as i, OUTBOX_MAX_CHARS as l, OfflineError as m, createHub as n, RESUME_MAX_STATE_BYTES as o, HubError as p, hub as r, CLIENT_VERSION_HEADER as s, Hub as t, OUTBOX_MAX_ENTRIES as u };
|
|
3886
4028
|
|
|
3887
4029
|
//# sourceMappingURL=src.js.map
|