@jgengine/convex 0.49.0 → 0.50.0

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/dist/server.d.ts CHANGED
@@ -16,13 +16,13 @@ export { JG_MAX_MEMBERS_PER_SERVER, canJoinPrivateServer, isListablePublicly, va
16
16
  export declare function jgengineTables(): {
17
17
  jgGameServers: import("convex/server").TableDefinition<import("convex/values").VObject<{
18
18
  createdAt: number;
19
- dirtyAt?: number | undefined;
19
+ dirtyAt?: number;
20
20
  gameId: string;
21
- joinCode?: string | undefined;
22
- lastSavedAt?: number | undefined;
23
- memberCount?: number | undefined;
21
+ joinCode?: string;
22
+ lastSavedAt?: number;
23
+ memberCount?: number;
24
24
  memberUserIds: string[];
25
- mode?: string | undefined;
25
+ mode?: string;
26
26
  modeConfig?: any;
27
27
  revision: number;
28
28
  save: "none" | {
@@ -34,9 +34,9 @@ export declare function jgengineTables(): {
34
34
  slotsPerServer: number;
35
35
  status: "closed" | "open" | "running";
36
36
  tickAnchorMs: number;
37
- topology?: "rooms" | "shared" | undefined;
37
+ topology?: "rooms" | "shared";
38
38
  updatedAt: number;
39
- visibility?: "private" | "public" | undefined;
39
+ visibility?: "private" | "public";
40
40
  }, {
41
41
  gameId: import("convex/values").VString<string, "required">;
42
42
  status: import("convex/values").VUnion<"closed" | "open" | "running", [import("convex/values").VLiteral<"open", "required">, import("convex/values").VLiteral<"running", "required">, import("convex/values").VLiteral<"closed", "required">], "required", never>;
@@ -75,7 +75,7 @@ export declare function jgengineTables(): {
75
75
  jgServerCapacity: import("convex/server").TableDefinition<import("convex/values").VObject<{
76
76
  gameId: string;
77
77
  memberCount: number;
78
- mode?: string | undefined;
78
+ mode?: string;
79
79
  serverId: GenericId<"jgGameServers">;
80
80
  slotsPerServer: number;
81
81
  status: "closed" | "open" | "running";
@@ -92,7 +92,7 @@ export declare function jgengineTables(): {
92
92
  jgServerMembers: import("convex/server").TableDefinition<import("convex/values").VObject<{
93
93
  joinedAt: number;
94
94
  serverId: GenericId<"jgGameServers">;
95
- sessionIds?: string[] | undefined;
95
+ sessionIds?: string[];
96
96
  userId: string;
97
97
  }, {
98
98
  serverId: import("convex/values").VId<GenericId<"jgGameServers">, "required">;
@@ -133,11 +133,11 @@ export declare function jgengineTables(): {
133
133
  }, {}, {}>;
134
134
  jgPlayerProfiles: import("convex/server").TableDefinition<import("convex/values").VObject<{
135
135
  createdAt: number;
136
- dirtyAt?: number | undefined;
136
+ dirtyAt?: number;
137
137
  gameId: string;
138
138
  playerState: any;
139
139
  revision: number;
140
- sessionServerId?: GenericId<"jgGameServers"> | undefined;
140
+ sessionServerId?: GenericId<"jgGameServers">;
141
141
  sessionState?: any;
142
142
  updatedAt: number;
143
143
  userId: string;
@@ -156,7 +156,7 @@ export declare function jgengineTables(): {
156
156
  }, {}, {}>;
157
157
  jgWorldChunks: import("convex/server").TableDefinition<import("convex/values").VObject<{
158
158
  chunkKey: string;
159
- dirtyAt?: number | undefined;
159
+ dirtyAt?: number;
160
160
  serverId: GenericId<"jgGameServers">;
161
161
  snapshot: any;
162
162
  updatedAt: number;
@@ -173,7 +173,7 @@ export declare function jgengineTables(): {
173
173
  jgLeaderboardRows: import("convex/server").TableDefinition<import("convex/values").VObject<{
174
174
  gameId: string;
175
175
  scope: "global" | "profile" | "server";
176
- serverId?: GenericId<"jgGameServers"> | undefined;
176
+ serverId?: GenericId<"jgGameServers">;
177
177
  stat: string;
178
178
  updatedAt: number;
179
179
  userId: string;
@@ -204,17 +204,17 @@ export declare function jgengineTables(): {
204
204
  by_server_and_action: ["serverId", "action", "_creationTime"];
205
205
  }, {}, {}>;
206
206
  jgPoses: import("convex/server").TableDefinition<import("convex/values").VObject<{
207
- chunkKey?: string | undefined;
208
- homeGameId?: string | undefined;
209
- kind?: string | undefined;
210
- label?: string | undefined;
211
- lastWorldSnapshotAt?: number | undefined;
212
- ownerActorId?: string | undefined;
213
- revokedAt?: number | undefined;
207
+ chunkKey?: string;
208
+ homeGameId?: string;
209
+ kind?: string;
210
+ label?: string;
211
+ lastWorldSnapshotAt?: number;
212
+ ownerActorId?: string;
213
+ revokedAt?: number;
214
214
  rotationPitch: number;
215
215
  rotationY: number;
216
216
  serverId: string;
217
- sessionId?: string | undefined;
217
+ sessionId?: string;
218
218
  updatedAt: number;
219
219
  userId: string;
220
220
  x: number;
@@ -255,7 +255,7 @@ export declare function jgengineTables(): {
255
255
  }, {}, {}>;
256
256
  jgChatMessages: import("convex/server").TableDefinition<import("convex/values").VObject<{
257
257
  at: number;
258
- authorName?: string | undefined;
258
+ authorName?: string;
259
259
  body: string;
260
260
  channelId: string;
261
261
  serverId: string;
@@ -307,13 +307,13 @@ export declare function jgengineHostedTables(): {
307
307
  declare const schemaForTypes: import("convex/server").SchemaDefinition<{
308
308
  jgGameServers: import("convex/server").TableDefinition<import("convex/values").VObject<{
309
309
  createdAt: number;
310
- dirtyAt?: number | undefined;
310
+ dirtyAt?: number;
311
311
  gameId: string;
312
- joinCode?: string | undefined;
313
- lastSavedAt?: number | undefined;
314
- memberCount?: number | undefined;
312
+ joinCode?: string;
313
+ lastSavedAt?: number;
314
+ memberCount?: number;
315
315
  memberUserIds: string[];
316
- mode?: string | undefined;
316
+ mode?: string;
317
317
  modeConfig?: any;
318
318
  revision: number;
319
319
  save: "none" | {
@@ -325,9 +325,9 @@ declare const schemaForTypes: import("convex/server").SchemaDefinition<{
325
325
  slotsPerServer: number;
326
326
  status: "closed" | "open" | "running";
327
327
  tickAnchorMs: number;
328
- topology?: "rooms" | "shared" | undefined;
328
+ topology?: "rooms" | "shared";
329
329
  updatedAt: number;
330
- visibility?: "private" | "public" | undefined;
330
+ visibility?: "private" | "public";
331
331
  }, {
332
332
  gameId: import("convex/values").VString<string, "required">;
333
333
  status: import("convex/values").VUnion<"closed" | "open" | "running", [import("convex/values").VLiteral<"open", "required">, import("convex/values").VLiteral<"running", "required">, import("convex/values").VLiteral<"closed", "required">], "required", never>;
@@ -366,7 +366,7 @@ declare const schemaForTypes: import("convex/server").SchemaDefinition<{
366
366
  jgServerCapacity: import("convex/server").TableDefinition<import("convex/values").VObject<{
367
367
  gameId: string;
368
368
  memberCount: number;
369
- mode?: string | undefined;
369
+ mode?: string;
370
370
  serverId: GenericId<"jgGameServers">;
371
371
  slotsPerServer: number;
372
372
  status: "closed" | "open" | "running";
@@ -383,7 +383,7 @@ declare const schemaForTypes: import("convex/server").SchemaDefinition<{
383
383
  jgServerMembers: import("convex/server").TableDefinition<import("convex/values").VObject<{
384
384
  joinedAt: number;
385
385
  serverId: GenericId<"jgGameServers">;
386
- sessionIds?: string[] | undefined;
386
+ sessionIds?: string[];
387
387
  userId: string;
388
388
  }, {
389
389
  serverId: import("convex/values").VId<GenericId<"jgGameServers">, "required">;
@@ -424,11 +424,11 @@ declare const schemaForTypes: import("convex/server").SchemaDefinition<{
424
424
  }, {}, {}>;
425
425
  jgPlayerProfiles: import("convex/server").TableDefinition<import("convex/values").VObject<{
426
426
  createdAt: number;
427
- dirtyAt?: number | undefined;
427
+ dirtyAt?: number;
428
428
  gameId: string;
429
429
  playerState: any;
430
430
  revision: number;
431
- sessionServerId?: GenericId<"jgGameServers"> | undefined;
431
+ sessionServerId?: GenericId<"jgGameServers">;
432
432
  sessionState?: any;
433
433
  updatedAt: number;
434
434
  userId: string;
@@ -447,7 +447,7 @@ declare const schemaForTypes: import("convex/server").SchemaDefinition<{
447
447
  }, {}, {}>;
448
448
  jgWorldChunks: import("convex/server").TableDefinition<import("convex/values").VObject<{
449
449
  chunkKey: string;
450
- dirtyAt?: number | undefined;
450
+ dirtyAt?: number;
451
451
  serverId: GenericId<"jgGameServers">;
452
452
  snapshot: any;
453
453
  updatedAt: number;
@@ -464,7 +464,7 @@ declare const schemaForTypes: import("convex/server").SchemaDefinition<{
464
464
  jgLeaderboardRows: import("convex/server").TableDefinition<import("convex/values").VObject<{
465
465
  gameId: string;
466
466
  scope: "global" | "profile" | "server";
467
- serverId?: GenericId<"jgGameServers"> | undefined;
467
+ serverId?: GenericId<"jgGameServers">;
468
468
  stat: string;
469
469
  updatedAt: number;
470
470
  userId: string;
@@ -495,17 +495,17 @@ declare const schemaForTypes: import("convex/server").SchemaDefinition<{
495
495
  by_server_and_action: ["serverId", "action", "_creationTime"];
496
496
  }, {}, {}>;
497
497
  jgPoses: import("convex/server").TableDefinition<import("convex/values").VObject<{
498
- chunkKey?: string | undefined;
499
- homeGameId?: string | undefined;
500
- kind?: string | undefined;
501
- label?: string | undefined;
502
- lastWorldSnapshotAt?: number | undefined;
503
- ownerActorId?: string | undefined;
504
- revokedAt?: number | undefined;
498
+ chunkKey?: string;
499
+ homeGameId?: string;
500
+ kind?: string;
501
+ label?: string;
502
+ lastWorldSnapshotAt?: number;
503
+ ownerActorId?: string;
504
+ revokedAt?: number;
505
505
  rotationPitch: number;
506
506
  rotationY: number;
507
507
  serverId: string;
508
- sessionId?: string | undefined;
508
+ sessionId?: string;
509
509
  updatedAt: number;
510
510
  userId: string;
511
511
  x: number;
@@ -546,7 +546,7 @@ declare const schemaForTypes: import("convex/server").SchemaDefinition<{
546
546
  }, {}, {}>;
547
547
  jgChatMessages: import("convex/server").TableDefinition<import("convex/values").VObject<{
548
548
  at: number;
549
- authorName?: string | undefined;
549
+ authorName?: string;
550
550
  body: string;
551
551
  channelId: string;
552
552
  serverId: string;
@@ -626,7 +626,7 @@ export type RunCommandOutcome = {
626
626
  };
627
627
  /** Arguments of the `runCommand` mutation, and of the equivalent {@link GameServerHelpers.runCommand} helper. */
628
628
  export type ConvexRunCommandArgs = RunCommandArgs & {
629
- externalId?: string;
629
+ externalId?: string | undefined;
630
630
  /**
631
631
  * How much of the server to hydrate before applying the command. Overrides whatever the
632
632
  * {@link CommandDef} declares through its own `scope`; omit both to hydrate the whole world.
@@ -723,42 +723,42 @@ export declare function createGameServerFunctions(options?: {
723
723
  allowedFeedActions?: readonly string[];
724
724
  }): {
725
725
  joinServer: import("convex/server").RegisteredMutation<"public", {
726
- externalId?: string | undefined;
726
+ externalId?: string;
727
727
  gameId: string;
728
- joinCode?: string | undefined;
729
- mode?: string | undefined;
728
+ joinCode?: string;
729
+ mode?: string;
730
730
  modeConfig?: any;
731
- serverId?: GenericId<"jgGameServers"> | undefined;
732
- sessionId?: string | undefined;
733
- visibility?: "private" | "public" | undefined;
731
+ serverId?: GenericId<"jgGameServers">;
732
+ sessionId?: string;
733
+ visibility?: "private" | "public";
734
734
  }, Promise<EnsureJoinedOutcome>>;
735
735
  leaveServer: import("convex/server").RegisteredMutation<"public", {
736
- externalId?: string | undefined;
736
+ externalId?: string;
737
737
  serverId: GenericId<"jgGameServers">;
738
- sessionId?: string | undefined;
738
+ sessionId?: string;
739
739
  }, Promise<null>>;
740
740
  runCommand: import("convex/server").RegisteredMutation<"public", {
741
741
  command: string;
742
- externalId?: string | undefined;
742
+ externalId?: string;
743
743
  input: any;
744
744
  scope?: {
745
- chunkKeys?: string[] | undefined;
746
- players?: string[] | undefined;
747
- } | undefined;
745
+ chunkKeys?: string[];
746
+ players?: string[];
747
+ };
748
748
  serverId: GenericId<"jgGameServers">;
749
749
  }, Promise<RunCommandOutcome>>;
750
750
  flushSave: import("convex/server").RegisteredMutation<"public", {
751
- externalId?: string | undefined;
751
+ externalId?: string;
752
752
  serverId: GenericId<"jgGameServers">;
753
753
  }, Promise<boolean>>;
754
754
  getServer: import("convex/server").RegisteredQuery<"public", {
755
- externalId?: string | undefined;
755
+ externalId?: string;
756
756
  serverId: GenericId<"jgGameServers">;
757
757
  }, Promise<{
758
758
  _id: GenericId<"jgGameServers">;
759
759
  gameId: string;
760
760
  status: "closed" | "open" | "running";
761
- mode: string | undefined;
761
+ mode?: string;
762
762
  memberUserIds: string[];
763
763
  slotsPerServer: number;
764
764
  save: "none" | {
@@ -773,30 +773,30 @@ export declare function createGameServerFunctions(options?: {
773
773
  updatedAt: number;
774
774
  } | null>>;
775
775
  getServerMeta: import("convex/server").RegisteredQuery<"public", {
776
- externalId?: string | undefined;
776
+ externalId?: string;
777
777
  serverId: GenericId<"jgGameServers">;
778
- }, Promise<{
778
+ }, Promise<import("@jgengine/core/data/definedOnly").DefinedOnly<{
779
779
  _id: GenericId<"jgGameServers">;
780
780
  gameId: string;
781
781
  status: "closed" | "open" | "running";
782
782
  mode: string | undefined;
783
783
  memberCount: number;
784
784
  slotsPerServer: number;
785
- } | null>>;
785
+ }> | null>>;
786
786
  getServerCapacity: import("convex/server").RegisteredQuery<"public", {
787
- externalId?: string | undefined;
787
+ externalId?: string;
788
788
  serverId: GenericId<"jgGameServers">;
789
- }, Promise<{
789
+ }, Promise<import("@jgengine/core/data/definedOnly").DefinedOnly<{
790
790
  _id: GenericId<"jgGameServers">;
791
791
  gameId: string;
792
792
  status: "closed" | "open" | "running";
793
793
  mode: string | undefined;
794
794
  memberCount: number;
795
795
  slotsPerServer: number;
796
- } | null>>;
796
+ }> | null>>;
797
797
  getChunks: import("convex/server").RegisteredQuery<"public", {
798
798
  chunkKeys: string[];
799
- externalId?: string | undefined;
799
+ externalId?: string;
800
800
  serverId: GenericId<"jgGameServers">;
801
801
  }, Promise<{
802
802
  chunkKey: string;
@@ -804,7 +804,7 @@ export declare function createGameServerFunctions(options?: {
804
804
  updatedAt: number;
805
805
  }[]>>;
806
806
  getPlayerProfile: import("convex/server").RegisteredQuery<"public", {
807
- externalId?: string | undefined;
807
+ externalId?: string;
808
808
  gameId: string;
809
809
  }, Promise<{
810
810
  userId: string;
@@ -815,27 +815,28 @@ export declare function createGameServerFunctions(options?: {
815
815
  } | null>>;
816
816
  getFeed: import("convex/server").RegisteredQuery<"public", {
817
817
  action: string;
818
- externalId?: string | undefined;
818
+ externalId?: string;
819
819
  serverId: GenericId<"jgGameServers">;
820
820
  }, Promise<any[]>>;
821
821
  pushFeedEntry: import("convex/server").RegisteredMutation<"public", {
822
822
  action: string;
823
823
  entry: any;
824
- externalId?: string | undefined;
824
+ externalId?: string;
825
825
  serverId: GenericId<"jgGameServers">;
826
826
  }, Promise<null>>;
827
827
  listOpenServers: import("convex/server").RegisteredQuery<"public", {
828
- externalId?: string | undefined;
828
+ externalId?: string;
829
829
  gameId: string;
830
- limit?: number | undefined;
831
- }, Promise<{
830
+ limit?: number;
831
+ }, Promise<({
832
832
  _id: GenericId<"jgGameServers">;
833
833
  status: "closed" | "open" | "running";
834
834
  memberCount: number;
835
835
  slotsPerServer: number;
836
- mode: string | undefined;
837
836
  updatedAt: number;
838
- }[]>>;
837
+ } & {
838
+ mode?: string;
839
+ })[]>>;
839
840
  tickActiveServers: import("convex/server").RegisteredMutation<"internal", {}, Promise<{
840
841
  ticked: number;
841
842
  saved: number;
@@ -850,18 +851,18 @@ export declare function createLeaderboardFunctions(options?: {
850
851
  auth?: JgAuthMode;
851
852
  }): {
852
853
  getTop: import("convex/server").RegisteredQuery<"public", {
853
- externalId?: string | undefined;
854
+ externalId?: string;
854
855
  gameId: string;
855
- limit?: number | undefined;
856
+ limit?: number;
856
857
  scope: "global" | "profile" | "server";
857
- serverId?: GenericId<"jgGameServers"> | undefined;
858
+ serverId?: GenericId<"jgGameServers">;
858
859
  stat: string;
859
860
  }, Promise<{
860
861
  userId: string;
861
862
  value: number;
862
863
  }[]>>;
863
864
  getProfile: import("convex/server").RegisteredQuery<"public", {
864
- externalId?: string | undefined;
865
+ externalId?: string;
865
866
  gameId: string;
866
867
  userId: string;
867
868
  }, Promise<Record<string, number>>>;
@@ -869,7 +870,7 @@ export declare function createLeaderboardFunctions(options?: {
869
870
  entries: {
870
871
  by: number;
871
872
  scope: "global" | "profile" | "server";
872
- serverId?: GenericId<"jgGameServers"> | undefined;
873
+ serverId?: GenericId<"jgGameServers">;
873
874
  stat: string;
874
875
  userId: string;
875
876
  }[];
@@ -925,7 +926,7 @@ export declare function createPresenceFunctions(options?: {
925
926
  resolveSpawn?: (ctx: JGMutationCtx, args: {
926
927
  serverId: string;
927
928
  userId: string;
928
- kind?: string;
929
+ kind?: string | undefined;
929
930
  }) => Promise<{
930
931
  x: number;
931
932
  y: number;
@@ -937,28 +938,28 @@ export declare function createPresenceFunctions(options?: {
937
938
  } | null;
938
939
  }): {
939
940
  list: import("convex/server").RegisteredQuery<"public", {
940
- externalId?: string | undefined;
941
+ externalId?: string;
941
942
  serverId: string;
942
- viewerChunkKey?: string | undefined;
943
+ viewerChunkKey?: string;
943
944
  }, Promise<PresenceListRow[]>>;
944
945
  sync: import("convex/server").RegisteredMutation<"public", {
945
- externalId?: string | undefined;
946
- kind?: string | undefined;
947
- label?: string | undefined;
946
+ externalId?: string;
947
+ kind?: string;
948
+ label?: string;
948
949
  pose?: {
949
950
  rotationPitch: number;
950
951
  rotationY: number;
951
952
  x: number;
952
953
  y: number;
953
954
  z: number;
954
- } | undefined;
955
+ };
955
956
  serverId: string;
956
- sessionId?: string | undefined;
957
+ sessionId?: string;
957
958
  }, Promise<PresenceSyncResult | null>>;
958
959
  leave: import("convex/server").RegisteredMutation<"public", {
959
- externalId?: string | undefined;
960
+ externalId?: string;
960
961
  serverId: string;
961
- sessionId?: string | undefined;
962
+ sessionId?: string;
962
963
  }, Promise<null>>;
963
964
  reapIdlePresence: import("convex/server").RegisteredMutation<"internal", {}, Promise<{
964
965
  reaped: number;
@@ -1033,7 +1034,7 @@ export declare function recentChatMessages(ctx: {
1033
1034
  _creationTime: number;
1034
1035
  _id: GenericId<"jgChatMessages">;
1035
1036
  at: number;
1036
- authorName?: string | undefined;
1037
+ authorName?: string;
1037
1038
  body: string;
1038
1039
  channelId: string;
1039
1040
  serverId: string;
@@ -1045,19 +1046,19 @@ export declare function recentChatMessages(ctx: {
1045
1046
  */
1046
1047
  export declare function createClientErrorFunctions(): {
1047
1048
  reportClientError: import("convex/server").RegisteredMutation<"public", {
1048
- agentPrompt?: string | undefined;
1049
- componentStack?: string | undefined;
1050
- kind?: string | undefined;
1049
+ agentPrompt?: string;
1050
+ componentStack?: string;
1051
+ kind?: string;
1051
1052
  message: string;
1052
- pathname?: string | undefined;
1053
- stack?: string | undefined;
1054
- url?: string | undefined;
1055
- userAgent?: string | undefined;
1053
+ pathname?: string;
1054
+ stack?: string;
1055
+ url?: string;
1056
+ userAgent?: string;
1056
1057
  }, Promise<{
1057
1058
  ok: boolean;
1058
1059
  reason: string;
1059
1060
  } | {
1060
- reason?: undefined;
1061
+ reason?: never;
1061
1062
  ok: boolean;
1062
1063
  }>>;
1063
1064
  pruneClientErrors: import("convex/server").RegisteredMutation<"internal", {}, Promise<{
@@ -1078,18 +1079,18 @@ export declare function createChatFunctions(options?: {
1078
1079
  }): {
1079
1080
  messages: import("convex/server").RegisteredQuery<"public", {
1080
1081
  channelId: string;
1081
- externalId?: string | undefined;
1082
+ externalId?: string;
1082
1083
  serverId: string;
1083
1084
  }, Promise<ChatMessage[]>>;
1084
1085
  recent: import("convex/server").RegisteredQuery<"public", {
1085
1086
  channelId: string;
1086
- externalId?: string | undefined;
1087
+ externalId?: string;
1087
1088
  serverId: string;
1088
1089
  }, Promise<ChatMessage[]>>;
1089
1090
  sendMessage: import("convex/server").RegisteredMutation<"public", {
1090
1091
  body: string;
1091
1092
  channelId: string;
1092
- externalId?: string | undefined;
1093
+ externalId?: string;
1093
1094
  serverId: string;
1094
1095
  }, Promise<ChatSendOutcome>>;
1095
1096
  pruneChatMessages: import("convex/server").RegisteredMutation<"internal", {}, Promise<{
package/dist/server.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { defineSchema, defineTable, internalMutationGeneric, mutationGeneric, queryGeneric, } from "convex/server";
2
2
  import { ConvexError, v } from "convex/values";
3
3
  import { validateChatMessage } from "@jgengine/core/chat/chat";
4
+ import { definedOnly } from "@jgengine/core/data/definedOnly";
4
5
  import { createFeedWriteGate, validateFeedWrite, } from "@jgengine/core/multiplayer/feedWriteGate";
5
6
  import { DEFAULT_POSE_SYNC_RULES, decidePoseSync, isPresenceExpired, pickReusablePresence, resolveActivePresence, spawnPresenceState, } from "@jgengine/core/multiplayer/presenceModel";
6
7
  import { SERVER_ONLY_COMMAND_REASON, commandScopeEscape, scopeWithActor } from "@jgengine/core/commands/commandRunner";
@@ -298,10 +299,10 @@ async function ensureServerCapacity(ctx, server) {
298
299
  const existing = await serverCapacity(ctx, server);
299
300
  if (existing)
300
301
  return existing;
301
- const id = await ctx.db.insert("jgServerCapacity", {
302
+ const id = await ctx.db.insert("jgServerCapacity", definedOnly({
302
303
  serverId: server._id, gameId: server.gameId, status: server.status, mode: server.mode,
303
304
  memberCount: server.memberCount ?? server.memberUserIds.length, slotsPerServer: server.slotsPerServer,
304
- });
305
+ }));
305
306
  return (await ctx.db.get("jgServerCapacity", id));
306
307
  }
307
308
  /**
@@ -387,7 +388,7 @@ export async function applyLeaderboardIncrements(ctx, gameId, entries) {
387
388
  await ctx.db.patch(existing._id, { value: existing.value + entry.by, updatedAt: now });
388
389
  }
389
390
  else {
390
- await ctx.db.insert("jgLeaderboardRows", {
391
+ await ctx.db.insert("jgLeaderboardRows", definedOnly({
391
392
  gameId,
392
393
  stat: entry.stat,
393
394
  scope: entry.scope,
@@ -395,7 +396,7 @@ export async function applyLeaderboardIncrements(ctx, gameId, entries) {
395
396
  userId: entry.userId,
396
397
  value: entry.by,
397
398
  updatedAt: now,
398
- });
399
+ }));
399
400
  }
400
401
  }
401
402
  }
@@ -475,7 +476,8 @@ export async function persistServerSnapshot(ctx, server, snapshot, save) {
475
476
  await ctx.db.insert("jgWorldChunks", {
476
477
  serverId: server._id,
477
478
  chunkKey: chunk.chunkKey,
478
- ...chunkPatch,
479
+ snapshot: chunk.snapshot,
480
+ updatedAt: chunk.updatedAt,
479
481
  });
480
482
  }
481
483
  }
@@ -582,10 +584,10 @@ export function createGameServerFunctions(options) {
582
584
  const serverId = await ctx.db.insert("jgGameServers", {
583
585
  gameId: args.gameId,
584
586
  status: "running",
585
- mode: args.mode,
587
+ ...(args.mode === undefined ? {} : { mode: args.mode }),
586
588
  modeConfig: args.modeConfig,
587
589
  visibility: args.visibility ?? "public",
588
- joinCode: args.joinCode,
590
+ ...(args.joinCode === undefined ? {} : { joinCode: args.joinCode }),
589
591
  topology: shared ? "shared" : "rooms",
590
592
  memberCount: 0,
591
593
  memberUserIds: [],
@@ -930,7 +932,7 @@ export function createGameServerFunctions(options) {
930
932
  _id: server._id,
931
933
  gameId: server.gameId,
932
934
  status: server.status,
933
- mode: server.mode,
935
+ ...(server.mode === undefined ? {} : { mode: server.mode }),
934
936
  memberUserIds: server.memberUserIds,
935
937
  slotsPerServer: server.slotsPerServer,
936
938
  save: server.save,
@@ -958,7 +960,7 @@ export function createGameServerFunctions(options) {
958
960
  memberCount: v.number(),
959
961
  slotsPerServer: v.number(),
960
962
  }), v.null()),
961
- handler: (ctx, args) => withMember(ctx, mode, args, null, async (server) => ({
963
+ handler: (ctx, args) => withMember(ctx, mode, args, null, async (server) => definedOnly({
962
964
  _id: server._id,
963
965
  gameId: server.gameId,
964
966
  status: server.status,
@@ -983,10 +985,10 @@ export function createGameServerFunctions(options) {
983
985
  const member = await ctx.db.query("jgServerMembers").withIndex("by_server_and_user", q => q.eq("serverId", args.serverId).eq("userId", actor)).unique();
984
986
  if (!member)
985
987
  return null;
986
- return { _id: capacity.serverId, gameId: capacity.gameId, status: capacity.status, mode: capacity.mode, memberCount: capacity.memberCount, slotsPerServer: capacity.slotsPerServer };
988
+ return definedOnly({ _id: capacity.serverId, gameId: capacity.gameId, status: capacity.status, mode: capacity.mode, memberCount: capacity.memberCount, slotsPerServer: capacity.slotsPerServer });
987
989
  }
988
990
  const server = await requireServerMember(ctx, args.serverId, actor);
989
- return server ? { _id: server._id, gameId: server.gameId, status: server.status, mode: server.mode, memberCount: server.memberUserIds.length, slotsPerServer: server.slotsPerServer } : null;
991
+ return server ? definedOnly({ _id: server._id, gameId: server.gameId, status: server.status, mode: server.mode, memberCount: server.memberUserIds.length, slotsPerServer: server.slotsPerServer }) : null;
990
992
  },
991
993
  });
992
994
  /**
@@ -1125,7 +1127,7 @@ export function createGameServerFunctions(options) {
1125
1127
  return Promise.all(rows
1126
1128
  .filter((row) => isListablePublicly(row.visibility))
1127
1129
  .slice(0, limit)
1128
- .map(async (row) => ({
1130
+ .map(async (row) => definedOnly({
1129
1131
  _id: row._id,
1130
1132
  status: row.status,
1131
1133
  memberCount: (await serverCapacity(ctx, row))?.memberCount ?? row.memberCount ?? row.memberUserIds.length,
@@ -1327,7 +1329,7 @@ export function createPresenceFunctions(options) {
1327
1329
  }
1328
1330
  return rows
1329
1331
  .filter((row) => row.revokedAt === undefined && row.updatedAt >= threshold)
1330
- .map((row) => ({
1332
+ .map((row) => definedOnly({
1331
1333
  userId: row.userId,
1332
1334
  sessionId: row.sessionId,
1333
1335
  kind: row.kind,
@@ -1550,7 +1552,7 @@ export async function sendChatMessage(ctx, args) {
1550
1552
  const gate = await rateLimit(ctx, { key: JSON.stringify(["chat", args.serverId, args.userId]), windowMs: args.minIntervalMs ?? 2000, max: 1 });
1551
1553
  if (!gate.ok)
1552
1554
  return { ok: false, reason: "rate_limited" };
1553
- await ctx.db.insert("jgChatMessages", { serverId: args.serverId, channelId: args.channelId ?? "global", userId: args.userId, body: validation.text, authorName: args.authorName, at: Date.now() });
1555
+ await ctx.db.insert("jgChatMessages", definedOnly({ serverId: args.serverId, channelId: args.channelId ?? "global", userId: args.userId, body: validation.text, authorName: args.authorName, at: Date.now() }));
1554
1556
  return { ok: true };
1555
1557
  }
1556
1558
  /**
@@ -1664,8 +1666,8 @@ export function createChatFunctions(options) {
1664
1666
  .withIndex("by_server_channel", (q) => q.eq("serverId", args.serverId).eq("channelId", args.channelId))
1665
1667
  .order("desc")
1666
1668
  .take(historyLimit * 2 + 16);
1667
- for (let i = historyLimit * 2; i < recent.length; i += 1) {
1668
- await ctx.db.delete(recent[i]._id);
1669
+ for (const stale of recent.slice(historyLimit * 2)) {
1670
+ await ctx.db.delete(stale._id);
1669
1671
  }
1670
1672
  return { ok: true };
1671
1673
  },
@@ -18,7 +18,7 @@ export interface WorldPresenceRecord extends PresenceResidentRow {
18
18
  rotationY: number;
19
19
  rotationPitch: number;
20
20
  lastSeenAt: number;
21
- lastWorldSnapshotAt?: number;
21
+ lastWorldSnapshotAt?: number | undefined;
22
22
  }
23
23
  /** World chunk size and host-owned pose, checkpoint and retention policies. */
24
24
  export interface WorldPresenceOptions {
@@ -1,3 +1,4 @@
1
+ import { definedOnly } from "@jgengine/core/data/definedOnly";
1
2
  import { DEFAULT_POSE_SYNC_RULES, decidePoseSync, shouldPersistWorldSnapshot } from "@jgengine/core/multiplayer/presenceModel";
2
3
  import { chunkKeyAt, chunkKeysAround, parseChunkKey, DEFAULT_CHUNK_SIZE } from "@jgengine/core/runtime/worldChunks";
3
4
  function record(row) {
@@ -47,7 +48,7 @@ export function createWorldPresenceStore(options = {}) {
47
48
  label: args.label ?? existing?.label, x: args.position.x, y: args.position.y, z: args.position.z,
48
49
  rotationY: 0, rotationPitch: 0, chunkKey: chunkKeyAt([args.position.x, args.position.y, args.position.z], size),
49
50
  updatedAt: nowMs, revokedAt: undefined };
50
- const id = existing ? existing._id : await ctx.db.insert("jgPoses", patch);
51
+ const id = existing ? existing._id : await ctx.db.insert("jgPoses", definedOnly(patch));
51
52
  if (existing)
52
53
  await ctx.db.patch(id, patch);
53
54
  return record((await ctx.db.get("jgPoses", id)));