@tscircuit/fake-snippets 0.0.105 → 0.0.107

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 (33) hide show
  1. package/CLAUDE.md +92 -0
  2. package/api/generated-index.js +3 -4
  3. package/bun-tests/fake-snippets-api/routes/package_builds/get.test.ts +294 -0
  4. package/bun-tests/fake-snippets-api/routes/package_builds/list.test.ts +304 -0
  5. package/dist/bundle.js +698 -335
  6. package/dist/index.d.ts +147 -4
  7. package/dist/index.js +195 -7
  8. package/dist/schema.d.ts +206 -1
  9. package/dist/schema.js +31 -2
  10. package/fake-snippets-api/lib/db/db-client.ts +60 -3
  11. package/fake-snippets-api/lib/db/schema.ts +31 -0
  12. package/fake-snippets-api/lib/db/seed.ts +139 -2
  13. package/fake-snippets-api/lib/public-mapping/public-map-package-build.ts +41 -0
  14. package/fake-snippets-api/routes/api/package_builds/get.ts +70 -0
  15. package/fake-snippets-api/routes/api/package_builds/list.ts +97 -0
  16. package/package.json +3 -2
  17. package/src/App.tsx +21 -5
  18. package/src/components/PackageBreadcrumb.tsx +111 -0
  19. package/src/components/ViewPackagePage/components/sidebar-releases-section.tsx +22 -11
  20. package/src/components/preview/BuildsList.tsx +196 -211
  21. package/src/components/preview/ConnectedPackagesList.tsx +54 -25
  22. package/src/components/preview/ConnectedRepoOverview.tsx +63 -35
  23. package/src/components/preview/{ConnectedRepoDashboard.tsx → PackageReleasesDashboard.tsx} +33 -71
  24. package/src/components/preview/index.tsx +20 -77
  25. package/src/hooks/use-package-builds.ts +87 -0
  26. package/src/hooks/use-package-release-by-id-or-version.ts +36 -0
  27. package/src/hooks/use-package-release.ts +32 -0
  28. package/src/lib/utils/isUuid.ts +5 -0
  29. package/src/pages/preview-build.tsx +3 -3
  30. package/src/pages/release-builds.tsx +107 -0
  31. package/src/pages/release-detail.tsx +118 -0
  32. package/src/pages/releases.tsx +51 -0
  33. package/src/pages/view-connected-repo.tsx +0 -18
