@tscircuit/eval 0.0.319 → 0.0.321

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/lib/index.ts CHANGED
@@ -2,3 +2,4 @@ export * from "./runner"
2
2
  export * from "./worker"
3
3
  export * from "./getPossibleEntrypointComponentPaths"
4
4
  export * from "./getPlatformConfig"
5
+ export * from "./shared/static-asset-extensions"
@@ -1,3 +1,4 @@
1
1
  export * from "./CircuitRunner"
2
2
  export * from "./runTscircuitCode"
3
3
  export * from "./runTscircuitModule"
4
+ export * from "../shared/static-asset-extensions"
@@ -0,0 +1,10 @@
1
+ export const STATIC_ASSET_EXTENSIONS = [
2
+ ".glb",
3
+ ".kicad_mod",
4
+ ".gltf",
5
+ ".obj",
6
+ ".stl",
7
+ ]
8
+
9
+ export const isStaticAssetPath = (path: string) =>
10
+ STATIC_ASSET_EXTENSIONS.some((ext) => path.endsWith(ext))
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.319",
4
+ "version": "0.0.321",
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",
@@ -57,7 +57,7 @@
57
57
  "@tscircuit/checks": "^0.0.75",
58
58
  "@tscircuit/circuit-json-flex": "^0.0.3",
59
59
  "@tscircuit/circuit-json-util": "^0.0.67",
60
- "@tscircuit/core": "^0.0.722",
60
+ "@tscircuit/core": "^0.0.723",
61
61
  "@tscircuit/footprinter": "^0.0.236",
62
62
  "@tscircuit/import-snippet": "^0.0.4",
63
63
  "@tscircuit/infgrid-ijump-astar": "^0.0.33",
@@ -67,7 +67,7 @@
67
67
  "@tscircuit/math-utils": "^0.0.21",
68
68
  "@tscircuit/miniflex": "^0.0.4",
69
69
  "@tscircuit/parts-engine": "^0.0.8",
70
- "@tscircuit/props": "0.0.319",
70
+ "@tscircuit/props": "0.0.320",
71
71
  "@tscircuit/schematic-autolayout": "^0.0.6",
72
72
  "@tscircuit/schematic-match-adapt": "^0.0.16",
73
73
  "@tscircuit/schematic-trace-solver": "^0.0.36",
@@ -82,7 +82,7 @@
82
82
  "bun-match-svg": "0.0.12",
83
83
  "calculate-elbow": "^0.0.12",
84
84
  "chokidar-cli": "^3.0.0",
85
- "circuit-json": "^0.0.251",
85
+ "circuit-json": "^0.0.252",
86
86
  "circuit-json-to-bpc": "^0.0.13",
87
87
  "circuit-json-to-connectivity-map": "^0.0.22",
88
88
  "circuit-json-to-simple-3d": "^0.0.8",
@@ -0,0 +1,50 @@
1
+ import { expect, test } from "bun:test"
2
+ import { createCircuitWebWorker } from "lib"
3
+ import { repoFileUrl } from "tests/fixtures/resourcePaths"
4
+
5
+ test("should import .glb file as string URL when projectBaseUrl is configured", async () => {
6
+ const circuitWebWorker = createCircuitWebWorker({
7
+ webWorkerUrl: repoFileUrl("dist/webworker/entrypoint.js").href,
8
+ platform: {
9
+ projectBaseUrl: "https://example.com/assets",
10
+ },
11
+ })
12
+
13
+ const worker = await circuitWebWorker
14
+
15
+ await worker.executeWithFsMap({
16
+ fsMap: {
17
+ "index.tsx": `
18
+ import glbUrl from "./model.glb";
19
+ import kicadMod from "./footprint.kicad_mod";
20
+
21
+ export default () => {
22
+ return (
23
+ <board width="10mm" height="10mm">
24
+ <resistor resistance="1k" footprint="0402" name="R1" cadModel={{
25
+ glbUrl
26
+ }} />
27
+ </board>
28
+ );
29
+ };
30
+ `,
31
+ "model.glb": "__STATIC_ASSET__",
32
+ "footprint.kicad_mod": "__STATIC_ASSET__",
33
+ },
34
+ mainComponentPath: "index.tsx",
35
+ })
36
+
37
+ await worker.renderUntilSettled()
38
+
39
+ // Verify the circuit rendered successfully (imports worked)
40
+ const circuitJson = await worker.getCircuitJson()
41
+ expect(circuitJson).toBeDefined()
42
+
43
+ const cadComponent = circuitJson.find((e) => e.type === "cad_component")!
44
+
45
+ expect(cadComponent.model_glb_url).toBe(
46
+ "https://example.com/assets/model.glb",
47
+ )
48
+
49
+ await worker.kill()
50
+ })
@@ -9,6 +9,7 @@ import { evalCompiledJs } from "./eval-compiled-js"
9
9
  import type { ExecutionContext } from "./execution-context"
10
10
  import { importEvalPath } from "./import-eval-path"
11
11
  import Debug from "debug"
