@tscircuit/eval 0.0.275 → 0.0.276

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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/eval",
3
3
  "main": "dist/lib/index.js",
4
- "version": "0.0.275",
4
+ "version": "0.0.276",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "build": "bun run build:lib && bun run build:webworker && bun run build:blob-url && bun run build:runner && bun run build:worker-wrapper",
@@ -53,13 +53,13 @@
53
53
  "@biomejs/biome": "^1.8.3",
54
54
  "@playwright/test": "^1.50.1",
55
55
  "@tscircuit/capacity-autorouter": "^0.0.100",
56
- "@tscircuit/core": "^0.0.611",
56
+ "@tscircuit/core": "^0.0.614",
57
57
  "@tscircuit/math-utils": "^0.0.18",
58
58
  "@tscircuit/parts-engine": "^0.0.8",
59
59
  "@types/babel__standalone": "^7.1.9",
60
60
  "@types/bun": "^1.2.16",
61
61
  "@types/react": "^19.1.8",
62
- "circuit-json": "^0.0.224",
62
+ "circuit-json": "^0.0.226",
63
63
  "comlink": "^4.4.2",
64
64
  "graphics-debug": "^0.0.60",
65
65
  "jscad-fiber": "^0.0.82",
@@ -1,374 +0,0 @@
1
- # Example Circuit Transpilation and Execution Implementation
2
-
3
- This is a sample implementation of transpiling and executing tscircuit code from
4
- another project.
5
-
6
- ```tsx
7
- import * as tscircuitCore from "@tscircuit/core"
8
- import { getImportsFromCode } from "lib/utils/get-imports-from-code"
9
- import type { AnyCircuitElement } from "circuit-json"
10
- import * as jscadFiber from "jscad-fiber"
11
- import * as React from "react"
12
- import { useEffect, useMemo, useReducer, useRef, useState } from "react"
13
- import { safeCompileTsx } from "../use-compiled-tsx"
14
- import { useSnippetsBaseApiUrl } from "../use-snippets-base-api-url"
15
- import { constructCircuit } from "./construct-circuit"
16
- import { evalCompiledJs } from "./eval-compiled-js"
17
- import { getSyntaxError } from "@/lib/utils/getSyntaxError"
18
-
19
- type RunTsxResult = {
20
- compiledModule: any
21
- message: string
22
- circuitJson: AnyCircuitElement[] | null
23
- compiledJs?: string
24
- isLoading: boolean
25
- }
26
-
27
- export const useRunTsx = ({
28
- code,
29
- userImports,
30
- type,
31
- isStreaming = false,
32
- }: {
33
- code?: string
34
- userImports?: Record<string, object>
35
- type?: "board" | "footprint" | "package" | "model"
36
- isStreaming?: boolean
37
- } = {}): RunTsxResult & {
38
- circuitJsonKey: string
39
- triggerRunTsx: () => void
40
- tsxRunTriggerCount: number
41
- } => {
42
- type ??= "board"
43
- const [tsxRunTriggerCount, incTsxRunTriggerCount] = useReducer(
44
- (c) => c + 1,
45
- 0
46
- )
47
- const [tsxResult, setTsxResult] = useState<RunTsxResult>({
48
- compiledModule: null,
49
- message: "",
50
- circuitJson: null,
51
- isLoading: false,
52
- })
53
- const apiBaseUrl = useSnippetsBaseApiUrl()
54
- const preSuppliedImportsRef = useRef<Record<string, any>>({})
55
-
56
- useEffect(() => {
57
- if (tsxRunTriggerCount === 0) return
58
- if (isStreaming) {
59
- setTsxResult({
60
- compiledModule: null,
61
- message: "",
62
- circuitJson: null,
63
- isLoading: false,
64
- })
65
- }
66
- if (!code) return
67
- const syntaxError = getSyntaxError(code)
68
- if (syntaxError) {
69
- setTsxResult({
70
- compiledModule: null,
71
- message: syntaxError,
72
- circuitJson: null,
73
- isLoading: false,
74
- })
75
- return
76
- }
77
- async function run() {
78
- setTsxResult({
79
- compiledModule: null,
80
- message: "",
81
- circuitJson: null,
82
- isLoading: true,
83
- })
84
-
85
- const userCodeTsciImports = getImportsFromCode(code!).filter((imp) =>
86
- imp.startsWith("@tsci/")
87
- )
88
-
89
- const preSuppliedImports: Record<string, any> =
90
- preSuppliedImportsRef.current
91
-
92
- for (const [importName, importValue] of Object.entries(
93
- userImports ?? {}
94
- )) {
95
- preSuppliedImports[importName] = importValue
96
- }
97
-
98
- const __tscircuit_require = (name: string) => {
99
- if (!preSuppliedImports[name]) {
100
- throw new Error(
101
- `Import "${name}" not found (imports available: ${Object.keys(
102
- preSuppliedImports
103
- ).join(",")})`
104
- )
105
- }
106
- return preSuppliedImports[name]
107
- }
108
- ;(globalThis as any).__tscircuit_require = __tscircuit_require
109
- preSuppliedImports["@tscircuit/core"] = tscircuitCore
110
- preSuppliedImports["react"] = React
111
- preSuppliedImports["jscad-fiber"] = jscadFiber
112
- globalThis.React = React
113
-
114
- async function addImport(importName: string, depth = 0) {
115
- if (!importName.startsWith("@tsci/")) return
116
- if (preSuppliedImports[importName]) return
117
- if (depth > 5) {
118
- console.log("Max depth for imports reached")
119
- return
120
- }
121
-
122
- const fullSnippetName = importName
123
- .replace("@tsci/", "")
124
- .replace(".", "/")
125
- const { snippet: importedSnippet, error } = await fetch(
126
- `${apiBaseUrl}/snippets/get?name=${fullSnippetName}`
127
- )
128
- .then((res) => res.json())
129
- .catch((e) => ({ error: e }))
130
-
131
- if (error) {
132
- console.error("Error fetching import", importName, error)
133
- return
134
- }
135
-
136
- const { compiled_js, code } = importedSnippet
137
-
138
- const importNames = getImportsFromCode(code!)
139
-
140
- for (const importName of importNames) {
141
- if (!preSuppliedImports[importName]) {
142
- await addImport(importName, depth + 1)
143
- }
144
- }
145
-
146
- try {
147
- preSuppliedImports[importName] = evalCompiledJs(compiled_js).exports
148
- } catch (e) {
149
- console.error("Error importing snippet", e)
150
- }
151
- }
152
-
153
- for (const userCodeTsciImport of userCodeTsciImports) {
154
- await addImport(userCodeTsciImport)
155
- }
156
-
157
- const { success, compiledTsx: compiledJs, error } = safeCompileTsx(code!)
158
-
159
- if (!success) {
160
- setTsxResult({
161
- compiledModule: null,
162
- message: `Compile Error: ${error.message}`,
163
- circuitJson: null,
164
- isLoading: false,
165
- })
166
- }
167
-
168
- try {
169
- const module = evalCompiledJs(compiledJs!)
170
-
171
- const componentExportKeys = Object.keys(module.exports).filter(
172
- (key) => !key.startsWith("use")
173
- )
174
-
175
- if (componentExportKeys.length > 1) {
176
- throw new Error(
177
- `Too many exports, only export one component. You exported: ${JSON.stringify(
178
- Object.keys(module.exports)
179
- )}`
180
- )
181
- }
182
-
183
- const primaryKey = componentExportKeys[0]
184
-
185
- const UserElm = (props: any) =>
186
- React.createElement(module.exports[primaryKey], props)
187
-
188
- try {
189
- const circuit = constructCircuit(UserElm, type as any)
190
- const renderPromise = circuit.renderUntilSettled()
191
-
192
- // wait one tick to allow a single render pass
193
- await new Promise((resolve) => setTimeout(resolve, 1))
194
-
195
- let circuitJson = circuit.getCircuitJson()
196
- setTsxResult({
197
- compiledModule: module,
198
- compiledJs,
199
- message: "",
200
- circuitJson: circuitJson as AnyCircuitElement[],
201
- isLoading: true,
202
- })
203
-
204
- await renderPromise
205
-
206
- circuitJson = circuit.getCircuitJson()
207
- setTsxResult({
208
- compiledModule: module,
209
- compiledJs,
210
- message: "",
211
- circuitJson: circuitJson as AnyCircuitElement[],
212
- isLoading: false,
213
- })
214
- } catch (error: any) {
215
- console.error("Evaluation error:", error)
216
- setTsxResult({
217
- compiledModule: module,
218
- message: `Render Error: ${error.message}`,
219
- circuitJson: null,
220
- isLoading: false,
221
- })
222
- }
223
- } catch (error: any) {
224
- console.error("Evaluation error:", error)
225
- setTsxResult({
226
- compiledModule: null,
227
- message: `Eval Error: ${error.message}\n\n${error.stack}`,
228
- circuitJson: null,
229
- isLoading: false,
230
- })
231
- }
232
- }
233
- run()
234
- }, [tsxRunTriggerCount])
235
-
236
- const circuitJsonKey: string = useMemo(() => {
237
- if (!tsxResult.circuitJson) return ""
238
- return `cj-${Math.random().toString(36).substring(2, 15)}`
239
- }, [tsxResult.circuitJson, tsxResult.circuitJson?.length])
240
-
241
- return {
242
- ...tsxResult,
243
- circuitJsonKey: circuitJsonKey,
244
- triggerRunTsx: incTsxRunTriggerCount,
245
- tsxRunTriggerCount,
246
- }
247
- }
248
- ```
249
-
250
- ```tsx
251
- export const evalCompiledJs = (compiledCode: string) => {
252
- const functionBody = `
253
- var exports = {};
254
- var require = globalThis.__tscircuit_require;
255
- var module = { exports };
256
- ${compiledCode};
257
- return module;`.trim()
258
- return Function(functionBody).call(globalThis)
259
- }
260
- ```
261
-
262
- ```tsx
263
- import { Circuit } from "@tscircuit/core"
264
- import { useEffect, useMemo, useState } from "react"
265
- import * as React from "react"
266
- import { useCompiledTsx } from "../use-compiled-tsx"
267
- import { createJSCADRenderer } from "jscad-fiber"
268
- import { jscadPlanner } from "jscad-planner"
269
- import { jlcPartsEngine } from "@/lib/jlc-parts-engine"
270
-
271
- export const constructCircuit = (
272
- UserElm: any,
273
- type: "board" | "footprint" | "package" | "model"
274
- ) => {
275
- const circuit = new Circuit()
276
-
277
- if (type === "board") {
278
- circuit.add(<UserElm />)
279
- // HACK: switch to selectOne when root fixes bug with selecting board
280
- const board = circuit.root?.children[0]
281
- // const board = circuit.selectOne("board")
282
- if (board) {
283
- board.setProps({
284
- ...board.props,
285
- partsEngine: jlcPartsEngine,
286
- })
287
- }
288
- } else if (type === "package") {
289
- circuit.add(
290
- <board width="50mm" height="50mm">
291
- <UserElm name="U1" />
292
- </board>
293
- )
294
- } else if (type === "footprint") {
295
- circuit.add(
296
- <board width="10mm" height="10mm">
297
- <chip name="U1" footprint={<UserElm />} />
298
- </board>
299
- )
300
- } else if (type === "model") {
301
- const jscadGeoms: any[] = []
302
- const { createJSCADRoot } = createJSCADRenderer(jscadPlanner as any)
303
- const jscadRoot = createJSCADRoot(jscadGeoms)
304
- jscadRoot.render(<UserElm />)
305
- circuit.add(
306
- <board width="10mm" height="10mm">
307
- <chip
308
- name="U1"
309
- cadModel={{
310
- jscad: jscadGeoms[0],
311
- }}
312
- />
313
- </board>
314
- )
315
- }
316
- return circuit
317
- }
318
- ```
319
-
320
- ```tsx
321
- import * as Babel from "@babel/standalone"
322
-
323
- export function getSyntaxError(code: string): string | null {
324
- try {
325
- Babel.transform(code, {
326
- filename: "index.tsx",
327
- presets: ["react", "typescript"],
328
- })
329
- return null
330
- } catch (error: unknown) {
331
- return (error as Error).message
332
- }
333
- }
334
- ```
335
-
336
- ```tsx
337
- import { useMemo } from "react"
338
- import * as Babel from "@babel/standalone"
339
-
340
- export const safeCompileTsx = (
341
- code: string
342
- ):
343
- | { success: true; compiledTsx: string; error?: undefined }
344
- | { success: false; error: Error; compiledTsx?: undefined } => {
345
- try {
346
- return {
347
- success: true,
348
- compiledTsx:
349
- Babel.transform(code, {
350
- presets: ["react", "typescript"],
351
- plugins: ["transform-modules-commonjs"],
352
- filename: "virtual.tsx",
353
- }).code || "",
354
- }
355
- } catch (error: any) {
356
- return { success: false, error }
357
- }
358
- }
359
-
360
- export const useCompiledTsx = (
361
- code?: string,
362
- { isStreaming = false }: { isStreaming?: boolean } = {}
363
- ) => {
364
- return useMemo(() => {
365
- if (!code) return ""
366
- if (isStreaming) return ""
367
- const result = safeCompileTsx(code)
368
- if (result.success) {
369
- return result.compiledTsx
370
- }
371
- return `Error: ${result.error.message}`
372
- }, [code, isStreaming])
373
- }
374
- ```