caterium-app/ops/v1772-patch.mjs
2026-09-09 10:34:25 +03:00

116 lines
9.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import fs from 'node:fs';
const read=p=>fs.readFileSync(p,'utf8');
const write=(p,s)=>fs.writeFileSync(p,s);
const mustReplace=(s,from,to,label)=>{
const count=s.split(from).length-1;
if(!count) throw new Error(`Missing marker: ${label}`);
return s.split(from).join(to);
};
const release='20260909-v17-7-2-clients-foundation';
const cache='sun-catering-pwa-v77-20260909-v17-7-2-clients-foundation';
{
const p='public/core/performance.js'; let s=read(p);
s=mustReplace(s,"const VERSION='17.7.1';","const VERSION='17.7.2';",'performance version');
s=mustReplace(s,"const RELEASE='20260909-v17-7-1-data-layer-adoption';",`const RELEASE='${release}';`,'performance release');
s=mustReplace(s,"if(window.CateriumDataV1771||document.getElementById('cateriumDataV1771Script'))return;\n const script=document.createElement('script');script.id='cateriumDataV1771Script';script.src=`core/data-layer-v1771.js?v=${RELEASE}`;script.async=false;script.onerror=()=>console.error('[Caterium] Не загрузился data-layer-v1771.js');document.head.appendChild(script);",
"if(window.CateriumDataV1772||document.getElementById('cateriumDataV1772Script'))return;\n const script=document.createElement('script');script.id='cateriumDataV1772Script';script.src=`core/data-layer-v1772.js?v=${RELEASE}`;script.async=false;script.onerror=()=>console.error('[Caterium] Не загрузился data-layer-v1772.js');document.head.appendChild(script);",
'data layer loader');
write(p,s);
}
{
const p='public/service-worker.js'; let s=read(p);
s=mustReplace(s,"const CACHE='sun-catering-pwa-v76-20260909-v17-7-1-data-layer-adoption';",`const CACHE='${cache}';`,'sw cache');
s=mustReplace(s,"const VERSION='20260909-v17-7-1-data-layer-adoption';",`const VERSION='${release}';`,'sw version');
s=mustReplace(s,'data-layer-v1771.js','data-layer-v1772.js','sw data layer');
write(p,s);
}
{
const p='public/index.html'; let s=read(p);
s=mustReplace(s,'20260909-v17-7-1-data-layer-adoption',release,'index release');
write(p,s);
}
{
const p='public/app-runtime.js'; let s=read(p);
s=mustReplace(s,"const VERSION = '17.7.1'","const VERSION = '17.7.2'",'runtime version');
s=mustReplace(s,'v17.7.1 Data Layer Adoption','v17.7.2 Clients Foundation','runtime release label');
write(p,s);
}
{
const p='public/legacy/bootstrap.js'; let s=read(p);
s=mustReplace(s,"function dataLayer(){return window.CateriumDataV1771||window.CateriumData||window.CateriumDataV1770||null}","function dataLayer(){return window.CateriumDataV1772||window.CateriumDataV1771||window.CateriumData||window.CateriumDataV1770||null}",'legacy data layer alias');
write(p,s);
}
{
const p='package.json'; const j=JSON.parse(read(p));
j.version='17.7.2';
j.scripts['check:syntax']=j.scripts['check:syntax'].replace('public/core/data-layer-v1771.js','public/core/data-layer-v1772.js');
write(p,JSON.stringify(j,null,2)+'\n');
}
{
const p='package-lock.json'; const j=JSON.parse(read(p));
j.version='17.7.2'; if(j.packages?.['']) j.packages[''].version='17.7.2';
write(p,JSON.stringify(j,null,2)+'\n');
}
{
const p='docs/release-manifest.json'; const j=JSON.parse(read(p));
Object.assign(j,{
version:'v17.7.2',release,pwaCache:'v77-20260909-v17-7-2-clients-foundation',stabilityLoggerVersion:'17.7.2',
dataLayerPhase:3,clientDataLayer:true,clientLegacyDoubleWrite:true,clientCanonicalIdentity:'phone > normalized name > order id fallback',
clientNormalizedRpc:'sun_v17_save_client_v1772',clientLegacyRowsPreserved:true,
notes:'Client foundation: canonical client identity, loyalty and communication data routed through Caterium Data Layer with legacy localStorage compatibility and additive normalized server writes.'
});
write(p,JSON.stringify(j,null,2)+'\n');
}
{
const p='tests/static-security.mjs'; let s=read(p);
s=mustReplace(s,"dataLayer=readPub('core/data-layer-v1771.js')","dataLayer=readPub('core/data-layer-v1772.js')",'static data layer file');
s=s.split('v17-7-1-data-layer-adoption').join('v17-7-2-clients-foundation');
s=s.split('data-layer-v1771.js').join('data-layer-v1772.js');
s=s.split("const VERSION='17.7.1'").join("const VERSION='17.7.2'");
s=s.replace("if(!dataLayer.includes(\"const VERSION='17.7.2'\")||!dataLayer.includes('ordersRepo')||!dataLayer.includes('catalogRepo')||!dataLayer.includes('applyServerOrders')||!dataLayer.includes('CateriumDataV1770=api'))fail('v17.7.1 data layer missing');else ok('v17.7.1 data layer present');",
"if(!dataLayer.includes(\"const VERSION='17.7.2'\")||!dataLayer.includes('ordersRepo')||!dataLayer.includes('catalogRepo')||!dataLayer.includes('clientsRepo')||!dataLayer.includes('sun_v17_save_client_v1772')||!dataLayer.includes('CateriumDataV1771=api'))fail('v17.7.2 data layer missing');else ok('v17.7.2 data layer present');");
write(p,s);
}
{
const p='tests/release-check.mjs'; let s=read(p);
s=mustReplace(s,"dataLayer=read('core/data-layer-v1771.js')","dataLayer=read('core/data-layer-v1772.js')",'release data layer file');
s=s.split('v17-7-1-data-layer-adoption').join('v17-7-2-clients-foundation');
s=s.split('data-layer-v1771.js').join('data-layer-v1772.js');
s=s.split("pkg.version==='17.7.1'").join("pkg.version==='17.7.2'");
s=s.split("const VERSION = '17.7.1'").join("const VERSION = '17.7.2'");
s=s.split("const VERSION='17.7.1'").join("const VERSION='17.7.2'");
s=s.split('through v17.7.1').join('through v17.7.2');
s=s.replace("['17.6.2','17.6.3','17.6.4','17.6.5','17.6.6','17.6.7','17.6.8','17.6.9','17.7.0','17.7.1']","['17.6.2','17.6.3','17.6.4','17.6.5','17.6.6','17.6.7','17.6.8','17.6.9','17.7.0','17.7.1','17.7.2']");
s=s.replace("check(dataLayer.includes(\"const VERSION='17.7.2'\")&&dataLayer.includes('catalogRepo')&&dataLayer.includes('CateriumDataV1770=api'),'v17.7.1 data layer exposes order/catalog repositories with compatibility alias');",
"check(dataLayer.includes(\"const VERSION='17.7.2'\")&&dataLayer.includes('catalogRepo')&&dataLayer.includes('clientsRepo')&&dataLayer.includes('CateriumDataV1771=api'),'v17.7.2 data layer exposes order/catalog/client repositories with compatibility aliases');");
s=s.replace("check(releaseManifest.dataLayerPhase===2&&releaseManifest.dataLayerLegacyOrderWrites===true&&releaseManifest.dataLayerLegacyCatalogWrites===true,'release manifest records data layer phase 2');",
"check(releaseManifest.dataLayerPhase===3&&releaseManifest.clientDataLayer===true&&releaseManifest.clientLegacyDoubleWrite===true,'release manifest records client data layer phase 3');");
write(p,s);
}
{
const p='tests/app.spec.mjs'; let s=read(p);
s=s.split("'data-layer-v1771.js','CateriumDataV1771'").join("'data-layer-v1772.js','CateriumDataV1772'");
s=s.split('window.CateriumDataV1771').join('window.CateriumDataV1772');
s=s.split("version:'17.7.1'").join("version:'17.7.2'");
if(!s.includes("v17.7.2 client data layer uses phone then normalized name identity")){
s += `\n\ntest('v17.7.2 client data layer uses phone then normalized name identity', async ({ page }) => {\n await page.addInitScript(()=>{\n localStorage.setItem('sunOrders',JSON.stringify([{id:1,contact:' Иван Петров ',phone:'',address:'A',total:1000,lines:[]},{id:2,contact:'иван петров',phone:'',address:'B',total:2000,lines:[]},{id:3,contact:'Анна',phone:'+7 (999) 123-45-67',total:3000,lines:[]}]))\n localStorage.setItem('sunClientLoyaltyV1',JSON.stringify({'n:иван петров':{enabled:true,fixedDiscount:5}}));\n localStorage.setItem('sunClientCommunicationV1',JSON.stringify({'p:79991234567':{preferred:'telegram'}}));\n });\n await page.goto('/index.html',{waitUntil:'domcontentloaded'});\n await injectCore(page,'data-layer-v1772.js','CateriumDataV1772');\n const result=await page.evaluate(()=>{\n const d=window.CateriumDataV1772,clients=d.clients.list();\n return {version:d.VERSION,nameKey:d.clients.keyFromValues('', ' Иван Петров '),phoneKey:d.clients.keyFromValues('+7 (999) 123-45-67','Анна'),ivan:clients.find(x=>x.key==='n:иван петров'),anna:clients.find(x=>x.key==='p:79991234567'),alias:window.CateriumDataV1771===d};\n });\n expect(result.version).toBe('17.7.2');\n expect(result.nameKey).toBe('n:иван петров');\n expect(result.phoneKey).toBe('p:79991234567');\n expect(result.ivan.orderCount).toBe(2);\n expect(result.ivan.totalSpent).toBe(3000);\n expect(result.ivan.loyalty.fixedDiscount).toBe(5);\n expect(result.anna.communication.preferred).toBe('telegram');\n expect(result.alias).toBeTruthy();\n});\n`;
}
write(p,s);
}
write('docs/releases/V17.7.2-CHANGES.txt',`Caterium v17.7.2 — Clients Foundation\n\n- Added a client repository to Caterium Data Layer.\n- Canonical client identity: phone digits, then normalized name, then order ID only as a fallback.\n- Loyalty and communication stores remain backward-compatible in localStorage while being adopted by the client repository.\n- Added additive normalized client RPC sun_v17_save_client_v1772 with workspace, subscription, feature and permission checks plus optimistic version protection.\n- Existing legacy client rows are preserved for rollback safety.\n- No client UI redesign in this release.\n`);
console.log('v17.7.2 release patch applied');