@tscircuit/cli 0.0.61 → 0.0.63

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.
Files changed (27) hide show
  1. package/cli.ts +4 -2
  2. package/dev-server-api/bun.lockb +0 -0
  3. package/dev-server-api/routes/api/export_files/create.ts +32 -0
  4. package/dev-server-api/routes/api/export_files/download.ts +24 -0
  5. package/dev-server-api/routes/api/export_requests/create.ts +17 -49
  6. package/dev-server-api/routes/api/export_requests/get.ts +37 -0
  7. package/dev-server-api/routes/api/export_requests/list.ts +28 -0
  8. package/dev-server-api/routes/api/export_requests/update.ts +26 -0
  9. package/dev-server-api/src/db/create-schema.ts +1 -1
  10. package/dev-server-api/src/db/get-db.ts +4 -4
  11. package/dev-server-api/src/lib/public-mapping/public-map-export-file.ts +17 -0
  12. package/dev-server-api/src/lib/public-mapping/public-map-export-request.ts +23 -0
  13. package/dev-server-api/src/lib/zod/export_file.ts +8 -0
  14. package/dev-server-api/src/lib/zod/export_parameters.ts +10 -0
  15. package/dev-server-api/src/lib/zod/export_request.ts +19 -0
  16. package/dev-server-frontend/src/components/dialogs/gerber-export-dialog.tsx +45 -8
  17. package/dist/cli.js +356 -114
  18. package/lib/cmd-fns/dev/fulfill-export-requests.ts +56 -0
  19. package/lib/cmd-fns/dev/index.ts +5 -2
  20. package/lib/cmd-fns/dev/start-export-request-watcher.ts +39 -0
  21. package/lib/cmd-fns/dev/upload-examples-from-directory.ts +5 -1
  22. package/lib/cmd-fns/dev-server-fulfill-export-requests.ts +43 -0
  23. package/lib/cmd-fns/index.ts +1 -0
  24. package/lib/export-gerbers.ts +10 -0
  25. package/lib/get-program.ts +4 -0
  26. package/package.json +1 -1
  27. package/dev-server-api/routes/api/export_files/create_or_update.ts +0 -0
package/cli.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ import kleur from "kleur"
3
4
  import { AppContext } from "./lib/util/app-context"
4
5
  import { createContextAndRunProgram } from "./lib/util/create-context-and-run-program"
5
6
 
@@ -7,6 +8,7 @@ async function main() {
7
8
  await createContextAndRunProgram(process.argv)
8
9
  }
9
10
 
