Skip to content

Commit afb67fd

Browse files
authored
Merge pull request #120 from agility/fix/asset-url-mapping-PROD-915
fix: correct asset URL rewriting during push (PROD-915)
2 parents bbfb8ec + eb4d646 commit afb67fd

4 files changed

Lines changed: 67 additions & 19 deletions

File tree

package-lock.json

Lines changed: 2 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@agility/cli",
3-
"version": "1.0.0-beta.13.4",
3+
"version": "1.0.0-beta.13.5",
44
"description": "Agility CLI for working with your content. (Public Beta)",
55
"repository": {
66
"type": "git",

src/lib/content/content-field-mapper.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -245,13 +245,20 @@ export class ContentFieldMapper {
245245

246246
private mapAssetUrl(sourceUrl: string, context?: ContentFieldMappingContext): string {
247247

248-
// Try to find the asset by URL in the asset mapper
248+
// Try exact URL match first
249249
const assetMapping = context.assetMapper.getAssetMappingByMediaUrl(sourceUrl, "source");
250250
if (assetMapping) {
251-
const asset = assetMapping as any;
252-
return asset.originUrl || asset.url || asset.edgeUrl || sourceUrl;
253-
}
251+
// If exact match, use the target URL directly
252+
if (assetMapping.sourceUrl === sourceUrl) {
253+
return assetMapping.targetUrl || sourceUrl;
254+
}
254255

256+
// Container prefix match — swap source container for target, preserving subfolder path
257+
const remapped = context.assetMapper.remapUrlByContainer(sourceUrl, "source");
258+
if (remapped) return remapped;
259+
260+
return assetMapping.targetUrl || sourceUrl;
261+
}
255262

256263
// Return original URL if no mapping found
257264
return sourceUrl;

src/lib/mappers/asset-mapper.ts

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ interface AssetMapping {
1010
targetMediaID: number;
1111
sourceUrl?: string;
1212
targetUrl?: string;
13+
sourceContainerEdgeUrl?: string;
14+
targetContainerEdgeUrl?: string;
15+
sourceContainerOriginUrl?: string;
16+
targetContainerOriginUrl?: string;
1317
}
1418

1519

@@ -44,9 +48,48 @@ export class AssetMapper {
4448
}
4549

4650
getAssetMappingByMediaUrl(url: string, type: 'source' | 'target'): AssetMapping | null {
47-
const mapping = this.mappings.find((m: AssetMapping) => type === 'source' ? m.sourceUrl === url : m.targetUrl === url);
51+
// Try exact match first
52+
const exact = this.mappings.find((m: AssetMapping) => type === 'source' ? m.sourceUrl === url : m.targetUrl === url);
53+
if (exact) return exact;
54+
55+
// Fallback: match by container prefix (handles subfolder paths like /mobile/feature-carousel/)
56+
return this.findMappingByContainerPrefix(url, type);
57+
}
58+
59+
/**
60+
* Remap a URL from source container to target container, preserving any subfolder path.
61+
* e.g. "cdn-usa2.aglty.io/brightstar-tns-cat/mobile/feature-carousel/file.png"
62+
* → "cdn-usa2.aglty.io/2151a7f2/mobile/feature-carousel/file.png"
63+
*
64+
* Returns null if the URL doesn't match any mapping's container prefix.
65+
*/
66+
remapUrlByContainer(url: string, type: 'source' | 'target'): string | null {
67+
const mapping = this.findMappingByContainerPrefix(url, type);
4868
if (!mapping) return null;
49-
return mapping;
69+
70+
// Determine which container URLs to use based on whether this is an edge or origin URL
71+
const sourceEdge = type === 'source' ? mapping.sourceContainerEdgeUrl : mapping.targetContainerEdgeUrl;
72+
const targetEdge = type === 'source' ? mapping.targetContainerEdgeUrl : mapping.sourceContainerEdgeUrl;
73+
const sourceOrigin = type === 'source' ? mapping.sourceContainerOriginUrl : mapping.targetContainerOriginUrl;
74+
const targetOrigin = type === 'source' ? mapping.targetContainerOriginUrl : mapping.sourceContainerOriginUrl;
75+
76+
// Try edge URL swap first, then origin URL swap
77+
if (sourceEdge && targetEdge && url.startsWith(sourceEdge)) {
78+
return url.replace(sourceEdge, targetEdge);
79+
}
80+
if (sourceOrigin && targetOrigin && url.startsWith(sourceOrigin)) {
81+
return url.replace(sourceOrigin, targetOrigin);
82+
}
83+
84+
return null;
85+
}
86+
87+
private findMappingByContainerPrefix(url: string, type: 'source' | 'target'): AssetMapping | null {
88+
return this.mappings.find((m: AssetMapping) => {
89+
const edgeUrl = type === 'source' ? m.sourceContainerEdgeUrl : m.targetContainerEdgeUrl;
90+
const originUrl = type === 'source' ? m.sourceContainerOriginUrl : m.targetContainerOriginUrl;
91+
return (edgeUrl && url.startsWith(edgeUrl + '/')) || (originUrl && url.startsWith(originUrl + '/'));
92+
}) || null;
5093
}
5194

5295
getMappedEntity(mapping: AssetMapping, type: 'source' | 'target'): mgmtApi.Media | null {
@@ -75,7 +118,10 @@ export class AssetMapper {
75118
targetMediaID: targetAsset.mediaID,
76119
sourceUrl: sourceAsset.edgeUrl,
77120
targetUrl: targetAsset.edgeUrl,
78-
121+
sourceContainerEdgeUrl: sourceAsset.containerEdgeUrl,
122+
targetContainerEdgeUrl: targetAsset.containerEdgeUrl,
123+
sourceContainerOriginUrl: sourceAsset.containerOriginUrl,
124+
targetContainerOriginUrl: targetAsset.containerOriginUrl,
79125
}
80126

81127
this.mappings.push(newMapping);
@@ -95,6 +141,10 @@ export class AssetMapper {
95141
mapping.targetMediaID = targetAsset.mediaID;
96142
mapping.sourceUrl = sourceAsset.edgeUrl;
97143
mapping.targetUrl = targetAsset.edgeUrl;
144+
mapping.sourceContainerEdgeUrl = sourceAsset.containerEdgeUrl;
145+
mapping.targetContainerEdgeUrl = targetAsset.containerEdgeUrl;
146+
mapping.sourceContainerOriginUrl = sourceAsset.containerOriginUrl;
147+
mapping.targetContainerOriginUrl = targetAsset.containerOriginUrl;
98148
}
99149
this.saveMapping();
100150
}

0 commit comments

Comments
 (0)