@tscircuit/cli 0.0.39 → 0.0.41

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 (33) hide show
  1. package/bun.lockb +0 -0
  2. package/dev-server-api/routes/api/dev_package_examples/create.ts +3 -0
  3. package/dev-server-api/routes/api/dev_package_examples/get.ts +2 -0
  4. package/dev-server-api/routes/api/dev_package_examples/list.ts +13 -9
  5. package/dev-server-api/routes/api/dev_server/reset.ts +15 -0
  6. package/dev-server-api/src/db/create-schema.ts +1 -0
  7. package/dev-server-api/src/db/get-db.ts +5 -2
  8. package/dev-server-api/src/middlewares/with-error-response.ts +15 -2
  9. package/dev-server-frontend/bun.lockb +0 -0
  10. package/dev-server-frontend/package.json +5 -4
  11. package/dev-server-frontend/src/ExampleContentView.tsx +29 -1
  12. package/dev-server-frontend/src/components/command-k.tsx +29 -5
  13. package/dist/cli.js +243 -154
  14. package/lib/cmd-fns/config-set-runtime.ts +7 -0
  15. package/lib/cmd-fns/dev/index.ts +9 -6
  16. package/lib/cmd-fns/dev/mark-all-examples-loading.ts +18 -0
  17. package/lib/cmd-fns/dev/soupify-and-upload-example-file.ts +29 -14
  18. package/lib/cmd-fns/dev/start-watcher.ts +11 -8
  19. package/lib/cmd-fns/dev/upload-examples-from-directory.ts +23 -12
  20. package/lib/cmd-fns/dev-server-upload.ts +2 -2
  21. package/lib/cmd-fns/index.ts +1 -0
  22. package/lib/cmd-fns/package-examples-create.ts +7 -4
  23. package/lib/cmd-fns/publish/index.ts +7 -4
  24. package/lib/cmd-fns/soupify.ts +7 -4
  25. package/lib/create-config-manager.ts +1 -0
  26. package/lib/get-program.ts +7 -0
  27. package/lib/param-handlers/index.ts +2 -0
  28. package/lib/param-handlers/interact-for-runtime.ts +33 -0
  29. package/lib/soupify.ts +13 -8
  30. package/lib/util/app-context.ts +1 -0
  31. package/lib/util/create-context-and-run-program.ts +1 -0
  32. package/package.json +9 -6
  33. package/dev-server-api/index.ts +0 -1
package/bun.lockb CHANGED
Binary file
@@ -9,6 +9,7 @@ export default withEdgeSpec({
9
9
  export_name: z.string().default("default"),
10
10
  tscircuit_soup: z.any(),
11
11
  error: z.string().nullable().optional().default(null),
12
+ is_loading: z.boolean().optional(),
12
13
  }),
13
14
  jsonResponse: z.object({
14
15
  dev_package_example: z.object({
@@ -31,6 +32,7 @@ export default withEdgeSpec({
31
32
  export_name: req.jsonBody.export_name,
32
33
  error: req.jsonBody.error,
33
34
  tscircuit_soup,
35
+ is_loading: req.jsonBody.is_loading ? 1 : 0,
34
36
  last_updated_at: new Date().toISOString(),
35
37
  })
36
38
  .onConflict((oc) =>
@@ -38,6 +40,7 @@ export default withEdgeSpec({
38
40
  export_name: req.jsonBody.export_name,
39
41
  error: req.jsonBody.error,
40
42
  tscircuit_soup,
43
+ is_loading: req.jsonBody.is_loading ? 1 : 0,
41
44
  last_updated_at: new Date().toISOString(),
42
45
  })
43
46
  )
@@ -12,6 +12,7 @@ export default withEdgeSpec({
12
12
  dev_package_example_id: z.coerce.number(),
13
13
  file_path: z.string(),
14
14
  tscircuit_soup: z.any(),
15
+ is_loading: z.boolean(),
15
16
  error: z.string().nullable().optional().default(null),
16
17
  last_updated_at: z.string().datetime(),
17
18
  }),
@@ -32,6 +33,7 @@ export default withEdgeSpec({
32
33
  })
33
34
  .then((r) => ({
34
35
  ...r,
36
+ is_loading: r.is_loading === 1,
35
37
  tscircuit_soup: JSON.parse(r.tscircuit_soup),
36
38
  })),
37
39
  })
@@ -1,3 +1,4 @@
1
+ import { sql } from "kysely"
1
2
  import { withEdgeSpec } from "src/with-edge-spec"
2
3
  import { z } from "zod"
3
4
 
@@ -9,21 +10,24 @@ export default withEdgeSpec({
9
10
  dev_package_example_id: z.coerce.number(),
10
11
  file_path: z.string(),
11
12
  export_name: z.string(),
13
+ is_loading: z.coerce.boolean(),
12
14
  last_updated_at: z.string().datetime(),
13
15
  })
14
16
  ),
15
17
  }),
16
18
  auth: "none",
