@adcp/sdk 14.0.0-beta.8 → 14.0.0-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/core/AgentClient.d.ts.map +1 -1
- package/dist/lib/core/ConversationTypes.d.mts +8 -0
- package/dist/lib/core/ConversationTypes.d.ts +8 -0
- package/dist/lib/core/ConversationTypes.d.ts.map +1 -1
- package/dist/lib/core/ConversationTypes.js.map +1 -1
- package/dist/lib/core/SingleAgentClient.d.ts.map +1 -1
- package/dist/lib/core/SingleAgentClient.js +30 -3
- package/dist/lib/core/SingleAgentClient.js.map +1 -1
- package/dist/lib/core/SingleAgentClient.mjs +30 -3
- package/dist/lib/core/SingleAgentClient.mjs.map +1 -1
- package/dist/lib/core/TaskExecutor.d.ts.map +1 -1
- package/dist/lib/core/TaskExecutor.js +32 -5
- package/dist/lib/core/TaskExecutor.js.map +1 -1
- package/dist/lib/core/TaskExecutor.mjs +32 -5
- package/dist/lib/core/TaskExecutor.mjs.map +1 -1
- package/dist/lib/index.d.mts +2 -2
- package/dist/lib/index.d.ts +2 -2
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +2 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +2 -1
- package/dist/lib/index.mjs.map +1 -1
- package/dist/lib/schemas/index.d.mts +14 -0
- package/dist/lib/schemas/index.d.ts +14 -0
- package/dist/lib/schemas/index.d.ts.map +1 -1
- package/dist/lib/schemas/index.js +13 -1
- package/dist/lib/schemas/index.js.map +1 -1
- package/dist/lib/schemas/index.mjs +13 -1
- package/dist/lib/schemas/index.mjs.map +1 -1
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/adcp-server.d.mts +1 -0
- package/dist/lib/server/adcp-server.d.ts +1 -0
- package/dist/lib/server/adcp-server.d.ts.map +1 -1
- package/dist/lib/server/adcp-server.js +1 -1
- package/dist/lib/server/adcp-server.js.map +1 -1
- package/dist/lib/server/adcp-server.mjs +1 -1
- package/dist/lib/server/adcp-server.mjs.map +1 -1
- package/dist/lib/server/create-adcp-server.d.mts +10 -2
- package/dist/lib/server/create-adcp-server.d.ts +10 -2
- package/dist/lib/server/create-adcp-server.d.ts.map +1 -1
- package/dist/lib/server/create-adcp-server.js +26 -19
- package/dist/lib/server/create-adcp-server.js.map +1 -1
- package/dist/lib/server/create-adcp-server.mjs +26 -26
- package/dist/lib/server/create-adcp-server.mjs.map +1 -1
- package/dist/lib/server/decisioning/capabilities.d.mts +15 -1
- package/dist/lib/server/decisioning/capabilities.d.ts +15 -1
- package/dist/lib/server/decisioning/capabilities.d.ts.map +1 -1
- package/dist/lib/server/decisioning/capabilities.js.map +1 -1
- package/dist/lib/server/decisioning/capabilities.mjs.map +1 -1
- package/dist/lib/server/decisioning/index.d.mts +2 -2
- package/dist/lib/server/decisioning/index.d.ts +2 -2
- package/dist/lib/server/decisioning/index.d.ts.map +1 -1
- package/dist/lib/server/decisioning/index.js +2 -0
- package/dist/lib/server/decisioning/index.js.map +1 -1
- package/dist/lib/server/decisioning/index.mjs +2 -0
- package/dist/lib/server/decisioning/index.mjs.map +1 -1
- package/dist/lib/server/decisioning/proposal/types.d.mts +3 -2
- package/dist/lib/server/decisioning/proposal/types.d.ts +3 -2
- package/dist/lib/server/decisioning/proposal/types.d.ts.map +1 -1
- package/dist/lib/server/decisioning/proposal/types.js.map +1 -1
- package/dist/lib/server/decisioning/proposal/types.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.d.mts +14 -1
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts +14 -1
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.js +402 -9
- package/dist/lib/server/decisioning/runtime/from-platform.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +405 -9
- package/dist/lib/server/decisioning/runtime/from-platform.mjs.map +1 -1
- package/dist/lib/server/decisioning/runtime/validate-platform.d.mts +1 -1
- package/dist/lib/server/decisioning/runtime/validate-platform.d.ts +1 -1
- package/dist/lib/server/decisioning/runtime/validate-platform.d.ts.map +1 -1
- package/dist/lib/server/decisioning/runtime/validate-platform.js +2 -2
- package/dist/lib/server/decisioning/runtime/validate-platform.js.map +1 -1
- package/dist/lib/server/decisioning/runtime/validate-platform.mjs +2 -2
- package/dist/lib/server/decisioning/runtime/validate-platform.mjs.map +1 -1
- package/dist/lib/server/decisioning/specialisms/sales.d.mts +7 -1
- package/dist/lib/server/decisioning/specialisms/sales.d.ts +7 -1
- package/dist/lib/server/decisioning/specialisms/sales.d.ts.map +1 -1
- package/dist/lib/server/decisioning/specialisms/sales.js.map +1 -1
- package/dist/lib/storage/interfaces.d.mts +2 -0
- package/dist/lib/storage/interfaces.d.ts +2 -0
- package/dist/lib/storage/interfaces.d.ts.map +1 -1
- package/dist/lib/storage/interfaces.js.map +1 -1
- package/dist/lib/testing/compliance/comply.d.mts +18 -0
- package/dist/lib/testing/compliance/comply.d.ts +18 -0
- package/dist/lib/testing/compliance/comply.d.ts.map +1 -1
- package/dist/lib/testing/compliance/comply.js +30 -5
- package/dist/lib/testing/compliance/comply.js.map +1 -1
- package/dist/lib/testing/compliance/comply.mjs +28 -4
- package/dist/lib/testing/compliance/comply.mjs.map +1 -1
- package/dist/lib/testing/compliance/index.d.mts +1 -1
- package/dist/lib/testing/compliance/index.d.ts +1 -1
- package/dist/lib/testing/compliance/index.d.ts.map +1 -1
- package/dist/lib/testing/compliance/index.js +4 -2
- package/dist/lib/testing/compliance/index.js.map +1 -1
- package/dist/lib/testing/compliance/index.mjs +4 -2
- package/dist/lib/testing/compliance/index.mjs.map +1 -1
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/types/list-creatives.d.ts +129 -6
- package/dist/lib/types/schemas.generated.d.ts +411 -16
- package/dist/lib/types/schemas.generated.d.ts.map +1 -1
- package/dist/lib/types/schemas.generated.js +22 -6
- package/dist/lib/types/schemas.generated.js.map +1 -1
- package/dist/lib/types/schemas.generated.mjs +22 -6
- package/dist/lib/types/schemas.generated.mjs.map +1 -1
- package/dist/lib/types/tools.generated.d.mts +80 -6
- package/dist/lib/types/tools.generated.d.ts +80 -6
- package/dist/lib/types/tools.generated.d.ts.map +1 -1
- package/dist/lib/types/tools.generated.js.map +1 -1
- package/dist/lib/utils/adcp-version-config.d.mts +12 -0
- package/dist/lib/utils/adcp-version-config.d.ts +12 -0
- package/dist/lib/utils/adcp-version-config.d.ts.map +1 -1
- package/dist/lib/utils/adcp-version-config.js +5 -3
- package/dist/lib/utils/adcp-version-config.js.map +1 -1
- package/dist/lib/utils/adcp-version-config.mjs +4 -3
- package/dist/lib/utils/adcp-version-config.mjs.map +1 -1
- package/dist/lib/utils/pricing-adapter.d.mts +2 -0
- package/dist/lib/utils/pricing-adapter.d.ts +2 -0
- package/dist/lib/utils/pricing-adapter.d.ts.map +1 -1
- package/dist/lib/utils/pricing-adapter.js +68 -1
- package/dist/lib/utils/pricing-adapter.js.map +1 -1
- package/dist/lib/utils/pricing-adapter.mjs +67 -1
- package/dist/lib/utils/pricing-adapter.mjs.map +1 -1
- package/dist/lib/v2/projection/index.d.mts +1 -1
- package/dist/lib/v2/projection/index.d.ts +1 -1
- package/dist/lib/v2/projection/index.d.ts.map +1 -1
- package/dist/lib/v2/projection/index.js.map +1 -1
- package/dist/lib/v2/projection/index.mjs.map +1 -1
- package/dist/lib/v2/projection/v1-to-v2.d.mts +17 -3
- package/dist/lib/v2/projection/v1-to-v2.d.ts +17 -3
- package/dist/lib/v2/projection/v1-to-v2.d.ts.map +1 -1
- package/dist/lib/v2/projection/v1-to-v2.js.map +1 -1
- package/dist/lib/v2/projection/v1-to-v2.mjs.map +1 -1
- package/dist/lib/validation/schema-loader.d.mts +17 -0
- package/dist/lib/validation/schema-loader.d.ts +17 -0
- package/dist/lib/validation/schema-loader.d.ts.map +1 -1
- package/dist/lib/validation/schema-loader.js +24 -0
- package/dist/lib/validation/schema-loader.js.map +1 -1
- package/dist/lib/validation/schema-loader.mjs +23 -0
- package/dist/lib/validation/schema-loader.mjs.map +1 -1
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.js.map +1 -1
- package/dist/lib/version.mjs +3 -3
- package/dist/lib/version.mjs.map +1 -1
- package/docs/llms.txt +2 -2
- package/docs/migration-13-to-14.md +59 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/utils/pricing-adapter.ts"],"sourcesContent":["/**\n * Pricing Option Adapter\n *\n * Handles conversion between v2.x and v3 pricing option field names.\n * The library exposes only v3 API (fixed_price, floor_price) to clients,\n * and internally adapts requests for v2.x servers.\n *\n * Field mappings:\n * - v3 fixed_price ↔ v2 rate (for fixed pricing)\n * - v3 floor_price ↔ v2 price_guidance.floor (for auction pricing)\n * - v3 presence of fixed_price ↔ v2 is_fixed: true/false\n */\n\n/**\n * v3 price guidance (percentiles only, floor moved to top level)\n */\nexport interface PriceGuidanceV3 {\n p25?: number;\n p50?: number;\n p75?: number;\n p90?: number;\n}\n\n/**\n * v2 price guidance (includes floor)\n */\nexport interface PriceGuidanceV2 {\n floor?: number;\n p25?: number;\n p50?: number;\n p75?: number;\n p90?: number;\n}\n\n/**\n * v3 pricing option structure\n */\nexport interface PricingOptionV3 {\n pricing_option_id: string;\n pricing_model: string;\n currency: string;\n /** Fixed price - if present, this is fixed pricing */\n fixed_price?: number;\n /** Floor price for auction - mutually exclusive with fixed_price */\n floor_price?: number;\n /** Percentile hints for auction bidding */\n price_guidance?: PriceGuidanceV3;\n min_spend_per_package?: number;\n parameters?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\n/**\n * v2 pricing option structure\n */\nexport interface PricingOptionV2 {\n pricing_option_id: string;\n pricing_model: string;\n currency: string;\n /** Fixed rate (v2 name for fixed_price) */\n rate?: number;\n /** Boolean discriminator for fixed vs auction */\n is_fixed?: boolean;\n /** Price guidance including floor */\n price_guidance?: PriceGuidanceV2;\n min_spend_per_package?: number;\n parameters?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\n/**\n * Check if a pricing option uses v2 field names\n */\nexport function usesV2PricingFields(option: any): boolean {\n if (!option || typeof option !== 'object') return false;\n // v2 uses 'rate' or 'is_fixed' or has floor inside price_guidance\n return option.rate !== undefined || option.is_fixed !== undefined || option.price_guidance?.floor !== undefined;\n}\n\n/**\n * Check if a pricing option uses v3 field names\n */\nexport function usesV3PricingFields(option: any): boolean {\n if (!option || typeof option !== 'object') return false;\n // v3 uses fixed_price or floor_price at top level\n return option.fixed_price !== undefined || option.floor_price !== undefined;\n}\n\n/**\n * Detect if a pricing option is fixed pricing (works with v2 or v3)\n */\nexport function isFixedPricing(option: PricingOptionV2 | PricingOptionV3): boolean {\n // v3: presence of fixed_price indicates fixed pricing\n if ((option as PricingOptionV3).fixed_price !== undefined) {\n return true;\n }\n // v2: is_fixed boolean\n if ((option as PricingOptionV2).is_fixed !== undefined) {\n return (option as PricingOptionV2).is_fixed!;\n }\n // v2: presence of rate without is_fixed defaults to fixed\n if ((option as PricingOptionV2).rate !== undefined) {\n return true;\n }\n return false;\n}\n\n/**\n * Detect if a pricing option is CPA (cost per acquisition) pricing\n */\nexport function isCPAPricing(option: PricingOptionV2 | PricingOptionV3): boolean {\n return option?.pricing_model === 'cpa';\n}\n\n/**\n * Get the price value from a pricing option (works with v2 or v3)\n */\nexport function getPrice(option: PricingOptionV2 | PricingOptionV3): number | undefined {\n // v3 field takes precedence\n if ((option as PricingOptionV3).fixed_price !== undefined) {\n return (option as PricingOptionV3).fixed_price;\n }\n // Fall back to v2 field\n return (option as PricingOptionV2).rate;\n}\n\n/**\n * Get the floor price from a pricing option (works with v2 or v3)\n */\nexport function getFloorPrice(option: PricingOptionV2 | PricingOptionV3): number | undefined {\n // v3 field takes precedence\n if ((option as PricingOptionV3).floor_price !== undefined) {\n return (option as PricingOptionV3).floor_price;\n }\n // Fall back to v2 field (inside price_guidance)\n return (option as PricingOptionV2).price_guidance?.floor;\n}\n\n/**\n * Adapt a v3-style pricing option for a v2 server.\n * Converts fixed_price → rate, floor_price → price_guidance.floor\n */\nexport function adaptPricingOptionForV2(option: PricingOptionV3): PricingOptionV2 {\n // Already v2 format or no v3 fields\n if (!usesV3PricingFields(option)) {\n return option as unknown as PricingOptionV2;\n }\n\n const { fixed_price, floor_price, price_guidance, ...rest } = option;\n\n const result: PricingOptionV2 = { ...rest } as PricingOptionV2;\n\n if (fixed_price !== undefined) {\n // Fixed pricing\n result.rate = fixed_price;\n result.is_fixed = true;\n } else {\n // Auction pricing\n result.is_fixed = false;\n\n // Build v2 price_guidance with floor inside\n if (floor_price !== undefined || price_guidance) {\n result.price_guidance = {\n ...(price_guidance || {}),\n };\n if (floor_price !== undefined) {\n result.price_guidance.floor = floor_price;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Normalize a v2-style pricing option to v3.\n * Converts rate → fixed_price, price_guidance.floor → floor_price\n */\nexport function normalizePricingOption(option: PricingOptionV2 | PricingOptionV3): PricingOptionV3 {\n // Already v3 format\n if (usesV3PricingFields(option) && !usesV2PricingFields(option)) {\n return option as PricingOptionV3;\n }\n\n const v2Option = option as PricingOptionV2;\n const { rate, is_fixed, price_guidance, ...rest } = v2Option;\n\n const result: PricingOptionV3 = { ...rest } as PricingOptionV3;\n\n // Convert rate → fixed_price (for fixed pricing)\n if (rate !== undefined && (is_fixed === true || is_fixed === undefined)) {\n result.fixed_price = rate;\n }\n\n // Convert price_guidance.floor → floor_price (for auction pricing)\n if (price_guidance) {\n const { floor, ...percentiles } = price_guidance;\n\n if (floor !== undefined) {\n result.floor_price = floor;\n }\n\n // Keep percentiles in price_guidance if any exist\n if (Object.keys(percentiles).length > 0) {\n result.price_guidance = percentiles;\n }\n }\n\n return result;\n}\n\n/**\n * Adapt all pricing options in a product for v2 server\n */\nexport function adaptProductPricingForV2(product: any): any {\n if (!product?.pricing_options || !Array.isArray(product.pricing_options)) {\n return product;\n }\n\n return {\n ...product,\n pricing_options: product.pricing_options.map(adaptPricingOptionForV2),\n };\n}\n\n/**\n * Normalize all pricing options in a product to v3\n */\nexport function normalizeProductPricing(product: any): any {\n if (!product?.pricing_options || !Array.isArray(product.pricing_options)) {\n return product;\n }\n\n return {\n ...product,\n pricing_options: product.pricing_options.map(normalizePricingOption),\n };\n}\n\n/**\n * Adapt a get_products request for a v2 server.\n *\n * Converts v3 fields to their v2 equivalents:\n * - brand (BrandReference) → brand_manifest (base domain URL string)\n * - catalog → promoted_offerings (type='offering') or promoted_offerings.product_selectors (type='product')\n * - channels in filters → v2 channel names\n *\n * Strips v3-only fields v2 agents don't understand:\n * - buying_mode, buyer_campaign_ref, property_list, account_id, pagination (top-level)\n * - filters: required_features, required_axe_integrations, required_geo_targeting,\n * signal_targeting, regions, metros\n */\nexport function adaptGetProductsRequestForV2(request: any): any {\n const adapted: any = { ...request };\n\n // Convert v3 brand (BrandReference) → v2 brand_manifest (bare domain URL).\n // v2 servers resolve brand info from the base domain URL.\n if (adapted.brand?.domain) {\n adapted.brand_manifest = `https://${adapted.brand.domain}`;\n delete adapted.brand;\n }\n\n // Convert v3 catalog → v2 promoted_offerings\n if (adapted.catalog) {\n const catalog = adapted.catalog;\n if (catalog.type === 'product') {\n adapted.promoted_offerings = {\n product_selectors: {\n ...(catalog.gtins?.length && { manifest_gtins: catalog.gtins }),\n ...(catalog.ids?.length && { manifest_skus: catalog.ids }),\n ...(catalog.tags?.length && { manifest_tags: catalog.tags }),\n ...(catalog.category && { manifest_category: catalog.category }),\n ...(catalog.query && { manifest_query: catalog.query }),\n },\n };\n } else if (catalog.type === 'offering') {\n adapted.promoted_offerings = {\n ...(catalog.items?.length && { offerings: catalog.items }),\n };\n }\n delete adapted.catalog;\n }\n\n // Map v3 channel names to v2 equivalents\n if (adapted.filters?.channels) {\n const v2ChannelMap: Record<string, string> = {\n olv: 'video',\n ctv: 'video',\n streaming_audio: 'audio',\n retail_media: 'retail',\n };\n // Deduplicate after mapping (e.g. olv+ctv both become 'video')\n const mapped = adapted.filters.channels.map((ch: string) => v2ChannelMap[ch] ?? ch);\n adapted.filters = {\n ...adapted.filters,\n channels: [...new Set(mapped)],\n };\n }\n\n // Strip v3-only filter fields (format_ids exists in both v2 and v3, keep it)\n if (adapted.filters) {\n const {\n required_features,\n required_axe_integrations,\n required_geo_targeting,\n signal_targeting,\n regions,\n metros,\n ...v2Filters\n } = adapted.filters;\n adapted.filters = v2Filters;\n }\n\n // Strip v3-only top-level fields\n delete adapted.buying_mode;\n delete adapted.buyer_campaign_ref;\n delete adapted.property_list;\n delete adapted.account;\n delete adapted.pagination;\n delete adapted.adcp_major_version;\n\n return adapted;\n}\n\n/**\n * Normalize v2 channel names on a product to v3.\n * v2 used coarser buckets; some map one-to-many (e.g. 'video' → ['olv', 'ctv']).\n */\nexport function normalizeProductChannels(product: any): any {\n if (!product?.channels || !Array.isArray(product.channels)) {\n return product;\n }\n\n const v3ChannelMap: Record<string, string[]> = {\n video: ['olv', 'ctv'],\n audio: ['streaming_audio'],\n native: ['display'],\n retail: ['retail_media'],\n };\n\n const normalized = product.channels.flatMap((ch: string) => v3ChannelMap[ch] ?? [ch]);\n return { ...product, channels: [...new Set(normalized)] };\n}\n\n/**\n * Normalize all products in a get_products response to v3\n */\nexport function normalizeGetProductsResponse(response: any): any {\n // If there's no products field at all, this may be an error response — pass through\n if (!('products' in (response ?? {}))) {\n return response;\n }\n\n // If products exists but isn't an array, the response is malformed\n if (!Array.isArray(response.products)) {\n return {\n errors: [\n {\n code: 'invalid_response',\n message: `Expected products to be an array, got ${typeof response.products}`,\n },\n ],\n };\n }\n\n return {\n ...response,\n products: response.products.map((p: any) => normalizeProductChannels(normalizeProductPricing(p))),\n };\n}\n\n/**\n * Adapt a package request's pricing option selection for v2 server.\n * This handles bid_price which references pricing option floor semantics.\n */\nexport function adaptPackagePricingForV2(pkg: any): any {\n // Package requests don't typically contain pricing_options,\n // but they do contain pricing_option_id which selects one.\n // No transformation needed for bid_price - it's the same in both versions.\n return pkg;\n}\n\n/**\n * Adapt a create_media_buy request for v2 server (pricing fields)\n */\nexport function adaptMediaBuyPricingForV2(request: any): any {\n // Media buy requests select pricing options by ID, not by defining them.\n // No pricing field transformation needed in requests.\n return request;\n}\n\n/**\n * Normalize a media buy response's package pricing to v3\n */\nexport function normalizeMediaBuyPricingResponse(response: any): any {\n // Media buy responses may include products with pricing_options\n if (response?.products && Array.isArray(response.products)) {\n return {\n ...response,\n products: response.products.map(normalizeProductPricing),\n };\n }\n return response;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/utils/pricing-adapter.ts"],"sourcesContent":["/**\n * Pricing Option Adapter\n *\n * Handles conversion between v2.x and v3 pricing option field names.\n * The library exposes only v3 API (fixed_price, floor_price) to clients,\n * and internally adapts requests for v2.x servers.\n *\n * Field mappings:\n * - v3 fixed_price ↔ v2 rate (for fixed pricing)\n * - v3 floor_price ↔ v2 price_guidance.floor (for auction pricing)\n * - v3 presence of fixed_price ↔ v2 is_fixed: true/false\n */\n\n/**\n * v3 price guidance (percentiles only, floor moved to top level)\n */\nexport interface PriceGuidanceV3 {\n p25?: number;\n p50?: number;\n p75?: number;\n p90?: number;\n}\n\n/**\n * v2 price guidance (includes floor)\n */\nexport interface PriceGuidanceV2 {\n floor?: number;\n p25?: number;\n p50?: number;\n p75?: number;\n p90?: number;\n}\n\n/**\n * v3 pricing option structure\n */\nexport interface PricingOptionV3 {\n pricing_option_id: string;\n pricing_model: string;\n currency: string;\n /** Fixed price - if present, this is fixed pricing */\n fixed_price?: number;\n /** Floor price for auction - mutually exclusive with fixed_price */\n floor_price?: number;\n /** Percentile hints for auction bidding */\n price_guidance?: PriceGuidanceV3;\n min_spend_per_package?: number;\n parameters?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\n/**\n * v2 pricing option structure\n */\nexport interface PricingOptionV2 {\n pricing_option_id: string;\n pricing_model: string;\n currency: string;\n /** Fixed rate (v2 name for fixed_price) */\n rate?: number;\n /** Boolean discriminator for fixed vs auction */\n is_fixed?: boolean;\n /** Price guidance including floor */\n price_guidance?: PriceGuidanceV2;\n min_spend_per_package?: number;\n parameters?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\n/**\n * Check if a pricing option uses v2 field names\n */\nexport function usesV2PricingFields(option: any): boolean {\n if (!option || typeof option !== 'object') return false;\n // v2 uses 'rate' or 'is_fixed' or has floor inside price_guidance\n return option.rate !== undefined || option.is_fixed !== undefined || option.price_guidance?.floor !== undefined;\n}\n\n/**\n * Check if a pricing option uses v3 field names\n */\nexport function usesV3PricingFields(option: any): boolean {\n if (!option || typeof option !== 'object') return false;\n // v3 uses fixed_price or floor_price at top level\n return option.fixed_price !== undefined || option.floor_price !== undefined;\n}\n\n/**\n * Detect if a pricing option is fixed pricing (works with v2 or v3)\n */\nexport function isFixedPricing(option: PricingOptionV2 | PricingOptionV3): boolean {\n // v3: presence of fixed_price indicates fixed pricing\n if ((option as PricingOptionV3).fixed_price !== undefined) {\n return true;\n }\n // v2: is_fixed boolean\n if ((option as PricingOptionV2).is_fixed !== undefined) {\n return (option as PricingOptionV2).is_fixed!;\n }\n // v2: presence of rate without is_fixed defaults to fixed\n if ((option as PricingOptionV2).rate !== undefined) {\n return true;\n }\n return false;\n}\n\n/**\n * Detect if a pricing option is CPA (cost per acquisition) pricing\n */\nexport function isCPAPricing(option: PricingOptionV2 | PricingOptionV3): boolean {\n return option?.pricing_model === 'cpa';\n}\n\n/**\n * Get the price value from a pricing option (works with v2 or v3)\n */\nexport function getPrice(option: PricingOptionV2 | PricingOptionV3): number | undefined {\n // v3 field takes precedence\n if ((option as PricingOptionV3).fixed_price !== undefined) {\n return (option as PricingOptionV3).fixed_price;\n }\n // Fall back to v2 field\n return (option as PricingOptionV2).rate;\n}\n\n/**\n * Get the floor price from a pricing option (works with v2 or v3)\n */\nexport function getFloorPrice(option: PricingOptionV2 | PricingOptionV3): number | undefined {\n // v3 field takes precedence\n if ((option as PricingOptionV3).floor_price !== undefined) {\n return (option as PricingOptionV3).floor_price;\n }\n // Fall back to v2 field (inside price_guidance)\n return (option as PricingOptionV2).price_guidance?.floor;\n}\n\n/**\n * Adapt a v3-style pricing option for a v2 server.\n * Converts fixed_price → rate, floor_price → price_guidance.floor\n */\nexport function adaptPricingOptionForV2(option: PricingOptionV3): PricingOptionV2 {\n // Already v2 format or no v3 fields\n if (!usesV3PricingFields(option)) {\n return option as unknown as PricingOptionV2;\n }\n\n const { fixed_price, floor_price, price_guidance, ...rest } = option;\n\n const result: PricingOptionV2 = { ...rest } as PricingOptionV2;\n\n if (fixed_price !== undefined) {\n // Fixed pricing\n result.rate = fixed_price;\n result.is_fixed = true;\n } else {\n // Auction pricing\n result.is_fixed = false;\n\n // Build v2 price_guidance with floor inside\n if (floor_price !== undefined || price_guidance) {\n result.price_guidance = {\n ...(price_guidance || {}),\n };\n if (floor_price !== undefined) {\n result.price_guidance.floor = floor_price;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Normalize a v2-style pricing option to v3.\n * Converts rate → fixed_price, price_guidance.floor → floor_price\n */\nexport function normalizePricingOption(option: PricingOptionV2 | PricingOptionV3): PricingOptionV3 {\n // Already v3 format\n if (usesV3PricingFields(option) && !usesV2PricingFields(option)) {\n return option as PricingOptionV3;\n }\n\n const v2Option = option as PricingOptionV2;\n const { rate, is_fixed, price_guidance, ...rest } = v2Option;\n\n const result: PricingOptionV3 = { ...rest } as PricingOptionV3;\n\n // Convert rate → fixed_price (for fixed pricing)\n if (rate !== undefined && (is_fixed === true || is_fixed === undefined)) {\n result.fixed_price = rate;\n }\n\n // Convert price_guidance.floor → floor_price (for auction pricing)\n if (price_guidance) {\n const { floor, ...percentiles } = price_guidance;\n\n if (floor !== undefined) {\n result.floor_price = floor;\n }\n\n // Keep percentiles in price_guidance if any exist\n if (Object.keys(percentiles).length > 0) {\n result.price_guidance = percentiles;\n }\n }\n\n return result;\n}\n\n/**\n * Adapt all pricing options in a product for v2 server\n */\nexport function adaptProductPricingForV2(product: any): any {\n if (!product?.pricing_options || !Array.isArray(product.pricing_options)) {\n return product;\n }\n\n return {\n ...product,\n pricing_options: product.pricing_options.map(adaptPricingOptionForV2),\n };\n}\n\n/**\n * Normalize all pricing options in a product to v3\n */\nexport function normalizeProductPricing(product: any): any {\n if (!product?.pricing_options || !Array.isArray(product.pricing_options)) {\n return product;\n }\n\n return {\n ...product,\n pricing_options: product.pricing_options.map(normalizePricingOption),\n };\n}\n\n/**\n * Adapt a get_products request for a v2 server.\n *\n * Converts v3 fields to their v2 equivalents:\n * - brand (BrandReference) → brand_manifest (base domain URL string)\n * - catalog → promoted_offerings (type='offering') or promoted_offerings.product_selectors (type='product')\n * - channels in filters → v2 channel names\n *\n * Strips v3-only fields v2 agents don't understand:\n * - buying_mode, buyer_campaign_ref, property_list, account_id, pagination (top-level)\n * - filters: required_features, required_axe_integrations, required_geo_targeting,\n * signal_targeting, regions, metros\n */\nexport function adaptGetProductsRequestForV2(request: any): any {\n const adapted: any = { ...request };\n\n // Convert v3 brand (BrandReference) → v2 brand_manifest (bare domain URL).\n // v2 servers resolve brand info from the base domain URL.\n if (adapted.brand?.domain) {\n adapted.brand_manifest = `https://${adapted.brand.domain}`;\n delete adapted.brand;\n }\n\n // Convert v3 catalog → v2 promoted_offerings\n if (adapted.catalog) {\n const catalog = adapted.catalog;\n if (catalog.type === 'product') {\n adapted.promoted_offerings = {\n product_selectors: {\n ...(catalog.gtins?.length && { manifest_gtins: catalog.gtins }),\n ...(catalog.ids?.length && { manifest_skus: catalog.ids }),\n ...(catalog.tags?.length && { manifest_tags: catalog.tags }),\n ...(catalog.category && { manifest_category: catalog.category }),\n ...(catalog.query && { manifest_query: catalog.query }),\n },\n };\n } else if (catalog.type === 'offering') {\n adapted.promoted_offerings = {\n ...(catalog.items?.length && { offerings: catalog.items }),\n };\n }\n delete adapted.catalog;\n }\n\n // Map v3 channel names to v2 equivalents\n if (adapted.filters?.channels) {\n const v2ChannelMap: Record<string, string> = {\n olv: 'video',\n ctv: 'video',\n streaming_audio: 'audio',\n retail_media: 'retail',\n };\n // Deduplicate after mapping (e.g. olv+ctv both become 'video')\n const mapped = adapted.filters.channels.map((ch: string) => v2ChannelMap[ch] ?? ch);\n adapted.filters = {\n ...adapted.filters,\n channels: [...new Set(mapped)],\n };\n }\n\n // Strip v3-only filter fields (format_ids exists in both v2 and v3, keep it)\n if (adapted.filters) {\n const {\n required_features,\n required_axe_integrations,\n required_geo_targeting,\n signal_targeting,\n regions,\n metros,\n ...v2Filters\n } = adapted.filters;\n adapted.filters = v2Filters;\n }\n\n // Strip v3-only top-level fields\n delete adapted.buying_mode;\n delete adapted.buyer_campaign_ref;\n delete adapted.property_list;\n delete adapted.account;\n delete adapted.pagination;\n delete adapted.adcp_major_version;\n\n return adapted;\n}\n\n/**\n * Normalize v2 channel names on a product to v3.\n * v2 used coarser buckets; some map one-to-many (e.g. 'video' → ['olv', 'ctv']).\n */\nexport function normalizeProductChannels(product: any): any {\n if (!product?.channels || !Array.isArray(product.channels)) {\n return product;\n }\n\n const v3ChannelMap: Record<string, string[]> = {\n video: ['olv', 'ctv'],\n audio: ['streaming_audio'],\n native: ['display'],\n retail: ['retail_media'],\n };\n\n const normalized = product.channels.flatMap((ch: string) => v3ChannelMap[ch] ?? [ch]);\n return { ...product, channels: [...new Set(normalized)] };\n}\n\nconst LEGACY_ZONED_TIMESTAMP =\n /^(\\d{4})-(\\d{2})-(\\d{2})[Tt ](\\d{2}):(\\d{2}):(\\d{2})(\\.\\d+)?(?:[Zz]|\\s*UTC|([+-])(\\d{2})(?::?(\\d{2}))?)$/i;\n\nfunction normalizeLegacyZonedTimestamp(value: unknown): unknown {\n let candidate = value;\n if (candidate && typeof candidate === 'object' && !Array.isArray(candidate)) {\n const entries = Object.entries(candidate as Record<string, unknown>);\n if (entries.length === 0) return undefined;\n if (entries.length !== 1 || (entries[0]![0] !== '$date' && entries[0]![0] !== 'value')) return value;\n candidate = entries[0]![1];\n }\n if (candidate === null) return undefined;\n if (candidate && typeof candidate === 'object' && !Array.isArray(candidate)) {\n return Object.keys(candidate as Record<string, unknown>).length === 0 ? undefined : value;\n }\n if (typeof candidate !== 'string') return value;\n\n const match = LEGACY_ZONED_TIMESTAMP.exec(candidate.trim());\n if (!match) return value;\n const [\n ,\n yearText,\n monthText,\n dayText,\n hourText,\n minuteText,\n secondText,\n fraction = '',\n sign,\n offsetHourText,\n offsetMinuteText,\n ] = match;\n const year = Number(yearText);\n const month = Number(monthText);\n const day = Number(dayText);\n const hour = Number(hourText);\n const minute = Number(minuteText);\n const second = Number(secondText);\n const offsetHours = offsetHourText === undefined ? 0 : Number(offsetHourText);\n const offsetMinutes = offsetMinuteText === undefined ? 0 : Number(offsetMinuteText);\n if (sign === '-' && offsetHours === 0 && offsetMinutes === 0) return value;\n if (\n month < 1 ||\n month > 12 ||\n day < 1 ||\n day > 31 ||\n hour > 23 ||\n minute > 59 ||\n second > 59 ||\n offsetHours > 23 ||\n offsetMinutes > 59\n ) {\n return value;\n }\n\n const local = new Date(0);\n local.setUTCFullYear(year, month - 1, day);\n local.setUTCHours(hour, minute, second, 0);\n if (\n local.getUTCFullYear() !== year ||\n local.getUTCMonth() !== month - 1 ||\n local.getUTCDate() !== day ||\n local.getUTCHours() !== hour ||\n local.getUTCMinutes() !== minute ||\n local.getUTCSeconds() !== second\n ) {\n return value;\n }\n\n const offset = (offsetHours * 60 + offsetMinutes) * 60_000 * (sign === '-' ? -1 : 1);\n const utc = new Date(local.getTime() - offset);\n if (utc.getUTCFullYear() < 0 || utc.getUTCFullYear() > 9999) return value;\n return `${utc.toISOString().slice(0, 19)}${fraction}Z`;\n}\n\n/** Normalize optional forecast timestamps at the v2.5 compatibility boundary. */\nexport function normalizeLegacyProductForecast(product: any): any {\n if (!product?.forecast || typeof product.forecast !== 'object' || Array.isArray(product.forecast)) return product;\n const forecast = { ...product.forecast };\n for (const field of ['generated_at', 'valid_until'] as const) {\n if (!(field in forecast)) continue;\n const normalized = normalizeLegacyZonedTimestamp(forecast[field]);\n if (normalized === undefined) delete forecast[field];\n else forecast[field] = normalized;\n }\n return { ...product, forecast };\n}\n\n/**\n * Normalize all products in a get_products response to v3\n */\nexport function normalizeGetProductsResponse(response: any): any {\n // If there's no products field at all, this may be an error response — pass through\n if (!('products' in (response ?? {}))) {\n return response;\n }\n\n // If products exists but isn't an array, the response is malformed\n if (!Array.isArray(response.products)) {\n return {\n errors: [\n {\n code: 'invalid_response',\n message: `Expected products to be an array, got ${typeof response.products}`,\n },\n ],\n };\n }\n\n return {\n ...response,\n products: response.products.map((p: any) =>\n normalizeLegacyProductForecast(normalizeProductChannels(normalizeProductPricing(p)))\n ),\n };\n}\n\n/**\n * Adapt a package request's pricing option selection for v2 server.\n * This handles bid_price which references pricing option floor semantics.\n */\nexport function adaptPackagePricingForV2(pkg: any): any {\n // Package requests don't typically contain pricing_options,\n // but they do contain pricing_option_id which selects one.\n // No transformation needed for bid_price - it's the same in both versions.\n return pkg;\n}\n\n/**\n * Adapt a create_media_buy request for v2 server (pricing fields)\n */\nexport function adaptMediaBuyPricingForV2(request: any): any {\n // Media buy requests select pricing options by ID, not by defining them.\n // No pricing field transformation needed in requests.\n return request;\n}\n\n/**\n * Normalize a media buy response's package pricing to v3\n */\nexport function normalizeMediaBuyPricingResponse(response: any): any {\n // Media buy responses may include products with pricing_options\n if (response?.products && Array.isArray(response.products)) {\n return {\n ...response,\n products: response.products.map(normalizeProductPricing),\n };\n }\n return response;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
* surface so ordinary buyers do not accidentally retain legacy identities.
|
|
41
41
|
*/
|
|
42
42
|
export { projectV1ProductToV2, canonicalDeclarationFromBareId, resolveCanonicalFormatKind } from './v1-to-v2.mjs';
|
|
43
|
-
export type { V1ToV2Result, V1ToV2ProjectionOptions, BareFormatIdResolveOptions, LegacyFormatConversionContext, LegacyFormatConverter, } from './v1-to-v2.mjs';
|
|
43
|
+
export type { V1ToV2Result, V1ToV2ProjectionOptions, BareFormatIdResolveOptions, LegacyFormatConversionContext, LegacyFormatConverter, LegacyFormatResolutionContext, LegacyFormatResolver, } from './v1-to-v2.mjs';
|
|
44
44
|
export { projectV2ProductToV1 } from './v2-to-v1.mjs';
|
|
45
45
|
export type { V2ToV1Result, V2ToV1ProjectionOptions, CanonicalFormatLegacyResolver, CanonicalFormatLegacyResolutionContext, CanonicalProductFormatLegacyResolutionContext, CanonicalCreativeFormatLegacyResolutionContext, CanonicalSelectorFormatLegacyResolutionContext, } from './v2-to-v1.mjs';
|
|
46
46
|
export { canonicalFormatLegacyResolverFromRoutes, legacyRoutesForProduct, type CanonicalFormatLegacyRoute, } from './legacy-routes.mjs';
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
* surface so ordinary buyers do not accidentally retain legacy identities.
|
|
41
41
|
*/
|
|
42
42
|
export { projectV1ProductToV2, canonicalDeclarationFromBareId, resolveCanonicalFormatKind } from './v1-to-v2';
|
|
43
|
-
export type { V1ToV2Result, V1ToV2ProjectionOptions, BareFormatIdResolveOptions, LegacyFormatConversionContext, LegacyFormatConverter, } from './v1-to-v2';
|
|
43
|
+
export type { V1ToV2Result, V1ToV2ProjectionOptions, BareFormatIdResolveOptions, LegacyFormatConversionContext, LegacyFormatConverter, LegacyFormatResolutionContext, LegacyFormatResolver, } from './v1-to-v2';
|
|
44
44
|
export { projectV2ProductToV1 } from './v2-to-v1';
|
|
45
45
|
export type { V2ToV1Result, V2ToV1ProjectionOptions, CanonicalFormatLegacyResolver, CanonicalFormatLegacyResolutionContext, CanonicalProductFormatLegacyResolutionContext, CanonicalCreativeFormatLegacyResolutionContext, CanonicalSelectorFormatLegacyResolutionContext, } from './v2-to-v1';
|
|
46
46
|
export { canonicalFormatLegacyResolverFromRoutes, legacyRoutesForProduct, type CanonicalFormatLegacyRoute, } from './legacy-routes';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/v2/projection/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAAE,oBAAoB,EAAE,8BAA8B,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAC9G,YAAY,EACV,YAAY,EACZ,uBAAuB,EACvB,0BAA0B,EAC1B,6BAA6B,EAC7B,qBAAqB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/v2/projection/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/v2/projection/index.ts"],"sourcesContent":["/**\n * v1 ↔ v2 Product projection layer (AdCP 3.1).\n *\n * Public surfaces:\n *\n * - `projectV1ProductToV2` / `projectV2ProductToV1` — the symmetric\n * core projections. Read a Product on one side, return a Product\n * on the other plus structured diagnostics (`source: 'sdk'`,\n * normative spec codes + SDK-local codes).\n *\n * - `resolveCanonicalFormatKind` / `canonicalDeclarationFromBareId` —\n * resolve a single bare format-id string (no surrounding Product,\n * no `agent_url`) to its canonical `format_kind` or full declaration.\n * Registry- and catalog-backed; fails closed to `null`.\n *\n * - `withFormatOptions` / `augmentProductWithFormatOptions` —\n * buyer-side response augmentation. Adds `format_options[]` to a\n * v1-shaped get_products response so canonical-format-aware buyers\n * can read the canonical model regardless of the seller's wire\n * version. Additive — `format_ids[]` is preserved.\n *\n * - `toAdditiveCanonicalProduct` — additive projection with URL-free\n * `format_options[]`, preserved top-level `format_ids[]`, and explicit\n * serializable legacy-route sidecars for later forwarding.\n * `withAdditiveCanonicalFormatOptions` is the response-level companion.\n * `toCanonicalFormatOptionsWithRoutes` provides the same safe route-first\n * concealment for callers that hold only a declaration array.\n *\n * - `toCanonicalOnlyProduct` / `toCanonicalOnlyResponse` — the\n * read-side narrowing for a fully-migrated consumer. Returns\n * `format_options[]` with `format_ids[]` dropped, surfacing a\n * diagnostic for any ref that couldn't be carried over.\n *\n * - Catalog + registry primitives (`lookupV1Format`,\n * `findCatalogEntryByCanonicalAndSize`, registry exports) for\n * callers wiring projection into their own code paths.\n *\n * Legacy-preserving and raw wire projection helpers are exposed only from\n * `@adcp/sdk/v2/projection`. The package root exports the canonical authoring\n * surface so ordinary buyers do not accidentally retain legacy identities.\n */\n\nexport { projectV1ProductToV2, canonicalDeclarationFromBareId, resolveCanonicalFormatKind } from './v1-to-v2';\nexport type {\n V1ToV2Result,\n V1ToV2ProjectionOptions,\n BareFormatIdResolveOptions,\n LegacyFormatConversionContext,\n LegacyFormatConverter,\n} from './v1-to-v2';\n\nexport { projectV2ProductToV1 } from './v2-to-v1';\nexport type {\n V2ToV1Result,\n V2ToV1ProjectionOptions,\n CanonicalFormatLegacyResolver,\n CanonicalFormatLegacyResolutionContext,\n CanonicalProductFormatLegacyResolutionContext,\n CanonicalCreativeFormatLegacyResolutionContext,\n CanonicalSelectorFormatLegacyResolutionContext,\n} from './v2-to-v1';\n\nexport {\n canonicalFormatLegacyResolverFromRoutes,\n legacyRoutesForProduct,\n type CanonicalFormatLegacyRoute,\n} from './legacy-routes';\n\nexport {\n augmentProductWithFormatOptions,\n withFormatOptions,\n toCanonicalFormatOptionsWithRoutes,\n toAdditiveCanonicalProduct,\n withAdditiveCanonicalFormatOptions,\n toCanonicalOnlyProduct,\n toCanonicalOnlyResponse,\n type V2AugmentedProduct,\n type AdditiveCanonicalProduct,\n type CanonicalOnlyProduct,\n} from './augment-response';\n\nexport {\n CanonicalFormat,\n audioDaastFormatDeclaration,\n audioHostedFormatDeclaration,\n agentPlacementFormatDeclaration,\n canonicalFormatDeclaration,\n customFormatDeclaration,\n displayTagFormatDeclaration,\n legacyFormatRef,\n legacyFormatRefs,\n html5FormatDeclaration,\n imageCarouselFormatDeclaration,\n imageFormatDeclaration,\n nativeInFeedFormatDeclaration,\n productCard,\n productCardDetailed,\n responsiveCreativeFormatDeclaration,\n sellerRenderedStatefulDisplayFormatDeclaration,\n sponsoredPlacementFormatDeclaration,\n coordinatedPlacementsFormatDeclaration,\n videoHostedFormatDeclaration,\n videoVastFormatDeclaration,\n type CanonicalFormatDeclaration,\n type CanonicalFormatDeclarationFields,\n type CanonicalFormatKind,\n type CanonicalFormatParams,\n type FormatReferenceInput,\n type ProductCardDetailedFields,\n type ProductCardFields,\n} from './builders';\n\nexport {\n packageRefsForFormatOptions,\n packageRefsForCapabilities,\n legacyFormatIdsFromOptions,\n tryLegacyFormatIdsFromOptions,\n legacyFormatIdsForFormatOption,\n legacyFormatIdsForCapability,\n lintPackageFormatSelectorDimensions,\n FormatOptionRefsLookupError,\n CapabilityIdsLookupError,\n type PackageFormatRefs,\n type PackageCapabilityRefs,\n type FormatOptionRef,\n type FormatOptionSelector,\n type FormatOptionRefsLookupErrorCode,\n type CapabilityIdsLookupErrorCode,\n type PackageFormatSelectorInput,\n type PackageFormatSelectorDimensionOptions,\n type FixedSizeDimensions,\n type PackageFormatSelectorDimensionDiagnosticCode,\n type PackageFormatSelectorDimensionDiagnostic,\n} from './write-side';\n\nexport type {\n V1FormatId,\n V2ProductFormatDeclaration,\n V2ProductInput,\n V2Product,\n V1ProductInput,\n V1Product,\n ProjectionProductInput,\n ProjectionDiagnostic,\n} from './types';\nexport { isProjectionProductInput } from './types';\nexport {\n legacyFormatConverterFromCatalogSnapshots,\n canonicalFormatLegacyResolverFromCatalogSnapshots,\n projectionAdaptersFromCatalogSnapshots,\n type ProjectionCatalogAdapters,\n type ProjectionCatalogSnapshot,\n type ProjectionCatalogSource,\n} from './catalog-snapshot';\n\nexport {\n loadCatalog,\n lookupV1Format,\n findCatalogEntryByCanonicalAndSize,\n parseSizedIdTemplate,\n _resetCatalogCache,\n type V1FormatDefinition,\n type CanonicalProjectionRef,\n} from './catalog';\n\nexport { isCanonicalV1Translatable } from './canonical-properties';\n\nexport {\n CreativeFormatProjectionError,\n CreativeFormatCapabilityError,\n projectCreativeForDelivery,\n projectMediaBuyCreativesForDelivery,\n projectSyncCreativesForDelivery,\n stripLegacyCreativeIdentity,\n resolveCreativeFormatWireMode,\n type CreativeFormatSelectorContainer,\n type CanonicalCreativeFormatSelectorContainer,\n type CreativeFormatWireMode,\n type CanonicalCreativeAsset,\n type CanonicalSyncCreativeAsset,\n type CanonicalCreativeResponse,\n type CanonicalGetProductsResponse,\n type CanonicalGetProductsRequest,\n type CanonicalCreateMediaBuyRequest,\n type CanonicalCreateMediaBuyResponse,\n type CanonicalCreativeFilters,\n type CanonicalListCreativesRequest,\n type CanonicalListCreativesResponse,\n type CanonicalGetCreativeDeliveryResponse,\n type CanonicalGetMediaBuyDeliveryResponse,\n type CanonicalGetMediaBuysResponse,\n type CanonicalListedCreative,\n type CanonicalPackageRequest,\n type CanonicalPackageUpdate,\n type CanonicalPackage,\n type CanonicalPlacement,\n type CanonicalPreviewCreativeRequest,\n type CanonicalPreviewCreativeResponse,\n type CanonicalProduct,\n type CanonicalProjectedCreative,\n type CanonicalSyncCreativesRequest,\n type CanonicalSyncCreativesResponse,\n type CanonicalUpdateMediaBuyRequest,\n type CanonicalUpdateMediaBuyResponse,\n type LegacyCreativeAsset,\n type LegacyProjectedCreative,\n type ProjectedMediaBuyCreativeRequest,\n type ProjectedSyncCreativeRequest,\n type SyncCreativeFormatProjection,\n} from './creative-delivery';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0CA,sBAAiG;
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/v2/projection/index.ts"],"sourcesContent":["/**\n * v1 ↔ v2 Product projection layer (AdCP 3.1).\n *\n * Public surfaces:\n *\n * - `projectV1ProductToV2` / `projectV2ProductToV1` — the symmetric\n * core projections. Read a Product on one side, return a Product\n * on the other plus structured diagnostics (`source: 'sdk'`,\n * normative spec codes + SDK-local codes).\n *\n * - `resolveCanonicalFormatKind` / `canonicalDeclarationFromBareId` —\n * resolve a single bare format-id string (no surrounding Product,\n * no `agent_url`) to its canonical `format_kind` or full declaration.\n * Registry- and catalog-backed; fails closed to `null`.\n *\n * - `withFormatOptions` / `augmentProductWithFormatOptions` —\n * buyer-side response augmentation. Adds `format_options[]` to a\n * v1-shaped get_products response so canonical-format-aware buyers\n * can read the canonical model regardless of the seller's wire\n * version. Additive — `format_ids[]` is preserved.\n *\n * - `toAdditiveCanonicalProduct` — additive projection with URL-free\n * `format_options[]`, preserved top-level `format_ids[]`, and explicit\n * serializable legacy-route sidecars for later forwarding.\n * `withAdditiveCanonicalFormatOptions` is the response-level companion.\n * `toCanonicalFormatOptionsWithRoutes` provides the same safe route-first\n * concealment for callers that hold only a declaration array.\n *\n * - `toCanonicalOnlyProduct` / `toCanonicalOnlyResponse` — the\n * read-side narrowing for a fully-migrated consumer. Returns\n * `format_options[]` with `format_ids[]` dropped, surfacing a\n * diagnostic for any ref that couldn't be carried over.\n *\n * - Catalog + registry primitives (`lookupV1Format`,\n * `findCatalogEntryByCanonicalAndSize`, registry exports) for\n * callers wiring projection into their own code paths.\n *\n * Legacy-preserving and raw wire projection helpers are exposed only from\n * `@adcp/sdk/v2/projection`. The package root exports the canonical authoring\n * surface so ordinary buyers do not accidentally retain legacy identities.\n */\n\nexport { projectV1ProductToV2, canonicalDeclarationFromBareId, resolveCanonicalFormatKind } from './v1-to-v2';\nexport type {\n V1ToV2Result,\n V1ToV2ProjectionOptions,\n BareFormatIdResolveOptions,\n LegacyFormatConversionContext,\n LegacyFormatConverter,\n LegacyFormatResolutionContext,\n LegacyFormatResolver,\n} from './v1-to-v2';\n\nexport { projectV2ProductToV1 } from './v2-to-v1';\nexport type {\n V2ToV1Result,\n V2ToV1ProjectionOptions,\n CanonicalFormatLegacyResolver,\n CanonicalFormatLegacyResolutionContext,\n CanonicalProductFormatLegacyResolutionContext,\n CanonicalCreativeFormatLegacyResolutionContext,\n CanonicalSelectorFormatLegacyResolutionContext,\n} from './v2-to-v1';\n\nexport {\n canonicalFormatLegacyResolverFromRoutes,\n legacyRoutesForProduct,\n type CanonicalFormatLegacyRoute,\n} from './legacy-routes';\n\nexport {\n augmentProductWithFormatOptions,\n withFormatOptions,\n toCanonicalFormatOptionsWithRoutes,\n toAdditiveCanonicalProduct,\n withAdditiveCanonicalFormatOptions,\n toCanonicalOnlyProduct,\n toCanonicalOnlyResponse,\n type V2AugmentedProduct,\n type AdditiveCanonicalProduct,\n type CanonicalOnlyProduct,\n} from './augment-response';\n\nexport {\n CanonicalFormat,\n audioDaastFormatDeclaration,\n audioHostedFormatDeclaration,\n agentPlacementFormatDeclaration,\n canonicalFormatDeclaration,\n customFormatDeclaration,\n displayTagFormatDeclaration,\n legacyFormatRef,\n legacyFormatRefs,\n html5FormatDeclaration,\n imageCarouselFormatDeclaration,\n imageFormatDeclaration,\n nativeInFeedFormatDeclaration,\n productCard,\n productCardDetailed,\n responsiveCreativeFormatDeclaration,\n sellerRenderedStatefulDisplayFormatDeclaration,\n sponsoredPlacementFormatDeclaration,\n coordinatedPlacementsFormatDeclaration,\n videoHostedFormatDeclaration,\n videoVastFormatDeclaration,\n type CanonicalFormatDeclaration,\n type CanonicalFormatDeclarationFields,\n type CanonicalFormatKind,\n type CanonicalFormatParams,\n type FormatReferenceInput,\n type ProductCardDetailedFields,\n type ProductCardFields,\n} from './builders';\n\nexport {\n packageRefsForFormatOptions,\n packageRefsForCapabilities,\n legacyFormatIdsFromOptions,\n tryLegacyFormatIdsFromOptions,\n legacyFormatIdsForFormatOption,\n legacyFormatIdsForCapability,\n lintPackageFormatSelectorDimensions,\n FormatOptionRefsLookupError,\n CapabilityIdsLookupError,\n type PackageFormatRefs,\n type PackageCapabilityRefs,\n type FormatOptionRef,\n type FormatOptionSelector,\n type FormatOptionRefsLookupErrorCode,\n type CapabilityIdsLookupErrorCode,\n type PackageFormatSelectorInput,\n type PackageFormatSelectorDimensionOptions,\n type FixedSizeDimensions,\n type PackageFormatSelectorDimensionDiagnosticCode,\n type PackageFormatSelectorDimensionDiagnostic,\n} from './write-side';\n\nexport type {\n V1FormatId,\n V2ProductFormatDeclaration,\n V2ProductInput,\n V2Product,\n V1ProductInput,\n V1Product,\n ProjectionProductInput,\n ProjectionDiagnostic,\n} from './types';\nexport { isProjectionProductInput } from './types';\nexport {\n legacyFormatConverterFromCatalogSnapshots,\n canonicalFormatLegacyResolverFromCatalogSnapshots,\n projectionAdaptersFromCatalogSnapshots,\n type ProjectionCatalogAdapters,\n type ProjectionCatalogSnapshot,\n type ProjectionCatalogSource,\n} from './catalog-snapshot';\n\nexport {\n loadCatalog,\n lookupV1Format,\n findCatalogEntryByCanonicalAndSize,\n parseSizedIdTemplate,\n _resetCatalogCache,\n type V1FormatDefinition,\n type CanonicalProjectionRef,\n} from './catalog';\n\nexport { isCanonicalV1Translatable } from './canonical-properties';\n\nexport {\n CreativeFormatProjectionError,\n CreativeFormatCapabilityError,\n projectCreativeForDelivery,\n projectMediaBuyCreativesForDelivery,\n projectSyncCreativesForDelivery,\n stripLegacyCreativeIdentity,\n resolveCreativeFormatWireMode,\n type CreativeFormatSelectorContainer,\n type CanonicalCreativeFormatSelectorContainer,\n type CreativeFormatWireMode,\n type CanonicalCreativeAsset,\n type CanonicalSyncCreativeAsset,\n type CanonicalCreativeResponse,\n type CanonicalGetProductsResponse,\n type CanonicalGetProductsRequest,\n type CanonicalCreateMediaBuyRequest,\n type CanonicalCreateMediaBuyResponse,\n type CanonicalCreativeFilters,\n type CanonicalListCreativesRequest,\n type CanonicalListCreativesResponse,\n type CanonicalGetCreativeDeliveryResponse,\n type CanonicalGetMediaBuyDeliveryResponse,\n type CanonicalGetMediaBuysResponse,\n type CanonicalListedCreative,\n type CanonicalPackageRequest,\n type CanonicalPackageUpdate,\n type CanonicalPackage,\n type CanonicalPlacement,\n type CanonicalPreviewCreativeRequest,\n type CanonicalPreviewCreativeResponse,\n type CanonicalProduct,\n type CanonicalProjectedCreative,\n type CanonicalSyncCreativesRequest,\n type CanonicalSyncCreativesResponse,\n type CanonicalUpdateMediaBuyRequest,\n type CanonicalUpdateMediaBuyResponse,\n type LegacyCreativeAsset,\n type LegacyProjectedCreative,\n type ProjectedMediaBuyCreativeRequest,\n type ProjectedSyncCreativeRequest,\n type SyncCreativeFormatProjection,\n} from './creative-delivery';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0CA,sBAAiG;AAWjG,sBAAqC;AAWrC,2BAIO;AAEP,8BAWO;AAEP,sBA6BO;AAEP,wBAqBO;AAYP,mBAAyC;AACzC,8BAOO;AAEP,qBAQO;AAEP,kCAA0C;AAE1C,+BA0CO;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/v2/projection/index.ts"],"sourcesContent":["/**\n * v1 ↔ v2 Product projection layer (AdCP 3.1).\n *\n * Public surfaces:\n *\n * - `projectV1ProductToV2` / `projectV2ProductToV1` — the symmetric\n * core projections. Read a Product on one side, return a Product\n * on the other plus structured diagnostics (`source: 'sdk'`,\n * normative spec codes + SDK-local codes).\n *\n * - `resolveCanonicalFormatKind` / `canonicalDeclarationFromBareId` —\n * resolve a single bare format-id string (no surrounding Product,\n * no `agent_url`) to its canonical `format_kind` or full declaration.\n * Registry- and catalog-backed; fails closed to `null`.\n *\n * - `withFormatOptions` / `augmentProductWithFormatOptions` —\n * buyer-side response augmentation. Adds `format_options[]` to a\n * v1-shaped get_products response so canonical-format-aware buyers\n * can read the canonical model regardless of the seller's wire\n * version. Additive — `format_ids[]` is preserved.\n *\n * - `toAdditiveCanonicalProduct` — additive projection with URL-free\n * `format_options[]`, preserved top-level `format_ids[]`, and explicit\n * serializable legacy-route sidecars for later forwarding.\n * `withAdditiveCanonicalFormatOptions` is the response-level companion.\n * `toCanonicalFormatOptionsWithRoutes` provides the same safe route-first\n * concealment for callers that hold only a declaration array.\n *\n * - `toCanonicalOnlyProduct` / `toCanonicalOnlyResponse` — the\n * read-side narrowing for a fully-migrated consumer. Returns\n * `format_options[]` with `format_ids[]` dropped, surfacing a\n * diagnostic for any ref that couldn't be carried over.\n *\n * - Catalog + registry primitives (`lookupV1Format`,\n * `findCatalogEntryByCanonicalAndSize`, registry exports) for\n * callers wiring projection into their own code paths.\n *\n * Legacy-preserving and raw wire projection helpers are exposed only from\n * `@adcp/sdk/v2/projection`. The package root exports the canonical authoring\n * surface so ordinary buyers do not accidentally retain legacy identities.\n */\n\nexport { projectV1ProductToV2, canonicalDeclarationFromBareId, resolveCanonicalFormatKind } from './v1-to-v2';\nexport type {\n V1ToV2Result,\n V1ToV2ProjectionOptions,\n BareFormatIdResolveOptions,\n LegacyFormatConversionContext,\n LegacyFormatConverter,\n} from './v1-to-v2';\n\nexport { projectV2ProductToV1 } from './v2-to-v1';\nexport type {\n V2ToV1Result,\n V2ToV1ProjectionOptions,\n CanonicalFormatLegacyResolver,\n CanonicalFormatLegacyResolutionContext,\n CanonicalProductFormatLegacyResolutionContext,\n CanonicalCreativeFormatLegacyResolutionContext,\n CanonicalSelectorFormatLegacyResolutionContext,\n} from './v2-to-v1';\n\nexport {\n canonicalFormatLegacyResolverFromRoutes,\n legacyRoutesForProduct,\n type CanonicalFormatLegacyRoute,\n} from './legacy-routes';\n\nexport {\n augmentProductWithFormatOptions,\n withFormatOptions,\n toCanonicalFormatOptionsWithRoutes,\n toAdditiveCanonicalProduct,\n withAdditiveCanonicalFormatOptions,\n toCanonicalOnlyProduct,\n toCanonicalOnlyResponse,\n type V2AugmentedProduct,\n type AdditiveCanonicalProduct,\n type CanonicalOnlyProduct,\n} from './augment-response';\n\nexport {\n CanonicalFormat,\n audioDaastFormatDeclaration,\n audioHostedFormatDeclaration,\n agentPlacementFormatDeclaration,\n canonicalFormatDeclaration,\n customFormatDeclaration,\n displayTagFormatDeclaration,\n legacyFormatRef,\n legacyFormatRefs,\n html5FormatDeclaration,\n imageCarouselFormatDeclaration,\n imageFormatDeclaration,\n nativeInFeedFormatDeclaration,\n productCard,\n productCardDetailed,\n responsiveCreativeFormatDeclaration,\n sellerRenderedStatefulDisplayFormatDeclaration,\n sponsoredPlacementFormatDeclaration,\n coordinatedPlacementsFormatDeclaration,\n videoHostedFormatDeclaration,\n videoVastFormatDeclaration,\n type CanonicalFormatDeclaration,\n type CanonicalFormatDeclarationFields,\n type CanonicalFormatKind,\n type CanonicalFormatParams,\n type FormatReferenceInput,\n type ProductCardDetailedFields,\n type ProductCardFields,\n} from './builders';\n\nexport {\n packageRefsForFormatOptions,\n packageRefsForCapabilities,\n legacyFormatIdsFromOptions,\n tryLegacyFormatIdsFromOptions,\n legacyFormatIdsForFormatOption,\n legacyFormatIdsForCapability,\n lintPackageFormatSelectorDimensions,\n FormatOptionRefsLookupError,\n CapabilityIdsLookupError,\n type PackageFormatRefs,\n type PackageCapabilityRefs,\n type FormatOptionRef,\n type FormatOptionSelector,\n type FormatOptionRefsLookupErrorCode,\n type CapabilityIdsLookupErrorCode,\n type PackageFormatSelectorInput,\n type PackageFormatSelectorDimensionOptions,\n type FixedSizeDimensions,\n type PackageFormatSelectorDimensionDiagnosticCode,\n type PackageFormatSelectorDimensionDiagnostic,\n} from './write-side';\n\nexport type {\n V1FormatId,\n V2ProductFormatDeclaration,\n V2ProductInput,\n V2Product,\n V1ProductInput,\n V1Product,\n ProjectionProductInput,\n ProjectionDiagnostic,\n} from './types';\nexport { isProjectionProductInput } from './types';\nexport {\n legacyFormatConverterFromCatalogSnapshots,\n canonicalFormatLegacyResolverFromCatalogSnapshots,\n projectionAdaptersFromCatalogSnapshots,\n type ProjectionCatalogAdapters,\n type ProjectionCatalogSnapshot,\n type ProjectionCatalogSource,\n} from './catalog-snapshot';\n\nexport {\n loadCatalog,\n lookupV1Format,\n findCatalogEntryByCanonicalAndSize,\n parseSizedIdTemplate,\n _resetCatalogCache,\n type V1FormatDefinition,\n type CanonicalProjectionRef,\n} from './catalog';\n\nexport { isCanonicalV1Translatable } from './canonical-properties';\n\nexport {\n CreativeFormatProjectionError,\n CreativeFormatCapabilityError,\n projectCreativeForDelivery,\n projectMediaBuyCreativesForDelivery,\n projectSyncCreativesForDelivery,\n stripLegacyCreativeIdentity,\n resolveCreativeFormatWireMode,\n type CreativeFormatSelectorContainer,\n type CanonicalCreativeFormatSelectorContainer,\n type CreativeFormatWireMode,\n type CanonicalCreativeAsset,\n type CanonicalSyncCreativeAsset,\n type CanonicalCreativeResponse,\n type CanonicalGetProductsResponse,\n type CanonicalGetProductsRequest,\n type CanonicalCreateMediaBuyRequest,\n type CanonicalCreateMediaBuyResponse,\n type CanonicalCreativeFilters,\n type CanonicalListCreativesRequest,\n type CanonicalListCreativesResponse,\n type CanonicalGetCreativeDeliveryResponse,\n type CanonicalGetMediaBuyDeliveryResponse,\n type CanonicalGetMediaBuysResponse,\n type CanonicalListedCreative,\n type CanonicalPackageRequest,\n type CanonicalPackageUpdate,\n type CanonicalPackage,\n type CanonicalPlacement,\n type CanonicalPreviewCreativeRequest,\n type CanonicalPreviewCreativeResponse,\n type CanonicalProduct,\n type CanonicalProjectedCreative,\n type CanonicalSyncCreativesRequest,\n type CanonicalSyncCreativesResponse,\n type CanonicalUpdateMediaBuyRequest,\n type CanonicalUpdateMediaBuyResponse,\n type LegacyCreativeAsset,\n type LegacyProjectedCreative,\n type ProjectedMediaBuyCreativeRequest,\n type ProjectedSyncCreativeRequest,\n type SyncCreativeFormatProjection,\n} from './creative-delivery';\n"],"mappings":"AA0CA,SAAS,sBAAsB,gCAAgC,kCAAkC;
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/v2/projection/index.ts"],"sourcesContent":["/**\n * v1 ↔ v2 Product projection layer (AdCP 3.1).\n *\n * Public surfaces:\n *\n * - `projectV1ProductToV2` / `projectV2ProductToV1` — the symmetric\n * core projections. Read a Product on one side, return a Product\n * on the other plus structured diagnostics (`source: 'sdk'`,\n * normative spec codes + SDK-local codes).\n *\n * - `resolveCanonicalFormatKind` / `canonicalDeclarationFromBareId` —\n * resolve a single bare format-id string (no surrounding Product,\n * no `agent_url`) to its canonical `format_kind` or full declaration.\n * Registry- and catalog-backed; fails closed to `null`.\n *\n * - `withFormatOptions` / `augmentProductWithFormatOptions` —\n * buyer-side response augmentation. Adds `format_options[]` to a\n * v1-shaped get_products response so canonical-format-aware buyers\n * can read the canonical model regardless of the seller's wire\n * version. Additive — `format_ids[]` is preserved.\n *\n * - `toAdditiveCanonicalProduct` — additive projection with URL-free\n * `format_options[]`, preserved top-level `format_ids[]`, and explicit\n * serializable legacy-route sidecars for later forwarding.\n * `withAdditiveCanonicalFormatOptions` is the response-level companion.\n * `toCanonicalFormatOptionsWithRoutes` provides the same safe route-first\n * concealment for callers that hold only a declaration array.\n *\n * - `toCanonicalOnlyProduct` / `toCanonicalOnlyResponse` — the\n * read-side narrowing for a fully-migrated consumer. Returns\n * `format_options[]` with `format_ids[]` dropped, surfacing a\n * diagnostic for any ref that couldn't be carried over.\n *\n * - Catalog + registry primitives (`lookupV1Format`,\n * `findCatalogEntryByCanonicalAndSize`, registry exports) for\n * callers wiring projection into their own code paths.\n *\n * Legacy-preserving and raw wire projection helpers are exposed only from\n * `@adcp/sdk/v2/projection`. The package root exports the canonical authoring\n * surface so ordinary buyers do not accidentally retain legacy identities.\n */\n\nexport { projectV1ProductToV2, canonicalDeclarationFromBareId, resolveCanonicalFormatKind } from './v1-to-v2';\nexport type {\n V1ToV2Result,\n V1ToV2ProjectionOptions,\n BareFormatIdResolveOptions,\n LegacyFormatConversionContext,\n LegacyFormatConverter,\n LegacyFormatResolutionContext,\n LegacyFormatResolver,\n} from './v1-to-v2';\n\nexport { projectV2ProductToV1 } from './v2-to-v1';\nexport type {\n V2ToV1Result,\n V2ToV1ProjectionOptions,\n CanonicalFormatLegacyResolver,\n CanonicalFormatLegacyResolutionContext,\n CanonicalProductFormatLegacyResolutionContext,\n CanonicalCreativeFormatLegacyResolutionContext,\n CanonicalSelectorFormatLegacyResolutionContext,\n} from './v2-to-v1';\n\nexport {\n canonicalFormatLegacyResolverFromRoutes,\n legacyRoutesForProduct,\n type CanonicalFormatLegacyRoute,\n} from './legacy-routes';\n\nexport {\n augmentProductWithFormatOptions,\n withFormatOptions,\n toCanonicalFormatOptionsWithRoutes,\n toAdditiveCanonicalProduct,\n withAdditiveCanonicalFormatOptions,\n toCanonicalOnlyProduct,\n toCanonicalOnlyResponse,\n type V2AugmentedProduct,\n type AdditiveCanonicalProduct,\n type CanonicalOnlyProduct,\n} from './augment-response';\n\nexport {\n CanonicalFormat,\n audioDaastFormatDeclaration,\n audioHostedFormatDeclaration,\n agentPlacementFormatDeclaration,\n canonicalFormatDeclaration,\n customFormatDeclaration,\n displayTagFormatDeclaration,\n legacyFormatRef,\n legacyFormatRefs,\n html5FormatDeclaration,\n imageCarouselFormatDeclaration,\n imageFormatDeclaration,\n nativeInFeedFormatDeclaration,\n productCard,\n productCardDetailed,\n responsiveCreativeFormatDeclaration,\n sellerRenderedStatefulDisplayFormatDeclaration,\n sponsoredPlacementFormatDeclaration,\n coordinatedPlacementsFormatDeclaration,\n videoHostedFormatDeclaration,\n videoVastFormatDeclaration,\n type CanonicalFormatDeclaration,\n type CanonicalFormatDeclarationFields,\n type CanonicalFormatKind,\n type CanonicalFormatParams,\n type FormatReferenceInput,\n type ProductCardDetailedFields,\n type ProductCardFields,\n} from './builders';\n\nexport {\n packageRefsForFormatOptions,\n packageRefsForCapabilities,\n legacyFormatIdsFromOptions,\n tryLegacyFormatIdsFromOptions,\n legacyFormatIdsForFormatOption,\n legacyFormatIdsForCapability,\n lintPackageFormatSelectorDimensions,\n FormatOptionRefsLookupError,\n CapabilityIdsLookupError,\n type PackageFormatRefs,\n type PackageCapabilityRefs,\n type FormatOptionRef,\n type FormatOptionSelector,\n type FormatOptionRefsLookupErrorCode,\n type CapabilityIdsLookupErrorCode,\n type PackageFormatSelectorInput,\n type PackageFormatSelectorDimensionOptions,\n type FixedSizeDimensions,\n type PackageFormatSelectorDimensionDiagnosticCode,\n type PackageFormatSelectorDimensionDiagnostic,\n} from './write-side';\n\nexport type {\n V1FormatId,\n V2ProductFormatDeclaration,\n V2ProductInput,\n V2Product,\n V1ProductInput,\n V1Product,\n ProjectionProductInput,\n ProjectionDiagnostic,\n} from './types';\nexport { isProjectionProductInput } from './types';\nexport {\n legacyFormatConverterFromCatalogSnapshots,\n canonicalFormatLegacyResolverFromCatalogSnapshots,\n projectionAdaptersFromCatalogSnapshots,\n type ProjectionCatalogAdapters,\n type ProjectionCatalogSnapshot,\n type ProjectionCatalogSource,\n} from './catalog-snapshot';\n\nexport {\n loadCatalog,\n lookupV1Format,\n findCatalogEntryByCanonicalAndSize,\n parseSizedIdTemplate,\n _resetCatalogCache,\n type V1FormatDefinition,\n type CanonicalProjectionRef,\n} from './catalog';\n\nexport { isCanonicalV1Translatable } from './canonical-properties';\n\nexport {\n CreativeFormatProjectionError,\n CreativeFormatCapabilityError,\n projectCreativeForDelivery,\n projectMediaBuyCreativesForDelivery,\n projectSyncCreativesForDelivery,\n stripLegacyCreativeIdentity,\n resolveCreativeFormatWireMode,\n type CreativeFormatSelectorContainer,\n type CanonicalCreativeFormatSelectorContainer,\n type CreativeFormatWireMode,\n type CanonicalCreativeAsset,\n type CanonicalSyncCreativeAsset,\n type CanonicalCreativeResponse,\n type CanonicalGetProductsResponse,\n type CanonicalGetProductsRequest,\n type CanonicalCreateMediaBuyRequest,\n type CanonicalCreateMediaBuyResponse,\n type CanonicalCreativeFilters,\n type CanonicalListCreativesRequest,\n type CanonicalListCreativesResponse,\n type CanonicalGetCreativeDeliveryResponse,\n type CanonicalGetMediaBuyDeliveryResponse,\n type CanonicalGetMediaBuysResponse,\n type CanonicalListedCreative,\n type CanonicalPackageRequest,\n type CanonicalPackageUpdate,\n type CanonicalPackage,\n type CanonicalPlacement,\n type CanonicalPreviewCreativeRequest,\n type CanonicalPreviewCreativeResponse,\n type CanonicalProduct,\n type CanonicalProjectedCreative,\n type CanonicalSyncCreativesRequest,\n type CanonicalSyncCreativesResponse,\n type CanonicalUpdateMediaBuyRequest,\n type CanonicalUpdateMediaBuyResponse,\n type LegacyCreativeAsset,\n type LegacyProjectedCreative,\n type ProjectedMediaBuyCreativeRequest,\n type ProjectedSyncCreativeRequest,\n type SyncCreativeFormatProjection,\n} from './creative-delivery';\n"],"mappings":"AA0CA,SAAS,sBAAsB,gCAAgC,kCAAkC;AAWjG,SAAS,4BAA4B;AAWrC;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAQK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAYK;AAYP,SAAS,gCAAgC;AACzC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAEP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AAEP,SAAS,iCAAiC;AAE1C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAmCK;","names":[]}
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
* deterministic for that single format_id.
|
|
33
33
|
*
|
|
34
34
|
* **Scope (prototype)**:
|
|
35
|
-
* - AAO catalog
|
|
36
|
-
*
|
|
37
|
-
*
|
|
35
|
+
* - AAO catalog plus explicit adopter resolvers for seller-specific
|
|
36
|
+
* formats. Network-backed resolution remains outside this pure module;
|
|
37
|
+
* server integrations can use `LegacyFormatResolver` before projection.
|
|
38
38
|
* - Param extraction is dimensions-only (`width`, `height`,
|
|
39
39
|
* `duration_ms`). Full canonical-specific params (slots, codecs,
|
|
40
40
|
* char limits, platform_extensions) are not constructed. A v2
|
|
@@ -71,6 +71,20 @@ export interface LegacyFormatConversionContext {
|
|
|
71
71
|
* definition, round-trippable to that ref.
|
|
72
72
|
*/
|
|
73
73
|
export type LegacyFormatConverter = (context: LegacyFormatConversionContext) => V2ProductFormatDeclaration | null | undefined;
|
|
74
|
+
/** Safe request context supplied to an asynchronous seller-specific resolver. */
|
|
75
|
+
export interface LegacyFormatResolutionContext extends LegacyFormatConversionContext {
|
|
76
|
+
operation: 'get_products';
|
|
77
|
+
servedAdcpVersion?: string;
|
|
78
|
+
accountId?: string;
|
|
79
|
+
/** Aborts when the request is cancelled or the SDK resolver deadline expires. */
|
|
80
|
+
signal?: AbortSignal;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Asynchronous counterpart to {@link LegacyFormatConverter}. Intended for
|
|
84
|
+
* catalog/database lookups that must complete before a server projects a
|
|
85
|
+
* legacy `get_products` result onto its canonical wire boundary.
|
|
86
|
+
*/
|
|
87
|
+
export type LegacyFormatResolver = (context: LegacyFormatResolutionContext) => PromiseLike<V2ProductFormatDeclaration | null | undefined> | V2ProductFormatDeclaration | null | undefined;
|
|
74
88
|
export interface V1ToV2ProjectionOptions {
|
|
75
89
|
legacyFormatConverter?: LegacyFormatConverter;
|
|
76
90
|
/** Pre-resolved exact-owner publisher/community catalogs, highest precedence first. */
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
* deterministic for that single format_id.
|
|
33
33
|
*
|
|
34
34
|
* **Scope (prototype)**:
|
|
35
|
-
* - AAO catalog
|
|
36
|
-
*
|
|
37
|
-
*
|
|
35
|
+
* - AAO catalog plus explicit adopter resolvers for seller-specific
|
|
36
|
+
* formats. Network-backed resolution remains outside this pure module;
|
|
37
|
+
* server integrations can use `LegacyFormatResolver` before projection.
|
|
38
38
|
* - Param extraction is dimensions-only (`width`, `height`,
|
|
39
39
|
* `duration_ms`). Full canonical-specific params (slots, codecs,
|
|
40
40
|
* char limits, platform_extensions) are not constructed. A v2
|
|
@@ -71,6 +71,20 @@ export interface LegacyFormatConversionContext {
|
|
|
71
71
|
* definition, round-trippable to that ref.
|
|
72
72
|
*/
|
|
73
73
|
export type LegacyFormatConverter = (context: LegacyFormatConversionContext) => V2ProductFormatDeclaration | null | undefined;
|
|
74
|
+
/** Safe request context supplied to an asynchronous seller-specific resolver. */
|
|
75
|
+
export interface LegacyFormatResolutionContext extends LegacyFormatConversionContext {
|
|
76
|
+
operation: 'get_products';
|
|
77
|
+
servedAdcpVersion?: string;
|
|
78
|
+
accountId?: string;
|
|
79
|
+
/** Aborts when the request is cancelled or the SDK resolver deadline expires. */
|
|
80
|
+
signal?: AbortSignal;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Asynchronous counterpart to {@link LegacyFormatConverter}. Intended for
|
|
84
|
+
* catalog/database lookups that must complete before a server projects a
|
|
85
|
+
* legacy `get_products` result onto its canonical wire boundary.
|
|
86
|
+
*/
|
|
87
|
+
export type LegacyFormatResolver = (context: LegacyFormatResolutionContext) => PromiseLike<V2ProductFormatDeclaration | null | undefined> | V2ProductFormatDeclaration | null | undefined;
|
|
74
88
|
export interface V1ToV2ProjectionOptions {
|
|
75
89
|
legacyFormatConverter?: LegacyFormatConverter;
|
|
76
90
|
/** Pre-resolved exact-owner publisher/community catalogs, highest precedence first. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v1-to-v2.d.ts","sourceRoot":"","sources":["../../../../src/lib/v2/projection/v1-to-v2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH,OAAO,KAAK,EAEV,cAAc,EACd,UAAU,EACV,SAAS,EACT,0BAA0B,EAC1B,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,SAAS,CAAC;AAMjB,OAAO,EAA6C,KAAK,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAK/G,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAkClE,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,SAAS,CAAC;IACd,WAAW,EAAE,oBAAoB,EAAE,CAAC;IACpC,gFAAgF;IAChF,YAAY,EAAE,0BAA0B,EAAE,CAAC;CAC5C;AAED,8EAA8E;AAC9E,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAClC,OAAO,EAAE,6BAA6B,KACnC,0BAA0B,GAAG,IAAI,GAAG,SAAS,CAAC;AAEnD,MAAM,WAAW,uBAAuB;IACtC,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAC9C,uFAAuF;IACvF,kBAAkB,CAAC,EAAE,SAAS,yBAAyB,EAAE,CAAC;CAG3D;AAoZD;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,YAAY,CA2BxG;AAED,MAAM,WAAW,0BAA0B;IACzC;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,wBAAgB,8BAA8B,CAC5C,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,0BAA0B,GACnC,0BAA0B,GAAG,IAAI,CAwBnC;AAkBD;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CACxC,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,0BAA0B,GACnC,mBAAmB,GAAG,IAAI,CAE5B"}
|
|
1
|
+
{"version":3,"file":"v1-to-v2.d.ts","sourceRoot":"","sources":["../../../../src/lib/v2/projection/v1-to-v2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAEH,OAAO,KAAK,EAEV,cAAc,EACd,UAAU,EACV,SAAS,EACT,0BAA0B,EAC1B,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,SAAS,CAAC;AAMjB,OAAO,EAA6C,KAAK,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAK/G,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAkClE,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,SAAS,CAAC;IACd,WAAW,EAAE,oBAAoB,EAAE,CAAC;IACpC,gFAAgF;IAChF,YAAY,EAAE,0BAA0B,EAAE,CAAC;CAC5C;AAED,8EAA8E;AAC9E,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAClC,OAAO,EAAE,6BAA6B,KACnC,0BAA0B,GAAG,IAAI,GAAG,SAAS,CAAC;AAEnD,iFAAiF;AACjF,MAAM,WAAW,6BAA8B,SAAQ,6BAA6B;IAClF,SAAS,EAAE,cAAc,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,CACjC,OAAO,EAAE,6BAA6B,KACnC,WAAW,CAAC,0BAA0B,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,0BAA0B,GAAG,IAAI,GAAG,SAAS,CAAC;AAEhH,MAAM,WAAW,uBAAuB;IACtC,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAC9C,uFAAuF;IACvF,kBAAkB,CAAC,EAAE,SAAS,yBAAyB,EAAE,CAAC;CAG3D;AAoZD;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,YAAY,CA2BxG;AAED,MAAM,WAAW,0BAA0B;IACzC;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,wBAAgB,8BAA8B,CAC5C,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,0BAA0B,GACnC,0BAA0B,GAAG,IAAI,CAwBnC;AAkBD;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CACxC,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,0BAA0B,GACnC,mBAAmB,GAAG,IAAI,CAE5B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/v2/projection/v1-to-v2.ts"],"sourcesContent":["/**\n * v1 → v2 Product projection (the upgrade direction).\n *\n * Used when the SDK is talking to a v1 seller but the buyer wrote V2\n * code. The 8.0 design at `docs/development/v3.1-sdk-design.md` makes\n * V2 the public mental model — the buyer never sees `Product.format_ids`\n * directly, only `Product.format_options`. This module is the wire-\n * boundary translator that makes that promise hold for v1 sellers.\n *\n * Resolution order per format_id, mirroring `v1-canonical-mapping.json`\n * step 1-4 in the forward direction:\n *\n * 1. **v1 catalog explicit `canonical` annotation**. If the v1 format\n * definition (from `reference-formats.json` or a seller's\n * `list_creative_formats`) carries `canonical: <kind>`, that's the\n * authoritative pairing. Seller-asserted, normative.\n * 2. **Registry glob match**. Look up `format_id.id` against the\n * registry's `format_id_glob` entries (including wildcards). First\n * match wins per the spec's ordering.\n * 3. **Structural match**. Match against the v1 format's declared\n * assets + version constraints. Family-level identification\n * yields a canonical (e.g., \"vast 4.x → video_vast\"). Less\n * precise on params; caller may need to fetch additional context.\n * 4. **Fail closed** → `FORMAT_PROJECTION_FAILED`. v1 product with\n * no catalog entry, no registry coverage, and no structural match\n * is invisible on the v2 side. SDK surfaces the diagnostic so\n * buyers know what got dropped.\n *\n * **Asymmetry vs the v2 → v1 direction**: every v1 format_id is a\n * specific thing, so there's no \"ambiguous family\" bucket here — if\n * the structural match identifies a family, the projection is\n * deterministic for that single format_id.\n *\n * **Scope (prototype)**:\n * - AAO catalog only — seller-specific catalogs (publisher's own\n * `list_creative_formats`) require an AgentClient hook the auto-\n * negotiation surface will provide in the full 8.0 enablement.\n * - Param extraction is dimensions-only (`width`, `height`,\n * `duration_ms`). Full canonical-specific params (slots, codecs,\n * char limits, platform_extensions) are not constructed. A v2\n * buyer reading the projected declaration's `params` sees the\n * minimum needed to identify the variant.\n * - Asset slot translation (v1 `assets[]` → v2 `slots[]` via the\n * asset_group_vocabulary aliases) is deliberately deferred. This\n * is the most adopter-relevant piece for actual creative\n * submission flows and lands in a follow-up.\n */\n\nimport type {\n V1Product,\n V1ProductInput,\n V1FormatId,\n V2Product,\n V2ProductFormatDeclaration,\n ProjectionDiagnostic,\n CanonicalFormatKind,\n} from './types';\nimport { forwardLookupByGlob, forwardLookupByStructural } from './registry';\nimport { lookupUniqueV1FormatById, lookupV1Format, type V1FormatDefinition } from './catalog';\nimport { AAO_CANONICAL_AGENT_URL } from './constants';\nimport { LIBRARY_VERSION } from '../../version';\nimport { ProductFormatDeclarationSchema } from '../../types/schemas.generated';\nimport { legacyFormatConverterFromCatalogSnapshots, type ProjectionCatalogSnapshot } from './catalog-snapshot';\nimport { canonicalizeAgentUrl } from '../../discovery/resolve-agent-properties';\nimport { isLikelyPrivateUrl } from '../../net/address-guards';\nimport { createHmac } from 'crypto';\nimport { legacyRoutesForProduct } from './legacy-routes';\nimport type { CanonicalFormatLegacyRoute } from './legacy-routes';\n\nconst SDK_ID = `@adcp/sdk@${LIBRARY_VERSION}`;\n\nclass CatalogRequirementConflict extends Error {}\n\n/**\n * Stable identity disambiguator, not a password hash. The input is a public\n * creative-format tuple and the output is a product-local routing label. As\n * with the transport cache disambiguators, HMAC-SHA256 with an empty key gives\n * deterministic collision resistance without placing this non-secret value\n * in CodeQL's password-storage dataflow class.\n */\nfunction formatIdentityDisambiguator(identity: string): string {\n return createHmac('sha256', '').update(identity).digest('hex').slice(0, 32);\n}\n\n/**\n * Give an unnamed projected option a stable, opaque identity derived from the\n * complete legacy tuple. Positional IDs are unsafe: a seller reordering its\n * `format_ids` array could otherwise make a persisted canonical selection\n * resolve to a different legacy format on the next discovery refresh.\n */\nfunction migratedFormatOptionId(fid: V1FormatId): string {\n const identity = JSON.stringify([\n fid.agent_url,\n fid.id,\n fid.width ?? null,\n fid.height ?? null,\n fid.duration_ms ?? null,\n ]);\n return `migrated_${formatIdentityDisambiguator(identity)}`;\n}\n\nexport interface V1ToV2Result {\n v2: V2Product;\n diagnostics: ProjectionDiagnostic[];\n /** Serializable exact routes that can be persisted for a later legacy write. */\n legacyRoutes: CanonicalFormatLegacyRoute[];\n}\n\n/** Context passed to an adopter's seller-specific legacy format converter. */\nexport interface LegacyFormatConversionContext {\n formatId: Readonly<V1FormatId>;\n productId: string;\n field: string;\n}\n\n/**\n * Escape hatch for legacy formats owned by a custom creative agent. The\n * converter returns the canonical product declaration that the legacy ref\n * represents. For bespoke shapes, return `format_kind: 'custom'` with both\n * `format_shape` and an immutable `format_schema` reference.\n *\n * The SDK adds the source `formatId` as `v1_format_ref`; converters must not\n * set `canonical_formats_only: true` because a legacy source is, by\n * definition, round-trippable to that ref.\n */\nexport type LegacyFormatConverter = (\n context: LegacyFormatConversionContext\n) => V2ProductFormatDeclaration | null | undefined;\n\nexport interface V1ToV2ProjectionOptions {\n legacyFormatConverter?: LegacyFormatConverter;\n /** Pre-resolved exact-owner publisher/community catalogs, highest precedence first. */\n projectionCatalogs?: readonly ProjectionCatalogSnapshot[];\n /** @internal Filesystem-isolated catalog fixture used by projector tests. */\n _catalogPath?: string;\n}\n\n/**\n * Build the v2 declaration's `params` block from the v1 format_id's\n * dimensional overrides + the catalog/registry entry's recorded params.\n *\n * Prototype scope: dimensions + duration only. A full implementation\n * would walk the canonical's parameter schema and populate every field\n * the catalog entry hints at (codecs, char limits, platform_extensions).\n */\nfunction buildParams(\n fid: V1FormatId,\n registryParams: Record<string, unknown>,\n catalogEntry?: V1FormatDefinition\n): Record<string, unknown> {\n const params: Record<string, unknown> = { ...registryParams };\n\n // Catalog-authored fixed requirements are normative projection inputs.\n // Prefer the primary render dimensions when there is exactly one fixed\n // size; otherwise accept one unambiguous width/height pair from the asset\n // requirements. A fixed duration is equally safe only when min === max.\n // Never guess from a name, a range, or conflicting requirements.\n const fixedSizes = new Map<string, { width: number; height: number }>();\n let hasUnsupportedSizeRequirement = false;\n for (const render of catalogEntry?.renders ?? []) {\n const width = render.dimensions?.width;\n const height = render.dimensions?.height;\n if (width === undefined && height === undefined) continue;\n if (\n typeof width === 'number' &&\n Number.isInteger(width) &&\n width > 0 &&\n typeof height === 'number' &&\n Number.isInteger(height) &&\n height > 0\n ) {\n fixedSizes.set(`${width}x${height}`, { width, height });\n } else hasUnsupportedSizeRequirement = true;\n }\n for (const asset of catalogEntry?.assets ?? []) {\n const width = asset.requirements?.width;\n const height = asset.requirements?.height;\n const minWidth = asset.requirements?.min_width;\n const maxWidth = asset.requirements?.max_width;\n const minHeight = asset.requirements?.min_height;\n const maxHeight = asset.requirements?.max_height;\n if (minWidth !== undefined || maxWidth !== undefined || minHeight !== undefined || maxHeight !== undefined) {\n if (\n typeof minWidth === 'number' &&\n Number.isInteger(minWidth) &&\n minWidth > 0 &&\n minWidth === maxWidth &&\n typeof minHeight === 'number' &&\n Number.isInteger(minHeight) &&\n minHeight > 0 &&\n minHeight === maxHeight\n ) {\n fixedSizes.set(`${minWidth}x${minHeight}`, { width: minWidth, height: minHeight });\n } else {\n hasUnsupportedSizeRequirement = true;\n }\n }\n if (width === undefined && height === undefined) continue;\n if (\n typeof width === 'number' &&\n Number.isInteger(width) &&\n width > 0 &&\n typeof height === 'number' &&\n Number.isInteger(height) &&\n height > 0\n ) {\n fixedSizes.set(`${width}x${height}`, { width, height });\n } else hasUnsupportedSizeRequirement = true;\n }\n if (fixedSizes.size > 1 || hasUnsupportedSizeRequirement) {\n throw new CatalogRequirementConflict('catalog contains conflicting fixed dimensions');\n }\n if (fixedSizes.size === 1) {\n const fixedSize = fixedSizes.values().next().value;\n if (fixedSize) {\n if (\n (typeof fid.width === 'number' && fid.width !== fixedSize.width) ||\n (typeof fid.height === 'number' && fid.height !== fixedSize.height)\n ) {\n throw new CatalogRequirementConflict('format id conflicts with catalog dimensions');\n }\n params.width = fixedSize.width;\n params.height = fixedSize.height;\n }\n }\n\n const fixedDurations = new Set<number>();\n let hasRangedDuration = false;\n for (const asset of catalogEntry?.assets ?? []) {\n const min = asset.requirements?.min_duration_ms;\n const max = asset.requirements?.max_duration_ms;\n if (min === undefined && max === undefined) continue;\n if (\n (min !== undefined && (typeof min !== 'number' || !Number.isInteger(min) || min <= 0)) ||\n (max !== undefined && (typeof max !== 'number' || !Number.isInteger(max) || max <= 0)) ||\n (typeof min === 'number' && typeof max === 'number' && min > max)\n ) {\n throw new CatalogRequirementConflict('catalog contains invalid duration requirements');\n }\n if (typeof min === 'number' && min === max) fixedDurations.add(min);\n else hasRangedDuration = true;\n }\n if (fixedDurations.size > 1 || hasRangedDuration) {\n throw new CatalogRequirementConflict('catalog contains conflicting fixed durations');\n }\n if (fixedDurations.size === 1) {\n const fixedDuration = fixedDurations.values().next().value;\n if (fixedDuration !== undefined) {\n if (typeof fid.duration_ms === 'number' && fid.duration_ms !== fixedDuration) {\n throw new CatalogRequirementConflict('format id conflicts with catalog duration');\n }\n params.duration_ms_exact = fixedDuration;\n }\n }\n\n // Inline discriminators narrow parameterized catalog templates. Concrete\n // catalog defaults were checked for contradictions above.\n if (typeof fid.width === 'number') params.width = fid.width;\n if (typeof fid.height === 'number') params.height = fid.height;\n if (typeof fid.duration_ms === 'number') params.duration_ms_exact = fid.duration_ms;\n return params;\n}\n\nfunction findLegacyCreativeIdentity(value: unknown, seen = new WeakSet<object>()): string | undefined {\n if (value === null || typeof value !== 'object') return undefined;\n if (seen.has(value)) return undefined;\n seen.add(value);\n if (Array.isArray(value)) {\n for (const item of value) {\n const nested = findLegacyCreativeIdentity(item, seen);\n if (nested) return nested;\n }\n return undefined;\n }\n for (const [key, child] of Object.entries(value as Record<string, unknown>)) {\n if (/(^|_)(?:format_ids?|v1_format_ref|agent_url)($|_)/.test(key)) {\n return key;\n }\n const nested = findLegacyCreativeIdentity(child, seen);\n if (nested) return nested;\n }\n return undefined;\n}\n\nfunction projectWithLegacyConverter(\n fid: V1FormatId,\n productId: string,\n field: string,\n converter: LegacyFormatConverter | undefined\n): { decl?: V2ProductFormatDeclaration; diagnostic?: ProjectionDiagnostic } | undefined {\n if (!converter) return undefined;\n try {\n const converted = converter({ formatId: { ...fid }, productId, field });\n if (!converted) return undefined;\n const forbidden = findLegacyCreativeIdentity(converted);\n if (forbidden) {\n throw new Error(`canonical conversion must not return ${forbidden}`);\n }\n const completed = { ...converted, v1_format_ref: [fid] };\n if (completed.canonical_formats_only === true) {\n throw new Error('a conversion from a legacy format cannot set canonical_formats_only: true');\n }\n if (\n completed.format_kind === 'custom' &&\n (typeof completed.format_shape !== 'string' ||\n completed.format_shape.trim().length === 0 ||\n !completed.format_schema)\n ) {\n throw new Error('custom conversions require format_shape and format_schema');\n }\n if (\n completed.format_kind === 'custom' &&\n (typeof completed.format_option_id !== 'string' || completed.format_option_id.trim().length === 0)\n ) {\n throw new Error('custom conversions require format_option_id');\n }\n const parsed = ProductFormatDeclarationSchema.safeParse(completed);\n if (!parsed.success) {\n throw new Error('converter returned an invalid canonical format declaration');\n }\n return { decl: parsed.data as V2ProductFormatDeclaration };\n } catch {\n return {\n diagnostic: {\n source: 'sdk',\n sdk_id: SDK_ID,\n field,\n code: 'FORMAT_PROJECTION_FAILED',\n error: {\n details: {\n format_kind: 'custom',\n product_id: productId,\n resolution_failure: 'custom_converter_failed',\n },\n },\n },\n };\n }\n}\n\n/**\n * Project a single v1 `format_id` to a v2 `ProductFormatDeclaration`,\n * or to a diagnostic when no projection is possible.\n */\nfunction projectFormatId(\n fid: V1FormatId,\n productId: string,\n field: string,\n options?: V1ToV2ProjectionOptions\n): { decl?: V2ProductFormatDeclaration; diagnostic?: ProjectionDiagnostic } {\n const hasWidth = fid.width !== undefined;\n const hasHeight = fid.height !== undefined;\n const invalidDimensions =\n hasWidth !== hasHeight ||\n (hasWidth && (!Number.isInteger(fid.width) || fid.width! <= 0)) ||\n (hasHeight && (!Number.isInteger(fid.height) || fid.height! <= 0));\n const invalidDuration = fid.duration_ms !== undefined && (!Number.isInteger(fid.duration_ms) || fid.duration_ms <= 0);\n if (invalidDimensions || invalidDuration) {\n return {\n diagnostic: {\n source: 'sdk',\n sdk_id: SDK_ID,\n field,\n code: 'FORMAT_PROJECTION_FAILED',\n error: {\n details: {\n format_kind: 'custom',\n product_id: productId,\n resolution_failure: 'invalid_format_id_parameters',\n },\n },\n },\n };\n }\n\n // A publisher/community catalog carrying an explicit v1_format_ref is the\n // most specific authoritative pairing. Public availability or a matching\n // format_option_id alone is not enough: canonical_formats_only declarations\n // and declarations without an alias do not participate here.\n const catalogSnapshot = projectWithLegacyConverter(\n fid,\n productId,\n field,\n legacyFormatConverterFromCatalogSnapshots(options?.projectionCatalogs)\n );\n if (catalogSnapshot) return catalogSnapshot;\n\n // Prefer the protocol-correct composite identity. During the legacy\n // migration, deployed sellers have also copied AAO standard IDs while\n // putting their own creative-agent URL in the tuple. Treat that as an\n // inbound alias only when the AAO catalog publishes exactly one entry for\n // the bare ID. `buildParams` below still rejects contradictory inline\n // dimensions/duration, and the emitted v1_format_ref preserves `fid` so a\n // legacy write routes back to the seller rather than the AAO host.\n const exactCatalogEntry = lookupV1Format(fid, options?._catalogPath);\n const canonicalAgentUrl = canonicalizeAgentUrl(fid.agent_url);\n const mayUseUniqueAlias =\n canonicalAgentUrl !== null &&\n new URL(canonicalAgentUrl).protocol === 'https:' &&\n !isLikelyPrivateUrl(canonicalAgentUrl);\n const uniqueAliasEntry =\n exactCatalogEntry === undefined && mayUseUniqueAlias\n ? lookupUniqueV1FormatById(fid.id, options?._catalogPath)\n : undefined;\n if (uniqueAliasEntry) {\n // A caller-authored converter is more specific than this compatibility\n // heuristic. Returning undefined opts into the AAO bare-ID fallback;\n // invalid/throwing converter output fails closed and is never bypassed.\n const explicit = projectWithLegacyConverter(fid, productId, field, options?.legacyFormatConverter);\n if (explicit) return explicit;\n }\n const catalogEntry = exactCatalogEntry ?? uniqueAliasEntry;\n\n // Step 1: v1 catalog has an explicit `canonical` annotation. Always\n // object-shaped per `canonical-projection-ref.json`: required `kind`,\n // optional `asset_source` + `slots_override`. Carry the refinement\n // fields onto the v2 declaration so the projection preserves the\n // spec-authored intent (generative AI projects with text-prompt slot;\n // native projects with extended slot set; etc.).\n if (catalogEntry?.canonical) {\n const projection = catalogEntry.canonical;\n let params: Record<string, unknown>;\n try {\n params = buildParams(fid, {}, catalogEntry);\n } catch (error) {\n if (!(error instanceof CatalogRequirementConflict)) throw error;\n return {\n diagnostic: {\n source: 'sdk',\n sdk_id: SDK_ID,\n field,\n code: 'FORMAT_PROJECTION_FAILED',\n error: {\n details: {\n format_kind: projection.kind,\n product_id: productId,\n resolution_failure: 'catalog_requirement_conflict',\n },\n },\n },\n };\n }\n if (projection.asset_source) params.asset_source = projection.asset_source;\n if (projection.slots_override) params.slots = projection.slots_override;\n return {\n decl: {\n format_kind: projection.kind,\n params,\n v1_format_ref: [fid],\n },\n };\n }\n\n // Step 1b: catalog HAS the entry but no `canonical:` annotation. This\n // is the AAO saying \"no v2 mapping yet for this category\" — at 3.1\n // GA, native/DOOH/broadcast/card-scaffolding sit in this bucket.\n // Falling through to structural match would shoehorn the format to\n // a coarse `display_tag` based on a `url` asset (or similar) — which\n // contradicts the AAO's deliberate absence of annotation. Fail-closed\n // honestly so the buyer sees \"category not yet v2-mapped\" rather than\n // a semantically wrong projection. Symmetric counterpart to\n // CANONICAL_NOT_V1_TRANSLATABLE on the v2→v1 side.\n if (catalogEntry && !catalogEntry.canonical) {\n const custom = projectWithLegacyConverter(fid, productId, field, options?.legacyFormatConverter);\n if (custom) return custom;\n return {\n diagnostic: {\n source: 'sdk',\n sdk_id: SDK_ID,\n field,\n code: 'FORMAT_PROJECTION_FAILED',\n error: {\n details: {\n format_kind: 'custom',\n product_id: productId,\n resolution_failure: 'catalog_lacks_canonical_annotation',\n },\n },\n },\n };\n }\n\n // Step 2: format not in the AAO catalog. Try registry glob match\n // against format_id.id. Catches publisher-bespoke ids that share the\n // AAO catalog's naming convention.\n const globMatch = forwardLookupByGlob(fid.id);\n if (globMatch) {\n return {\n decl: {\n format_kind: globMatch.canonical,\n params: buildParams(fid, globMatch.parameters),\n v1_format_ref: [fid],\n },\n };\n }\n\n // Step 3: structural match — only fires when the format is NOT in the\n // catalog (Step 1b ate the catalog-known-but-unannotated case). For\n // truly bespoke publisher formats this is the best signal we have:\n // a VAST tag is a VAST tag regardless of seller naming.\n if (catalogEntry?.assets) {\n const assetTypes = catalogEntry.assets.map(a => a.asset_type).filter((t): t is string => typeof t === 'string');\n const structMatch = forwardLookupByStructural({ asset_types: assetTypes });\n if (structMatch) {\n return {\n decl: {\n format_kind: structMatch.canonical,\n params: buildParams(fid, structMatch.parameters, catalogEntry),\n v1_format_ref: [fid],\n },\n };\n }\n }\n\n // Step 4: give the adopter one explicit, typed escape hatch for a\n // seller/creative-agent-owned legacy format. This runs only after all\n // protocol-owned mappings fail, so a callback cannot override a canonical\n // AAO mapping accidentally.\n const custom = projectWithLegacyConverter(fid, productId, field, options?.legacyFormatConverter);\n if (custom) return custom;\n\n // Step 5: fail-closed. v1 product is invisible on the canonical side.\n return {\n diagnostic: {\n source: 'sdk',\n sdk_id: SDK_ID,\n field,\n code: 'FORMAT_PROJECTION_FAILED',\n error: {\n details: {\n format_kind: 'custom',\n product_id: productId,\n resolution_failure: 'no_match',\n },\n },\n },\n };\n}\n\n/**\n * Project a v1 Product to a v2 Product. Drops `format_ids` from the\n * public output and rebuilds `format_options` per the resolution order.\n *\n * Caller decides what to do with the result when `format_options` is\n * empty — typically filter the product out of the response payload to\n * a v2-only buyer (the spec requires `format_options` to have\n * `minItems: 1` when present). The function always returns a Product\n * shape so adopters can inspect what got dropped via diagnostics.\n *\n * @see canonicalDeclarationFromBareId — resolve a single bare format-id\n * string (no surrounding Product) to a declaration or `format_kind`.\n */\nexport function projectV1ProductToV2(v1: V1ProductInput, options?: V1ToV2ProjectionOptions): V1ToV2Result {\n const format_options: V2ProductFormatDeclaration[] = [];\n const diagnostics: ProjectionDiagnostic[] = [];\n\n const inputFormatIds = v1.format_ids ?? [];\n for (let i = 0; i < inputFormatIds.length; i++) {\n const fid = inputFormatIds[i]! as V1FormatId;\n const field = `products[${v1.product_id}].format_ids[${i}]`;\n const { decl, diagnostic } = projectFormatId(fid, v1.product_id, field, options);\n if (decl) {\n format_options.push(\n typeof decl.format_option_id === 'string' && decl.format_option_id.length > 0\n ? decl\n : { ...decl, format_option_id: migratedFormatOptionId(fid) }\n );\n }\n if (diagnostic) diagnostics.push(diagnostic);\n }\n\n const { format_ids: _drop, ...rest } = v1;\n void _drop;\n const v2Product: V2Product = {\n ...(rest as Omit<V1ProductInput, 'format_ids'>),\n format_options,\n } as V2Product;\n\n return { v2: v2Product, diagnostics, legacyRoutes: legacyRoutesForProduct(v1.product_id, format_options) };\n}\n\nexport interface BareFormatIdResolveOptions {\n /**\n * `agent_url` to attach when lifting the bare `id` to a structured\n * {@link V1FormatId} for resolution. Defaults to the canonical AAO host\n * (`https://creative.adcontextprotocol.org/`) — the publisher of every\n * AAO catalog id, and the source of essentially all bare ids persisted\n * before the `{ agent_url, id }` convention. When an exact ID has one\n * unique AAO-published meaning, a valid non-AAO `agentUrl` is accepted as\n * a legacy owner alias and is preserved in `v1_format_ref`. Unknown or\n * colliding IDs still resolve to `null`.\n */\n agentUrl?: string;\n\n /**\n * Asset-type disambiguator for an under-specified bare id. The AAO\n * catalog names per-asset-type variants `<base>_<suffix>` (e.g.\n * `display_300x250` → `display_300x250_image` / `_html` / `_generative`).\n * A size-only bare id like `display_300x250` is genuinely ambiguous and\n * resolves to `null` on its own; pass the asset type you already hold\n * (an adopter's `format_type`) and the resolver retries the disambiguated\n * catalog variant `<id>_<suffix>`.\n *\n * The vocabulary is the catalog asset type where it differs from the\n * variant suffix (`javascript` → `_js`), otherwise the suffix itself\n * (`image`, `html`, `generative`, `js`). Canonical-kind aliases are also\n * accepted (`html5` → `html`, `display_tag` → `js`) for callers already\n * holding a kind-like local value.\n *\n * Only consulted when the bare id does NOT resolve on its own (a real\n * catalog id is authoritative). Still fails closed: if `<id>_<suffix>`\n * is not a catalog entry, returns `null` — the hint narrows, it never\n * fabricates.\n */\n assetType?: string;\n\n /**\n * @deprecated Use `assetType`. Kept as a backwards-compatible alias for\n * callers who adopted the initial helper surface before issue #2289.\n */\n assetTypeHint?: string;\n}\n\n/**\n * Resolve a bare v1 format-id string to its full v2\n * `ProductFormatDeclaration`, or `null` when the id has no canonical\n * mapping.\n *\n * Adopters migrating off legacy format storage routinely hold a bare id\n * (`display_300x250_image`, `video_standard_30s`) persisted before the\n * `{ agent_url, id }` structured-ref convention. This lifts that bare id\n * to a structured ref (via `agentUrl`, default the AAO host) and runs the\n * exact resolution the v1 → v2 product projection uses — in the registry\n * spec's `v1-canonical-mapping.json` resolution order:\n *\n * - AAO catalog `canonical:` annotation — the authoritative\n * seller-asserted mapping (registry resolution-order step 2).\n * - Registry `format_id_glob` literal match (registry resolution-order\n * step 3) — future-proof; 3.1 ships zero literal globs, so this fires\n * only when a future registry adds platform-specific literals.\n *\n * Fails closed: returns `null` — never a guess — when neither path\n * resolves the id. That covers an unknown id, an under-specified id\n * (`display_300x250`, which the catalog only carries as `_image` /\n * `_html` / `_generative` variants), and a catalog entry the AAO has not\n * yet annotated with a `canonical:`. Structural matching never\n * contributes a kind: a bare id absent from the catalog carries no asset\n * shape to match on, and a catalog entry lacking a `canonical:` fails\n * closed before the structural step is reached.\n *\n * For an under-specified bare id, pass `assetType` (the asset type you\n * already hold, such as an adopter's `format_type`) and the resolver retries\n * the disambiguated catalog variant\n * `<id>_<suffix>` — so the SDK owns the `_image` / `_html` suffix\n * convention instead of every adopter re-deriving it. The hint is\n * consulted only when the bare id doesn't resolve on its own, and still\n * fails closed when the disambiguated id isn't a catalog entry.\n *\n * The returned declaration carries `v1_format_ref: [{ agent_url, id }]`\n * (the resolved id — the disambiguated `<id>_<suffix>` when a hint\n * applied), so adopters lift a bare id to a structured ref in one step\n * (the pre-projection step the migration docs encourage).\n *\n * Like the rest of the projection layer, this requires the bundled AAO\n * catalog + canonical-mapping registry; it throws (rather than returning\n * `null`) only when those are missing from the install — a corrupted\n * `@adcp/sdk` package, not a normal unresolved-id outcome.\n *\n * For just the `format_kind`, use {@link resolveCanonicalFormatKind}. For\n * the structured diagnostic explaining *why* an id did not resolve, run\n * it through {@link projectV1ProductToV2} inside a one-format product.\n */\nexport function canonicalDeclarationFromBareId(\n id: string,\n options?: BareFormatIdResolveOptions\n): V2ProductFormatDeclaration | null {\n if (!id) return null;\n const agentUrl = options?.agentUrl ?? AAO_CANONICAL_AGENT_URL;\n\n // A real catalog id is authoritative — resolve it directly first.\n const direct = projectFormatId({ agent_url: agentUrl, id }, `<bare:${id}>`, `bareFormatId(${id})`).decl;\n if (direct) return direct;\n\n // Under-specified bare id + an asset-type hint: retry the disambiguated\n // catalog variant `<id>_<suffix>`. Fails closed if that isn't a catalog\n // entry either — the hint narrows, it never fabricates.\n const assetType = options?.assetType ?? options?.assetTypeHint;\n const suffix = assetType ? normalizeAssetTypeSuffix(assetType) : '';\n if (suffix) {\n const disambiguated = `${id}_${suffix}`;\n const hinted = projectFormatId(\n { agent_url: agentUrl, id: disambiguated },\n `<bare:${disambiguated}>`,\n `bareFormatId(${disambiguated})`\n ).decl;\n if (hinted) return hinted;\n }\n\n return null;\n}\n\n/**\n * Map an `assetType` to the AAO catalog's `<base>_<suffix>` suffix.\n * Catalog asset type `javascript` and canonical-kind names that differ from\n * their suffix (`html5`, `display_tag`) are aliased. Any other value is passed\n * through lowercased so a future asset type or suffix resolves without a code\n * change — an unknown value simply misses the catalog and the caller fails\n * closed.\n */\nfunction normalizeAssetTypeSuffix(hint: string): string {\n const h = hint.trim().toLowerCase();\n if (h === 'html5') return 'html';\n if (h === 'javascript') return 'js';\n if (h === 'display_tag') return 'js';\n return h;\n}\n\n/**\n * Resolve a bare v1 format-id string to its canonical `format_kind`, or\n * `null` when the id has no canonical mapping. Registry- and\n * catalog-backed: the single source of truth that replaces hand-rolled\n * `inferFormatKindFromFormatId` heuristics adopters maintain locally.\n *\n * Thin projection of {@link canonicalDeclarationFromBareId} down to the\n * `format_kind`; see it for the resolution order, fail-closed semantics,\n * the `agentUrl` default, and the `assetType` disambiguator.\n */\nexport function resolveCanonicalFormatKind(\n id: string,\n options?: BareFormatIdResolveOptions\n): CanonicalFormatKind | null {\n return canonicalDeclarationFromBareId(id, options)?.format_kind ?? null;\n}\n"],"mappings":"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","names":["custom"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/v2/projection/v1-to-v2.ts"],"sourcesContent":["/**\n * v1 → v2 Product projection (the upgrade direction).\n *\n * Used when the SDK is talking to a v1 seller but the buyer wrote V2\n * code. The 8.0 design at `docs/development/v3.1-sdk-design.md` makes\n * V2 the public mental model — the buyer never sees `Product.format_ids`\n * directly, only `Product.format_options`. This module is the wire-\n * boundary translator that makes that promise hold for v1 sellers.\n *\n * Resolution order per format_id, mirroring `v1-canonical-mapping.json`\n * step 1-4 in the forward direction:\n *\n * 1. **v1 catalog explicit `canonical` annotation**. If the v1 format\n * definition (from `reference-formats.json` or a seller's\n * `list_creative_formats`) carries `canonical: <kind>`, that's the\n * authoritative pairing. Seller-asserted, normative.\n * 2. **Registry glob match**. Look up `format_id.id` against the\n * registry's `format_id_glob` entries (including wildcards). First\n * match wins per the spec's ordering.\n * 3. **Structural match**. Match against the v1 format's declared\n * assets + version constraints. Family-level identification\n * yields a canonical (e.g., \"vast 4.x → video_vast\"). Less\n * precise on params; caller may need to fetch additional context.\n * 4. **Fail closed** → `FORMAT_PROJECTION_FAILED`. v1 product with\n * no catalog entry, no registry coverage, and no structural match\n * is invisible on the v2 side. SDK surfaces the diagnostic so\n * buyers know what got dropped.\n *\n * **Asymmetry vs the v2 → v1 direction**: every v1 format_id is a\n * specific thing, so there's no \"ambiguous family\" bucket here — if\n * the structural match identifies a family, the projection is\n * deterministic for that single format_id.\n *\n * **Scope (prototype)**:\n * - AAO catalog plus explicit adopter resolvers for seller-specific\n * formats. Network-backed resolution remains outside this pure module;\n * server integrations can use `LegacyFormatResolver` before projection.\n * - Param extraction is dimensions-only (`width`, `height`,\n * `duration_ms`). Full canonical-specific params (slots, codecs,\n * char limits, platform_extensions) are not constructed. A v2\n * buyer reading the projected declaration's `params` sees the\n * minimum needed to identify the variant.\n * - Asset slot translation (v1 `assets[]` → v2 `slots[]` via the\n * asset_group_vocabulary aliases) is deliberately deferred. This\n * is the most adopter-relevant piece for actual creative\n * submission flows and lands in a follow-up.\n */\n\nimport type {\n V1Product,\n V1ProductInput,\n V1FormatId,\n V2Product,\n V2ProductFormatDeclaration,\n ProjectionDiagnostic,\n CanonicalFormatKind,\n} from './types';\nimport { forwardLookupByGlob, forwardLookupByStructural } from './registry';\nimport { lookupUniqueV1FormatById, lookupV1Format, type V1FormatDefinition } from './catalog';\nimport { AAO_CANONICAL_AGENT_URL } from './constants';\nimport { LIBRARY_VERSION } from '../../version';\nimport { ProductFormatDeclarationSchema } from '../../types/schemas.generated';\nimport { legacyFormatConverterFromCatalogSnapshots, type ProjectionCatalogSnapshot } from './catalog-snapshot';\nimport { canonicalizeAgentUrl } from '../../discovery/resolve-agent-properties';\nimport { isLikelyPrivateUrl } from '../../net/address-guards';\nimport { createHmac } from 'crypto';\nimport { legacyRoutesForProduct } from './legacy-routes';\nimport type { CanonicalFormatLegacyRoute } from './legacy-routes';\n\nconst SDK_ID = `@adcp/sdk@${LIBRARY_VERSION}`;\n\nclass CatalogRequirementConflict extends Error {}\n\n/**\n * Stable identity disambiguator, not a password hash. The input is a public\n * creative-format tuple and the output is a product-local routing label. As\n * with the transport cache disambiguators, HMAC-SHA256 with an empty key gives\n * deterministic collision resistance without placing this non-secret value\n * in CodeQL's password-storage dataflow class.\n */\nfunction formatIdentityDisambiguator(identity: string): string {\n return createHmac('sha256', '').update(identity).digest('hex').slice(0, 32);\n}\n\n/**\n * Give an unnamed projected option a stable, opaque identity derived from the\n * complete legacy tuple. Positional IDs are unsafe: a seller reordering its\n * `format_ids` array could otherwise make a persisted canonical selection\n * resolve to a different legacy format on the next discovery refresh.\n */\nfunction migratedFormatOptionId(fid: V1FormatId): string {\n const identity = JSON.stringify([\n fid.agent_url,\n fid.id,\n fid.width ?? null,\n fid.height ?? null,\n fid.duration_ms ?? null,\n ]);\n return `migrated_${formatIdentityDisambiguator(identity)}`;\n}\n\nexport interface V1ToV2Result {\n v2: V2Product;\n diagnostics: ProjectionDiagnostic[];\n /** Serializable exact routes that can be persisted for a later legacy write. */\n legacyRoutes: CanonicalFormatLegacyRoute[];\n}\n\n/** Context passed to an adopter's seller-specific legacy format converter. */\nexport interface LegacyFormatConversionContext {\n formatId: Readonly<V1FormatId>;\n productId: string;\n field: string;\n}\n\n/**\n * Escape hatch for legacy formats owned by a custom creative agent. The\n * converter returns the canonical product declaration that the legacy ref\n * represents. For bespoke shapes, return `format_kind: 'custom'` with both\n * `format_shape` and an immutable `format_schema` reference.\n *\n * The SDK adds the source `formatId` as `v1_format_ref`; converters must not\n * set `canonical_formats_only: true` because a legacy source is, by\n * definition, round-trippable to that ref.\n */\nexport type LegacyFormatConverter = (\n context: LegacyFormatConversionContext\n) => V2ProductFormatDeclaration | null | undefined;\n\n/** Safe request context supplied to an asynchronous seller-specific resolver. */\nexport interface LegacyFormatResolutionContext extends LegacyFormatConversionContext {\n operation: 'get_products';\n servedAdcpVersion?: string;\n accountId?: string;\n /** Aborts when the request is cancelled or the SDK resolver deadline expires. */\n signal?: AbortSignal;\n}\n\n/**\n * Asynchronous counterpart to {@link LegacyFormatConverter}. Intended for\n * catalog/database lookups that must complete before a server projects a\n * legacy `get_products` result onto its canonical wire boundary.\n */\nexport type LegacyFormatResolver = (\n context: LegacyFormatResolutionContext\n) => PromiseLike<V2ProductFormatDeclaration | null | undefined> | V2ProductFormatDeclaration | null | undefined;\n\nexport interface V1ToV2ProjectionOptions {\n legacyFormatConverter?: LegacyFormatConverter;\n /** Pre-resolved exact-owner publisher/community catalogs, highest precedence first. */\n projectionCatalogs?: readonly ProjectionCatalogSnapshot[];\n /** @internal Filesystem-isolated catalog fixture used by projector tests. */\n _catalogPath?: string;\n}\n\n/**\n * Build the v2 declaration's `params` block from the v1 format_id's\n * dimensional overrides + the catalog/registry entry's recorded params.\n *\n * Prototype scope: dimensions + duration only. A full implementation\n * would walk the canonical's parameter schema and populate every field\n * the catalog entry hints at (codecs, char limits, platform_extensions).\n */\nfunction buildParams(\n fid: V1FormatId,\n registryParams: Record<string, unknown>,\n catalogEntry?: V1FormatDefinition\n): Record<string, unknown> {\n const params: Record<string, unknown> = { ...registryParams };\n\n // Catalog-authored fixed requirements are normative projection inputs.\n // Prefer the primary render dimensions when there is exactly one fixed\n // size; otherwise accept one unambiguous width/height pair from the asset\n // requirements. A fixed duration is equally safe only when min === max.\n // Never guess from a name, a range, or conflicting requirements.\n const fixedSizes = new Map<string, { width: number; height: number }>();\n let hasUnsupportedSizeRequirement = false;\n for (const render of catalogEntry?.renders ?? []) {\n const width = render.dimensions?.width;\n const height = render.dimensions?.height;\n if (width === undefined && height === undefined) continue;\n if (\n typeof width === 'number' &&\n Number.isInteger(width) &&\n width > 0 &&\n typeof height === 'number' &&\n Number.isInteger(height) &&\n height > 0\n ) {\n fixedSizes.set(`${width}x${height}`, { width, height });\n } else hasUnsupportedSizeRequirement = true;\n }\n for (const asset of catalogEntry?.assets ?? []) {\n const width = asset.requirements?.width;\n const height = asset.requirements?.height;\n const minWidth = asset.requirements?.min_width;\n const maxWidth = asset.requirements?.max_width;\n const minHeight = asset.requirements?.min_height;\n const maxHeight = asset.requirements?.max_height;\n if (minWidth !== undefined || maxWidth !== undefined || minHeight !== undefined || maxHeight !== undefined) {\n if (\n typeof minWidth === 'number' &&\n Number.isInteger(minWidth) &&\n minWidth > 0 &&\n minWidth === maxWidth &&\n typeof minHeight === 'number' &&\n Number.isInteger(minHeight) &&\n minHeight > 0 &&\n minHeight === maxHeight\n ) {\n fixedSizes.set(`${minWidth}x${minHeight}`, { width: minWidth, height: minHeight });\n } else {\n hasUnsupportedSizeRequirement = true;\n }\n }\n if (width === undefined && height === undefined) continue;\n if (\n typeof width === 'number' &&\n Number.isInteger(width) &&\n width > 0 &&\n typeof height === 'number' &&\n Number.isInteger(height) &&\n height > 0\n ) {\n fixedSizes.set(`${width}x${height}`, { width, height });\n } else hasUnsupportedSizeRequirement = true;\n }\n if (fixedSizes.size > 1 || hasUnsupportedSizeRequirement) {\n throw new CatalogRequirementConflict('catalog contains conflicting fixed dimensions');\n }\n if (fixedSizes.size === 1) {\n const fixedSize = fixedSizes.values().next().value;\n if (fixedSize) {\n if (\n (typeof fid.width === 'number' && fid.width !== fixedSize.width) ||\n (typeof fid.height === 'number' && fid.height !== fixedSize.height)\n ) {\n throw new CatalogRequirementConflict('format id conflicts with catalog dimensions');\n }\n params.width = fixedSize.width;\n params.height = fixedSize.height;\n }\n }\n\n const fixedDurations = new Set<number>();\n let hasRangedDuration = false;\n for (const asset of catalogEntry?.assets ?? []) {\n const min = asset.requirements?.min_duration_ms;\n const max = asset.requirements?.max_duration_ms;\n if (min === undefined && max === undefined) continue;\n if (\n (min !== undefined && (typeof min !== 'number' || !Number.isInteger(min) || min <= 0)) ||\n (max !== undefined && (typeof max !== 'number' || !Number.isInteger(max) || max <= 0)) ||\n (typeof min === 'number' && typeof max === 'number' && min > max)\n ) {\n throw new CatalogRequirementConflict('catalog contains invalid duration requirements');\n }\n if (typeof min === 'number' && min === max) fixedDurations.add(min);\n else hasRangedDuration = true;\n }\n if (fixedDurations.size > 1 || hasRangedDuration) {\n throw new CatalogRequirementConflict('catalog contains conflicting fixed durations');\n }\n if (fixedDurations.size === 1) {\n const fixedDuration = fixedDurations.values().next().value;\n if (fixedDuration !== undefined) {\n if (typeof fid.duration_ms === 'number' && fid.duration_ms !== fixedDuration) {\n throw new CatalogRequirementConflict('format id conflicts with catalog duration');\n }\n params.duration_ms_exact = fixedDuration;\n }\n }\n\n // Inline discriminators narrow parameterized catalog templates. Concrete\n // catalog defaults were checked for contradictions above.\n if (typeof fid.width === 'number') params.width = fid.width;\n if (typeof fid.height === 'number') params.height = fid.height;\n if (typeof fid.duration_ms === 'number') params.duration_ms_exact = fid.duration_ms;\n return params;\n}\n\nfunction findLegacyCreativeIdentity(value: unknown, seen = new WeakSet<object>()): string | undefined {\n if (value === null || typeof value !== 'object') return undefined;\n if (seen.has(value)) return undefined;\n seen.add(value);\n if (Array.isArray(value)) {\n for (const item of value) {\n const nested = findLegacyCreativeIdentity(item, seen);\n if (nested) return nested;\n }\n return undefined;\n }\n for (const [key, child] of Object.entries(value as Record<string, unknown>)) {\n if (/(^|_)(?:format_ids?|v1_format_ref|agent_url)($|_)/.test(key)) {\n return key;\n }\n const nested = findLegacyCreativeIdentity(child, seen);\n if (nested) return nested;\n }\n return undefined;\n}\n\nfunction projectWithLegacyConverter(\n fid: V1FormatId,\n productId: string,\n field: string,\n converter: LegacyFormatConverter | undefined\n): { decl?: V2ProductFormatDeclaration; diagnostic?: ProjectionDiagnostic } | undefined {\n if (!converter) return undefined;\n try {\n const converted = converter({ formatId: { ...fid }, productId, field });\n if (!converted) return undefined;\n const forbidden = findLegacyCreativeIdentity(converted);\n if (forbidden) {\n throw new Error(`canonical conversion must not return ${forbidden}`);\n }\n const completed = { ...converted, v1_format_ref: [fid] };\n if (completed.canonical_formats_only === true) {\n throw new Error('a conversion from a legacy format cannot set canonical_formats_only: true');\n }\n if (\n completed.format_kind === 'custom' &&\n (typeof completed.format_shape !== 'string' ||\n completed.format_shape.trim().length === 0 ||\n !completed.format_schema)\n ) {\n throw new Error('custom conversions require format_shape and format_schema');\n }\n if (\n completed.format_kind === 'custom' &&\n (typeof completed.format_option_id !== 'string' || completed.format_option_id.trim().length === 0)\n ) {\n throw new Error('custom conversions require format_option_id');\n }\n const parsed = ProductFormatDeclarationSchema.safeParse(completed);\n if (!parsed.success) {\n throw new Error('converter returned an invalid canonical format declaration');\n }\n return { decl: parsed.data as V2ProductFormatDeclaration };\n } catch {\n return {\n diagnostic: {\n source: 'sdk',\n sdk_id: SDK_ID,\n field,\n code: 'FORMAT_PROJECTION_FAILED',\n error: {\n details: {\n format_kind: 'custom',\n product_id: productId,\n resolution_failure: 'custom_converter_failed',\n },\n },\n },\n };\n }\n}\n\n/**\n * Project a single v1 `format_id` to a v2 `ProductFormatDeclaration`,\n * or to a diagnostic when no projection is possible.\n */\nfunction projectFormatId(\n fid: V1FormatId,\n productId: string,\n field: string,\n options?: V1ToV2ProjectionOptions\n): { decl?: V2ProductFormatDeclaration; diagnostic?: ProjectionDiagnostic } {\n const hasWidth = fid.width !== undefined;\n const hasHeight = fid.height !== undefined;\n const invalidDimensions =\n hasWidth !== hasHeight ||\n (hasWidth && (!Number.isInteger(fid.width) || fid.width! <= 0)) ||\n (hasHeight && (!Number.isInteger(fid.height) || fid.height! <= 0));\n const invalidDuration = fid.duration_ms !== undefined && (!Number.isInteger(fid.duration_ms) || fid.duration_ms <= 0);\n if (invalidDimensions || invalidDuration) {\n return {\n diagnostic: {\n source: 'sdk',\n sdk_id: SDK_ID,\n field,\n code: 'FORMAT_PROJECTION_FAILED',\n error: {\n details: {\n format_kind: 'custom',\n product_id: productId,\n resolution_failure: 'invalid_format_id_parameters',\n },\n },\n },\n };\n }\n\n // A publisher/community catalog carrying an explicit v1_format_ref is the\n // most specific authoritative pairing. Public availability or a matching\n // format_option_id alone is not enough: canonical_formats_only declarations\n // and declarations without an alias do not participate here.\n const catalogSnapshot = projectWithLegacyConverter(\n fid,\n productId,\n field,\n legacyFormatConverterFromCatalogSnapshots(options?.projectionCatalogs)\n );\n if (catalogSnapshot) return catalogSnapshot;\n\n // Prefer the protocol-correct composite identity. During the legacy\n // migration, deployed sellers have also copied AAO standard IDs while\n // putting their own creative-agent URL in the tuple. Treat that as an\n // inbound alias only when the AAO catalog publishes exactly one entry for\n // the bare ID. `buildParams` below still rejects contradictory inline\n // dimensions/duration, and the emitted v1_format_ref preserves `fid` so a\n // legacy write routes back to the seller rather than the AAO host.\n const exactCatalogEntry = lookupV1Format(fid, options?._catalogPath);\n const canonicalAgentUrl = canonicalizeAgentUrl(fid.agent_url);\n const mayUseUniqueAlias =\n canonicalAgentUrl !== null &&\n new URL(canonicalAgentUrl).protocol === 'https:' &&\n !isLikelyPrivateUrl(canonicalAgentUrl);\n const uniqueAliasEntry =\n exactCatalogEntry === undefined && mayUseUniqueAlias\n ? lookupUniqueV1FormatById(fid.id, options?._catalogPath)\n : undefined;\n if (uniqueAliasEntry) {\n // A caller-authored converter is more specific than this compatibility\n // heuristic. Returning undefined opts into the AAO bare-ID fallback;\n // invalid/throwing converter output fails closed and is never bypassed.\n const explicit = projectWithLegacyConverter(fid, productId, field, options?.legacyFormatConverter);\n if (explicit) return explicit;\n }\n const catalogEntry = exactCatalogEntry ?? uniqueAliasEntry;\n\n // Step 1: v1 catalog has an explicit `canonical` annotation. Always\n // object-shaped per `canonical-projection-ref.json`: required `kind`,\n // optional `asset_source` + `slots_override`. Carry the refinement\n // fields onto the v2 declaration so the projection preserves the\n // spec-authored intent (generative AI projects with text-prompt slot;\n // native projects with extended slot set; etc.).\n if (catalogEntry?.canonical) {\n const projection = catalogEntry.canonical;\n let params: Record<string, unknown>;\n try {\n params = buildParams(fid, {}, catalogEntry);\n } catch (error) {\n if (!(error instanceof CatalogRequirementConflict)) throw error;\n return {\n diagnostic: {\n source: 'sdk',\n sdk_id: SDK_ID,\n field,\n code: 'FORMAT_PROJECTION_FAILED',\n error: {\n details: {\n format_kind: projection.kind,\n product_id: productId,\n resolution_failure: 'catalog_requirement_conflict',\n },\n },\n },\n };\n }\n if (projection.asset_source) params.asset_source = projection.asset_source;\n if (projection.slots_override) params.slots = projection.slots_override;\n return {\n decl: {\n format_kind: projection.kind,\n params,\n v1_format_ref: [fid],\n },\n };\n }\n\n // Step 1b: catalog HAS the entry but no `canonical:` annotation. This\n // is the AAO saying \"no v2 mapping yet for this category\" — at 3.1\n // GA, native/DOOH/broadcast/card-scaffolding sit in this bucket.\n // Falling through to structural match would shoehorn the format to\n // a coarse `display_tag` based on a `url` asset (or similar) — which\n // contradicts the AAO's deliberate absence of annotation. Fail-closed\n // honestly so the buyer sees \"category not yet v2-mapped\" rather than\n // a semantically wrong projection. Symmetric counterpart to\n // CANONICAL_NOT_V1_TRANSLATABLE on the v2→v1 side.\n if (catalogEntry && !catalogEntry.canonical) {\n const custom = projectWithLegacyConverter(fid, productId, field, options?.legacyFormatConverter);\n if (custom) return custom;\n return {\n diagnostic: {\n source: 'sdk',\n sdk_id: SDK_ID,\n field,\n code: 'FORMAT_PROJECTION_FAILED',\n error: {\n details: {\n format_kind: 'custom',\n product_id: productId,\n resolution_failure: 'catalog_lacks_canonical_annotation',\n },\n },\n },\n };\n }\n\n // Step 2: format not in the AAO catalog. Try registry glob match\n // against format_id.id. Catches publisher-bespoke ids that share the\n // AAO catalog's naming convention.\n const globMatch = forwardLookupByGlob(fid.id);\n if (globMatch) {\n return {\n decl: {\n format_kind: globMatch.canonical,\n params: buildParams(fid, globMatch.parameters),\n v1_format_ref: [fid],\n },\n };\n }\n\n // Step 3: structural match — only fires when the format is NOT in the\n // catalog (Step 1b ate the catalog-known-but-unannotated case). For\n // truly bespoke publisher formats this is the best signal we have:\n // a VAST tag is a VAST tag regardless of seller naming.\n if (catalogEntry?.assets) {\n const assetTypes = catalogEntry.assets.map(a => a.asset_type).filter((t): t is string => typeof t === 'string');\n const structMatch = forwardLookupByStructural({ asset_types: assetTypes });\n if (structMatch) {\n return {\n decl: {\n format_kind: structMatch.canonical,\n params: buildParams(fid, structMatch.parameters, catalogEntry),\n v1_format_ref: [fid],\n },\n };\n }\n }\n\n // Step 4: give the adopter one explicit, typed escape hatch for a\n // seller/creative-agent-owned legacy format. This runs only after all\n // protocol-owned mappings fail, so a callback cannot override a canonical\n // AAO mapping accidentally.\n const custom = projectWithLegacyConverter(fid, productId, field, options?.legacyFormatConverter);\n if (custom) return custom;\n\n // Step 5: fail-closed. v1 product is invisible on the canonical side.\n return {\n diagnostic: {\n source: 'sdk',\n sdk_id: SDK_ID,\n field,\n code: 'FORMAT_PROJECTION_FAILED',\n error: {\n details: {\n format_kind: 'custom',\n product_id: productId,\n resolution_failure: 'no_match',\n },\n },\n },\n };\n}\n\n/**\n * Project a v1 Product to a v2 Product. Drops `format_ids` from the\n * public output and rebuilds `format_options` per the resolution order.\n *\n * Caller decides what to do with the result when `format_options` is\n * empty — typically filter the product out of the response payload to\n * a v2-only buyer (the spec requires `format_options` to have\n * `minItems: 1` when present). The function always returns a Product\n * shape so adopters can inspect what got dropped via diagnostics.\n *\n * @see canonicalDeclarationFromBareId — resolve a single bare format-id\n * string (no surrounding Product) to a declaration or `format_kind`.\n */\nexport function projectV1ProductToV2(v1: V1ProductInput, options?: V1ToV2ProjectionOptions): V1ToV2Result {\n const format_options: V2ProductFormatDeclaration[] = [];\n const diagnostics: ProjectionDiagnostic[] = [];\n\n const inputFormatIds = v1.format_ids ?? [];\n for (let i = 0; i < inputFormatIds.length; i++) {\n const fid = inputFormatIds[i]! as V1FormatId;\n const field = `products[${v1.product_id}].format_ids[${i}]`;\n const { decl, diagnostic } = projectFormatId(fid, v1.product_id, field, options);\n if (decl) {\n format_options.push(\n typeof decl.format_option_id === 'string' && decl.format_option_id.length > 0\n ? decl\n : { ...decl, format_option_id: migratedFormatOptionId(fid) }\n );\n }\n if (diagnostic) diagnostics.push(diagnostic);\n }\n\n const { format_ids: _drop, ...rest } = v1;\n void _drop;\n const v2Product: V2Product = {\n ...(rest as Omit<V1ProductInput, 'format_ids'>),\n format_options,\n } as V2Product;\n\n return { v2: v2Product, diagnostics, legacyRoutes: legacyRoutesForProduct(v1.product_id, format_options) };\n}\n\nexport interface BareFormatIdResolveOptions {\n /**\n * `agent_url` to attach when lifting the bare `id` to a structured\n * {@link V1FormatId} for resolution. Defaults to the canonical AAO host\n * (`https://creative.adcontextprotocol.org/`) — the publisher of every\n * AAO catalog id, and the source of essentially all bare ids persisted\n * before the `{ agent_url, id }` convention. When an exact ID has one\n * unique AAO-published meaning, a valid non-AAO `agentUrl` is accepted as\n * a legacy owner alias and is preserved in `v1_format_ref`. Unknown or\n * colliding IDs still resolve to `null`.\n */\n agentUrl?: string;\n\n /**\n * Asset-type disambiguator for an under-specified bare id. The AAO\n * catalog names per-asset-type variants `<base>_<suffix>` (e.g.\n * `display_300x250` → `display_300x250_image` / `_html` / `_generative`).\n * A size-only bare id like `display_300x250` is genuinely ambiguous and\n * resolves to `null` on its own; pass the asset type you already hold\n * (an adopter's `format_type`) and the resolver retries the disambiguated\n * catalog variant `<id>_<suffix>`.\n *\n * The vocabulary is the catalog asset type where it differs from the\n * variant suffix (`javascript` → `_js`), otherwise the suffix itself\n * (`image`, `html`, `generative`, `js`). Canonical-kind aliases are also\n * accepted (`html5` → `html`, `display_tag` → `js`) for callers already\n * holding a kind-like local value.\n *\n * Only consulted when the bare id does NOT resolve on its own (a real\n * catalog id is authoritative). Still fails closed: if `<id>_<suffix>`\n * is not a catalog entry, returns `null` — the hint narrows, it never\n * fabricates.\n */\n assetType?: string;\n\n /**\n * @deprecated Use `assetType`. Kept as a backwards-compatible alias for\n * callers who adopted the initial helper surface before issue #2289.\n */\n assetTypeHint?: string;\n}\n\n/**\n * Resolve a bare v1 format-id string to its full v2\n * `ProductFormatDeclaration`, or `null` when the id has no canonical\n * mapping.\n *\n * Adopters migrating off legacy format storage routinely hold a bare id\n * (`display_300x250_image`, `video_standard_30s`) persisted before the\n * `{ agent_url, id }` structured-ref convention. This lifts that bare id\n * to a structured ref (via `agentUrl`, default the AAO host) and runs the\n * exact resolution the v1 → v2 product projection uses — in the registry\n * spec's `v1-canonical-mapping.json` resolution order:\n *\n * - AAO catalog `canonical:` annotation — the authoritative\n * seller-asserted mapping (registry resolution-order step 2).\n * - Registry `format_id_glob` literal match (registry resolution-order\n * step 3) — future-proof; 3.1 ships zero literal globs, so this fires\n * only when a future registry adds platform-specific literals.\n *\n * Fails closed: returns `null` — never a guess — when neither path\n * resolves the id. That covers an unknown id, an under-specified id\n * (`display_300x250`, which the catalog only carries as `_image` /\n * `_html` / `_generative` variants), and a catalog entry the AAO has not\n * yet annotated with a `canonical:`. Structural matching never\n * contributes a kind: a bare id absent from the catalog carries no asset\n * shape to match on, and a catalog entry lacking a `canonical:` fails\n * closed before the structural step is reached.\n *\n * For an under-specified bare id, pass `assetType` (the asset type you\n * already hold, such as an adopter's `format_type`) and the resolver retries\n * the disambiguated catalog variant\n * `<id>_<suffix>` — so the SDK owns the `_image` / `_html` suffix\n * convention instead of every adopter re-deriving it. The hint is\n * consulted only when the bare id doesn't resolve on its own, and still\n * fails closed when the disambiguated id isn't a catalog entry.\n *\n * The returned declaration carries `v1_format_ref: [{ agent_url, id }]`\n * (the resolved id — the disambiguated `<id>_<suffix>` when a hint\n * applied), so adopters lift a bare id to a structured ref in one step\n * (the pre-projection step the migration docs encourage).\n *\n * Like the rest of the projection layer, this requires the bundled AAO\n * catalog + canonical-mapping registry; it throws (rather than returning\n * `null`) only when those are missing from the install — a corrupted\n * `@adcp/sdk` package, not a normal unresolved-id outcome.\n *\n * For just the `format_kind`, use {@link resolveCanonicalFormatKind}. For\n * the structured diagnostic explaining *why* an id did not resolve, run\n * it through {@link projectV1ProductToV2} inside a one-format product.\n */\nexport function canonicalDeclarationFromBareId(\n id: string,\n options?: BareFormatIdResolveOptions\n): V2ProductFormatDeclaration | null {\n if (!id) return null;\n const agentUrl = options?.agentUrl ?? AAO_CANONICAL_AGENT_URL;\n\n // A real catalog id is authoritative — resolve it directly first.\n const direct = projectFormatId({ agent_url: agentUrl, id }, `<bare:${id}>`, `bareFormatId(${id})`).decl;\n if (direct) return direct;\n\n // Under-specified bare id + an asset-type hint: retry the disambiguated\n // catalog variant `<id>_<suffix>`. Fails closed if that isn't a catalog\n // entry either — the hint narrows, it never fabricates.\n const assetType = options?.assetType ?? options?.assetTypeHint;\n const suffix = assetType ? normalizeAssetTypeSuffix(assetType) : '';\n if (suffix) {\n const disambiguated = `${id}_${suffix}`;\n const hinted = projectFormatId(\n { agent_url: agentUrl, id: disambiguated },\n `<bare:${disambiguated}>`,\n `bareFormatId(${disambiguated})`\n ).decl;\n if (hinted) return hinted;\n }\n\n return null;\n}\n\n/**\n * Map an `assetType` to the AAO catalog's `<base>_<suffix>` suffix.\n * Catalog asset type `javascript` and canonical-kind names that differ from\n * their suffix (`html5`, `display_tag`) are aliased. Any other value is passed\n * through lowercased so a future asset type or suffix resolves without a code\n * change — an unknown value simply misses the catalog and the caller fails\n * closed.\n */\nfunction normalizeAssetTypeSuffix(hint: string): string {\n const h = hint.trim().toLowerCase();\n if (h === 'html5') return 'html';\n if (h === 'javascript') return 'js';\n if (h === 'display_tag') return 'js';\n return h;\n}\n\n/**\n * Resolve a bare v1 format-id string to its canonical `format_kind`, or\n * `null` when the id has no canonical mapping. Registry- and\n * catalog-backed: the single source of truth that replaces hand-rolled\n * `inferFormatKindFromFormatId` heuristics adopters maintain locally.\n *\n * Thin projection of {@link canonicalDeclarationFromBareId} down to the\n * `format_kind`; see it for the resolution order, fail-closed semantics,\n * the `agentUrl` default, and the `assetType` disambiguator.\n */\nexport function resolveCanonicalFormatKind(\n id: string,\n options?: BareFormatIdResolveOptions\n): CanonicalFormatKind | null {\n return canonicalDeclarationFromBareId(id, options)?.format_kind ?? null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyDA,sBAA+D;AAC/D,qBAAkF;AAClF,uBAAwC;AACxC,qBAAgC;AAChC,qBAA+C;AAC/C,8BAA0F;AAC1F,sCAAqC;AACrC,4BAAmC;AACnC,oBAA2B;AAC3B,2BAAuC;AAGvC,MAAM,SAAS,aAAa,8BAAe;AAE3C,MAAM,mCAAmC,MAAM;AAAC;AAShD,SAAS,4BAA4B,UAA0B;AAC7D,aAAO,0BAAW,UAAU,EAAE,EAAE,OAAO,QAAQ,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,EAAE;AAC5E;AAQA,SAAS,uBAAuB,KAAyB;AACvD,QAAM,WAAW,KAAK,UAAU;AAAA,IAC9B,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI,SAAS;AAAA,IACb,IAAI,UAAU;AAAA,IACd,IAAI,eAAe;AAAA,EACrB,CAAC;AACD,SAAO,YAAY,4BAA4B,QAAQ,CAAC;AAC1D;AAgEA,SAAS,YACP,KACA,gBACA,cACyB;AACzB,QAAM,SAAkC,EAAE,GAAG,eAAe;AAO5D,QAAM,aAAa,oBAAI,IAA+C;AACtE,MAAI,gCAAgC;AACpC,aAAW,UAAU,cAAc,WAAW,CAAC,GAAG;AAChD,UAAM,QAAQ,OAAO,YAAY;AACjC,UAAM,SAAS,OAAO,YAAY;AAClC,QAAI,UAAU,UAAa,WAAW,OAAW;AACjD,QACE,OAAO,UAAU,YACjB,OAAO,UAAU,KAAK,KACtB,QAAQ,KACR,OAAO,WAAW,YAClB,OAAO,UAAU,MAAM,KACvB,SAAS,GACT;AACA,iBAAW,IAAI,GAAG,KAAK,IAAI,MAAM,IAAI,EAAE,OAAO,OAAO,CAAC;AAAA,IACxD,MAAO,iCAAgC;AAAA,EACzC;AACA,aAAW,SAAS,cAAc,UAAU,CAAC,GAAG;AAC9C,UAAM,QAAQ,MAAM,cAAc;AAClC,UAAM,SAAS,MAAM,cAAc;AACnC,UAAM,WAAW,MAAM,cAAc;AACrC,UAAM,WAAW,MAAM,cAAc;AACrC,UAAM,YAAY,MAAM,cAAc;AACtC,UAAM,YAAY,MAAM,cAAc;AACtC,QAAI,aAAa,UAAa,aAAa,UAAa,cAAc,UAAa,cAAc,QAAW;AAC1G,UACE,OAAO,aAAa,YACpB,OAAO,UAAU,QAAQ,KACzB,WAAW,KACX,aAAa,YACb,OAAO,cAAc,YACrB,OAAO,UAAU,SAAS,KAC1B,YAAY,KACZ,cAAc,WACd;AACA,mBAAW,IAAI,GAAG,QAAQ,IAAI,SAAS,IAAI,EAAE,OAAO,UAAU,QAAQ,UAAU,CAAC;AAAA,MACnF,OAAO;AACL,wCAAgC;AAAA,MAClC;AAAA,IACF;AACA,QAAI,UAAU,UAAa,WAAW,OAAW;AACjD,QACE,OAAO,UAAU,YACjB,OAAO,UAAU,KAAK,KACtB,QAAQ,KACR,OAAO,WAAW,YAClB,OAAO,UAAU,MAAM,KACvB,SAAS,GACT;AACA,iBAAW,IAAI,GAAG,KAAK,IAAI,MAAM,IAAI,EAAE,OAAO,OAAO,CAAC;AAAA,IACxD,MAAO,iCAAgC;AAAA,EACzC;AACA,MAAI,WAAW,OAAO,KAAK,+BAA+B;AACxD,UAAM,IAAI,2BAA2B,+CAA+C;AAAA,EACtF;AACA,MAAI,WAAW,SAAS,GAAG;AACzB,UAAM,YAAY,WAAW,OAAO,EAAE,KAAK,EAAE;AAC7C,QAAI,WAAW;AACb,UACG,OAAO,IAAI,UAAU,YAAY,IAAI,UAAU,UAAU,SACzD,OAAO,IAAI,WAAW,YAAY,IAAI,WAAW,UAAU,QAC5D;AACA,cAAM,IAAI,2BAA2B,6CAA6C;AAAA,MACpF;AACA,aAAO,QAAQ,UAAU;AACzB,aAAO,SAAS,UAAU;AAAA,IAC5B;AAAA,EACF;AAEA,QAAM,iBAAiB,oBAAI,IAAY;AACvC,MAAI,oBAAoB;AACxB,aAAW,SAAS,cAAc,UAAU,CAAC,GAAG;AAC9C,UAAM,MAAM,MAAM,cAAc;AAChC,UAAM,MAAM,MAAM,cAAc;AAChC,QAAI,QAAQ,UAAa,QAAQ,OAAW;AAC5C,QACG,QAAQ,WAAc,OAAO,QAAQ,YAAY,CAAC,OAAO,UAAU,GAAG,KAAK,OAAO,MAClF,QAAQ,WAAc,OAAO,QAAQ,YAAY,CAAC,OAAO,UAAU,GAAG,KAAK,OAAO,MAClF,OAAO,QAAQ,YAAY,OAAO,QAAQ,YAAY,MAAM,KAC7D;AACA,YAAM,IAAI,2BAA2B,gDAAgD;AAAA,IACvF;AACA,QAAI,OAAO,QAAQ,YAAY,QAAQ,IAAK,gBAAe,IAAI,GAAG;AAAA,QAC7D,qBAAoB;AAAA,EAC3B;AACA,MAAI,eAAe,OAAO,KAAK,mBAAmB;AAChD,UAAM,IAAI,2BAA2B,8CAA8C;AAAA,EACrF;AACA,MAAI,eAAe,SAAS,GAAG;AAC7B,UAAM,gBAAgB,eAAe,OAAO,EAAE,KAAK,EAAE;AACrD,QAAI,kBAAkB,QAAW;AAC/B,UAAI,OAAO,IAAI,gBAAgB,YAAY,IAAI,gBAAgB,eAAe;AAC5E,cAAM,IAAI,2BAA2B,2CAA2C;AAAA,MAClF;AACA,aAAO,oBAAoB;AAAA,IAC7B;AAAA,EACF;AAIA,MAAI,OAAO,IAAI,UAAU,SAAU,QAAO,QAAQ,IAAI;AACtD,MAAI,OAAO,IAAI,WAAW,SAAU,QAAO,SAAS,IAAI;AACxD,MAAI,OAAO,IAAI,gBAAgB,SAAU,QAAO,oBAAoB,IAAI;AACxE,SAAO;AACT;AAEA,SAAS,2BAA2B,OAAgB,OAAO,oBAAI,QAAgB,GAAuB;AACpG,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO;AACxD,MAAI,KAAK,IAAI,KAAK,EAAG,QAAO;AAC5B,OAAK,IAAI,KAAK;AACd,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,eAAW,QAAQ,OAAO;AACxB,YAAM,SAAS,2BAA2B,MAAM,IAAI;AACpD,UAAI,OAAQ,QAAO;AAAA,IACrB;AACA,WAAO;AAAA,EACT;AACA,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAgC,GAAG;AAC3E,QAAI,oDAAoD,KAAK,GAAG,GAAG;AACjE,aAAO;AAAA,IACT;AACA,UAAM,SAAS,2BAA2B,OAAO,IAAI;AACrD,QAAI,OAAQ,QAAO;AAAA,EACrB;AACA,SAAO;AACT;AAEA,SAAS,2BACP,KACA,WACA,OACA,WACsF;AACtF,MAAI,CAAC,UAAW,QAAO;AACvB,MAAI;AACF,UAAM,YAAY,UAAU,EAAE,UAAU,EAAE,GAAG,IAAI,GAAG,WAAW,MAAM,CAAC;AACtE,QAAI,CAAC,UAAW,QAAO;AACvB,UAAM,YAAY,2BAA2B,SAAS;AACtD,QAAI,WAAW;AACb,YAAM,IAAI,MAAM,wCAAwC,SAAS,EAAE;AAAA,IACrE;AACA,UAAM,YAAY,EAAE,GAAG,WAAW,eAAe,CAAC,GAAG,EAAE;AACvD,QAAI,UAAU,2BAA2B,MAAM;AAC7C,YAAM,IAAI,MAAM,2EAA2E;AAAA,IAC7F;AACA,QACE,UAAU,gBAAgB,aACzB,OAAO,UAAU,iBAAiB,YACjC,UAAU,aAAa,KAAK,EAAE,WAAW,KACzC,CAAC,UAAU,gBACb;AACA,YAAM,IAAI,MAAM,2DAA2D;AAAA,IAC7E;AACA,QACE,UAAU,gBAAgB,aACzB,OAAO,UAAU,qBAAqB,YAAY,UAAU,iBAAiB,KAAK,EAAE,WAAW,IAChG;AACA,YAAM,IAAI,MAAM,6CAA6C;AAAA,IAC/D;AACA,UAAM,SAAS,8CAA+B,UAAU,SAAS;AACjE,QAAI,CAAC,OAAO,SAAS;AACnB,YAAM,IAAI,MAAM,4DAA4D;AAAA,IAC9E;AACA,WAAO,EAAE,MAAM,OAAO,KAAmC;AAAA,EAC3D,QAAQ;AACN,WAAO;AAAA,MACL,YAAY;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR;AAAA,QACA,MAAM;AAAA,QACN,OAAO;AAAA,UACL,SAAS;AAAA,YACP,aAAa;AAAA,YACb,YAAY;AAAA,YACZ,oBAAoB;AAAA,UACtB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAMA,SAAS,gBACP,KACA,WACA,OACA,SAC0E;AAC1E,QAAM,WAAW,IAAI,UAAU;AAC/B,QAAM,YAAY,IAAI,WAAW;AACjC,QAAM,oBACJ,aAAa,aACZ,aAAa,CAAC,OAAO,UAAU,IAAI,KAAK,KAAK,IAAI,SAAU,MAC3D,cAAc,CAAC,OAAO,UAAU,IAAI,MAAM,KAAK,IAAI,UAAW;AACjE,QAAM,kBAAkB,IAAI,gBAAgB,WAAc,CAAC,OAAO,UAAU,IAAI,WAAW,KAAK,IAAI,eAAe;AACnH,MAAI,qBAAqB,iBAAiB;AACxC,WAAO;AAAA,MACL,YAAY;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR;AAAA,QACA,MAAM;AAAA,QACN,OAAO;AAAA,UACL,SAAS;AAAA,YACP,aAAa;AAAA,YACb,YAAY;AAAA,YACZ,oBAAoB;AAAA,UACtB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAMA,QAAM,kBAAkB;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,QACA,mEAA0C,SAAS,kBAAkB;AAAA,EACvE;AACA,MAAI,gBAAiB,QAAO;AAS5B,QAAM,wBAAoB,+BAAe,KAAK,SAAS,YAAY;AACnE,QAAM,wBAAoB,sDAAqB,IAAI,SAAS;AAC5D,QAAM,oBACJ,sBAAsB,QACtB,IAAI,IAAI,iBAAiB,EAAE,aAAa,YACxC,KAAC,0CAAmB,iBAAiB;AACvC,QAAM,mBACJ,sBAAsB,UAAa,wBAC/B,yCAAyB,IAAI,IAAI,SAAS,YAAY,IACtD;AACN,MAAI,kBAAkB;AAIpB,UAAM,WAAW,2BAA2B,KAAK,WAAW,OAAO,SAAS,qBAAqB;AACjG,QAAI,SAAU,QAAO;AAAA,EACvB;AACA,QAAM,eAAe,qBAAqB;AAQ1C,MAAI,cAAc,WAAW;AAC3B,UAAM,aAAa,aAAa;AAChC,QAAI;AACJ,QAAI;AACF,eAAS,YAAY,KAAK,CAAC,GAAG,YAAY;AAAA,IAC5C,SAAS,OAAO;AACd,UAAI,EAAE,iBAAiB,4BAA6B,OAAM;AAC1D,aAAO;AAAA,QACL,YAAY;AAAA,UACV,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR;AAAA,UACA,MAAM;AAAA,UACN,OAAO;AAAA,YACL,SAAS;AAAA,cACP,aAAa,WAAW;AAAA,cACxB,YAAY;AAAA,cACZ,oBAAoB;AAAA,YACtB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,QAAI,WAAW,aAAc,QAAO,eAAe,WAAW;AAC9D,QAAI,WAAW,eAAgB,QAAO,QAAQ,WAAW;AACzD,WAAO;AAAA,MACL,MAAM;AAAA,QACJ,aAAa,WAAW;AAAA,QACxB;AAAA,QACA,eAAe,CAAC,GAAG;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AAWA,MAAI,gBAAgB,CAAC,aAAa,WAAW;AAC3C,UAAMA,UAAS,2BAA2B,KAAK,WAAW,OAAO,SAAS,qBAAqB;AAC/F,QAAIA,QAAQ,QAAOA;AACnB,WAAO;AAAA,MACL,YAAY;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR;AAAA,QACA,MAAM;AAAA,QACN,OAAO;AAAA,UACL,SAAS;AAAA,YACP,aAAa;AAAA,YACb,YAAY;AAAA,YACZ,oBAAoB;AAAA,UACtB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAKA,QAAM,gBAAY,qCAAoB,IAAI,EAAE;AAC5C,MAAI,WAAW;AACb,WAAO;AAAA,MACL,MAAM;AAAA,QACJ,aAAa,UAAU;AAAA,QACvB,QAAQ,YAAY,KAAK,UAAU,UAAU;AAAA,QAC7C,eAAe,CAAC,GAAG;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AAMA,MAAI,cAAc,QAAQ;AACxB,UAAM,aAAa,aAAa,OAAO,IAAI,OAAK,EAAE,UAAU,EAAE,OAAO,CAAC,MAAmB,OAAO,MAAM,QAAQ;AAC9G,UAAM,kBAAc,2CAA0B,EAAE,aAAa,WAAW,CAAC;AACzE,QAAI,aAAa;AACf,aAAO;AAAA,QACL,MAAM;AAAA,UACJ,aAAa,YAAY;AAAA,UACzB,QAAQ,YAAY,KAAK,YAAY,YAAY,YAAY;AAAA,UAC7D,eAAe,CAAC,GAAG;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAMA,QAAM,SAAS,2BAA2B,KAAK,WAAW,OAAO,SAAS,qBAAqB;AAC/F,MAAI,OAAQ,QAAO;AAGnB,SAAO;AAAA,IACL,YAAY;AAAA,MACV,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR;AAAA,MACA,MAAM;AAAA,MACN,OAAO;AAAA,QACL,SAAS;AAAA,UACP,aAAa;AAAA,UACb,YAAY;AAAA,UACZ,oBAAoB;AAAA,QACtB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAeO,SAAS,qBAAqB,IAAoB,SAAiD;AACxG,QAAM,iBAA+C,CAAC;AACtD,QAAM,cAAsC,CAAC;AAE7C,QAAM,iBAAiB,GAAG,cAAc,CAAC;AACzC,WAAS,IAAI,GAAG,IAAI,eAAe,QAAQ,KAAK;AAC9C,UAAM,MAAM,eAAe,CAAC;AAC5B,UAAM,QAAQ,YAAY,GAAG,UAAU,gBAAgB,CAAC;AACxD,UAAM,EAAE,MAAM,WAAW,IAAI,gBAAgB,KAAK,GAAG,YAAY,OAAO,OAAO;AAC/E,QAAI,MAAM;AACR,qBAAe;AAAA,QACb,OAAO,KAAK,qBAAqB,YAAY,KAAK,iBAAiB,SAAS,IACxE,OACA,EAAE,GAAG,MAAM,kBAAkB,uBAAuB,GAAG,EAAE;AAAA,MAC/D;AAAA,IACF;AACA,QAAI,WAAY,aAAY,KAAK,UAAU;AAAA,EAC7C;AAEA,QAAM,EAAE,YAAY,OAAO,GAAG,KAAK,IAAI;AACvC,OAAK;AACL,QAAM,YAAuB;AAAA,IAC3B,GAAI;AAAA,IACJ;AAAA,EACF;AAEA,SAAO,EAAE,IAAI,WAAW,aAAa,kBAAc,6CAAuB,GAAG,YAAY,cAAc,EAAE;AAC3G;AA6FO,SAAS,+BACd,IACA,SACmC;AACnC,MAAI,CAAC,GAAI,QAAO;AAChB,QAAM,WAAW,SAAS,YAAY;AAGtC,QAAM,SAAS,gBAAgB,EAAE,WAAW,UAAU,GAAG,GAAG,SAAS,EAAE,KAAK,gBAAgB,EAAE,GAAG,EAAE;AACnG,MAAI,OAAQ,QAAO;AAKnB,QAAM,YAAY,SAAS,aAAa,SAAS;AACjD,QAAM,SAAS,YAAY,yBAAyB,SAAS,IAAI;AACjE,MAAI,QAAQ;AACV,UAAM,gBAAgB,GAAG,EAAE,IAAI,MAAM;AACrC,UAAM,SAAS;AAAA,MACb,EAAE,WAAW,UAAU,IAAI,cAAc;AAAA,MACzC,SAAS,aAAa;AAAA,MACtB,gBAAgB,aAAa;AAAA,IAC/B,EAAE;AACF,QAAI,OAAQ,QAAO;AAAA,EACrB;AAEA,SAAO;AACT;AAUA,SAAS,yBAAyB,MAAsB;AACtD,QAAM,IAAI,KAAK,KAAK,EAAE,YAAY;AAClC,MAAI,MAAM,QAAS,QAAO;AAC1B,MAAI,MAAM,aAAc,QAAO;AAC/B,MAAI,MAAM,cAAe,QAAO;AAChC,SAAO;AACT;AAYO,SAAS,2BACd,IACA,SAC4B;AAC5B,SAAO,+BAA+B,IAAI,OAAO,GAAG,eAAe;AACrE;","names":["custom"]}
|