接入 AGC shell TS 资源 kind 边界
新增消费 Rust 生成绑定的未知值解析模块 迁移资源引用与画布引用入口并补充日志测试 更新逐项迁移清单与实施计划
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
import type { GameCreationAppAssetKind } from './generated/GameCreationAppAssetKind';
|
||||
|
||||
export type { GameCreationAppAssetKind } from './generated/GameCreationAppAssetKind';
|
||||
|
||||
export const GAME_CREATION_APP_ASSET_KINDS = [
|
||||
'image',
|
||||
'scene',
|
||||
'character',
|
||||
'character-animation',
|
||||
'icon',
|
||||
'icon-spritesheet',
|
||||
'icon-spec',
|
||||
'ui-design',
|
||||
'ui-design-doc',
|
||||
'publication-material',
|
||||
'spec',
|
||||
'video',
|
||||
'audio',
|
||||
'sound-effect',
|
||||
'background-music',
|
||||
'font',
|
||||
'document',
|
||||
'code',
|
||||
'unknown',
|
||||
] as const satisfies readonly GameCreationAppAssetKind[];
|
||||
|
||||
const KNOWN_ASSET_KINDS = new Set<string>(GAME_CREATION_APP_ASSET_KINDS);
|
||||
|
||||
export function parseGameCreationAppAssetKind(
|
||||
raw: unknown,
|
||||
context: string,
|
||||
): GameCreationAppAssetKind {
|
||||
if (typeof raw === 'string' && KNOWN_ASSET_KINDS.has(raw)) {
|
||||
return raw as GameCreationAppAssetKind;
|
||||
}
|
||||
|
||||
const rawValue = typeof raw === 'string' ? raw : String(raw);
|
||||
if (rawValue !== 'unknown') {
|
||||
console.warn('未知的 GameCreationApp 资源 kind,已收口为 unknown', {
|
||||
rawKind: rawValue,
|
||||
sourceContext: context,
|
||||
});
|
||||
}
|
||||
return 'unknown';
|
||||
}
|
||||
@@ -10,6 +10,10 @@ import {
|
||||
buildGameCreationAppAssetTagLibrary,
|
||||
type GameCreationAppAssetTagLibraryEntry,
|
||||
} from '../../../../../packages/shared/src/contracts/gameCreationAppAssetTagLibrary';
|
||||
import {
|
||||
type GameCreationAppAssetKind,
|
||||
parseGameCreationAppAssetKind,
|
||||
} from '../../contracts/assetKind';
|
||||
|
||||
export type ResourceReferenceSource =
|
||||
| 'asset-picker'
|
||||
@@ -20,7 +24,7 @@ export type ResourceReferenceSource =
|
||||
export type ResourceReference = {
|
||||
type: 'resource';
|
||||
resourceId: string;
|
||||
kind: string;
|
||||
kind: GameCreationAppAssetKind;
|
||||
mediaType: string;
|
||||
label: string;
|
||||
category: GameCreationAppAssetCategory;
|
||||
@@ -98,7 +102,7 @@ export function resourceReferenceFromAsset(
|
||||
return {
|
||||
type: 'resource',
|
||||
resourceId: asset.id,
|
||||
kind: asset.kind,
|
||||
kind: parseGameCreationAppAssetKind(asset.kind, 'resource-reference'),
|
||||
mediaType: asset.mediaType,
|
||||
label: resourceDisplayName(asset),
|
||||
category: gameCreationAppAssetCategory(asset),
|
||||
|
||||
@@ -96,6 +96,7 @@ import {
|
||||
isFloatingOverlayWheelEvent,
|
||||
useImageCanvasFloatingOptionDismiss,
|
||||
} from '../../../../../src/components/image-editor/useImageCanvasFloatingOptionDismiss';
|
||||
import { parseGameCreationAppAssetKind } from '../../contracts/assetKind';
|
||||
import { DesignWorkspacePanel } from '../../features/project-workspace/DesignWorkspacePanel';
|
||||
import {
|
||||
LocalGamePreviewFrame,
|
||||
@@ -7226,9 +7227,11 @@ export default function ProjectDevelopmentView({
|
||||
type: 'resource',
|
||||
resourceId:
|
||||
selectedResource.manifestAssetId!,
|
||||
kind:
|
||||
kind: parseGameCreationAppAssetKind(
|
||||
selectedResource.subtype ||
|
||||
selectedResource.category,
|
||||
selectedResource.category,
|
||||
'project-development.resource-reference',
|
||||
),
|
||||
mediaType: selectedResource.mediaType,
|
||||
label: selectedResource.label,
|
||||
category:
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import {
|
||||
GAME_CREATION_APP_ASSET_KINDS,
|
||||
parseGameCreationAppAssetKind,
|
||||
} from '../src/contracts/assetKind';
|
||||
|
||||
describe('shell generated asset kind boundary', () => {
|
||||
it('keeps the generated kind values aligned with the manifest vocabulary', () => {
|
||||
expect(GAME_CREATION_APP_ASSET_KINDS).toContain('font');
|
||||
expect(GAME_CREATION_APP_ASSET_KINDS).toContain('audio');
|
||||
expect(GAME_CREATION_APP_ASSET_KINDS).toContain('sound-effect');
|
||||
expect(GAME_CREATION_APP_ASSET_KINDS).toContain('background-music');
|
||||
expect(GAME_CREATION_APP_ASSET_KINDS).toContain('unknown');
|
||||
});
|
||||
|
||||
it('does not alias old values and records unknown input', () => {
|
||||
const warn = vi.spyOn(console, 'warn').mockImplementation(() => undefined);
|
||||
expect(parseGameCreationAppAssetKind('ui', 'manifest.asset.kind')).toBe(
|
||||
'unknown',
|
||||
);
|
||||
expect(warn).toHaveBeenCalledWith(
|
||||
'未知的 GameCreationApp 资源 kind,已收口为 unknown',
|
||||
{ rawKind: 'ui', sourceContext: 'manifest.asset.kind' },
|
||||
);
|
||||
warn.mockRestore();
|
||||
});
|
||||
});
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
- `GameCreationAppAssetManifestEntry.kind` 改为 `GameCreationAppAssetKind`;manifest 反序列化未知值收口为 `Unknown`。
|
||||
- 上传内容推断的字体写入 `Font`,未知上传类型写入 `Unknown`;图集切片 manifest 写入 `Icon`。
|
||||
- shell TS 资源引用边界开始消费生成绑定,并为未知值保留原始值与上下文日志。
|
||||
|
||||
明确不修改:
|
||||
|
||||
|
||||
@@ -210,3 +210,11 @@
|
||||
- `resourceCanvasBottomToolbarModel.ts:243` 的 `art-spritesheet` 和 `:258` 的 `ui-prototype` 当前位于生成入口选项,需先确认该字段是否传入 manifest 登记;若只是 API/生成请求 kind,使用显式转换函数,不把旧值加入 manifest enum。
|
||||
- `resourceProjectionModel.ts:326`、`uiDesignResourceBridge.ts:87` 是直接比较 manifest asset kind 的消费点,必须跟随生成绑定迁移到 enum。
|
||||
- `SupervisorChatOnlyView.tsx`、`ProjectSupervisorView.tsx` 等仍直接从 `packages/shared` 导入 manifest 类型,需在删除旧文件前完成 shell 内导入收口。
|
||||
|
||||
## 已迁移的 TS 边界(增量)
|
||||
|
||||
- `src/contracts/assetKind.ts`:消费 Rust 生成的 `GameCreationAppAssetKind`,未知输入记录 `rawKind` / `sourceContext` 并返回 `unknown`,不做旧 alias 转换。
|
||||
- `src/features/project-workspace/resourceReferences.ts`:资源引用 kind 改为生成枚举类型并通过 parser 收口。
|
||||
- `src/view/project-development/index.tsx`:画布引用入口通过同一 parser 构造资源引用 kind。
|
||||
|
||||
其余 `packages/shared` import 和前端 manifest `kind: string` 字段仍未迁移,继续作为后续小切片,不在本次提交中伪装完成。
|
||||
|
||||
Reference in New Issue
Block a user