@tscircuit/cli 0.0.203 → 0.0.205

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bun.lockb CHANGED
Binary file
package/bunfig.toml ADDED
@@ -0,0 +1,2 @@
1
+ [test]
2
+ preload = ["./cli/tests/fixtures/preload.ts"]
@@ -60,17 +60,6 @@ export const fulfillExportRequests = async (
60
60
 
61
61
  if (export_request.export_parameters.should_export_gerber_zip) {
62
62
  console.log(kleur.gray(`\n exporting gerbers...`))
63
- if (typeof Bun !== "undefined") {
64
- const err_str =
65
- "Bun currently isn't capable of exporting due to an archiver bug, exports will not work."
66
- console.log(kleur.red(err_str))
67
- await dev_server_axios.post("/api/export_requests/update", {
68
- export_request_id: export_request.export_request_id,
69
- has_error: true,
70
- error: err_str,
71
- })
72
- return
73
- }
74
63
  const zip_buffer = await exportGerbersToZipBuffer(
75
64
  {
76
65
  example_file_path: export_request.example_file_path!,
@@ -5,15 +5,21 @@ import { exportGerbersToFile } from "cli/lib/export-fns/export-gerbers"
5
5
  export const exportGerbersCmd = async (ctx: AppContext, args: any) => {
6
6
  const params = z
7
7
  .object({
8
- file: z.string(),
8
+ file: z.string().optional(),
9
+ input: z.string().optional(),
9
10
  export: z.string().optional(),
10
11
  outputfile: z.string().optional().default("gerbers.zip"),
11
12
  })
13
+ .refine((data) => data.file || data.input, {
14
+ message: "Either 'file' or 'input' must be provided",
15
+ })
12
16
  .parse(args)
13
17
 
18
+ const inputFile = params.input || params.file
19
+
14
20
  await exportGerbersToFile(
15
21
  {
16
- example_file_path: params.file,
22
+ example_file_path: inputFile!,
17
23
  export_name: params.export,
18
24
  output_zip_path: params.outputfile,
19
25
  },
@@ -63,14 +63,9 @@ export const exportGerbersToFile = async (
63
63
  }
64
64
 
65
65
  console.log(kleur.gray("[zipping tmp dir]..."))
66
+ console.log(kleur.gray(" writing to " + params.output_zip_path))
66
67
  const output = fs.createWriteStream(params.output_zip_path)
67
68
 
68
- if (typeof Bun !== "undefined") {
69
- throw new Error(
70
- `Exporting gerbers doesn't currently work with Bun (bug w/ archiver module)`,
71
- )
72
- }
73
-
74
69
  const archive = archiver("zip", {
75
70
  zlib: { level: 9 },
76
71
  })
@@ -281,7 +281,11 @@ export const getProgram = (ctx: AppContext) => {
281
281
  exportCmd
282
282
  .command("gerbers")
283
283
  .description("Export Gerber files from an example file")
284
- .requiredOption("--file <file>", "Input example files")
284
+ .option(
285
+ "--file <file>",
286
+ "Input example file (deprecated, use --input instead)",
287
+ )
288
+ .option("--input <input>", "Input example file")
285
289
  .option(
286
290
  "--export <export_name>",
287
291
  "Name of export to soupify, if not specified, soupify the default/only export",
@@ -121,7 +121,12 @@ export const createContextAndRunProgram = async (process_args: any) => {
121
121
  params: args,
122
122
  }
123
123
 
124
+ if (args["color"] === false) {
125
+ kleur.enabled = false
126
+ }
127
+
124
128
  delete args["cwd"]
129
+ delete args["color"]
125
130
 
126
131
  const { _: positional, ...flagsAndParams } = args
127
132
  const args_without_globals = positional.concat(dargs(flagsAndParams))
@@ -0,0 +1,16 @@
1
+ import { test, expect, describe } from "bun:test"
2
+ import { $ } from "bun"
3
+ import { temporaryDirectory } from "tempy"
4
+ import { join } from "path"
5
+ import { existsSync } from "fs"
6
+
7
+ test("tsci export gerbers --input example-project/examples/macrokeypad.tsx", async () => {
8
+ const tempDir = temporaryDirectory()
9
+ const { stdout, stderr } =
10
+ await $`bun cli/cli.ts export gerbers --input example-project/examples/macrokeypad.tsx --outputfile ${join(tempDir, "gerbers.zip")} --no-color`
11
+
12
+ expect(stderr.toString()).toBe("")
13
+ expect(stdout.toString()).toContain("gerbers.zip")
14
+
15
+ expect(existsSync(join(tempDir, "gerbers.zip"))).toBe(true)
16
+ })
@@ -0,0 +1,49 @@
1
+ import { test, expect, describe } from "bun:test"
2
+ import { $ } from "bun"
3
+ import { temporaryDirectory } from "tempy"
4
+ import { join } from "path"
5
+ import { existsSync, readdirSync, readFileSync } from "fs"
6
+ import extract from "extract-zip"
7
+ import pcbStackup from "pcb-stackup"
8
+
9
+ test("tsci export gerbers --input example-project/examples/basic-chip.tsx", async () => {
10
+ const tempDir = temporaryDirectory()
11
+ const gerberPath = join(tempDir, "gerbers.zip")
12
+ const { stdout, stderr } =
13
+ await $`bun cli/cli.ts export gerbers --input example-project/examples/basic-chip.tsx --outputfile ${gerberPath} --no-color`
14
+
15
+ expect(stderr.toString()).toBe("")
16
+ expect(stdout.toString()).toContain("gerbers.zip")
17
+
18
+ expect(existsSync(join(tempDir, "gerbers.zip"))).toBe(true)
19
+
20
+ await extract(gerberPath, { dir: join(tempDir, "gerbers") })
21
+
22
+ const files = readdirSync(join(tempDir, "gerbers"))
23
+ const expectedFiles = [
24
+ "F_Mask.gbr",
25
+ "F_SilkScreen.gbr",
26
+ "B_Cu.gbr",
27
+ "plated.drl",
28
+ "B_SilkScreen.gbr",
29
+ "F_Cu.gbr",
30
+ "B_Paste.gbr",
31
+ "F_Paste.gbr",
32
+ "B_Mask.gbr",
33
+ "Edge_Cuts.gbr",
34
+ ]
35
+
36
+ expectedFiles.forEach((file) => {
37
+ expect(files).toContain(file)
38
+ })
39
+
40
+ const gerberOutputMap = Object.entries(
41
+ files.map((filename) => [
42
+ filename,
43
+ readFileSync(join(tempDir, "gerbers", filename)),
44
+ ]),
45
+ )
46
+
47
+ // Unfortunately doesn't work in bun yet due to some bug in node:stream
48
+ // expect(gerberOutputMap).toMatchGerberSnapshot(import.meta.path)
49
+ })
@@ -0,0 +1,54 @@
1
+ import "bun-match-svg"
2
+ import { expect } from "bun:test"
3
+ import pcbStackup, { type Stackup } from "pcb-stackup"
4
+ import { Readable } from "stream"
5
+
6
+ async function toMatchGerberSnapshot(
7
+ this: any,
8
+ gerberOutput: Record<string, string>,
9
+ testPathOriginal: string,
10
+ svgName?: string,
11
+ ) {
12
+ // Create layers array from gerberOutput
13
+ const layers = Object.entries(gerberOutput).map(([filename, content]) => ({
14
+ filename,
15
+ gerber: Readable.from(content),
16
+ }))
17
+
18
+ try {
19
+ const stackup = await pcbStackup(layers)
20
+ const svgArray: string[] = []
21
+ const svgNames: string[] = []
22
+
23
+ for (const item of Object.keys(stackup!) as Array<keyof Stackup>) {
24
+ const layer = stackup[item] as { svg: string }
25
+ if (layer.svg) {
26
+ svgArray.push(layer.svg)
27
+ svgNames.push(`${svgName}-${item}`)
28
+ }
29
+ }
30
+ return expect(svgArray).toMatchMultipleSvgSnapshots(
31
+ testPathOriginal,
32
+ svgNames,
33
+ )
34
+ } catch (error) {
35
+ throw new Error(`Failed to generate PCB stackup: ${error}`)
36
+ }
37
+ }
38
+
39
+ expect.extend({
40
+ // biome-ignore lint/suspicious/noExplicitAny:
41
+ toMatchGerberSnapshot: toMatchGerberSnapshot as any,
42
+ })
43
+
44
+ declare module "bun:test" {
45
+ interface Matchers<T = unknown> {
46
+ /**
47
+ * This doesn't currently work in bun, some bug in node:stream
48
+ */
49
+ toMatchGerberSnapshot(
50
+ testImportMetaPath: string,
51
+ svgName?: string,
52
+ ): Promise<MatcherResult>
53
+ }
54
+ }