@tscircuit/fake-snippets 0.0.65 → 0.0.67

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.
Files changed (87) hide show
  1. package/CONTRIBUTING.md +2 -2
  2. package/README.md +2 -2
  3. package/bun-tests/fake-snippets-api/fixtures/get-circuit-json.ts +5 -143
  4. package/bun-tests/fake-snippets-api/fixtures/get-test-server.ts +1 -4
  5. package/bun-tests/fake-snippets-api/fixtures/start-server.ts +7 -3
  6. package/bun-tests/fake-snippets-api/routes/order_quotes/create.test.ts +20 -56
  7. package/bun-tests/fake-snippets-api/routes/package_files/create_or_update.test.ts +2 -2
  8. package/bun-tests/fake-snippets-api/routes/package_releases/update.test.ts +1 -1
  9. package/bun-tests/fake-snippets-api/routes/packages/images.test.ts +1 -16
  10. package/bun.lock +42 -31
  11. package/dist/bundle.js +34 -41
  12. package/fake-snippets-api/routes/api/order_quotes/create.ts +30 -37
  13. package/fake-snippets-api/routes/api/order_quotes/get.ts +5 -8
  14. package/fake-snippets-api/routes/api/packages/images/[owner_github_username]/[unscoped_name]/[view_format].ts +3 -3
  15. package/package.json +7 -5
  16. package/src/App.tsx +0 -7
  17. package/src/ContextProviders.tsx +2 -0
  18. package/src/components/DownloadButtonAndMenu.tsx +1 -4
  19. package/src/components/ErrorTabContent.tsx +1 -1
  20. package/src/components/Footer.tsx +5 -2
  21. package/src/components/HeaderLogin.tsx +37 -54
  22. package/src/components/ImageWithFallback.tsx +37 -0
  23. package/src/components/JLCPCBImportDialog.tsx +43 -24
  24. package/src/components/PackageCard.tsx +12 -3
  25. package/src/components/{SnippetLink.tsx → PackageLink.tsx} +8 -16
  26. package/src/components/PackageSearchResults.tsx +87 -0
  27. package/src/components/PackagesList.tsx +3 -3
  28. package/src/components/PageSearchComponent.tsx +9 -9
  29. package/src/components/ShippingInformationForm.tsx +1 -1
  30. package/src/components/TrendingPackagesCarousel.tsx +43 -23
  31. package/src/components/ViewPackagePage/components/ShikiCodeViewer.tsx +5 -28
  32. package/src/components/ViewPackagePage/components/main-content-header.tsx +10 -22
  33. package/src/components/ViewPackagePage/components/mobile-sidebar.tsx +25 -14
  34. package/src/components/ViewPackagePage/components/package-header.tsx +9 -4
  35. package/src/components/ViewPackagePage/components/preview-image-squares.tsx +6 -1
  36. package/src/components/ViewPackagePage/components/repo-page-content.tsx +4 -4
  37. package/src/components/ViewPackagePage/components/sidebar.tsx +2 -14
  38. package/src/components/ViewSnippetSidebar.tsx +1 -1
  39. package/src/components/package-port/CodeEditor.tsx +13 -10
  40. package/src/components/package-port/CodeEditorHeader.tsx +1 -1
  41. package/src/components/package-port/EditorNav.tsx +2 -2
  42. package/src/hooks/use-get-fsmap-hash-for-package.ts +19 -0
  43. package/src/hooks/use-global-store.ts +1 -0
  44. package/src/hooks/use-preview-images.ts +20 -4
  45. package/src/hooks/use-shiki-highlighter.ts +13 -6
  46. package/src/hooks/use-toast.tsx +1 -1
  47. package/src/lib/download-fns/download-gltf.ts +3 -10
  48. package/src/lib/handleManualEditsImport.tsx +1 -1
  49. package/src/lib/types.ts +4 -2
  50. package/src/pages/dashboard.tsx +3 -4
  51. package/src/pages/editor.tsx +20 -14
  52. package/src/pages/latest.tsx +25 -26
  53. package/src/pages/package-editor.tsx +14 -2
  54. package/src/pages/search.tsx +120 -19
  55. package/src/pages/trending.tsx +14 -59
  56. package/src/pages/user-profile.tsx +13 -8
  57. package/bun-tests/fake-snippets-api/routes/snippets/add_star.test.ts +0 -84
  58. package/bun-tests/fake-snippets-api/routes/snippets/create.test.ts +0 -53
  59. package/bun-tests/fake-snippets-api/routes/snippets/delete.test.ts +0 -82
  60. package/bun-tests/fake-snippets-api/routes/snippets/download.test.ts +0 -90
  61. package/bun-tests/fake-snippets-api/routes/snippets/generate_from_jlcpcb.test.ts +0 -16
  62. package/bun-tests/fake-snippets-api/routes/snippets/get.test.ts +0 -163
  63. package/bun-tests/fake-snippets-api/routes/snippets/get_image.test.ts +0 -117
  64. package/bun-tests/fake-snippets-api/routes/snippets/images.test.ts +0 -114
  65. package/bun-tests/fake-snippets-api/routes/snippets/list.test.ts +0 -169
  66. package/bun-tests/fake-snippets-api/routes/snippets/list_newest.test.ts +0 -50
  67. package/bun-tests/fake-snippets-api/routes/snippets/list_trending.test.ts +0 -72
  68. package/bun-tests/fake-snippets-api/routes/snippets/remove_star.test.ts +0 -80
  69. package/bun-tests/fake-snippets-api/routes/snippets/search.test.ts +0 -75
  70. package/bun-tests/fake-snippets-api/routes/snippets/star-count.test.ts +0 -51
  71. package/bun-tests/fake-snippets-api/routes/snippets/update.test.ts +0 -175
  72. package/src/components/AiChatInterface.tsx +0 -229
  73. package/src/components/CodeAndPreview.tsx +0 -289
  74. package/src/components/CodeEditor.tsx +0 -539
  75. package/src/components/CodeEditorHeader.tsx +0 -135
  76. package/src/components/EditorNav.tsx +0 -502
  77. package/src/components/PreviewContent.tsx +0 -372
  78. package/src/components/SnippetCard.tsx +0 -159
  79. package/src/components/SnippetList.tsx +0 -71
  80. package/src/hooks/use-compiled-tsx.ts +0 -37
  81. package/src/hooks/use-run-tsx/construct-circuit.tsx +0 -62
  82. package/src/hooks/use-run-tsx/index.tsx +0 -256
  83. package/src/hooks/use-save-snippet.ts +0 -66
  84. package/src/hooks/use-typecheck.ts +0 -54
  85. package/src/lib/utils/getSyntaxError.ts +0 -13
  86. package/src/pages/ai.tsx +0 -92
  87. package/src/pages/view-snippet.tsx +0 -166
