/** * What a client is shown for a shot. * * `Shot.clientCode` is the naming alias some productions supply โ€” their own * code for the same shot. It already drives slates, overlay burn-ins and * delivered file names (RenderPipeline2 ยง11.2); internal paths, comp names and * every DB lookup stay on `shotCode`. * * The client portal is the other place the client's own naming belongs, and * that includes task titles: they follow the house convention * `UNG_102_019_010_cmp_TT_v004`, so the internal code is embedded in the * string the client reads and copies. * * Apply these at the API boundary rather than at each render site, so nothing * downstream has to remember which code it is holding. */ export interface ShotCodeFields { shotCode: string; clientCode?: string | null; } /** The shot's code as the client knows it; their alias if set, ours otherwise. */ export function clientShotCode(shot: ShotCodeFields): string { return shot.clientCode?.trim() || shot.shotCode; } /** * A task title with the internal shot code swapped for the client's alias. * * Titles are built from the shot code by convention, so this is a substring * swap rather than a rename โ€” a title that does not contain the code (a * hand-edited one, say) is returned untouched rather than guessed at. */ export function clientTaskTitle(title: string, shot: ShotCodeFields): string { const alias = shot.clientCode?.trim(); if (!alias || !title || alias === shot.shotCode) return title; // split/join rather than a regex: shot codes are user-supplied and would // otherwise need escaping. return title.split(shot.shotCode).join(alias); } /** * The High Res (ProRes) download name for a client. With an alias it follows * the slate's client naming, `{clientCode}_{version}` โ€” no internal code and * no "_cmp_TT_" studio suffix; without one the file keeps its own name. */ export function clientHighResFilename(fileName: string, shot: ShotCodeFields | null): string { const alias = shot?.clientCode?.trim(); if (!shot || !alias || alias === shot.shotCode) return fileName; const m = /_(v\d+)(\.[a-z0-9]+)$/i.exec(fileName); if (m && fileName.startsWith(shot.shotCode)) return `${alias}_${m[1]}${m[2]}`; return fileName.split(shot.shotCode).join(alias); }