@transcend-io/cli 8.34.0 → 8.34.2
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/README.md +2 -2
- package/dist/{api-keys-CDp8NUhN.cjs → api-keys-DQKR5mr6.cjs} +2 -2
- package/dist/{api-keys-CDp8NUhN.cjs.map → api-keys-DQKR5mr6.cjs.map} +1 -1
- package/dist/{app-rVGy2Ks-.cjs → app-7Nt3fjr3.cjs} +18 -18
- package/dist/{app-rVGy2Ks-.cjs.map → app-7Nt3fjr3.cjs.map} +1 -1
- package/dist/bin/bash-complete.cjs +1 -1
- package/dist/bin/cli.cjs +1 -1
- package/dist/bin/deprecated-command.cjs +1 -1
- package/dist/{code-scanning-BwfVNIHr.cjs → code-scanning-Dw_M6bvD.cjs} +2 -2
- package/dist/{code-scanning-BwfVNIHr.cjs.map → code-scanning-Dw_M6bvD.cjs.map} +1 -1
- package/dist/{command-3fhEz5PC.cjs → command-DR1-zcHn.cjs} +2 -2
- package/dist/{command-3fhEz5PC.cjs.map → command-DR1-zcHn.cjs.map} +1 -1
- package/dist/{consent-manager-DXWjvCtI.cjs → consent-manager-yfT0ldzq.cjs} +2 -2
- package/dist/{consent-manager-DXWjvCtI.cjs.map → consent-manager-yfT0ldzq.cjs.map} +1 -1
- package/dist/{constants-B-TmLA0w.cjs → constants-Ck15_dOP.cjs} +2 -2
- package/dist/{constants-B-TmLA0w.cjs.map → constants-Ck15_dOP.cjs.map} +1 -1
- package/dist/{cron-DQHN57v7.cjs → cron-DjzQakpu.cjs} +2 -2
- package/dist/{cron-DQHN57v7.cjs.map → cron-DjzQakpu.cjs.map} +1 -1
- package/dist/{data-inventory-flXV6qPl.cjs → data-inventory-CvILSgb2.cjs} +2 -2
- package/dist/{data-inventory-flXV6qPl.cjs.map → data-inventory-CvILSgb2.cjs.map} +1 -1
- package/dist/{dataFlowsToDataSilos-Lk7WQ39V.cjs → dataFlowsToDataSilos-MmEqa0DG.cjs} +2 -2
- package/dist/{dataFlowsToDataSilos-Lk7WQ39V.cjs.map → dataFlowsToDataSilos-MmEqa0DG.cjs.map} +1 -1
- package/dist/{impl-B6qG10UZ.cjs → impl-5_JaY8jW.cjs} +2 -2
- package/dist/{impl-B6qG10UZ.cjs.map → impl-5_JaY8jW.cjs.map} +1 -1
- package/dist/{impl-EEKe6HmF.cjs → impl-6CHrtJ1S.cjs} +2 -2
- package/dist/{impl-EEKe6HmF.cjs.map → impl-6CHrtJ1S.cjs.map} +1 -1
- package/dist/{impl-CzO7dqsL.cjs → impl-B0MJjjNA.cjs} +2 -2
- package/dist/{impl-CzO7dqsL.cjs.map → impl-B0MJjjNA.cjs.map} +1 -1
- package/dist/{impl-Cw7Jxx0V.cjs → impl-B5L80zX3.cjs} +2 -2
- package/dist/{impl-Cw7Jxx0V.cjs.map → impl-B5L80zX3.cjs.map} +1 -1
- package/dist/{impl-DBnRvkUi.cjs → impl-BALncBPL.cjs} +2 -2
- package/dist/{impl-DBnRvkUi.cjs.map → impl-BALncBPL.cjs.map} +1 -1
- package/dist/{impl-C2_oQebA.cjs → impl-BE7hvm-o.cjs} +2 -2
- package/dist/{impl-C2_oQebA.cjs.map → impl-BE7hvm-o.cjs.map} +1 -1
- package/dist/{impl-DoP4FUJI.cjs → impl-BEtIBM3H.cjs} +2 -2
- package/dist/{impl-DoP4FUJI.cjs.map → impl-BEtIBM3H.cjs.map} +1 -1
- package/dist/{impl-CpoSlP1o.cjs → impl-BL1UK3c7.cjs} +2 -2
- package/dist/{impl-CpoSlP1o.cjs.map → impl-BL1UK3c7.cjs.map} +1 -1
- package/dist/{impl-BJ8i_gqQ.cjs → impl-BQE6Uay6.cjs} +2 -2
- package/dist/{impl-BJ8i_gqQ.cjs.map → impl-BQE6Uay6.cjs.map} +1 -1
- package/dist/{impl-DOmKR8yz.cjs → impl-BWAPcxmK.cjs} +2 -2
- package/dist/{impl-DOmKR8yz.cjs.map → impl-BWAPcxmK.cjs.map} +1 -1
- package/dist/{impl-Cc-Lfiig.cjs → impl-Baci0G6w.cjs} +2 -2
- package/dist/{impl-Cc-Lfiig.cjs.map → impl-Baci0G6w.cjs.map} +1 -1
- package/dist/{impl-DjTjLgew.cjs → impl-Bl-9i-F0.cjs} +2 -2
- package/dist/{impl-DjTjLgew.cjs.map → impl-Bl-9i-F0.cjs.map} +1 -1
- package/dist/{impl-Bsqlw8_g.cjs → impl-Bpiix3Up.cjs} +2 -2
- package/dist/{impl-Bsqlw8_g.cjs.map → impl-Bpiix3Up.cjs.map} +1 -1
- package/dist/{impl-BqyO4vYa.cjs → impl-ByCMcwi7.cjs} +2 -2
- package/dist/{impl-BqyO4vYa.cjs.map → impl-ByCMcwi7.cjs.map} +1 -1
- package/dist/{impl-B1p9GNrM.cjs → impl-C6Flxs5Z.cjs} +2 -2
- package/dist/{impl-B1p9GNrM.cjs.map → impl-C6Flxs5Z.cjs.map} +1 -1
- package/dist/{impl-DrNWIvMG.cjs → impl-C7yf9HJB.cjs} +2 -2
- package/dist/{impl-DrNWIvMG.cjs.map → impl-C7yf9HJB.cjs.map} +1 -1
- package/dist/{impl-CrsHy3BZ.cjs → impl-CJ6efbwZ.cjs} +2 -2
- package/dist/{impl-CrsHy3BZ.cjs.map → impl-CJ6efbwZ.cjs.map} +1 -1
- package/dist/{impl-D0r4dSxM.cjs → impl-CKfTAVk5.cjs} +2 -2
- package/dist/{impl-D0r4dSxM.cjs.map → impl-CKfTAVk5.cjs.map} +1 -1
- package/dist/{impl-b6KwZ74o.cjs → impl-CU1jfTc6.cjs} +2 -2
- package/dist/{impl-b6KwZ74o.cjs.map → impl-CU1jfTc6.cjs.map} +1 -1
- package/dist/{impl-TQVXJemY.cjs → impl-Cb2y0rmA.cjs} +2 -2
- package/dist/{impl-TQVXJemY.cjs.map → impl-Cb2y0rmA.cjs.map} +1 -1
- package/dist/{impl-2u3q0rji.cjs → impl-Cdwey5Ad.cjs} +2 -2
- package/dist/{impl-2u3q0rji.cjs.map → impl-Cdwey5Ad.cjs.map} +1 -1
- package/dist/{impl-CZmlwib3.cjs → impl-CqpWJ35V.cjs} +2 -2
- package/dist/{impl-CZmlwib3.cjs.map → impl-CqpWJ35V.cjs.map} +1 -1
- package/dist/{impl-BjsBvvGF.cjs → impl-D0kWgQ25.cjs} +2 -2
- package/dist/{impl-BjsBvvGF.cjs.map → impl-D0kWgQ25.cjs.map} +1 -1
- package/dist/impl-D2btoDa0.cjs +2 -0
- package/dist/impl-D2btoDa0.cjs.map +1 -0
- package/dist/{impl-Bc9DMV-V.cjs → impl-D6VaotKB.cjs} +2 -2
- package/dist/{impl-Bc9DMV-V.cjs.map → impl-D6VaotKB.cjs.map} +1 -1
- package/dist/{impl-DvlAq8xf.cjs → impl-DEv-oWoY.cjs} +2 -2
- package/dist/{impl-DvlAq8xf.cjs.map → impl-DEv-oWoY.cjs.map} +1 -1
- package/dist/{impl-DcQ_HfDZ.cjs → impl-DGRFzFu_.cjs} +2 -2
- package/dist/{impl-DcQ_HfDZ.cjs.map → impl-DGRFzFu_.cjs.map} +1 -1
- package/dist/{impl-CUkxcZrf.cjs → impl-DGRQPEpr.cjs} +2 -2
- package/dist/{impl-CUkxcZrf.cjs.map → impl-DGRQPEpr.cjs.map} +1 -1
- package/dist/{impl-DX7gLoTo.cjs → impl-DSwZ_Zpg.cjs} +2 -2
- package/dist/{impl-DX7gLoTo.cjs.map → impl-DSwZ_Zpg.cjs.map} +1 -1
- package/dist/{impl-CaSO2LPb.cjs → impl-DXYFSbdT.cjs} +2 -2
- package/dist/{impl-CaSO2LPb.cjs.map → impl-DXYFSbdT.cjs.map} +1 -1
- package/dist/{impl-CaUSDPuW.cjs → impl-DcZxvv9d.cjs} +2 -2
- package/dist/{impl-CaUSDPuW.cjs.map → impl-DcZxvv9d.cjs.map} +1 -1
- package/dist/{impl-BuJNWbOW.cjs → impl-DhGAHD6N.cjs} +2 -2
- package/dist/{impl-BuJNWbOW.cjs.map → impl-DhGAHD6N.cjs.map} +1 -1
- package/dist/{impl-8PlQ3Cvy.cjs → impl-DilrEold.cjs} +2 -2
- package/dist/{impl-8PlQ3Cvy.cjs.map → impl-DilrEold.cjs.map} +1 -1
- package/dist/{impl-E1vzeNmp.cjs → impl-Gy2MhlbR.cjs} +2 -2
- package/dist/{impl-E1vzeNmp.cjs.map → impl-Gy2MhlbR.cjs.map} +1 -1
- package/dist/{impl-B4iI3rcF.cjs → impl-KtaRdVpP.cjs} +2 -2
- package/dist/{impl-B4iI3rcF.cjs.map → impl-KtaRdVpP.cjs.map} +1 -1
- package/dist/{impl-t_fZSUcj.cjs → impl-M-kD-8Qh.cjs} +2 -2
- package/dist/{impl-t_fZSUcj.cjs.map → impl-M-kD-8Qh.cjs.map} +1 -1
- package/dist/{impl-CwPRkBc0.cjs → impl-NwB7y3aW.cjs} +2 -2
- package/dist/{impl-CwPRkBc0.cjs.map → impl-NwB7y3aW.cjs.map} +1 -1
- package/dist/{impl-80GXtjmz.cjs → impl-PU77PoPR.cjs} +2 -2
- package/dist/{impl-80GXtjmz.cjs.map → impl-PU77PoPR.cjs.map} +1 -1
- package/dist/{impl-CtMVi5m1.cjs → impl-keqxvDu-.cjs} +2 -2
- package/dist/{impl-CtMVi5m1.cjs.map → impl-keqxvDu-.cjs.map} +1 -1
- package/dist/{impl-CCeEUy6z.cjs → impl-miCFpR_U.cjs} +2 -2
- package/dist/{impl-CCeEUy6z.cjs.map → impl-miCFpR_U.cjs.map} +1 -1
- package/dist/{impl-3ih-x09b.cjs → impl-vDiQmycv.cjs} +2 -2
- package/dist/{impl-3ih-x09b.cjs.map → impl-vDiQmycv.cjs.map} +1 -1
- package/dist/{impl-BZc5cmdE.cjs → impl-xU8wyFx4.cjs} +2 -2
- package/dist/{impl-BZc5cmdE.cjs.map → impl-xU8wyFx4.cjs.map} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +529 -312
- package/dist/{manual-enrichment-Y_BQaSZQ.cjs → manual-enrichment-CkdYjftx.cjs} +2 -2
- package/dist/{manual-enrichment-Y_BQaSZQ.cjs.map → manual-enrichment-CkdYjftx.cjs.map} +1 -1
- package/dist/{pooling-Ct83vfEh.cjs → pooling-CE5JT_os.cjs} +2 -2
- package/dist/{pooling-Ct83vfEh.cjs.map → pooling-CE5JT_os.cjs.map} +1 -1
- package/dist/{preference-management-5uJDKuMK.cjs → preference-management-Dsrpuzbl.cjs} +2 -2
- package/dist/{preference-management-5uJDKuMK.cjs.map → preference-management-Dsrpuzbl.cjs.map} +1 -1
- package/dist/{syncConfigurationToTranscend-Bpge5AcC.cjs → syncConfigurationToTranscend-f6E4-H5W.cjs} +176 -176
- package/dist/syncConfigurationToTranscend-f6E4-H5W.cjs.map +1 -0
- package/dist/{uploadConsents-CJc_6Qwd.cjs → uploadConsents-BwTW5VNv.cjs} +2 -2
- package/dist/{uploadConsents-CJc_6Qwd.cjs.map → uploadConsents-BwTW5VNv.cjs.map} +1 -1
- package/package.json +8 -8
- package/dist/impl-NdV_MRsm.cjs +0 -2
- package/dist/impl-NdV_MRsm.cjs.map +0 -1
- package/dist/syncConfigurationToTranscend-Bpge5AcC.cjs.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
const e=require(`./enums-CBXlBJii.cjs`),t=require(`./constants-
|
|
1
|
+
const e=require(`./enums-CBXlBJii.cjs`),t=require(`./constants-Ck15_dOP.cjs`),n=require(`./syncConfigurationToTranscend-f6E4-H5W.cjs`),r=require(`./logger-BaHHbWVd.cjs`);let i=require(`@transcend-io/privacy-types`),a=require(`@transcend-io/type-utils`),o=require(`colors`);o=e.s(o);let s=require(`io-ts`);s=e.s(s);let c=require(`inquirer`);c=e.s(c);let l=require(`cli-progress`);l=e.s(l);let u=require(`@transcend-io/persisted-state`);const d=[`ENOTFOUND`,`ECONNRESET`,`ETIMEDOUT`,`502 Bad Gateway`,`504 Gateway Time-out`,`429`,`Rate limit exceeded`,`Task timed out after`,`unknown request error`].map(e=>e.toLowerCase());async function f(e,t,{maxAttempts:i=3,baseDelayMs:a=250,isRetryable:s=(e,t)=>d.some(e=>t.toLowerCase().includes(e)),onRetry:c}={}){let l=0;for(;;){l+=1;try{return await t()}catch(t){let u=(t&&(t.response?.body||t.message))??String(t??`Unknown error`);if(!(l<i&&s(t,u)))throw Error(`${e} failed after ${l} attempt(s): ${u}`);c?.(l,t,u);let d=a*2**(l-1)+Math.floor(Math.random()*a);r.t.warn(o.default.yellow(`[retry] attempt ${l}/${i-1}; backing off ${d}ms: ${u}`)),await n.D(d)}}}const p=s.intersection([s.type({nodes:s.array(i.PreferenceQueryResponseItem)}),s.partial({cursor:s.string})]);async function m(e,{identifiers:t,partitionKey:i,skipLogging:s=!1,concurrency:c=40}){let u=[],d=n.Ns(t,100),m=new Date().getTime(),h=new l.default.SingleBar({},l.default.Presets.shades_classic);s||h.start(t.length,0);let g=0;await n.Ts(d,async t=>{let n=(0,a.decodeCodec)(p,await f(`Preference Query`,()=>e.post(`v1/preferences/${i}/query`,{json:{filter:{identifiers:t},limit:t.length}}).json(),{onRetry:(e,n,a)=>{r.t.warn(o.default.yellow(`[RETRY] group size=${t.length} partition=${i} attempt=${e}: ${a}`))}}));u.push(...n.nodes),g+=t.length,h.update(g)},{concurrency:c}),h.stop();let _=new Date().getTime()-m;return s||r.t.info(o.default.green(`Completed download in "${_/1e3}" seconds.`)),u}function h({row:e,columnToPurposeName:t,purposeSlugs:r,preferenceTopics:o}){let s={};return Object.entries(t).forEach(([t,{purpose:a,preference:c,valueMapping:l}])=>{if(!r.includes(a))throw Error(`Invalid purpose slug: ${a}, expected: ${r.join(`, `)}`);let u=e[t];if(c){let e=o.find(e=>e.slug===c&&e.purpose.trackingType===a);if(!e){let e=o.filter(e=>e.purpose.trackingType===a).map(e=>e.slug);throw Error(`Invalid preference slug: ${c} for purpose: ${a}. Allowed preference slugs for purpose are: ${e.join(`,`)}`)}switch(s[a]||(s[a]={preferences:[]}),s[a].preferences||(s[a].preferences=[]),e.type){case i.PreferenceTopicType.Boolean:{let e=l[u];if(e===void 0&&u!==``)throw Error(`No preference mapping found for value "${u}" in column "${t}" (purpose=${a}, preference=${c})`);if(e==null)return;if(typeof e!=`boolean`)throw Error(`Invalid value for boolean preference: ${c}, expected boolean, got: ${u}`);s[a].preferences.push({topic:c,choice:{booleanValue:e}});break}case i.PreferenceTopicType.Select:{let n=l[u];if(n===void 0&&u!==``)throw Error(`No preference mapping found for value "${u}" in column "${t}" (purpose=${a}, preference=${c})`);if(n==null)return;if(typeof n!=`string`)throw Error(`Invalid value for select preference: ${c}, expected string, got: ${u}`);let r=n.trim()||null;if(r&&!e.preferenceOptionValues.map(({slug:e})=>e).includes(r))throw Error(`Invalid value for select preference: ${c}, expected one of: ${e.preferenceOptionValues.map(({slug:e})=>e).join(`, `)}, got: ${u}`);s[a].preferences.push({topic:c,choice:{selectValue:r}});break}case i.PreferenceTopicType.MultiSelect:{if(typeof u!=`string`)throw Error(`Invalid value for multi select preference: ${c}, expected string, got: ${u}`);let r=n.li(u).map(n=>{let r=l[n];if(r===void 0&&u!==``)throw Error(`No preference mapping found for multi select token "${u}" in column "${t}" (purpose=${a}, preference=${c})`);if(r==null)return null;if(typeof r!=`string`)throw Error(`Invalid value for multi select preference: ${c}, expected one of: ${e.preferenceOptionValues.map(({slug:e})=>e).join(`, `)}, got: ${n}`);return r}).filter(e=>e!==null).sort((e,t)=>e.localeCompare(t));r.length>0&&s[a].preferences.push({topic:c,choice:{selectValues:r}});break}default:throw Error(`Unknown preference type: ${e.type}`)}}else{let e=l[u];if(e===void 0&&u!==``)throw Error(`No preference mapping found for value "${u}" in column "${t}" (purpose=${a}, preference=∅)`);if(e===null)return;s[a]?s[a].enabled=e===!0:s[a]={enabled:e===!0}}}),(0,a.apply)(s,(e,t)=>{if(typeof e.enabled!=`boolean`)throw Error(`No mapping provided for purpose.enabled=true/false value: ${t}`);return{...e,enabled:e.enabled}})}const g=`[NONE]`;async function _(e,t){let i=n.js(n.Ds(e.map(e=>Object.keys(e)).flat()),[...t.identifierColumn?[t.identifierColumn]:[],...Object.keys(t.columnToPurposeName)]);if(!t.timestampColum){let{timestampName:e}=await c.default.prompt([{name:`timestampName`,message:`Choose the column that will be used as the timestamp of last preference update`,type:`list`,default:i.find(e=>e.toLowerCase().includes(`date`))||i.find(e=>e.toLowerCase().includes(`time`))||i[0],choices:[...i,g]}]);t.timestampColum=e}if(r.t.info(o.default.magenta(`Using timestamp column "${t.timestampColum}"`)),t.timestampColum!==g){let n=e.map((e,n)=>e[t.timestampColum]?null:[n]).filter(e=>!!e).flat();if(n.length>0)throw Error(`The timestamp column "${t.timestampColum}" is missing a value for the following rows: ${n.join(`
|
|
2
2
|
`)}`);r.t.info(o.default.magenta(`The timestamp column "${t.timestampColum}" is present for all row`))}return t}async function v(e,t){let i=n.js(n.Ds(e.map(e=>Object.keys(e)).flat()),[...t.identifierColumn?[t.identifierColumn]:[],...Object.keys(t.columnToPurposeName)]);if(!t.identifierColumn){let{identifierName:e}=await c.default.prompt([{name:`identifierName`,message:`Choose the column that will be used as the identifier to upload consent preferences by`,type:`list`,default:i.find(e=>e.toLowerCase().includes(`email`))||i[0],choices:i}]);t.identifierColumn=e}r.t.info(o.default.magenta(`Using identifier column "${t.identifierColumn}"`));let a=e.map((e,n)=>e[t.identifierColumn]?null:[n]).filter(e=>!!e).flat();if(a.length>0){let i=`The identifier column "${t.identifierColumn}" is missing a value for the following rows: ${a.join(`, `)}`;if(r.t.warn(o.default.yellow(i)),!await n.M({message:`Would you like to skip rows missing an identifier?`}))throw Error(i);let s=e.length;e=e.filter(e=>e[t.identifierColumn]),r.t.info(o.default.yellow(`Skipped ${s-e.length} rows missing an identifier`))}r.t.info(o.default.magenta(`The identifier column "${t.identifierColumn}" is present for all rows`));let s=n.As(e,t.identifierColumn),l=Object.entries(s).filter(([,e])=>e.length>1);if(l.length>0){let i=`The identifier column "${t.identifierColumn}" has duplicate values for the following rows: ${l.slice(0,10).map(([e,t])=>`${e} (${t.length})`).join(`
|
|
3
3
|
`)}`;if(r.t.warn(o.default.yellow(i)),!await n.M({message:`Would you like to automatically take the latest update?`}))throw Error(i);e=Object.entries(s).map(([,e])=>e.sort((e,n)=>new Date(n[t.timestampColum]).getTime()-new Date(e[t.timestampColum]).getTime())[0]).filter(e=>e)}return{currentState:t,preferences:e}}async function y(e,t,{purposeSlugs:a,preferenceTopics:s,forceTriggerWorkflows:l}){let u=n.js(n.Ds(e.map(e=>Object.keys(e)).flat()),[...t.identifierColumn?[t.identifierColumn]:[],...t.timestampColum?[t.timestampColum]:[]]);if(u.length===0){if(l)return t;throw Error(`No other columns to process`)}let d=[...a,...s.map(e=>`${e.purpose.trackingType}->${e.slug}`)];return await n.Es(u,async l=>{let u=n.Ds(e.map(e=>e[l])),f=t.columnToPurposeName[l];if(f)r.t.info(o.default.magenta(`Column "${l}" is associated with purpose "${f.purpose}"`));else{let{purposeName:e}=await c.default.prompt([{name:`purposeName`,message:`Choose the purpose that column ${l} is associated with`,type:`list`,default:d.find(e=>e.startsWith(a[0])),choices:d}]),[t,n]=e.split(`->`);f={purpose:t,preference:n||null,valueMapping:{}}}await n.Es(u,async e=>{if(f.valueMapping[e]!==void 0){r.t.info(o.default.magenta(`Value "${e}" is associated with purpose value "${f.valueMapping[e]}"`));return}if(f.preference===null){let{purposeValue:t}=await c.default.prompt([{name:`purposeValue`,message:`Choose the purpose value for value "${e}" associated with purpose "${f.purpose}"`,type:`confirm`,default:e!==`false`}]);f.valueMapping[e]=t}if(f.preference!==null){let t=s.find(e=>e.slug===f.preference);if(!t){r.t.error(o.default.red(`Preference topic "${f.preference}" not found`));return}let a=t.preferenceOptionValues.map(({slug:e})=>e);if(t.type===i.PreferenceTopicType.Boolean){let{preferenceValue:n}=await c.default.prompt([{name:`preferenceValue`,message:`Choose the preference value for "${t.slug}" value "${e}" associated with purpose "${f.purpose}"`,type:`confirm`,default:e!==`false`}]);f.valueMapping[e]=n;return}if(t.type===i.PreferenceTopicType.Select){let{preferenceValue:n}=await c.default.prompt([{name:`preferenceValue`,message:`Choose the preference value for "${t.slug}" value "${e}" associated with purpose "${f.purpose}"`,type:`list`,choices:a,default:a.find(t=>t===e)}]);f.valueMapping[e]=n;return}if(t.type===i.PreferenceTopicType.MultiSelect){await n.Es(n.li(e),async e=>{if(f.valueMapping[e]!==void 0)return;let{preferenceValue:n}=await c.default.prompt([{name:`preferenceValue`,message:`Choose the preference value for "${t.slug}" value "${e}" associated with purpose "${f.purpose}"`,type:`list`,choices:a,default:a.find(t=>t===e)}]);f.valueMapping[e]=n});return}throw Error(`Unknown preference topic type: ${t.type}`)}}),t.columnToPurposeName[l]=f}),t}function b({currentConsentRecord:e,pendingUpdates:t,preferenceTopics:n}){return Object.entries(t).every(([t,{preferences:r=[],enabled:a}])=>{let o=e.purposes.find(e=>e.purpose===t);return o&&o.enabled===a?r.every(({topic:e,choice:r})=>o.preferences&&o.preferences.find(a=>{if(a.topic!==e)return!1;let o=n.find(n=>n.slug===e&&n.purpose.trackingType===t);if(!o)throw Error(`Could not find preference topic for ${e}`);switch(o.type){case i.PreferenceTopicType.Boolean:return a.choice.booleanValue===r.booleanValue;case i.PreferenceTopicType.Select:return a.choice.selectValue===r.selectValue;case i.PreferenceTopicType.MultiSelect:let e=(a.choice.selectValues||[]).sort(),t=(r.selectValues||[]).sort();return e.length===t.length&&e.every((e,n)=>e===t[n]);default:throw Error(`Unknown preference topic type: ${o.type}`)}})):!1})}function x({currentConsentRecord:e,pendingUpdates:t,preferenceTopics:n,log:a}){return!!Object.entries(t).find(([t,{preferences:o=[],enabled:s}])=>{let c=e.purposes.find(e=>e.purpose===t);return c?c.enabled===s?!!o.find(({topic:o,choice:s})=>{let l=(c.preferences||[]).find(e=>e.topic===o);if(!l)return a&&r.t.warn(`No existing preference found for topic ${o} in purpose ${t} for user ${e.userId}.`),!1;let u=n.find(e=>e.slug===o&&e.purpose.trackingType===t);if(!u)throw Error(`Could not find preference topic for ${o}`);let d,f;switch(u.type){case i.PreferenceTopicType.Boolean:return d=l.choice.booleanValue!==s.booleanValue,a&&r.t.warn(`Preference topic ${o} boolean value conflict for user ${e.userId}. Expected: ${s.booleanValue}, Found: ${l.choice.booleanValue}`),d;case i.PreferenceTopicType.Select:return f=l.choice.selectValue!==s.selectValue,a&&r.t.warn(`Preference topic ${o} select value conflict for user ${e.userId}. Expected: ${s.selectValue}, Found: ${l.choice.selectValue}`),f;case i.PreferenceTopicType.MultiSelect:let t=(l.choice.selectValues||[]).sort(),n=(s.selectValues||[]).sort();return f=t.length!==n.length||!t.every((e,t)=>e===n[t]),a&&r.t.warn(`Preference topic ${o} multi-select value conflict for user ${e.userId}. Expected: ${n.join(`, `)}, Found: ${t.join(`, `)}`),f;default:throw Error(`Unknown preference topic type: ${u.type}`)}}):(a&&r.t.warn(`Purpose ${t} enabled value conflict for user ${e.userId}. Pending Value: ${s}, Current Value: ${c.enabled}`),!0):(a&&r.t.warn(`No existing purpose found for ${t} in consent record for ${e.userId}.`),!1)})}async function S({file:e,sombra:i,purposeSlugs:a,preferenceTopics:c,partitionKey:l,skipExistingRecordCheck:u,forceTriggerWorkflows:d},f){let p=new Date().getTime(),g=f.getValue(`fileMetadata`);r.t.info(o.default.magenta(`Reading in file: "${e}"`));let S=n.oi(e,s.record(s.string,s.string)),C={columnToPurposeName:{},pendingSafeUpdates:{},pendingConflictUpdates:{},skippedUpdates:{},...g[e]||{},lastFetchedAt:new Date().toISOString()};C=await _(S,C),g[e]=C,await f.setValue(g,`fileMetadata`);let w=await v(S,C);C=w.currentState,S=w.preferences,g[e]=C,await f.setValue(g,`fileMetadata`),C=await y(S,C,{preferenceTopics:c,purposeSlugs:a,forceTriggerWorkflows:d}),g[e]=C,await f.setValue(g,`fileMetadata`);let T=S.map(e=>e[C.identifierColumn]),E=t.g(u?[]:await m(i,{identifiers:T.map(e=>({value:e})),partitionKey:l}),`userId`);C.pendingConflictUpdates={},C.pendingSafeUpdates={},C.skippedUpdates={},S.forEach(e=>{let t=e[C.identifierColumn],n=h({row:e,columnToPurposeName:C.columnToPurposeName,preferenceTopics:c,purposeSlugs:a}),r=E[t];if(d&&!r)throw Error(`No existing consent record found for user with id: ${t}.
|
|
4
4
|
When 'forceTriggerWorkflows' is set all the user identifiers should contain a consent record`);if(r&&b({currentConsentRecord:r,pendingUpdates:n,preferenceTopics:c})&&!d){C.skippedUpdates[t]=e;return}if(r&&x({currentConsentRecord:r,pendingUpdates:n,preferenceTopics:c})){C.pendingConflictUpdates[t]={row:e,record:r};return}C.pendingSafeUpdates[t]=e}),g[e]=C,await f.setValue(g,`fileMetadata`);let D=new Date().getTime();r.t.info(o.default.green(`Successfully pre-processed file: "${e}" in ${(D-p)/1e3}s`))}const C=s.type({purpose:s.string,preference:s.union([s.string,s.null]),valueMapping:s.record(s.string,s.union([s.string,s.boolean,s.null,s.undefined]))}),w=s.record(s.string,C),T=s.type({name:s.string,isUniqueOnPreferenceStore:s.boolean}),E=s.record(s.string,T),D=s.intersection([s.type({columnToPurposeName:s.record(s.string,C),lastFetchedAt:s.string,pendingSafeUpdates:s.record(s.string,s.record(s.string,s.string)),pendingConflictUpdates:s.record(s.string,s.type({record:i.PreferenceQueryResponseItem,row:s.record(s.string,s.string)})),skippedUpdates:s.record(s.string,s.record(s.string,s.string))}),s.partial({identifierColumn:s.string,timestampColum:s.string})]),O=s.record(s.string,s.union([s.boolean,i.PreferenceUpdateItem])),k=s.record(s.string,s.union([s.boolean,s.record(s.string,s.string)])),A=s.record(s.string,s.type({uploadedAt:s.string,error:s.string,update:i.PreferenceUpdateItem})),j=s.record(s.string,s.type({record:i.PreferenceQueryResponseItem,row:s.record(s.string,s.string)})),M=s.record(s.string,s.record(s.string,s.string)),N=s.type({fileMetadata:s.record(s.string,D),failingUpdates:s.record(s.string,s.type({uploadedAt:s.string,error:s.string,update:i.PreferenceUpdateItem})),pendingUpdates:s.record(s.string,i.PreferenceUpdateItem)}),P=s.type({records:s.array(s.type({anchorIdentifier:i.PreferenceStoreIdentifier,timestamp:s.string}))}),F=s.intersection([s.type({records:s.array(s.intersection([s.type({success:s.boolean}),s.partial({errorMessage:s.string})])),failures:s.array(s.type({index:s.number,error:s.string}))}),s.partial({errors:s.array(s.string)})]),I=s.type({name:s.string,value:s.string});async function L({auth:e,sombraAuth:t,receiptFilepath:i,file:s,partition:c,isSilent:d=!0,dryRun:f=!1,skipWorkflowTriggers:p=!1,skipConflictUpdates:m=!1,skipExistingRecordCheck:_=!1,attributes:v=[],transcendUrl:y,forceTriggerWorkflows:b=!1}){let x=n.ci(v),C=new u.PersistedState(i,N,{fileMetadata:{},failingUpdates:{},pendingUpdates:{}}),w=C.getValue(`failingUpdates`),T=C.getValue(`pendingUpdates`),E=C.getValue(`fileMetadata`);r.t.info(o.default.magenta(`Restored cache, there are:
|
|
5
5
|
${Object.values(w).length} failing requests to be retried\n${Object.values(T).length} pending requests to be processed\nThe following files are stored in cache and will be used:\n${Object.keys(E).map(e=>e).join(`
|
|
6
6
|
`)}\nThe following file will be processed: ${s}\n`));let D=n.ti(y,e),[O,k,A]=await Promise.all([n.ei(y,e,t),n.vr(D),n.Sr(D)]);await S({file:s,purposeSlugs:k.map(e=>e.trackingType),preferenceTopics:A,sombra:O,partitionKey:c,skipExistingRecordCheck:_,forceTriggerWorkflows:b},C);let j={};E=C.getValue(`fileMetadata`);let M=E[s];if(r.t.info(o.default.magenta(`Found ${Object.entries(M.pendingSafeUpdates).length} safe updates in ${s}`)),r.t.info(o.default.magenta(`Found ${Object.entries(M.pendingConflictUpdates).length} conflict updates in ${s}`)),r.t.info(o.default.magenta(`Found ${Object.entries(M.skippedUpdates).length} skipped updates in ${s}`)),Object.entries({...M.pendingSafeUpdates,...m?{}:(0,a.apply)(M.pendingConflictUpdates,({row:e})=>e)}).forEach(([e,t])=>{let n=M.timestampColum===g?new Date:new Date(t[M.timestampColum]),r=h({row:t,columnToPurposeName:M.columnToPurposeName,preferenceTopics:A,purposeSlugs:k.map(e=>e.trackingType)});j[e]={userId:e,partition:c,timestamp:n.toISOString(),purposes:Object.entries(r).map(([e,t])=>({...t,purpose:e,workflowSettings:{attributes:x,isSilent:d,skipWorkflowTrigger:p,...b?{forceTriggerWorkflow:b}:{}}}))}}),await C.setValue(j,`pendingUpdates`),await C.setValue({},`failingUpdates`),f){r.t.info(o.default.green(`Dry run complete, exiting. ${Object.values(j).length} pending updates. Check file: ${i}`));return}r.t.info(o.default.magenta(`Uploading ${Object.values(j).length} preferences to partition: ${c}`));let P=new Date().getTime(),F=new l.default.SingleBar({},l.default.Presets.shades_classic),I=0,L=Object.entries(j),R=n.Ns(L,p?100:10);F.start(L.length,0),await n.Ts(R,async e=>{try{await O.put(`v1/preferences`,{json:{records:e.map(([,e])=>e),skipWorkflowTriggers:p}}).json()}catch(t){try{let e=JSON.parse(t?.response?.body||`{}`);e.error&&r.t.error(o.default.red(`Error: ${e.error}`))}catch{}r.t.error(o.default.red(`Failed to upload ${e.length} user preferences to partition ${c}: ${t?.response?.body||t?.message}`));let n=C.getValue(`failingUpdates`);e.forEach(([e,r])=>{n[e]={uploadedAt:new Date().toISOString(),update:r,error:t?.response?.body||t?.message||`Unknown error`}}),await C.setValue(n,`failingUpdates`)}I+=e.length,F.update(I)},{concurrency:40}),F.stop();let z=new Date().getTime()-P;r.t.info(o.default.green(`Successfully uploaded ${L.length} user preferences to partition ${c} in "${z/1e3}" seconds!`))}function R({identifiers:e=[],purposes:t=[],metadata:n=[],consentManagement:r={},system:i={decryptionStatus:`DECRYPTED`},...a},o){let s={...a,...i,...r};if(Array.isArray(e)){let t=new Map;for(let{name:n,value:r}of e)t.has(n)||t.set(n,new Set),r&&t.get(n).add(r);for(let[e,n]of t.entries())s[e]=Array.from(n).join(o)}if(Array.isArray(n)&&(s.metadata=JSON.stringify(n.reduce((e,{key:t,value:n})=>(e[t]=n,e),{}))),Array.isArray(t)){for(let{purpose:e,preferences:n,enabled:r}of t)if(s[e]=!!r,Array.isArray(n))for(let{topic:t,choice:r}of n){let n=`${e}_${t}`,i=null;i=typeof r.booleanValue==`boolean`?r.booleanValue:r.selectValue?r.selectValue:Array.isArray(r.selectValues)?r.selectValues.filter(e=>e.length>0).join(`,`):null,s[n]=i}}return s}async function*z(e,t,n,i){let s;for(;;){let c={limit:i};n&&Object.keys(n).length&&(c.filter=n),s&&(c.cursor=s);let{nodes:l,cursor:u}=(0,a.decodeCodec)(p,await f(`Preference Query`,()=>e.post(`v1/preferences/${t}/query`,{json:c}).json(),{maxAttempts:5,onRetry:(e,t,n)=>{r.t.warn(o.default.yellow(`Retry attempt ${e} for fetchConsentPreferences due to error: ${n}`))}}));if(!l?.length||(yield l,!u))break;s=u}}function B(e){return e.timestampAfter||e.timestampBefore?`timestamp`:`updated`}function V(e,t){return e===`timestamp`?new Date(t.timestamp):t.system?.updatedAt?new Date(t.system.updatedAt):new Date}function H(e,t){if(e===`timestamp`)return{after:t.timestampAfter?new Date(t.timestampAfter):void 0,before:t.timestampBefore?new Date(t.timestampBefore):void 0};let n=t.system??{};return{after:n.updatedAfter?new Date(n.updatedAfter):void 0,before:n.updatedBefore?new Date(n.updatedBefore):void 0}}function U(e,t,n){return e===`timestamp`?{...t,timestampBefore:n??t.timestampBefore}:{...t,system:{...t.system||{},...n?{updatedBefore:n}:{}},timestampAfter:void 0,timestampBefore:void 0}}async function W(e,t,n){r.t.info(o.default.magenta(`Single-record probe with filter: ${JSON.stringify(n)}`));let i=await z(e,t,n,1).next();if(i.done||!i.value||i.value.length===0)return r.t.info(o.default.yellow(`Probe result: no record`)),null;let a=i.value[0];return r.t.info(o.default.green(`Probe result: found record at ${V(B(n),a).toISOString()}`)),a}async function G(e,t){let{partition:i,mode:a,baseFilter:s,maxLookbackDays:c=3650}=t,l=await W(e,i,U(a,s));if(!l)return r.t.info(o.default.yellow(`No records found; defaulting earliest day to today.`)),n.y(new Date);let u=V(a,l);r.t.info(o.default.green(`Newest instant: ${u.toISOString()}`));let d=[1,7,30],f=0,p=d[0]*n.f,m=u,h=null;for(;;){let t=f<d.length?new Date(u.getTime()-d[f]*n.f):new Date(u.getTime()-p);if((n.y(new Date).getTime()-n.y(t).getTime())/n.f>c){r.t.warn(o.default.yellow(`Exponential jump exceeded maxLookbackDays=${c}. Using current bounds.`)),h=t;break}r.t.info(o.default.magenta(`Probing before=${t.toISOString()} (jump step ${f<d.length?`${d[f]}d`:`${Math.round(p/n.f)}d`})…`));let l=await W(e,i,U(a,s,t.toISOString()));if(l){m=V(a,l),r.t.info(o.default.green(`Found older record at ${m.toISOString()} — continue jumping back.`)),f<d.length-1?(f+=1,p=d[f]*n.f):f===d.length-1?(f+=1,p=d[d.length-1]*2*n.f):p*=2;continue}h=t,r.t.info(o.default.green(`No record before ${t.toISOString()} — established empty lower bound.`));break}h||=new Date(m.getTime()-n.f);let g=h,_=m,v=Math.max(n.f,Math.floor((_.getTime()-g.getTime())/64));r.t.info(o.default.magenta(`Exponential forward-from-empty start: empty=${g.toISOString()} found=${_.toISOString()} step=${Math.round(v/n.f)}d`));for(let t=0;t<8;t+=1){let t=new Date(g.getTime()+v);if(t.getTime()>=_.getTime())break;r.t.info(o.default.magenta(`Forward gallop probe before=${t.toISOString()}…`));let c=await W(e,i,U(a,s,t.toISOString()));if(c?(_=V(a,c),r.t.info(o.default.green(`Gallop hit at ${_.toISOString()} — tightening found bound. Next step halves.`)),v=Math.max(n.f,Math.floor(v/2))):(g.setTime(t.getTime()),r.t.info(o.default.yellow(`Gallop miss — advancing empty bound to ${g.toISOString()}. Next step doubles.`)),v=Math.min(_.getTime()-g.getTime(),v*2),v<n.f&&(v=n.f)),_.getTime()-g.getTime()<=n.f)break}for(;_.getTime()-g.getTime()>n.f;){let t=new Date(g.getTime()+Math.floor((_.getTime()-g.getTime())/2));r.t.info(o.default.magenta(`Binary probe before=${t.toISOString()}…`));let n=await W(e,i,U(a,s,t.toISOString()));if(n){let e=V(a,n);r.t.info(o.default.green(`Binary probe found record at ${e.toISOString()}.`)),_=e}else r.t.info(o.default.yellow(`Binary probe found no record.`)),g=t}let y=n.y(_);return r.t.info(o.default.green(`Earliest day (UTC) resolved to ${y.toISOString()} (instant ≈ ${_.toISOString()}).`)),y}async function K(e,t){let{partition:i,mode:a,baseFilter:s}=t;r.t.info(o.default.magenta(`Latest-day discovery: probing newest record…`));let c=await W(e,i,U(a,s));if(!c)return r.t.info(o.default.yellow(`No records found at all; defaulting latest day to today.`)),n.y(new Date);let l=V(a,c);r.t.info(o.default.green(`Newest record instant is ${l.toISOString()}.`));let u=n.y(l);return r.t.info(o.default.green(`Latest day (UTC) resolved to ${u.toISOString()} from instant ${l.toISOString()}.`)),u}function q(e,t,r,i=5e3){let a=Math.max(0,r.getTime()-t.getTime());if(a===0)return[];let o=new Date(Math.floor(t.getTime()/n.p)*n.p),s=Math.ceil(a/Math.max(1,i)),c=Math.max(n.p,s),l=Math.ceil((r.getTime()-o.getTime())/c),u=[];for(let t=0;t<l;t+=1){let n=o.getTime()+t*c,i=Math.min(r.getTime(),n+c)-1,a=Math.max(n,i),s=new Date(n).toISOString(),l=new Date(a).toISOString();e===`timestamp`?u.push({timestampAfter:s,timestampBefore:l}):u.push({system:{updatedAfter:s,updatedBefore:l}})}return u}function J(e,t,n){return e===`timestamp`?{...t,timestampAfter:n.timestampAfter??t.timestampAfter,timestampBefore:n.timestampBefore??t.timestampBefore,system:void 0}:{...t,system:{...t.system||{},...n.system?.updatedAfter?{updatedAfter:n.system.updatedAfter}:{},...n.system?.updatedBefore?{updatedBefore:n.system.updatedBefore}:{}},timestampAfter:void 0,timestampBefore:void 0}}async function Y(e,{partition:t,filterBy:i={},limit:a=50,windowConcurrency:s=25,maxChunks:c=5e3,maxLookbackDays:u=3650,onItems:d}){let f=B(i);r.t.info(o.default.magenta(`Fetching consent preferences in chunks by ${f===`timestamp`?`timestamp`:`system.updatedAt`}...`));let{after:p,before:m}=H(f,i);if(r.t.info(o.default.magenta(`Initial bounds: after=${p?.toISOString()??`undefined`} before=${m?.toISOString()??`undefined`}`)),(!p||!m)&&(p||(r.t.info(o.default.magenta(`Discovering earliest day with data for partition ${t}...`)),p=await G(e,{partition:t,mode:f,baseFilter:i,maxLookbackDays:u}),r.t.info(o.default.green(`Discovered earliest day with data: ${p.toISOString()}`))),!m)){r.t.info(o.default.magenta(`Discovering latest day with data for partition ${t}...`));let a=await K(e,{partition:t,mode:f,baseFilter:i,earliest:p});m=n.h(a,1),r.t.info(o.default.green(`Discovered latest day with data: ${a.toISOString()}`))}r.t.info(o.default.green(`Final bounds (UTC): after=${p.toISOString()} before=${m.toISOString()}`));let h=q(f,p,m,c);r.t.info(o.default.magenta(`Fetching consent preferences from partition ${t} in ${h.length} chunks...`));let g=new l.default.SingleBar({format:`Downloading [{bar}] {percentage}% | chunks {value}/{total} | fetched {fetched}`},l.default.Presets.shades_classic),_=0,v=0;g.start(h.length,0,{fetched:v});let y=Date.now(),b=n._(a),x=[];return await n.Ts(h.map((e,t)=>({windowFilter:e,idx:t})),async({windowFilter:n})=>{let r=J(f,i,n);for await(let n of z(e,t,r,b))v+=n.length,g.update(_,{fetched:v}),d?await d(n):x.push(...n);_+=1,g.update(_,{fetched:v})},{concurrency:Math.max(1,s)}),g.update(_,{fetched:v}),g.stop(),r.t.info(o.default.green(`Fetched ${v} consent preference records from partition ${t} in ${(Date.now()-y)/1e3}s.`)),d?[]:x}async function X(e,{partition:t,filterBy:n={},limit:i=50,onItems:s}){let c=[],l,u=n&&(Object.keys(n).length>0||n.system&&Object.keys(n.system).length>0),d=Math.max(1,Math.min(50,i??50));for(;;){let i={limit:d};u&&(i.filter=n),l&&(i.cursor=l);let{nodes:m,cursor:h}=(0,a.decodeCodec)(p,await f(`Preference Query`,()=>e.post(`v1/preferences/${t}/query`,{json:i}).json(),{maxAttempts:5,onRetry:(e,t,n)=>{r.t.warn(o.default.yellow(`Retry attempt ${e} for fetchConsentPreferences due to error: ${n}`))}}));if(!m||m.length===0||(s?await s(m):c.push(...m),!h))break;l=h}return s?[]:c}async function Z(e,{partition:t,identifierChunk:n,timestamp:i}){try{let{failures:s}=(0,a.decodeCodec)(F,await f(`Delete Preference Records`,()=>e.post(`v1/preferences/${t}/delete`,{json:{records:n.map(e=>({anchorIdentifier:e,timestamp:i.toISOString()}))}}).json(),{maxAttempts:3,onRetry:(e,t,n)=>{r.t.debug(o.default.yellow(`Attempt ${e} to delete preference records failed: ${n}`))}}));return s.length>0?s.map(({index:e,error:t})=>({...n[e],error:t})):[]}catch(e){return n.map(t=>({...t,error:e.message}))}}async function Q(e,{partition:t,filePath:r,timestamp:i,maxItemsInChunk:a,maxConcurrency:o}){return(await n.Ts(n.Ns(n.oi(r,I),a),async n=>await Z(e,{partition:t,identifierChunk:n,timestamp:i}),{concurrency:o})).flat()}Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return L}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return R}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return X}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return Y}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return Q}});
|
|
7
|
-
//# sourceMappingURL=preference-management-
|
|
7
|
+
//# sourceMappingURL=preference-management-Dsrpuzbl.cjs.map
|