package/CONTRIBUTING.md CHANGED
@@ -27,9 +27,9 @@ Pull requests are the best way to propose changes to the codebase. We actively w
27
27
 
28
28
  In short, when you submit code changes, your submissions are understood to be under the same [MIT License](http://choosealicense.com/licenses/mit/) that covers the project. Feel free to contact the maintainers if that's a concern.
29
29
 
30
- ## Report bugs using Github's [issues](https://github.com/tscircuit/snippets/issues)
30
+ ## Report bugs using Github's [issues](https://github.com/tscircuit/tscircuit.com/issues)
31
31
 
32
- We use GitHub issues to track public bugs. Report a bug by [opening a new issue](https://github.com/tscircuit/snippets/issues/new); it's that easy!
32
+ We use GitHub issues to track public bugs. Report a bug by [opening a new issue](https://github.com/tscircuit/tscircuit.com/issues/new); it's that easy!
33
33
 
34
34
  ## Write bug reports with detail, background, and sample code
35
35
 
package/README.md CHANGED
@@ -30,8 +30,8 @@ TSCircuit Snippets is a web application for creating, sharing, and managing circ
30
30
  1. Clone the repository:
31
31
 
32
32
  ```bash
33
- git clone https://github.com/tscircuit/snippets.git
34
- cd snippets
33
+ git clone https://github.com/tscircuit/tscircuit.com.git
34
+ cd tscircuit.com
35
35
  ```
36
36
 
37
37
  2. Install dependencies:
@@ -1,148 +1,10 @@
1
- import * as React from "react"
2
- import { getImportsFromCode } from "@tscircuit/prompt-benchmarks/code-runner-utils"
3
- import * as tscircuitCore from "@tscircuit/core"
4
- import * as jscadFiber from "jscad-fiber"
5
1
  import type { AnyCircuitElement } from "circuit-json"
6
- import { safeCompileTsx } from "@/hooks/use-compiled-tsx"
7
- import { evalCompiledJs } from "@/hooks/use-run-tsx/eval-compiled-js"
8
- import { constructCircuit } from "@/hooks/use-run-tsx/construct-circuit"
9
-
10
- type GenerateCircuitJson = {
11
- code: string
12
- type: "board" | "footprint" | "package" | "model"
13
- compiled_js: string
14
- }
15
-
16
- // Keeping track of processed imports to avoid circular dependencies
17
- const processedImports = new Set<string>()
18
-
19
- async function processImport(
20
- importName: string,
21
- preSuppliedImports: Record<string, any>,
22
- depth = 0,
23
- code: string,
24
- compiled_js: string,
25
- ): Promise<void> {
26
- if (!importName.startsWith("@tsci/")) return
27
- if (preSuppliedImports[importName]) return
28
- if (processedImports.has(importName)) return
29
- if (depth > 5) {
30
- throw new Error(
31
- `Max depth for imports reached when processing ${importName}`,
32
- )
33
- }
34
-
35
- processedImports.add(importName)
36
-
37
- try {
38
- // Process nested imports first
39
- const nestedImports = getImportsFromCode(code)
40
-
41
- // Filter out already processed imports and non-@tsci imports
42
- const validNestedImports = nestedImports.filter(
43
- (imp) =>
44
- imp.startsWith("@tsci/") &&
45
- !processedImports.has(imp) &&
46
- !preSuppliedImports[imp],
47
- )
48
-
49
- // Process each valid nested import
50
- for (const nestedImport of validNestedImports) {
51
- await processImport(
52
- nestedImport,
53
- preSuppliedImports,
54
- depth + 1,
55
- code,
56
- compiled_js,
57
- )
58
- }
59
- // Set React in the global scope before evaluation
60
- ;(globalThis as any).React = React
61
- const exports = evalCompiledJs(compiled_js).exports
62
-
63
- // Only set the import if we successfully evaluated it
64
- if (exports) {
65
- preSuppliedImports[importName] = exports
66
- }
67
- } catch (e) {
68
- processedImports.delete(importName) // Clean up on error
69
- }
70
- }
2
+ import { runTscircuitCode } from "@tscircuit/eval"
71
3
 
72
4
  export const generateCircuitJson = async ({
73
5
  code,
74
- type,
75
- compiled_js,
76
- }: GenerateCircuitJson): Promise<AnyCircuitElement[]> => {
77
- // Clear the processed imports set at the start of each generation
78
- processedImports.clear()
79
-
80
- // Set up pre-supplied imports
81
- const preSuppliedImports: Record<string, any> = {
82
- "@tscircuit/core": tscircuitCore,
83
- react: React,
84
- "jscad-fiber": jscadFiber,
85
- }
86
- ;(globalThis as any).React = React
87
- ;(globalThis as any).createElement = React.createElement
88
-
89
- try {
90
- // Process all @tsci imports
91
- const tsciImports = getImportsFromCode(code).filter((imp) =>
92
- imp.startsWith("@tsci/"),
93
- )
94
- for (const importName of tsciImports) {
95
- await processImport(importName, preSuppliedImports, 0, code, compiled_js)
96
- }
97
-
98
- // Create require function for imports
99
- const __tscircuit_require = (name: string) => {
100
- if (!preSuppliedImports[name]) {
101
- throw new Error(
102
- `Import "${name}" not found (available imports: ${Object.keys(preSuppliedImports).join(", ")})`,
103
- )
104
- }
105
- return preSuppliedImports[name]
106
- }
107
- ;(globalThis as any).__tscircuit_require = __tscircuit_require
108
-
109
- // Add a custom JSX runtime
110
- ;(globalThis as any).jsx = React.createElement
111
- ;(globalThis as any).jsxs = React.createElement
112
-
113
- const { success, compiledTsx, error } = safeCompileTsx(code)
114
- if (!success || !compiledTsx) {
115
- throw new Error(
116
- `Compile Error: ${error?.message || "Unknown compilation error"}`,
117
- )
118
- }
119
-
120
- const module = evalCompiledJs(compiledTsx)
121
- const componentExportKeys = Object.keys(module.exports).filter(
122
- (key) => !key.startsWith("use"),
123
- )
124
-
125
- if (componentExportKeys.length > 1) {
126
- throw new Error(
127
- `Too many exports, only export one component. Exports: ${JSON.stringify(componentExportKeys)}`,
128
- )
129
- }
130
-
131
- const primaryKey = componentExportKeys[0]
132
-
133
- // Create the user element with explicit React scope
134
- const UserElm = function (props: any) {
135
- return React.createElement(module.exports[primaryKey], props)
136
- }
137
-
138
- // Construct and render the circuit
139
- const circuit = constructCircuit({ UserElm, type })
140
-
141
- // Wait for the circuit to settle
142
- await circuit.renderUntilSettled()
143
-
144
- return circuit.getCircuitJson() as AnyCircuitElement[]
145
- } catch (e) {
146
- throw new Error("Circuit generation failed!")
147
- }
6
+ }: {
7
+ code: string
8
+ }): Promise<AnyCircuitElement[]> => {
9
+ return (await runTscircuitCode(code)) as any
148
10
  }
@@ -2,7 +2,6 @@ import { afterEach } from "bun:test"
2
2
  import defaultAxios from "redaxios"
3
3
  import { startServer } from "./start-server"
4
4
  import { DbClient } from "fake-snippets-api/lib/db/db-client"
5
- import getPort from "get-port"
6
5
 
7
6
  process.env.BUN_TEST = "true"
8
7
  interface TestFixture {
@@ -16,12 +15,10 @@ interface TestFixture {
16
15
  }
17
16
 
18
17
  export const getTestServer = async (): Promise<TestFixture> => {
19
- const port = await getPort()
20
18
  const testInstanceId = Math.random().toString(36).substring(2, 15)
21
19
  const testDbName = `testdb${testInstanceId}`
22
20
 
23
- const { server, db } = await startServer({
24
- port,
21
+ const { server, db, port } = await startServer({
25
22
  testDbName,
26
23
  })
27
24
 
@@ -11,7 +11,7 @@ import { createDatabase } from "fake-snippets-api/lib/db/db-client"
11
11
  export const startServer = async ({
12
12
  port,
13
13
  testDbName,
14
- }: { port: number; testDbName: string }) => {
14
+ }: { port?: number; testDbName: string }) => {
15
15
  const winterspecBundle = await createWinterSpecBundleFromDir(
16
16
  join(import.meta.dir, "../../../fake-snippets-api/routes"),
17
17
  )
@@ -37,8 +37,12 @@ export const startServer = async ({
37
37
  middleware,
38
38
  })
39
39
  },
40
- port,
40
+ port: port ?? 0,
41
41
  })
42
42
 
43
- return { server: { ...server, stop: () => server.stop() }, db }
43
+ return {
44
+ server: { ...server, stop: () => server.stop() },
45
+ db,
46
+ port: server.port,
47
+ }
44
48
  }
@@ -1,69 +1,33 @@
1
1
  import { getTestServer } from "bun-tests/fake-snippets-api/fixtures/get-test-server"
2
2
  import { test, expect } from "bun:test"
3
3
 
4
- test("create order_quote with only circuit_json (✅)", async () => {
5
- const {
6
- axios,
7
- seed: { order },
8
- } = await getTestServer()
9
-
10
- const response = await axios.post("/api/order_quotes/create", {
11
- vendor_name: "jlcpcb",
12
- circuit_json: order.circuit_json,
13
- })
4
+ test("create order_quote with only package_release_id (✅)", async () => {
5
+ const { axios, jane_axios } = await getTestServer()
14
6
 
15
- expect(response.status).toBe(200)
16
- expect(response.data.order_quote_id).toBeDefined()
17
- })
7
+ const pkg = await jane_axios
8
+ .post("/api/packages/create", {
9
+ name: "jane/test-package",
10
+ })
11
+ .then((res) => res.data.package)
18
12
 
19
- test("create order_quote with only package_release_id (✅)", async () => {
20
- const {
21
- axios,
22
- seed: { packageRelease },
23
- } = await getTestServer()
13
+ const packageRelease = await jane_axios
14
+ .post("/api/package_releases/create", {
15
+ package_id: pkg.package_id,
16
+ version: "1.0.0",
17
+ is_latest: true,
18
+ })
19
+ .then((res) => res.data.package_release)
24
20
 
21
+ await jane_axios.post(`/api/package_files/create`, {
22
+ package_release_id: packageRelease.package_release_id,
23
+ file_path: "/dist/index.js",
24
+ content_text: "console.log('Hello, world!');",
25
+ })
25
26
  const response = await axios.post("/api/order_quotes/create", {
26
27
  vendor_name: "jlcpcb",
27
- package_release_id: packageRelease!.package_release_id,
28
+ package_release_id: packageRelease.package_release_id,
28
29
  })
29
30
 
30
31
  expect(response.status).toBe(200)
31
32
  expect(response.data.order_quote_id).toBeDefined()
32
33
  })
33
-
34
- test("create order_quote with both circuit_json and package_release_id (✅)", async () => {
35
- const {
36
- axios,
37
- seed: { order, packageRelease },
38
- } = await getTestServer()
39
-
40
- const response = await axios
41
- .post("/api/order_quotes/create", {
42
- vendor_name: "jlcpcb",
43
- circuit_json: order.circuit_json,
44
- package_release_id: packageRelease!.package_release_id,
45
- })
46
- .catch((error) => error) // Capture response even on error
47
-
48
- // Expecting backend to fail with 400
49
- expect(response?.status).toBe(400)
50
- expect(response?.data.message).toContain(
51
- "You must provide either circuit_json or package_release_id, but not both.",
52
- )
53
- })
54
-
55
- test("create order_quote with neither circuit_json nor package_release_id (✅)", async () => {
56
- const { axios } = await getTestServer()
57
-
58
- const response = await axios
59
- .post("/api/order_quotes/create", {
60
- vendor_name: "jlcpcb",
61
- })
62
- .catch((error) => error) // Capture response even on error
63
-
64
- // Expecting backend to fail with 400
65
- expect(response?.status).toBe(400)
66
- expect(response?.data.message).toContain(
67
- "You must provide either circuit_json or package_release_id.",
68
- )
69
- })
@@ -398,7 +398,7 @@ test("create_or_update - 404 for npm_pack_output without is_release_tarball", as
398
398
  }
399
399
  })
400
400
 
401
- test("update package file with content_base64", async () => {
401
+ test.skip("update package file with content_base64", async () => {
402
402
  const { axios } = await getTestServer()
403
403
 
404
404
  const packageResponse = await axios.post("/api/packages/create", {
@@ -506,7 +506,7 @@ test("create_or_update detects correct content mimetype", async () => {
506
506
  }
507
507
  })
508
508
 
509
- test("create_or_update respects provided content_mimetype", async () => {
509
+ test.skip("create_or_update respects provided content_mimetype", async () => {
510
510
  const { axios } = await getTestServer()
511
511
 
512
512
  const packageResponse = await axios.post("/api/packages/create", {
@@ -69,7 +69,7 @@ test("update package release using package_name_with_version", async () => {
69
69
  expect(updatedRelease?.is_locked).toBe(true)
70
70
  })
71
71
 
72
- test("update package release - handle is_latest flag", async () => {
72
+ test.skip("update package release - handle is_latest flag", async () => {
73
73
  const { axios, db } = await getTestServer()
74
74
 
75
75
  // Create a package
@@ -27,17 +27,6 @@ export default () => (
27
27
  <A555Timer name="U1" />
28
28
  </board>
29
29
  )`.trim(),
30
- type: "board",
31
- compiled_js: `
32
- "use strict";
33
- Object.defineProperty(exports, "__esModule", { value: true });
34
- exports.A555Timer = void 0;
35
- const A555Timer = ({ name }) => /*#__PURE__*/React.createElement("chip", {
36
- name: name,
37
- footprint: "dip8"
38
- });
39
- exports.A555Timer = A555Timer;
40
- `.trim(),
41
30
  })
42
31
  // create a package file
43
32
  const pkg_file = await axios.post("/api/package_files/create", {
@@ -53,11 +42,7 @@ export default () => (
53
42
  package_release_id: pkg_release.data.package_release.package_release_id,
54
43
  })
55
44
  for (const file of files.data.package_files) {
56
- // get the file content
57
- const file_content = await axios.post("/api/package_files/get", {
58
- package_file_id: file.package_file_id,
59
- })
60
- fsMap.set(file.file_path, file_content.data.package_file.content_text)
45
+ fsMap.set(file.file_path, file.content_text)
61
46
  }
62
47
 
63
48
  const fsMapHash = md5(JSON.stringify(fsMap))