Skip to content

Commit

Permalink
Merge branch 'tscircuit:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Abse2001 authored Oct 10, 2024
2 parents 06734ee + dee5baf commit 64f4398
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 59 deletions.
14 changes: 14 additions & 0 deletions fake-snippets-api/lib/db/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,21 @@ declare module "@tsci/seveibar.a555timer" {
}) => any;
}
`.trim(),
compiled_js: `
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.A555Timer = void 0;
const A555Timer = ({
name
}) => /*#__PURE__*/React.createElement("chip", {
name: name,
footprint: "dip8"
});
exports.A555Timer = A555Timer;
`.trim(),
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
snippet_type: "package",
Expand Down
6 changes: 5 additions & 1 deletion src/components/CodeAndPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ export function CodeAndPreview({ snippet }: Props) {
}, [snippet?.code])
const { toast } = useToast()

const { message, circuitJson } = useRunTsx(code, snippet?.snippet_type)
const { message, circuitJson, compiledJs } = useRunTsx(
code,
snippet?.snippet_type,
)
const qc = useQueryClient()

const updateSnippetMutation = useMutation({
Expand All @@ -51,6 +54,7 @@ export function CodeAndPreview({ snippet }: Props) {
snippet_id: snippet.snippet_id,
code: code,
dts: dts,
compiled_js: compiledJs,
})
if (response.status !== 200) {
throw new Error("Failed to save snippet")
Expand Down
46 changes: 46 additions & 0 deletions src/hooks/use-run-tsx/construct-circuit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Circuit } from "@tscircuit/core"
import { useEffect, useMemo, useState } from "react"
import * as React from "react"
import { useCompiledTsx } from "../use-compiled-tsx"
import { createJSCADRenderer } from "jscad-fiber"
import { jscadPlanner } from "jscad-planner"
import { getImportsFromCode } from "@tscircuit/prompt-benchmarks/code-runner-utils"

export const constructCircuit = (
UserElm: any,
type: "board" | "footprint" | "package" | "model",
) => {
const circuit = new Circuit()

if (type === "board") {
circuit.add(<UserElm />)
} else if (type === "package") {
circuit.add(
<board width="10mm" height="10mm">
<UserElm name="U1" />
</board>,
)
} else if (type === "footprint") {
circuit.add(
<board width="10mm" height="10mm">
<chip name="U1" footprint={<UserElm />} />
</board>,
)
} else if (type === "model") {
const jscadGeoms: any[] = []
const { createJSCADRoot } = createJSCADRenderer(jscadPlanner as any)
const jscadRoot = createJSCADRoot(jscadGeoms)
jscadRoot.render(<UserElm />)
circuit.add(
<board width="10mm" height="10mm">
<chip
name="U1"
cadModel={{
jscad: jscadGeoms[0],
}}
/>
</board>,
)
}
return circuit
}
9 changes: 9 additions & 0 deletions src/hooks/use-run-tsx/eval-compiled-js.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export const evalCompiledJs = (compiledCode: string) => {
const functionBody = `
var exports = {};
var require = globalThis.__tscircuit_require;
var module = { exports };
${compiledCode};
return module;`.trim()
return Function(functionBody).call(globalThis)
}
85 changes: 28 additions & 57 deletions src/hooks/use-run-tsx.tsx → src/hooks/use-run-tsx/index.tsx
Original file line number Diff line number Diff line change
@@ -1,84 +1,40 @@
import { useEffect, useMemo, useState } from "react"
import * as React from "react"
import { useCompiledTsx } from "./use-compiled-tsx"
import { useCompiledTsx } from "../use-compiled-tsx"
import { Circuit } from "@tscircuit/core"
import { createJSCADRenderer } from "jscad-fiber"
import { jscadPlanner } from "jscad-planner"
import { getImportsFromCode } from "@tscircuit/prompt-benchmarks/code-runner-utils"
import { evalCompiledJs } from "./eval-compiled-js"
import { constructCircuit } from "./construct-circuit"
import { useSnippetsBaseApiUrl } from "../use-snippets-base-api-url"

type RunTsxResult = {
compiledModule: any
message: string
circuitJson: any
compiledJs?: string
isLoading: boolean
}

const constructCircuit = (
UserElm: any,
type: "board" | "footprint" | "package" | "model",
) => {
const circuit = new Circuit()

if (type === "board") {
circuit.add(<UserElm />)
} else if (type === "package") {
circuit.add(
<board width="10mm" height="10mm">
<UserElm name="U1" />
</board>,
)
} else if (type === "footprint") {
circuit.add(
<board width="10mm" height="10mm">
<chip name="U1" footprint={<UserElm />} />
</board>,
)
} else if (type === "model") {
const jscadGeoms: any[] = []
const { createJSCADRoot } = createJSCADRenderer(jscadPlanner as any)
const jscadRoot = createJSCADRoot(jscadGeoms)
jscadRoot.render(<UserElm />)
circuit.add(
<board width="10mm" height="10mm">
<chip
name="U1"
cadModel={{
jscad: jscadGeoms[0],
}}
/>
</board>,
)
}
return circuit
}

const evalCompiledJs = (compiledCode: string) => {
const functionBody = `
var exports = {};
var require = globalThis.__tscircuit_require;
var module = { exports };
${compiledCode};
return module;`.trim()
return Function(functionBody).call(globalThis)
}

export const useRunTsx = (
code?: string,
type?: "board" | "footprint" | "package" | "model",
{ isStreaming = false }: { isStreaming?: boolean } = {},
): RunTsxResult => {
type ??= "board"
const compiledCode = useCompiledTsx(code, { isStreaming })
const compiledJs = useCompiledTsx(code, { isStreaming })
const [tsxResult, setTsxResult] = useState<RunTsxResult>({
compiledModule: null,
message: "",
circuitJson: null,
isLoading: false,
})
const apiBaseUrl = useSnippetsBaseApiUrl()

useEffect(() => {
async function run() {
if (isStreaming || !compiledCode || !code) {
if (isStreaming || !compiledJs || !code) {
setTsxResult({
compiledModule: null,
message: "",
Expand All @@ -95,9 +51,24 @@ export const useRunTsx = (
const preSuppliedImports: Record<string, any> = {}

for (const importName of imports) {
const fullSnippetName = importName
.replace("@tsci/", "")
.replace(".", "/")
console.log({ importName, fullSnippetName })
// Fetch compiled code from the server
// await fetch("https://registry-api.tscircuit.com/
// preSuppliedImports[importName] =
const { snippet: importedSnippet } = await fetch(
`${apiBaseUrl}/snippets/get?name=${fullSnippetName}`,
).then((res) => res.json())

try {
console.log("importedSnippet", importedSnippet)
// eval the imported snippet compiled_js
preSuppliedImports[importName] = evalCompiledJs(
importedSnippet.compiled_js,
)
} catch (e) {
console.error("Error importing snippet", e)
}
}

const __tscircuit_require = (name: string) => {
Expand All @@ -107,12 +78,11 @@ export const useRunTsx = (
return preSuppliedImports[name]
}
;(globalThis as any).__tscircuit_require = __tscircuit_require
// Add these imports to the require fn

try {
globalThis.React = React

const module = evalCompiledJs(compiledCode)
const module = evalCompiledJs(compiledJs)

if (Object.keys(module.exports).length > 1) {
throw new Error(
Expand All @@ -132,6 +102,7 @@ export const useRunTsx = (

setTsxResult({
compiledModule: module,
compiledJs,
message: "",
circuitJson,
isLoading: false,
Expand All @@ -156,7 +127,7 @@ export const useRunTsx = (
}
}
run()
}, [compiledCode, isStreaming])
}, [compiledJs, isStreaming])

return tsxResult
}
3 changes: 2 additions & 1 deletion src/pages/quickstart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { TypeBadge } from "@/components/TypeBadge"
import { JLCPCBImportDialog } from "@/components/JLCPCBImportDialog"
import { useNotImplementedToast } from "@/hooks/use-toast"
import { useGlobalStore } from "@/hooks/use-global-store"

export const QuickstartPage = () => {
const axios = useAxios()
const [isJLCPCBDialogOpen, setIsJLCPCBDialogOpen] = useState(false)
const toastNotImplemented = useNotImplementedToast()
const currentUser = useGlobalStore((s) => s.session?.github_username)
const { data: mySnippets, isLoading } = useQuery<Snippet[]>(
"userSnippets",
async () => {
const currentUser = "seveibar"
const response = await axios.get(
`/snippets/list?owner_name=${currentUser}`,
)
Expand Down

0 comments on commit 64f4398

Please sign in to comment.