From 6a9a7e5998364ec86bf661e1884cd046ba8ff938 Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Sun, 10 May 2026 14:05:02 -0400 Subject: [PATCH] feat(types): tighten Format.assets typing and emit named slot unions + Zod schemas MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #1652. Codegen post-processor now (a) injects an import for the *AssetRequirements types into tools.generated.ts so the per-slot requirements?: field survives, (b) restores asset_type + requirements on the 12 Group*Asset shapes, and (c) emits named IndividualAssetSlot / GroupAssetSlot / FormatAssetSlot unions. Format.assets[] and RepeatableGroupAsset.assets[] now reference those names. ts-to-zod produces matching IndividualAssetSlotSchema / GroupAssetSlotSchema / FormatAssetSlotSchema and per-type slot schemas carrying the requirements branch. The hand-authored format-asset-slots.ts shim is reduced to thin *Slot aliases over the codegen names; downstream imports keep working. Two no-op group builders (briefGroupAsset, catalogGroupAsset) are removed — the spec excludes brief/catalog from RepeatableGroupAsset.assets[]. Co-Authored-By: Claude Opus 4.7 (1M context) --- .changeset/format-asset-slot-codegen.md | 21 + scripts/generate-types.ts | 116 ++++- src/lib/index.ts | 2 - src/lib/types/core.generated.ts | 127 +++-- src/lib/types/format-asset-slots.ts | 275 +++------- src/lib/types/schemas.generated.ts | 529 +++++++++----------- src/lib/types/tools.generated.ts | 151 ++++-- src/lib/utils/format-asset-slot-builders.ts | 122 ++--- 8 files changed, 693 insertions(+), 650 deletions(-) create mode 100644 .changeset/format-asset-slot-codegen.md diff --git a/.changeset/format-asset-slot-codegen.md b/.changeset/format-asset-slot-codegen.md new file mode 100644 index 000000000..95deb0ee1 --- /dev/null +++ b/.changeset/format-asset-slot-codegen.md @@ -0,0 +1,21 @@ +--- +'@adcp/sdk': minor +--- + +feat(types): tighten `Format.assets` typing and emit named slot unions + Zod schemas + +Closes adcontextprotocol/adcp-client#1652. + +The codegen post-processor that restored the `asset_type` discriminator on `Individual*Asset` slot types (#1498) now also: + +- Imports the `*AssetRequirements` types into `tools.generated.ts` from `core.generated.ts`, so the per-slot `requirements?:` field is preserved on every `IndividualImageAsset` / `IndividualVideoAsset` / … exported from the tools surface (previously missing — a downstream cast pattern). +- Restores the same `asset_type` + `requirements` discriminator on the 12 `Group*Asset` shapes inside `RepeatableGroupAsset.assets[]`. +- Emits named `IndividualAssetSlot`, `GroupAssetSlot`, and `FormatAssetSlot` unions in both `core.generated.ts` and `tools.generated.ts`, and tightens `Format.assets?: FormatAssetSlot[]` and `RepeatableGroupAsset.assets: GroupAssetSlot[]` to reference them. +- ts-to-zod picks up the named unions, so the generated schemas now include `IndividualAssetSlotSchema`, `GroupAssetSlotSchema`, `FormatAssetSlotSchema`, and per-type `IndividualImageAssetSchema { asset_type, requirements }` / `GroupImageAssetSchema { asset_type, requirements }` carrying the requirements branch. + +Consumer impact: + +- `Format.assets[i]` narrows correctly: `slot.asset_type === 'image'` now gives `slot.requirements: ImageAssetRequirements | undefined` for free. The cast pattern from #1652's worked example goes away. +- New runtime-validation entry points: import `IndividualAssetSlotSchema`, `GroupAssetSlotSchema`, or `FormatAssetSlotSchema` from `@adcp/sdk` instead of forking a local `z.union([...])` over the per-type schemas. +- The hand-authored `src/lib/types/format-asset-slots.ts` shim is reduced to thin `*Slot` aliases over the codegen names. Consumers importing `IndividualImageAssetSlot` etc. continue to work; the underlying type is now identical to the spec-derived `IndividualImageAsset`. **Optionality note:** the prior hand-authored shim modeled `requirements` as required on the `*Slot` types; it is now optional (`?:`) to match the spec, where the field appears in `properties` but never in `required`. Adopters that destructured `slot.requirements` and treated the value as defined will need to handle `undefined` or assert. +- Two no-op group builders (`briefGroupAsset`, `catalogGroupAsset`) are removed from `@adcp/sdk`'s public exports. The spec doesn't include `brief` or `catalog` in `RepeatableGroupAsset.assets[].oneOf`, so calling these always produced an object that would fail wire-schema validation. Treated as a bug-fix removal under the minor bump rather than a breaking contract change. The 12 valid `*GroupAsset` builders (and their `FormatAsset.group*` namespace entries) are unchanged. diff --git a/scripts/generate-types.ts b/scripts/generate-types.ts index 0c4246269..544f5dc72 100644 --- a/scripts/generate-types.ts +++ b/scripts/generate-types.ts @@ -1481,24 +1481,126 @@ const INDIVIDUAL_ASSET_DISCRIMINATORS: Array<{ name: string; assetType: string; { name: 'IndividualCatalogAsset', assetType: 'catalog' }, ]; +const GROUP_ASSET_DISCRIMINATORS: Array<{ name: string; assetType: string; requirementsType: string }> = [ + { name: 'GroupImageAsset', assetType: 'image', requirementsType: 'ImageAssetRequirements' }, + { name: 'GroupVideoAsset', assetType: 'video', requirementsType: 'VideoAssetRequirements' }, + { name: 'GroupAudioAsset', assetType: 'audio', requirementsType: 'AudioAssetRequirements' }, + { name: 'GroupTextAsset', assetType: 'text', requirementsType: 'TextAssetRequirements' }, + { name: 'GroupMarkdownAsset', assetType: 'markdown', requirementsType: 'MarkdownAssetRequirements' }, + { name: 'GroupHtmlAsset', assetType: 'html', requirementsType: 'HTMLAssetRequirements' }, + { name: 'GroupCssAsset', assetType: 'css', requirementsType: 'CSSAssetRequirements' }, + { name: 'GroupJavaScriptAsset', assetType: 'javascript', requirementsType: 'JavaScriptAssetRequirements' }, + { name: 'GroupVastAsset', assetType: 'vast', requirementsType: 'VASTAssetRequirements' }, + { name: 'GroupDaastAsset', assetType: 'daast', requirementsType: 'DAASTAssetRequirements' }, + { name: 'GroupUrlAsset', assetType: 'url', requirementsType: 'URLAssetRequirements' }, + { name: 'GroupWebhookAsset', assetType: 'webhook', requirementsType: 'WebhookAssetRequirements' }, +]; + export function applyIndividualAssetDiscriminators(typeDefinitions: string): string { let result = typeDefinitions; let rewritten = 0; + // The *AssetRequirements interfaces are declared in core.generated.ts. When this + // post-processor runs against tools.generated.ts, those interfaces aren't local — + // we inject an import so `requirements?: ImageAssetRequirements` references resolve + // and TS + ts-to-zod (and downstream Format.assets[] consumers) see the full shape. + const requirementsLocallyDeclared = /^export (interface|type) ImageAssetRequirements\b/m.test(result); + const importedRequirementsTypes: string[] = []; + for (const entry of INDIVIDUAL_ASSET_DISCRIMINATORS) { const aliasPattern = new RegExp(`^export type ${entry.name} = BaseIndividualAsset;$`, 'm'); if (!aliasPattern.test(result)) continue; - // Only emit `requirements?:` if the requirements type is declared in this - // same file — the tools.generated.ts artifact reuses BaseIndividualAsset - // but does not redeclare the *AssetRequirements interfaces, so referencing - // them there triggers TS2304. - const reqsAvailable = - entry.requirementsType !== undefined && - new RegExp(`^export interface ${entry.requirementsType}\\b`, 'm').test(result); + const reqsAvailable = entry.requirementsType !== undefined; const reqsField = reqsAvailable ? `\n requirements?: ${entry.requirementsType};` : ''; const replacement = `export type ${entry.name} = BaseIndividualAsset & {\n asset_type: '${entry.assetType}';${reqsField}\n};`; result = result.replace(aliasPattern, replacement); rewritten++; + if (reqsAvailable && !requirementsLocallyDeclared && entry.requirementsType) { + importedRequirementsTypes.push(entry.requirementsType); + } + } + + for (const entry of GROUP_ASSET_DISCRIMINATORS) { + const aliasPattern = new RegExp(`^export type ${entry.name} = BaseGroupAsset;$`, 'm'); + if (!aliasPattern.test(result)) continue; + const replacement = `export type ${entry.name} = BaseGroupAsset & {\n asset_type: '${entry.assetType}';\n requirements?: ${entry.requirementsType};\n};`; + result = result.replace(aliasPattern, replacement); + rewritten++; + if (!requirementsLocallyDeclared) { + importedRequirementsTypes.push(entry.requirementsType); + } + } + + // tools.generated.ts has no existing `import` statements — we only inject one when + // we actually emitted a reference to a non-local requirements type. + if (importedRequirementsTypes.length > 0) { + const sortedImports = [...new Set(importedRequirementsTypes)].sort(); + const importBlock = `import type {\n${sortedImports.map(name => ` ${name},`).join('\n')}\n} from './core.generated';\n\n`; + result = importBlock + result; } + + // Emit named union aliases for the slot shapes so ts-to-zod produces named + // schemas (IndividualAssetSlotSchema, FormatAssetSlotSchema) and consumers + // can import the unions directly. Only emit when the constituent types are + // present in this file — keeps the post-processor a no-op on unrelated files. + const allIndividualPresent = INDIVIDUAL_ASSET_DISCRIMINATORS.every(entry => + new RegExp(`^export type ${entry.name} = BaseIndividualAsset & \\{`, 'm').test(result) + ); + const repeatableGroupPresent = /^export interface RepeatableGroupAsset \{/m.test(result); + + if (allIndividualPresent && repeatableGroupPresent && !/^export type IndividualAssetSlot\b/m.test(result)) { + const slotUnion = [ + `export type IndividualAssetSlot =`, + ...INDIVIDUAL_ASSET_DISCRIMINATORS.map((entry, i) => { + const tail = i === INDIVIDUAL_ASSET_DISCRIMINATORS.length - 1 ? ';' : ''; + return ` | ${entry.name}${tail}`; + }), + ``, + `export type GroupAssetSlot =`, + ...GROUP_ASSET_DISCRIMINATORS.map((entry, i) => { + const tail = i === GROUP_ASSET_DISCRIMINATORS.length - 1 ? ';' : ''; + return ` | ${entry.name}${tail}`; + }), + ``, + `export type FormatAssetSlot = IndividualAssetSlot | RepeatableGroupAsset;`, + ``, + ].join('\n'); + result = result.trimEnd() + '\n\n' + slotUnion; + + // Tighten Format.assets[] from the inline anonymous union to the named + // FormatAssetSlot[]. The codegen emits the inline union right after the + // 'Array of all assets supported for this format.' comment. If jsts ever + // changes its emitted indentation/wrapping the regex silently no-ops, so + // we count replacements and warn loudly — Format.assets[] would otherwise + // fall back to the loose anonymous union without TS surfacing it. + const formatAssetsPattern = new RegExp( + `( assets\\?: )\\(\\s*(?:\\|\\s*Individual\\w+Asset\\s*)+\\|\\s*RepeatableGroupAsset\\s*\\)\\[\\];`, + 'g' + ); + let formatAssetsReplaced = 0; + result = result.replace(formatAssetsPattern, (_match, prefix) => { + formatAssetsReplaced++; + return `${prefix}FormatAssetSlot[];`; + }); + if (formatAssetsReplaced === 0) { + console.warn( + '⚠️ applyIndividualAssetDiscriminators: Format.assets[] inline union not rewritten — jsts output layout may have changed' + ); + } + + // Same for RepeatableGroupAsset.assets[] — replace the inline group union with GroupAssetSlot[]. + const groupAssetsPattern = new RegExp(`( assets: )\\(\\s*(?:\\|\\s*Group\\w+Asset\\s*)+\\)\\[\\];`, 'g'); + let groupAssetsReplaced = 0; + result = result.replace(groupAssetsPattern, (_match, prefix) => { + groupAssetsReplaced++; + return `${prefix}GroupAssetSlot[];`; + }); + if (groupAssetsReplaced === 0) { + console.warn( + '⚠️ applyIndividualAssetDiscriminators: RepeatableGroupAsset.assets[] inline union not rewritten — jsts output layout may have changed' + ); + } + } + if (rewritten > 0) { console.log(`🔀 Restored asset_type discriminator on ${rewritten} Individual*Asset alias(es)`); } diff --git a/src/lib/index.ts b/src/lib/index.ts index 4ba27f2a1..e0aa34264 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -938,8 +938,6 @@ export { daastGroupAsset, urlGroupAsset, webhookGroupAsset, - briefGroupAsset, - catalogGroupAsset, } from './utils/format-asset-slot-builders'; // ====== PREVIEW RENDER BUILDERS ====== diff --git a/src/lib/types/core.generated.ts b/src/lib/types/core.generated.ts index 756ed7ec7..ac9efc5a3 100644 --- a/src/lib/types/core.generated.ts +++ b/src/lib/types/core.generated.ts @@ -1,5 +1,5 @@ // Generated AdCP core types from official schemas v3.0.9 -// Generated at: 2026-05-10T10:33:36.437Z +// Generated at: 2026-05-10T17:46:01.057Z // MEDIA-BUY SCHEMA /** @@ -15155,51 +15155,87 @@ export type IndividualCatalogAsset = BaseIndividualAsset & { /** * Image asset in group */ -export type GroupImageAsset = BaseGroupAsset; +export type GroupImageAsset = BaseGroupAsset & { + asset_type: 'image'; + requirements?: ImageAssetRequirements; +}; /** * Video asset in group */ -export type GroupVideoAsset = BaseGroupAsset; +export type GroupVideoAsset = BaseGroupAsset & { + asset_type: 'video'; + requirements?: VideoAssetRequirements; +}; /** * Audio asset in group */ -export type GroupAudioAsset = BaseGroupAsset; +export type GroupAudioAsset = BaseGroupAsset & { + asset_type: 'audio'; + requirements?: AudioAssetRequirements; +}; /** * Text asset in group */ -export type GroupTextAsset = BaseGroupAsset; +export type GroupTextAsset = BaseGroupAsset & { + asset_type: 'text'; + requirements?: TextAssetRequirements; +}; /** * Markdown asset in group */ -export type GroupMarkdownAsset = BaseGroupAsset; +export type GroupMarkdownAsset = BaseGroupAsset & { + asset_type: 'markdown'; + requirements?: MarkdownAssetRequirements; +}; /** * HTML asset in group */ -export type GroupHtmlAsset = BaseGroupAsset; +export type GroupHtmlAsset = BaseGroupAsset & { + asset_type: 'html'; + requirements?: HTMLAssetRequirements; +}; /** * CSS asset in group */ -export type GroupCssAsset = BaseGroupAsset; +export type GroupCssAsset = BaseGroupAsset & { + asset_type: 'css'; + requirements?: CSSAssetRequirements; +}; /** * JavaScript asset in group */ -export type GroupJavaScriptAsset = BaseGroupAsset; +export type GroupJavaScriptAsset = BaseGroupAsset & { + asset_type: 'javascript'; + requirements?: JavaScriptAssetRequirements; +}; /** * VAST asset in group */ -export type GroupVastAsset = BaseGroupAsset; +export type GroupVastAsset = BaseGroupAsset & { + asset_type: 'vast'; + requirements?: VASTAssetRequirements; +}; /** * DAAST asset in group */ -export type GroupDaastAsset = BaseGroupAsset; +export type GroupDaastAsset = BaseGroupAsset & { + asset_type: 'daast'; + requirements?: DAASTAssetRequirements; +}; /** * URL asset in group */ -export type GroupUrlAsset = BaseGroupAsset; +export type GroupUrlAsset = BaseGroupAsset & { + asset_type: 'url'; + requirements?: URLAssetRequirements; +}; /** * Webhook asset in group */ -export type GroupWebhookAsset = BaseGroupAsset; +export type GroupWebhookAsset = BaseGroupAsset & { + asset_type: 'webhook'; + requirements?: WebhookAssetRequirements; +}; /** * Represents a creative format with its requirements */ @@ -15283,23 +15319,7 @@ export interface Format { /** * Array of all assets supported for this format. Each asset is identified by its asset_id, which must be used as the key in creative manifests. Use the 'required' boolean on each asset to indicate whether it's mandatory. */ - assets?: ( - | IndividualImageAsset - | IndividualVideoAsset - | IndividualAudioAsset - | IndividualTextAsset - | IndividualMarkdownAsset - | IndividualHtmlAsset - | IndividualCssAsset - | IndividualJavaScriptAsset - | IndividualVastAsset - | IndividualDaastAsset - | IndividualUrlAsset - | IndividualWebhookAsset - | IndividualBriefAsset - | IndividualCatalogAsset - | RepeatableGroupAsset - )[]; + assets?: FormatAssetSlot[]; /** * Delivery method specifications (e.g., hosted, VAST, third-party tags) */ @@ -15477,20 +15497,7 @@ export interface RepeatableGroupAsset { /** * Assets within each repetition of this group */ - assets: ( - | GroupImageAsset - | GroupVideoAsset - | GroupAudioAsset - | GroupTextAsset - | GroupMarkdownAsset - | GroupHtmlAsset - | GroupCssAsset - | GroupJavaScriptAsset - | GroupVastAsset - | GroupDaastAsset - | GroupUrlAsset - | GroupWebhookAsset - )[]; + assets: GroupAssetSlot[]; } export interface BaseGroupAsset { /** @@ -17770,3 +17777,35 @@ export interface PropertyListChangedWebhook { signature: string; ext?: ExtensionObject; } + +export type IndividualAssetSlot = + | IndividualImageAsset + | IndividualVideoAsset + | IndividualAudioAsset + | IndividualTextAsset + | IndividualMarkdownAsset + | IndividualHtmlAsset + | IndividualCssAsset + | IndividualJavaScriptAsset + | IndividualVastAsset + | IndividualDaastAsset + | IndividualUrlAsset + | IndividualWebhookAsset + | IndividualBriefAsset + | IndividualCatalogAsset; + +export type GroupAssetSlot = + | GroupImageAsset + | GroupVideoAsset + | GroupAudioAsset + | GroupTextAsset + | GroupMarkdownAsset + | GroupHtmlAsset + | GroupCssAsset + | GroupJavaScriptAsset + | GroupVastAsset + | GroupDaastAsset + | GroupUrlAsset + | GroupWebhookAsset; + +export type FormatAssetSlot = IndividualAssetSlot | RepeatableGroupAsset; diff --git a/src/lib/types/format-asset-slots.ts b/src/lib/types/format-asset-slots.ts index 02fb0416d..e11659ffc 100644 --- a/src/lib/types/format-asset-slots.ts +++ b/src/lib/types/format-asset-slots.ts @@ -1,205 +1,74 @@ -// Strict types for the asset slots inside a Format definition (Format.assets[]). -// -// These describe what a publisher/platform SELLS — the slots buyers must fill -// when building a creative for the format. They are distinct from the creative -// instance types (ImageAsset, VideoAsset, …) in `tools.generated.ts`, which -// describe the assets a buyer DELIVERS. -// -// The generated `Format.assets[]` collapses to `BaseIndividualAsset` (no -// per-asset-type discriminator, no `requirements` field) — the json-schema-to- -// typescript codegen loses the `oneOf` branching when all branches share a -// `$ref` base. The per-asset-type `*AssetRequirements` interfaces already -// exist in `core.generated.ts`; these hand-authored slot types wire them in -// so misnamed fields (`file_types` vs `formats`), wrong units (`_seconds` vs -// `_ms`), and misplaced `min_count` (on an individual asset instead of a -// repeatable_group) become TypeScript errors at the authorship site. -// -// Source of truth: schemas/cache/{version}/bundled/{creative,media-buy}/list-creative-formats-response.json +// Backwards-compatible aliases for the format asset slot types. The strict +// per-asset-type slot shapes (with `asset_type` discriminator + per-type +// `requirements`) are now produced by the codegen post-processor in +// scripts/generate-types.ts and live in tools.generated.ts. These aliases +// keep the prior `*Slot`-suffixed names working for downstream consumers. import type { - AudioAssetRequirements, - CSSAssetRequirements, - CatalogRequirements, - DAASTAssetRequirements, - HTMLAssetRequirements, - ImageAssetRequirements, - JavaScriptAssetRequirements, - MarkdownAssetRequirements, - TextAssetRequirements, - URLAssetRequirements, - VASTAssetRequirements, - VideoAssetRequirements, - WebhookAssetRequirements, -} from './core.generated'; -import type { Overlay } from './tools.generated'; - -// ---------- Shared base ---------- - -export interface BaseIndividualAssetSlot { - item_type: 'individual'; - /** Unique identifier for this asset. Creative manifests MUST use this exact value as the key in the assets object. */ - asset_id: string; - /** Descriptive label for this asset's purpose (for documentation / UI only). */ - asset_role?: string; - /** Whether this asset is required for a valid creative. */ - required: boolean; - /** Publisher-controlled overlay elements rendered over buyer content at this asset's position. */ - overlays?: Overlay[]; -} - -export interface BaseGroupAssetSlot { - /** Identifier within the group. */ - asset_id: string; - asset_role?: string; - /** Whether this asset is required within each repetition of the group. */ - required: boolean; - overlays?: Overlay[]; -} - -// ---------- Per-asset-type individual slot shapes ---------- - -export interface IndividualImageAssetSlot extends BaseIndividualAssetSlot { - asset_type: 'image'; - requirements?: ImageAssetRequirements; -} - -export interface IndividualVideoAssetSlot extends BaseIndividualAssetSlot { - asset_type: 'video'; - requirements?: VideoAssetRequirements; -} - -export interface IndividualAudioAssetSlot extends BaseIndividualAssetSlot { - asset_type: 'audio'; - requirements?: AudioAssetRequirements; -} - -export interface IndividualTextAssetSlot extends BaseIndividualAssetSlot { - asset_type: 'text'; - requirements?: TextAssetRequirements; -} - -export interface IndividualMarkdownAssetSlot extends BaseIndividualAssetSlot { - asset_type: 'markdown'; - requirements?: MarkdownAssetRequirements; -} - -export interface IndividualHtmlAssetSlot extends BaseIndividualAssetSlot { - asset_type: 'html'; - requirements?: HTMLAssetRequirements; -} - -export interface IndividualCssAssetSlot extends BaseIndividualAssetSlot { - asset_type: 'css'; - requirements?: CSSAssetRequirements; -} - -export interface IndividualJavascriptAssetSlot extends BaseIndividualAssetSlot { - asset_type: 'javascript'; - requirements?: JavaScriptAssetRequirements; -} - -export interface IndividualVastAssetSlot extends BaseIndividualAssetSlot { - asset_type: 'vast'; - requirements?: VASTAssetRequirements; -} - -export interface IndividualDaastAssetSlot extends BaseIndividualAssetSlot { - asset_type: 'daast'; - requirements?: DAASTAssetRequirements; -} - -export interface IndividualUrlAssetSlot extends BaseIndividualAssetSlot { - asset_type: 'url'; - requirements?: URLAssetRequirements; -} - -export interface IndividualWebhookAssetSlot extends BaseIndividualAssetSlot { - asset_type: 'webhook'; - requirements?: WebhookAssetRequirements; -} - -export interface IndividualBriefAssetSlot extends BaseIndividualAssetSlot { - asset_type: 'brief'; -} - -export interface IndividualCatalogAssetSlot extends BaseIndividualAssetSlot { - asset_type: 'catalog'; - requirements?: CatalogRequirements; -} - -export type IndividualAssetSlot = - | IndividualImageAssetSlot - | IndividualVideoAssetSlot - | IndividualAudioAssetSlot - | IndividualTextAssetSlot - | IndividualMarkdownAssetSlot - | IndividualHtmlAssetSlot - | IndividualCssAssetSlot - | IndividualJavascriptAssetSlot - | IndividualVastAssetSlot - | IndividualDaastAssetSlot - | IndividualUrlAssetSlot - | IndividualWebhookAssetSlot - | IndividualBriefAssetSlot - | IndividualCatalogAssetSlot; - -// ---------- Group asset slot shapes (inside a repeatable_group) ---------- - -type GroupSlotOf = Omit & BaseGroupAssetSlot; - -export type GroupImageAssetSlot = GroupSlotOf; -export type GroupVideoAssetSlot = GroupSlotOf; -export type GroupAudioAssetSlot = GroupSlotOf; -export type GroupTextAssetSlot = GroupSlotOf; -export type GroupMarkdownAssetSlot = GroupSlotOf; -export type GroupHtmlAssetSlot = GroupSlotOf; -export type GroupCssAssetSlot = GroupSlotOf; -export type GroupJavascriptAssetSlot = GroupSlotOf; -export type GroupVastAssetSlot = GroupSlotOf; -export type GroupDaastAssetSlot = GroupSlotOf; -export type GroupUrlAssetSlot = GroupSlotOf; -export type GroupWebhookAssetSlot = GroupSlotOf; -export type GroupBriefAssetSlot = GroupSlotOf; -export type GroupCatalogAssetSlot = GroupSlotOf; - -export type GroupAssetSlot = - | GroupImageAssetSlot - | GroupVideoAssetSlot - | GroupAudioAssetSlot - | GroupTextAssetSlot - | GroupMarkdownAssetSlot - | GroupHtmlAssetSlot - | GroupCssAssetSlot - | GroupJavascriptAssetSlot - | GroupVastAssetSlot - | GroupDaastAssetSlot - | GroupUrlAssetSlot - | GroupWebhookAssetSlot - | GroupBriefAssetSlot - | GroupCatalogAssetSlot; - -// ---------- Repeatable group ---------- - -/** - * Wrapper for asset groups that repeat (carousels, collections, story-pin - * frames, product showcases). `min_count` and `max_count` live here — NOT on - * individual assets inside `assets[]`. Putting count constraints on an - * individual asset slot violates the spec. - */ -export interface RepeatableGroupSlot { - item_type: 'repeatable_group'; - /** Identifier for this asset group (e.g., 'product', 'slide', 'card'). */ - asset_group_id: string; - /** Whether this asset group is required. If true, at least `min_count` repetitions must be provided. */ - required: boolean; - /** Minimum number of repetitions. */ - min_count: number; - /** Maximum number of repetitions. */ - max_count: number; - /** Display semantics: 'sequential' (carousel) or 'optimize' (platform selects best-performing). */ - selection_mode?: 'sequential' | 'optimize'; - /** Assets within each repetition of this group. */ - assets: GroupAssetSlot[]; -} - -export type FormatAssetSlot = IndividualAssetSlot | RepeatableGroupSlot; + BaseGroupAsset, + BaseIndividualAsset, + GroupAudioAsset, + GroupCssAsset, + GroupDaastAsset, + GroupHtmlAsset, + GroupImageAsset, + GroupJavaScriptAsset, + GroupMarkdownAsset, + GroupTextAsset, + GroupUrlAsset, + GroupVastAsset, + GroupVideoAsset, + GroupWebhookAsset, + IndividualAudioAsset, + IndividualBriefAsset, + IndividualCatalogAsset, + IndividualCssAsset, + IndividualDaastAsset, + IndividualHtmlAsset, + IndividualImageAsset, + IndividualJavaScriptAsset, + IndividualMarkdownAsset, + IndividualTextAsset, + IndividualUrlAsset, + IndividualVastAsset, + IndividualVideoAsset, + IndividualWebhookAsset, + RepeatableGroupAsset, +} from './tools.generated'; + +// Re-export the codegen-produced slot unions so consumers importing from +// `@adcp/sdk` continue to find them under the same names. +export type { FormatAssetSlot, GroupAssetSlot, IndividualAssetSlot } from './tools.generated'; + +export type BaseIndividualAssetSlot = BaseIndividualAsset; +export type BaseGroupAssetSlot = BaseGroupAsset; + +export type IndividualImageAssetSlot = IndividualImageAsset; +export type IndividualVideoAssetSlot = IndividualVideoAsset; +export type IndividualAudioAssetSlot = IndividualAudioAsset; +export type IndividualTextAssetSlot = IndividualTextAsset; +export type IndividualMarkdownAssetSlot = IndividualMarkdownAsset; +export type IndividualHtmlAssetSlot = IndividualHtmlAsset; +export type IndividualCssAssetSlot = IndividualCssAsset; +export type IndividualJavascriptAssetSlot = IndividualJavaScriptAsset; +export type IndividualVastAssetSlot = IndividualVastAsset; +export type IndividualDaastAssetSlot = IndividualDaastAsset; +export type IndividualUrlAssetSlot = IndividualUrlAsset; +export type IndividualWebhookAssetSlot = IndividualWebhookAsset; +export type IndividualBriefAssetSlot = IndividualBriefAsset; +export type IndividualCatalogAssetSlot = IndividualCatalogAsset; + +export type GroupImageAssetSlot = GroupImageAsset; +export type GroupVideoAssetSlot = GroupVideoAsset; +export type GroupAudioAssetSlot = GroupAudioAsset; +export type GroupTextAssetSlot = GroupTextAsset; +export type GroupMarkdownAssetSlot = GroupMarkdownAsset; +export type GroupHtmlAssetSlot = GroupHtmlAsset; +export type GroupCssAssetSlot = GroupCssAsset; +export type GroupJavascriptAssetSlot = GroupJavaScriptAsset; +export type GroupVastAssetSlot = GroupVastAsset; +export type GroupDaastAssetSlot = GroupDaastAsset; +export type GroupUrlAssetSlot = GroupUrlAsset; +export type GroupWebhookAssetSlot = GroupWebhookAsset; + +export type RepeatableGroupSlot = RepeatableGroupAsset; diff --git a/src/lib/types/schemas.generated.ts b/src/lib/types/schemas.generated.ts index da02d1ef5..8145df69a 100644 --- a/src/lib/types/schemas.generated.ts +++ b/src/lib/types/schemas.generated.ts @@ -1,5 +1,5 @@ // Generated Zod v4 schemas from TypeScript types -// Generated at: 2026-05-03T20:22:15.243Z +// Generated at: 2026-05-10T17:46:04.922Z // Sources: // - core.generated.ts (core types) // - tools.generated.ts (tool types) @@ -3260,123 +3260,6 @@ export const FormatIDParameterSchema = z.union([z.literal("dimensions"), z.liter export const DimensionUnitSchema = z.union([z.literal("px"), z.literal("dp"), z.literal("inches"), z.literal("cm"), z.literal("mm"), z.literal("pt")]); -export const ImageAssetRequirementsSchema = z.object({ - min_width: z.number().optional(), - max_width: z.number().optional(), - min_height: z.number().optional(), - max_height: z.number().optional(), - unit: DimensionUnitSchema.optional(), - aspect_ratio: z.string().optional(), - formats: z.array(z.union([z.literal("jpg"), z.literal("jpeg"), z.literal("png"), z.literal("gif"), z.literal("webp"), z.literal("svg"), z.literal("avif"), z.literal("tiff"), z.literal("pdf"), z.literal("eps")])).optional(), - min_dpi: z.number().optional(), - bleed: z.union([z.object({ - uniform: z.number() - }).passthrough(), z.object({ - top: z.number(), - right: z.number(), - bottom: z.number(), - left: z.number() - }).passthrough()]).optional(), - color_space: z.union([z.literal("rgb"), z.literal("cmyk"), z.literal("grayscale")]).optional(), - max_file_size_kb: z.number().optional(), - transparency_required: z.boolean().optional(), - animation_allowed: z.boolean().optional(), - max_animation_duration_ms: z.number().optional(), - max_weight_grams: z.number().optional() -}).passthrough(); - -export const VideoAssetRequirementsSchema = z.object({ - min_width: z.number().optional(), - max_width: z.number().optional(), - min_height: z.number().optional(), - max_height: z.number().optional(), - aspect_ratio: z.string().optional(), - min_duration_ms: z.number().optional(), - max_duration_ms: z.number().optional(), - containers: z.array(z.union([z.literal("mp4"), z.literal("webm"), z.literal("mov"), z.literal("avi"), z.literal("mkv")])).optional(), - codecs: z.array(z.union([z.literal("h264"), z.literal("h265"), z.literal("vp8"), z.literal("vp9"), z.literal("av1"), z.literal("prores")])).optional(), - max_file_size_kb: z.number().optional(), - min_bitrate_kbps: z.number().optional(), - max_bitrate_kbps: z.number().optional(), - frame_rates: z.array(z.number()).optional(), - audio_required: z.boolean().optional(), - frame_rate_type: FrameRateTypeSchema.optional(), - scan_type: ScanTypeSchema.optional(), - gop_type: GOPTypeSchema.optional(), - min_gop_interval_seconds: z.number().optional(), - max_gop_interval_seconds: z.number().optional(), - moov_atom_position: MoovAtomPositionSchema.optional(), - audio_codecs: z.array(z.union([z.literal("aac"), z.literal("pcm"), z.literal("ac3"), z.literal("eac3"), z.literal("mp3"), z.literal("opus"), z.literal("vorbis"), z.literal("flac")])).optional(), - audio_sample_rates: z.array(z.number()).optional(), - audio_channels: z.array(AudioChannelLayoutSchema).optional(), - loudness_lufs: z.number().optional(), - loudness_tolerance_db: z.number().optional(), - true_peak_dbfs: z.number().optional() -}).passthrough(); - -export const AudioAssetRequirementsSchema = z.object({ - min_duration_ms: z.number().optional(), - max_duration_ms: z.number().optional(), - formats: z.array(z.union([z.literal("mp3"), z.literal("aac"), z.literal("wav"), z.literal("ogg"), z.literal("flac")])).optional(), - max_file_size_kb: z.number().optional(), - sample_rates: z.array(z.number()).optional(), - channels: z.array(z.union([z.literal("mono"), z.literal("stereo")])).optional(), - min_bitrate_kbps: z.number().optional(), - max_bitrate_kbps: z.number().optional() -}).passthrough(); - -export const TextAssetRequirementsSchema = z.object({ - min_length: z.number().optional(), - max_length: z.number().optional(), - min_lines: z.number().optional(), - max_lines: z.number().optional(), - character_pattern: z.string().optional(), - prohibited_terms: z.array(z.string()).optional() -}).passthrough(); - -export const MarkdownAssetRequirementsSchema = z.object({ - max_length: z.number().optional() -}).passthrough(); - -export const HTMLAssetRequirementsSchema = z.object({ - max_file_size_kb: z.number().optional(), - sandbox: z.union([z.literal("none"), z.literal("iframe"), z.literal("safeframe"), z.literal("fencedframe")]).optional(), - external_resources_allowed: z.boolean().optional(), - allowed_external_domains: z.array(z.string()).optional() -}).passthrough(); - -export const CSSAssetRequirementsSchema = z.object({ - max_file_size_kb: z.number().optional() -}).passthrough(); - -export const JavaScriptAssetRequirementsSchema = z.object({ - max_file_size_kb: z.number().optional(), - module_type: z.union([z.literal("script"), z.literal("module"), z.literal("iife")]).optional(), - strict_mode_required: z.boolean().optional(), - external_resources_allowed: z.boolean().optional(), - allowed_external_domains: z.array(z.string()).optional() -}).passthrough(); - -export const VASTAssetRequirementsSchema = z.object({ - vast_version: z.union([z.literal("2.0"), z.literal("3.0"), z.literal("4.0"), z.literal("4.1"), z.literal("4.2")]).optional() -}).passthrough(); - -export const DAASTAssetRequirementsSchema = z.object({ - daast_version: z.literal("1.0").optional() -}).passthrough(); - -export const URLAssetRequirementsSchema = z.object({ - role: z.union([z.literal("clickthrough"), z.literal("landing_page"), z.literal("impression_tracker"), z.literal("click_tracker"), z.literal("viewability_tracker"), z.literal("third_party_tracker")]).optional(), - protocols: z.array(z.union([z.literal("https"), z.literal("http")])).optional(), - allowed_domains: z.array(z.string()).optional(), - max_length: z.number().optional(), - macro_support: z.boolean().optional() -}).passthrough(); - -export const WebhookAssetRequirementsSchema = z.object({ - methods: z.array(z.union([z.literal("GET"), z.literal("POST")])).optional() -}).passthrough(); - export const OverlaySchema = z.object({ id: z.string(), description: z.string().optional(), @@ -3556,8 +3439,6 @@ export const RealEstateItemSchema = z.object({ ext: ExtensionObjectSchema.optional() }).passthrough(); -export const AssetRequirementsSchema = z.union([ImageAssetRequirementsSchema, VideoAssetRequirementsSchema, AudioAssetRequirementsSchema, TextAssetRequirementsSchema, MarkdownAssetRequirementsSchema, HTMLAssetRequirementsSchema, CSSAssetRequirementsSchema, JavaScriptAssetRequirementsSchema, VASTAssetRequirementsSchema, DAASTAssetRequirementsSchema, URLAssetRequirementsSchema, WebhookAssetRequirementsSchema]); - export const ScalarBindingSchema = z.object({ kind: z.literal("scalar"), asset_id: z.string(), @@ -3572,16 +3453,6 @@ export const AssetPoolBindingSchema = z.object({ ext: ExtensionObjectSchema.optional() }).passthrough(); -export const OfferingAssetConstraintSchema = z.object({ - asset_group_id: z.string(), - asset_type: AssetContentTypeSchema, - required: z.boolean().optional(), - min_count: z.number().optional(), - max_count: z.number().optional(), - asset_requirements: AssetRequirementsSchema.optional(), - ext: ExtensionObjectSchema.optional() -}).passthrough(); - export const CatalogFieldBindingSchema = z.union([ScalarBindingSchema, AssetPoolBindingSchema, z.object({ kind: z.literal("catalog_group"), format_group_id: z.string(), @@ -4034,50 +3905,6 @@ export const BaseIndividualAssetSchema = z.object({ overlays: z.array(OverlaySchema).optional() }).passthrough(); -export const IndividualVideoAssetSchema = BaseIndividualAssetSchema.and(z.object({ - asset_type: z.literal("video") -}).passthrough()); - -export const IndividualAudioAssetSchema = BaseIndividualAssetSchema.and(z.object({ - asset_type: z.literal("audio") -}).passthrough()); - -export const IndividualTextAssetSchema = BaseIndividualAssetSchema.and(z.object({ - asset_type: z.literal("text") -}).passthrough()); - -export const IndividualMarkdownAssetSchema = BaseIndividualAssetSchema.and(z.object({ - asset_type: z.literal("markdown") -}).passthrough()); - -export const IndividualHtmlAssetSchema = BaseIndividualAssetSchema.and(z.object({ - asset_type: z.literal("html") -}).passthrough()); - -export const IndividualCssAssetSchema = BaseIndividualAssetSchema.and(z.object({ - asset_type: z.literal("css") -}).passthrough()); - -export const IndividualJavaScriptAssetSchema = BaseIndividualAssetSchema.and(z.object({ - asset_type: z.literal("javascript") -}).passthrough()); - -export const IndividualVastAssetSchema = BaseIndividualAssetSchema.and(z.object({ - asset_type: z.literal("vast") -}).passthrough()); - -export const IndividualDaastAssetSchema = BaseIndividualAssetSchema.and(z.object({ - asset_type: z.literal("daast") -}).passthrough()); - -export const IndividualUrlAssetSchema = BaseIndividualAssetSchema.and(z.object({ - asset_type: z.literal("url") -}).passthrough()); - -export const IndividualWebhookAssetSchema = BaseIndividualAssetSchema.and(z.object({ - asset_type: z.literal("webhook") -}).passthrough()); - export const IndividualBriefAssetSchema = BaseIndividualAssetSchema.and(z.object({ asset_type: z.literal("brief") }).passthrough()); @@ -4086,48 +3913,10 @@ export const IndividualCatalogAssetSchema = BaseIndividualAssetSchema.and(z.obje asset_type: z.literal("catalog") }).passthrough()); -export const GroupImageAssetSchema = BaseGroupAssetSchema; - -export const GroupVideoAssetSchema = BaseGroupAssetSchema; - -export const GroupAudioAssetSchema = BaseGroupAssetSchema; - -export const GroupTextAssetSchema = BaseGroupAssetSchema; - -export const GroupMarkdownAssetSchema = BaseGroupAssetSchema; - -export const GroupHtmlAssetSchema = BaseGroupAssetSchema; - -export const GroupCssAssetSchema = BaseGroupAssetSchema; - -export const GroupJavaScriptAssetSchema = BaseGroupAssetSchema; - -export const GroupVastAssetSchema = BaseGroupAssetSchema; - -export const GroupDaastAssetSchema = BaseGroupAssetSchema; - -export const GroupUrlAssetSchema = BaseGroupAssetSchema; - -export const GroupWebhookAssetSchema = BaseGroupAssetSchema; - export const VendorPricingOptionSchema = z.object({ pricing_option_id: z.string() }).passthrough().and(VendorPricingSchema); -export const IndividualImageAssetSchema = BaseIndividualAssetSchema.and(z.object({ - asset_type: z.literal("image") -}).passthrough()); - -export const RepeatableGroupAssetSchema = z.object({ - item_type: z.literal("repeatable_group"), - asset_group_id: z.string(), - required: z.boolean(), - min_count: z.number(), - max_count: z.number(), - selection_mode: z.union([z.literal("sequential"), z.literal("optimize")]).optional(), - assets: z.array(z.union([GroupImageAssetSchema, GroupVideoAssetSchema, GroupAudioAssetSchema, GroupTextAssetSchema, GroupMarkdownAssetSchema, GroupHtmlAssetSchema, GroupCssAssetSchema, GroupJavaScriptAssetSchema, GroupVastAssetSchema, GroupDaastAssetSchema, GroupUrlAssetSchema, GroupWebhookAssetSchema])) -}).passthrough(); - export const CreativeBriefSchema = z.object({ name: z.string(), objective: z.union([z.literal("awareness"), z.literal("consideration"), z.literal("conversion"), z.literal("retention"), z.literal("engagement")]).optional(), @@ -5551,6 +5340,30 @@ export const ControllerErrorSchema = z.object({ ext: ExtensionObjectSchema.optional() }).passthrough(); +const ImageAssetRequirementsSchema = z.any(); + +const VideoAssetRequirementsSchema = z.any(); + +const AudioAssetRequirementsSchema = z.any(); + +const TextAssetRequirementsSchema = z.any(); + +const MarkdownAssetRequirementsSchema = z.any(); + +const HTMLAssetRequirementsSchema = z.any(); + +const CSSAssetRequirementsSchema = z.any(); + +const JavaScriptAssetRequirementsSchema = z.any(); + +const VASTAssetRequirementsSchema = z.any(); + +const DAASTAssetRequirementsSchema = z.any(); + +const URLAssetRequirementsSchema = z.any(); + +const WebhookAssetRequirementsSchema = z.any(); + export const MediaBuySchema = z.object({ media_buy_id: z.string(), account: AccountSchema.optional(), @@ -6251,67 +6064,138 @@ export const CollectionSchema = z.object({ ext: ExtensionObjectSchema.optional() }).passthrough(); -export const FormatSchema = z.object({ - format_id: FormatReferenceStructuredObjectSchema, - name: z.string(), - description: z.string().optional(), - example_url: z.string().optional(), - accepts_parameters: z.array(FormatIDParameterSchema).optional(), - renders: z.array(z.union([z.object({ - role: z.string(), - dimensions: z.object({ - width: z.number().optional(), - height: z.number().optional(), - min_width: z.number().optional(), - min_height: z.number().optional(), - max_width: z.number().optional(), - max_height: z.number().optional(), - unit: DimensionUnitSchema.optional(), - responsive: z.object({ - width: z.boolean(), - height: z.boolean() - }).passthrough().optional(), - aspect_ratio: z.string().optional() - }).passthrough() - }).passthrough(), z.object({ - role: z.string(), - parameters_from_format_id: z.literal(true) - }).passthrough()])).optional(), - assets: z.array(z.union([IndividualImageAssetSchema, IndividualVideoAssetSchema, IndividualAudioAssetSchema, IndividualTextAssetSchema, IndividualMarkdownAssetSchema, IndividualHtmlAssetSchema, IndividualCssAssetSchema, IndividualJavaScriptAssetSchema, IndividualVastAssetSchema, IndividualDaastAssetSchema, IndividualUrlAssetSchema, IndividualWebhookAssetSchema, IndividualBriefAssetSchema, IndividualCatalogAssetSchema, RepeatableGroupAssetSchema])).optional(), - delivery: z.object({}).passthrough().optional(), - supported_macros: z.array(z.union([UniversalMacroSchema, z.string()])).optional(), - input_format_ids: z.array(FormatReferenceStructuredObjectSchema).optional(), - output_format_ids: z.array(FormatReferenceStructuredObjectSchema).optional(), - format_card: z.object({ - format_id: FormatReferenceStructuredObjectSchema, - manifest: z.object({}).passthrough() - }).passthrough().optional(), - accessibility: z.object({ - wcag_level: WCAGLevelSchema, - requires_accessible_assets: z.boolean().optional() - }).passthrough().optional(), - supported_disclosure_positions: z.array(DisclosurePositionSchema).optional(), - disclosure_capabilities: z.array(z.object({ - position: DisclosurePositionSchema, - persistence: z.array(DisclosurePersistenceSchema) - }).passthrough()).optional(), - format_card_detailed: z.object({ - format_id: FormatReferenceStructuredObjectSchema, - manifest: z.object({}).passthrough() - }).passthrough().optional(), - reported_metrics: z.array(AvailableMetricSchema).optional(), - pricing_options: z.array(VendorPricingOptionSchema).optional() -}).passthrough(); +export const IndividualImageAssetSchema = BaseIndividualAssetSchema.and(z.object({ + asset_type: z.literal("image"), + requirements: ImageAssetRequirementsSchema.optional() +}).passthrough()); -export const CatalogRequirementsSchema = z.object({ - catalog_type: CatalogTypeSchema, +export const IndividualVideoAssetSchema = BaseIndividualAssetSchema.and(z.object({ + asset_type: z.literal("video"), + requirements: VideoAssetRequirementsSchema.optional() +}).passthrough()); + +export const IndividualAudioAssetSchema = BaseIndividualAssetSchema.and(z.object({ + asset_type: z.literal("audio"), + requirements: AudioAssetRequirementsSchema.optional() +}).passthrough()); + +export const IndividualTextAssetSchema = BaseIndividualAssetSchema.and(z.object({ + asset_type: z.literal("text"), + requirements: TextAssetRequirementsSchema.optional() +}).passthrough()); + +export const IndividualMarkdownAssetSchema = BaseIndividualAssetSchema.and(z.object({ + asset_type: z.literal("markdown"), + requirements: MarkdownAssetRequirementsSchema.optional() +}).passthrough()); + +export const IndividualHtmlAssetSchema = BaseIndividualAssetSchema.and(z.object({ + asset_type: z.literal("html"), + requirements: HTMLAssetRequirementsSchema.optional() +}).passthrough()); + +export const IndividualCssAssetSchema = BaseIndividualAssetSchema.and(z.object({ + asset_type: z.literal("css"), + requirements: CSSAssetRequirementsSchema.optional() +}).passthrough()); + +export const IndividualJavaScriptAssetSchema = BaseIndividualAssetSchema.and(z.object({ + asset_type: z.literal("javascript"), + requirements: JavaScriptAssetRequirementsSchema.optional() +}).passthrough()); + +export const IndividualVastAssetSchema = BaseIndividualAssetSchema.and(z.object({ + asset_type: z.literal("vast"), + requirements: VASTAssetRequirementsSchema.optional() +}).passthrough()); + +export const IndividualDaastAssetSchema = BaseIndividualAssetSchema.and(z.object({ + asset_type: z.literal("daast"), + requirements: DAASTAssetRequirementsSchema.optional() +}).passthrough()); + +export const IndividualUrlAssetSchema = BaseIndividualAssetSchema.and(z.object({ + asset_type: z.literal("url"), + requirements: URLAssetRequirementsSchema.optional() +}).passthrough()); + +export const IndividualWebhookAssetSchema = BaseIndividualAssetSchema.and(z.object({ + asset_type: z.literal("webhook"), + requirements: WebhookAssetRequirementsSchema.optional() +}).passthrough()); + +export const GroupImageAssetSchema = BaseGroupAssetSchema.and(z.object({ + asset_type: z.literal("image"), + requirements: ImageAssetRequirementsSchema.optional() +}).passthrough()); + +export const GroupVideoAssetSchema = BaseGroupAssetSchema.and(z.object({ + asset_type: z.literal("video"), + requirements: VideoAssetRequirementsSchema.optional() +}).passthrough()); + +export const GroupAudioAssetSchema = BaseGroupAssetSchema.and(z.object({ + asset_type: z.literal("audio"), + requirements: AudioAssetRequirementsSchema.optional() +}).passthrough()); + +export const GroupTextAssetSchema = BaseGroupAssetSchema.and(z.object({ + asset_type: z.literal("text"), + requirements: TextAssetRequirementsSchema.optional() +}).passthrough()); + +export const GroupMarkdownAssetSchema = BaseGroupAssetSchema.and(z.object({ + asset_type: z.literal("markdown"), + requirements: MarkdownAssetRequirementsSchema.optional() +}).passthrough()); + +export const GroupHtmlAssetSchema = BaseGroupAssetSchema.and(z.object({ + asset_type: z.literal("html"), + requirements: HTMLAssetRequirementsSchema.optional() +}).passthrough()); + +export const GroupCssAssetSchema = BaseGroupAssetSchema.and(z.object({ + asset_type: z.literal("css"), + requirements: CSSAssetRequirementsSchema.optional() +}).passthrough()); + +export const GroupJavaScriptAssetSchema = BaseGroupAssetSchema.and(z.object({ + asset_type: z.literal("javascript"), + requirements: JavaScriptAssetRequirementsSchema.optional() +}).passthrough()); + +export const GroupVastAssetSchema = BaseGroupAssetSchema.and(z.object({ + asset_type: z.literal("vast"), + requirements: VASTAssetRequirementsSchema.optional() +}).passthrough()); + +export const GroupDaastAssetSchema = BaseGroupAssetSchema.and(z.object({ + asset_type: z.literal("daast"), + requirements: DAASTAssetRequirementsSchema.optional() +}).passthrough()); + +export const GroupUrlAssetSchema = BaseGroupAssetSchema.and(z.object({ + asset_type: z.literal("url"), + requirements: URLAssetRequirementsSchema.optional() +}).passthrough()); + +export const GroupWebhookAssetSchema = BaseGroupAssetSchema.and(z.object({ + asset_type: z.literal("webhook"), + requirements: WebhookAssetRequirementsSchema.optional() +}).passthrough()); + +export const GroupAssetSlotSchema = z.union([GroupImageAssetSchema, GroupVideoAssetSchema, GroupAudioAssetSchema, GroupTextAssetSchema, GroupMarkdownAssetSchema, GroupHtmlAssetSchema, GroupCssAssetSchema, GroupJavaScriptAssetSchema, GroupVastAssetSchema, GroupDaastAssetSchema, GroupUrlAssetSchema, GroupWebhookAssetSchema]); + +export const AssetRequirementsSchema = z.union([ImageAssetRequirementsSchema, VideoAssetRequirementsSchema, AudioAssetRequirementsSchema, TextAssetRequirementsSchema, MarkdownAssetRequirementsSchema, HTMLAssetRequirementsSchema, CSSAssetRequirementsSchema, JavaScriptAssetRequirementsSchema, VASTAssetRequirementsSchema, DAASTAssetRequirementsSchema, URLAssetRequirementsSchema, WebhookAssetRequirementsSchema]); + +export const OfferingAssetConstraintSchema = z.object({ + asset_group_id: z.string(), + asset_type: AssetContentTypeSchema, required: z.boolean().optional(), - min_items: z.number().optional(), - max_items: z.number().optional(), - required_fields: z.array(z.string()).optional(), - feed_formats: z.array(FeedFormatSchema).optional(), - offering_asset_constraints: z.array(OfferingAssetConstraintSchema).optional(), - field_bindings: z.array(CatalogFieldBindingSchema).optional() + min_count: z.number().optional(), + max_count: z.number().optional(), + asset_requirements: AssetRequirementsSchema.optional(), + ext: ExtensionObjectSchema.optional() }).passthrough(); export const SignalPricingOptionSchema = z.object({ @@ -6348,6 +6232,18 @@ export const PropertyFeatureResultSchema = z.object({ ext: ExtensionObjectSchema.optional() }).passthrough(); +export const IndividualAssetSlotSchema = z.union([IndividualImageAssetSchema, IndividualVideoAssetSchema, IndividualAudioAssetSchema, IndividualTextAssetSchema, IndividualMarkdownAssetSchema, IndividualHtmlAssetSchema, IndividualCssAssetSchema, IndividualJavaScriptAssetSchema, IndividualVastAssetSchema, IndividualDaastAssetSchema, IndividualUrlAssetSchema, IndividualWebhookAssetSchema, IndividualBriefAssetSchema, IndividualCatalogAssetSchema]); + +export const RepeatableGroupAssetSchema = z.object({ + item_type: z.literal("repeatable_group"), + asset_group_id: z.string(), + required: z.boolean(), + min_count: z.number(), + max_count: z.number(), + selection_mode: z.union([z.literal("sequential"), z.literal("optimize")]).optional(), + assets: z.array(GroupAssetSlotSchema) +}).passthrough(); + export const GetProductsResponseSchema = z.object({ products: z.array(ProductSchema), proposals: z.array(ProposalSchema).optional(), @@ -6380,19 +6276,7 @@ export const GetProductsResponseSchema = z.object({ ext: ExtensionObjectSchema.optional() }).passthrough(); -export const ListCreativeFormatsResponseSchema = z.object({ - formats: z.array(FormatSchema), - creative_agents: z.array(z.object({ - agent_url: z.string(), - agent_name: z.string().optional(), - capabilities: z.array(CreativeAgentCapabilitySchema).optional() - }).passthrough()).optional(), - errors: z.array(ErrorSchema).optional(), - pagination: PaginationResponseSchema.optional(), - sandbox: z.boolean().optional(), - context: ContextObjectSchema.optional(), - ext: ExtensionObjectSchema.optional() -}).passthrough(); +export const FormatAssetSlotSchema = z.union([IndividualAssetSlotSchema, RepeatableGroupAssetSchema]); export const CreateMediaBuyRequestSchema = z.object({ adcp_major_version: z.number().optional(), @@ -6580,6 +6464,83 @@ export const ValidatePropertyDeliveryResponseSchema = z.object({ ext: ExtensionObjectSchema.optional() }).passthrough(); +export const FormatSchema = z.object({ + format_id: FormatReferenceStructuredObjectSchema, + name: z.string(), + description: z.string().optional(), + example_url: z.string().optional(), + accepts_parameters: z.array(FormatIDParameterSchema).optional(), + renders: z.array(z.union([z.object({ + role: z.string(), + dimensions: z.object({ + width: z.number().optional(), + height: z.number().optional(), + min_width: z.number().optional(), + min_height: z.number().optional(), + max_width: z.number().optional(), + max_height: z.number().optional(), + unit: DimensionUnitSchema.optional(), + responsive: z.object({ + width: z.boolean(), + height: z.boolean() + }).passthrough().optional(), + aspect_ratio: z.string().optional() + }).passthrough() + }).passthrough(), z.object({ + role: z.string(), + parameters_from_format_id: z.literal(true) + }).passthrough()])).optional(), + assets: z.array(FormatAssetSlotSchema).optional(), + delivery: z.object({}).passthrough().optional(), + supported_macros: z.array(z.union([UniversalMacroSchema, z.string()])).optional(), + input_format_ids: z.array(FormatReferenceStructuredObjectSchema).optional(), + output_format_ids: z.array(FormatReferenceStructuredObjectSchema).optional(), + format_card: z.object({ + format_id: FormatReferenceStructuredObjectSchema, + manifest: z.object({}).passthrough() + }).passthrough().optional(), + accessibility: z.object({ + wcag_level: WCAGLevelSchema, + requires_accessible_assets: z.boolean().optional() + }).passthrough().optional(), + supported_disclosure_positions: z.array(DisclosurePositionSchema).optional(), + disclosure_capabilities: z.array(z.object({ + position: DisclosurePositionSchema, + persistence: z.array(DisclosurePersistenceSchema) + }).passthrough()).optional(), + format_card_detailed: z.object({ + format_id: FormatReferenceStructuredObjectSchema, + manifest: z.object({}).passthrough() + }).passthrough().optional(), + reported_metrics: z.array(AvailableMetricSchema).optional(), + pricing_options: z.array(VendorPricingOptionSchema).optional() +}).passthrough(); + +export const CatalogRequirementsSchema = z.object({ + catalog_type: CatalogTypeSchema, + required: z.boolean().optional(), + min_items: z.number().optional(), + max_items: z.number().optional(), + required_fields: z.array(z.string()).optional(), + feed_formats: z.array(FeedFormatSchema).optional(), + offering_asset_constraints: z.array(OfferingAssetConstraintSchema).optional(), + field_bindings: z.array(CatalogFieldBindingSchema).optional() +}).passthrough(); + +export const ListCreativeFormatsResponseSchema = z.object({ + formats: z.array(FormatSchema), + creative_agents: z.array(z.object({ + agent_url: z.string(), + agent_name: z.string().optional(), + capabilities: z.array(CreativeAgentCapabilitySchema).optional() + }).passthrough()).optional(), + errors: z.array(ErrorSchema).optional(), + pagination: PaginationResponseSchema.optional(), + sandbox: z.boolean().optional(), + context: ContextObjectSchema.optional(), + ext: ExtensionObjectSchema.optional() +}).passthrough(); + export const ComplyTestControllerRequestSchema = z.object({ scenario: z.union([z.literal("list_scenarios"), z.literal("force_creative_status"), z.literal("force_account_status"), z.literal("force_media_buy_status"), z.literal("force_create_media_buy_arm"), z.literal("force_task_completion"), z.literal("force_session_status"), z.literal("simulate_delivery"), z.literal("simulate_budget_spend"), z.literal("seed_product"), z.literal("seed_pricing_option"), z.literal("seed_creative"), z.literal("seed_plan"), z.literal("seed_media_buy"), z.literal("seed_creative_format")]), params: z.object({ diff --git a/src/lib/types/tools.generated.ts b/src/lib/types/tools.generated.ts index db9fd2aa9..e95fd7aec 100644 --- a/src/lib/types/tools.generated.ts +++ b/src/lib/types/tools.generated.ts @@ -1,3 +1,18 @@ +import type { + AudioAssetRequirements, + CSSAssetRequirements, + DAASTAssetRequirements, + HTMLAssetRequirements, + ImageAssetRequirements, + JavaScriptAssetRequirements, + MarkdownAssetRequirements, + TextAssetRequirements, + URLAssetRequirements, + VASTAssetRequirements, + VideoAssetRequirements, + WebhookAssetRequirements, +} from './core.generated'; + // Tool Parameter and Response Types // Generated from official AdCP schemas @@ -2713,72 +2728,84 @@ export type DimensionUnit = 'px' | 'dp' | 'inches' | 'cm' | 'mm' | 'pt'; */ export type IndividualImageAsset = BaseIndividualAsset & { asset_type: 'image'; + requirements?: ImageAssetRequirements; }; /** * Video asset */ export type IndividualVideoAsset = BaseIndividualAsset & { asset_type: 'video'; + requirements?: VideoAssetRequirements; }; /** * Audio asset */ export type IndividualAudioAsset = BaseIndividualAsset & { asset_type: 'audio'; + requirements?: AudioAssetRequirements; }; /** * Text asset */ export type IndividualTextAsset = BaseIndividualAsset & { asset_type: 'text'; + requirements?: TextAssetRequirements; }; /** * Markdown asset */ export type IndividualMarkdownAsset = BaseIndividualAsset & { asset_type: 'markdown'; + requirements?: MarkdownAssetRequirements; }; /** * HTML asset */ export type IndividualHtmlAsset = BaseIndividualAsset & { asset_type: 'html'; + requirements?: HTMLAssetRequirements; }; /** * CSS asset */ export type IndividualCssAsset = BaseIndividualAsset & { asset_type: 'css'; + requirements?: CSSAssetRequirements; }; /** * JavaScript asset */ export type IndividualJavaScriptAsset = BaseIndividualAsset & { asset_type: 'javascript'; + requirements?: JavaScriptAssetRequirements; }; /** * VAST asset */ export type IndividualVastAsset = BaseIndividualAsset & { asset_type: 'vast'; + requirements?: VASTAssetRequirements; }; /** * DAAST asset */ export type IndividualDaastAsset = BaseIndividualAsset & { asset_type: 'daast'; + requirements?: DAASTAssetRequirements; }; /** * URL asset */ export type IndividualUrlAsset = BaseIndividualAsset & { asset_type: 'url'; + requirements?: URLAssetRequirements; }; /** * Webhook asset */ export type IndividualWebhookAsset = BaseIndividualAsset & { asset_type: 'webhook'; + requirements?: WebhookAssetRequirements; }; /** * Brief asset @@ -2795,51 +2822,87 @@ export type IndividualCatalogAsset = BaseIndividualAsset & { /** * Image asset in group */ -export type GroupImageAsset = BaseGroupAsset; +export type GroupImageAsset = BaseGroupAsset & { + asset_type: 'image'; + requirements?: ImageAssetRequirements; +}; /** * Video asset in group */ -export type GroupVideoAsset = BaseGroupAsset; +export type GroupVideoAsset = BaseGroupAsset & { + asset_type: 'video'; + requirements?: VideoAssetRequirements; +}; /** * Audio asset in group */ -export type GroupAudioAsset = BaseGroupAsset; +export type GroupAudioAsset = BaseGroupAsset & { + asset_type: 'audio'; + requirements?: AudioAssetRequirements; +}; /** * Text asset in group */ -export type GroupTextAsset = BaseGroupAsset; +export type GroupTextAsset = BaseGroupAsset & { + asset_type: 'text'; + requirements?: TextAssetRequirements; +}; /** * Markdown asset in group */ -export type GroupMarkdownAsset = BaseGroupAsset; +export type GroupMarkdownAsset = BaseGroupAsset & { + asset_type: 'markdown'; + requirements?: MarkdownAssetRequirements; +}; /** * HTML asset in group */ -export type GroupHtmlAsset = BaseGroupAsset; +export type GroupHtmlAsset = BaseGroupAsset & { + asset_type: 'html'; + requirements?: HTMLAssetRequirements; +}; /** * CSS asset in group */ -export type GroupCssAsset = BaseGroupAsset; +export type GroupCssAsset = BaseGroupAsset & { + asset_type: 'css'; + requirements?: CSSAssetRequirements; +}; /** * JavaScript asset in group */ -export type GroupJavaScriptAsset = BaseGroupAsset; +export type GroupJavaScriptAsset = BaseGroupAsset & { + asset_type: 'javascript'; + requirements?: JavaScriptAssetRequirements; +}; /** * VAST asset in group */ -export type GroupVastAsset = BaseGroupAsset; +export type GroupVastAsset = BaseGroupAsset & { + asset_type: 'vast'; + requirements?: VASTAssetRequirements; +}; /** * DAAST asset in group */ -export type GroupDaastAsset = BaseGroupAsset; +export type GroupDaastAsset = BaseGroupAsset & { + asset_type: 'daast'; + requirements?: DAASTAssetRequirements; +}; /** * URL asset in group */ -export type GroupUrlAsset = BaseGroupAsset; +export type GroupUrlAsset = BaseGroupAsset & { + asset_type: 'url'; + requirements?: URLAssetRequirements; +}; /** * Webhook asset in group */ -export type GroupWebhookAsset = BaseGroupAsset; +export type GroupWebhookAsset = BaseGroupAsset & { + asset_type: 'webhook'; + requirements?: WebhookAssetRequirements; +}; /** * Standardized macro placeholders for dynamic value substitution in creative tracking URLs. Macros are replaced with actual values at impression time. See docs/creative/universal-macros.mdx for detailed documentation. */ @@ -3051,23 +3114,7 @@ export interface Format { /** * Array of all assets supported for this format. Each asset is identified by its asset_id, which must be used as the key in creative manifests. Use the 'required' boolean on each asset to indicate whether it's mandatory. */ - assets?: ( - | IndividualImageAsset - | IndividualVideoAsset - | IndividualAudioAsset - | IndividualTextAsset - | IndividualMarkdownAsset - | IndividualHtmlAsset - | IndividualCssAsset - | IndividualJavaScriptAsset - | IndividualVastAsset - | IndividualDaastAsset - | IndividualUrlAsset - | IndividualWebhookAsset - | IndividualBriefAsset - | IndividualCatalogAsset - | RepeatableGroupAsset - )[]; + assets?: FormatAssetSlot[]; /** * Delivery method specifications (e.g., hosted, VAST, third-party tags) */ @@ -3245,20 +3292,7 @@ export interface RepeatableGroupAsset { /** * Assets within each repetition of this group */ - assets: ( - | GroupImageAsset - | GroupVideoAsset - | GroupAudioAsset - | GroupTextAsset - | GroupMarkdownAsset - | GroupHtmlAsset - | GroupCssAsset - | GroupJavaScriptAsset - | GroupVastAsset - | GroupDaastAsset - | GroupUrlAsset - | GroupWebhookAsset - )[]; + assets: GroupAssetSlot[]; } export interface BaseGroupAsset { /** @@ -14985,3 +15019,34 @@ export interface ControllerError { ext?: ExtensionObject; } +export type IndividualAssetSlot = + | IndividualImageAsset + | IndividualVideoAsset + | IndividualAudioAsset + | IndividualTextAsset + | IndividualMarkdownAsset + | IndividualHtmlAsset + | IndividualCssAsset + | IndividualJavaScriptAsset + | IndividualVastAsset + | IndividualDaastAsset + | IndividualUrlAsset + | IndividualWebhookAsset + | IndividualBriefAsset + | IndividualCatalogAsset; + +export type GroupAssetSlot = + | GroupImageAsset + | GroupVideoAsset + | GroupAudioAsset + | GroupTextAsset + | GroupMarkdownAsset + | GroupHtmlAsset + | GroupCssAsset + | GroupJavaScriptAsset + | GroupVastAsset + | GroupDaastAsset + | GroupUrlAsset + | GroupWebhookAsset; + +export type FormatAssetSlot = IndividualAssetSlot | RepeatableGroupAsset; diff --git a/src/lib/utils/format-asset-slot-builders.ts b/src/lib/utils/format-asset-slot-builders.ts index d7478fcfa..cad8f8eed 100644 --- a/src/lib/utils/format-asset-slot-builders.ts +++ b/src/lib/utils/format-asset-slot-builders.ts @@ -9,144 +9,134 @@ // compile-time errors at the authorship site. import type { - GroupAudioAssetSlot, - GroupBriefAssetSlot, - GroupCatalogAssetSlot, - GroupCssAssetSlot, - GroupDaastAssetSlot, - GroupHtmlAssetSlot, - GroupImageAssetSlot, - GroupJavascriptAssetSlot, - GroupMarkdownAssetSlot, - GroupTextAssetSlot, - GroupUrlAssetSlot, - GroupVastAssetSlot, - GroupVideoAssetSlot, - GroupWebhookAssetSlot, - IndividualAudioAssetSlot, - IndividualBriefAssetSlot, - IndividualCatalogAssetSlot, - IndividualCssAssetSlot, - IndividualDaastAssetSlot, - IndividualHtmlAssetSlot, - IndividualImageAssetSlot, - IndividualJavascriptAssetSlot, - IndividualMarkdownAssetSlot, - IndividualTextAssetSlot, - IndividualUrlAssetSlot, - IndividualVastAssetSlot, - IndividualVideoAssetSlot, - IndividualWebhookAssetSlot, - RepeatableGroupSlot, -} from '../types/format-asset-slots'; + GroupAudioAsset, + GroupCssAsset, + GroupDaastAsset, + GroupHtmlAsset, + GroupImageAsset, + GroupJavaScriptAsset, + GroupMarkdownAsset, + GroupTextAsset, + GroupUrlAsset, + GroupVastAsset, + GroupVideoAsset, + GroupWebhookAsset, + IndividualAudioAsset, + IndividualBriefAsset, + IndividualCatalogAsset, + IndividualCssAsset, + IndividualDaastAsset, + IndividualHtmlAsset, + IndividualImageAsset, + IndividualJavaScriptAsset, + IndividualMarkdownAsset, + IndividualTextAsset, + IndividualUrlAsset, + IndividualVastAsset, + IndividualVideoAsset, + IndividualWebhookAsset, + RepeatableGroupAsset, +} from '../types/tools.generated'; type IndividualFields = Omit; type GroupFields = Omit; // ---------- Individual asset slot builders ---------- -export function imageAssetSlot(fields: IndividualFields): IndividualImageAssetSlot { +export function imageAssetSlot(fields: IndividualFields): IndividualImageAsset { return { ...fields, item_type: 'individual', asset_type: 'image' }; } -export function videoAssetSlot(fields: IndividualFields): IndividualVideoAssetSlot { +export function videoAssetSlot(fields: IndividualFields): IndividualVideoAsset { return { ...fields, item_type: 'individual', asset_type: 'video' }; } -export function audioAssetSlot(fields: IndividualFields): IndividualAudioAssetSlot { +export function audioAssetSlot(fields: IndividualFields): IndividualAudioAsset { return { ...fields, item_type: 'individual', asset_type: 'audio' }; } -export function textAssetSlot(fields: IndividualFields): IndividualTextAssetSlot { +export function textAssetSlot(fields: IndividualFields): IndividualTextAsset { return { ...fields, item_type: 'individual', asset_type: 'text' }; } -export function markdownAssetSlot(fields: IndividualFields): IndividualMarkdownAssetSlot { +export function markdownAssetSlot(fields: IndividualFields): IndividualMarkdownAsset { return { ...fields, item_type: 'individual', asset_type: 'markdown' }; } -export function htmlAssetSlot(fields: IndividualFields): IndividualHtmlAssetSlot { +export function htmlAssetSlot(fields: IndividualFields): IndividualHtmlAsset { return { ...fields, item_type: 'individual', asset_type: 'html' }; } -export function cssAssetSlot(fields: IndividualFields): IndividualCssAssetSlot { +export function cssAssetSlot(fields: IndividualFields): IndividualCssAsset { return { ...fields, item_type: 'individual', asset_type: 'css' }; } -export function javascriptAssetSlot( - fields: IndividualFields -): IndividualJavascriptAssetSlot { +export function javascriptAssetSlot(fields: IndividualFields): IndividualJavaScriptAsset { return { ...fields, item_type: 'individual', asset_type: 'javascript' }; } -export function vastAssetSlot(fields: IndividualFields): IndividualVastAssetSlot { +export function vastAssetSlot(fields: IndividualFields): IndividualVastAsset { return { ...fields, item_type: 'individual', asset_type: 'vast' }; } -export function daastAssetSlot(fields: IndividualFields): IndividualDaastAssetSlot { +export function daastAssetSlot(fields: IndividualFields): IndividualDaastAsset { return { ...fields, item_type: 'individual', asset_type: 'daast' }; } -export function urlAssetSlot(fields: IndividualFields): IndividualUrlAssetSlot { +export function urlAssetSlot(fields: IndividualFields): IndividualUrlAsset { return { ...fields, item_type: 'individual', asset_type: 'url' }; } -export function webhookAssetSlot(fields: IndividualFields): IndividualWebhookAssetSlot { +export function webhookAssetSlot(fields: IndividualFields): IndividualWebhookAsset { return { ...fields, item_type: 'individual', asset_type: 'webhook' }; } -export function briefAssetSlot(fields: IndividualFields): IndividualBriefAssetSlot { +export function briefAssetSlot(fields: IndividualFields): IndividualBriefAsset { return { ...fields, item_type: 'individual', asset_type: 'brief' }; } -export function catalogAssetSlot(fields: IndividualFields): IndividualCatalogAssetSlot { +export function catalogAssetSlot(fields: IndividualFields): IndividualCatalogAsset { return { ...fields, item_type: 'individual', asset_type: 'catalog' }; } // ---------- Group asset slot builders (for use inside repeatableGroup) ---------- -export function imageGroupAsset(fields: GroupFields): GroupImageAssetSlot { +export function imageGroupAsset(fields: GroupFields): GroupImageAsset { return { ...fields, asset_type: 'image' }; } -export function videoGroupAsset(fields: GroupFields): GroupVideoAssetSlot { +export function videoGroupAsset(fields: GroupFields): GroupVideoAsset { return { ...fields, asset_type: 'video' }; } -export function audioGroupAsset(fields: GroupFields): GroupAudioAssetSlot { +export function audioGroupAsset(fields: GroupFields): GroupAudioAsset { return { ...fields, asset_type: 'audio' }; } -export function textGroupAsset(fields: GroupFields): GroupTextAssetSlot { +export function textGroupAsset(fields: GroupFields): GroupTextAsset { return { ...fields, asset_type: 'text' }; } -export function markdownGroupAsset(fields: GroupFields): GroupMarkdownAssetSlot { +export function markdownGroupAsset(fields: GroupFields): GroupMarkdownAsset { return { ...fields, asset_type: 'markdown' }; } -export function htmlGroupAsset(fields: GroupFields): GroupHtmlAssetSlot { +export function htmlGroupAsset(fields: GroupFields): GroupHtmlAsset { return { ...fields, asset_type: 'html' }; } -export function cssGroupAsset(fields: GroupFields): GroupCssAssetSlot { +export function cssGroupAsset(fields: GroupFields): GroupCssAsset { return { ...fields, asset_type: 'css' }; } -export function javascriptGroupAsset(fields: GroupFields): GroupJavascriptAssetSlot { +export function javascriptGroupAsset(fields: GroupFields): GroupJavaScriptAsset { return { ...fields, asset_type: 'javascript' }; } -export function vastGroupAsset(fields: GroupFields): GroupVastAssetSlot { +export function vastGroupAsset(fields: GroupFields): GroupVastAsset { return { ...fields, asset_type: 'vast' }; } -export function daastGroupAsset(fields: GroupFields): GroupDaastAssetSlot { +export function daastGroupAsset(fields: GroupFields): GroupDaastAsset { return { ...fields, asset_type: 'daast' }; } -export function urlGroupAsset(fields: GroupFields): GroupUrlAssetSlot { +export function urlGroupAsset(fields: GroupFields): GroupUrlAsset { return { ...fields, asset_type: 'url' }; } -export function webhookGroupAsset(fields: GroupFields): GroupWebhookAssetSlot { +export function webhookGroupAsset(fields: GroupFields): GroupWebhookAsset { return { ...fields, asset_type: 'webhook' }; } -export function briefGroupAsset(fields: GroupFields): GroupBriefAssetSlot { - return { ...fields, asset_type: 'brief' }; -} -export function catalogGroupAsset(fields: GroupFields): GroupCatalogAssetSlot { - return { ...fields, asset_type: 'catalog' }; -} // ---------- Repeatable group builder ---------- @@ -156,7 +146,7 @@ export function catalogGroupAsset(fields: GroupFields): G * frames, product showcases. The platform repeats the inner `assets` once * per item; each repetition must provide all required assets within it. */ -export function repeatableGroup(fields: Omit): RepeatableGroupSlot { +export function repeatableGroup(fields: Omit): RepeatableGroupAsset { return { ...fields, item_type: 'repeatable_group' }; } @@ -193,6 +183,4 @@ export const FormatAsset = { groupDaast: daastGroupAsset, groupUrl: urlGroupAsset, groupWebhook: webhookGroupAsset, - groupBrief: briefGroupAsset, - groupCatalog: catalogGroupAsset, } as const;