shibosoftwaredev/f1c100s-linux-nema17-stepper-controller

A four-layer NEMA 17 motor-controller PCB combining an Allwinner F1C100S Linux computer, USB‑PD/buck power system, W5500 Ethernet, STM32 real-time motion control, DRV8825 stepper driver, protection/temperature/current telemetry, USB interfaces, and local LED/buzzer diagnostics.

Version
0.4.56
License
unset
Stars
0

scripts/save-checkpoint.mjs

import fs from "node:fs"
import path from "node:path"
import crypto from "node:crypto"
import assert from "node:assert/strict"
import { spawnSync } from "node:child_process"

const source = process.cwd()
const checkpointRoot = path.resolve(process.argv[2])
assert.notEqual(checkpointRoot, source)
assert.ok(!checkpointRoot.startsWith(source + path.sep), "backup must be outside source")
fs.mkdirSync(checkpointRoot, { recursive: true })
const destination = fs.mkdtempSync(path.join(checkpointRoot, process.argv[3] ?? "nema17-current-sense-20261019-"))
const hash = file => crypto.createHash("sha256").update(fs.readFileSync(file)).digest("hex")
const collect = directory => fs.readdirSync(directory, { withFileTypes: true }).flatMap(entry => {
  if (["node_modules", ".DS_Store"].includes(entry.name)) return []
  const fullPath = path.join(directory, entry.name)
  if (entry.isDirectory()) return collect(fullPath)
  assert.ok(entry.isFile(), `unexpected non-file in backup: ${fullPath}`)
  return [path.relative(source, fullPath)]
})
const files = collect(source).sort().map(file => ({ file, sha256: hash(path.join(source, file)) }))
const archive = path.join(destination, "board-checkpoint.tar.gz")
const run = args => {
  const result = spawnSync("tar", args, { encoding: "utf8" })
  assert.equal(result.status, 0, result.stderr || "archive operation failed")
}
run(["-czf", archive, "--exclude=node_modules", "--exclude=.DS_Store", "-C", source, "."])
const restored = path.join(destination, "restore-verified")
fs.mkdirSync(restored)
run(["-xzf", archive, "-C", restored])
for (const file of files)
  assert.equal(hash(path.join(restored, file.file)), file.sha256, `restored bytes match: ${file.file}`)
const manifest = {
  createdAt: new Date().toISOString(), source, archive, archiveSha256: hash(archive),
  restoredDirectory: restored, restoreVerified: true, fileCount: files.length,
  caveats: ["NOT FABRICATION READY; see verification.json and the hash-bound reports saved in this checkpoint",
    "node_modules excluded; reinstall pinned dependencies before building",
    "Remote checkpoint publishing is separate from this verified local backup"],
  circuitSha256: hash(path.join(source, "dist/index/circuit.json")),
  replaySha256: hash(path.join(source, "routing/complete-routes.json")),
  fabricationReady: false,
  files,
}
fs.writeFileSync(path.join(destination, "checkpoint-manifest.json"), JSON.stringify(manifest, null, 2) + "\n")
console.log(JSON.stringify({ destination, archive, archiveSha256: manifest.archiveSha256,
  fileCount: files.length, restoreVerified: true, fabricationReady: false }, null, 2))