Context
@adcp/client 5.x uses json-schema-to-typescript to generate TypeScript types from the AdCP JSON schemas. When the same asset schema is referenced from two parent schemas, the generator emits a numerically-suffixed duplicate type for the inline form. This surfaces as the following exported types in core.generated.ts:
VASTAsset (from creative/asset-types) and VASTAsset1 (from creative-asset.json's asset map)
DAASTAsset and DAASTAsset1
BriefAsset and BriefAsset1
CatalogAsset and CatalogAsset1
CreativeAsset1 (from creative-manifest.json referencing creative-asset.json)
The two forms are NOT byte-identical — VASTAsset is the wrapped form ({ asset_type: 'vast', vast_version, vpaid_enabled, captions_url, … } & (url|inline)), while VASTAsset1 is just the inner discriminated (url|inline) union exposed inline inside creative-asset.json's asset map. Both shapes are valid public types — but the 1 suffix reads as a versioning artifact and makes consumer imports harder to review.
AgeVerificationMethod was the same artifact and got fixed upstream by introducing a single $ref to enums/age-verification-method.json so json-schema-to-typescript only emits one type. This issue tracks the equivalent fix for the asset-variant refs.
Repro
git clone https://github.com/adcontextprotocol/adcp-client
cd adcp-client
npm i && npm run sync-schemas && npm run generate-types
grep -E '^export type (VAST|DAAST|Brief|Catalog)Asset1' src/lib/types/core.generated.ts
# → emits VASTAsset1, DAASTAsset1, BriefAsset1, CatalogAsset1
Where the duplication originates
The asset map in core/creative-asset.json and core/creative-manifest.json both inline a oneOf over the asset variant schemas:
{
"oneOf": [
{ "$ref": "/schemas/3.0.1/core/assets/vast-asset.json" },
{ "$ref": "/schemas/3.0.1/core/assets/daast-asset.json" },
{ "$ref": "/schemas/3.0.1/core/assets/brief-asset.json" },
{ "$ref": "/schemas/3.0.1/core/assets/catalog-asset.json" },
…
]
}
The generator hoists the inline form a second time when it crosses the second parent.
Suggested fix
Two options, in increasing order of churn:
Option A — promote the shared inline-variant union to its own schema file. Create something like core/assets/asset-variant.json that is the oneOf union, and have both creative-asset.json and creative-manifest.json reference that single schema. json-schema-to-typescript then emits one shared type instead of two suffixed copies.
Option B — inline the variant union as a JSON Schema $defs in a single canonical location (e.g. inside creative-asset.json's top-level $defs) and have other parents reference creative-asset.json#/$defs/asset-variant. Less invasive than (A) but still produces a single emitted type.
Either is fine; option (A) is cleaner because the variant list isn't a 'private' concept of creative-asset.json — it's the canonical list of inline asset forms.
SDK-side workaround we are NOT pursuing
Renaming *Asset1 to Inline*AssetDelivery via a post-process step on core.generated.ts is straightforward (~50 LOC + alias map). We've decided against it because the right fix is at the schema source — bandaiding in the SDK compounds drift across implementations.
Cross-ref
🤖 Filed by Claude Code on behalf of @bokelley
Context
@adcp/client5.x usesjson-schema-to-typescriptto generate TypeScript types from the AdCP JSON schemas. When the same asset schema is referenced from two parent schemas, the generator emits a numerically-suffixed duplicate type for the inline form. This surfaces as the following exported types incore.generated.ts:VASTAsset(fromcreative/asset-types) andVASTAsset1(fromcreative-asset.json's asset map)DAASTAssetandDAASTAsset1BriefAssetandBriefAsset1CatalogAssetandCatalogAsset1CreativeAsset1(fromcreative-manifest.jsonreferencingcreative-asset.json)The two forms are NOT byte-identical —
VASTAssetis the wrapped form ({ asset_type: 'vast', vast_version, vpaid_enabled, captions_url, … } & (url|inline)), whileVASTAsset1is just the inner discriminated(url|inline)union exposed inline insidecreative-asset.json's asset map. Both shapes are valid public types — but the1suffix reads as a versioning artifact and makes consumer imports harder to review.AgeVerificationMethodwas the same artifact and got fixed upstream by introducing a single$reftoenums/age-verification-method.jsonso json-schema-to-typescript only emits one type. This issue tracks the equivalent fix for the asset-variant refs.Repro
Where the duplication originates
The asset map in
core/creative-asset.jsonandcore/creative-manifest.jsonboth inline aoneOfover the asset variant schemas:{ "oneOf": [ { "$ref": "/schemas/3.0.1/core/assets/vast-asset.json" }, { "$ref": "/schemas/3.0.1/core/assets/daast-asset.json" }, { "$ref": "/schemas/3.0.1/core/assets/brief-asset.json" }, { "$ref": "/schemas/3.0.1/core/assets/catalog-asset.json" }, … ] }The generator hoists the inline form a second time when it crosses the second parent.
Suggested fix
Two options, in increasing order of churn:
Option A — promote the shared inline-variant union to its own schema file. Create something like
core/assets/asset-variant.jsonthat is theoneOfunion, and have bothcreative-asset.jsonandcreative-manifest.jsonreference that single schema. json-schema-to-typescript then emits one shared type instead of two suffixed copies.Option B — inline the variant union as a JSON Schema
$defsin a single canonical location (e.g. insidecreative-asset.json's top-level$defs) and have other parents referencecreative-asset.json#/$defs/asset-variant. Less invasive than (A) but still produces a single emitted type.Either is fine; option (A) is cleaner because the variant list isn't a 'private' concept of
creative-asset.json— it's the canonical list of inline asset forms.SDK-side workaround we are NOT pursuing
Renaming
*Asset1toInline*AssetDeliveryvia a post-process step oncore.generated.tsis straightforward (~50 LOC + alias map). We've decided against it because the right fix is at the schema source — bandaiding in the SDK compounds drift across implementations.Cross-ref
@adcp/clientissue: Rename SCREAMING_SNAKE schema artifacts (RATE_LIMITEDDetails, AgeVerificationMethod1) propagated by json-schema-to-typescript adcp-client#942@adcp/clientproject memory documenting thejson-schema-to-typescriptartifact: project_jsts_numbered_dupes.mdAgeVerificationMethod/AgeVerificationMethod1was the same artifact, fixed upstream via single$ref.🤖 Filed by Claude Code on behalf of @bokelley