@jgengine/convex 0.18.0 → 0.19.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/CHANGELOG.md +265 -2
- package/dist/convexPresenceTransport.d.ts +2 -6
- package/dist/convexPresenceTransport.js +2 -2
- package/dist/createConvexGameTransport.d.ts +15 -11
- package/dist/createConvexGameTransport.js +66 -3
- package/dist/hostedServer.d.ts +1 -1
- package/dist/hostedServer.js +12 -12
- package/dist/server.d.ts +362 -26
- package/dist/server.js +576 -201
- package/dist/territory.d.ts +20 -0
- package/dist/territory.js +47 -0
- package/dist/worldPresence.d.ts +68 -0
- package/dist/worldPresence.js +128 -0
- package/package.json +2 -2
- package/skills/ce-handoff/SKILL.md +2 -2
- package/skills/jgengine/SKILL.md +9 -5
- package/skills/jgengine/api.md +205 -101
- package/skills/jgengine/capabilities.md +56 -0
- package/skills/jgengine/recipes/minimal-game.md +3 -0
- package/skills/jgengine-multiplayer/SKILL.md +25 -0
- package/skills/jgengine-multiplayer/api.md +159 -109
- package/skills/jgengine-multiplayer/capabilities.md +37 -0
package/dist/server.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Auth, DataModelFromSchemaDefinition, DocumentByName, GenericMutationCtx } from "convex/server";
|
|
1
|
+
import type { Auth, FunctionReference, DataModelFromSchemaDefinition, DocumentByName, GenericMutationCtx, GenericQueryCtx } from "convex/server";
|
|
2
2
|
import type { GenericId } from "convex/values";
|
|
3
|
-
import type
|
|
3
|
+
import { type ChatMessage } from "@jgengine/core/game/chat";
|
|
4
4
|
import type { ChatSendOutcome } from "@jgengine/core/multiplayer/chatContract";
|
|
5
5
|
import { type PoseSyncRules } from "@jgengine/core/multiplayer/presenceModel";
|
|
6
6
|
import type { CommandScope } from "@jgengine/core/runtime/commandRunner";
|
|
@@ -8,7 +8,7 @@ import type { GameRuntime } from "@jgengine/core/runtime/gameRuntime";
|
|
|
8
8
|
import type { LeaderboardIncrement } from "@jgengine/core/runtime/hostPersistence";
|
|
9
9
|
import { type MatchmakingMode } from "@jgengine/core/runtime/hostPolicy";
|
|
10
10
|
import type { SaveConfig } from "@jgengine/core/runtime/save";
|
|
11
|
-
import type { GameRuntimeSnapshot } from "@jgengine/core/runtime/snapshot";
|
|
11
|
+
import type { GameRuntimeSnapshot, RuntimePlayerRow } from "@jgengine/core/runtime/snapshot";
|
|
12
12
|
/** @internal Re-export shared host-policy pure helpers so existing convex imports keep working. */
|
|
13
13
|
export { JG_MAX_MEMBERS_PER_SERVER, canJoinPrivateServer, isListablePublicly, validateSlotsPerServer, type MatchmakingMode, } from "@jgengine/core/runtime/hostPolicy";
|
|
14
14
|
/** @internal */
|
|
@@ -19,6 +19,7 @@ export declare function jgengineTables(): {
|
|
|
19
19
|
gameId: string;
|
|
20
20
|
joinCode?: string | undefined;
|
|
21
21
|
lastSavedAt?: number | undefined;
|
|
22
|
+
memberCount?: number | undefined;
|
|
22
23
|
memberUserIds: string[];
|
|
23
24
|
mode?: string | undefined;
|
|
24
25
|
modeConfig?: any;
|
|
@@ -32,6 +33,7 @@ export declare function jgengineTables(): {
|
|
|
32
33
|
slotsPerServer: number;
|
|
33
34
|
status: "closed" | "open" | "running";
|
|
34
35
|
tickAnchorMs: number;
|
|
36
|
+
topology?: "rooms" | "shared" | undefined;
|
|
35
37
|
updatedAt: number;
|
|
36
38
|
visibility?: "private" | "public" | undefined;
|
|
37
39
|
}, {
|
|
@@ -41,6 +43,8 @@ export declare function jgengineTables(): {
|
|
|
41
43
|
modeConfig: import("convex/values").VAny<any, "optional", string>;
|
|
42
44
|
visibility: import("convex/values").VUnion<"private" | "public" | undefined, [import("convex/values").VLiteral<"public", "required">, import("convex/values").VLiteral<"private", "required">], "optional", never>;
|
|
43
45
|
joinCode: import("convex/values").VString<string | undefined, "optional">;
|
|
46
|
+
topology: import("convex/values").VUnion<"rooms" | "shared" | undefined, [import("convex/values").VLiteral<"shared", "required">, import("convex/values").VLiteral<"rooms", "required">], "optional", never>;
|
|
47
|
+
memberCount: import("convex/values").VFloat64<number | undefined, "optional">;
|
|
44
48
|
memberUserIds: import("convex/values").VArray<string[], import("convex/values").VString<string, "required">, "required">;
|
|
45
49
|
slotsPerServer: import("convex/values").VFloat64<number, "required">;
|
|
46
50
|
save: import("convex/values").VUnion<"none" | {
|
|
@@ -61,29 +65,92 @@ export declare function jgengineTables(): {
|
|
|
61
65
|
dirtyAt: import("convex/values").VFloat64<number | undefined, "optional">;
|
|
62
66
|
createdAt: import("convex/values").VFloat64<number, "required">;
|
|
63
67
|
updatedAt: import("convex/values").VFloat64<number, "required">;
|
|
64
|
-
}, "required", "createdAt" | "dirtyAt" | "gameId" | "joinCode" | "lastSavedAt" | "memberUserIds" | "mode" | "modeConfig" | "revision" | "save" | "save.auto" | "save.scope" | "serverState" | "sessionPlayers" | "slotsPerServer" | "status" | "tickAnchorMs" | "updatedAt" | "visibility" | `modeConfig.${string}` | `serverState.${string}` | `sessionPlayers.${string}`>, {
|
|
68
|
+
}, "required", "createdAt" | "dirtyAt" | "gameId" | "joinCode" | "lastSavedAt" | "memberCount" | "memberUserIds" | "mode" | "modeConfig" | "revision" | "save" | "save.auto" | "save.scope" | "serverState" | "sessionPlayers" | "slotsPerServer" | "status" | "tickAnchorMs" | "topology" | "updatedAt" | "visibility" | `modeConfig.${string}` | `serverState.${string}` | `sessionPlayers.${string}`>, {
|
|
65
69
|
by_dirty: ["dirtyAt", "_creationTime"];
|
|
66
70
|
by_game_and_status: ["gameId", "status", "_creationTime"];
|
|
67
71
|
by_game_status_tick: ["gameId", "status", "tickAnchorMs", "_creationTime"];
|
|
68
72
|
by_status: ["status", "_creationTime"];
|
|
69
73
|
}, {}, {}>;
|
|
74
|
+
jgServerCapacity: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
75
|
+
gameId: string;
|
|
76
|
+
memberCount: number;
|
|
77
|
+
mode?: string | undefined;
|
|
78
|
+
serverId: GenericId<"jgGameServers">;
|
|
79
|
+
slotsPerServer: number;
|
|
80
|
+
status: "closed" | "open" | "running";
|
|
81
|
+
}, {
|
|
82
|
+
serverId: import("convex/values").VId<GenericId<"jgGameServers">, "required">;
|
|
83
|
+
gameId: import("convex/values").VString<string, "required">;
|
|
84
|
+
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>;
|
|
85
|
+
mode: import("convex/values").VString<string | undefined, "optional">;
|
|
86
|
+
memberCount: import("convex/values").VFloat64<number, "required">;
|
|
87
|
+
slotsPerServer: import("convex/values").VFloat64<number, "required">;
|
|
88
|
+
}, "required", "gameId" | "memberCount" | "mode" | "serverId" | "slotsPerServer" | "status">, {
|
|
89
|
+
by_server: ["serverId", "_creationTime"];
|
|
90
|
+
}, {}, {}>;
|
|
91
|
+
jgServerMembers: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
92
|
+
joinedAt: number;
|
|
93
|
+
serverId: GenericId<"jgGameServers">;
|
|
94
|
+
sessionIds?: string[] | undefined;
|
|
95
|
+
userId: string;
|
|
96
|
+
}, {
|
|
97
|
+
serverId: import("convex/values").VId<GenericId<"jgGameServers">, "required">;
|
|
98
|
+
userId: import("convex/values").VString<string, "required">;
|
|
99
|
+
joinedAt: import("convex/values").VFloat64<number, "required">;
|
|
100
|
+
/** Live client sessions holding this membership; absent on legacy and host-driven joins. */
|
|
101
|
+
sessionIds: import("convex/values").VArray<string[] | undefined, import("convex/values").VString<string, "required">, "optional">;
|
|
102
|
+
}, "required", "joinedAt" | "serverId" | "sessionIds" | "userId">, {
|
|
103
|
+
by_server: ["serverId", "_creationTime"];
|
|
104
|
+
by_server_and_user: ["serverId", "userId", "_creationTime"];
|
|
105
|
+
}, {}, {}>;
|
|
106
|
+
jgRateLimits: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
107
|
+
count: number;
|
|
108
|
+
expiresAt: number;
|
|
109
|
+
key: string;
|
|
110
|
+
startedAt: number;
|
|
111
|
+
}, {
|
|
112
|
+
key: import("convex/values").VString<string, "required">;
|
|
113
|
+
startedAt: import("convex/values").VFloat64<number, "required">;
|
|
114
|
+
count: import("convex/values").VFloat64<number, "required">;
|
|
115
|
+
expiresAt: import("convex/values").VFloat64<number, "required">;
|
|
116
|
+
}, "required", "count" | "expiresAt" | "key" | "startedAt">, {
|
|
117
|
+
by_expires: ["expiresAt", "_creationTime"];
|
|
118
|
+
by_key: ["key", "_creationTime"];
|
|
119
|
+
}, {}, {}>;
|
|
120
|
+
jgClientErrors: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
121
|
+
createdAt: number;
|
|
122
|
+
details?: any;
|
|
123
|
+
message: string;
|
|
124
|
+
userId: string;
|
|
125
|
+
}, {
|
|
126
|
+
userId: import("convex/values").VString<string, "required">;
|
|
127
|
+
message: import("convex/values").VString<string, "required">;
|
|
128
|
+
details: import("convex/values").VAny<any, "optional", string>;
|
|
129
|
+
createdAt: import("convex/values").VFloat64<number, "required">;
|
|
130
|
+
}, "required", "createdAt" | "details" | "message" | "userId" | `details.${string}`>, {
|
|
131
|
+
by_created: ["createdAt", "_creationTime"];
|
|
132
|
+
}, {}, {}>;
|
|
70
133
|
jgPlayerProfiles: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
71
134
|
createdAt: number;
|
|
72
135
|
dirtyAt?: number | undefined;
|
|
73
136
|
gameId: string;
|
|
74
137
|
playerState: any;
|
|
75
138
|
revision: number;
|
|
139
|
+
sessionServerId?: GenericId<"jgGameServers"> | undefined;
|
|
140
|
+
sessionState?: any;
|
|
76
141
|
updatedAt: number;
|
|
77
142
|
userId: string;
|
|
78
143
|
}, {
|
|
79
144
|
userId: import("convex/values").VString<string, "required">;
|
|
80
145
|
gameId: import("convex/values").VString<string, "required">;
|
|
81
146
|
playerState: import("convex/values").VAny<any, "required", string>;
|
|
147
|
+
sessionState: import("convex/values").VAny<any, "optional", string>;
|
|
148
|
+
sessionServerId: import("convex/values").VId<GenericId<"jgGameServers"> | undefined, "optional">;
|
|
82
149
|
revision: import("convex/values").VFloat64<number, "required">;
|
|
83
150
|
dirtyAt: import("convex/values").VFloat64<number | undefined, "optional">;
|
|
84
151
|
createdAt: import("convex/values").VFloat64<number, "required">;
|
|
85
152
|
updatedAt: import("convex/values").VFloat64<number, "required">;
|
|
86
|
-
}, "required", "createdAt" | "dirtyAt" | "gameId" | "playerState" | "revision" | "updatedAt" | "userId" | `playerState.${string}`>, {
|
|
153
|
+
}, "required", "createdAt" | "dirtyAt" | "gameId" | "playerState" | "revision" | "sessionServerId" | "sessionState" | "updatedAt" | "userId" | `playerState.${string}` | `sessionState.${string}`>, {
|
|
87
154
|
by_user_and_game: ["userId", "gameId", "_creationTime"];
|
|
88
155
|
}, {}, {}>;
|
|
89
156
|
jgWorldChunks: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
@@ -136,8 +203,12 @@ export declare function jgengineTables(): {
|
|
|
136
203
|
by_server_and_action: ["serverId", "action", "_creationTime"];
|
|
137
204
|
}, {}, {}>;
|
|
138
205
|
jgPoses: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
206
|
+
chunkKey?: string | undefined;
|
|
207
|
+
homeGameId?: string | undefined;
|
|
139
208
|
kind?: string | undefined;
|
|
140
209
|
label?: string | undefined;
|
|
210
|
+
lastWorldSnapshotAt?: number | undefined;
|
|
211
|
+
ownerActorId?: string | undefined;
|
|
141
212
|
revokedAt?: number | undefined;
|
|
142
213
|
rotationPitch: number;
|
|
143
214
|
rotationY: number;
|
|
@@ -150,6 +221,10 @@ export declare function jgengineTables(): {
|
|
|
150
221
|
z: number;
|
|
151
222
|
}, {
|
|
152
223
|
serverId: import("convex/values").VString<string, "required">;
|
|
224
|
+
homeGameId: import("convex/values").VString<string | undefined, "optional">;
|
|
225
|
+
ownerActorId: import("convex/values").VString<string | undefined, "optional">;
|
|
226
|
+
lastWorldSnapshotAt: import("convex/values").VFloat64<number | undefined, "optional">;
|
|
227
|
+
chunkKey: import("convex/values").VString<string | undefined, "optional">;
|
|
153
228
|
userId: import("convex/values").VString<string, "required">;
|
|
154
229
|
/** One row per live session, so a second tab is a second row rather than a fight over one. */
|
|
155
230
|
sessionId: import("convex/values").VString<string | undefined, "optional">;
|
|
@@ -165,13 +240,21 @@ export declare function jgengineTables(): {
|
|
|
165
240
|
updatedAt: import("convex/values").VFloat64<number, "required">;
|
|
166
241
|
/** Set when the session was displaced or left; the reaper deletes the row once it goes idle. */
|
|
167
242
|
revokedAt: import("convex/values").VFloat64<number | undefined, "optional">;
|
|
168
|
-
}, "required", "kind" | "label" | "revokedAt" | "rotationPitch" | "rotationY" | "serverId" | "sessionId" | "updatedAt" | "userId" | "x" | "y" | "z">, {
|
|
243
|
+
}, "required", "chunkKey" | "homeGameId" | "kind" | "label" | "lastWorldSnapshotAt" | "ownerActorId" | "revokedAt" | "rotationPitch" | "rotationY" | "serverId" | "sessionId" | "updatedAt" | "userId" | "x" | "y" | "z">, {
|
|
244
|
+
by_home_game: ["homeGameId", "_creationTime"];
|
|
245
|
+
by_home_game_revoked_updated: ["homeGameId", "revokedAt", "updatedAt", "_creationTime"];
|
|
246
|
+
by_revoked: ["revokedAt", "_creationTime"];
|
|
247
|
+
by_revoked_updated: ["revokedAt", "updatedAt", "_creationTime"];
|
|
169
248
|
by_server: ["serverId", "_creationTime"];
|
|
249
|
+
by_server_and_chunk: ["serverId", "chunkKey", "_creationTime"];
|
|
170
250
|
by_server_and_user: ["serverId", "userId", "_creationTime"];
|
|
251
|
+
by_server_user_revoked_updated: ["serverId", "userId", "revokedAt", "updatedAt", "_creationTime"];
|
|
171
252
|
by_updated: ["updatedAt", "_creationTime"];
|
|
253
|
+
by_user: ["userId", "_creationTime"];
|
|
172
254
|
}, {}, {}>;
|
|
173
255
|
jgChatMessages: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
174
256
|
at: number;
|
|
257
|
+
authorName?: string | undefined;
|
|
175
258
|
body: string;
|
|
176
259
|
channelId: string;
|
|
177
260
|
serverId: string;
|
|
@@ -181,9 +264,11 @@ export declare function jgengineTables(): {
|
|
|
181
264
|
channelId: import("convex/values").VString<string, "required">;
|
|
182
265
|
userId: import("convex/values").VString<string, "required">;
|
|
183
266
|
body: import("convex/values").VString<string, "required">;
|
|
267
|
+
authorName: import("convex/values").VString<string | undefined, "optional">;
|
|
184
268
|
at: import("convex/values").VFloat64<number, "required">;
|
|
185
|
-
}, "required", "at" | "body" | "channelId" | "serverId" | "userId">, {
|
|
186
|
-
|
|
269
|
+
}, "required", "at" | "authorName" | "body" | "channelId" | "serverId" | "userId">, {
|
|
270
|
+
by_at: ["at", "_creationTime"];
|
|
271
|
+
by_server_channel: ["serverId", "channelId", "at", "_creationTime"];
|
|
187
272
|
}, {}, {}>;
|
|
188
273
|
};
|
|
189
274
|
/**
|
|
@@ -225,6 +310,7 @@ declare const schemaForTypes: import("convex/server").SchemaDefinition<{
|
|
|
225
310
|
gameId: string;
|
|
226
311
|
joinCode?: string | undefined;
|
|
227
312
|
lastSavedAt?: number | undefined;
|
|
313
|
+
memberCount?: number | undefined;
|
|
228
314
|
memberUserIds: string[];
|
|
229
315
|
mode?: string | undefined;
|
|
230
316
|
modeConfig?: any;
|
|
@@ -238,6 +324,7 @@ declare const schemaForTypes: import("convex/server").SchemaDefinition<{
|
|
|
238
324
|
slotsPerServer: number;
|
|
239
325
|
status: "closed" | "open" | "running";
|
|
240
326
|
tickAnchorMs: number;
|
|
327
|
+
topology?: "rooms" | "shared" | undefined;
|
|
241
328
|
updatedAt: number;
|
|
242
329
|
visibility?: "private" | "public" | undefined;
|
|
243
330
|
}, {
|
|
@@ -247,6 +334,8 @@ declare const schemaForTypes: import("convex/server").SchemaDefinition<{
|
|
|
247
334
|
modeConfig: import("convex/values").VAny<any, "optional", string>;
|
|
248
335
|
visibility: import("convex/values").VUnion<"private" | "public" | undefined, [import("convex/values").VLiteral<"public", "required">, import("convex/values").VLiteral<"private", "required">], "optional", never>;
|
|
249
336
|
joinCode: import("convex/values").VString<string | undefined, "optional">;
|
|
337
|
+
topology: import("convex/values").VUnion<"rooms" | "shared" | undefined, [import("convex/values").VLiteral<"shared", "required">, import("convex/values").VLiteral<"rooms", "required">], "optional", never>;
|
|
338
|
+
memberCount: import("convex/values").VFloat64<number | undefined, "optional">;
|
|
250
339
|
memberUserIds: import("convex/values").VArray<string[], import("convex/values").VString<string, "required">, "required">;
|
|
251
340
|
slotsPerServer: import("convex/values").VFloat64<number, "required">;
|
|
252
341
|
save: import("convex/values").VUnion<"none" | {
|
|
@@ -267,29 +356,92 @@ declare const schemaForTypes: import("convex/server").SchemaDefinition<{
|
|
|
267
356
|
dirtyAt: import("convex/values").VFloat64<number | undefined, "optional">;
|
|
268
357
|
createdAt: import("convex/values").VFloat64<number, "required">;
|
|
269
358
|
updatedAt: import("convex/values").VFloat64<number, "required">;
|
|
270
|
-
}, "required", "createdAt" | "dirtyAt" | "gameId" | "joinCode" | "lastSavedAt" | "memberUserIds" | "mode" | "modeConfig" | "revision" | "save" | "save.auto" | "save.scope" | "serverState" | "sessionPlayers" | "slotsPerServer" | "status" | "tickAnchorMs" | "updatedAt" | "visibility" | `modeConfig.${string}` | `serverState.${string}` | `sessionPlayers.${string}`>, {
|
|
359
|
+
}, "required", "createdAt" | "dirtyAt" | "gameId" | "joinCode" | "lastSavedAt" | "memberCount" | "memberUserIds" | "mode" | "modeConfig" | "revision" | "save" | "save.auto" | "save.scope" | "serverState" | "sessionPlayers" | "slotsPerServer" | "status" | "tickAnchorMs" | "topology" | "updatedAt" | "visibility" | `modeConfig.${string}` | `serverState.${string}` | `sessionPlayers.${string}`>, {
|
|
271
360
|
by_dirty: ["dirtyAt", "_creationTime"];
|
|
272
361
|
by_game_and_status: ["gameId", "status", "_creationTime"];
|
|
273
362
|
by_game_status_tick: ["gameId", "status", "tickAnchorMs", "_creationTime"];
|
|
274
363
|
by_status: ["status", "_creationTime"];
|
|
275
364
|
}, {}, {}>;
|
|
365
|
+
jgServerCapacity: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
366
|
+
gameId: string;
|
|
367
|
+
memberCount: number;
|
|
368
|
+
mode?: string | undefined;
|
|
369
|
+
serverId: GenericId<"jgGameServers">;
|
|
370
|
+
slotsPerServer: number;
|
|
371
|
+
status: "closed" | "open" | "running";
|
|
372
|
+
}, {
|
|
373
|
+
serverId: import("convex/values").VId<GenericId<"jgGameServers">, "required">;
|
|
374
|
+
gameId: import("convex/values").VString<string, "required">;
|
|
375
|
+
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>;
|
|
376
|
+
mode: import("convex/values").VString<string | undefined, "optional">;
|
|
377
|
+
memberCount: import("convex/values").VFloat64<number, "required">;
|
|
378
|
+
slotsPerServer: import("convex/values").VFloat64<number, "required">;
|
|
379
|
+
}, "required", "gameId" | "memberCount" | "mode" | "serverId" | "slotsPerServer" | "status">, {
|
|
380
|
+
by_server: ["serverId", "_creationTime"];
|
|
381
|
+
}, {}, {}>;
|
|
382
|
+
jgServerMembers: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
383
|
+
joinedAt: number;
|
|
384
|
+
serverId: GenericId<"jgGameServers">;
|
|
385
|
+
sessionIds?: string[] | undefined;
|
|
386
|
+
userId: string;
|
|
387
|
+
}, {
|
|
388
|
+
serverId: import("convex/values").VId<GenericId<"jgGameServers">, "required">;
|
|
389
|
+
userId: import("convex/values").VString<string, "required">;
|
|
390
|
+
joinedAt: import("convex/values").VFloat64<number, "required">;
|
|
391
|
+
/** Live client sessions holding this membership; absent on legacy and host-driven joins. */
|
|
392
|
+
sessionIds: import("convex/values").VArray<string[] | undefined, import("convex/values").VString<string, "required">, "optional">;
|
|
393
|
+
}, "required", "joinedAt" | "serverId" | "sessionIds" | "userId">, {
|
|
394
|
+
by_server: ["serverId", "_creationTime"];
|
|
395
|
+
by_server_and_user: ["serverId", "userId", "_creationTime"];
|
|
396
|
+
}, {}, {}>;
|
|
397
|
+
jgRateLimits: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
398
|
+
count: number;
|
|
399
|
+
expiresAt: number;
|
|
400
|
+
key: string;
|
|
401
|
+
startedAt: number;
|
|
402
|
+
}, {
|
|
403
|
+
key: import("convex/values").VString<string, "required">;
|
|
404
|
+
startedAt: import("convex/values").VFloat64<number, "required">;
|
|
405
|
+
count: import("convex/values").VFloat64<number, "required">;
|
|
406
|
+
expiresAt: import("convex/values").VFloat64<number, "required">;
|
|
407
|
+
}, "required", "count" | "expiresAt" | "key" | "startedAt">, {
|
|
408
|
+
by_expires: ["expiresAt", "_creationTime"];
|
|
409
|
+
by_key: ["key", "_creationTime"];
|
|
410
|
+
}, {}, {}>;
|
|
411
|
+
jgClientErrors: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
412
|
+
createdAt: number;
|
|
413
|
+
details?: any;
|
|
414
|
+
message: string;
|
|
415
|
+
userId: string;
|
|
416
|
+
}, {
|
|
417
|
+
userId: import("convex/values").VString<string, "required">;
|
|
418
|
+
message: import("convex/values").VString<string, "required">;
|
|
419
|
+
details: import("convex/values").VAny<any, "optional", string>;
|
|
420
|
+
createdAt: import("convex/values").VFloat64<number, "required">;
|
|
421
|
+
}, "required", "createdAt" | "details" | "message" | "userId" | `details.${string}`>, {
|
|
422
|
+
by_created: ["createdAt", "_creationTime"];
|
|
423
|
+
}, {}, {}>;
|
|
276
424
|
jgPlayerProfiles: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
277
425
|
createdAt: number;
|
|
278
426
|
dirtyAt?: number | undefined;
|
|
279
427
|
gameId: string;
|
|
280
428
|
playerState: any;
|
|
281
429
|
revision: number;
|
|
430
|
+
sessionServerId?: GenericId<"jgGameServers"> | undefined;
|
|
431
|
+
sessionState?: any;
|
|
282
432
|
updatedAt: number;
|
|
283
433
|
userId: string;
|
|
284
434
|
}, {
|
|
285
435
|
userId: import("convex/values").VString<string, "required">;
|
|
286
436
|
gameId: import("convex/values").VString<string, "required">;
|
|
287
437
|
playerState: import("convex/values").VAny<any, "required", string>;
|
|
438
|
+
sessionState: import("convex/values").VAny<any, "optional", string>;
|
|
439
|
+
sessionServerId: import("convex/values").VId<GenericId<"jgGameServers"> | undefined, "optional">;
|
|
288
440
|
revision: import("convex/values").VFloat64<number, "required">;
|
|
289
441
|
dirtyAt: import("convex/values").VFloat64<number | undefined, "optional">;
|
|
290
442
|
createdAt: import("convex/values").VFloat64<number, "required">;
|
|
291
443
|
updatedAt: import("convex/values").VFloat64<number, "required">;
|
|
292
|
-
}, "required", "createdAt" | "dirtyAt" | "gameId" | "playerState" | "revision" | "updatedAt" | "userId" | `playerState.${string}`>, {
|
|
444
|
+
}, "required", "createdAt" | "dirtyAt" | "gameId" | "playerState" | "revision" | "sessionServerId" | "sessionState" | "updatedAt" | "userId" | `playerState.${string}` | `sessionState.${string}`>, {
|
|
293
445
|
by_user_and_game: ["userId", "gameId", "_creationTime"];
|
|
294
446
|
}, {}, {}>;
|
|
295
447
|
jgWorldChunks: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
@@ -342,8 +494,12 @@ declare const schemaForTypes: import("convex/server").SchemaDefinition<{
|
|
|
342
494
|
by_server_and_action: ["serverId", "action", "_creationTime"];
|
|
343
495
|
}, {}, {}>;
|
|
344
496
|
jgPoses: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
497
|
+
chunkKey?: string | undefined;
|
|
498
|
+
homeGameId?: string | undefined;
|
|
345
499
|
kind?: string | undefined;
|
|
346
500
|
label?: string | undefined;
|
|
501
|
+
lastWorldSnapshotAt?: number | undefined;
|
|
502
|
+
ownerActorId?: string | undefined;
|
|
347
503
|
revokedAt?: number | undefined;
|
|
348
504
|
rotationPitch: number;
|
|
349
505
|
rotationY: number;
|
|
@@ -356,6 +512,10 @@ declare const schemaForTypes: import("convex/server").SchemaDefinition<{
|
|
|
356
512
|
z: number;
|
|
357
513
|
}, {
|
|
358
514
|
serverId: import("convex/values").VString<string, "required">;
|
|
515
|
+
homeGameId: import("convex/values").VString<string | undefined, "optional">;
|
|
516
|
+
ownerActorId: import("convex/values").VString<string | undefined, "optional">;
|
|
517
|
+
lastWorldSnapshotAt: import("convex/values").VFloat64<number | undefined, "optional">;
|
|
518
|
+
chunkKey: import("convex/values").VString<string | undefined, "optional">;
|
|
359
519
|
userId: import("convex/values").VString<string, "required">;
|
|
360
520
|
/** One row per live session, so a second tab is a second row rather than a fight over one. */
|
|
361
521
|
sessionId: import("convex/values").VString<string | undefined, "optional">;
|
|
@@ -371,13 +531,21 @@ declare const schemaForTypes: import("convex/server").SchemaDefinition<{
|
|
|
371
531
|
updatedAt: import("convex/values").VFloat64<number, "required">;
|
|
372
532
|
/** Set when the session was displaced or left; the reaper deletes the row once it goes idle. */
|
|
373
533
|
revokedAt: import("convex/values").VFloat64<number | undefined, "optional">;
|
|
374
|
-
}, "required", "kind" | "label" | "revokedAt" | "rotationPitch" | "rotationY" | "serverId" | "sessionId" | "updatedAt" | "userId" | "x" | "y" | "z">, {
|
|
534
|
+
}, "required", "chunkKey" | "homeGameId" | "kind" | "label" | "lastWorldSnapshotAt" | "ownerActorId" | "revokedAt" | "rotationPitch" | "rotationY" | "serverId" | "sessionId" | "updatedAt" | "userId" | "x" | "y" | "z">, {
|
|
535
|
+
by_home_game: ["homeGameId", "_creationTime"];
|
|
536
|
+
by_home_game_revoked_updated: ["homeGameId", "revokedAt", "updatedAt", "_creationTime"];
|
|
537
|
+
by_revoked: ["revokedAt", "_creationTime"];
|
|
538
|
+
by_revoked_updated: ["revokedAt", "updatedAt", "_creationTime"];
|
|
375
539
|
by_server: ["serverId", "_creationTime"];
|
|
540
|
+
by_server_and_chunk: ["serverId", "chunkKey", "_creationTime"];
|
|
376
541
|
by_server_and_user: ["serverId", "userId", "_creationTime"];
|
|
542
|
+
by_server_user_revoked_updated: ["serverId", "userId", "revokedAt", "updatedAt", "_creationTime"];
|
|
377
543
|
by_updated: ["updatedAt", "_creationTime"];
|
|
544
|
+
by_user: ["userId", "_creationTime"];
|
|
378
545
|
}, {}, {}>;
|
|
379
546
|
jgChatMessages: import("convex/server").TableDefinition<import("convex/values").VObject<{
|
|
380
547
|
at: number;
|
|
548
|
+
authorName?: string | undefined;
|
|
381
549
|
body: string;
|
|
382
550
|
channelId: string;
|
|
383
551
|
serverId: string;
|
|
@@ -387,14 +555,18 @@ declare const schemaForTypes: import("convex/server").SchemaDefinition<{
|
|
|
387
555
|
channelId: import("convex/values").VString<string, "required">;
|
|
388
556
|
userId: import("convex/values").VString<string, "required">;
|
|
389
557
|
body: import("convex/values").VString<string, "required">;
|
|
558
|
+
authorName: import("convex/values").VString<string | undefined, "optional">;
|
|
390
559
|
at: import("convex/values").VFloat64<number, "required">;
|
|
391
|
-
}, "required", "at" | "body" | "channelId" | "serverId" | "userId">, {
|
|
392
|
-
|
|
560
|
+
}, "required", "at" | "authorName" | "body" | "channelId" | "serverId" | "userId">, {
|
|
561
|
+
by_at: ["at", "_creationTime"];
|
|
562
|
+
by_server_channel: ["serverId", "channelId", "at", "_creationTime"];
|
|
393
563
|
}, {}, {}>;
|
|
394
564
|
}, true>;
|
|
395
565
|
/** Data model of the {@link jgengineTables} schema — the shape a host's own Convex ctx must satisfy to
|
|
396
566
|
* call the exported persistence helpers. */
|
|
397
567
|
export type JGDataModel = DataModelFromSchemaDefinition<typeof schemaForTypes>;
|
|
568
|
+
/** Read-only context accepted by engine host queries. */
|
|
569
|
+
export type JGQueryCtx = GenericQueryCtx<JGDataModel>;
|
|
398
570
|
/** Mutation ctx accepted by {@link loadServerSnapshot} / {@link persistServerSnapshot}. */
|
|
399
571
|
export type JGMutationCtx = GenericMutationCtx<JGDataModel>;
|
|
400
572
|
/** A `jgGameServers` row — the server handle the persistence helpers load from and write back to. */
|
|
@@ -407,6 +579,10 @@ export declare const DEFAULT_CONVEX_POSE_RULES: PoseSyncRules;
|
|
|
407
579
|
export declare function resolveActor(ctx: {
|
|
408
580
|
auth: Auth;
|
|
409
581
|
}, claimedExternalId: string | undefined, mode: JgAuthMode): Promise<string | null>;
|
|
582
|
+
/** Most live client sessions one shared-topology membership remembers; the oldest drop first. */
|
|
583
|
+
export declare const MAX_MEMBER_SESSIONS = 16;
|
|
584
|
+
/** Longest accepted client `sessionId`. */
|
|
585
|
+
export declare const MAX_SESSION_ID_LENGTH = 128;
|
|
410
586
|
/**
|
|
411
587
|
* How much of a server to hydrate. Both fields default to "everything", which is a document read per
|
|
412
588
|
* member plus one per chunk — the cost that makes a large shared world unaffordable per mutation.
|
|
@@ -460,6 +636,22 @@ export type RunCommandArgs = {
|
|
|
460
636
|
* {@link CommandDef} declares through its own `scope`; omit both to hydrate the whole world.
|
|
461
637
|
*/
|
|
462
638
|
scope?: LoadSnapshotScope;
|
|
639
|
+
/**
|
|
640
|
+
* Trusted host override after game-specific authorization; never forward a client-supplied actor.
|
|
641
|
+
* The actor must be a member; when they might have no live session (a closed tab, an agent), call
|
|
642
|
+
* {@link GameServerHelpers.ensureJoined} first.
|
|
643
|
+
*/
|
|
644
|
+
actorUserId?: string;
|
|
645
|
+
beforePersist?: (ctx: JGMutationCtx, loaded: LoadedServerSnapshot) => Promise<void>;
|
|
646
|
+
};
|
|
647
|
+
/** Outcome of a join: the server joined and whether the player's profile was created, or why it was refused. */
|
|
648
|
+
export type EnsureJoinedOutcome = {
|
|
649
|
+
ok: true;
|
|
650
|
+
serverId: GenericId<"jgGameServers">;
|
|
651
|
+
isNew: boolean;
|
|
652
|
+
} | {
|
|
653
|
+
ok: false;
|
|
654
|
+
reason: "full" | "closed" | "unauthorized";
|
|
463
655
|
};
|
|
464
656
|
/** A server resolved for runtime work: its row, its registered runtime, and its hydrated snapshot. */
|
|
465
657
|
export type LoadedServerSnapshot = {
|
|
@@ -473,6 +665,7 @@ export type LoadedServerSnapshot = {
|
|
|
473
665
|
* table writes in one transaction, which a pre-registered mutation cannot do.
|
|
474
666
|
*/
|
|
475
667
|
export type GameServerHelpers = {
|
|
668
|
+
ensureServer: (ctx: JGMutationCtx, gameId: string) => Promise<ServerDoc>;
|
|
476
669
|
loadSnapshot: (ctx: JGMutationCtx, serverId: string, scope?: LoadSnapshotScope) => Promise<LoadedServerSnapshot | null>;
|
|
477
670
|
applyCommand: (args: {
|
|
478
671
|
gameId: string;
|
|
@@ -490,7 +683,22 @@ export type GameServerHelpers = {
|
|
|
490
683
|
reason: string;
|
|
491
684
|
};
|
|
492
685
|
persistSnapshot: (ctx: JGMutationCtx, server: ServerDoc, snapshot: GameRuntimeSnapshot, save?: SaveConfig) => Promise<boolean>;
|
|
686
|
+
/**
|
|
687
|
+
* Apply a command as the actor. Refuses non-members with "Not a member of this server"; host
|
|
688
|
+
* mutations acting for a user who might have no live session call {@link ensureJoined} first.
|
|
689
|
+
*/
|
|
493
690
|
runCommand: (ctx: JGMutationCtx, args: RunCommandArgs) => Promise<RunCommandOutcome>;
|
|
691
|
+
/**
|
|
692
|
+
* Join a trusted, already-authorized actor through the same path as the `joinServer` mutation.
|
|
693
|
+
* Idempotent: an existing member of `serverId` returns at once. Pins no client session, so it never
|
|
694
|
+
* keeps a membership alive past the user's own session leaves.
|
|
695
|
+
*/
|
|
696
|
+
ensureJoined: (ctx: JGMutationCtx, args: {
|
|
697
|
+
gameId: string;
|
|
698
|
+
userId: string;
|
|
699
|
+
serverId?: string;
|
|
700
|
+
}) => Promise<EnsureJoinedOutcome>;
|
|
701
|
+
resetPlayerProfile: (ctx: JGMutationCtx, serverId: string, userId: string) => Promise<RuntimePlayerRow>;
|
|
494
702
|
};
|
|
495
703
|
/** How many running servers one `tickActiveServers` transaction may hydrate, tick, and persist. */
|
|
496
704
|
export declare const DEFAULT_MAX_SERVERS_PER_TICK = 32;
|
|
@@ -499,10 +707,9 @@ export declare const MAX_CHUNKS_PER_QUERY = 64;
|
|
|
499
707
|
/**
|
|
500
708
|
* Build the hosted-server Convex functions for a set of game runtimes.
|
|
501
709
|
*
|
|
502
|
-
*
|
|
503
|
-
*
|
|
504
|
-
*
|
|
505
|
-
* larger value throws here, at wiring time, rather than at the write that overflows the document.
|
|
710
|
+
* Room topology keeps its roster and session map in the server document and caps capacity at
|
|
711
|
+
* {@link JG_MAX_MEMBERS_PER_SERVER}. Shared topology stores membership, capacity, and per-player
|
|
712
|
+
* session state separately; player-only commands and roster changes do not rewrite the world row.
|
|
506
713
|
* World geometry that outgrows one row belongs in `jgWorldChunks`, hydrated by key
|
|
507
714
|
* ({@link LoadSnapshotScope}) and read by clients through `getChunks` — not in `serverState`.
|
|
508
715
|
*
|
|
@@ -514,6 +721,7 @@ export declare function createGameServerFunctions(options?: {
|
|
|
514
721
|
runtimes?: GameRuntime[];
|
|
515
722
|
auth?: JgAuthMode;
|
|
516
723
|
slotsPerServer?: number;
|
|
724
|
+
topology?: "shared" | "rooms";
|
|
517
725
|
matchmaking?: MatchmakingMode;
|
|
518
726
|
maxServersPerTick?: number;
|
|
519
727
|
allowedFeedActions?: readonly string[];
|
|
@@ -525,14 +733,13 @@ export declare function createGameServerFunctions(options?: {
|
|
|
525
733
|
mode?: string | undefined;
|
|
526
734
|
modeConfig?: any;
|
|
527
735
|
serverId?: GenericId<"jgGameServers"> | undefined;
|
|
736
|
+
sessionId?: string | undefined;
|
|
528
737
|
visibility?: "private" | "public" | undefined;
|
|
529
|
-
}, Promise<
|
|
530
|
-
serverId: GenericId<"jgGameServers">;
|
|
531
|
-
isNew: boolean;
|
|
532
|
-
}>>;
|
|
738
|
+
}, Promise<EnsureJoinedOutcome>>;
|
|
533
739
|
leaveServer: import("convex/server").RegisteredMutation<"public", {
|
|
534
740
|
externalId?: string | undefined;
|
|
535
741
|
serverId: GenericId<"jgGameServers">;
|
|
742
|
+
sessionId?: string | undefined;
|
|
536
743
|
}, Promise<null>>;
|
|
537
744
|
runCommand: import("convex/server").RegisteredMutation<"public", {
|
|
538
745
|
command: string;
|
|
@@ -579,8 +786,17 @@ export declare function createGameServerFunctions(options?: {
|
|
|
579
786
|
mode: string | undefined;
|
|
580
787
|
memberCount: number;
|
|
581
788
|
slotsPerServer: number;
|
|
582
|
-
|
|
583
|
-
|
|
789
|
+
} | null>>;
|
|
790
|
+
getServerCapacity: import("convex/server").RegisteredQuery<"public", {
|
|
791
|
+
externalId?: string | undefined;
|
|
792
|
+
serverId: GenericId<"jgGameServers">;
|
|
793
|
+
}, Promise<{
|
|
794
|
+
_id: GenericId<"jgGameServers">;
|
|
795
|
+
gameId: string;
|
|
796
|
+
status: "closed" | "open" | "running";
|
|
797
|
+
mode: string | undefined;
|
|
798
|
+
memberCount: number;
|
|
799
|
+
slotsPerServer: number;
|
|
584
800
|
} | null>>;
|
|
585
801
|
getChunks: import("convex/server").RegisteredQuery<"public", {
|
|
586
802
|
chunkKeys: string[];
|
|
@@ -727,6 +943,7 @@ export declare function createPresenceFunctions(options?: {
|
|
|
727
943
|
list: import("convex/server").RegisteredQuery<"public", {
|
|
728
944
|
externalId?: string | undefined;
|
|
729
945
|
serverId: string;
|
|
946
|
+
viewerChunkKey?: string | undefined;
|
|
730
947
|
}, Promise<PresenceListRow[]>>;
|
|
731
948
|
sync: import("convex/server").RegisteredMutation<"public", {
|
|
732
949
|
externalId?: string | undefined;
|
|
@@ -751,6 +968,111 @@ export declare function createPresenceFunctions(options?: {
|
|
|
751
968
|
reaped: number;
|
|
752
969
|
}>>;
|
|
753
970
|
};
|
|
971
|
+
/** One active player delivered to an online-system batch. */
|
|
972
|
+
export type OnlinePlayer = {
|
|
973
|
+
serverId: string;
|
|
974
|
+
userId: string;
|
|
975
|
+
homeGameId?: string;
|
|
976
|
+
};
|
|
977
|
+
/**
|
|
978
|
+
* Scan one bounded presence page and schedule its handler and continuation in separate transactions.
|
|
979
|
+
* @capability online-player-batches Schedule bounded active-player or home-game work in separate transactions.
|
|
980
|
+
*/
|
|
981
|
+
export declare function forEachOnlinePlayer(ctx: JGMutationCtx, options: {
|
|
982
|
+
batchSize?: number;
|
|
983
|
+
handler: FunctionReference<"mutation", "internal", {
|
|
984
|
+
players: OnlinePlayer[];
|
|
985
|
+
nowMs: number;
|
|
986
|
+
}>;
|
|
987
|
+
continuation: FunctionReference<"mutation", "internal", {
|
|
988
|
+
cursor?: string | null;
|
|
989
|
+
nowMs?: number;
|
|
990
|
+
}>;
|
|
991
|
+
cursor?: string | null;
|
|
992
|
+
nowMs?: number;
|
|
993
|
+
freshWindowMs?: number;
|
|
994
|
+
/** Deliver one representative per home game when several agents share a simulation. */
|
|
995
|
+
groupBy?: "userId" | "homeGameId";
|
|
996
|
+
}): Promise<{
|
|
997
|
+
scheduled: number;
|
|
998
|
+
remaining: boolean;
|
|
999
|
+
}>;
|
|
1000
|
+
/**
|
|
1001
|
+
* Consume one request in a fixed rate window; concurrent callers serialize on the indexed key.
|
|
1002
|
+
* @capability host-rate-limit Enforce indexed per-key request windows inside authoritative mutations.
|
|
1003
|
+
*/
|
|
1004
|
+
export declare function rateLimit(ctx: JGMutationCtx, args: {
|
|
1005
|
+
key: string;
|
|
1006
|
+
windowMs: number;
|
|
1007
|
+
max: number;
|
|
1008
|
+
nowMs?: number;
|
|
1009
|
+
}): Promise<{
|
|
1010
|
+
ok: boolean;
|
|
1011
|
+
retryAfterMs: number;
|
|
1012
|
+
}>;
|
|
1013
|
+
/**
|
|
1014
|
+
* Write validated chat in a host transaction after the caller resolves its actor and world.
|
|
1015
|
+
* @capability host-chat-send Validate, rate-limit and persist chat inside an authorized host mutation.
|
|
1016
|
+
*/
|
|
1017
|
+
export declare function sendChatMessage(ctx: JGMutationCtx, args: {
|
|
1018
|
+
serverId: string;
|
|
1019
|
+
userId: string;
|
|
1020
|
+
body: string;
|
|
1021
|
+
channelId?: string;
|
|
1022
|
+
authorName?: string;
|
|
1023
|
+
maxBodyLength?: number;
|
|
1024
|
+
minIntervalMs?: number;
|
|
1025
|
+
}): Promise<ChatSendOutcome>;
|
|
1026
|
+
/**
|
|
1027
|
+
* Bounded recent chat for a resolved server; authorization belongs to the calling query.
|
|
1028
|
+
* @capability host-chat-history Read bounded channel history inside an authorized host query.
|
|
1029
|
+
*/
|
|
1030
|
+
export declare function recentChatMessages(ctx: {
|
|
1031
|
+
db: Pick<JGQueryCtx["db"], "query">;
|
|
1032
|
+
}, args: {
|
|
1033
|
+
serverId: string;
|
|
1034
|
+
channelId?: string;
|
|
1035
|
+
limit?: number;
|
|
1036
|
+
}): Promise<{
|
|
1037
|
+
_creationTime: number;
|
|
1038
|
+
_id: GenericId<"jgChatMessages">;
|
|
1039
|
+
at: number;
|
|
1040
|
+
authorName?: string | undefined;
|
|
1041
|
+
body: string;
|
|
1042
|
+
channelId: string;
|
|
1043
|
+
serverId: string;
|
|
1044
|
+
userId: string;
|
|
1045
|
+
}[]>;
|
|
1046
|
+
/**
|
|
1047
|
+
* Authenticated, bounded client diagnostics and bounded retention sweeps.
|
|
1048
|
+
* @capability client-error-reporting Accept authenticated bounded diagnostics with cooldown and retention sweeps.
|
|
1049
|
+
*/
|
|
1050
|
+
export declare function createClientErrorFunctions(): {
|
|
1051
|
+
reportClientError: import("convex/server").RegisteredMutation<"public", {
|
|
1052
|
+
agentPrompt?: string | undefined;
|
|
1053
|
+
componentStack?: string | undefined;
|
|
1054
|
+
kind?: string | undefined;
|
|
1055
|
+
message: string;
|
|
1056
|
+
pathname?: string | undefined;
|
|
1057
|
+
stack?: string | undefined;
|
|
1058
|
+
url?: string | undefined;
|
|
1059
|
+
userAgent?: string | undefined;
|
|
1060
|
+
}, Promise<{
|
|
1061
|
+
ok: boolean;
|
|
1062
|
+
reason: string;
|
|
1063
|
+
} | {
|
|
1064
|
+
reason?: undefined;
|
|
1065
|
+
ok: boolean;
|
|
1066
|
+
}>>;
|
|
1067
|
+
pruneClientErrors: import("convex/server").RegisteredMutation<"internal", {}, Promise<{
|
|
1068
|
+
deleted: number;
|
|
1069
|
+
remaining: boolean;
|
|
1070
|
+
}>>;
|
|
1071
|
+
pruneRateLimits: import("convex/server").RegisteredMutation<"internal", {}, Promise<{
|
|
1072
|
+
deleted: number;
|
|
1073
|
+
remaining: boolean;
|
|
1074
|
+
}>>;
|
|
1075
|
+
};
|
|
754
1076
|
/** @internal */
|
|
755
1077
|
export declare function createChatFunctions(options?: {
|
|
756
1078
|
auth?: JgAuthMode;
|
|
@@ -763,19 +1085,33 @@ export declare function createChatFunctions(options?: {
|
|
|
763
1085
|
externalId?: string | undefined;
|
|
764
1086
|
serverId: string;
|
|
765
1087
|
}, Promise<ChatMessage[]>>;
|
|
1088
|
+
recent: import("convex/server").RegisteredQuery<"public", {
|
|
1089
|
+
channelId: string;
|
|
1090
|
+
externalId?: string | undefined;
|
|
1091
|
+
serverId: string;
|
|
1092
|
+
}, Promise<ChatMessage[]>>;
|
|
766
1093
|
sendMessage: import("convex/server").RegisteredMutation<"public", {
|
|
767
1094
|
body: string;
|
|
768
1095
|
channelId: string;
|
|
769
1096
|
externalId?: string | undefined;
|
|
770
1097
|
serverId: string;
|
|
771
1098
|
}, Promise<ChatSendOutcome>>;
|
|
1099
|
+
pruneChatMessages: import("convex/server").RegisteredMutation<"internal", {}, Promise<{
|
|
1100
|
+
deleted: number;
|
|
1101
|
+
remaining: boolean;
|
|
1102
|
+
}>>;
|
|
772
1103
|
};
|
|
773
1104
|
export type JgCronSpec = {
|
|
774
1105
|
name: string;
|
|
775
1106
|
intervalSeconds: number;
|
|
776
|
-
functionKey: "tickActiveServers" | "flushDirtyServers" | "reapIdlePresence";
|
|
1107
|
+
functionKey: "tickActiveServers" | "flushDirtyServers" | "reapIdlePresence" | "pruneChatMessages" | "pruneClientErrors" | "pruneRateLimits";
|
|
777
1108
|
/** Which factory's exports the function lives in, i.e. which `convex/*.ts` file to reach it through. */
|
|
778
|
-
module: "runtime" | "presence";
|
|
1109
|
+
module: "runtime" | "presence" | "chat" | "clientErrors";
|
|
779
1110
|
};
|
|
780
1111
|
/** @internal */
|
|
781
|
-
export declare function jgengineCronSpecs(
|
|
1112
|
+
export declare function jgengineCronSpecs(options?: {
|
|
1113
|
+
runtimes?: readonly Pick<GameRuntime, "hasTick">[];
|
|
1114
|
+
intervalSeconds?: Partial<Record<JgCronSpec["functionKey"], number>>;
|
|
1115
|
+
chat?: boolean;
|
|
1116
|
+
clientErrors?: boolean;
|
|
1117
|
+
}): readonly JgCronSpec[];
|