package/CLAUDE.md ADDED
@@ -0,0 +1,92 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ tscircuit.com is a React-based web application for creating, sharing, and managing electronic circuit designs using TypeScript and React. It features a circuit editor, package management system, AI-assisted design tools, and visualization of PCB layouts and 3D models.
8
+
9
+ ## Development Commands
10
+
11
+ - `bun run dev` - Start development server (builds fake API and runs on localhost:5173)
12
+ - `bun run build` - Full production build (generates images, sitemap, builds fake API, compiles TypeScript, and builds with Vite)
13
+ - `bun run typecheck` - Run TypeScript type checking without emitting files
14
+ - `bun run format` - Format code using Biome
15
+ - `bun run lint` - Check code formatting with Biome
16
+ - `bun run playwright` - Run Playwright end-to-end tests
17
+ - `bun run playwright:update` - Update Playwright test snapshots
18
+ - `bun run snapshot` - Interactive snapshot updating tool (prompts for specific test file)
19
+
20
+ ### Fake API Development
21
+ - `bun run build:fake-api` - Build the complete fake API (TypeScript compilation, bundle generation, schema building)
22
+ - `bun run dev:registry` - Run dev server using registry API at localhost:3100
23
+
24
+ ## Architecture
25
+
26
+ ### Frontend Structure
27
+ - **React SPA** with Vite bundler, using Wouter for routing and lazy-loaded pages
28
+ - **State Management**: Zustand for global state, React Query for server state
29
+ - **UI Framework**: Tailwind CSS with Radix UI components and custom shadcn/ui components
30
+ - **Code Editor**: CodeMirror 6 with TypeScript support and AI completion
31
+
32
+ ### API Architecture
33
+ - **Fake API**: Development API built with Winterspec, providing full backend simulation
34
+ - **Database Schema**: Zod-validated schemas for packages, builds, releases, snippets, accounts, orders
35
+ - **Authentication**: Session-based auth with GitHub integration
36
+
37
+ ### Key Domains
38
+ - **Packages**: Reusable circuit components with versioning and releases
39
+ - **Package Builds**: Compilation artifacts with build status and logs
40
+ - **Package Releases**: Published versions with metadata and assets
41
+ - **Snippets**: Legacy circuit designs (being migrated to packages)
42
+ - **Circuit JSON**: Standard format for circuit data interchange
43
+
44
+ ### File Organization
45
+ - `src/components/` - Reusable UI components
46
+ - `src/pages/` - Route-based page components
47
+ - `src/hooks/` - Custom React hooks for data fetching and state
48
+ - `src/lib/` - Utilities, constants, and helper functions
49
+ - `fake-snippets-api/` - Mock API implementation with Winterspec
50
+ - `playwright-tests/` - End-to-end tests with visual regression snapshots
51
+
52
+ ## Testing Strategy
53
+
54
+ Uses Playwright for end-to-end testing with visual regression snapshots. Tests cover critical user flows including editor functionality, package management, authentication, and responsive design across viewport sizes.
55
+
56
+ ## Key Technical Patterns
57
+
58
+ ### Data Fetching
59
+ - React Query for server state with custom hooks (use-package-*, use-snippet-*, etc.)
60
+ - Fake API provides development backend with realistic data simulation
61
+ - SSR support via Vercel for SEO and performance
62
+
63
+ ### Circuit Visualization
64
+ - Multiple viewers: PCB viewer, schematic viewer, 3D viewer, assembly viewer
65
+ - SVG-based rendering with interactive controls
66
+ - Real-time preview updates during code editing
67
+
68
+ ### Code Compilation
69
+ - TypeScript compilation in browser using Monaco/TypeScript compiler API
70
+ - Circuit JSON generation from TypeScript code
71
+ - Error handling and display for compilation issues
72
+
73
+ ### Package Management
74
+ - Package files with hierarchical structure
75
+ - Build artifacts and release management
76
+ - GitHub integration for repository linking
77
+
78
+ ## Environment Variables
79
+
80
+ Development AI testing requires:
81
+ ```bash
82
+ VITE_USE_DIRECT_AI_REQUESTS=true
83
+ VITE_ANTHROPIC_API_KEY=<your-key-here>
84
+ ```
85
+
86
+ ## Build Tools
87
+
88
+ - **Bundler**: Vite with React plugin and image optimization
89
+ - **TypeScript**: Strict mode with path aliases (@/* → src/*)
90
+ - **Styling**: Tailwind CSS with custom design tokens
91
+ - **Code Quality**: Biome for formatting and linting
92
+ - **Package Manager**: Bun for fast installs and script execution
@@ -31,7 +31,7 @@ const PREFETCHABLE_PAGES = new Set([
31
31
  "latest",
32
32
  "settings",
33
33
  "quickstart",
34
- "view-connected-repo",
34
+ "releases",
35
35
  ])
36
36
 
37
37
  const pageDescriptions = {
@@ -51,8 +51,7 @@ const pageDescriptions = {
51
51
  "Get started quickly with tscircuit. Create new circuit packages, import components from JLCPCB, or start from templates to begin your electronic design journey.",
52
52
  settings:
53
53
  "Manage your tscircuit account settings, shipping information, and preferences for electronic design and PCB ordering.",
54
- "view-connected-repo":
55
- "View and manage your connected repositories. Monitor repository status, access build information, and configure build options.",
54
+ releases: "View all package releases, access build information.",
56
55
  }
57
56
 
58
57
  function getPageDescription(pageName) {
@@ -185,7 +184,7 @@ async function handleCustomPackageHtml(req, res) {
185
184
  throw new Error("Datasheet route")
186
185
  }
187
186
  if (author === "build" || unscopedPackageName === "view-connected-repo") {
188
- throw new Error("Deployment route - not a package")
187
+ throw new Error("Build route - not a package")
189
188
  }
190
189
 
191
190
  const packageNotFoundHtml = getHtmlWithModifiedSeoTags({
@@ -0,0 +1,294 @@
1
+ import { getTestServer } from "bun-tests/fake-snippets-api/fixtures/get-test-server"
2
+ import { test, expect } from "bun:test"
3
+ import defaultAxios from "redaxios"
4
+
5
+ export const createTestPackage = async (axios: typeof defaultAxios) => {
6
+ const packageRes = await axios.post("/api/packages/create", {
7
+ json: {
8
+ name: "test-package",
9
+ description: "Test package for builds",
10
+ },
11
+ })
12
+ return packageRes.data
13
+ }
14
+
15
+ export const createTestPackageRelease = async (
16
+ axios: typeof defaultAxios,
17
+ packageId: string,
18
+ ) => {
19
+ const releaseRes = await axios.post("/api/package_releases/create", {
20
+ package_id: packageId,
21
+ version: "1.0.0",
22
+ is_latest: true,
23
+ })
24
+ return releaseRes.data
25
+ }
26
+
27
+ test("GET /api/package_builds/get - requires package_build_id 69", async () => {
28
+ const { jane_axios } = await getTestServer()
29
+ const res = await jane_axios.get("/api/package_builds/get", {
30
+ validateStatus: () => true,
31
+ })
32
+ expect(res.status).toBe(400)
33
+ })
34
+
35
+ test("GET /api/package_builds/get - returns 404 for non-existent package build", async () => {
36
+ const { jane_axios } = await getTestServer()
37
+ const res = await jane_axios.get(
38
+ "/api/package_builds/get?package_build_id=non-existent-build",
39
+ { validateStatus: () => true },
40
+ )
41
+ expect(res.status).toBe(404)
42
+ expect(res.data.error.error_code).toBe("package_build_not_found")
43
+ expect(res.data.error.message).toBe("Package build not found")
44
+ })
45
+
46
+ test("GET /api/package_builds/get - returns 403 for unauthorized package build access", async () => {
47
+ const { jane_axios, axios, db } = await getTestServer()
48
+ const packageData = await createTestPackage(jane_axios)
49
+ const { package_release } = await createTestPackageRelease(
50
+ jane_axios,
51
+ packageData.package.package_id,
52
+ )
53
+
54
+ const packageBuild = db.addPackageBuild({
55
+ package_release_id: package_release.package_release_id,
56
+ created_at: new Date().toISOString(),
57
+ transpilation_in_progress: false,
58
+ transpilation_started_at: new Date().toISOString(),
59
+ transpilation_completed_at: new Date().toISOString(),
60
+ transpilation_logs: [],
61
+ transpilation_error: null,
62
+ circuit_json_build_in_progress: false,
63
+ circuit_json_build_started_at: new Date().toISOString(),
64
+ circuit_json_build_completed_at: new Date().toISOString(),
65
+ circuit_json_build_logs: [],
66
+ circuit_json_build_error: null,
67
+ build_in_progress: false,
68
+ build_started_at: new Date().toISOString(),
69
+ build_completed_at: new Date().toISOString(),
70
+ build_error: null,
71
+ build_error_last_updated_at: new Date().toISOString(),
72
+ build_logs: null,
73
+ preview_url: "https://preview.tscircuit.com/pb_test",
74
+ branch_name: "main",
75
+ commit_message: "Test build",
76
+ commit_author: "jane.doe",
77
+ })
78
+
79
+ const res = await axios.get(
80
+ `/api/package_builds/get?package_build_id=${packageBuild.package_build_id}`,
81
+ { validateStatus: () => true },
82
+ )
83
+ expect(res.status).toBe(403)
84
+ expect(res.data.error.error_code).toBe("unauthorized")
85
+ })
86
+
87
+ test("GET /api/package_builds/get - successfully returns package build with logs", async () => {
88
+ const { axios, db } = await getTestServer()
89
+ const { package: pkg } = await createTestPackage(axios)
90
+ const { package_release } = await createTestPackageRelease(
91
+ axios,
92
+ pkg.package_id,
93
+ )
94
+
95
+ const buildLogs = ["Started build", "Building components", "Build completed"]
96
+ const transpilationLogs = ["Transpiling files", "Transpilation done"]
97
+ const circuitJsonBuildLogs = ["Generating circuit JSON", "Circuit JSON ready"]
98
+
99
+ const packageBuild = db.addPackageBuild({
100
+ package_release_id: package_release.package_release_id,
101
+ created_at: new Date(Date.now() - 1000 * 60 * 30).toISOString(),
102
+ transpilation_in_progress: false,
103
+ transpilation_started_at: new Date(
104
+ Date.now() - 1000 * 60 * 35,
105
+ ).toISOString(),
106
+ transpilation_completed_at: new Date(
107
+ Date.now() - 1000 * 60 * 32,
108
+ ).toISOString(),
109
+ transpilation_logs: transpilationLogs,
110
+ transpilation_error: null,
111
+ circuit_json_build_in_progress: false,
112
+ circuit_json_build_started_at: new Date(
113
+ Date.now() - 1000 * 60 * 32,
114
+ ).toISOString(),
115
+ circuit_json_build_completed_at: new Date(
116
+ Date.now() - 1000 * 60 * 30,
117
+ ).toISOString(),
118
+ circuit_json_build_logs: circuitJsonBuildLogs,
119
+ circuit_json_build_error: null,
120
+ build_in_progress: false,
121
+ build_started_at: new Date(Date.now() - 1000 * 60 * 30).toISOString(),
122
+ build_completed_at: new Date(Date.now() - 1000 * 60 * 25).toISOString(),
123
+ build_error: null,
124
+ build_error_last_updated_at: new Date(
125
+ Date.now() - 1000 * 60 * 25,
126
+ ).toISOString(),
127
+ build_logs: buildLogs.join(" "),
128
+ preview_url: "https://preview.tscircuit.com/pb_1a2b3c4d",
129
+ branch_name: "main",
130
+ commit_message: "Add new LED component with improved brightness control",
131
+ commit_author: "john.doe",
132
+ })
133
+
134
+ const res = await axios.get(
135
+ `/api/package_builds/get?package_build_id=${packageBuild.package_build_id}`,
136
+ )
137
+ expect(res.status).toBe(200)
138
+ expect(res.data.package_build).toBeDefined()
139
+ expect(res.data.package_build.package_build_id).toBe(
140
+ packageBuild.package_build_id,
141
+ )
142
+ expect(res.data.package_build.transpilation_logs).toEqual(transpilationLogs)
143
+ expect(res.data.package_build.circuit_json_build_logs).toEqual(
144
+ circuitJsonBuildLogs,
145
+ )
146
+ expect(res.data.package_build.build_logs).toBe(buildLogs.join(" "))
147
+ })
148
+
149
+ test("GET /api/package_builds/get - returns package build without logs when include_logs is false", async () => {
150
+ const { axios, db } = await getTestServer()
151
+ const { package: pkg } = await createTestPackage(axios)
152
+ const { package_release } = await createTestPackageRelease(
153
+ axios,
154
+ pkg.package_id,
155
+ )
156
+
157
+ const packageBuild = db.addPackageBuild({
158
+ package_release_id: package_release.package_release_id,
159
+ created_at: new Date().toISOString(),
160
+ transpilation_in_progress: false,
161
+ transpilation_started_at: new Date().toISOString(),
162
+ transpilation_completed_at: new Date().toISOString(),
163
+ transpilation_logs: ["Some logs"],
164
+ transpilation_error: null,
165
+ circuit_json_build_in_progress: false,
166
+ circuit_json_build_started_at: new Date().toISOString(),
167
+ circuit_json_build_completed_at: new Date().toISOString(),
168
+ circuit_json_build_logs: ["Some circuit logs"],
169
+ circuit_json_build_error: null,
170
+ build_in_progress: false,
171
+ build_started_at: new Date().toISOString(),
172
+ build_completed_at: new Date().toISOString(),
173
+ build_error: null,
174
+ build_error_last_updated_at: new Date().toISOString(),
175
+ build_logs: "Some build logs",
176
+ preview_url: "https://preview.tscircuit.com/pb_test",
177
+ branch_name: "main",
178
+ commit_message: "Test build",
179
+ commit_author: "john.doe",
180
+ })
181
+
182
+ const res = await axios.get(
183
+ `/api/package_builds/get?package_build_id=${packageBuild.package_build_id}`,
184
+ )
185
+ expect(res.status).toBe(200)
186
+ expect(res.data.package_build).toBeDefined()
187
+ expect(res.data.package_build.package_build_id).toBe(
188
+ packageBuild.package_build_id,
189
+ )
190
+ expect(res.data.package_build.transpilation_logs).toEqual(["Some logs"])
191
+ expect(res.data.package_build.circuit_json_build_logs).toEqual([
192
+ "Some circuit logs",
193
+ ])
194
+ expect(res.data.package_build.build_logs).toBe("Some build logs")
195
+ })
196
+
197
+ test("GET /api/package_builds/get - handles build with errors", async () => {
198
+ const { axios, db } = await getTestServer()
199
+ const { package: pkg } = await createTestPackage(axios)
200
+ const { package_release } = await createTestPackageRelease(
201
+ axios,
202
+ pkg.package_id,
203
+ )
204
+
205
+ const packageBuild = db.addPackageBuild({
206
+ package_release_id: package_release.package_release_id,
207
+ created_at: new Date().toISOString(),
208
+ transpilation_in_progress: false,
209
+ transpilation_started_at: new Date().toISOString(),
210
+ transpilation_completed_at: null,
211
+ transpilation_logs: [],
212
+ transpilation_error: "Transpilation failed: syntax error",
213
+ circuit_json_build_in_progress: false,
214
+ circuit_json_build_started_at: null,
215
+ circuit_json_build_completed_at: null,
216
+ circuit_json_build_logs: [],
217
+ circuit_json_build_error: "Circuit JSON build failed",
218
+ build_in_progress: false,
219
+ build_started_at: new Date().toISOString(),
220
+ build_completed_at: null,
221
+ build_error: "Build failed: compilation error",
222
+ build_error_last_updated_at: new Date().toISOString(),
223
+ build_logs: null,
224
+ preview_url: null,
225
+ branch_name: "feature/new-component",
226
+ commit_message: "Add broken component",
227
+ commit_author: "john.doe",
228
+ })
229
+
230
+ const res = await axios.get(
231
+ `/api/package_builds/get?package_build_id=${packageBuild.package_build_id}`,
232
+ )
233
+ expect(res.status).toBe(200)
234
+ expect(res.data.package_build).toBeDefined()
235
+ expect(res.data.package_build.package_build_id).toBe(
236
+ packageBuild.package_build_id,
237
+ )
238
+ expect(res.data.package_build.transpilation_error).toBe(
239
+ "Transpilation failed: syntax error",
240
+ )
241
+ expect(res.data.package_build.circuit_json_build_error).toBe(
242
+ "Circuit JSON build failed",
243
+ )
244
+ expect(res.data.package_build.build_error).toBe(
245
+ "Build failed: compilation error",
246
+ )
247
+ })
248
+
249
+ test("GET /api/package_builds/get - handles build in progress", async () => {
250
+ const { axios, db } = await getTestServer()
251
+ const { package: pkg } = await createTestPackage(axios)
252
+ const { package_release } = await createTestPackageRelease(
253
+ axios,
254
+ pkg.package_id,
255
+ )
256
+
257
+ const packageBuild = db.addPackageBuild({
258
+ package_release_id: package_release.package_release_id,
259
+ created_at: new Date().toISOString(),
260
+ transpilation_in_progress: true,
261
+ transpilation_started_at: new Date().toISOString(),
262
+ transpilation_completed_at: null,
263
+ transpilation_logs: ["Starting transpilation"],
264
+ transpilation_error: null,
265
+ circuit_json_build_in_progress: false,
266
+ circuit_json_build_started_at: null,
267
+ circuit_json_build_completed_at: null,
268
+ circuit_json_build_logs: [],
269
+ circuit_json_build_error: null,
270
+ build_in_progress: false,
271
+ build_started_at: null,
272
+ build_completed_at: null,
273
+ build_error: null,
274
+ build_error_last_updated_at: new Date().toISOString(),
275
+ build_logs: null,
276
+ preview_url: null,
277
+ branch_name: "main",
278
+ commit_message: "Building in progress",
279
+ commit_author: "john.doe",
280
+ })
281
+
282
+ const res = await axios.get(
283
+ `/api/package_builds/get?package_build_id=${packageBuild.package_build_id}`,
284
+ )
285
+ expect(res.status).toBe(200)
286
+ expect(res.data.package_build).toBeDefined()
287
+ expect(res.data.package_build.package_build_id).toBe(
288
+ packageBuild.package_build_id,
289
+ )
290
+ expect(res.data.package_build.transpilation_in_progress).toBe(true)
291
+ expect(res.data.package_build.transpilation_logs).toEqual([
292
+ "Starting transpilation",
293
+ ])
294
+ })