From 634c01646f1446c4e9496205c110e820e6e33337 Mon Sep 17 00:00:00 2001 From: seveibar Date: Fri, 25 Oct 2024 12:40:30 -0700 Subject: [PATCH] introduce CLI, fix slot issues from experiments w/ jlcpcb --- .gitignore | 2 + bun.lockb | Bin 126966 -> 137079 bytes package.json | 8 +- src/cli.ts | 71 ++++++++++++++++++ .../getCommandHeaders.ts | 2 +- 5 files changed, 81 insertions(+), 2 deletions(-) create mode 100755 src/cli.ts diff --git a/.gitignore b/.gitignore index b151154..5156cb7 100644 --- a/.gitignore +++ b/.gitignore @@ -184,3 +184,5 @@ gerber-output gerber-output.zip .aider* *.diff.png + +tmp* \ No newline at end of file diff --git a/bun.lockb b/bun.lockb index c3a36213a08677afda03bba91f761ec7bf81051b..375f2a97244d3d9ebbd183bac54bdb0318563eb7 100755 GIT binary patch delta 25836 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 delta 19998 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 YZ6C6RqTms0FLpPO-AcCBlJ_?GKX1f?3jhEB diff --git a/package.json b/package.json index d2d12ae..bcee1bd 100644 --- a/package.json +++ b/package.json @@ -4,20 +4,26 @@ "main": "dist/index.js", "type": "module", "scripts": { - "build": "tsup-node src/index.ts --format esm --dts --sourcemap", + "build": "tsup-node src/index.ts src/cli.ts --format esm --dts --sourcemap", "format": "biome format --write .", "format:check": "biome format ." }, "files": [ "dist" ], + "bin": { + "circuit-to-gerber": "./dist/cli.js" + }, "devDependencies": { "@biomejs/biome": "^1.8.3", "@tscircuit/core": "^0.0.131", + "@types/archiver": "^6.0.3", "@types/bun": "^1.1.8", "@types/node": "^22.5.2", "@types/react": "^18.3.12", + "archiver": "^7.0.1", "bun-match-svg": "^0.0.3", + "commander": "^12.1.0", "gerber-to-svg": "^4.2.8", "pcb-stackup": "^4.2.8", "react": "^18.3.1", diff --git a/src/cli.ts b/src/cli.ts new file mode 100755 index 0000000..8da0272 --- /dev/null +++ b/src/cli.ts @@ -0,0 +1,71 @@ +#!/usr/bin/env node + +import { program } from "commander" +import { readFile, writeFile } from "node:fs/promises" +import { createWriteStream } from "node:fs" +import { resolve, dirname, basename } from "node:path" +import { fileURLToPath } from "node:url" +import archiver from "archiver" +import { convertSoupToGerberCommands, stringifyGerberCommandLayers } from "./" +import { convertSoupToExcellonDrillCommands, stringifyExcellonDrill } from "./" + +const __dirname = dirname(fileURLToPath(import.meta.url)) + +program + .name("circuit-to-gerber") + .description("Convert circuit JSON files to Gerber/Excellon files") + .argument("", "Input circuit JSON file (*.circuit.json)") + .option( + "-o, --output ", + "Output ZIP file (defaults to input.gerbers.zip)", + ) + .action(async (input, options) => { + try { + // Read and parse input JSON + const circuitJson = JSON.parse(await readFile(input, "utf8")) + + // Convert to gerber commands + const gerberCmds = convertSoupToGerberCommands(circuitJson) + const excellonDrillCmds = convertSoupToExcellonDrillCommands({ + circuitJson, + is_plated: true, + }) + const excellonDrillUnplatedCmds = convertSoupToExcellonDrillCommands({ + circuitJson, + is_plated: false, + }) + + // Stringify all outputs + const gerberOutput = stringifyGerberCommandLayers(gerberCmds) + const excellonDrillOutput = stringifyExcellonDrill(excellonDrillCmds) + const excellonDrillUnplatedOutput = stringifyExcellonDrill( + excellonDrillUnplatedCmds, + ) + + // Create output ZIP file + const outputPath = + options.output || input.replace(".circuit.json", ".gerbers.zip") + const output = createWriteStream(outputPath) + const archive = archiver("zip", { zlib: { level: 9 } }) + + archive.pipe(output) + + // Add all gerber files to ZIP + for (const [filename, content] of Object.entries(gerberOutput)) { + archive.append(content, { name: `${filename}.gbr` }) + } + + // Add drill files + archive.append(excellonDrillOutput, { name: "plated.drl" }) + archive.append(excellonDrillUnplatedOutput, { name: "unplated.drl" }) + + await archive.finalize() + + console.log(`Created ${outputPath}`) + } catch (err) { + console.error("Error:", (err as Error).message) + process.exit(1) + } + }) + +program.parse() diff --git a/src/gerber/convert-soup-to-gerber-commands/getCommandHeaders.ts b/src/gerber/convert-soup-to-gerber-commands/getCommandHeaders.ts index bdea7e6..2e0108c 100644 --- a/src/gerber/convert-soup-to-gerber-commands/getCommandHeaders.ts +++ b/src/gerber/convert-soup-to-gerber-commands/getCommandHeaders.ts @@ -1,6 +1,6 @@ import type { AnyGerberCommand } from "src/gerber/any_gerber_command" import { gerberBuilder } from "../gerber-builder" -import packageJson from "package.json" +import packageJson from "../../../package.json" const layerAndTypeToFileFunction = { "top-copper": "Copper,L1,Top",