@diffenderfer-games/hub 2.0.0-next.1 → 2.0.0-next.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.
Files changed (102) hide show
  1. package/CHANGELOG.md +40 -6
  2. package/README.md +25 -10
  3. package/dist/auto.d.ts +7 -7
  4. package/dist/auto.js +3 -3
  5. package/dist/doctor/cli.mjs +14 -7
  6. package/dist/doctor/cli.mjs.map +1 -1
  7. package/dist/index.d.ts +7 -7
  8. package/dist/index.js +3 -3
  9. package/dist/input.d.ts +2 -2
  10. package/dist/input.js +2 -2
  11. package/dist/mp.d.ts +3 -3
  12. package/dist/race.d.ts +1 -1
  13. package/dist/rooms.d.ts +3 -3
  14. package/dist/shared/bridge.js +9 -3
  15. package/dist/shared/bridge.js.map +1 -1
  16. package/dist/shared/client-version.gen.js +1 -1
  17. package/dist/shared/daily.d.ts +10 -4
  18. package/dist/shared/daily.d.ts.map +1 -1
  19. package/dist/shared/daily.js +12 -2
  20. package/dist/shared/daily.js.map +1 -1
  21. package/dist/shared/index.d.ts +315 -36
  22. package/dist/shared/index.d.ts.map +1 -1
  23. package/dist/shared/input.d.ts +47 -5
  24. package/dist/shared/input.d.ts.map +1 -1
  25. package/dist/shared/input.js +139 -23
  26. package/dist/shared/input.js.map +1 -1
  27. package/dist/shared/latest-state.js +1 -1
  28. package/dist/shared/mp.js +10 -2
  29. package/dist/shared/mp.js.map +1 -1
  30. package/dist/shared/multiplayer-types.d.ts +15 -2
  31. package/dist/shared/multiplayer-types.d.ts.map +1 -1
  32. package/dist/shared/race-types.d.ts +1 -1
  33. package/dist/shared/race.js +1 -1
  34. package/dist/shared/room-types.d.ts +28 -3
  35. package/dist/shared/room-types.d.ts.map +1 -1
  36. package/dist/shared/rooms.d.ts.map +1 -1
  37. package/dist/shared/rooms.js +10 -2
  38. package/dist/shared/rooms.js.map +1 -1
  39. package/dist/shared/runtime-opener.js +1 -1
  40. package/dist/shared/social.d.ts +23 -8
  41. package/dist/shared/social.d.ts.map +1 -1
  42. package/dist/shared/social.js +6 -1
  43. package/dist/shared/social.js.map +1 -1
  44. package/dist/shared/src.js +1588 -388
  45. package/dist/shared/src.js.map +1 -1
  46. package/dist/shared/wire-types.d.ts +6 -2
  47. package/dist/shared/wire-types.d.ts.map +1 -1
  48. package/dist/social.d.ts +5 -5
  49. package/dist/social.js +1 -1
  50. package/package.json +2 -2
  51. package/src/core/connection.ts +187 -92
  52. package/src/core/game-data.ts +11 -9
  53. package/src/core/hub-economy.ts +47 -10
  54. package/src/core/hub-progress.ts +13 -16
  55. package/src/core/hub.ts +4 -2
  56. package/src/core/offline/hub-kinds/daily-kind.ts +68 -0
  57. package/src/core/offline/hub-kinds/economy-kinds.ts +86 -0
  58. package/src/core/offline/hub-kinds/game-fields.ts +2 -0
  59. package/src/core/offline/hub-kinds/index.ts +35 -0
  60. package/src/core/offline/hub-kinds/legacy-ops.ts +37 -0
  61. package/src/core/offline/hub-kinds/progress-kinds.ts +148 -0
  62. package/src/core/offline/kind-adapters.ts +48 -0
  63. package/src/core/offline/local-inventory.ts +64 -0
  64. package/src/core/offline/local-store.ts +20 -22
  65. package/src/core/offline/offline-api.ts +65 -0
  66. package/src/core/offline/outbox-entry.ts +59 -0
  67. package/src/core/offline/outbox-kinds.ts +78 -0
  68. package/src/core/offline/outbox-merge.ts +39 -0
  69. package/src/core/offline/outbox-replayer.ts +141 -0
  70. package/src/core/offline/outbox-store.ts +85 -0
  71. package/src/core/offline/outbox.ts +232 -0
  72. package/src/core/offline/queue.ts +4 -49
  73. package/src/core/offline/replay-lease.ts +87 -0
  74. package/src/core/offline/replay-policy.ts +52 -0
  75. package/src/core/rest/rest-client.ts +14 -3
  76. package/src/core/rest/routes.gen.ts +108 -87
  77. package/src/core/storage/json-guards.ts +6 -0
  78. package/src/core/version/client-version.gen.ts +1 -1
  79. package/src/daily/daily-system.ts +8 -1
  80. package/src/daily/types.ts +3 -2
  81. package/src/doctor/checks.ts +10 -2
  82. package/src/index.ts +6 -1
  83. package/src/input/focus-ring.ts +13 -0
  84. package/src/input/input-registry.ts +9 -2
  85. package/src/input/input-system.ts +4 -0
  86. package/src/input/modality.ts +122 -0
  87. package/src/input/nav-state.ts +13 -4
  88. package/src/input/zero-config.ts +1 -14
  89. package/src/input.ts +3 -0
  90. package/src/mp.ts +1 -1
  91. package/src/overlay/overlay.ts +5 -3
  92. package/src/overlay/styles.ts +4 -3
  93. package/src/realtime/bridge.ts +5 -0
  94. package/src/realtime/multiplayer-forwarder.ts +13 -1
  95. package/src/realtime/multiplayer-types.ts +15 -1
  96. package/src/realtime/room-types.ts +28 -2
  97. package/src/realtime/rooms-forwarder.ts +13 -1
  98. package/src/realtime/runtime-api.ts +19 -8
  99. package/src/realtime/social-forwarder.ts +5 -0
  100. package/src/realtime/social-types.ts +8 -0
  101. package/src/realtime/wire-types.ts +7 -0
  102. package/src/rooms.ts +1 -1
