ShiboSoftwareDev/linux-gameboy-advance

A multilayer PCB carrier board routing the MCU, USB‑C, battery/AA power selector and TPS63020 regulator, LCD/SD interfaces, UART/I²C/SPI service headers, controls, audio/status LEDs, and backlight with reviewed traces and vias.

Version
1.0.125
License
unset
Stars
0

scripts/prepare-cloud-artifact.mjs

import { mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs"
import { fileURLToPath } from "node:url"
import { gzipSync } from "node:zlib"
import {
  getCloudArtifactSourceState,
  sha256File,
} from "./cloud-artifact-sources.mjs"

const projectDirectory = fileURLToPath(new URL("../", import.meta.url))
const sourcePath = new URL("../dist/index/circuit.json", import.meta.url)
const artifactDirectory = new URL("../cloud-artifacts/", import.meta.url)
const artifactPath = new URL("index.circuit.json.gz", artifactDirectory)
const siteSourcePath = new URL("../dist/index.html", import.meta.url)
const pcbSourcePath = new URL("../dist/index/pcb.svg", import.meta.url)
const schematicSourcePath = new URL(
  "../dist/index/schematic.svg",
  import.meta.url,
)
const previewSourcePath = new URL("../dist/index/3d.png", import.meta.url)
const buildOutputs = [
  sourcePath,
  siteSourcePath,
  pcbSourcePath,
  schematicSourcePath,
  previewSourcePath,
]
const sourceState = getCloudArtifactSourceState(projectDirectory)

for (const output of buildOutputs) {
  const outputMtimeMs = statSync(output).mtimeMs
  if (outputMtimeMs < sourceState.newestSourceMtimeMs) {
    throw new Error(
      `${fileURLToPath(output)} predates a board source file; run \`bun run build\` before preparing cloud artifacts`,
    )
  }
}

const circuitJsonText = readFileSync(sourcePath, "utf8")
const circuitJson = JSON.parse(circuitJsonText)

if (!Array.isArray(circuitJson) || circuitJson.length === 0) {
  throw new Error("dist/index/circuit.json is empty or malformed")
}

const emittedErrors = circuitJson.filter((element) =>
  typeof element?.type === "string" && element.type.endsWith("_error"),
)

if (emittedErrors.length > 0) {
  throw new Error(
    `Refusing to package Circuit JSON with ${emittedErrors.length} emitted error(s)`,
  )
}

mkdirSync(artifactDirectory, { recursive: true })
// Store canonical compact JSON. The pretty-printed build output is over 11 MB
// and can trigger registry upload timeouts even after gzip compression.
writeFileSync(artifactPath, gzipSync(JSON.stringify(circuitJson), { level: 9 }))
writeFileSync(
  new URL("index.html.gz", artifactDirectory),
  gzipSync(readFileSync(siteSourcePath), { level: 9 }),
)
writeFileSync(
  new URL("index.pcb.svg.gz", artifactDirectory),
  gzipSync(readFileSync(pcbSourcePath), { level: 9 }),
)
writeFileSync(
  new URL("index.schematic.svg.gz", artifactDirectory),
  gzipSync(readFileSync(schematicSourcePath), { level: 9 }),
)
writeFileSync(
  new URL("index.3d.png", artifactDirectory),
  readFileSync(previewSourcePath),
)
const artifactFiles = [
  "index.html.gz",
  "index.circuit.json.gz",
  "index.pcb.svg.gz",
  "index.schematic.svg.gz",
  "index.3d.png",
]
const artifactSha256 = Object.fromEntries(
  artifactFiles.map((file) => [
    file,
    sha256File(fileURLToPath(new URL(file, artifactDirectory))),
  ]),
)
writeFileSync(
  new URL("manifest.json", artifactDirectory),
  `${JSON.stringify({
    schemaVersion: 1,
    sourceSha256: sourceState.sourceSha256,
    sourceFiles: sourceState.sourceFiles,
    artifactSha256,
  }, null, 2)}\n`,
)
console.log(
  `Prepared 5 cloud site artifacts and freshness manifest (${circuitJson.length} elements)`,
)