diff --git a/fake-snippets-api/lib/db/seed.ts b/fake-snippets-api/lib/db/seed.ts index ebb8c97..4db55a8 100644 --- a/fake-snippets-api/lib/db/seed.ts +++ b/fake-snippets-api/lib/db/seed.ts @@ -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", diff --git a/src/components/CodeAndPreview.tsx b/src/components/CodeAndPreview.tsx index b455809..f32f453 100644 --- a/src/components/CodeAndPreview.tsx +++ b/src/components/CodeAndPreview.tsx @@ -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({ @@ -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") diff --git a/src/hooks/use-run-tsx/construct-circuit.tsx b/src/hooks/use-run-tsx/construct-circuit.tsx new file mode 100644 index 0000000..c291465 --- /dev/null +++ b/src/hooks/use-run-tsx/construct-circuit.tsx @@ -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() + } else if (type === "package") { + circuit.add( + + + , + ) + } else if (type === "footprint") { + circuit.add( + + } /> + , + ) + } else if (type === "model") { + const jscadGeoms: any[] = [] + const { createJSCADRoot } = createJSCADRenderer(jscadPlanner as any) + const jscadRoot = createJSCADRoot(jscadGeoms) + jscadRoot.render() + circuit.add( + + + , + ) + } + return circuit +} diff --git a/src/hooks/use-run-tsx/eval-compiled-js.ts b/src/hooks/use-run-tsx/eval-compiled-js.ts new file mode 100644 index 0000000..2d7aba5 --- /dev/null +++ b/src/hooks/use-run-tsx/eval-compiled-js.ts @@ -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) +} diff --git a/src/hooks/use-run-tsx.tsx b/src/hooks/use-run-tsx/index.tsx similarity index 64% rename from src/hooks/use-run-tsx.tsx rename to src/hooks/use-run-tsx/index.tsx index 0b2cfaf..77552e1 100644 --- a/src/hooks/use-run-tsx.tsx +++ b/src/hooks/use-run-tsx/index.tsx @@ -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() - } else if (type === "package") { - circuit.add( - - - , - ) - } else if (type === "footprint") { - circuit.add( - - } /> - , - ) - } else if (type === "model") { - const jscadGeoms: any[] = [] - const { createJSCADRoot } = createJSCADRenderer(jscadPlanner as any) - const jscadRoot = createJSCADRoot(jscadGeoms) - jscadRoot.render() - circuit.add( - - - , - ) - } - 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({ 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: "", @@ -95,9 +51,24 @@ export const useRunTsx = ( const preSuppliedImports: Record = {} 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) => { @@ -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( @@ -132,6 +102,7 @@ export const useRunTsx = ( setTsxResult({ compiledModule: module, + compiledJs, message: "", circuitJson, isLoading: false, @@ -156,7 +127,7 @@ export const useRunTsx = ( } } run() - }, [compiledCode, isStreaming]) + }, [compiledJs, isStreaming]) return tsxResult } diff --git a/src/pages/quickstart.tsx b/src/pages/quickstart.tsx index 4a783f7..f076ad5 100644 --- a/src/pages/quickstart.tsx +++ b/src/pages/quickstart.tsx @@ -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( "userSnippets", async () => { - const currentUser = "seveibar" const response = await axios.get( `/snippets/list?owner_name=${currentUser}`, )