import JSZip from 'jszip'; import type {OfferPreparation} from './iva-offer-preparations.ts'; import {recordOfferWorkflow,offerAttachmentValid,offerWrittenRequest} from './iva-offer-workflow.ts'; export async function buildOfferPackage(row:OfferPreparation,load:(url:string)=>Promise){ const item=recordOfferWorkflow(row,'form'),w=item.workflow!,zip=new JSZip(); for(const [folder,attachment]of [['despacho',w.decisionAttachment],['formulario',w.formAttachment]] as const){if(!attachment)continue;if(!offerAttachmentValid(attachment))throw Error('Referência de anexo inválida.');const bytes=await load(attachment.url),hash=Array.from(new Uint8Array(await crypto.subtle.digest('SHA-256',bytes))).map(b=>b.toString(16).padStart(2,'0')).join('');if(hash!==attachment.sha256)throw Error('O anexo diverge do hash registado;conjunto não emitido.');zip.file(folder+'/'+attachment.name.replace(/[^\p{L}\p{N}._-]/gu,'_'),bytes);} zip.file('pedido.txt',offerWrittenRequest(item,w));zip.file('preparacao-formulario.txt',`${w.formName}\nFonte/aplicabilidade:${w.formSource}\n${w.formContent}\nDespacho:${item.request?.decisionRef};SHA256:${w.decisionAttachment!.sha256}\nApresentação fora do InvesteMoz.`); zip.file('manifesto.json',JSON.stringify({branch:item.branch,request:item.request,workflow:w,scope:'Submissão externa;conteúdo de preparação e anexos,não recibo de entrega à autoridade.'},null,2)); return{row:item,bytes:await zip.generateAsync({type:'uint8array'})}; }