@tscircuit/eval 0.0.316 → 0.0.318

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.
@@ -51,7 +51,7 @@ export const resolveFilePath = (
51
51
  }
52
52
 
53
53
  // Search for file with a set of different extensions
54
- const extension = ["tsx", "ts", "json", "js", "jsx", "obj"]
54
+ const extension = ["tsx", "ts", "json", "js", "jsx", "obj", "gltf", "glb"]
55
55
  for (const ext of extension) {
56
56
  const possibleFilePath = `${normalizedResolvedPath}.${ext}`
57
57
  if (normalizedFilePathMap.has(possibleFilePath)) {
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.316",
4
+ "version": "0.0.318",
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.71",
58
58
  "@tscircuit/circuit-json-flex": "^0.0.3",
59
59
  "@tscircuit/circuit-json-util": "^0.0.67",
60
- "@tscircuit/core": "^0.0.715",
60
+ "@tscircuit/core": "^0.0.719",
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,11 +67,11 @@
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.313",
70
+ "@tscircuit/props": "0.0.319",
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",
74
- "@tscircuit/simple-3d-svg": "^0.0.38",
74
+ "@tscircuit/simple-3d-svg": "^0.0.41",
75
75
  "@types/babel__standalone": "^7.1.9",
76
76
  "@types/bun": "^1.2.16",
77
77
  "@types/debug": "^4.1.12",
@@ -82,11 +82,11 @@
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.249",
85
+ "circuit-json": "^0.0.250",
86
86
  "circuit-json-to-bpc": "^0.0.13",
87
87
  "circuit-json-to-connectivity-map": "^0.0.22",
88
- "circuit-json-to-simple-3d": "^0.0.6",
89
- "circuit-to-svg": "^0.0.185",
88
+ "circuit-json-to-simple-3d": "^0.0.8",
89
+ "circuit-to-svg": "^0.0.189",
90
90
  "comlink": "^4.4.2",
91
91
  "concurrently": "^9.1.2",
92
92
  "connectivity-map": "^1.0.0",
@@ -0,0 +1,78 @@
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,5 +1,8 @@
1
1
  import * as Babel from "@babel/standalone"
2
- import { resolveFilePathOrThrow } from "lib/runner/resolveFilePath"
2
+ import {
3
+ resolveFilePath,
4
+ resolveFilePathOrThrow,
5
+ } from "lib/runner/resolveFilePath"
3
6
  import { dirname } from "lib/utils/dirname"
4
7
  import { getImportsFromCode } from "lib/utils/get-imports-from-code"
5
8
  import { evalCompiledJs } from "./eval-compiled-js"
@@ -41,6 +44,61 @@ export const importLocalFile = async (
41
44
  __esModule: true,
42
45
  default: objUrl,
43
46
  }
47
+ } else if (fsPath.endsWith(".gltf")) {
48
+ const gltfJson = JSON.parse(fileContent)
49
+ const fileDir = dirname(fsPath)
50
+
51
+ const inlineUri = (uri: string) => {
52
+ if (uri && !uri.startsWith("data:") && !uri.startsWith("http")) {
53
+ const assetPath = resolveFilePath(uri, fsMap, fileDir)
54
+ if (!assetPath) {
55
+ console.warn(`Asset not found for URI: ${uri} in ${fsPath}`)
56
+ return uri
57
+ }
58
+ const assetContentStr = fsMap[assetPath]
59
+
60
+ try {
61
+ const base64Content = btoa(assetContentStr)
62
+
63
+ let mimeType = "application/octet-stream"
64
+ if (assetPath.endsWith(".bin")) {
65
+ mimeType = "application/octet-stream"
66
+ } else if (assetPath.endsWith(".png")) {
67
+ mimeType = "image/png"
68
+ } else if (
69
+ assetPath.endsWith(".jpeg") ||
70
+ assetPath.endsWith(".jpg")
71
+ ) {
72
+ mimeType = "image/jpeg"
73
+ }
74
+
75
+ return `data:${mimeType};base64,${base64Content}`
76
+ } catch (e) {
77
+ console.error(`Failed to encode asset to base64: ${assetPath}`, e)
78
+ return uri
79
+ }
80
+ }
81
+ return uri
82
+ }
83
+
84
+ if (gltfJson.buffers) {
85
+ for (const buffer of gltfJson.buffers) {
86
+ if (buffer.uri) buffer.uri = inlineUri(buffer.uri)
87
+ }
88
+ }
89
+ if (gltfJson.images) {
90
+ for (const image of gltfJson.images) {
91
+ if (image.uri) image.uri = inlineUri(image.uri)
92
+ }
93
+ }
94
+
95
+ const gltfContent = JSON.stringify(gltfJson)
96
+ const gltfBlob = new Blob([gltfContent], { type: "model/gltf+json" })
97
+ const gltfUrl = URL.createObjectURL(gltfBlob)
98
+ preSuppliedImports[fsPath] = {
99
+ __esModule: true,
100
+ default: gltfUrl,
101
+ }
44
102
  } else if (fsPath.endsWith(".tsx") || fsPath.endsWith(".ts")) {
45
103
  const importNames = getImportsFromCode(fileContent)
46
104