abse/museair-usb
USB-C–powered ESP32-C3 controller board with AP63203 buck conversion, AP2112K 3.3V regulation, I²C SEN62 sensor interface, status LED, buttons, UART/I²C headers, and extensive decoupling.
- Version
- 0.5.7
- License
- unset
- Stars
- 0
scripts/hosted-build.mjs
// Use the same guarded routing pipeline locally and in tscircuit cloud builds.
import fs from 'node:fs'
import {spawnSync} from 'node:child_process'
import {createHash} from 'node:crypto'
import {Resvg} from '@resvg/resvg-js'
const run=(args)=>{const p=spawnSync('bun',args,{stdio:'inherit'});if(p.status!==0)throw Error(`Build command failed (${p.status}): bun ${args.join(' ')}`)}
const sha=v=>createHash('sha256').update(JSON.stringify(v)).digest('hex')
const baseline=JSON.parse(fs.readFileSync('scripts/hosted-build-baseline.json'))
// Use the native-viewer assembly preview: CLI's binary-only GLTF parser cannot
// parse the PCB's external-buffer GLTF. Interactive CAD uses the full model.
fs.mkdirSync('dist/assembly',{recursive:true})
fs.copyFileSync('preview/flat-light-pipe-closed.png','dist/assembly/3d.png')
run(['x','tscircuit','build','--routing-disabled','--disable-parts-engine','--site','--transpile','--use-cdn-javascript','--pcb-svgs','--schematic-svgs','--concurrency','1'])
run(['scripts/repair-routing.mjs'])
const board=JSON.parse(fs.readFileSync('dist/index/circuit.json'))
if(board.some(x=>x.type.includes('error')))throw Error('Circuit errors remain after routing validation')
for(const [name,types] of Object.entries(baseline.types)){
const actual=sha(board.filter(x=>types.includes(x.type)))
if(actual!==baseline.hashes[name])throw Error(`Reviewed ${name} changed; reroute and review before publishing`)
}
const assembly=JSON.parse(fs.readFileSync('dist/assembly/circuit.json'))
if(assembly.some(x=>x.type.includes('error'))||assembly.filter(x=>x.type==='cad_component').length!==19)throw Error('Invalid assembly output')
// File-detail viewer uses this alias; retain the real board as the default.
fs.mkdirSync('dist/assembly.circuit',{recursive:true})
fs.copyFileSync('dist/assembly/circuit.json','dist/assembly.circuit/circuit.json')
for(const entry of ['index','assembly']){
for(const kind of ['pcb','schematic']){
const svg=`dist/${entry}/${kind}.svg`
if(fs.existsSync(svg))fs.writeFileSync(`dist/${entry}/${kind}.png`,new Resvg(fs.readFileSync(svg),{fitTo:{mode:'width',value:1600}}).render().asPng())
}
}
fs.mkdirSync('validation',{recursive:true})
fs.writeFileSync('validation/hosted-build-review.json',JSON.stringify({status:'pass',reviewed_geometry_nets_copper_unchanged:true,board_errors:0,assembly_cad_groups:19},null,2))
console.log('Hosted build verified: original geometry, nets and reviewed copper; zero circuit errors; 19 assembly CAD groups.')