@zhin.js/game-kit 2.0.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -16
- package/lib/base-session-service.d.ts +54 -0
- package/lib/base-session-service.d.ts.map +1 -0
- package/lib/base-session-service.js +139 -0
- package/lib/base-session-service.js.map +1 -0
- package/lib/board-sender.d.ts +6 -7
- package/lib/board-sender.d.ts.map +1 -1
- package/lib/board-sender.js.map +1 -1
- package/lib/choice-keyboard.d.ts +3 -1
- package/lib/choice-keyboard.d.ts.map +1 -1
- package/lib/choice-keyboard.js +4 -2
- package/lib/choice-keyboard.js.map +1 -1
- package/lib/command-alias.d.ts +3 -1
- package/lib/command-alias.d.ts.map +1 -1
- package/lib/command-alias.js.map +1 -1
- package/lib/command-message.d.ts +4 -1
- package/lib/command-message.d.ts.map +1 -1
- package/lib/command-message.js +0 -6
- package/lib/command-message.js.map +1 -1
- package/lib/define-game-plugin.d.ts +32 -0
- package/lib/define-game-plugin.d.ts.map +1 -0
- package/lib/define-game-plugin.js +87 -0
- package/lib/define-game-plugin.js.map +1 -0
- package/lib/deterministic-random.d.ts +16 -0
- package/lib/deterministic-random.d.ts.map +1 -0
- package/lib/deterministic-random.js +68 -0
- package/lib/deterministic-random.js.map +1 -0
- package/lib/game-action-alias.d.ts +7 -0
- package/lib/game-action-alias.d.ts.map +1 -1
- package/lib/game-action-alias.js +25 -0
- package/lib/game-action-alias.js.map +1 -1
- package/lib/game-events.d.ts +53 -0
- package/lib/game-events.d.ts.map +1 -0
- package/lib/game-events.js +26 -0
- package/lib/game-events.js.map +1 -0
- package/lib/game-interactive.d.ts +0 -22
- package/lib/game-interactive.d.ts.map +1 -1
- package/lib/game-interactive.js +1 -57
- package/lib/game-interactive.js.map +1 -1
- package/lib/game-records.d.ts +8 -3
- package/lib/game-records.d.ts.map +1 -1
- package/lib/game-records.js +27 -62
- package/lib/game-records.js.map +1 -1
- package/lib/game-session.d.ts +0 -59
- package/lib/game-session.d.ts.map +1 -1
- package/lib/game-session.js +2 -30
- package/lib/game-session.js.map +1 -1
- package/lib/grid-keyboard.d.ts.map +1 -1
- package/lib/grid-keyboard.js +2 -1
- package/lib/grid-keyboard.js.map +1 -1
- package/lib/index.d.ts +6 -9
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +6 -9
- package/lib/index.js.map +1 -1
- package/lib/memory-db.d.ts +6 -0
- package/lib/memory-db.d.ts.map +1 -1
- package/lib/memory-db.js +14 -2
- package/lib/memory-db.js.map +1 -1
- package/lib/runtime-hub.d.ts +0 -4
- package/lib/runtime-hub.d.ts.map +1 -1
- package/lib/runtime-hub.js +8 -0
- package/lib/runtime-hub.js.map +1 -1
- package/lib/session-coordinator.d.ts +27 -0
- package/lib/session-coordinator.d.ts.map +1 -0
- package/lib/session-coordinator.js +57 -0
- package/lib/session-coordinator.js.map +1 -0
- package/lib/versioned-session-service.d.ts +48 -0
- package/lib/versioned-session-service.d.ts.map +1 -0
- package/lib/versioned-session-service.js +116 -0
- package/lib/versioned-session-service.js.map +1 -0
- package/package.json +8 -7
- package/src/base-session-service.ts +210 -0
- package/src/board-sender.ts +6 -7
- package/src/choice-keyboard.ts +3 -1
- package/src/command-alias.ts +3 -1
- package/src/command-message.ts +9 -1
- package/src/define-game-plugin.ts +162 -0
- package/src/deterministic-random.ts +81 -0
- package/src/game-action-alias.ts +33 -0
- package/src/game-events.ts +75 -0
- package/src/game-interactive.ts +1 -80
- package/src/game-records.ts +30 -77
- package/src/game-session.ts +2 -84
- package/src/grid-keyboard.ts +2 -1
- package/src/index.ts +6 -9
- package/src/memory-db.ts +19 -2
- package/src/runtime-hub.ts +5 -0
- package/src/session-coordinator.ts +74 -0
- package/src/versioned-session-service.ts +162 -0
- package/lib/command-help.d.ts +0 -19
- package/lib/command-help.d.ts.map +0 -1
- package/lib/command-help.js +0 -91
- package/lib/command-help.js.map +0 -1
- package/lib/game-commands.d.ts +0 -3
- package/lib/game-commands.d.ts.map +0 -1
- package/lib/game-commands.js +0 -5
- package/lib/game-commands.js.map +0 -1
- package/lib/game-hub-feature.d.ts +0 -58
- package/lib/game-hub-feature.d.ts.map +0 -1
- package/lib/game-hub-feature.js +0 -102
- package/lib/game-hub-feature.js.map +0 -1
- package/lib/game-hub-flow.d.ts +0 -9
- package/lib/game-hub-flow.d.ts.map +0 -1
- package/lib/game-hub-flow.js +0 -90
- package/lib/game-hub-flow.js.map +0 -1
- package/lib/game-hub-menu-context.d.ts +0 -25
- package/lib/game-hub-menu-context.d.ts.map +0 -1
- package/lib/game-hub-menu-context.js +0 -64
- package/lib/game-hub-menu-context.js.map +0 -1
- package/lib/game-hub-menu.d.ts +0 -37
- package/lib/game-hub-menu.d.ts.map +0 -1
- package/lib/game-hub-menu.js +0 -162
- package/lib/game-hub-menu.js.map +0 -1
- package/lib/game-hub-mount.d.ts +0 -9
- package/lib/game-hub-mount.d.ts.map +0 -1
- package/lib/game-hub-mount.js +0 -108
- package/lib/game-hub-mount.js.map +0 -1
- package/lib/game-middleware.d.ts +0 -6
- package/lib/game-middleware.d.ts.map +0 -1
- package/lib/game-middleware.js +0 -9
- package/lib/game-middleware.js.map +0 -1
- package/lib/game-onboarding.d.ts +0 -8
- package/lib/game-onboarding.d.ts.map +0 -1
- package/lib/game-onboarding.js +0 -66
- package/lib/game-onboarding.js.map +0 -1
- package/lib/help-card.d.ts +0 -12
- package/lib/help-card.d.ts.map +0 -1
- package/lib/help-card.js +0 -129
- package/lib/help-card.js.map +0 -1
- package/src/command-help.ts +0 -117
- package/src/game-commands.ts +0 -4
- package/src/game-hub-feature.ts +0 -154
- package/src/game-hub-flow.ts +0 -114
- package/src/game-hub-menu-context.ts +0 -94
- package/src/game-hub-menu.ts +0 -223
- package/src/game-hub-mount.ts +0 -172
- package/src/game-middleware.ts +0 -14
- package/src/game-onboarding.ts +0 -69
- package/src/help-card.ts +0 -188
package/lib/game-session.d.ts
CHANGED
|
@@ -1,64 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 通用游戏会话接口
|
|
3
|
-
* 定义回合制游戏的基础会话结构
|
|
4
|
-
*/
|
|
5
|
-
import type { Message } from '@zhin.js/core';
|
|
6
|
-
/** 会话状态 */
|
|
7
|
-
export type GameStatus = 'active' | 'won' | 'draw' | 'aborted';
|
|
8
|
-
/** 通用游戏会话接口 */
|
|
9
|
-
export interface GameSession {
|
|
10
|
-
/** 会话 ID */
|
|
11
|
-
id: string;
|
|
12
|
-
/** 适配器名称 */
|
|
13
|
-
adapter: string;
|
|
14
|
-
/** Endpoint 名称 */
|
|
15
|
-
endpoint: string;
|
|
16
|
-
/** 频道类型 */
|
|
17
|
-
channel_type: 'private' | 'group' | 'channel';
|
|
18
|
-
/** 频道 ID */
|
|
19
|
-
channel_id: string;
|
|
20
|
-
/** 频道唯一键 */
|
|
21
|
-
channel_key: string;
|
|
22
|
-
/** 棋盘消息 ID(用于编辑) */
|
|
23
|
-
board_message_id: string;
|
|
24
|
-
/** 当前状态 */
|
|
25
|
-
status: GameStatus;
|
|
26
|
-
/** 更新时间戳 */
|
|
27
|
-
updated_at: number;
|
|
28
|
-
/** 创建时间戳 */
|
|
29
|
-
created_at: number;
|
|
30
|
-
}
|
|
31
|
-
/** 回合制游戏会话(2 人对战) */
|
|
32
|
-
export interface TurnBasedSession extends GameSession {
|
|
33
|
-
/** 玩家 1 ID */
|
|
34
|
-
player_1: string;
|
|
35
|
-
/** 玩家 2 ID */
|
|
36
|
-
player_2: string;
|
|
37
|
-
/** 玩家 1 显示名 */
|
|
38
|
-
player_1_name: string;
|
|
39
|
-
/** 玩家 2 显示名 */
|
|
40
|
-
player_2_name: string;
|
|
41
|
-
/** 当前回合(1 或 2) */
|
|
42
|
-
turn: 1 | 2;
|
|
43
|
-
/** 胜者(0=无,1=玩家1,2=玩家2) */
|
|
44
|
-
winner: 0 | 1 | 2;
|
|
45
|
-
/** 步数 */
|
|
46
|
-
move_count: number;
|
|
47
|
-
}
|
|
48
1
|
/** 生成会话 ID */
|
|
49
2
|
export declare function generateSessionId(): string;
|
|
50
|
-
/** 获取当前回合玩家 ID */
|
|
51
|
-
export declare function currentPlayerId(session: TurnBasedSession): string;
|
|
52
|
-
/** 判断用户是否为本局玩家 */
|
|
53
|
-
export declare function isPlayer(session: TurnBasedSession, userId: string): boolean;
|
|
54
|
-
/** 判断是否轮到该用户 */
|
|
55
|
-
export declare function isPlayerTurn(session: TurnBasedSession, userId: string): boolean;
|
|
56
|
-
/** 获取玩家编号(1 或 2),非玩家返回 null */
|
|
57
|
-
export declare function playerNumber(session: TurnBasedSession, userId: string): 1 | 2 | null;
|
|
58
|
-
/** 切换回合 */
|
|
59
|
-
export declare function nextTurn(current: 1 | 2): 1 | 2;
|
|
60
|
-
/** 从 Message 提取发送者显示名 */
|
|
61
|
-
export declare function senderDisplayName(message: Message): string;
|
|
62
3
|
/** 比对出站 board_message_id 与平台回调 messageId(含 composite id) */
|
|
63
4
|
export declare function boardMessageMatches(stored: string, messageId: string): boolean;
|
|
64
5
|
//# sourceMappingURL=game-session.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"game-session.d.ts","sourceRoot":"","sources":["../src/game-session.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"game-session.d.ts","sourceRoot":"","sources":["../src/game-session.ts"],"names":[],"mappings":"AAEA,cAAc;AACd,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,4DAA4D;AAC5D,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAM9E"}
|
package/lib/game-session.js
CHANGED
|
@@ -3,35 +3,6 @@ import { generateCompactId } from './random.js';
|
|
|
3
3
|
export function generateSessionId() {
|
|
4
4
|
return generateCompactId('s');
|
|
5
5
|
}
|
|
6
|
-
/** 获取当前回合玩家 ID */
|
|
7
|
-
export function currentPlayerId(session) {
|
|
8
|
-
return session.turn === 1 ? session.player_1 : session.player_2;
|
|
9
|
-
}
|
|
10
|
-
/** 判断用户是否为本局玩家 */
|
|
11
|
-
export function isPlayer(session, userId) {
|
|
12
|
-
return session.player_1 === userId || session.player_2 === userId;
|
|
13
|
-
}
|
|
14
|
-
/** 判断是否轮到该用户 */
|
|
15
|
-
export function isPlayerTurn(session, userId) {
|
|
16
|
-
return currentPlayerId(session) === userId;
|
|
17
|
-
}
|
|
18
|
-
/** 获取玩家编号(1 或 2),非玩家返回 null */
|
|
19
|
-
export function playerNumber(session, userId) {
|
|
20
|
-
if (session.player_1 === userId)
|
|
21
|
-
return 1;
|
|
22
|
-
if (session.player_2 === userId)
|
|
23
|
-
return 2;
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
/** 切换回合 */
|
|
27
|
-
export function nextTurn(current) {
|
|
28
|
-
return current === 1 ? 2 : 1;
|
|
29
|
-
}
|
|
30
|
-
/** 从 Message 提取发送者显示名 */
|
|
31
|
-
export function senderDisplayName(message) {
|
|
32
|
-
const name = message.$sender.name?.trim();
|
|
33
|
-
return name || message.$sender.id;
|
|
34
|
-
}
|
|
35
6
|
/** 比对出站 board_message_id 与平台回调 messageId(含 composite id) */
|
|
36
7
|
export function boardMessageMatches(stored, messageId) {
|
|
37
8
|
if (!stored || !messageId)
|
|
@@ -39,6 +10,7 @@ export function boardMessageMatches(stored, messageId) {
|
|
|
39
10
|
if (stored === messageId || stored.endsWith(`:${messageId}`))
|
|
40
11
|
return true;
|
|
41
12
|
const tail = stored.split(':').pop();
|
|
42
|
-
|
|
13
|
+
// 尾段匹配要求全等或以 `:tail` 结尾(段边界),避免 x99912345 误中 12345
|
|
14
|
+
return !!tail && (messageId === tail || messageId.endsWith(`:${tail}`));
|
|
43
15
|
}
|
|
44
16
|
//# sourceMappingURL=game-session.js.map
|
package/lib/game-session.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"game-session.js","sourceRoot":"","sources":["../src/game-session.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"game-session.js","sourceRoot":"","sources":["../src/game-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,cAAc;AACd,MAAM,UAAU,iBAAiB;IAC/B,OAAO,iBAAiB,CAAC,GAAG,CAAC,CAAC;AAChC,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,mBAAmB,CAAC,MAAc,EAAE,SAAiB;IACnE,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS;QAAE,OAAO,KAAK,CAAC;IACxC,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,SAAS,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1E,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;IACrC,mDAAmD;IACnD,OAAO,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;AAC1E,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grid-keyboard.d.ts","sourceRoot":"","sources":["../src/grid-keyboard.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAW,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAA0B,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAIjF,MAAM,WAAW,QAAQ,CAAC,CAAC,GAAG,OAAO;IACnC,mCAAmC;IACnC,KAAK,EAAE,CAAC,CAAC;IACT,aAAa;IACb,KAAK,EAAE,MAAM,CAAC;IACd,mBAAmB;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,gBAAgB;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB,CAAC,CAAC,GAAG,OAAO;IAC9C,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS;IACT,IAAI,EAAE,MAAM,CAAC;IACb,SAAS;IACT,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IACrB,YAAY;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4BAA4B;IAC5B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mCAAmC;IACnC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,MAAM,CAAC;IACjG,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,oBAAoB;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,YAAY,EAAE,CAAC;IAC7B,0CAA0C;IAC1C,kBAAkB,CAAC,EAAE,UAAU,CAAC;IAChC,6BAA6B;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,QAAQ,EAAE,GAChB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWxB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,WAAW,
|
|
1
|
+
{"version":3,"file":"grid-keyboard.d.ts","sourceRoot":"","sources":["../src/grid-keyboard.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAW,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAA0B,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAIjF,MAAM,WAAW,QAAQ,CAAC,CAAC,GAAG,OAAO;IACnC,mCAAmC;IACnC,KAAK,EAAE,CAAC,CAAC;IACT,aAAa;IACb,KAAK,EAAE,MAAM,CAAC;IACd,mBAAmB;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,gBAAgB;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB,CAAC,CAAC,GAAG,OAAO;IAC9C,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS;IACT,IAAI,EAAE,MAAM,CAAC;IACb,SAAS;IACT,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IACrB,YAAY;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4BAA4B;IAC5B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mCAAmC;IACnC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,KAAK,MAAM,CAAC;IACjG,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,oBAAoB;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,YAAY,EAAE,CAAC;IAC7B,0CAA0C;IAC1C,kBAAkB,CAAC,EAAE,UAAU,CAAC;IAChC,6BAA6B;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,QAAQ,EAAE,GAChB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWxB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,WAAW,CAmFjF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,cAAc,CAAC,EAAE,MAAM,GACtB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAS5D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ9D"}
|
package/lib/grid-keyboard.js
CHANGED
|
@@ -63,7 +63,8 @@ export function buildGridKeyboard(options) {
|
|
|
63
63
|
channelType,
|
|
64
64
|
}));
|
|
65
65
|
}));
|
|
66
|
-
|
|
66
|
+
// postChoices 编号从可落子格子数后续起,避免覆盖格子数字映射
|
|
67
|
+
Object.assign(fallback, buildChoiceFallbackMap(gamePrefix, sessionId, postChoices, Object.keys(fallback).length + 1));
|
|
67
68
|
}
|
|
68
69
|
const parts = [
|
|
69
70
|
segment.text(textLines.join('\n')),
|
package/lib/grid-keyboard.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grid-keyboard.js","sourceRoot":"","sources":["../src/grid-keyboard.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"grid-keyboard.js","sourceRoot":"","sources":["../src/grid-keyboard.ts"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts
CHANGED
|
@@ -7,19 +7,16 @@ export * from './grid-keyboard.js';
|
|
|
7
7
|
export * from './choice-keyboard.js';
|
|
8
8
|
export * from './board-sender.js';
|
|
9
9
|
export * from './game-session.js';
|
|
10
|
-
export * from './
|
|
11
|
-
export * from './
|
|
12
|
-
export * from './
|
|
13
|
-
export * from './game-
|
|
14
|
-
export * from './
|
|
15
|
-
export * from './game-
|
|
10
|
+
export * from './base-session-service.js';
|
|
11
|
+
export * from './versioned-session-service.js';
|
|
12
|
+
export * from './deterministic-random.js';
|
|
13
|
+
export * from './game-events.js';
|
|
14
|
+
export * from './session-coordinator.js';
|
|
15
|
+
export * from './define-game-plugin.js';
|
|
16
16
|
export * from './game-action-alias.js';
|
|
17
|
-
export * from './game-commands.js';
|
|
18
17
|
export * from './game-interactive.js';
|
|
19
18
|
export * from './interaction-profiles.js';
|
|
20
19
|
export * from './game-records.js';
|
|
21
|
-
export * from './game-onboarding.js';
|
|
22
|
-
export * from './command-help.js';
|
|
23
20
|
export * from './command-message.js';
|
|
24
21
|
export * from './memory-db.js';
|
|
25
22
|
export * from './send-content-text.js';
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -7,19 +7,16 @@ export * from './grid-keyboard.js';
|
|
|
7
7
|
export * from './choice-keyboard.js';
|
|
8
8
|
export * from './board-sender.js';
|
|
9
9
|
export * from './game-session.js';
|
|
10
|
-
export * from './
|
|
11
|
-
export * from './
|
|
12
|
-
export * from './
|
|
13
|
-
export * from './game-
|
|
14
|
-
export * from './
|
|
15
|
-
export * from './game-
|
|
10
|
+
export * from './base-session-service.js';
|
|
11
|
+
export * from './versioned-session-service.js';
|
|
12
|
+
export * from './deterministic-random.js';
|
|
13
|
+
export * from './game-events.js';
|
|
14
|
+
export * from './session-coordinator.js';
|
|
15
|
+
export * from './define-game-plugin.js';
|
|
16
16
|
export * from './game-action-alias.js';
|
|
17
|
-
export * from './game-commands.js';
|
|
18
17
|
export * from './game-interactive.js';
|
|
19
18
|
export * from './interaction-profiles.js';
|
|
20
19
|
export * from './game-records.js';
|
|
21
|
-
export * from './game-onboarding.js';
|
|
22
|
-
export * from './command-help.js';
|
|
23
20
|
export * from './command-message.js';
|
|
24
21
|
export * from './memory-db.js';
|
|
25
22
|
export * from './send-content-text.js';
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC"}
|
package/lib/memory-db.d.ts
CHANGED
|
@@ -17,6 +17,12 @@ export interface InMemoryGameDb {
|
|
|
17
17
|
}
|
|
18
18
|
/** Create an in-memory db with the given model table names. */
|
|
19
19
|
export declare function createInMemoryGameDb(tableNames: readonly string[]): InMemoryGameDb;
|
|
20
|
+
/**
|
|
21
|
+
* Typed boundary used by game tests and standalone embedders. The database
|
|
22
|
+
* implementation is deliberately structural so game packages keep their
|
|
23
|
+
* precise model types without each package recreating the same adapter.
|
|
24
|
+
*/
|
|
25
|
+
export declare function createMemoryGameServices<TDatabase, TServices>(tableNames: readonly string[], factory: (database: TDatabase) => TServices): TServices;
|
|
20
26
|
/** Minimal DatabaseHost model surface (structural typing; no plugin-runtime dep). */
|
|
21
27
|
export interface HostGameModelSource {
|
|
22
28
|
select(): {
|
package/lib/memory-db.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-db.d.ts","sourceRoot":"","sources":["../src/memory-db.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEnC,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACzD,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IAC9D,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7E,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAClE;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE;QAAE,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,iBAAiB,GAAG,SAAS,CAAA;KAAE,CAAC;CAClE;
|
|
1
|
+
{"version":3,"file":"memory-db.d.ts","sourceRoot":"","sources":["../src/memory-db.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEnC,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACzD,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IAC9D,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7E,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAClE;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE;QAAE,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,iBAAiB,GAAG,SAAS,CAAA;KAAE,CAAC;CAClE;AA4CD,+DAA+D;AAC/D,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,cAAc,CAUlF;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,SAAS,EAC3D,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,OAAO,EAAE,CAAC,QAAQ,EAAE,SAAS,KAAK,SAAS,GAC1C,SAAS,CAEX;AAED,qFAAqF;AACrF,MAAM,WAAW,mBAAmB;IAClC,MAAM,IAAI;QAER,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;KAC/E,CAAC;IACF,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvD,MAAM,IAAI;QAAE,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;KAAE,CAAC;IACtE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;QACtC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;KACzD,CAAC;CACH;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE;QAAE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAAA;KAAE,CAAC;CAChE;AA+BD,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,gBAAgB,EACtB,UAAU,EAAE,SAAS,MAAM,EAAE,GAC5B,cAAc,CAUhB"}
|
package/lib/memory-db.js
CHANGED
|
@@ -6,8 +6,12 @@ function createMemoryModel() {
|
|
|
6
6
|
const rows = [];
|
|
7
7
|
const match = (row, q) => Object.entries(q).every(([k, v]) => row[k] === v);
|
|
8
8
|
return {
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
// 返回行拷贝,避免调用方直接改字段绕过 updateWhere
|
|
10
|
+
findAll: async (q = {}) => rows.filter((row) => match(row, q)).map((row) => ({ ...row })),
|
|
11
|
+
findOne: async (q = {}) => {
|
|
12
|
+
const found = rows.find((row) => match(row, q));
|
|
13
|
+
return found ? { ...found } : null;
|
|
14
|
+
},
|
|
11
15
|
create: async (row) => {
|
|
12
16
|
rows.push({ ...row });
|
|
13
17
|
return row;
|
|
@@ -47,6 +51,14 @@ export function createInMemoryGameDb(tableNames) {
|
|
|
47
51
|
},
|
|
48
52
|
};
|
|
49
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Typed boundary used by game tests and standalone embedders. The database
|
|
56
|
+
* implementation is deliberately structural so game packages keep their
|
|
57
|
+
* precise model types without each package recreating the same adapter.
|
|
58
|
+
*/
|
|
59
|
+
export function createMemoryGameServices(tableNames, factory) {
|
|
60
|
+
return factory(createInMemoryGameDb(tableNames));
|
|
61
|
+
}
|
|
50
62
|
function wrapHostModel(model) {
|
|
51
63
|
return {
|
|
52
64
|
findAll: async (q = {}) => {
|
package/lib/memory-db.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-db.js","sourceRoot":"","sources":["../src/memory-db.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAgBH,SAAS,iBAAiB;IACxB,MAAM,IAAI,GAAU,EAAE,CAAC;IAEvB,MAAM,KAAK,GAAG,CAAC,GAAQ,EAAE,CAA0B,EAAE,EAAE,CACrD,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAEpD,OAAO;QACL,OAAO,EAAE,KAAK,EAAE,IAA6B,EAAE,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"memory-db.js","sourceRoot":"","sources":["../src/memory-db.ts"],"names":[],"mappings":"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"}
|
package/lib/runtime-hub.d.ts
CHANGED
package/lib/runtime-hub.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-hub.d.ts","sourceRoot":"","sources":["../src/runtime-hub.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runtime-hub.d.ts","sourceRoot":"","sources":["../src/runtime-hub.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;CACnD;AAID,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,qBAAqB,GAAG,MAAM,IAAI,CAe3E;AAED,wBAAgB,eAAe,IAAI,SAAS,qBAAqB,EAAE,CAKlE;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS,CAW5E;AAED,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD;AAED,wBAAgB,sBAAsB,IAAI,MAAM,CAmB/C;AAED,gEAAgE;AAChE,eAAO,MAAM,0BAA0B,QAAiB,CAAC;AAEzD,oCAAoC;AACpC,eAAO,MAAM,uBAAuB,mBAAmB,CAAC"}
|
package/lib/runtime-hub.js
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin Runtime game hub — module-level registry (no legacy Feature / getPlugin).
|
|
3
|
+
* Games call `registerRuntimeGame` from `setup()`; hub plugin lists them.
|
|
4
|
+
*/
|
|
5
|
+
import { bindGameRecordDatabase } from './game-records.js';
|
|
1
6
|
const games = new Map();
|
|
2
7
|
export function registerRuntimeGame(game) {
|
|
3
8
|
const registered = Object.freeze({ ...game });
|
|
4
9
|
const registrations = games.get(game.id) ?? [];
|
|
5
10
|
registrations.push(registered);
|
|
6
11
|
games.set(game.id, registrations);
|
|
12
|
+
// 把游戏绑定到其插件刚注册的战绩库(按 Host/插件作用域取库)
|
|
13
|
+
const unbindRecords = bindGameRecordDatabase(game.id);
|
|
7
14
|
return () => {
|
|
15
|
+
unbindRecords();
|
|
8
16
|
const current = games.get(game.id);
|
|
9
17
|
if (!current)
|
|
10
18
|
return;
|
package/lib/runtime-hub.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-hub.js","sourceRoot":"","sources":["../src/runtime-hub.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runtime-hub.js","sourceRoot":"","sources":["../src/runtime-hub.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface ActiveGameSession {
|
|
2
|
+
readonly id: string;
|
|
3
|
+
readonly channel_key: string;
|
|
4
|
+
}
|
|
5
|
+
export interface GameSessionProvider {
|
|
6
|
+
readonly gameId: string;
|
|
7
|
+
getActiveForUser(channelKey: string, userId: string): Promise<ActiveGameSession | null>;
|
|
8
|
+
}
|
|
9
|
+
export declare class GameSessionConflictError extends Error {
|
|
10
|
+
readonly requestedGameId: string;
|
|
11
|
+
readonly activeGameId: string;
|
|
12
|
+
readonly sessionId: string;
|
|
13
|
+
readonly userId: string;
|
|
14
|
+
constructor(requestedGameId: string, activeGameId: string, sessionId: string, userId: string);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Cross-game active-session index. Registrations form per-game stacks so HMR
|
|
18
|
+
* can install a new generation before disposing the old one without a gap.
|
|
19
|
+
*/
|
|
20
|
+
export declare class GameSessionCoordinator {
|
|
21
|
+
#private;
|
|
22
|
+
register(provider: GameSessionProvider): () => void;
|
|
23
|
+
assertAvailable(requestedGameId: string, channelKey: string, userIds: readonly string[]): Promise<void>;
|
|
24
|
+
clear(): void;
|
|
25
|
+
}
|
|
26
|
+
export declare const gameSessionCoordinator: GameSessionCoordinator;
|
|
27
|
+
//# sourceMappingURL=session-coordinator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-coordinator.d.ts","sourceRoot":"","sources":["../src/session-coordinator.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;CACzF;AAED,qBAAa,wBAAyB,SAAQ,KAAK;IAE/C,QAAQ,CAAC,eAAe,EAAE,MAAM;IAChC,QAAQ,CAAC,YAAY,EAAE,MAAM;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM;gBAHd,eAAe,EAAE,MAAM,EACvB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM;CAQ1B;AAED;;;GAGG;AACH,qBAAa,sBAAsB;;IAGjC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,GAAG,MAAM,IAAI;IAa7C,eAAe,CACnB,eAAe,EAAE,MAAM,EACvB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,OAAO,CAAC,IAAI,CAAC;IAmBhB,KAAK,IAAI,IAAI;CAGd;AAED,eAAO,MAAM,sBAAsB,wBAA+B,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export class GameSessionConflictError extends Error {
|
|
2
|
+
requestedGameId;
|
|
3
|
+
activeGameId;
|
|
4
|
+
sessionId;
|
|
5
|
+
userId;
|
|
6
|
+
constructor(requestedGameId, activeGameId, sessionId, userId) {
|
|
7
|
+
super(`你在当前频道已有进行中的「${activeGameId}」对局,`
|
|
8
|
+
+ `请先结束它,再开始「${requestedGameId}」。`);
|
|
9
|
+
this.requestedGameId = requestedGameId;
|
|
10
|
+
this.activeGameId = activeGameId;
|
|
11
|
+
this.sessionId = sessionId;
|
|
12
|
+
this.userId = userId;
|
|
13
|
+
this.name = 'GameSessionConflictError';
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Cross-game active-session index. Registrations form per-game stacks so HMR
|
|
18
|
+
* can install a new generation before disposing the old one without a gap.
|
|
19
|
+
*/
|
|
20
|
+
export class GameSessionCoordinator {
|
|
21
|
+
#providers = new Map();
|
|
22
|
+
register(provider) {
|
|
23
|
+
const providers = this.#providers.get(provider.gameId) ?? [];
|
|
24
|
+
providers.push(provider);
|
|
25
|
+
this.#providers.set(provider.gameId, providers);
|
|
26
|
+
return () => {
|
|
27
|
+
const current = this.#providers.get(provider.gameId);
|
|
28
|
+
if (!current)
|
|
29
|
+
return;
|
|
30
|
+
const index = current.lastIndexOf(provider);
|
|
31
|
+
if (index >= 0)
|
|
32
|
+
current.splice(index, 1);
|
|
33
|
+
if (current.length === 0)
|
|
34
|
+
this.#providers.delete(provider.gameId);
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
async assertAvailable(requestedGameId, channelKey, userIds) {
|
|
38
|
+
for (const [gameId, registrations] of this.#providers) {
|
|
39
|
+
if (gameId === requestedGameId)
|
|
40
|
+
continue;
|
|
41
|
+
const provider = registrations[registrations.length - 1];
|
|
42
|
+
if (!provider)
|
|
43
|
+
continue;
|
|
44
|
+
for (const userId of new Set(userIds.filter(Boolean))) {
|
|
45
|
+
const active = await provider.getActiveForUser(channelKey, userId);
|
|
46
|
+
if (active) {
|
|
47
|
+
throw new GameSessionConflictError(requestedGameId, gameId, active.id, userId);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
clear() {
|
|
53
|
+
this.#providers.clear();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export const gameSessionCoordinator = new GameSessionCoordinator();
|
|
57
|
+
//# sourceMappingURL=session-coordinator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-coordinator.js","sourceRoot":"","sources":["../src/session-coordinator.ts"],"names":[],"mappings":"AAUA,MAAM,OAAO,wBAAyB,SAAQ,KAAK;IAEtC;IACA;IACA;IACA;IAJX,YACW,eAAuB,EACvB,YAAoB,EACpB,SAAiB,EACjB,MAAc;QAEvB,KAAK,CACH,gBAAgB,YAAY,MAAM;cAChC,aAAa,eAAe,IAAI,CACnC,CAAC;QARO,oBAAe,GAAf,eAAe,CAAQ;QACvB,iBAAY,GAAZ,YAAY,CAAQ;QACpB,cAAS,GAAT,SAAS,CAAQ;QACjB,WAAM,GAAN,MAAM,CAAQ;QAMvB,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;IACzC,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,sBAAsB;IACxB,UAAU,GAAG,IAAI,GAAG,EAAiC,CAAC;IAE/D,QAAQ,CAAC,QAA6B;QACpC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAC7D,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAChD,OAAO,GAAG,EAAE;YACV,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACrD,IAAI,CAAC,OAAO;gBAAE,OAAO;YACrB,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YAC5C,IAAI,KAAK,IAAI,CAAC;gBAAE,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YACzC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;gBAAE,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACpE,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,eAAuB,EACvB,UAAkB,EAClB,OAA0B;QAE1B,KAAK,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACtD,IAAI,MAAM,KAAK,eAAe;gBAAE,SAAS;YACzC,MAAM,QAAQ,GAAG,aAAa,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACzD,IAAI,CAAC,QAAQ;gBAAE,SAAS;YACxB,KAAK,MAAM,MAAM,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;gBACtD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,gBAAgB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;gBACnE,IAAI,MAAM,EAAE,CAAC;oBACX,MAAM,IAAI,wBAAwB,CAChC,eAAe,EACf,MAAM,EACN,MAAM,CAAC,EAAE,EACT,MAAM,CACP,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IAC1B,CAAC;CACF;AAED,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,sBAAsB,EAAE,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { BaseSessionService, type BaseGameSessionRow, type BaseSessionServiceOptions, type GameSessionDatabase } from './base-session-service.js';
|
|
2
|
+
export interface VersionedGameSessionRow extends BaseGameSessionRow {
|
|
3
|
+
revision: number;
|
|
4
|
+
/** JSON string containing the bounded action-id history. */
|
|
5
|
+
processed_actions: string;
|
|
6
|
+
}
|
|
7
|
+
export interface SessionMutationOptions<TRow extends VersionedGameSessionRow> {
|
|
8
|
+
readonly actionId: string;
|
|
9
|
+
readonly expectedRevision?: number;
|
|
10
|
+
readonly apply: Partial<TRow> | ((session: Readonly<TRow>) => Partial<TRow> | Promise<Partial<TRow>>);
|
|
11
|
+
}
|
|
12
|
+
export type SessionMutationResult<TRow extends VersionedGameSessionRow> = {
|
|
13
|
+
readonly kind: 'applied';
|
|
14
|
+
readonly session: TRow;
|
|
15
|
+
} | {
|
|
16
|
+
readonly kind: 'duplicate';
|
|
17
|
+
readonly session: TRow;
|
|
18
|
+
};
|
|
19
|
+
export declare class SessionNotFoundError extends Error {
|
|
20
|
+
readonly sessionId: string;
|
|
21
|
+
constructor(sessionId: string);
|
|
22
|
+
}
|
|
23
|
+
export declare class SessionRevisionConflictError extends Error {
|
|
24
|
+
readonly sessionId: string;
|
|
25
|
+
readonly expectedRevision: number;
|
|
26
|
+
readonly actualRevision: number;
|
|
27
|
+
constructor(sessionId: string, expectedRevision: number, actualRevision: number);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A keyed promise queue. It prevents lost updates inside one runtime while the
|
|
31
|
+
* persisted revision check protects deployments that share a database.
|
|
32
|
+
*/
|
|
33
|
+
export declare class SessionActionGate {
|
|
34
|
+
#private;
|
|
35
|
+
run<TResult>(sessionId: string, action: () => TResult | Promise<TResult>): Promise<TResult>;
|
|
36
|
+
get pendingSessions(): number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Adds serialized, optimistic and idempotent mutations to BaseSessionService.
|
|
40
|
+
* Action ids are intentionally persisted so adapter retries remain harmless
|
|
41
|
+
* after a process restart.
|
|
42
|
+
*/
|
|
43
|
+
export declare abstract class VersionedSessionService<TRow extends VersionedGameSessionRow> extends BaseSessionService<TRow> {
|
|
44
|
+
#private;
|
|
45
|
+
protected constructor(database: GameSessionDatabase<TRow>, options: BaseSessionServiceOptions<TRow>);
|
|
46
|
+
mutateSession(id: string, options: SessionMutationOptions<TRow>): Promise<SessionMutationResult<TRow>>;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=versioned-session-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"versioned-session-service.d.ts","sourceRoot":"","sources":["../src/versioned-session-service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,mBAAmB,EACzB,MAAM,2BAA2B,CAAC;AAInC,MAAM,WAAW,uBAAwB,SAAQ,kBAAkB;IACjE,QAAQ,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,sBAAsB,CAAC,IAAI,SAAS,uBAAuB;IAC1E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,KAAK,EACV,OAAO,CAAC,IAAI,CAAC,GACb,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,KACzB,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;CAC7C;AAED,MAAM,MAAM,qBAAqB,CAAC,IAAI,SAAS,uBAAuB,IAClE;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAA;CAAE,GACpD;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAA;CAAE,CAAC;AAE3D,qBAAa,oBAAqB,SAAQ,KAAK;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM;gBAAjB,SAAS,EAAE,MAAM;CAIvC;AAED,qBAAa,4BAA6B,SAAQ,KAAK;IAEnD,QAAQ,CAAC,SAAS,EAAE,MAAM;IAC1B,QAAQ,CAAC,gBAAgB,EAAE,MAAM;IACjC,QAAQ,CAAC,cAAc,EAAE,MAAM;gBAFtB,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,MAAM,EACxB,cAAc,EAAE,MAAM;CAQlC;AAED;;;GAGG;AACH,qBAAa,iBAAiB;;IAGtB,GAAG,CAAC,OAAO,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GACvC,OAAO,CAAC,OAAO,CAAC;IAiBnB,IAAI,eAAe,IAAI,MAAM,CAE5B;CACF;AAED;;;;GAIG;AACH,8BAAsB,uBAAuB,CAC3C,IAAI,SAAS,uBAAuB,CACpC,SAAQ,kBAAkB,CAAC,IAAI,CAAC;;IAIhC,SAAS,aACP,QAAQ,EAAE,mBAAmB,CAAC,IAAI,CAAC,EACnC,OAAO,EAAE,yBAAyB,CAAC,IAAI,CAAC;IAM1C,aAAa,CACX,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,sBAAsB,CAAC,IAAI,CAAC,GACpC,OAAO,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC;CAgDxC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { BaseSessionService, } from './base-session-service.js';
|
|
2
|
+
const DEFAULT_ACTION_HISTORY_LIMIT = 128;
|
|
3
|
+
export class SessionNotFoundError extends Error {
|
|
4
|
+
sessionId;
|
|
5
|
+
constructor(sessionId) {
|
|
6
|
+
super(`Game session "${sessionId}" does not exist.`);
|
|
7
|
+
this.sessionId = sessionId;
|
|
8
|
+
this.name = 'SessionNotFoundError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export class SessionRevisionConflictError extends Error {
|
|
12
|
+
sessionId;
|
|
13
|
+
expectedRevision;
|
|
14
|
+
actualRevision;
|
|
15
|
+
constructor(sessionId, expectedRevision, actualRevision) {
|
|
16
|
+
super(`Game session "${sessionId}" changed: expected revision `
|
|
17
|
+
+ `${expectedRevision}, received ${actualRevision}.`);
|
|
18
|
+
this.sessionId = sessionId;
|
|
19
|
+
this.expectedRevision = expectedRevision;
|
|
20
|
+
this.actualRevision = actualRevision;
|
|
21
|
+
this.name = 'SessionRevisionConflictError';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A keyed promise queue. It prevents lost updates inside one runtime while the
|
|
26
|
+
* persisted revision check protects deployments that share a database.
|
|
27
|
+
*/
|
|
28
|
+
export class SessionActionGate {
|
|
29
|
+
#tails = new Map();
|
|
30
|
+
async run(sessionId, action) {
|
|
31
|
+
const previous = this.#tails.get(sessionId) ?? Promise.resolve();
|
|
32
|
+
let release = () => undefined;
|
|
33
|
+
const pending = new Promise((resolve) => {
|
|
34
|
+
release = resolve;
|
|
35
|
+
});
|
|
36
|
+
const tail = previous.catch(() => undefined).then(() => pending);
|
|
37
|
+
this.#tails.set(sessionId, tail);
|
|
38
|
+
await previous.catch(() => undefined);
|
|
39
|
+
try {
|
|
40
|
+
return await action();
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
release();
|
|
44
|
+
if (this.#tails.get(sessionId) === tail)
|
|
45
|
+
this.#tails.delete(sessionId);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
get pendingSessions() {
|
|
49
|
+
return this.#tails.size;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Adds serialized, optimistic and idempotent mutations to BaseSessionService.
|
|
54
|
+
* Action ids are intentionally persisted so adapter retries remain harmless
|
|
55
|
+
* after a process restart.
|
|
56
|
+
*/
|
|
57
|
+
export class VersionedSessionService extends BaseSessionService {
|
|
58
|
+
#gate = new SessionActionGate();
|
|
59
|
+
#actionHistoryLimit;
|
|
60
|
+
constructor(database, options) {
|
|
61
|
+
super(database, options);
|
|
62
|
+
this.#actionHistoryLimit = DEFAULT_ACTION_HISTORY_LIMIT;
|
|
63
|
+
}
|
|
64
|
+
mutateSession(id, options) {
|
|
65
|
+
if (!options.actionId.trim()) {
|
|
66
|
+
return Promise.reject(new TypeError('actionId must not be empty'));
|
|
67
|
+
}
|
|
68
|
+
return this.#gate.run(id, async () => {
|
|
69
|
+
const previous = await this.getById(id);
|
|
70
|
+
if (!previous)
|
|
71
|
+
throw new SessionNotFoundError(id);
|
|
72
|
+
const processedActions = parseActionHistory(previous.processed_actions);
|
|
73
|
+
if (processedActions.includes(options.actionId)) {
|
|
74
|
+
return { kind: 'duplicate', session: previous };
|
|
75
|
+
}
|
|
76
|
+
if (options.expectedRevision !== undefined
|
|
77
|
+
&& options.expectedRevision !== previous.revision) {
|
|
78
|
+
throw new SessionRevisionConflictError(id, options.expectedRevision, previous.revision);
|
|
79
|
+
}
|
|
80
|
+
const patch = typeof options.apply === 'function'
|
|
81
|
+
? await options.apply(previous)
|
|
82
|
+
: options.apply;
|
|
83
|
+
const revision = previous.revision + 1;
|
|
84
|
+
const nextActions = [
|
|
85
|
+
...processedActions,
|
|
86
|
+
options.actionId,
|
|
87
|
+
].slice(-this.#actionHistoryLimit);
|
|
88
|
+
const session = await this.commitSession(previous, {
|
|
89
|
+
...patch,
|
|
90
|
+
revision,
|
|
91
|
+
processed_actions: JSON.stringify(nextActions),
|
|
92
|
+
}, { id, revision: previous.revision });
|
|
93
|
+
if (!session
|
|
94
|
+
|| session.revision !== revision
|
|
95
|
+
|| !parseActionHistory(session.processed_actions).includes(options.actionId)) {
|
|
96
|
+
const actual = session?.revision
|
|
97
|
+
?? (await this.getById(id))?.revision
|
|
98
|
+
?? previous.revision;
|
|
99
|
+
throw new SessionRevisionConflictError(id, previous.revision, actual);
|
|
100
|
+
}
|
|
101
|
+
return { kind: 'applied', session };
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function parseActionHistory(value) {
|
|
106
|
+
try {
|
|
107
|
+
const parsed = JSON.parse(value);
|
|
108
|
+
if (!Array.isArray(parsed))
|
|
109
|
+
return [];
|
|
110
|
+
return parsed.filter((item) => typeof item === 'string');
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=versioned-session-service.js.map
|