From 2f97150a6f348425c3984b27fe872b1454fdca30 Mon Sep 17 00:00:00 2001 From: Joywayer Date: Sun, 28 Jun 2026 16:30:49 +0800 Subject: [PATCH] =?UTF-8?q?feat(framework):=20config=20=E8=BA=AB=E4=BB=BD?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=20+=20=E7=BA=AF=E5=90=88=E5=B9=B6=20resolveI?= =?UTF-8?q?dentity=20+=20=E6=9E=84=E5=BB=BA=E6=9C=9F=E9=BB=98=E8=AE=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) --- .../assets/framework/config/identity.ts | 32 +++++++++++++++ .../framework/config/sources/defaults.ts | 14 +++++++ .../framework-tests/config/identity.test.ts | 39 +++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 cocoscreator_projects/YouleNexus/assets/framework/config/identity.ts create mode 100644 cocoscreator_projects/YouleNexus/assets/framework/config/sources/defaults.ts create mode 100644 cocoscreator_projects/framework-tests/config/identity.test.ts diff --git a/cocoscreator_projects/YouleNexus/assets/framework/config/identity.ts b/cocoscreator_projects/YouleNexus/assets/framework/config/identity.ts new file mode 100644 index 0000000..e7431ea --- /dev/null +++ b/cocoscreator_projects/YouleNexus/assets/framework/config/identity.ts @@ -0,0 +1,32 @@ +/** 渠道身份(属性名沿用协议字段,序列化进 player_login,逐字不变)。 */ +export interface ChannelIdentity { + agentid: string | number; + channelid: string | number; + gameid: string; + marketid: string | number; + version: string; // 旧 GameData.Version + versionCode: number; // 旧 GameData.versionCode +} + +/** 身份来源:返回部分字段覆盖。 */ +export type IdentitySource = () => Partial; + +function hasValue(v: unknown): boolean { + return v !== undefined && v !== null && v !== ''; +} + +/** + * 按数组顺序合并身份,后者覆盖前者(仅覆盖有效值字段)。 + * 约定首个 source 为完整 defaults,故返回视为完整 ChannelIdentity。 + */ +export function resolveIdentity(sources: IdentitySource[]): ChannelIdentity { + const out: Partial = {}; + for (const src of sources) { + const part = src(); + for (const k of Object.keys(part) as (keyof ChannelIdentity)[]) { + const v = part[k]; + if (hasValue(v)) (out as Record)[k] = v; + } + } + return out as ChannelIdentity; +} diff --git a/cocoscreator_projects/YouleNexus/assets/framework/config/sources/defaults.ts b/cocoscreator_projects/YouleNexus/assets/framework/config/sources/defaults.ts new file mode 100644 index 0000000..10afb1b --- /dev/null +++ b/cocoscreator_projects/YouleNexus/assets/framework/config/sources/defaults.ts @@ -0,0 +1,14 @@ +import type { ChannelIdentity } from '../identity.ts'; + +/** + * 构建期默认渠道身份(旧 version.js 等价物)。 + * gameid 每子游戏固定写死;agentid/channelid/marketid/version 为默认,运行期由 query/native/profile 覆盖。 + */ +export const BUILD_IDENTITY: ChannelIdentity = { + agentid: '00bA05haB0d9ZC0fwGD09Q2OA30insbQ', + channelid: 'frdt0C1GG0t91P0McFo0rbA1he5yurbS', + gameid: '8x4l0rGjf026f60c48h0mbUAhK5vV16f', + marketid: 4, + version: '1.1', + versionCode: 10000, +}; diff --git a/cocoscreator_projects/framework-tests/config/identity.test.ts b/cocoscreator_projects/framework-tests/config/identity.test.ts new file mode 100644 index 0000000..d165b57 --- /dev/null +++ b/cocoscreator_projects/framework-tests/config/identity.test.ts @@ -0,0 +1,39 @@ +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { resolveIdentity } from '../../YouleNexus/assets/framework/config/identity.ts'; +import { BUILD_IDENTITY } from '../../YouleNexus/assets/framework/config/sources/defaults.ts'; + +test('BUILD_IDENTITY 含全部字段且 gameid 为固定 token', () => { + assert.ok(BUILD_IDENTITY.gameid.length > 0); + assert.ok('agentid' in BUILD_IDENTITY); + assert.ok('channelid' in BUILD_IDENTITY); + assert.ok('marketid' in BUILD_IDENTITY); + assert.equal(typeof BUILD_IDENTITY.version, 'string'); + assert.equal(typeof BUILD_IDENTITY.versionCode, 'number'); +}); + +test('resolveIdentity:后面的 source 覆盖前面的', () => { + const id = resolveIdentity([ + () => BUILD_IDENTITY, + () => ({ agentid: 'A2' }), + () => ({ agentid: 'A3', channelid: 'C3' }), + ]); + assert.equal(id.agentid, 'A3'); + assert.equal(id.channelid, 'C3'); + assert.equal(id.gameid, BUILD_IDENTITY.gameid); // 未被覆盖 +}); + +test('resolveIdentity:undefined / null / 空串 不覆盖', () => { + const id = resolveIdentity([ + () => BUILD_IDENTITY, + () => ({ agentid: undefined as any, channelid: '' , marketid: null as any }), + ]); + assert.equal(id.agentid, BUILD_IDENTITY.agentid); + assert.equal(id.channelid, BUILD_IDENTITY.channelid); + assert.equal(id.marketid, BUILD_IDENTITY.marketid); +}); + +test('resolveIdentity:marketid=0 是有效值,应覆盖', () => { + const id = resolveIdentity([() => BUILD_IDENTITY, () => ({ marketid: 0 })]); + assert.equal(id.marketid, 0); +});