Files
UHD_Media_Tool/packages/mapping/src/path-binding.ts
T
rootandClaude Opus 5.5 42ecc93fa5 feat(mapping): centralize domain <-> contracts mappings (B5)
New @umt/mapping (depends on domain + contracts only): download status + pause reason,
evidence level / media kind, identity resolution status, slot status / spec columns /
evaluation, ParsedRelease <-> source_release.parsed, SiteRelease <-> source_release,
PathBinding, OrganizePlan -> organization_record / file results / organize.plan output.
Tables are Record<union, ...> so adding a value on either side fails typecheck or tests.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 19:20:30 +08:00

45 lines
1.8 KiB
TypeScript

import type { PathBinding as ContractPathBinding, PathBindingCreate } from "@umt/contracts";
import type { PathBinding as DomainPathBinding, NewBinding } from "@umt/domain";
// 路径绑定:domain {entityId, scope, season, templateVersion:number, active}
// ↔ contracts / path_binding {mediaEntityId, bindingKind, seasonNumber, templateVersion:string|null, status}
export type { DomainPathBinding };
/** 模板版本:库里是文本(可能是 "3" 或历史导入的任意串),domain 用整数;无法解析按 0(未知)处理 */
export function parseTemplateVersion(v: string | null): number {
return v !== null && /^\d+$/.test(v) ? Number(v) : 0;
}
/** path_binding 行 → domain;只有 status=active 的绑定参与目标目录决策 */
export function toDomainPathBinding(b: ContractPathBinding): DomainPathBinding {
return {
id: b.id,
entityId: b.mediaEntityId,
scope: b.bindingKind,
...(b.seasonNumber !== null ? { season: b.seasonNumber } : {}),
libraryRootId: b.libraryRootId,
relativePath: b.relativePath,
templateVersion: parseTemplateVersion(b.templateVersion),
active: b.status === "active",
};
}
/** domain 决策里的新绑定 → path_binding 新建输入(status=active) */
export function toPathBindingCreate(
nb: NewBinding,
target: { mediaEntityId: string; contentUnitId?: string | null; note?: string | null },
): PathBindingCreate {
return {
mediaEntityId: target.mediaEntityId,
...(target.contentUnitId !== undefined ? { contentUnitId: target.contentUnitId } : {}),
bindingKind: nb.scope,
...(nb.scope === "season" ? { seasonNumber: nb.season ?? null } : {}),
libraryRootId: nb.libraryRootId,
relativePath: nb.relativePath,
templateVersion: String(nb.templateVersion),
status: "active",
...(target.note !== undefined ? { note: target.note } : {}),
};
}