AnasSarkiz/muse-voice-remote
Muse Voice Remote — bare ESP32-S3R8, 155 TOP JLCPCB parts with real supplier CAD, native 3D assembly and GLB exports. Revised 17 mm case allocation; 0.30 mm via drill /0.45 mm pad. Checked prototype PCB; mechanical, RF and MUSE qualification pending.
- Version
- 1.3.2
- License
- unset
- Stars
- 0
scripts/chunk-assets.ts
import {readFile,writeFile,mkdir,rm,readdir} from "node:fs/promises"
import {createHash} from "node:crypto"
import {dirname,join,basename} from "node:path"
const hash=(bytes:Uint8Array)=>createHash("sha256").update(bytes).digest("hex")
export async function writeAssetChunks(files:string[],manifestFile:string){
const root=dirname(manifestFile),directory=join(root,"asset-parts")
await mkdir(directory,{recursive:true})
const assets:Record<string,{bytes:number;sha256:string;parts:{path:string;bytes:number;sha256:string}[]}>= {}
for(const file of files){
const bytes=await readFile(file),name=basename(file),parts=[]
for(const old of await readdir(directory))
if(old.startsWith(`${name}.part`)&&old.endsWith(".bin"))await rm(join(directory,old))
for(let start=0,n=0;start<bytes.length;start+=2*1024*1024,n++){
const chunk=bytes.subarray(start,Math.min(start+2*1024*1024,bytes.length))
const path=`asset-parts/${name}.part${String(n).padStart(3,"0")}.bin`
await writeFile(join(root,path),chunk)
parts.push({path,bytes:chunk.length,sha256:hash(chunk)})
}
const reassembled=Buffer.concat(await Promise.all(parts.map(p=>readFile(join(root,p.path)))))
if(!reassembled.equals(bytes))throw Error(`Asset round trip failed: ${name}`)
assets[name]={bytes:bytes.length,sha256:hash(bytes),parts}
}
const result={format:"sha256-verified-byte-parts-v1",chunk_bytes:2*1024*1024,assets}
await writeFile(manifestFile,JSON.stringify(result,null,2)+"\n")
return result
}