17
19
  })(async (req, ctx) => {
20
+ const dev_package_examples = await ctx.db
21
+ .selectFrom("dev_package_example")
22
+ .select([
23
+ "dev_package_example_id",
24
+ "file_path",
25
+ "export_name",
26
+ "last_updated_at",
27
+ sql`(is_loading = 1)`.$castTo<boolean>().as("is_loading"),
28
+ ])
29
+ .execute()
18
30
  return ctx.json({
19
- dev_package_examples: await ctx.db
20
- .selectFrom("dev_package_example")
21
- .select([
22
- "dev_package_example_id",
23
- "file_path",
24
- "export_name",
25
- "last_updated_at",
26
- ])
27
- .execute(),
31
+ dev_package_examples,
28
32
  })
29
33
  })
@@ -0,0 +1,15 @@
1
+ import { sql } from "kysely"
2
+ import { withEdgeSpec } from "src/with-edge-spec"
3
+ import { z } from "zod"
4
+ import { unlinkSync } from "fs"
5
+ import { getDbFilePath } from "src/db/get-db"
6
+
7
+ export default (req: Request) => {
8
+ unlinkSync(getDbFilePath())
9
+
10
+ return new Response(JSON.stringify({}), {
11
+ headers: {
12
+ "content-type": "application/json",
13
+ },
14
+ })
15
+ }
@@ -10,6 +10,7 @@ export const createSchema = async (db: DbClient) => {
10
10
  .addColumn("export_name", "text")
11
11
  .addColumn("tscircuit_soup", "json")
12
12
  .addColumn("error", "text")
13
+ .addColumn("is_loading", "boolean", (cb) => cb.defaultTo(0).notNull())
13
14
  .addColumn("last_updated_at", "text")
14
15
  .execute()
15
16
  }
@@ -9,6 +9,7 @@ interface DevPackageExample {
9
9
  file_path: string
10
10
  export_name: string
11
11
  error: string | null
12
+ is_loading: 1 | 0
12
13
  last_updated_at: string
13
14
  }
14
15
 
@@ -22,11 +23,13 @@ export type DbClient = Kysely<KyselyDatabaseSchema>
22
23
 
23
24
  let globalDb: Kysely<KyselyDatabaseSchema> | undefined
24
25
 