@@ -1,10 +1,10 @@
1
1
  import { s as DailySystem } from "./daily.js";
2
- import { n as getUiStack, w as InputSystem } from "./input.js";
2
+ import { O as InputSystem, n as getUiStack } from "./input.js";
3
3
  import { o as multiplayerForwarder } from "./mp.js";
4
4
  import { f as raceForwarder } from "./race.js";
5
5
  import { n as roomsForwarder } from "./rooms.js";
6
6
  import { Q as socialForwarder, X as notifyForwarder, Z as presenceForwarder } from "./social.js";
7
- import { Board, Board as Board$1, ErrorCode, GameInfo, GameLeaderboards, GameRecords, HubVersion, Inventory, Json, Json as Json$1, LeaderboardEntry, Metrics, Metrics as Metrics$1, PublicEndpoints, RejectReason, SessionUser, SortDir, SortDir as SortDir$1, Stats, Stats as Stats$1 } from "@diffenderfer-games/hub-contract";
7
+ import { Board, Board as Board$1, ErrorCode, GameInfo, GameLeaderboards, GameRecords, HubVersion, Inventory, Inventory as Inventory$1, Json, Json as Json$1, LeaderboardEntry, Metrics, Metrics as Metrics$1, PublicEndpoints, RejectReason, SessionUser, SortDir, SortDir as SortDir$1, Stats, Stats as Stats$1 } from "@diffenderfer-games/hub-contract";
8
8
  import { CallReturn, ClientData } from "@ayepi/core/client";
9
9
  //#region src/core/storage/key-value.d.ts
10
10
  /**
@@ -234,7 +234,6 @@ type StatUpdateMode = 'set' | 'incr' | 'max';
234
234
  declare class LocalStore {
235
235
  private readonly prefix;
236
236
  private readonly store;
237
- private sequence;
238
237
  /** The cache for game `slug` in `store` (default: `localStorage`, or memory without it). */
239
238
  constructor(slug: string, store?: KeyValueStore);
240
239
  private readStored;
