Skip to content

Commit

Permalink
Add core to runtime, add format button, 404 snippet page, minor fixes (
Browse files Browse the repository at this point in the history
…#53)

* add core to runtime

* format button
  • Loading branch information
seveibar authored Oct 12, 2024
1 parent ea87e9f commit 5372616
Show file tree
Hide file tree
Showing 13 changed files with 123 additions and 24 deletions.
Binary file modified bun.lockb
Binary file not shown.
2 changes: 0 additions & 2 deletions fake-snippets-api/routes/api/snippets/download.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ export default withRouteSpec({
})(async (req, ctx) => {
const { jsdelivr_path, jsdelivr_resolve } = req.query

console.log({ jsdelivr_path, jsdelivr_resolve })

// Parse the file path
const [owner, packageWithVersion, ...rest] = jsdelivr_path.split("/")
const [packageName, version] = packageWithVersion.split("@")
Expand Down
10 changes: 7 additions & 3 deletions fake-snippets-api/routes/api/snippets/generate_from_jlcpcb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@ export default withRouteSpec({

try {
// Fetch the EasyEDA component data
const rawEasyJson = await fetchEasyEDAComponent(jlcpcb_part_number)
const rawEasyJson = await fetchEasyEDAComponent(jlcpcb_part_number).catch(
(e) => `Error in fetchEasyEDAComponent: ${e.toString()}`,
)

// Convert to TypeScript React component
const tsxComponent = await convertRawEasyEdaToTs(rawEasyJson)
const tsxComponent = await convertRawEasyEdaToTs(rawEasyJson).catch(
(e) => `Error in convertRawEasyEdaToTs ${e.toString()}`,
)

// Create a new snippet
const newSnippet = {
Expand All @@ -43,7 +47,7 @@ export default withRouteSpec({
} catch (error: any) {
return ctx.error(500, {
error_code: "jlcpcb_generation_failed",
message: `Failed to generate snippet from JLCPCB part: ${error.message}`,
message: `Failed to generate snippet from JLCPCB part: ${error.message}\n\n${error.stack}`,
})
}
})
14 changes: 7 additions & 7 deletions fake-snippets-api/routes/api/snippets/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ export default withRouteSpec({
})(async (req, ctx) => {
const { snippet_id, name, owner_name, unscoped_name } = req.commonParams

const foundSnippet = ctx.db.snippets.find(
(s) =>
(snippet_id && s.snippet_id === snippet_id) ||
(name && s.name === name) ||
(owner_name && s.owner_name === owner_name) ||
(unscoped_name && s.unscoped_name === unscoped_name),
)
const foundSnippet = ctx.db.snippets.find((s) => {
if (snippet_id && s.snippet_id !== snippet_id) return false
if (name && s.name !== name) return false
if (owner_name && s.owner_name !== owner_name) return false
if (unscoped_name && s.unscoped_name !== unscoped_name) return false
return true
})

if (!foundSnippet) {
return ctx.error(404, {
Expand Down
2 changes: 2 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
<script async src="https://unpkg.com/[email protected]/standalone.js"></script>
<script async src="https://unpkg.com/[email protected]/parser-typescript.js"></script>
</body>
</html>
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
"cmdk": "1.0.0",
"codemirror": "^6.0.1",
"date-fns": "^4.1.0",
"easyeda": "^0.0.32",
"easyeda": "^0.0.43",
"embla-carousel-react": "^8.3.0",
"fflate": "^0.8.2",
"file-saver": "^2.0.5",
Expand All @@ -91,7 +91,7 @@
"@anthropic-ai/sdk": "^0.27.3",
"@babel/standalone": "^7.25.6",
"@biomejs/biome": "^1.9.2",
"@tscircuit/core": "^0.0.109",
"@tscircuit/core": "^0.0.111",
"@tscircuit/prompt-benchmarks": "^0.0.14",
"@types/babel__standalone": "^7.1.7",
"@types/bun": "^1.1.10",
Expand Down
32 changes: 31 additions & 1 deletion src/components/CodeAndPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { PreviewContent } from "./PreviewContent"
import { useGlobalStore } from "@/hooks/use-global-store"
import { useUrlParams } from "@/hooks/use-url-params"
import { getSnippetTemplate } from "@/lib/get-snippet-template"
import "src/prettier"

interface Props {
snippet?: Snippet | null
Expand Down Expand Up @@ -127,10 +128,39 @@ export function CodeAndPreview({ snippet }: Props) {
<div className={`flex ${showPreview ? "flex-col md:flex-row" : ""}`}>
<div
className={cn(
"hidden md:flex p-2 border-r border-gray-200 bg-gray-50",
"hidden flex-col md:flex border-r border-gray-200 bg-gray-50",
showPreview ? "w-full md:w-1/2" : "w-full flex",
)}
>
<div className="flex items-center px-2 py-1 border-b border-gray-200">
<div className="font-mono text-xs">index.tsx</div>
<div className="flex-grow" />
<Button
size="sm"
variant="ghost"
onClick={() => {
if (window.prettier && window.prettierPlugins) {
try {
const formattedCode = window.prettier.format(code, {
semi: false,
parser: "typescript",
plugins: window.prettierPlugins,
})
setCode(formattedCode)
} catch (error) {
toast({
title: "Formatting error",
description:
"Failed to format the code. Please check for syntax errors.",
variant: "destructive",
})
}
}
}}
>
Format
</Button>
</div>
<CodeEditor
code={code}
onCodeChange={(newCode) => setCode(newCode)}
Expand Down
13 changes: 12 additions & 1 deletion src/components/CodeEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export const CodeEditor = ({
const ata = setupTypeAcquisition(ataConfig)
ata(`
import React from "@types/react/jsx-runtime"
import { Circuit } from "@tscircuit/core"
import { Circuit, createUseComponent } from "@tscircuit/core"
import type { CommonLayoutProps } from "@tscircuit/props"
${code}
`)
Expand Down Expand Up @@ -137,6 +137,17 @@ ${code}
}
}, [code !== "", !isStreaming])

useEffect(() => {
if (viewRef.current) {
const state = viewRef.current.state
if (state.doc.toString() !== code) {
viewRef.current.dispatch({
changes: { from: 0, to: state.doc.length, insert: code },
})
}
}
}, [code])

if (isStreaming) {
return <div className="font-mono whitespace-pre-wrap text-xs">{code}</div>
}
Expand Down
40 changes: 36 additions & 4 deletions src/components/JLCPCBImportDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { useAxios } from "@/hooks/use-axios"
import { useToast } from "@/hooks/use-toast"
import { useLocation } from "wouter"
import { Link, useLocation } from "wouter"
import { useGlobalStore } from "@/hooks/use-global-store"

interface JLCPCBImportDialogProps {
open: boolean
Expand All @@ -27,6 +28,8 @@ export function JLCPCBImportDialog({
const axios = useAxios()
const { toast } = useToast()
const [, navigate] = useLocation()
const isLoggedIn = useGlobalStore((s) => Boolean(s.session))
const session = useGlobalStore((s) => s.session)

const handleImport = async () => {
if (!partNumber.startsWith("C")) {
Expand All @@ -41,6 +44,31 @@ export function JLCPCBImportDialog({
setIsLoading(true)
setError(null)
try {
// Check that module doesn't already exist
const existingSnippetRes = await axios.get(
`/snippets/get?owner_name=${session?.github_username}&unscoped_name=${partNumber}`,
{
validateStatus: (status) => true,
},
)

if (existingSnippetRes.status !== 404) {
toast({
title: "JLCPCB Part Already Imported",
description: (
<div>
<Link
className="text-blue-500 hover:underline"
href={`/editor?snippet_id=${existingSnippetRes.data.snippet.snippet_id}`}
>
View {partNumber}
</Link>
</div>
),
})
return
}

const response = await axios
.post("/snippets/generate_from_jlcpcb", {
jlcpcb_part_number: partNumber,
Expand Down Expand Up @@ -98,7 +126,7 @@ export function JLCPCBImportDialog({
variant="default"
onClick={() => {
const issueTitle = `[${partNumber}] Failed to import from JLCPCB`
const issueBody = `I tried to import the part number ${partNumber} from JLCPCB, but it failed. Here's the error I got:\n\`\`\`\n${error}\n\`\`\``
const issueBody = `I tried to import the part number ${partNumber} from JLCPCB, but it failed. Here's the error I got:\n\`\`\`\n${error}\n\`\`\`\n\nCould be an issue in \`fetchEasyEDAComponent\` or \`convertRawEasyEdaToTs\``
const issueLabels = "snippets,good first issue"
const url = `https://github.com/tscircuit/easyeda-converter/issues/new?title=${encodeURIComponent(issueTitle)}&body=${encodeURIComponent(issueBody)}&labels=${encodeURIComponent(issueLabels)}`

Expand All @@ -112,8 +140,12 @@ export function JLCPCBImportDialog({
)}
</div>
<DialogFooter>
<Button onClick={handleImport} disabled={isLoading}>
{isLoading ? "Importing..." : "Import"}
<Button onClick={handleImport} disabled={isLoading || !isLoggedIn}>
{!isLoggedIn
? "Must be logged in for jlcpcb import"
: isLoading
? "Importing..."
: "Import"}
</Button>
</DialogFooter>
</DialogContent>
Expand Down
4 changes: 3 additions & 1 deletion src/hooks/use-run-tsx/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, useMemo, useReducer, useState } from "react"
import * as React from "react"
import { safeCompileTsx, useCompiledTsx } from "../use-compiled-tsx"
import { Circuit } from "@tscircuit/core"
import * as tscircuitCore from "@tscircuit/core"
import { createJSCADRenderer } from "jscad-fiber"
import { jscadPlanner } from "jscad-planner"
import { getImportsFromCode } from "@tscircuit/prompt-benchmarks/code-runner-utils"
Expand Down Expand Up @@ -89,6 +89,8 @@ export const useRunTsx = ({
}
}

preSuppliedImports["@tscircuit/core"] = tscircuitCore

const __tscircuit_require = (name: string) => {
if (!preSuppliedImports[name]) {
throw new Error(
Expand Down
3 changes: 2 additions & 1 deletion src/hooks/use-snippet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { Snippet } from "fake-snippets-api/lib/db/schema"

export const useSnippet = (snippetId: string | null) => {
const axios = useAxios()
return useQuery<Snippet, Error>(
return useQuery<Snippet, Error & { status: number }>(
["snippets", snippetId],
async () => {
if (!snippetId) {
Expand All @@ -17,6 +17,7 @@ export const useSnippet = (snippetId: string | null) => {
},
{
enabled: Boolean(snippetId),
retry: false,
},
)
}
14 changes: 12 additions & 2 deletions src/pages/editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,22 @@ import { useSnippet } from "@/hooks/use-snippet"

export const EditorPage = () => {
const snippetId = useCurrentSnippetId()
const { data: snippet, isLoading } = useSnippet(snippetId)
const { data: snippet, isLoading, error } = useSnippet(snippetId)

return (
<div>
<Header />
<CodeAndPreview snippet={snippet} />
{!error && <CodeAndPreview snippet={snippet} />}
{error && error.status === 404 && (
<div className="w-full h-[calc(100vh-20rem)] text-xl text-center flex justify-center items-center">
Snippet not found
</div>
)}
{error && error.status !== 404 && (
<div className="flex flex-col">
Something strange happened<div>{error.message}</div>
</div>
)}
<Footer />
</div>
)
Expand Down
9 changes: 9 additions & 0 deletions src/prettier.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Prettier is injected into the global scope inside index.html
declare global {
interface Window {
prettier: {
format: (code: string, options: any) => string
}
prettierPlugins: any
}
}

0 comments on commit 5372616

Please sign in to comment.