12
+ import { isStaticAssetPath } from "lib/shared/static-asset-extensions"
12
13
 
13
14
  const debug = Debug("tsci:eval:import-local-file")
14
15
 
@@ -37,75 +38,13 @@ export const importLocalFile = async (
37
38
  __esModule: true,
38
39
  default: jsonData,
39
40
  }
40
- } else if (fsPath.endsWith(".obj")) {
41
- const objBlob = new Blob([fileContent], { type: "model/obj" })
42
- const objUrl = URL.createObjectURL(objBlob)
41
+ } else if (isStaticAssetPath(fsPath)) {
42
+ const platformConfig = ctx.circuit.platform
43
+ // Use projectBaseUrl for static file imports
44
+ const staticUrl = `${platformConfig?.projectBaseUrl ?? ""}/${fsPath.startsWith("./") ? fsPath.slice(2) : fsPath}`
43
45
  preSuppliedImports[fsPath] = {
44
46
  __esModule: true,
45
- default: objUrl,
46
- }
47
- } else if (fsPath.endsWith(".glb")) {
48
- const glbArray = Uint8Array.from(fileContent, (c) => c.charCodeAt(0))
49
- const glbBlob = new Blob([glbArray], { type: "model/gltf-binary" })
50
- const glbUrl = URL.createObjectURL(glbBlob)
51
- preSuppliedImports[fsPath] = {
52
- __esModule: true,
53
- default: glbUrl,
54
- }
55
- } else if (fsPath.endsWith(".gltf")) {
56
- const gltfJson = JSON.parse(fileContent)
57
- const fileDir = dirname(fsPath)
58
-
59
- const inlineUri = (uri: string) => {
60
- if (uri && !uri.startsWith("data:") && !uri.startsWith("http")) {
61
- const assetPath = resolveFilePath(uri, fsMap, fileDir)
62
- if (!assetPath) {
63
- console.warn(`Asset not found for URI: ${uri} in ${fsPath}`)
64
- return uri
65
- }
66
- const assetContentStr = fsMap[assetPath]
67
-
68
- try {
69
- const base64Content = btoa(assetContentStr)
70
-
71
- let mimeType = "application/octet-stream"
72
- if (assetPath.endsWith(".bin")) {
73
- mimeType = "application/octet-stream"
74
- } else if (assetPath.endsWith(".png")) {
75
- mimeType = "image/png"
76
- } else if (
77
- assetPath.endsWith(".jpeg") ||
78
- assetPath.endsWith(".jpg")
79
- ) {
80
- mimeType = "image/jpeg"
81
- }
82
-
83
- return `data:${mimeType};base64,${base64Content}`
84
- } catch (e) {
85
- console.error(`Failed to encode asset to base64: ${assetPath}`, e)
86
- return uri
87
- }
88
- }
89
- return uri
90
- }
91
-
92
- if (gltfJson.buffers) {
93
- for (const buffer of gltfJson.buffers) {
94
- if (buffer.uri) buffer.uri = inlineUri(buffer.uri)
95
- }
96
- }
97
- if (gltfJson.images) {
98
- for (const image of gltfJson.images) {
99
- if (image.uri) image.uri = inlineUri(image.uri)
100
- }
101
- }
102
-
103
- const gltfContent = JSON.stringify(gltfJson)
104
- const gltfBlob = new Blob([gltfContent], { type: "model/gltf+json" })
105
- const gltfUrl = URL.createObjectURL(gltfBlob)
106
- preSuppliedImports[fsPath] = {
107
- __esModule: true,
108
- default: gltfUrl,
47
+ default: staticUrl,
109
48
  }
110
49
  } else if (fsPath.endsWith(".tsx") || fsPath.endsWith(".ts")) {
111
50
  const importNames = getImportsFromCode(fileContent)
@@ -1,54 +0,0 @@
1
- import { expect, test } from "bun:test"
2
- import type { AnyCircuitElement, CadComponent } from "circuit-json"
3
- import { CircuitRunner } from "lib/runner/CircuitRunner"
4
-
5
- test("should support importing .glb files", async () => {
6
- const runner = new CircuitRunner()
7
-
8
- const glbContent = "This is a dummy glb file"
9
-
10
- const fsMap = {
11
- "my-model.glb": glbContent,
12
- "user-code.tsx": `
13
- import myGlbUrl from "./my-model.glb"
14
-
15
- export default () => (
16
- <chip
17
- name="C1"
18
- cadModel={{
19
- gltfUrl: myGlbUrl,
20
- }}
21
- />
22
- )
23
- `,
24
- }
25
-
26
- await runner.executeWithFsMap({
27
- fsMap,
28
- mainComponentPath: "user-code.tsx",
29
- })
30
-
31
- await runner.renderUntilSettled()
32
- const circuitJson = await runner.getCircuitJson()
33
-
34
- const chip =
35
- (circuitJson.find(
36
- (elm) => elm.type === "source_component" && elm.name === "C1",
37
- ) as AnyCircuitElement) || undefined
38
- const cadModel =
39
- (circuitJson.find((elm) => elm.type === "cad_component") as CadComponent) ||
40
- undefined
41
-
42
- expect(chip).toBeDefined()
43
- expect(cadModel?.model_gltf_url).toBeString()
44
- expect(cadModel?.model_gltf_url).toStartWith("blob:")
45
-
46
- if (cadModel?.model_gltf_url) {
47
- const response = await fetch(cadModel.model_gltf_url)
48
- const arrayBuffer = await response.arrayBuffer()
49
- const text = new TextDecoder().decode(arrayBuffer)
50
- expect(text).toBe(glbContent)
51
- }
52
-
53
- await runner.kill()
54
- })
@@ -1,78 +0,0 @@
1
- import { expect, test } from "bun:test"
2
- import type { AnyCircuitElement, CadComponent } from "circuit-json"
3
- import { CircuitRunner } from "lib/runner/CircuitRunner"
4
-
5
- test("should support importing .gltf files with binary", async () => {
6
- const runner = new CircuitRunner()
7
-
8
- const gltfContent = {
9
- asset: { version: "2.0" },
10
- scenes: [{ nodes: [0] }],
11
- nodes: [{ mesh: 0 }],
12
- meshes: [
13
- {
14
- primitives: [{ attributes: { POSITION: 0 } }],
15
- },
16
- ],
17
- buffers: [{ uri: "model.bin", byteLength: 36 }],
18
- bufferViews: [{ buffer: 0, byteOffset: 0, byteLength: 36 }],
19
- accessors: [
20
- {
21
- bufferView: 0,
22
- componentType: 5126, // FLOAT
23
- count: 3,
24
- type: "VEC3",
25
- },
26
- ],
27
- }
28
-
29
- const binContent = "This is a dummy binary file content.".padEnd(36, "\0")
30
-
31
- const fsMap = {
32
- "my-model.gltf": JSON.stringify(gltfContent),
33
- "model.bin": binContent,
34
- "user-code.tsx": `
35
- import myGltfUrl from "./my-model.gltf"
36
-
37
- export default () => (
38
- <chip
39
- name="C1"
40
- cadModel={{
41
- gltfUrl: myGltfUrl,
42
- }}
43
- />
44
- )
45
- `,
46
- }
47
-
48
- await runner.executeWithFsMap({
49
- fsMap,
50
- mainComponentPath: "user-code.tsx",
51
- })
52
-
53
- await runner.renderUntilSettled()
54
- const circuitJson = await runner.getCircuitJson()
55
-
56
- const chip =
57
- (circuitJson.find(
58
- (elm) => elm.type === "source_component" && elm.name === "C1",
59
- ) as AnyCircuitElement) || undefined
60
- const cadModel =
61
- (circuitJson.find((elm) => elm.type === "cad_component") as CadComponent) ||
62
- undefined
63
-
64
- expect(chip).toBeDefined()
65
- expect(cadModel?.model_gltf_url).toBeString()
66
- expect(cadModel?.model_gltf_url).toStartWith("blob:")
67
-
68
- if (cadModel?.model_gltf_url) {
69
- const response = await fetch(cadModel.model_gltf_url)
70
- const text = await response.text()
71
- const json = JSON.parse(text)
72
- expect(json.buffers[0].uri).toStartWith(
73
- "data:application/octet-stream;base64,",
74
- )
75
- }
76
-
77
- await runner.kill()
78
- })
@@ -1,49 +0,0 @@
1
- import { expect, test } from "bun:test"
2
- import type {
3
- AnyCircuitElement,
4
- AnySourceComponent,
5
- CadComponent,
6
- } from "circuit-json"
7
- import { CircuitRunner } from "lib/runner/CircuitRunner"
8
-
9
- test("should support importing .obj files", async () => {
10
- const runner = new CircuitRunner()
11
-
12
- const fsMap = {
13
- "my-model.obj": `v 1.0 1.0 0.0`, // some dummy obj content
14
- "user-code.tsx": `
15
- import myObjUrl from "./my-model.obj"
16
-
17
- export default () => (
18
- <chip
19
- name="C1"
20
- cadModel={{
21
- objUrl: myObjUrl,
22
- }}
23
- />
24
- )
25
- `,
26
- }
27
-
28
- await runner.executeWithFsMap({
29
- fsMap,
30
- mainComponentPath: "user-code.tsx",
31
- })
32
-
33
- await runner.renderUntilSettled()
34
- const circuitJson = await runner.getCircuitJson()
35
-
36
- const chip =
37
- (circuitJson.find(
38
- (elm) => elm.type === "source_component" && elm.name === "C1",
39
- ) as AnyCircuitElement) || undefined
40
- const cadModel =
41
- (circuitJson.find((elm) => elm.type === "cad_component") as CadComponent) ||
42
- undefined
43
-
44
- expect(chip).toBeDefined()
45
- expect(cadModel?.model_obj_url).toBeString()
46
- expect(cadModel?.model_obj_url).toStartWith("blob:")
47
-
48
- await runner.kill()
49
- })