// Create a separate mutable copy. Never edits a supplied or frozen candidate. import assert from 'node:assert/strict';import{readFile,writeFile,mkdir,cp,readdir,access,realpath}from'node:fs/promises';import path from'node:path';import{createHash}from'node:crypto'; const[sourceArg,replacementArg,targetArg]=process.argv.slice(2);assert(sourceArg&&replacementArg&&targetArg,'Usage: node REPLACE-HEIC.mjs ');const source=await realpath(sourceArg),replacement=await readFile(replacementArg),target=path.resolve(targetArg);assert(target!==source&&!target.startsWith(source+path.sep),'Choose a separate new directory');try{await access(target);throw Error('Output exists; choose a new directory.');}catch(e){if(e.code!=='ENOENT')throw e;}assert(replacement.length>0);const leaf='assets/image-heic-lib.mjs',old=await readFile(path.join(source,leaf)),sha=b=>createHash('sha256').update(b).digest('hex');await mkdir(target,{recursive:false});await cp(source,path.join(target,'public'),{recursive:true,force:false,errorOnExist:true});await writeFile(path.join(target,'public',leaf),replacement); const files=[];async function walk(dir,prefix=''){for(const e of await readdir(dir,{withFileTypes:true})){assert(!e.isSymbolicLink(),'No symlinks');const rel=prefix?prefix+'/'+e.name:e.name;if(e.isDirectory())await walk(path.join(dir,e.name),rel);else{const bytes=await readFile(path.join(dir,e.name));files.push({file:rel,bytes:bytes.length,sha256:sha(bytes)});if(rel!==leaf)assert(bytes.equals(await readFile(path.join(source,rel))),'Unexpected change '+rel);}}}await walk(path.join(target,'public'));files.sort((a,b)=>a.file.localeCompare(b.file));await writeFile(path.join(target,'PUBLIC-MANIFEST.json'),JSON.stringify(files,null,2)+'\n',{flag:'wx'});await writeFile(path.join(target,'REPLACEMENT-RECEIPT.json'),JSON.stringify({status:'SEPARATE_MUTABLE_COPY_CREATED_RETEST_REQUIRED',replacementLeaf:leaf,originalSHA256:sha(old),replacementSHA256:sha(replacement),otherFilesByteIdentical:true,originalCandidateModified:false,policyChanged:false,rootEntrySRIChanged:false,compatibility:'Replacement must export a compatible libheif module factory/object including HeifDecoder and existing image/free APIs. Same origin dynamic import remains separate from the application. Re-test HEIC outputs and existing resource limits. No installation, upload, policy relaxation or execution of replacement was performed by this helper.'},null,2)+'\n',{flag:'wx'});console.log(JSON.stringify({status:'SEPARATE_MUTABLE_COPY_CREATED_RETEST_REQUIRED',files:files.length,originalCandidateModified:false,policyChanged:false}));