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))