26
+ export const getDbFilePath = () =>
27
+ process.env.TSCI_DEV_SERVER_DB ?? "./.tscircuit/dev-server.sqlite"
28
+
25
29
  export const getDb = async (): Promise<Kysely<KyselyDatabaseSchema>> => {
26
30
  if (globalDb) return globalDb
27
31
 
28
- const devServerDbPath =
29
- process.env.TSCI_DEV_SERVER_DB ?? "./.tscircuit/dev-server.db"
32
+ const devServerDbPath = getDbFilePath()
30
33
 
31
34
  mkdirSync(Path.dirname(devServerDbPath), { recursive: true })
32
35
 
@@ -1,15 +1,28 @@
1
- import type { Middleware } from "edgespec/middleware"
1
+ import { NotFoundError, type Middleware } from "edgespec/middleware"
2
2
  import kleur from "kleur"
3
3
 
4
4
  export const withErrorResponse: Middleware<{}, {}> = async (req, ctx, next) => {
5
5
  try {
6
6
  return await next(req, ctx)
7
7
  } catch (error: any) {
8
- console.error(kleur.red("Intercepted error:"), error)
9
8
  // If error is a Response, return it
10
9
  if (error instanceof Response) {
11
10
  return error
12
11
  }
12
+ if (error instanceof NotFoundError) {
13
+ return (ctx as any).json(
14
+ {
15
+ ok: false,
16
+ error: {
17
+ message: error?.message,
18
+ error_code: "not_found",
19
+ },
20
+ },
21
+ { status: error?.status || 404 }
22
+ )
23
+ }
24
+
25
+ console.error(kleur.red("Intercepted unhandled error:"), error)
13
26
  return (ctx as any).json(
14
27
  {
15
28
  ok: false,
Binary file
@@ -12,7 +12,8 @@
12
12
  "start": "npm run dev",
13
13
  "build": "tsc && vite build --base /preview && rm -f dist/bundle* && make-vfs --dir dist --outfile ./dist/bundle.ts",
14
14
  "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 10",
15
- "preview": "vite preview"
15
+ "preview": "vite preview",
16
+ "update-deps": "bun add @tscircuit/pcb-viewer@latest @tscircuit/builder@latest @tscircuit/schematic-viewer@latest"
16
17
  },
17
18
  "dependencies": {
18
19
  "@radix-ui/react-alert-dialog": "^1.0.5",
@@ -28,9 +29,9 @@
28
29
  "@radix-ui/react-toggle": "^1.0.3",
29
30
  "@radix-ui/react-toggle-group": "^1.0.4",
30
31
  "@radix-ui/react-tooltip": "^1.0.7",
31
- "@tscircuit/builder": "^1.5.5",
32
- "@tscircuit/pcb-viewer": "^1.2.12",
33
- "@tscircuit/schematic-viewer": "^1.1.7",
32
+ "@tscircuit/builder": "latest",
33
+ "@tscircuit/pcb-viewer": "latest",
34
+ "@tscircuit/schematic-viewer": "latest",
34
35
  "axios": "^1.6.7",
35
36
  "class-variance-authority": "^0.7.0",
36
37
  "clsx": "^2.1.0",
@@ -10,7 +10,12 @@ export const ExampleContentView = () => {
10
10
  (s) => s.active_dev_example_package_id
11
11
  )
12
12
 
13
- const { data: pkg } = useQuery(
13
+ const {
14
+ data: pkg,
15
+ error,
16
+ isError,
17
+ isLoading,
18
+ } = useQuery(
14
19
  ["dev_package_example", devExamplePackageId],
15
20
  async () =>
16
21
  axios
@@ -20,9 +25,12 @@ export const ExampleContentView = () => {
20
25
  .then((r) => r.data.dev_package_example),
21
26
  {
22
27
  refetchIntervalInBackground: true,
28
+ retry: false,
23
29
  }
24
30
  )
25
31
 
32
+ const notFound = (error as any)?.response?.status === 404
33
+
26
34
  const viewMode = useGlobalStore((s) => s.view_mode)
27
35
  const splitMode = useGlobalStore((s) => s.split_mode)
28
36
 
@@ -44,6 +52,26 @@ export const ExampleContentView = () => {
44
52
  viewMode === "split" && splitMode === "vertical" && "grid grid-rows-2"
45
53
  )}
46
54
  >
55
+ {notFound && (
56
+ <div className="absolute top-0 w-full flex justify-center">
57
+ <div className="bg-yellow-50 shadow-lg p-4 m-16 border-yellow-200 border rounded-lg whitespace-pre max-w-[400px]">
58
+ Select an example from the menu above
59
+ </div>
60
+ </div>
61
+ )}
62
+ {isLoading && !isError && (
63
+ <div className="absolute top-0 w-full flex justify-center">
64
+ <div className="bg-gray-50 shadow-lg p-4 m-16 border-gray-200 border rounded-lg whitespace-pre">
65
+ Loading...
66
+ </div>
67
+ </div>
68
+ )}
69
+ {pkg && pkg.is_loading && (
70
+ <div className="absolute top-0 right-0 bg-white p-4 py-2 m-4 rounded-md flex items-center z-10 shadow-lg border border-gray-200">
71
+ <div className="border-2 border-blue-400 border-t-transparent rounded-full w-4 h-4 animate-spin mr-2"></div>
72
+ Rebuilding...
73
+ </div>
74
+ )}
47
75
  {pkg && (viewMode === "schematic" || viewMode === "split") && (
48
76
  <Schematic
49
77
  key={pkg?.last_updated_at}
@@ -9,6 +9,8 @@ import {
9
9
  CommandShortcut,
10
10
  } from "./ui/command"
11
11
  import { useGlobalStore } from "src/hooks/use-global-store"
12
+ import { useDevPackageExamples } from "./select-example-search"
13
+ import { CommandSeparator } from "cmdk"
12
14
 
13
15
  export const CommandK = () => {
14
16
  const [open, setOpen] = useState(false)
@@ -19,23 +21,28 @@ export const CommandK = () => {
19
21
  e.preventDefault()
20
22
  setOpen((open) => !open)
21
23
  }
24
+ if (e.key === "Escape") {
25
+ setOpen(false)
26
+ }
22
27
  }
23
28
 
24
29
  document.addEventListener("keydown", down)
25
30
  return () => document.removeEventListener("keydown", down)
26
31
  }, [])
27
32
 
33
+ const { data: examples } = useDevPackageExamples()
34
+
28
35
  const close = () => {
29
36
  setOpen(false)
30
37
  return true
31
38
  }
32
39
 
33
40
  return (
34
- <CommandDialog open={open}>
41
+ <CommandDialog open={open} onOpenChange={(open) => setOpen(open)}>
35
42
  <Command className="rounded-lg border shadow-md">
36
43
  <CommandInput placeholder="Type a command or search..." />
37
- <CommandGroup>
38
- <CommandList>
44
+ <CommandList>
45
+ <CommandGroup heading="Viewing Options">
39
46
  <CommandItem
40
47
  onSelect={() => close() && store.setViewMode("schematic")}
41
48
  >
@@ -54,8 +61,25 @@ export const CommandK = () => {
54
61
  Vertical Split
55
62
  <CommandShortcut></CommandShortcut>
56
63
  </CommandItem>
57
- </CommandList>
58
- </CommandGroup>
64
+ </CommandGroup>
65
+ <CommandSeparator />
66
+ <CommandGroup heading="Examples">
67
+ {examples?.map((ex) => (
68
+ <CommandItem
69
+ key={ex.dev_package_example_id}
70
+ value={ex.expath}
71
+ onSelect={() =>
72
+ close() &&
73
+ store.setActiveDevExamplePackageId(
74
+ ex.dev_package_example_id.toString()
75
+ )
76
+ }
77
+ >
78
+ {ex.expath}
79
+ </CommandItem>
80
+ ))}
81
+ </CommandGroup>
82
+ </CommandList>
59
83
  </Command>
60
84
  </CommandDialog>
61
85
  )