diff --git a/bun.lock b/bun.lock index 33738ef60..766698e31 100644 --- a/bun.lock +++ b/bun.lock @@ -38,7 +38,7 @@ "circuit-json-to-bom-csv": "^0.0.7", "circuit-json-to-connectivity-map": "^0.0.25", "circuit-json-to-fdm-component-box": "^0.0.2", - "circuit-json-to-footprinter": "^0.0.15", + "circuit-json-to-footprinter": "^0.0.46", "circuit-json-to-gerber": "^0.0.94", "circuit-json-to-kicad": "0.0.157", "circuit-json-to-pnp-csv": "^0.0.9", @@ -573,7 +573,7 @@ "circuit-json-to-fdm-component-box": ["circuit-json-to-fdm-component-box@0.0.2", "", { "dependencies": { "@tscircuit/alphabet": "^0.0.25", "circuit-json": "^0.0.465", "fflate": "^0.8.3", "manifold-3d": "3.5.1", "poppygl": "^0.0.26" }, "peerDependencies": { "typescript": "^5" }, "bin": { "circuit-json-to-fdm-component-box": "dist/cli.js" } }, "sha512-9Xv/Q87ZIc+u11zYzVhhSBWCZRzTpp5yitJgVb0kot/zvzMYAvGqrCU9rI9WEsKD2tjK3jOgfy2cXdkcuYoMrQ=="], - "circuit-json-to-footprinter": ["circuit-json-to-footprinter@0.0.15", "", { "dependencies": { "@tscircuit/footprinter": "^0.0.385", "@tscircuit/math-utils": "^0.0.36", "circuit-json": "^0.0.448", "format-si-unit": "^0.0.10" } }, "sha512-TBRI7rryKSWA15aX0LpNdy4RvKUQQ+qpp3FHpMblPW1IpzKQTQOi6lqcbABWzDllh7Cd3QZEvwYJYjdbGfm5Sw=="], + "circuit-json-to-footprinter": ["circuit-json-to-footprinter@0.0.46", "", { "dependencies": { "@tscircuit/footprinter": "0.0.418", "@tscircuit/manifold-2d": "^0.0.6", "@tscircuit/math-utils": "^0.0.36", "circuit-json": "^0.0.453", "format-si-unit": "^0.0.10" } }, "sha512-tvnKI7iX2ysyUEl9CDcG7A74aQSfRuGrNlZUvqt3eJ8qFm6t+QEa1qE14//3k0v3KOSCrG037PWG8Q+mYG37CQ=="], "circuit-json-to-gerber": ["circuit-json-to-gerber@0.0.94", "", { "dependencies": { "@tscircuit/alphabet": "^0.0.25", "fast-json-stable-stringify": "^2.1.0", "polygon-clipping": "^0.15.7", "transformation-matrix": "^3.0.0" }, "peerDependencies": { "circuit-json": "*", "tscircuit": "*", "typescript": "^5.0.0" }, "bin": { "circuit-to-gerber": "dist/cli.js" } }, "sha512-moJ8C7vFzm20H1Ydzyqyqe3GQQWyyFOmi8qHarmEfzBEeu2exV98nIUIOtI6gSpdP0lMWdYTJKMfkb6xIri1JA=="], @@ -1319,9 +1319,7 @@ "circuit-json-to-fdm-component-box/poppygl": ["poppygl@0.0.26", "", { "dependencies": { "fast-png": "^8.0.0", "gl-matrix": "^3.4.4", "pureimage": "^0.4.18", "readable-stream": "^4.7.0" }, "peerDependencies": { "typescript": "^5" } }, "sha512-5jnQuKpDCfFT0b9aCm/AidGdzwjw/I3obFpc10j66FY7ZtDPMRekHYU76BzfKDyV5iU8BBWQzxX+8lS9+EEkbg=="], - "circuit-json-to-footprinter/@tscircuit/footprinter": ["@tscircuit/footprinter@0.0.385", "", { "dependencies": { "@tscircuit/mm": "^0.0.8", "zod": "^3.23.8" }, "peerDependencies": { "circuit-json": "*" } }, "sha512-kJZT+2NqEkgjCnMZCdeib++OAvImjPbXjvylqvGXcdfBXXN1o+GBHCCFszjIThmJngHERdiyEzvDEBAlyCS4bg=="], - - "circuit-json-to-footprinter/circuit-json": ["circuit-json@0.0.448", "", {}, "sha512-4qKp+2/aNoynSckOBRg6UcxkySX9XNi9FeXZG8PbTZexPKHUW4HOnuab7UA4SW0YLnppUtCCgx461YEA8ruFqw=="], + "circuit-json-to-footprinter/circuit-json": ["circuit-json@0.0.453", "", { "peerDependencies": { "format-si-unit": "*" } }, "sha512-BxdRuD6WPlUXfwQjwZzX0dA9V6CsmusH5SK4UT34oheCU/XPGi+SZuUHfUTqvKd+V8LcCa68+Hjkdld7x4BG1Q=="], "circuit-json-to-gerber/transformation-matrix": ["transformation-matrix@3.1.0", "", {}, "sha512-oYubRWTi2tYFHAL2J8DLvPIqIYcYZ0fSOi2vmSy042Ho4jBW2ce6VP7QfD44t65WQz6bw5w1Pk22J7lcUpaTKA=="], diff --git a/lib/shared/circuit-json-to-footprinter.ts b/lib/shared/circuit-json-to-footprinter.ts index 20c9212e8..e204c4bfc 100644 --- a/lib/shared/circuit-json-to-footprinter.ts +++ b/lib/shared/circuit-json-to-footprinter.ts @@ -1,8 +1,8 @@ import type { AnyCircuitElement } from "circuit-json" import { - circuitJsonToFootprinter as circuitJsonToFootprinterWithBundledTypes, type CircuitJsonToFootprinterOptions, type FootprinterDiscoveryResult, + circuitJsonToFootprinter as circuitJsonToFootprinterWithBundledTypes, } from "circuit-json-to-footprinter" export type { FootprinterDiscoveryCandidate } from "circuit-json-to-footprinter" @@ -12,7 +12,7 @@ type CircuitJsonToFootprinter = ( options?: CircuitJsonToFootprinterOptions, ) => FootprinterDiscoveryResult -// circuit-json-to-footprinter@0.0.15 bundles an older circuit-json type. -// Keep that compatibility detail isolated at this dependency boundary. +// circuit-json-to-footprinter bundles its own circuit-json version, which can +// differ from the CLI peer version. Keep that type drift isolated here. export const circuitJsonToFootprinter = circuitJsonToFootprinterWithBundledTypes as CircuitJsonToFootprinter diff --git a/package.json b/package.json index e76e0d46f..df82b4c8a 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "circuit-json-to-bom-csv": "^0.0.7", "circuit-json-to-connectivity-map": "^0.0.25", "circuit-json-to-fdm-component-box": "^0.0.2", - "circuit-json-to-footprinter": "^0.0.15", + "circuit-json-to-footprinter": "^0.0.46", "circuit-json-to-gerber": "^0.0.94", "circuit-json-to-kicad": "0.0.157", "circuit-json-to-pnp-csv": "^0.0.9", diff --git a/scripts/bun-build.ts b/scripts/bun-build.ts index a4aad997d..4ac75bfee 100644 --- a/scripts/bun-build.ts +++ b/scripts/bun-build.ts @@ -35,10 +35,18 @@ if (!success) { process.exit(1) } +const manifoldWasmSourcePath = Bun.resolveSync( + "@tscircuit/manifold-2d/manifold.wasm", + import.meta.dir, +) +const manifoldWasm = Bun.file(manifoldWasmSourcePath) +await Bun.write("./dist/cli/manifold.wasm", manifoldWasm) + for (const output of outputs) { console.log( `${basename(output.path)} ${(output.size / 1024 / 1024).toFixed(2)} MB`, ) } +console.log(`manifold.wasm ${(manifoldWasm.size / 1024 / 1024).toFixed(2)} MB`) export {} diff --git a/tests/lib/import/__snapshots__/C2871569-thermal-vias.snap.svg b/tests/lib/import/__snapshots__/C2871569-thermal-vias.snap.svg new file mode 100644 index 000000000..60cece620 --- /dev/null +++ b/tests/lib/import/__snapshots__/C2871569-thermal-vias.snap.svg @@ -0,0 +1 @@ +{REF} \ No newline at end of file diff --git a/tests/lib/import/convert-imported-footprint-to-footprinter.test.ts b/tests/lib/import/convert-imported-footprint-to-footprinter.test.ts index 24df3cf20..9e33a0f48 100644 --- a/tests/lib/import/convert-imported-footprint-to-footprinter.test.ts +++ b/tests/lib/import/convert-imported-footprint-to-footprinter.test.ts @@ -1,4 +1,7 @@ +import "bun-match-svg" import { expect, test } from "bun:test" +import { rm, symlink, writeFile } from "node:fs/promises" +import path from "node:path" import { fp } from "@tscircuit/footprinter" import type { AnyCircuitElement, @@ -6,8 +9,7 @@ import type { PcbSmtPad, SourcePort, } from "circuit-json" -import { rm, symlink, writeFile } from "node:fs/promises" -import path from "node:path" +import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" import { convertImportedFootprintToFootprinter } from "lib/import/footprinter/convert-imported-footprint-to-footprinter" import { generateCircuitJson } from "lib/shared/generate-circuit-json" import { temporaryDirectory } from "tempy" @@ -93,6 +95,41 @@ export const TestChip = () => ( } }) +test("compacts C2871569 while preserving its 4x4 thermal-via array", () => { + const circuitJson = fp + .string( + "qfn64_thermalpad6.3mmx6.3mm_thermalvias4x4_thermalviapitch1mm_thermalviaid0.3048mm_thermalviaod0.6096mm_pillpads_h9.67mm_pw0.28mm_pl0.66mm", + ) + .circuitJson() as AnyCircuitElement[] + const exactTsx = + "} />" + + const result = convertImportedFootprintToFootprinter({ + circuitJson, + sourceHints: ["C2871569", "QFN-64"], + tsx: exactTsx, + }) + + expect(result.mode).toBe("footprinter") + expect(result.candidate?.footprinterString).toContain("_thermalvias4x4") + expect(result.candidate?.footprinterString).toContain("_thermalviapitch1mm") + expect(result.candidate?.footprinterString).toContain("_thermalviaid0.3048mm") + expect(result.candidate?.footprinterString).toContain("_thermalviaod0.6096mm") + expect(result.candidate?.holeIntersectionOverUnion).toBeGreaterThan(0.99) + expect(result.tsx).not.toContain("footprint={") + + const recoveredCircuitJson = fp + .string(result.candidate!.footprinterString) + .circuitJson() + expect( + recoveredCircuitJson.filter((element) => element.type === "pcb_via"), + ).toHaveLength(16) + expect(convertCircuitJsonToPcbSvg(recoveredCircuitJson)).toMatchSvgSnapshot( + import.meta.path, + "C2871569-thermal-vias", + ) +}) + test("keeps the exact footprint when copper IoU is at or below 98%", () => { const circuitJson = fp .string("res_p1.3mm_pw0.55mm_ph0.7mm") @@ -101,7 +138,7 @@ test("keeps the exact footprint when copper IoU is at or below 98%", () => { if (!firstPad || firstPad.type !== "pcb_smtpad") { throw new Error("Expected an SMT pad") } - firstPad.shape = "circle" + Object.assign(firstPad, { radius: 0.1, shape: "circle" as const }) const exactTsx = "} />" const result = convertImportedFootprintToFootprinter({