10
- main().catch((e) => {
11
- console.log("Error running CLI:", e.toString())
11
+ main().catch((e: any) => {
12
+ console.log(kleur.gray(e.stack))
13
+ console.log(kleur.red(`Error running CLI: ${e.toString()}`))
12
14
  })
Binary file
@@ -0,0 +1,32 @@
1
+ import { publicMapExportFile } from "src/lib/public-mapping/public-map-export-file"
2
+ import { export_file } from "src/lib/zod/export_file"
3
+ import { withEdgeSpec } from "src/with-edge-spec"
4
+ import { z } from "zod"
5
+
6
+ export default withEdgeSpec({
7
+ methods: ["POST"],
8
+ jsonBody: z.object({
9
+ export_request_id: z.number().int(),
10
+ file_name: z.string(),
11
+ file_content_base64: z.string().transform((a) => Buffer.from(a, "base64")),
12
+ }),
13
+ jsonResponse: z.object({
14
+ export_file,
15
+ }),
16
+ auth: "none",
17
+ })(async (req, ctx) => {
18
+ const db_export_file = await ctx.db
19
+ .insertInto("export_file")
20
+ .values({
21
+ export_request_id: req.jsonBody.export_request_id,
22
+ file_name: req.jsonBody.file_name,
23
+ file_content: req.jsonBody.file_content_base64,
24
+ created_at: new Date().toISOString(),
25
+ })
26
+ .returningAll()
27
+ .executeTakeFirstOrThrow()
28
+
29
+ return ctx.json({
30
+ export_file: publicMapExportFile(db_export_file),
31
+ })
32
+ })
@@ -0,0 +1,24 @@
1
+ import { publicMapExportFile } from "src/lib/public-mapping/public-map-export-file"
2
+ import { export_file } from "src/lib/zod/export_file"
3
+ import { withEdgeSpec } from "src/with-edge-spec"
4
+ import { z } from "zod"
5
+
6
+ export default withEdgeSpec({
7
+ methods: ["GET"],
8
+ queryParams: z.object({
9
+ export_file_id: z.coerce.number().int(),
10
+ }),
11
+ auth: "none",
12
+ })(async (req, ctx) => {
13
+ const db_export_file = await ctx.db
14
+ .selectFrom("export_file")
15
+ .selectAll()
16
+ .where("export_file_id", "=", req.query.export_file_id)
17
+ .executeTakeFirstOrThrow()
18
+
19
+ return new Response(db_export_file.file_content, {
20
+ headers: {
21
+ "Content-Disposition": `attachment; filename="${db_export_file.file_name}"`,
22
+ },
23
+ })
24
+ })
@@ -1,67 +1,35 @@
1
1
  import { withEdgeSpec } from "src/with-edge-spec"
2
2
  import { NotFoundError } from "edgespec/middleware"
3
3
  import { z } from "zod"
4
+ import { export_request } from "src/lib/zod/export_request"
5
+ import { publicMapExportRequest } from "src/lib/public-mapping/public-map-export-request"
6
+ import { export_parameters } from "../../../src/lib/zod/export_parameters"
4
7
 
5
8
  export default withEdgeSpec({
6
9
  methods: ["POST"],
7
10
  jsonBody: z.object({
8
11
  example_file_path: z.string(),
9
12
  export_name: z.string().nullable().optional(),
10
- export_parameters: z.object({
11
- should_export_gerber_zip: z.boolean().default(false),
12
- gerbers_zip_file_name: z
13
- .string()
14
- .nullable()
15
- .optional()
16
- .default("gerbers.zip"),
17
- }),
13
+ export_parameters: export_parameters,
18
14
  }),
19
15
  jsonResponse: z.object({
20
- export_request: z.object({
21
- export_request_id: z.coerce.number(),
22
- created_at: z.string(),
23
- file_summary: z.array(
24
- z.object({
25
- file_name: z.string(),
26
- is_complete: z.boolean(),
27
- })
28
- ),
29
- }),
16
+ export_request,
30
17
  }),
31
18
  auth: "none",
32
19
  })(async (req, ctx) => {
33
- // const tscircuit_soup = req.jsonBody.tscircuit_soup
34
- // ? JSON.stringify(req.jsonBody.tscircuit_soup)
35
- // : undefined
36
- // const dev_package_example = await ctx.db
37
- // .insertInto("dev_package_example")
38
- // .values({
39
- // file_path: req.jsonBody.file_path,
40
- // export_name: req.jsonBody.export_name,
41
- // error: req.jsonBody.error,
42
- // tscircuit_soup,
43
- // is_loading: req.jsonBody.is_loading ? 1 : 0,
44
- // last_updated_at: new Date().toISOString(),
45
- // })
46
- // .onConflict((oc) =>
47
- // oc.columns(["file_path"]).doUpdateSet({
48
- // export_name: req.jsonBody.export_name,
49
- // error: req.jsonBody.error,
50
- // tscircuit_soup,
51
- // is_loading: req.jsonBody.is_loading ? 1 : 0,
52
- // last_updated_at: new Date().toISOString(),
53
- // })
54
- // )
55
- // .returningAll()
56
- // .executeTakeFirstOrThrow()
57
-
58
- const export_request = {
59
- export_request_id: 1,
60
- created_at: new Date().toISOString(),
61
- file_summary: [],
62
- }
20
+ const db_export_request = await ctx.db
21
+ .insertInto("export_request")
22
+ .values({
23
+ example_file_path: req.jsonBody.example_file_path,
24
+ export_parameters: JSON.stringify(req.jsonBody.export_parameters),
25
+ export_name: req.jsonBody.export_name ?? "default",
26
+ is_complete: 0,
27
+ created_at: new Date().toISOString(),
28
+ })
29
+ .returningAll()
30
+ .executeTakeFirstOrThrow()
63
31
 
64
32
  return ctx.json({
65
- export_request,
33
+ export_request: publicMapExportRequest(db_export_request),
66
34
  })
67
35
  })
@@ -0,0 +1,37 @@
1
+ import { withEdgeSpec } from "src/with-edge-spec"
2
+ import { z } from "zod"
3
+ import { export_request } from "src/lib/zod/export_request"
4
+ import { publicMapExportRequest } from "src/lib/public-mapping/public-map-export-request"
5
+
6
+ export default withEdgeSpec({
7
+ methods: ["GET", "POST"],
8
+ commonParams: z.object({
9
+ export_request_id: z.coerce.number(),
10
+ }),
11
+ jsonResponse: z.object({
12
+ export_request: export_request,
13
+ }),
14
+ auth: "none",
15
+ })(async (req, ctx) => {
16
+ const { export_request_id } = req.commonParams
17
+ const db_export_request: any = await ctx.db
18
+ .selectFrom("export_request")
19
+ .selectAll()
20
+ .where("export_request_id", "=", export_request_id)
21
+ .executeTakeFirstOrThrow()
22
+
23
+ db_export_request.file_summary = (
24
+ await ctx.db
25
+ .selectFrom("export_file")
26
+ .where("export_request_id", "=", export_request_id)
27
+ .selectAll()
28
+ .execute()
29
+ ).map((ef) => ({
30
+ file_name: ef.file_name,
31
+ export_file_id: ef.export_file_id,
32
+ }))
33
+
34
+ return ctx.json({
35
+ export_request: publicMapExportRequest(db_export_request),
36
+ })
37
+ })
@@ -0,0 +1,28 @@
1
+ import { withEdgeSpec } from "src/with-edge-spec"
2
+ import { z } from "zod"
3
+ import { export_request } from "src/lib/zod/export_request"
4
+ import { publicMapExportRequest } from "src/lib/public-mapping/public-map-export-request"
5
+
6
+ export default withEdgeSpec({
7
+ methods: ["GET", "POST"],
8
+ commonParams: z.object({
9
+ is_complete: z.boolean().nullable().default(null),
10
+ }),
11
+ jsonResponse: z.object({
12
+ export_requests: z.array(export_request),
13
+ }),
14
+ auth: "none",
15
+ })(async (req, ctx) => {
16
+ const { is_complete } = req.commonParams
17
+ const db_export_requests = await ctx.db
18
+ .selectFrom("export_request")
19
+ .selectAll()
20
+ .$if(is_complete !== null, (q) =>
21
+ q.where("export_request.is_complete", "=", is_complete ? 1 : 0)
22
+ )
23
+ .execute()
24
+
25
+ return ctx.json({
26
+ export_requests: db_export_requests.map((er) => publicMapExportRequest(er)),
27
+ })
28
+ })
@@ -0,0 +1,26 @@
1
+ import { withEdgeSpec } from "src/with-edge-spec"
2
+ import { NotFoundError } from "edgespec/middleware"
3
+ import { z } from "zod"
4
+ import { export_request } from "src/lib/zod/export_request"
5
+ import { publicMapExportRequest } from "src/lib/public-mapping/public-map-export-request"
6
+ import { export_parameters } from "src/lib/zod/export_parameters"
7
+
8
+ export default withEdgeSpec({
9
+ methods: ["POST"],
10
+ jsonBody: z.object({
11
+ export_request_id: z.coerce.number(),
12
+ is_complete: z.boolean(),
13
+ }),
14
+ jsonResponse: z.object({}),
15
+ auth: "none",
16
+ })(async (req, ctx) => {
17
+ await ctx.db
18
+ .updateTable("export_request")
19
+ .set({
20
+ is_complete: req.jsonBody.is_complete ? 1 : 0,
21
+ })
22
+ .where("export_request_id", "=", req.jsonBody.export_request_id)
23
+ .execute()
24
+
25
+ return ctx.json({})
26
+ })
@@ -20,7 +20,7 @@ export const createSchema = async (db: DbClient) => {
20
20
  col.primaryKey().autoIncrement()
21
21
  )
22
22
  .addColumn("example_file_path", "text")
23
- .addColumn("export_parameters", "jsonb")
23
+ .addColumn("export_parameters", "json")
24
24
  .addColumn("export_name", "text")
25
25
  .addColumn("is_complete", "boolean", (col) => col.defaultTo(0).notNull())
26
26
  .addColumn("created_at", "text")
@@ -3,7 +3,7 @@ import { createSchema } from "./create-schema"
3
3
  import { mkdirSync } from "fs"
4
4
  import * as Path from "path"
5
5
 
6
- interface DevPackageExample {
6
+ export interface DevPackageExample {
7
7
  dev_package_example_id: Generated<number>
8
8
  tscircuit_soup: any
9
9
  file_path: string
@@ -13,19 +13,19 @@ interface DevPackageExample {
13
13
  last_updated_at: string
14
14
  }
15
15
 
16
- interface ExportRequest {
16
+ export interface ExportRequest {
17
17
  export_request_id: Generated<number>
18
18
  example_file_path: string
19
+ export_parameters: string
19
20
  export_name: string
20
21
  is_complete: 1 | 0
21
22
  created_at: string
22
23
  }
23
24
 
24
- interface ExportFile {
25
+ export interface ExportFile {
25
26
  export_file_id: Generated<number>
26
27
  file_name: string
27
28
  file_content: Buffer
28
- is_complete: 1 | 0
29
29
  export_request_id: number
30
30
  created_at: string
31
31
  }
@@ -0,0 +1,17 @@
1
+ import type { ExportRequest } from "src/db/get-db"
2
+ import { export_file } from "src/lib/zod/export_file"
3
+ import { z } from "zod"
4
+
5
+ export const publicMapExportFile = (db_export_file: {
6
+ export_file_id: number
7
+ export_request_id: number
8
+ file_name: string
9
+ created_at: string
10
+ }): z.infer<typeof export_file> => {
11
+ return {
12
+ export_request_id: db_export_file.export_request_id as any,
13
+ export_file_id: db_export_file.export_file_id as any,
14
+ file_name: db_export_file.file_name,
15
+ created_at: db_export_file.created_at,
16
+ }
17
+ }
@@ -0,0 +1,23 @@
1
+ import type { ExportRequest } from "src/db/get-db"
2
+ import { export_request } from "src/lib/zod/export_request"
3
+ import { z } from "zod"
4
+
5
+ export const publicMapExportRequest = (db_export_request: {
6
+ export_request_id: number
7
+ example_file_path: string
8
+ export_parameters: string
9
+ export_name: string
10
+ is_complete: 1 | 0
11
+ file_summary?: Array<any>
12
+ created_at: string
13
+ }): z.infer<typeof export_request> => {
14
+ return {
15
+ export_request_id: db_export_request.export_request_id as any,
16
+ example_file_path: db_export_request.example_file_path,
17
+ export_name: db_export_request.export_name,
18
+ is_complete: db_export_request.is_complete === 1,
19
+ export_parameters: JSON.parse(db_export_request.export_parameters),
20
+ file_summary: db_export_request.file_summary,
21
+ created_at: db_export_request.created_at,
22
+ }
23
+ }
@@ -0,0 +1,8 @@
1
+ import { z } from "zod"
2
+
3
+ export const export_file = z.object({
4
+ export_file_id: z.number().int(),
5
+ export_request_id: z.number().int(),
6
+ file_name: z.string(),
7
+ created_at: z.string(),
8
+ })
@@ -0,0 +1,10 @@
1
+ import { z } from "zod"
2
+
3
+ export const export_parameters = z.object({
4
+ should_export_gerber_zip: z.boolean().default(false),
5
+ gerbers_zip_file_name: z
6
+ .string()
7
+ .nullable()
8
+ .optional()
9
+ .default("gerbers.zip"),
10
+ })
@@ -0,0 +1,19 @@
1
+ import { z } from "zod"
2
+ import { export_parameters } from "./export_parameters"
3
+
4
+ export const export_request = z.object({
5
+ export_request_id: z.coerce.number(),
6
+ is_complete: z.boolean(),
7
+ created_at: z.string(),
8
+ export_name: z.string(),
9
+ example_file_path: z.string(),
10
+ export_parameters,
11
+ file_summary: z
12
+ .array(
13
+ z.object({
14
+ file_name: z.string(),
15
+ export_file_id: z.number().int(),
16
+ })
17
+ )
18
+ .optional(),
19
+ })
@@ -45,14 +45,51 @@ export const useGerberExportDialog = () => {
45
45
  setExportError(null)
46
46
  setIsExporting(true)
47
47
  try {
48
- await axios.post("/api/export_requests/create", {
49
- example_file_path: activeDevExamplePackage.file_path,
50
- export_name: activeDevExamplePackage.export_name,
51
- export_parameters: {
52
- should_export_gerber_zip: true,
53
- gerbers_zip_file_name: outputName,
54
- },
55
- })
48
+ let export_request = await axios
49
+ .post("/api/export_requests/create", {
50
+ example_file_path: activeDevExamplePackage.file_path,
51
+ export_name: activeDevExamplePackage.export_name,
52
+ export_parameters: {
53
+ should_export_gerber_zip: true,
54
+ gerbers_zip_file_name: outputName,
55
+ },
56
+ })
57
+ .then((r) => r.data.export_request)
58
+
59
+ const pollExportRequest = async () => {
60
+ while (!export_request.is_complete) {
61
+ try {
62
+ export_request = await axios
63
+ .post("/api/export_requests/get", {
64
+ export_request_id: export_request.export_request_id,
65
+ })
66
+ .then((r) => r.data.export_request)
67
+ } catch (e: any) {
68
+ console.error(e)
69
+ setExportError(
70
+ `${e.toString()}\n\n${e.response?.data?.error?.message}`
71
+ )
72
+ setIsExporting(false)
73
+ return
74
+ }
75
+ await new Promise((resolve) => setTimeout(resolve, 100))
76
+ }
77
+ setIsExporting(false)
78
+ }
79
+
80
+ await pollExportRequest()
81
+
82
+ // open /api/export_files/download?export_file_id=... in new tab
83
+
84
+ const export_file_id =
85
+ export_request.file_summary[0].export_file_id
86
+
87
+ window.open(
88
+ `/api/export_files/download?export_file_id=${export_file_id}`,
89
+ "_blank"
90
+ )
91
+
92
+ setIsExporting(false)
56
93
  } catch (e: any) {
57
94
  console.error(e)
58
95
  setExportError(