refactor: 迁移大鱼与汪汪 runtime 请求骨架
This commit is contained in:
@@ -44,7 +44,8 @@
|
|||||||
|
|
||||||
- 背景:Match3D、SquareHole、Puzzle、Jump Hop 等 runtime client 重复手写 path segment 编码、JSON header / body、runtime guest token、auth options 和 retry options,新增玩法容易遗漏同一请求骨架。
|
- 背景:Match3D、SquareHole、Puzzle、Jump Hop 等 runtime client 重复手写 path segment 编码、JSON header / body、runtime guest token、auth options 和 retry options,新增玩法容易遗漏同一请求骨架。
|
||||||
- 决策:新增 `src/services/runtimeRequest.ts`,以 `buildRuntimeApiPath` 统一 runtime path 编码,以 `requestRuntimeJson` 统一 JSON 请求、runtime guest auth 和 retry 合并。Match3D 与 SquareHole runtime client 已先迁移,保留原导出函数名、错误文案、返回契约和重试常量。
|
- 决策:新增 `src/services/runtimeRequest.ts`,以 `buildRuntimeApiPath` 统一 runtime path 编码,以 `requestRuntimeJson` 统一 JSON 请求、runtime guest auth 和 retry 合并。Match3D 与 SquareHole runtime client 已先迁移,保留原导出函数名、错误文案、返回契约和重试常量。
|
||||||
- 影响范围:`src/services/runtimeRequest.ts`、Match3D runtime client、SquareHole runtime client、后续 Puzzle / Jump Hop / Visual Novel / Bark Battle / Big Fish runtime client 迁移。
|
- 追加决策:Big Fish 与 Bark Battle runtime client 也迁入 `runtimeRequest.ts`;玩法专属 payload 归一化(如 Bark Battle start / finish 自动补 `workId`、`runId`)仍留在各玩法 client,通用 Module 只承接请求骨架。
|
||||||
|
- 影响范围:`src/services/runtimeRequest.ts`、Match3D / SquareHole / Big Fish / Bark Battle runtime client、后续 Puzzle / Jump Hop / Visual Novel runtime client 迁移。
|
||||||
- 验证方式:`npm run test -- src/services/runtimeRequest.test.ts src/services/recommendedRuntimeGuestLaunch.test.ts src/services/match3d-runtime/match3dRuntimeAdapter.test.ts`、`npm run typecheck`、`npm run check:encoding`、相关文件 ESLint 通过。
|
- 验证方式:`npm run test -- src/services/runtimeRequest.test.ts src/services/recommendedRuntimeGuestLaunch.test.ts src/services/match3d-runtime/match3dRuntimeAdapter.test.ts`、`npm run typecheck`、`npm run check:encoding`、相关文件 ESLint 通过。
|
||||||
- 关联文档:`docs/technical/【前端架构】RuntimeClientFamily收口计划-2026-06-03.md`。
|
- 关联文档:`docs/technical/【前端架构】RuntimeClientFamily收口计划-2026-06-03.md`。
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ AI 文字游戏模板接入以 [AI_NATIVE_TEXT_GAME_TEMPLATE_MOKU_REFERENCE_PRD_
|
|||||||
|
|
||||||
创作中心作品架打开动作由 `CreationWorkShelfItem.actions.open` 统一承载,Hub 不再按玩法 `kind` 分发,规则见 [【前端架构】WorkShelfModule收口计划-2026-06-03.md](./technical/%E3%80%90%E5%89%8D%E7%AB%AF%E6%9E%B6%E6%9E%84%E3%80%91WorkShelfModule%E6%94%B6%E5%8F%A3%E8%AE%A1%E5%88%92-2026-06-03.md)。
|
创作中心作品架打开动作由 `CreationWorkShelfItem.actions.open` 统一承载,Hub 不再按玩法 `kind` 分发,规则见 [【前端架构】WorkShelfModule收口计划-2026-06-03.md](./technical/%E3%80%90%E5%89%8D%E7%AB%AF%E6%9E%B6%E6%9E%84%E3%80%91WorkShelfModule%E6%94%B6%E5%8F%A3%E8%AE%A1%E5%88%92-2026-06-03.md)。
|
||||||
|
|
||||||
小游戏 runtime client 的路径编码、JSON 请求、runtime guest auth 与 retry 选项收口到 `src/services/runtimeRequest.ts`,Match3D 与 SquareHole 已先迁移,规则见 [【前端架构】RuntimeClientFamily收口计划-2026-06-03.md](./technical/%E3%80%90%E5%89%8D%E7%AB%AF%E6%9E%B6%E6%9E%84%E3%80%91RuntimeClientFamily%E6%94%B6%E5%8F%A3%E8%AE%A1%E5%88%92-2026-06-03.md)。
|
小游戏 runtime client 的路径编码、JSON 请求、runtime guest auth 与 retry 选项收口到 `src/services/runtimeRequest.ts`,Match3D、SquareHole、Big Fish 与 Bark Battle 已先迁移,规则见 [【前端架构】RuntimeClientFamily收口计划-2026-06-03.md](./technical/%E3%80%90%E5%89%8D%E7%AB%AF%E6%9E%B6%E6%9E%84%E3%80%91RuntimeClientFamily%E6%94%B6%E5%8F%A3%E8%AE%A1%E5%88%92-2026-06-03.md)。
|
||||||
|
|
||||||
公开作品分类、搜索、跨来源去重、今日筛选、排行排序和时间戳解析收口到 `src/components/rpg-entry/rpgEntryPublicGalleryViewModel.ts`,规则见 [【前端架构】PublicGalleryViewModel收口计划-2026-06-03.md](./technical/%E3%80%90%E5%89%8D%E7%AB%AF%E6%9E%B6%E6%9E%84%E3%80%91PublicGalleryViewModel%E6%94%B6%E5%8F%A3%E8%AE%A1%E5%88%92-2026-06-03.md)。
|
公开作品分类、搜索、跨来源去重、今日筛选、排行排序和时间戳解析收口到 `src/components/rpg-entry/rpgEntryPublicGalleryViewModel.ts`,规则见 [【前端架构】PublicGalleryViewModel收口计划-2026-06-03.md](./technical/%E3%80%90%E5%89%8D%E7%AB%AF%E6%9E%B6%E6%9E%84%E3%80%91PublicGalleryViewModel%E6%94%B6%E5%8F%A3%E8%AE%A1%E5%88%92-2026-06-03.md)。
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
- `buildRuntimeApiPath(basePath, ...segments)`:统一对 runtime path segment 执行 `encodeURIComponent`。
|
- `buildRuntimeApiPath(basePath, ...segments)`:统一对 runtime path segment 执行 `encodeURIComponent`。
|
||||||
- `requestRuntimeJson(params)`:统一设置 method、JSON body、`Content-Type`、runtime guest `Authorization`、auth options 和 retry options。
|
- `requestRuntimeJson(params)`:统一设置 method、JSON body、`Content-Type`、runtime guest `Authorization`、auth options 和 retry options。
|
||||||
|
|
||||||
`match3dRuntimeClient.ts` 与 `squareHoleRuntimeClient.ts` 已迁入此 **Module**,并保留原有导出函数名、错误文案、返回契约和重试常量。点击 / 投入等玩法专属返回映射仍留在各自 client 内,避免把领域规则塞进通用请求 **Implementation**。
|
`match3dRuntimeClient.ts`、`squareHoleRuntimeClient.ts`、`bigFishRuntimeClient.ts` 与 `barkBattleRuntimeClient.ts` 已迁入此 **Module**,并保留原有导出函数名、错误文案、返回契约和重试常量。点击 / 投入 / 成绩提交等玩法专属 payload 归一化仍留在各自 client 内,避免把领域规则塞进通用请求 **Implementation**。
|
||||||
|
|
||||||
## 约定
|
## 约定
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
## 后续深化
|
## 后续深化
|
||||||
|
|
||||||
下一批可迁移 Puzzle、Jump Hop、Visual Novel、Bark Battle 与 Big Fish runtime client。迁移顺序以测试覆盖和请求形状接近度为准,优先迁移已有 guest launch 或 client 单测覆盖的函数。
|
下一批可迁移 Puzzle、Jump Hop 与 Visual Novel runtime client。迁移顺序以测试覆盖和请求形状接近度为准,优先迁移已有 guest launch 或 client 单测覆盖的函数。
|
||||||
|
|
||||||
## 验证
|
## 验证
|
||||||
|
|
||||||
|
|||||||
@@ -5,15 +5,11 @@ import type {
|
|||||||
BarkBattleRunStartResponse,
|
BarkBattleRunStartResponse,
|
||||||
BarkBattleRuntimeConfig,
|
BarkBattleRuntimeConfig,
|
||||||
} from '../../../packages/shared/src/contracts/barkBattle';
|
} from '../../../packages/shared/src/contracts/barkBattle';
|
||||||
import {
|
import { type ApiRetryOptions } from '../apiClient';
|
||||||
type ApiRetryOptions,
|
import { type RuntimeGuestRequestOptions } from '../runtimeGuestAuth';
|
||||||
requestJson,
|
import { buildRuntimeApiPath, requestRuntimeJson } from '../runtimeRequest';
|
||||||
} from '../apiClient';
|
|
||||||
import {
|
const BARK_BATTLE_RUNTIME_API_BASE = '/api/runtime/bark-battle';
|
||||||
buildRuntimeGuestAuthOptions,
|
|
||||||
buildRuntimeGuestHeaders,
|
|
||||||
type RuntimeGuestRequestOptions,
|
|
||||||
} from '../runtimeGuestAuth';
|
|
||||||
|
|
||||||
const BARK_BATTLE_RUNTIME_READ_RETRY: ApiRetryOptions = {
|
const BARK_BATTLE_RUNTIME_READ_RETRY: ApiRetryOptions = {
|
||||||
maxRetries: 1,
|
maxRetries: 1,
|
||||||
@@ -34,16 +30,17 @@ export function getBarkBattleRuntimeConfig(
|
|||||||
workId: string,
|
workId: string,
|
||||||
options: BarkBattleRuntimeRequestOptions = {},
|
options: BarkBattleRuntimeRequestOptions = {},
|
||||||
) {
|
) {
|
||||||
const requestOptions = buildRuntimeGuestAuthOptions(options);
|
return requestRuntimeJson<BarkBattleRuntimeConfig>({
|
||||||
return requestJson<BarkBattleRuntimeConfig>(
|
url: buildRuntimeApiPath(
|
||||||
`/api/runtime/bark-battle/works/${encodeURIComponent(workId)}/config`,
|
BARK_BATTLE_RUNTIME_API_BASE,
|
||||||
{ method: 'GET', headers: buildRuntimeGuestHeaders(options) },
|
'works',
|
||||||
'读取汪汪声浪大作战配置失败',
|
workId,
|
||||||
{
|
'config',
|
||||||
|
),
|
||||||
|
fallbackMessage: '读取汪汪声浪大作战配置失败',
|
||||||
retry: BARK_BATTLE_RUNTIME_READ_RETRY,
|
retry: BARK_BATTLE_RUNTIME_READ_RETRY,
|
||||||
...requestOptions,
|
requestOptions: options,
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function startBarkBattleRun(
|
export function startBarkBattleRun(
|
||||||
@@ -51,39 +48,34 @@ export function startBarkBattleRun(
|
|||||||
payload: Partial<BarkBattleRunStartRequest> = {},
|
payload: Partial<BarkBattleRunStartRequest> = {},
|
||||||
options: BarkBattleRuntimeRequestOptions = {},
|
options: BarkBattleRuntimeRequestOptions = {},
|
||||||
) {
|
) {
|
||||||
const requestOptions = buildRuntimeGuestAuthOptions(options);
|
return requestRuntimeJson<BarkBattleRunStartResponse>({
|
||||||
return requestJson<BarkBattleRunStartResponse>(
|
url: buildRuntimeApiPath(
|
||||||
`/api/runtime/bark-battle/works/${encodeURIComponent(workId)}/runs`,
|
BARK_BATTLE_RUNTIME_API_BASE,
|
||||||
{
|
'works',
|
||||||
|
workId,
|
||||||
|
'runs',
|
||||||
|
),
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: buildRuntimeGuestHeaders(options, { 'Content-Type': 'application/json' }),
|
jsonBody: {
|
||||||
body: JSON.stringify({
|
|
||||||
...payload,
|
...payload,
|
||||||
workId: payload.workId ?? workId,
|
workId: payload.workId ?? workId,
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
'启动汪汪声浪大作战正式局失败',
|
fallbackMessage: '启动汪汪声浪大作战正式局失败',
|
||||||
{
|
|
||||||
retry: BARK_BATTLE_RUNTIME_WRITE_RETRY,
|
retry: BARK_BATTLE_RUNTIME_WRITE_RETRY,
|
||||||
...requestOptions,
|
requestOptions: options,
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBarkBattleRun(
|
export function getBarkBattleRun(
|
||||||
runId: string,
|
runId: string,
|
||||||
options: BarkBattleRuntimeRequestOptions = {},
|
options: BarkBattleRuntimeRequestOptions = {},
|
||||||
) {
|
) {
|
||||||
const requestOptions = buildRuntimeGuestAuthOptions(options);
|
return requestRuntimeJson<unknown>({
|
||||||
return requestJson<unknown>(
|
url: buildRuntimeApiPath(BARK_BATTLE_RUNTIME_API_BASE, 'runs', runId),
|
||||||
`/api/runtime/bark-battle/runs/${encodeURIComponent(runId)}`,
|
fallbackMessage: '读取汪汪声浪大作战单局失败',
|
||||||
{ method: 'GET', headers: buildRuntimeGuestHeaders(options) },
|
|
||||||
'读取汪汪声浪大作战单局失败',
|
|
||||||
{
|
|
||||||
retry: BARK_BATTLE_RUNTIME_READ_RETRY,
|
retry: BARK_BATTLE_RUNTIME_READ_RETRY,
|
||||||
...requestOptions,
|
requestOptions: options,
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function finishBarkBattleRun(
|
export function finishBarkBattleRun(
|
||||||
@@ -91,21 +83,20 @@ export function finishBarkBattleRun(
|
|||||||
payload: BarkBattleRunFinishRequest,
|
payload: BarkBattleRunFinishRequest,
|
||||||
options: BarkBattleRuntimeRequestOptions = {},
|
options: BarkBattleRuntimeRequestOptions = {},
|
||||||
) {
|
) {
|
||||||
const requestOptions = buildRuntimeGuestAuthOptions(options);
|
return requestRuntimeJson<BarkBattleFinishResponse>({
|
||||||
return requestJson<BarkBattleFinishResponse>(
|
url: buildRuntimeApiPath(
|
||||||
`/api/runtime/bark-battle/runs/${encodeURIComponent(runId)}/finish`,
|
BARK_BATTLE_RUNTIME_API_BASE,
|
||||||
{
|
'runs',
|
||||||
|
runId,
|
||||||
|
'finish',
|
||||||
|
),
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: buildRuntimeGuestHeaders(options, { 'Content-Type': 'application/json' }),
|
jsonBody: {
|
||||||
body: JSON.stringify({
|
|
||||||
...payload,
|
...payload,
|
||||||
runId: payload.runId ?? runId,
|
runId: payload.runId ?? runId,
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
'提交汪汪声浪大作战成绩失败',
|
fallbackMessage: '提交汪汪声浪大作战成绩失败',
|
||||||
{
|
|
||||||
retry: BARK_BATTLE_RUNTIME_WRITE_RETRY,
|
retry: BARK_BATTLE_RUNTIME_WRITE_RETRY,
|
||||||
...requestOptions,
|
requestOptions: options,
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,16 +4,11 @@ import type {
|
|||||||
SubmitBigFishInputRequest,
|
SubmitBigFishInputRequest,
|
||||||
} from '../../../packages/shared/src/contracts/bigFish';
|
} from '../../../packages/shared/src/contracts/bigFish';
|
||||||
import type { BigFishWorksResponse } from '../../../packages/shared/src/contracts/bigFishWorkSummary';
|
import type { BigFishWorksResponse } from '../../../packages/shared/src/contracts/bigFishWorkSummary';
|
||||||
import {
|
import { type ApiRetryOptions } from '../apiClient';
|
||||||
type ApiRetryOptions,
|
import { type RuntimeGuestRequestOptions } from '../runtimeGuestAuth';
|
||||||
requestJson,
|
import { buildRuntimeApiPath, requestRuntimeJson } from '../runtimeRequest';
|
||||||
} from '../apiClient';
|
|
||||||
import {
|
|
||||||
buildRuntimeGuestAuthOptions,
|
|
||||||
buildRuntimeGuestHeaders,
|
|
||||||
type RuntimeGuestRequestOptions,
|
|
||||||
} from '../runtimeGuestAuth';
|
|
||||||
|
|
||||||
|
const BIG_FISH_RUNTIME_API_BASE = '/api/runtime/big-fish';
|
||||||
const BIG_FISH_RUNTIME_WRITE_RETRY: ApiRetryOptions = {
|
const BIG_FISH_RUNTIME_WRITE_RETRY: ApiRetryOptions = {
|
||||||
maxRetries: 1,
|
maxRetries: 1,
|
||||||
baseDelayMs: 120,
|
baseDelayMs: 120,
|
||||||
@@ -30,51 +25,44 @@ export function recordBigFishPlay(
|
|||||||
payload: RecordBigFishPlayRequest,
|
payload: RecordBigFishPlayRequest,
|
||||||
options: BigFishRuntimeRequestOptions = {},
|
options: BigFishRuntimeRequestOptions = {},
|
||||||
) {
|
) {
|
||||||
const requestOptions = buildRuntimeGuestAuthOptions(options);
|
return requestRuntimeJson<BigFishWorksResponse>({
|
||||||
return requestJson<BigFishWorksResponse>(
|
url: buildRuntimeApiPath(
|
||||||
`/api/runtime/big-fish/sessions/${encodeURIComponent(sessionId)}/play`,
|
BIG_FISH_RUNTIME_API_BASE,
|
||||||
{
|
'sessions',
|
||||||
|
sessionId,
|
||||||
|
'play',
|
||||||
|
),
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: buildRuntimeGuestHeaders(options, {
|
jsonBody: payload,
|
||||||
'Content-Type': 'application/json',
|
fallbackMessage: '记录大鱼吃小鱼游玩失败',
|
||||||
}),
|
|
||||||
body: JSON.stringify(payload),
|
|
||||||
},
|
|
||||||
'记录大鱼吃小鱼游玩失败',
|
|
||||||
{
|
|
||||||
retry: BIG_FISH_RUNTIME_WRITE_RETRY,
|
retry: BIG_FISH_RUNTIME_WRITE_RETRY,
|
||||||
...requestOptions,
|
requestOptions: options,
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function startBigFishRun(
|
export function startBigFishRun(
|
||||||
sessionId: string,
|
sessionId: string,
|
||||||
options: BigFishRuntimeRequestOptions = {},
|
options: BigFishRuntimeRequestOptions = {},
|
||||||
) {
|
) {
|
||||||
const requestOptions = buildRuntimeGuestAuthOptions(options);
|
return requestRuntimeJson<BigFishRunResponse>({
|
||||||
return requestJson<BigFishRunResponse>(
|
url: buildRuntimeApiPath(
|
||||||
`/api/runtime/big-fish/sessions/${encodeURIComponent(sessionId)}/runs`,
|
BIG_FISH_RUNTIME_API_BASE,
|
||||||
{
|
'sessions',
|
||||||
|
sessionId,
|
||||||
|
'runs',
|
||||||
|
),
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: buildRuntimeGuestHeaders(options),
|
fallbackMessage: '启动大鱼吃小鱼玩法失败',
|
||||||
},
|
|
||||||
'启动大鱼吃小鱼玩法失败',
|
|
||||||
{
|
|
||||||
retry: BIG_FISH_RUNTIME_WRITE_RETRY,
|
retry: BIG_FISH_RUNTIME_WRITE_RETRY,
|
||||||
...requestOptions,
|
requestOptions: options,
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getBigFishRun(runId: string) {
|
export function getBigFishRun(runId: string) {
|
||||||
return requestJson<BigFishRunResponse>(
|
return requestRuntimeJson<BigFishRunResponse>({
|
||||||
`/api/runtime/big-fish/runs/${encodeURIComponent(runId)}`,
|
url: buildRuntimeApiPath(BIG_FISH_RUNTIME_API_BASE, 'runs', runId),
|
||||||
{
|
fallbackMessage: '读取大鱼吃小鱼玩法失败',
|
||||||
method: 'GET',
|
});
|
||||||
},
|
|
||||||
'读取大鱼吃小鱼玩法失败',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function submitBigFishInput(
|
export function submitBigFishInput(
|
||||||
@@ -82,20 +70,12 @@ export function submitBigFishInput(
|
|||||||
payload: SubmitBigFishInputRequest,
|
payload: SubmitBigFishInputRequest,
|
||||||
options: BigFishRuntimeRequestOptions = {},
|
options: BigFishRuntimeRequestOptions = {},
|
||||||
) {
|
) {
|
||||||
const requestOptions = buildRuntimeGuestAuthOptions(options);
|
return requestRuntimeJson<BigFishRunResponse>({
|
||||||
return requestJson<BigFishRunResponse>(
|
url: buildRuntimeApiPath(BIG_FISH_RUNTIME_API_BASE, 'runs', runId, 'input'),
|
||||||
`/api/runtime/big-fish/runs/${encodeURIComponent(runId)}/input`,
|
|
||||||
{
|
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: buildRuntimeGuestHeaders(options, {
|
jsonBody: payload,
|
||||||
'Content-Type': 'application/json',
|
fallbackMessage: '同步大鱼吃小鱼输入失败',
|
||||||
}),
|
|
||||||
body: JSON.stringify(payload),
|
|
||||||
},
|
|
||||||
'同步大鱼吃小鱼输入失败',
|
|
||||||
{
|
|
||||||
retry: BIG_FISH_RUNTIME_WRITE_RETRY,
|
retry: BIG_FISH_RUNTIME_WRITE_RETRY,
|
||||||
...requestOptions,
|
requestOptions: options,
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ vi.mock('./apiClient', async () => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
import { startBigFishRun } from './big-fish-runtime/bigFishRuntimeClient';
|
|
||||||
import { startBarkBattleRun } from './bark-battle-runtime/barkBattleRuntimeClient';
|
import { startBarkBattleRun } from './bark-battle-runtime/barkBattleRuntimeClient';
|
||||||
|
import { startBigFishRun } from './big-fish-runtime/bigFishRuntimeClient';
|
||||||
import { startJumpHopRuntimeRun } from './jump-hop/jumpHopClient';
|
import { startJumpHopRuntimeRun } from './jump-hop/jumpHopClient';
|
||||||
import { startMatch3DRun } from './match3d-runtime/match3dRuntimeClient';
|
import { startMatch3DRun } from './match3d-runtime/match3dRuntimeClient';
|
||||||
import {
|
import {
|
||||||
|
|||||||
Reference in New Issue
Block a user