From 4ecc2c6fde6c6d1935bb3b847e8acf88ace05a83 Mon Sep 17 00:00:00 2001 From: Max Ostapenko <1611259+max-ostapenko@users.noreply.github.com> Date: Sun, 25 Jan 2026 16:43:09 +0100 Subject: [PATCH 1/2] feat: Add parsing and inclusion of DSR delete JSON for data subject rights. Signed-off-by: Max Ostapenko <1611259+max-ostapenko@users.noreply.github.com> --- dist/ads.js | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/dist/ads.js b/dist/ads.js index d647d32..4e81ff4 100644 --- a/dist/ads.js +++ b/dist/ads.js @@ -177,15 +177,48 @@ const parseSellersJSON = async (response) => { return result; } + +// https://github.com/InteractiveAdvertisingBureau/Data-Subject-Rights/blob/main/Data%20Deletion%20Request%20Framework.md +const parseDSRDeleteJSON = async (response) => { + let content; + try { + content = JSON.parse(await response.text()); + } catch { + content = null; + } + let result = { + present: isPresent(response, ['/dsrdelete.json']), + status: response.status, + redirected: response.redirected, + }; + + if (result.present && content) { + result = { + ...result, + redirected_to: response.redirected ? response.url : null, + endpoint: content.endpoint || null, + pollFrequency: content.pollFrequency || null, + identifiers: content.identifiers ? content.identifiers.map(({ type, format }) => ({ type, format })) : null, + vendorScriptRequirement: typeof content.vendorScriptRequirement === 'boolean' ? content.vendorScriptRequirement : null, + vendorScript: typeof content.vendorScript === 'string' ? true : null, + dsrdeleteJsonUri: content.dsrdeleteJsonUri || null, + }; + } + + return result; +} + return Promise.all([ fetchAndParse("/ads.txt", parseAdsTxt).catch(e => e), fetchAndParse("/app-ads.txt", parseAdsTxt).catch(e => e), fetchAndParse("/sellers.json", parseSellersJSON).catch(e => e), + fetchAndParse("/dsrdelete.json", parseDSRDeleteJSON).catch(e => e), ]).then((all_data) => { return JSON.stringify({ ads: all_data[0], app_ads: all_data[1], - sellers: all_data[2] + sellers: all_data[2], + dsrdelete: all_data[3] }); }).catch(error => { return JSON.stringify({ From 6a9f070070d5f0fc4de6406aa1602f80794b7f7c Mon Sep 17 00:00:00 2001 From: Max Ostapenko <1611259+max-ostapenko@users.noreply.github.com> Date: Sun, 25 Jan 2026 16:58:15 +0100 Subject: [PATCH 2/2] refactor: skip result object properties conditionally when content properties are missing Signed-off-by: Max Ostapenko <1611259+max-ostapenko@users.noreply.github.com> --- dist/ads.js | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/dist/ads.js b/dist/ads.js index 4e81ff4..639fdfb 100644 --- a/dist/ads.js +++ b/dist/ads.js @@ -193,16 +193,13 @@ const parseDSRDeleteJSON = async (response) => { }; if (result.present && content) { - result = { - ...result, - redirected_to: response.redirected ? response.url : null, - endpoint: content.endpoint || null, - pollFrequency: content.pollFrequency || null, - identifiers: content.identifiers ? content.identifiers.map(({ type, format }) => ({ type, format })) : null, - vendorScriptRequirement: typeof content.vendorScriptRequirement === 'boolean' ? content.vendorScriptRequirement : null, - vendorScript: typeof content.vendorScript === 'string' ? true : null, - dsrdeleteJsonUri: content.dsrdeleteJsonUri || null, - }; + if (response.redirected) result.redirected_to = response.url; + if (content.endpoint) result.endpoint = content.endpoint; + if (content.pollFrequency) result.pollFrequency = content.pollFrequency; + if (content.identifiers) result.identifiers = content.identifiers.map(({ type, format }) => ({ type, format })); + if (typeof content.vendorScriptRequirement === 'boolean') result.vendorScriptRequirement = content.vendorScriptRequirement; + if (typeof content.vendorScript === 'string') result.vendorScript = true; + if (content.dsrdeleteJsonUri) result.dsrdeleteJsonUri = content.dsrdeleteJsonUri; } return result;