Files
Genarrative/scripts/game-distribution-e2e-helpers.mjs
T
k88936 0f127dbc70 移除游戏分发 E2E helper 中无引用的导出
- 删除 coverImagePart:各 E2E 脚本都有自己的本地实现,仓库内无人导入
- COVER_PNG 只作 imagePart 的默认值,收回 export
2026-10-07 13:55:05 +08:00

83 lines
2.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 游戏分发 E2E 脚本共用的 multipart 发布 helper。
//
// 这些脚本都直连 api-server,发布口是同一套契约:`metadata` JSON 文本 part + 可选 `cover`
// 二进制 part + 按顺序重复的 `screenshot` 二进制 part;各自的 `api()` 也只在 body 形态上分支。
// 这里收敛这段稳定契约,脚本只保留自己的路径、鉴权头与返回形状差异。
/** 1x1 透明 PNG:仅用于满足发布必填的封面/截图 part,内容不参与断言。 */
const COVER_PNG = Buffer.from(
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==',
'base64',
);
/**
* 发布用图片 part。
*
* 默认文件名 `<kind>-<id>.png`、`image/png`;脚本可通过 `options.fileName` 保留自己的前缀,
* 或用 `options.bytes` / `options.contentType` 覆盖字节与类型。
*/
export function imagePart(kind, id, options = {}) {
const {
bytes = COVER_PNG,
fileName = `${kind}-${id}.png`,
contentType = 'image/png',
} = options;
return { bytes, fileName, contentType };
}
/**
* 组装发布请求体:`metadata` 文本 part + 可选 `cover` / 按顺序重复的 `screenshot` 二进制 part。
*
* `metadata.screenshots` 里的 `null` 槽位按出现顺序消费 `screenshots` 数组里的 part;string
* 槽位沿用该 objectKey。调用方负责保证 null 槽位数量与 part 数量一致(不一致服务端会 400)。
*/
export function publishFormData(metadata, { cover, screenshots = [] } = {}) {
const form = new FormData();
form.append('metadata', JSON.stringify(metadata));
if (cover) {
form.append(
'cover',
new Blob([cover.bytes], { type: cover.contentType }),
cover.fileName,
);
}
for (const screenshot of screenshots) {
if (!screenshot) continue;
form.append(
'screenshot',
new Blob([screenshot.bytes], { type: screenshot.contentType }),
screenshot.fileName,
);
}
return form;
}
/**
* 推导 `api()` 的最终请求头与请求体。
*
* - `formData`:multipart/form-data,不手动设 `Content-Type`,交给 fetch 生成 boundary。
* - `binary`:直接作为 body(例如分片 PUT 的字节)。
* - `body !== undefined`:按 JSON 序列化,并补 `Content-Type: application/json`。
*
* 调用方先自行合并 `{ ...ENVELOPE, ...headers }` 与 `Authorization`,再把结果作为 `headers`
* 传进来;返回值里的 `headers` 是补完 `Content-Type` 后的副本。
*/
export function resolveApiRequest({
formData,
binary,
body,
headers = {},
} = {}) {
const finalHeaders = { ...headers };
let finalBody;
if (formData) {
finalBody = formData;
} else if (binary) {
finalBody = binary;
} else if (body !== undefined) {
finalHeaders['Content-Type'] = 'application/json';
finalBody = JSON.stringify(body);
}
return { headers: finalHeaders, body: finalBody };
}