@@ -267,14 +266,12 @@ declare class LocalStore {
267
266
  getBoard(key: string): LocalBoard | null;
268
267
  /** Record a score locally, keeping the best one; returns the board and best. */
269
268
  submitScore(key: string, score: number, options: QueuedScoreOptions): LocalBoard;
270
- /** The queued writes, oldest first. */
271
- getQueue(): QueueOp[];
272
- /** Replace the queue. */
273
- setQueue(queue: readonly QueueOp[]): void;
274
- /** How many writes are queued. */
275
- queueLength(): number;
276
- /** Queue a write, collapsing it with a compatible queued one. */
277
- enqueue(input: QueueOpInput): void;
269
+ /** The v1 client's queued writes, removed from storage (the caller moves them into the outbox). */
270
+ takeLegacyQueue(): QueueOp[];
271
+ /** This game's cached inventory (empty when none is cached). */
272
+ getInventory(): Inventory;
273
+ /** Store this game's inventory and return it. */
274
+ setInventory(inventory: Inventory): Inventory;
278
275
  /** The buffered analytics events, oldest first. */
279
276
  getEvents(): BufferedEvent[];
280
277
  /** Replace the event buffer. */
@@ -296,21 +293,270 @@ interface RestClient {
296
293
  readonly apiBase: string;
297
294
  /** Call an endpoint; resolves with its reply body, rejects with a {@link HubError}. */
298
295
  call<K extends EndpointName>(name: K, ...fieldsArgument: CallArguments<K>): Promise<EndpointReply<K>>;
296
+ /**
297
+ * Call an endpoint as part of an offline operation: an endpoint marked for
298
+ * offline replay gets `opKey` in the operation header, so the hub runs it
299
+ * once however often it is sent; any other endpoint is called as usual.
300
+ */
301
+ callOnce<K extends EndpointName>(opKey: string, name: K, ...fieldsArgument: CallArguments<K>): Promise<EndpointReply<K>>;
302
+ }
303
+ //#endregion
304
+ //#region src/core/offline/outbox-entry.d.ts
305
+ /** A queued operation. */
306
+ interface OutboxEntry {
307
+ /** Unique and sortable by queue time: replay runs in `id` order. Also the base of its operation keys. */
308
+ readonly id: string;
309
+ /** Which handler performs it (`hub.save`, `hub.stat`, or a game's own kind). */
310
+ readonly kind: string;
311
+ /** The handler's input. */
312
+ readonly payload: Json;
313
+ /** When it was queued (epoch ms). */
314
+ readonly createdAt: number;
315
+ /** How many times replay has started it. A started entry never absorbs a later one. */
316
+ readonly attempts: number;
317
+ /** Not before this time (epoch ms); 0 means as soon as possible. */
318
+ readonly retryAt: number;
319
+ /** The last failure's message, when it has failed before. */
320
+ readonly lastError?: string;
321
+ }
322
+ //#endregion
323
+ //#region src/core/offline/outbox-kinds.d.ts
324
+ /** What a kind's handler gets besides its payload. */
325
+ interface ReplayContext {
326
+ /** The operation's id (stable across retries). */
327
+ readonly opId: string;
328
+ /** Which try this is, from 1. */
329
+ readonly attempt: number;
330
+ /** `false` when the op runs at once (online, nothing waiting); `true` when it runs from the queue. */
331
+ readonly isReplay: boolean;
332
+ /**
333
+ * Call a hub endpoint. Calls to endpoints marked for offline replay carry
334
+ * an operation key made from the op id and the call's position in the
335
+ * handler, so a retried op whose earlier calls already landed gets their
336
+ * remembered replies instead of running them twice. Make the same calls in
337
+ * the same order on every try.
338
+ */
339
+ call<K extends EndpointName>(name: K, ...fieldsArgument: CallArguments<K>): Promise<EndpointReply<K>>;
340
+ /** A key for `step` of this op that is the same on every try: send it to a game server to deduplicate there. */
341
+ key(step: string): string;
342
+ }
343
+ /** Performs one operation of a kind. Throw to fail it (see the docs for which failures retry). */
344
+ type OfflineHandler<Payload> = (payload: Payload, context: ReplayContext) => Promise<Json | undefined> | Json | undefined;
345
+ /** A kind, with optional rules for folding new operations into waiting ones. */
346
+ interface OfflineKindDefinition<Payload> {
347
+ /** Perform one operation. */
348
+ readonly run: OfflineHandler<Payload>;
349
+ /**
350
+ * Operations with the same merge key may fold together. Without one, every
351
+ * operation replays on its own.
352
+ */
353
+ readonly mergeKey?: (payload: Payload) => string;
354
+ /**
355
+ * Fold `incoming` into the newest waiting operation with the same merge key
356
+ * (in its place in the queue); `undefined` to queue it separately.
357
+ */
358
+ readonly merge?: (waiting: Payload, incoming: Payload) => Payload | undefined;
359
+ /** `true`: a new operation replaces every waiting one with the same merge key and goes last (a save slot's last write wins). */
360
+ readonly replaces?: boolean;
361
+ }
362
+ /** A kind as the outbox runs it: payloads are the stored JSON. */
363
+ interface RegisteredKind {
364
+ /** Perform one operation (malformed payloads are refused before this). */
365
+ readonly run: (payload: Json, context: ReplayContext) => Promise<Json | undefined> | Json | undefined;
366
+ /** Whether a stored payload is well formed for this kind. */
367
+ readonly accepts: (payload: Json) => boolean;
368
+ readonly mergeKey?: (payload: Json) => string;
369
+ readonly merge?: (waiting: Json, incoming: Json) => Json | undefined;
370
+ readonly replaces: boolean;
371
+ }
372
+ /** The registered kinds of one client. */
373
+ declare class KindRegistry {
374
+ private readonly kinds;
375
+ /** Register (or replace) a kind. */
376
+ register(kind: string, definition: RegisteredKind): void;
377
+ /** A registered kind, or `undefined`. */
378
+ get(kind: string): RegisteredKind | undefined;
379
+ }
380
+ //#endregion
381
+ //#region src/core/offline/outbox-store.d.ts
382
+ /** The most entries one game's outbox holds. */
383
+ declare const OUTBOX_MAX_ENTRIES = 500;
384
+ /** The most stored characters one game's outbox holds (about 2 MB of `localStorage`). */
385
+ declare const OUTBOX_MAX_CHARS = 1000000;
386
+ /** One game's outbox. */
387
+ declare class OutboxStore {
388
+ /** The key prefix of this game's entries. */
389
+ readonly prefix: string;
390
+ private readonly store;
391
+ /** The outbox for game `slug` in `store`. */
392
+ constructor(slug: string, store: KeyValueStore);
393
+ /** Every well-formed entry, oldest first. Malformed ones are removed. */
394
+ list(): OutboxEntry[];
395
+ /** How many entries are queued. */
396
+ count(): number;
397
+ /** One entry, or `undefined` once it is gone (replayed, or removed by another tab). */
398
+ get(id: string): OutboxEntry | undefined;
399
+ /** Whether `extra` more stored characters in one more entry still fit under the caps. */
400
+ fits(extraChars: number): boolean;
401
+ /** Store an entry (new or updated); `false` when the storage refused it (full or blocked). */
402
+ put(entry: OutboxEntry): boolean;
403
+ /** Forget an entry. */
404
+ remove(id: string): void;
405
+ /** Whether a storage key belongs to this outbox (for cross-tab `storage` events). */
406
+ owns(key: string | null): boolean;
407
+ private entryKeys;
408
+ }
409
+ //#endregion
410
+ //#region src/core/offline/outbox-replayer.d.ts
411
+ /** An op dropped during replay, with why. */
412
+ interface ReplayFailure {
413
+ /** The dropped op. */
414
+ readonly entry: OutboxEntry;
415
+ /** Why it was dropped (the hub's message, or the handler's). */
416
+ readonly error: string;
417
+ }
418
+ /** Why a replay stopped before the outbox was empty. */
419
+ type ReplayStop = 'connection' | 'backoff' | 'unknown-kind' | 'lease';
420
+ /** What one replay did. */
421
+ interface ReplayReport {
422
+ /** The ops that landed, in order. */
423
+ readonly replayed: OutboxEntry[];
424
+ /** The ops dropped. */
425
+ readonly failed: ReplayFailure[];
426
+ /** Why it stopped early, or `undefined` when the outbox is empty. */
427
+ readonly stoppedBy?: ReplayStop;
428
+ }
429
+ //#endregion
430
+ //#region src/core/offline/outbox.d.ts
431
+ /** A queued operation, as `hub.offline` reports it. */
432
+ type OfflineOp = OutboxEntry;
433
+ /** Each outbox event's detail. */
434
+ interface OfflineEventDetails {
435
+ /** An op was queued (or folded into a waiting one, which is then the `op`). */
436
+ queued: {
437
+ readonly op: OfflineOp;
438
+ };
439
+ /** An op landed; `result` is what its handler returned. */
440
+ replayed: {
441
+ readonly op: OfflineOp;
442
+ readonly result?: Json;
443
+ };
444
+ /** An op was dropped: the hub refused it, or it kept failing. */
445
+ failed: {
446
+ readonly op: OfflineOp;
447
+ readonly error: string;
448
+ };
449
+ }
450
+ /** An outbox event's name. */
451
+ type OfflineEventName = keyof OfflineEventDetails;
452
+ /** An outbox event listener. */
453
+ type OfflineListener<Name extends OfflineEventName> = (detail: OfflineEventDetails[Name]) => void;
454
+ /** The code of the error `add` throws when the outbox is full. */
455
+ declare const OUTBOX_FULL_CODE = "offline_queue_full";
456
+ /** What the outbox needs from its client. */
457
+ interface OutboxOptions {
458
+ /** The game whose outbox it is. */
459
+ readonly slug: string;
460
+ /** Where it lives (`localStorage`, or memory). */
461
+ readonly store: KeyValueStore;
462
+ /** The REST client its handlers call through. */
463
+ readonly rest: RestClient;
464
+ /** Fire a window event (the menu listens). */
465
+ readonly emit: (name: string, detail: OfflineEventDetails[OfflineEventName]) => void;
466
+ /** The hub couldn't be reached during a replay. */
467
+ readonly onUnreachable: () => void;
468
+ /** The queue length may have changed. */
469
+ readonly onChange: () => void;
470
+ /** A retry is due: replay again. */
471
+ readonly onRetryDue: () => void;
472
+ readonly now?: () => number;
473
+ }
474
+ /** One game's outbox. */
475
+ declare class Outbox {
476
+ /** The kinds this client can perform. */
477
+ readonly kinds: KindRegistry;
478
+ /** The stored entries. */
479
+ readonly entries: OutboxStore;
480
+ private readonly options;
481
+ private readonly replayer;
482
+ private readonly now;
483
+ private sequence;
484
+ private retryTimer;
485
+ private retryAt;
486
+ private readonly listeners;
487
+ /** The outbox for `options.slug`. */
488
+ constructor(options: OutboxOptions);
489
+ /** Register a kind. */
490
+ define(kind: string, definition: RegisteredKind): void;
491
+ /** A new, not yet stored, op of `kind`. */
492
+ stamp(kind: string, payload: Json): OutboxEntry;
493
+ /**
494
+ * Queue an op, folding it into a waiting one where its kind says so.
495
+ * Throws a {@link HubError} (code {@link OUTBOX_FULL_CODE}) when the
496
+ * outbox is full or the storage refuses it.
497
+ */
498
+ add(op: OutboxEntry): void;
499
+ /** Perform an op now, without queueing it (the online path); throws what its handler throws. */
500
+ runNow(op: OutboxEntry): Promise<Json | undefined>;
501
+ /** Replay what is due, in order. `isEager`: the connection just came back, so ops waiting for it go at once. */
502
+ replay(isEager?: boolean): Promise<ReplayReport>;
503
+ /** The waiting ops, oldest first. */
504
+ pending(): OfflineOp[];
505
+ /** How many ops are waiting. */
506
+ count(): number;
507
+ /** Listen for an event; returns the unsubscribe function. */
508
+ on<Name extends OfflineEventName>(name: Name, listener: OfflineListener<Name>): () => void;
509
+ private fire;
510
+ private contextFor;
511
+ private scheduleRetry;
512
+ private clearRetry;
513
+ }
514
+ //#endregion
515
+ //#region src/core/offline/offline-api.d.ts
516
+ /** What `hub.offline` drives. */
517
+ interface OfflineHost {
518
+ /** The game's outbox. */
519
+ readonly outbox: Outbox;
520
+ /** Replay now when the hub is reachable (and nothing else is replaying). */
521
+ requestSync(): void;
522
+ }
523
+ /** The game-facing outbox API. */
524
+ declare class OfflineApi {
525
+ private readonly host;
526
+ /** The API over `host`. */
527
+ constructor(host: OfflineHost);
528
+ /**
529
+ * Define what an operation of `kind` does when it replays. Define every
530
+ * kind at load, before or after enqueueing: waiting ops of an undefined
531
+ * kind hold the queue until it is defined. `hub.*` kinds are the hub's own.
532
+ */
533
+ define<Payload extends GamePayload>(kind: string, definition: OfflineHandler<Payload> | OfflineKindDefinition<Payload>): void;
534
+ /**
535
+ * Queue an operation of `kind` and replay it as soon as the hub is
536
+ * reachable (at once when online). Resolves the queued op; its outcome
537
+ * arrives as a `replayed` or `failed` event. Throws a `HubError` (code
538
+ * `offline_queue_full`) when the outbox is full.
539
+ */
540
+ enqueue(kind: string, payload: GamePayload): OfflineOp;
541
+ /** The waiting operations (the hub's and the game's), oldest first. */
542
+ pending(): OfflineOp[];
543
+ /** Listen for `queued`, `replayed` or `failed`; returns the unsubscribe function. */
544
+ on<Name extends OfflineEventName>(name: Name, listener: OfflineListener<Name>): () => void;
299
545
  }
300
546
  //#endregion
301
547
  //#region src/core/connection.d.ts
302
- /** A queued write the hub refused during a sync: dropped, with the hub's message. */
548
+ /** A queued op the hub refused during a sync (or that kept failing): dropped, with the reason. */
303
549
  interface SyncConflict {
304
- /** The refused op. */
305
- readonly op: QueueOp;
306
- /** The hub's message. */
550
+ /** The dropped op. */
551
+ readonly op: OfflineOp;
552
+ /** The hub's (or the handler's) message. */
307
553
  readonly error?: string;
308
554
  }
309
555
  /** What one `sync()` did. */
310
556
  interface SyncResult {
311
- /** Queued writes the hub accepted. */
557
+ /** Queued ops that landed. */
312
558
  readonly flushed: number;
313
- /** Queued writes the hub refused (and that were dropped). */
559
+ /** Queued ops that were dropped. */
314
560
  readonly conflicts: SyncConflict[];
315
561
  }
316
562
  /** The game slug's path field, or a {@link HubError} when the slug is unknown. */
@@ -326,12 +572,18 @@ declare class HubConnection {
326
572
  readonly apiBase: string;
327
573
  /** Typed REST calls to {@link apiBase}. */
328
574
  protected readonly rest: RestClient;
329
- /** This game's offline cache, queue and event buffer. */
575
+ /** This game's offline cache and event buffer. */
330
576
  protected readonly store: LocalStore;
577
+ /** This game's queued operations. */
578
+ protected readonly outbox: Outbox;
331
579
  private readonly offlineMode;
332
580
  private isReachable;
333
- private isSyncing;
581
+ private runningSync;
582
+ private followingSync;
583
+ private isFollowingEager;
584
+ private directSend;
334
585
  private lastPrefetchAt;
586
+ private offlineApi;
335
587
  private readonly statusListeners;
336
588
  /** A connection for `options` (slug and API base default to the page's). */
337
589
  constructor(options?: HubOptions);
@@ -339,13 +591,18 @@ declare class HubConnection {
339
591
  get isOffline(): boolean;
340
592
  /** `true` while the hub is reachable. */
341
593
  get isOnline(): boolean;
342
- /** Queued writes plus buffered analytics events waiting to sync. */
594
+ /**
595
+ * The offline outbox: define your own kinds of operation, queue them, and
596
+ * hear how they replay (`hub.offline.define`, `enqueue`, `pending`, `on`).
597
+ */
598
+ get offline(): OfflineApi;
599
+ /** Queued operations plus buffered analytics events waiting to sync. */
343
600
  pending(): number;
344
601
  /** Subscribe to connection and sync status changes; returns the unsubscribe function. */
345
602
  onStatus(listener: (status: HubStatus) => void): () => void;
346
603
  /** Tell `onStatus` listeners and the page (`hub:status`) the current status. */
347
604
  protected notifyStatus(): void;
348
- /** Record reachability; coming back online syncs the queue and re-warms the cache. */
605
+ /** Record reachability; coming back online replays the outbox and re-warms the cache. */
349
606
  protected setReachable(isReachableNow: boolean): void;
350
607
  /** `{ slug }` for this game's endpoints; throws when the slug is unknown. */
351
608
  protected gameFields(): GameFields;
@@ -355,23 +612,38 @@ declare class HubConnection {
355
612
  * status) always reach the caller.
356
613
  */
357
614
  protected withFallback<Reply>(networkCall: () => Promise<Reply>, offlineAnswer: () => Reply): Promise<Reply>;
358
- /** Send one queued write. */
359
- private sendOp;
360
615
  /**
361
- * Apply a write to the offline cache at once, then send it now (online
362
- * with an empty queue) or queue it behind the others. Resolves with the
363
- * local answer; a real API error on the direct path reaches the caller and
364
- * is not queued.
616
+ * Apply a write to the offline cache at once, then perform it as an op of
617
+ * `kind`: sent now when online with nothing waiting, else queued behind
618
+ * the others. Resolves with the local answer (or, sent now, with
619
+ * `replyAnswer`'s reading of the hub's reply). A real API error on the
620
+ * direct path reaches the caller and is not queued; a transport failure
621
+ * queues the op under the same id, so if the request did land, its replay
622
+ * is recognised by the hub and not applied twice.
365
623
  */
366
- protected mutateQueued<Reply>(input: QueueOpInput, localAnswer: () => Reply): Promise<Reply>;
624
+ protected mutateOffline<Reply>(kind: string, payload: Json, localAnswer: () => Reply, replyAnswer?: (result: Json | undefined) => Reply | undefined): Promise<Reply>;
367
625
  /**
368
- * Replay the queue, then the buffered events, in order. Stops at the first
369
- * transport failure (offline again: the rest stays queued); a write the hub
370
- * refuses is dropped and reported as a conflict.
626
+ * Replay the outbox, then the buffered events, in order. Stops at the
627
+ * first transport failure (offline again: the rest stays queued); an op
628
+ * the hub refuses is dropped and reported as a conflict.
371
629
  */
372
630
  sync(): Promise<SyncResult>;
631
+ /** A retry came due: try again even when the hub was last unreachable (the try is the probe), unless the browser itself is offline. */
632
+ private retrySync;
633
+ /**
634
+ * One replay at a time per client. A call during one queues a single
635
+ * follow-up replay (eager if any caller asked for that), so an op queued
636
+ * or a reconnect that happens mid-replay is never missed.
637
+ */
638
+ private replayAll;
639
+ private startReplay;
640
+ private runReplay;
373
641
  /** Send the buffered analytics events; a refused one is dropped (telemetry never blocks). */
374
642
  private flushEvents;
643
+ /** Move a v1 copy's queued writes into the outbox, in their order. */
644
+ private importLegacyQueue;
645
+ /** Follow the browser's connection, other tabs' outbox changes, and replay what an earlier page left queued. */
646
+ private listenToPage;
375
647
  /**
376
648
  * Warm the offline cache for every game the player has touched, in one
377
649
  * request, so going offline later still shows complete progress.
@@ -509,7 +781,7 @@ declare class HubEconomy extends HubProgress {
509
781
  favorites(): Promise<{
510
782
  games: string[];
511
783
  }>;
512
- /** Star (`isOn = true`) or unstar a game. Needs a connection. */
784
+ /** Star (`isOn = true`) or unstar a game. Offline, the local list changes at once and the hub's when it is back. */
513
785
  setFavorite(slug: string, isOn: boolean): Promise<{
514
786
  games: string[];
515
787
  }>;
@@ -519,9 +791,16 @@ declare class HubEconomy extends HubProgress {
519
791
  getInventory(): Promise<InventorySnapshot>;
520
792
  /** Another player's available holdings (to compose a trade). */
521
793
  playerInventory(userId: number): Promise<InventorySnapshot>;
522
- /** Add goods to the player (gameplay rewards); answers the new holdings. */
794
+ /**
795
+ * Add goods to the player (gameplay rewards); answers the new holdings.
796
+ * Offline, the cached holdings change at once and the grant replays later.
797
+ */
523
798
  grant(bundle: GrantBundle): Promise<EndpointReply<'grantInventoryItems'>>;
524
- /** An atomic swap with the house: remove `take`, add `give`. */
799
+ /**
800
+ * An atomic swap with the house: remove `take`, add `give`. Offline it is
801
+ * checked against the cached holdings (409 when they can't cover `take`),
802
+ * applied to them at once, and replayed later; the hub has the last word.
803
+ */
525
804
  exchange(take?: TradeBundle, give?: TradeBundle): Promise<EndpointReply<'exchangeInventoryItems'>>;
526
805
  /** Sell items to the house for coins. */
527
806
  sell(items: Record<string, number>, coins: number): Promise<EndpointReply<'exchangeInventoryItems'>>;
@@ -700,7 +979,7 @@ declare class ContentRejectedError extends HubError {
700
979
  //#endregion
701
980
  //#region src/core/version/client-version.gen.d.ts
702
981
  /** This client's package version, sent as `x-hub-client` on REST calls and `client` in `hello`. */
703
- declare const HUB_CLIENT_VERSION = "2.0.0-next.1";
982
+ declare const HUB_CLIENT_VERSION = "2.0.0-next.3";
704
983
  //#endregion
705
- export { SubmitScoreResult as $, BoardWithTop as A, Json$1 as B, CLIENT_VERSION_HEADER as C, QueuedScoreOptions as D, QueueOpInput as E, GlobalAnalytics as F, Profile as G, LeaderboardResult as H, HubOptions as I, SaveMeta as J, ProfileSummary as K, HubStatus as L, GameInfo$1 as M, GameLeaderboards as N, BufferedEvent as O, GameRecords as P, SubmitScoreOptions as Q, Inventory as R, SyncResult as S, QueueOp as T, MeResponse as U, LeaderboardEntry as V, Metrics$1 as W, SortDir$1 as X, SnapshotResponse as Y, Stats$1 as Z, TradeNoteOptions as _, HubErrorDetails as a, StatResult as b, Hub as c, ClientSupport as d, User as et, HubMenuControl as f, TradeListOptions as g, TradeId as h, HubErrorCode as i, GamePayload as it, GameAnalytics as j, Board$1 as k, createHub as l, TradeBundle as m, ContentRejectedError as n, EndpointName as nt, OfflineError as o, GrantBundle as p, Save as q, HubError as r, EndpointReply as rt, UNSUPPORTED_BY_HUB as s, HUB_CLIENT_VERSION as t, EndpointFields as tt, hub as u, AuthResponse as v, ProfilePatch as w, SyncConflict as x, ProfileUpdate as y, InventorySnapshot as z };
984
+ export { LeaderboardResult as $, OUTBOX_MAX_ENTRIES as A, Board$1 as B, OfflineApi as C, OfflineListener as D, OfflineEventName as E, ProfilePatch as F, GameRecords as G, GameAnalytics as H, QueueOp as I, HubStatus as J, GlobalAnalytics as K, QueueOpInput as L, OfflineKindDefinition as M, ReplayContext as N, OfflineOp as O, CLIENT_VERSION_HEADER as P, LeaderboardEntry as Q, QueuedScoreOptions as R, SyncResult as S, OfflineEventDetails as T, GameInfo$1 as U, BoardWithTop as V, GameLeaderboards as W, InventorySnapshot as X, Inventory$1 as Y, Json$1 as Z, TradeNoteOptions as _, HubErrorDetails as a, SaveMeta as at, StatResult as b, Hub as c, Stats$1 as ct, ClientSupport as d, User as dt, MeResponse as et, HubMenuControl as f, EndpointFields as ft, TradeListOptions as g, TradeId as h, GamePayload as ht, HubErrorCode as i, Save as it, OfflineHandler as j, OUTBOX_MAX_CHARS as k, createHub as l, SubmitScoreOptions as lt, TradeBundle as m, EndpointReply as mt, ContentRejectedError as n, Profile as nt, OfflineError as o, SnapshotResponse as ot, GrantBundle as p, EndpointName as pt, HubOptions as q, HubError as r, ProfileSummary as rt, UNSUPPORTED_BY_HUB as s, SortDir$1 as st, HUB_CLIENT_VERSION as t, Metrics$1 as tt, hub as u, SubmitScoreResult as ut, AuthResponse as v, OUTBOX_FULL_CODE as w, SyncConflict as x, ProfileUpdate as y, BufferedEvent as z };
706
985
  //# 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/connection.ts","../../src/core/hub-progress.ts","../../src/core/hub-economy.ts","../../src/core/menu-control.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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"}
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/connection.ts","../../src/core/hub-progress.ts","../../src/core/hub-economy.ts","../../src/core/menu-control.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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"}
@@ -375,6 +375,7 @@ declare class InputSystem implements ControlsPanelHost, PageInputControl {
375
375
  private activeSource;
376
376
  private isPageOwner;
377
377
  private pageOwner;
378
+ private readonly modality;
378
379
  constructor(host: InputHost, options?: InputSystemOptions);
379
380
  /** Whether this page counts as a touch device. */
380
381
  get touchDevice(): boolean;
@@ -491,11 +492,52 @@ declare function parseInputOverrides(saved: unknown): InputOverrides;
491
492
  */
492
493
  declare function getInput(options?: InputOptions): InputSystem;
493
494
  //#endregion
495
+ //#region src/input/focus-ring.d.ts
496
+ /**
497
+ * The hub's focus ring: a two-tone box-shadow (a dark gap, then a light ring)
498
+ * that follows the element's own border-radius and shows on light and dark
499
+ * buttons alike. Pages tune it with CSS variables:
500
+ * `--hub-focus-color` (the ring), `--hub-focus-inner` (the gap),
501
+ * `--hub-focus-width` and `--hub-focus-gap`.
502
+ */
503
+ /** The ring as a `box-shadow` value. */
504
+ declare const FOCUS_RING_SHADOW = "0 0 0 var(--hub-focus-gap, 2px) var(--hub-focus-inner, rgba(13, 15, 20, 0.85)), 0 0 0 calc(var(--hub-focus-gap, 2px) + var(--hub-focus-width, 3px)) var(--hub-focus-color, #fff)";
505
+ //#endregion
506
+ //#region src/input/modality.d.ts
507
+ /** `keys`: keyboard or gamepad. `pointer`: mouse or pen. `touch`: a finger. */
508
+ type InputModality = 'keys' | 'pointer' | 'touch';
509
+ /** The `<html>` attribute that holds the modality. */
510
+ declare const MODALITY_ATTRIBUTE = "data-hub-input";
511
+ /** Where the modality is stored: `<html>`, or a fake in tests. */
512
+ interface ModalityRoot {
513
+ getAttribute(name: string): string | null;
514
+ setAttribute(name: string, value: string): void;
515
+ }
516
+ /** Reads and writes the page's modality attribute. */
517
+ declare class ModalityTracker {
518
+ private readonly root;
519
+ /** Start at `initial` unless another copy already set the attribute. */
520
+ constructor(root: ModalityRoot, initial: InputModality);
521
+ /** The last modality used. */
522
+ get current(): InputModality;
523
+ /** Whether focus should show: the last input was a keyboard or gamepad. */
524
+ get showsFocus(): boolean;
525
+ /** Record the modality the player just used. */
526
+ set(modality: InputModality): void;
527
+ /** A key went down (`isTyping`: in a text field). */
528
+ noteKey(key: string, isTyping: boolean): void;
529
+ /** A pointer went down. */
530
+ notePointer(pointerType: string): void;
531
+ private readAttribute;
532
+ }
533
+ /** Track the page's modality (once per bundle) and add the focus styles (once per page). */
534
+ declare function trackInputModality(): ModalityTracker;
535
+ //#endregion
494
536
  //#region src/input/nav-state.d.ts
495
537
  /** What a navigable list draws with (the overlay). */
496
538
  interface NavHighlighter {
497
- /** Ring the highlighted element. */
498
- showHighlight(bounds: Rect): void;
539
+ /** Ring the highlighted element, following its corner radius (a CSS `border-radius`, or empty). */
540
+ showHighlight(bounds: Rect, radius: string): void;
499
541
  /** Remove the ring. */
500
542
  hideHighlight(): void;
501
543
  /** Open the on-screen keyboard for a text field. */
@@ -591,8 +633,8 @@ declare class Overlay implements NavHighlighter {
591
633
  setInsets(insets: Partial<Insets>): void;
592
634
  /** Re-place every control for the current viewport, keeping the player's dragged spots. */
593
635
  layout(): void;
594
- /** Ring the highlighted element. */
595
- showHighlight(bounds: Rect): void;
636
+ /** Ring the highlighted element, for keyboard and gamepad players only (never after a tap or click). */
637
+ showHighlight(bounds: Rect, radius: string): void;
596
638
  /** Remove the ring. */
597
639
  hideHighlight(): void;
598
640
  /** Open the on-screen keyboard for a text field. */
@@ -726,5 +768,5 @@ declare function getUiStack(): UiStack;
726
768
  /** Bump when the UiStack contract gains behaviour; idle older instances are replaced. */
727
769
  declare const UI_STACK_VERSION = 1;
728
770
  //#endregion
729
- export { VirtualControlType as $, AxisSide as A, InputReading as B, parseInputOverrides as C, isPageInputControl as D, PageInputControl as E, InputConfig as F, NavElement as G, MenuBridge as H, InputDef as I, NavTarget as J, NavElementKind as K, InputEvents as L, EdgeOffsets as M, GamepadMapping as N, Anchor as O, GroupDef as P, Vector as Q, InputHost as R, isInputSystem as S, InputSystemOptions as T, MouseMapping as U, InputSource as V, NavBlurEvent as W, Rect as X, NavigableDef as Y, TouchMapping as Z, boxesTouch as _, OverlayEdge as a, InputOptions as b, OverlayReason as c, LayoutOptions as d, VirtualDef as et, layoutControls as f, LayoutItem as g, LayoutBox as h, AutoPauseOptions as i, DraggedSpot as j, AxisDef as k, UiStack as l, Insets as m, getUiStack as n, VirtualOverride as nt, OverlayEvent as o, Overlay as p, NavFocusEvent as q, isUiStack as r, OverlayListener as s, UI_STACK_VERSION as t, VirtualInputs as tt, UiStackHandoff as u, controlSize as v, InputSystem as w, getInput as x, INPUT_SINGLETON_API as y, InputOverrides as z };
771
+ export { NavigableDef as $, PageInputControl as A, InputDef as B, INPUT_SINGLETON_API as C, parseInputOverrides as D, isInputSystem as E, DraggedSpot as F, InputSource as G, InputHost as H, EdgeOffsets as I, NavBlurEvent as J, MenuBridge as K, GamepadMapping as L, Anchor as M, AxisDef as N, InputSystem as O, AxisSide as P, NavTarget as Q, GroupDef as R, FOCUS_RING_SHADOW as S, getInput as T, InputOverrides as U, InputEvents as V, InputReading as W, NavElementKind as X, NavElement as Y, NavFocusEvent as Z, boxesTouch as _, OverlayEdge as a, VirtualInputs as at, MODALITY_ATTRIBUTE as b, OverlayReason as c, LayoutOptions as d, Rect as et, layoutControls as f, LayoutItem as g, LayoutBox as h, AutoPauseOptions as i, VirtualDef as it, isPageInputControl as j, InputSystemOptions as k, UiStack as l, Insets as m, getUiStack as n, Vector as nt, OverlayEvent as o, VirtualOverride as ot, Overlay as p, MouseMapping as q, isUiStack as r, VirtualControlType as rt, OverlayListener as s, UI_STACK_VERSION as t, TouchMapping as tt, UiStackHandoff as u, controlSize as v, InputOptions as w, trackInputModality as x, InputModality as y, InputConfig as z };
730
772
  //# sourceMappingURL=input.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"input.d.ts","names":[],"sources":["../../src/input/types.ts","../../src/overlay/controls-panel.ts","../../src/input/page-control.ts","../../src/input/input-system.ts","../../src/input/page-input.ts","../../src/input/nav-state.ts","../../src/overlay/layout-geometry.ts","../../src/overlay/virtual-controls.ts","../../src/overlay/overlay.ts","../../src/overlay/layout.ts","../../src/uistack/types.ts","../../src/uistack/page-stack.ts","../../src/uistack/ui-stack.ts"],"mappings":"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"}
1
+ {"version":3,"file":"input.d.ts","names":[],"sources":["../../src/input/types.ts","../../src/overlay/controls-panel.ts","../../src/input/page-control.ts","../../src/input/input-system.ts","../../src/input/page-input.ts","../../src/input/focus-ring.ts","../../src/input/modality.ts","../../src/input/nav-state.ts","../../src/overlay/layout-geometry.ts","../../src/overlay/virtual-controls.ts","../../src/overlay/overlay.ts","../../src/overlay/layout.ts","../../src/uistack/types.ts","../../src/uistack/page-stack.ts","../../src/uistack/ui-stack.ts"],"mappings":"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"}