@tscircuit/fake-snippets 0.0.108 → 0.0.110

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 (203) hide show
  1. package/.github/workflows/bun-formatcheck.yml +2 -2
  2. package/.github/workflows/bun-pver-release.yml +3 -3
  3. package/.github/workflows/bun-test.yml +1 -1
  4. package/.github/workflows/bun-typecheck.yml +2 -2
  5. package/.github/workflows/update-snapshots.yml +1 -1
  6. package/README.md +4 -0
  7. package/api/generated-index.js +37 -3
  8. package/biome.json +2 -1
  9. package/bun-tests/fake-snippets-api/fixtures/get-test-server.ts +31 -3
  10. package/bun-tests/fake-snippets-api/fixtures/preload.ts +18 -0
  11. package/bun-tests/fake-snippets-api/routes/orgs/add_member.test.ts +26 -0
  12. package/bun-tests/fake-snippets-api/routes/orgs/create.test.ts +37 -0
  13. package/bun-tests/fake-snippets-api/routes/orgs/get.test.ts +52 -0
  14. package/bun-tests/fake-snippets-api/routes/orgs/list.test.ts +17 -0
  15. package/bun-tests/fake-snippets-api/routes/orgs/list_members.test.ts +23 -0
  16. package/bun-tests/fake-snippets-api/routes/orgs/remove_member.test.ts +81 -0
  17. package/bun-tests/fake-snippets-api/routes/orgs/update.test.ts +99 -0
  18. package/bun-tests/fake-snippets-api/routes/package_builds/get.test.ts +1 -1
  19. package/bun-tests/fake-snippets-api/routes/package_files/create.test.ts +15 -13
  20. package/bun-tests/fake-snippets-api/routes/package_files/create_or_update.test.ts +26 -24
  21. package/bun-tests/fake-snippets-api/routes/package_files/delete.test.ts +9 -9
  22. package/bun-tests/fake-snippets-api/routes/package_files/download.test.ts +4 -4
  23. package/bun-tests/fake-snippets-api/routes/package_files/get.test.ts +38 -28
  24. package/bun-tests/fake-snippets-api/routes/package_files/list.test.ts +23 -15
  25. package/bun-tests/fake-snippets-api/routes/package_releases/create.test.ts +33 -0
  26. package/bun-tests/fake-snippets-api/routes/package_releases/get.test.ts +4 -4
  27. package/bun-tests/fake-snippets-api/routes/package_releases/get_image_generation_fields.test.ts +38 -0
  28. package/bun-tests/fake-snippets-api/routes/packages/create.test.ts +19 -0
  29. package/bun-tests/fake-snippets-api/routes/packages/fork.test.ts +3 -4
  30. package/bun-tests/fake-snippets-api/routes/packages/get.test.ts +30 -0
  31. package/bun-tests/fake-snippets-api/routes/packages/images.test.ts +4 -2
  32. package/bun-tests/fake-snippets-api/routes/packages/list-1.test.ts +34 -0
  33. package/bun.lock +389 -450
  34. package/bunfig.toml +2 -1
  35. package/dist/bundle.js +1255 -625
  36. package/dist/index.d.ts +296 -4
  37. package/dist/index.js +325 -24
  38. package/dist/schema.d.ts +282 -1
  39. package/dist/schema.js +54 -2
  40. package/fake-snippets-api/lib/db/autoload-dev-packages.ts +31 -20
  41. package/fake-snippets-api/lib/db/db-client.ts +214 -3
  42. package/fake-snippets-api/lib/db/schema.ts +62 -0
  43. package/fake-snippets-api/lib/db/seed.ts +100 -0
  44. package/fake-snippets-api/lib/middleware/with-session-auth.ts +1 -1
  45. package/fake-snippets-api/lib/package_file/get-package-file-id-from-file-descriptor.ts +2 -2
  46. package/fake-snippets-api/lib/public-mapping/public-map-org.ts +32 -0
  47. package/fake-snippets-api/lib/public-mapping/public-map-package-build.ts +10 -0
  48. package/fake-snippets-api/lib/public-mapping/public-map-package-release.ts +17 -0
  49. package/fake-snippets-api/routes/api/orgs/add_member.ts +52 -0
  50. package/fake-snippets-api/routes/api/orgs/create.ts +46 -0
  51. package/fake-snippets-api/routes/api/orgs/get.ts +39 -0
  52. package/fake-snippets-api/routes/api/orgs/list.ts +31 -0
  53. package/fake-snippets-api/routes/api/orgs/list_members.ts +67 -0
  54. package/fake-snippets-api/routes/api/orgs/remove_member.ts +46 -0
  55. package/fake-snippets-api/routes/api/orgs/update.ts +93 -0
  56. package/fake-snippets-api/routes/api/package_files/get.ts +3 -6
  57. package/fake-snippets-api/routes/api/package_files/list.ts +7 -4
  58. package/fake-snippets-api/routes/api/packages/create.ts +54 -10
  59. package/fake-snippets-api/routes/api/packages/get.ts +23 -0
  60. package/fake-snippets-api/routes/api/packages/images/[owner_github_username]/[unscoped_name]/[view_format].ts +13 -11
  61. package/fake-snippets-api/routes/api/packages/list.ts +29 -2
  62. package/fake-snippets-api/routes/api/packages/update_ai_description.ts +37 -0
  63. package/package.json +27 -24
  64. package/renovate.json +1 -1
  65. package/scripts/generate-sitemap.ts +1 -1
  66. package/src/App.tsx +29 -10
  67. package/src/ContextProviders.tsx +25 -2
  68. package/src/components/CircuitJsonImportDialog.tsx +1 -1
  69. package/src/components/CmdKMenu.tsx +281 -247
  70. package/src/components/DownloadButtonAndMenu.tsx +133 -36
  71. package/src/components/FileSidebar.tsx +41 -50
  72. package/src/components/Footer.tsx +8 -10
  73. package/src/components/Header.tsx +19 -32
  74. package/src/components/Header2.tsx +16 -32
  75. package/src/components/HeaderDropdown.tsx +13 -8
  76. package/src/components/HeaderLogin.tsx +44 -16
  77. package/src/components/HiddenFilesDropdown.tsx +0 -2
  78. package/src/components/NotFound.tsx +5 -5
  79. package/src/components/PackageBreadcrumb.tsx +6 -12
  80. package/src/components/PackageCard.tsx +0 -1
  81. package/src/components/PackageSearchResults.tsx +1 -1
  82. package/src/components/PrefetchPageLink.tsx +7 -1
  83. package/src/components/ProfileRouter.tsx +32 -0
  84. package/src/components/SearchComponent.tsx +12 -8
  85. package/src/components/UserCard.tsx +80 -0
  86. package/src/components/ViewPackagePage/components/ShikiCodeViewer.tsx +20 -11
  87. package/src/components/ViewPackagePage/components/build-status.tsx +1 -1
  88. package/src/components/ViewPackagePage/components/important-files-view.tsx +174 -87
  89. package/src/components/ViewPackagePage/components/main-content-header.tsx +8 -4
  90. package/src/components/ViewPackagePage/components/main-content-view-selector.tsx +1 -2
  91. package/src/components/ViewPackagePage/components/mobile-sidebar.tsx +54 -20
  92. package/src/components/ViewPackagePage/components/package-header.tsx +26 -37
  93. package/src/components/ViewPackagePage/components/preview-image-squares.tsx +11 -19
  94. package/src/components/ViewPackagePage/components/repo-page-content.tsx +33 -25
  95. package/src/components/ViewPackagePage/components/sidebar-about-section.tsx +16 -10
  96. package/src/components/ViewPackagePage/components/sidebar-releases-section.tsx +11 -11
  97. package/src/components/ViewPackagePage/components/sidebar.tsx +0 -2
  98. package/src/components/ViewPackagePage/components/tab-views/files-view.tsx +18 -17
  99. package/src/components/ViewPackagePage/components/tab-views/pcb-view.tsx +1 -2
  100. package/src/components/ViewPackagePage/components/tab-views/schematic-view.tsx +2 -1
  101. package/src/components/ViewPackagePage/components/theme-toggle.tsx +0 -2
  102. package/src/components/ViewPackagePage/hooks/use-toast.tsx +0 -1
  103. package/src/components/dialogs/GitHubRepositorySelector.tsx +56 -49
  104. package/src/components/dialogs/edit-package-details-dialog.tsx +5 -6
  105. package/src/components/dialogs/import-component-dialog.tsx +16 -9
  106. package/src/components/dialogs/import-package-dialog.tsx +3 -2
  107. package/src/components/dialogs/new-package-save-prompt-dialog.tsx +190 -0
  108. package/src/components/organization/OrganizationCard.tsx +204 -0
  109. package/src/components/organization/OrganizationCardSkeleton.tsx +55 -0
  110. package/src/components/organization/OrganizationHeader.tsx +154 -0
  111. package/src/components/organization/OrganizationMembers.tsx +146 -0
  112. package/src/components/package-port/CodeAndPreview.tsx +32 -46
  113. package/src/components/package-port/CodeEditor.tsx +28 -31
  114. package/src/components/package-port/CodeEditorHeader.tsx +128 -63
  115. package/src/components/package-port/EditorNav.tsx +32 -49
  116. package/src/components/preview/ConnectedPackagesList.tsx +8 -8
  117. package/src/components/preview/ConnectedRepoOverview.tsx +102 -2
  118. package/src/components/preview/PackageReleasesDashboard.tsx +53 -36
  119. package/src/components/ui/tree-view.tsx +6 -3
  120. package/src/hooks/use-add-org-member-mutation.ts +51 -0
  121. package/src/hooks/use-create-org-mutation.ts +38 -0
  122. package/src/hooks/use-create-package-mutation.ts +3 -0
  123. package/src/hooks/use-current-package-id.ts +5 -30
  124. package/src/hooks/use-current-package-info.ts +29 -5
  125. package/src/hooks/use-current-package-release.ts +4 -3
  126. package/src/hooks/use-download-zip.ts +2 -2
  127. package/src/hooks/use-global-store.ts +6 -4
  128. package/src/hooks/use-jlcpcb-component-import.tsx +164 -0
  129. package/src/hooks/use-list-org-members.ts +27 -0
  130. package/src/hooks/use-list-user-orgs.ts +25 -0
  131. package/src/hooks/use-org-by-github-handle.ts +26 -0
  132. package/src/hooks/use-org.ts +24 -0
  133. package/src/hooks/use-organization.ts +42 -0
  134. package/src/hooks/use-package-as-snippet.ts +4 -2
  135. package/src/hooks/use-package-builds.ts +6 -2
  136. package/src/hooks/use-package-files.ts +5 -3
  137. package/src/hooks/use-package-release-by-id-or-version.ts +29 -20
  138. package/src/hooks/use-package-release-images.ts +105 -0
  139. package/src/hooks/use-package-release.ts +2 -2
  140. package/src/hooks/use-package-stars.ts +80 -4
  141. package/src/hooks/use-preview-images.ts +6 -3
  142. package/src/hooks/use-remove-org-member-mutation.ts +32 -0
  143. package/src/hooks/use-update-ai-description-mutation.ts +42 -0
  144. package/src/hooks/use-update-org-mutation.ts +41 -0
  145. package/src/hooks/use-warn-user-on-page-change.ts +71 -4
  146. package/src/hooks/useFileManagement.ts +183 -35
  147. package/src/hooks/useOptimizedPackageFilesLoader.ts +136 -0
  148. package/src/hooks/usePackageFilesLoader.ts +2 -2
  149. package/src/hooks/useUpdatePackageFilesMutation.ts +15 -1
  150. package/src/lib/download-fns/download-circuit-png.ts +11 -3
  151. package/src/lib/download-fns/download-gltf-from-circuit-json.ts +44 -0
  152. package/src/lib/download-fns/download-kicad-files.ts +12 -11
  153. package/src/lib/normalize-svg-for-tile.ts +50 -0
  154. package/src/lib/posthog.ts +11 -9
  155. package/src/lib/react-query-api-failure-tracking.ts +148 -0
  156. package/src/lib/sentry.ts +14 -0
  157. package/src/lib/templates/blank-circuit-board-template.ts +0 -4
  158. package/src/lib/ts-lib-cache.ts +122 -7
  159. package/src/lib/utils/checkIfManualEditsImported.ts +4 -4
  160. package/src/lib/utils/findTargetFile.ts +45 -10
  161. package/src/lib/utils/isComponentExported.ts +10 -0
  162. package/src/main.tsx +2 -1
  163. package/src/pages/authorize.tsx +0 -2
  164. package/src/pages/create-organization.tsx +168 -0
  165. package/src/pages/dashboard.tsx +38 -6
  166. package/src/pages/datasheet.tsx +1 -1
  167. package/src/pages/datasheets.tsx +3 -3
  168. package/src/pages/editor.tsx +4 -6
  169. package/src/pages/landing.tsx +6 -7
  170. package/src/pages/latest.tsx +3 -0
  171. package/src/pages/organization-profile.tsx +199 -0
  172. package/src/pages/organization-settings.tsx +566 -0
  173. package/src/pages/package-editor.tsx +21 -21
  174. package/src/pages/preview-release.tsx +76 -136
  175. package/src/pages/quickstart.tsx +159 -123
  176. package/src/pages/release-detail.tsx +119 -31
  177. package/src/pages/search.tsx +192 -57
  178. package/src/pages/settings-redirect.tsx +44 -0
  179. package/src/pages/trending.tsx +29 -20
  180. package/src/pages/user-profile.tsx +58 -7
  181. package/src/pages/view-package.tsx +21 -26
  182. package/vite.config.ts +9 -0
  183. package/fake-snippets-api/routes/api/autocomplete/create_autocomplete.ts +0 -133
  184. package/src/components/Footer2.tsx +0 -100
  185. package/src/components/JLCPCBImportDialog.tsx +0 -280
  186. package/src/components/PackageBuildsPage/LogContent.tsx +0 -72
  187. package/src/components/PackageBuildsPage/PackageBuildDetailsPage.tsx +0 -115
  188. package/src/components/PackageBuildsPage/build-preview-content.tsx +0 -27
  189. package/src/components/PackageBuildsPage/collapsible-section.tsx +0 -63
  190. package/src/components/PackageBuildsPage/package-build-details-panel.tsx +0 -166
  191. package/src/components/PackageBuildsPage/package-build-header.tsx +0 -79
  192. package/src/components/PageSearchComponent.tsx +0 -148
  193. package/src/components/ShippingInformationForm.tsx +0 -423
  194. package/src/components/StaticViewSnippetHeader.tsx +0 -70
  195. package/src/components/ViewPackagePage/components/file-explorer.tsx +0 -67
  196. package/src/components/ViewPackagePage/components/readme-view.tsx +0 -58
  197. package/src/components/ViewPackagePage/components/repo-header-button.tsx +0 -36
  198. package/src/components/ViewPackagePage/components/repo-header.tsx +0 -4
  199. package/src/components/ViewPackagePage/components/sidebar-contributors-section.tsx +0 -31
  200. package/src/components/ViewSnippetHeader.tsx +0 -181
  201. package/src/components/ui/input-otp.tsx +0 -69
  202. package/src/pages/package-builds.tsx +0 -33
  203. package/src/pages/settings.tsx +0 -25
@@ -10,7 +10,7 @@ import { useAxios } from "@/hooks/use-axios"
10
10
  import { useGlobalStore } from "@/hooks/use-global-store"
11
11
  import { useApiBaseUrl } from "@/hooks/use-packages-base-api-url"
12
12
  import { GitHubLogoIcon } from "@radix-ui/react-icons"
13
- import type { Package } from "fake-snippets-api/lib/db/schema"
13
+ import type { Package, PublicOrgSchema } from "fake-snippets-api/lib/db/schema"
14
14
  import type React from "react"
15
15
  import { useState } from "react"
16
16
  import { useQuery } from "react-query"
@@ -23,21 +23,25 @@ import {
23
23
  SelectTrigger,
24
24
  SelectValue,
25
25
  } from "@/components/ui/select"
26
- import { Box, Star } from "lucide-react"
26
+ import { Box, Star, Building2 } from "lucide-react"
27
27
  import { PackageCardSkeleton } from "@/components/PackageCardSkeleton"
28
28
  import { ConnectedPackagesList } from "@/components/preview/ConnectedPackagesList"
29
+ import { useListUserOrgs } from "@/hooks/use-list-user-orgs"
30
+ import { OrganizationCard } from "@/components/organization/OrganizationCard"
29
31
 
30
32
  export const UserProfilePage = () => {
31
33
  const { username } = useParams()
32
34
  const axios = useAxios()
35
+ const { data: organizations } = useListUserOrgs(username)
33
36
  const [searchQuery, setSearchQuery] = useState("")
34
37
  const [activeTab, setActiveTab] = useState("all")
35
- const [filter, setFilter] = useState("most-recent") // Changed default from "newest" to "most-recent"
38
+ const [filter, setFilter] = useState("most-recent")
36
39
  const session = useGlobalStore((s) => s.session)
37
40
  const {
38
41
  data: account,
39
42
  error: accountError,
40
43
  isLoading: isLoadingAccount,
44
+ isFetched: isFetchedAccount,
41
45
  } = useQuery<
42
46
  { account: { github_username: string } },
43
47
  Error & { status: number }
@@ -98,6 +102,10 @@ export const UserProfilePage = () => {
98
102
 
99
103
  const baseUrl = useApiBaseUrl()
100
104
 
105
+ if (!isFetchedAccount) {
106
+ return null
107
+ }
108
+
101
109
  if (accountError) {
102
110
  return <NotFoundPage heading="User Not Found" />
103
111
  }
@@ -145,8 +153,11 @@ export const UserProfilePage = () => {
145
153
  <div className="container mx-auto px-4 py-8">
146
154
  <div className="flex items-center gap-4 mb-6">
147
155
  <Avatar className="h-16 w-16">
148
- <AvatarImage src={`https://github.com/${githubUsername}.png`} />
149
- <AvatarFallback>
156
+ <AvatarImage
157
+ src={`https://github.com/${githubUsername}.png`}
158
+ draggable={false}
159
+ />
160
+ <AvatarFallback className="select-none">
150
161
  {githubUsername?.[0]?.toUpperCase()}
151
162
  </AvatarFallback>
152
163
  </Avatar>
@@ -174,10 +185,17 @@ export const UserProfilePage = () => {
174
185
  </Button>
175
186
  </a>
176
187
  </div>
177
- <Tabs defaultValue="all" onValueChange={setActiveTab} className="mb-4">
188
+ <Tabs
189
+ defaultValue="all"
190
+ onValueChange={setActiveTab}
191
+ className="mb-4 select-none overflow-x-auto no-scrollbar"
192
+ >
178
193
  <TabsList>
179
194
  <TabsTrigger value="all">Packages</TabsTrigger>
180
195
  <TabsTrigger value="starred">Starred Packages</TabsTrigger>
196
+ {organizations && organizations.length > 0 && (
197
+ <TabsTrigger value="organizations">Organizations</TabsTrigger>
198
+ )}
181
199
  {isCurrentUserProfile &&
182
200
  (
183
201
  userPackages?.filter((x) => Boolean(x.github_repo_full_name)) ??
@@ -217,6 +235,39 @@ export const UserProfilePage = () => {
217
235
  []
218
236
  }
219
237
  />
238
+ ) : activeTab === "organizations" ? (
239
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
240
+ {organizations && organizations.length > 0 ? (
241
+ organizations
242
+ ?.filter((o) => {
243
+ if (!isCurrentUserProfile && o.is_personal_org) {
244
+ return false
245
+ } else {
246
+ return true
247
+ }
248
+ })
249
+ .map((org: PublicOrgSchema) => (
250
+ <OrganizationCard
251
+ key={org.org_id}
252
+ organization={org}
253
+ withLink={true}
254
+ showStats={true}
255
+ showMembers={true}
256
+ className="p-3"
257
+ />
258
+ ))
259
+ ) : (
260
+ <div className="col-span-full flex justify-center">
261
+ <div className="flex flex-col items-center py-12 text-gray-500">
262
+ <Building2 className="mb-2" size={24} />
263
+ <span className="text-lg font-medium">No organizations</span>
264
+ <span className="text-sm">
265
+ You're not a member of any organizations yet.
266
+ </span>
267
+ </div>
268
+ </div>
269
+ )}
270
+ </div>
220
271
  ) : isLoading ? (
221
272
  <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
222
273
  {[...Array(6)].map((_, i) => (
@@ -240,7 +291,7 @@ export const UserProfilePage = () => {
240
291
  ))
241
292
  ) : (
242
293
  <div className="col-span-full flex justify-center">
243
- <div className="flex flex-col items-center py-12 text-gray-500">
294
+ <div className="flex flex-col items-center py-20 text-gray-500">
244
295
  {activeTab === "starred" ? (
245
296
  <>
246
297
  <Star className="mb-2" size={24} />
@@ -1,43 +1,37 @@
1
1
  import RepoPageContent from "@/components/ViewPackagePage/components/repo-page-content"
2
2
  import { usePackageFiles } from "@/hooks/use-package-files"
3
- import { usePackageRelease } from "@/hooks/use-package-release"
3
+ import { useCurrentPackageRelease } from "@/hooks/use-current-package-release"
4
4
  import { useLocation, useParams } from "wouter"
5
5
  import { Helmet } from "react-helmet-async"
6
6
  import { useEffect, useState } from "react"
7
7
  import NotFoundPage from "./404"
8
- import { useCurrentPackageId } from "@/hooks/use-current-package-id"
9
- import { usePackage } from "@/hooks/use-package"
8
+ import { usePackageByName } from "@/hooks/use-package-by-package-name"
10
9
 
11
10
  export const ViewPackagePage = () => {
12
- const {
13
- packageId,
14
- error: packageIdError,
15
- isLoading: isLoadingPackageId,
16
- } = useCurrentPackageId()
17
- const { data: packageInfo } = usePackage(packageId)
18
11
  const { author, packageName } = useParams()
12
+ const packageNameFull = `${author}/${packageName}`
19
13
  const [, setLocation] = useLocation()
14
+
15
+ // Get package data directly by name - this will also cache by ID
16
+ const {
17
+ data: packageInfo,
18
+ error: packageError,
19
+ isLoading: isLoadingPackage,
20
+ } = usePackageByName(packageNameFull)
20
21
  const {
21
- data: packageRelease,
22
+ packageRelease,
22
23
  error: packageReleaseError,
23
24
  isLoading: isLoadingPackageRelease,
24
- } = usePackageRelease(
25
- {
26
- is_latest: true,
27
- package_name: `${author}/${packageName}`,
28
- include_ai_review: true,
29
- },
30
- {
31
- refetchInterval: (data) =>
32
- data?.ai_review_requested && !data.ai_review_text ? 2000 : false,
33
- },
34
- )
25
+ } = useCurrentPackageRelease({
26
+ include_ai_review: true,
27
+ refetchInterval: (data) =>
28
+ data?.ai_review_requested && !data.ai_review_text ? 2000 : false,
29
+ })
35
30
 
36
- const { data: packageFiles } = usePackageFiles(
37
- packageRelease?.package_release_id,
38
- )
31
+ const { data: packageFiles, isFetched: arePackageFilesFetched } =
32
+ usePackageFiles(packageRelease?.package_release_id)
39
33
 
40
- if (!isLoadingPackageId && packageIdError) {
34
+ if (!isLoadingPackage && packageError) {
41
35
  return <NotFoundPage heading="Package Not Found" />
42
36
  }
43
37
 
@@ -51,7 +45,8 @@ export const ViewPackagePage = () => {
51
45
  <title>{`${author}/${packageName} - tscircuit`}</title>
52
46
  </Helmet>
53
47
  <RepoPageContent
54
- packageFiles={packageFiles as any}
48
+ packageFiles={packageFiles ?? []}
49
+ arePackageFilesFetched={arePackageFilesFetched}
55
50
  packageInfo={packageInfo}
56
51
  packageRelease={packageRelease}
57
52
  importantFilePaths={["README.md", "LICENSE", "package.json"]}
package/vite.config.ts CHANGED
@@ -183,11 +183,18 @@ export default defineConfig(async (): Promise<UserConfig> => {
183
183
  }
184
184
  }
185
185
 
186
+ if (process.env.SENTRY_DSN) {
187
+ process.env.VITE_SENTRY_DSN = process.env.SENTRY_DSN
188
+ }
189
+
186
190
  return {
187
191
  plugins,
188
192
  define: {
189
193
  global: {},
190
194
  },
195
+ optimizeDeps: {
196
+ exclude: ["@resvg/resvg-js", "@resvg/resvg-js-darwin-arm64"],
197
+ },
191
198
  server: {
192
199
  host: "127.0.0.1",
193
200
  proxy: proxyConfig,
@@ -211,11 +218,13 @@ export default defineConfig(async (): Promise<UserConfig> => {
211
218
  main: path.resolve(__dirname, "index.html"),
212
219
  landing: path.resolve(__dirname, "landing.html"),
213
220
  },
221
+ external: ["@resvg/resvg-js"],
214
222
  },
215
223
  },
216
224
  ssr: {
217
225
  noExternal: ["react-dom/client"],
218
226
  target: "node",
227
+ external: ["@resvg/resvg-js", "@resvg/resvg-js-darwin-arm64"],
219
228
  },
220
229
  resolve: {
221
230
  alias: {
@@ -1,133 +0,0 @@
1
- import { withRouteSpec } from "fake-snippets-api/lib/middleware/with-winter-spec"
2
- import { z } from "zod"
3
- import OpenAI from "openai"
4
-
5
- // Lazy-loaded client instance
6
- let openai: OpenAI | null = null
7
- let cachedReadme: string | null = null
8
-
9
- function getOpenAIClient() {
10
- const apiKey = process.env.VITE_OPENROUTER_API_KEY
11
- if (!apiKey) {
12
- throw new Error("Missing Api Key in env")
13
- }
14
-
15
- if (!openai) {
16
- openai = new OpenAI({
17
- apiKey,
18
- baseURL: "https://openrouter.ai/api/v1",
19
- defaultHeaders: {
20
- "HTTP-Referer": "https://tscircuit.com",
21
- "X-Title": "TSCircuit Editor",
22
- },
23
- })
24
- }
25
-
26
- return openai
27
- }
28
-
29
- // Cache README
30
- async function getCachedReadme(): Promise<string> {
31
- if (cachedReadme !== null) return cachedReadme
32
- const res = await fetch(
33
- "https://raw.githubusercontent.com/tscircuit/props/main/README.md",
34
- )
35
- if (!res.ok) {
36
- throw new Error(`Failed to fetch README: ${res.status}`)
37
- }
38
- cachedReadme = await res.text()
39
- return cachedReadme
40
- }
41
-
42
- async function completion(
43
- openai: OpenAI,
44
- readmeContent: string,
45
- prefix: string,
46
- suffix: string,
47
- model = "openai/gpt-4.1-mini",
48
- language?: string,
49
- ) {
50
- const systemMessage = `You are an expert ${language ? language + " " : ""}programmer working in a TSX (TypeScript + React JSX) environment.
51
-
52
- Below is the README.md for the available components. You MUST use this to determine which components and props are valid.
53
- Only use components explicitly documented under Available Components in the README. Never invent or guess new components. If the user partially types a component that does not exist in the README, do NOT try to complete it.
54
-
55
- ===== README.md START =====
56
- ${readmeContent}
57
- ===== README.md END =====
58
-
59
- Special instruction for the <chip> component:
60
- - Do NOT add chip as a prop (e.g., <chip chip="..."> is invalid).
61
- - Always use this format:
62
- <chip name="U<number>" footprint="<valid footprint>" pinLabels={{}} pcbX={0} pcbY={0} schX={0} schY={0} />
63
- - Determine the next sequential name automatically: e.g. U1, U2, U3.
64
- - Only use valid footprints and pinLabels from the README.
65
- - Some components like <netlabel> do not have a 'name' prop — do not add it for those.
66
-
67
- STRICT rules:
68
- - If partial like "<capa", only append remaining "citor". Never repeat letters.
69
- - If input is "<capacitor", add only props, never repeat tag.
70
- - Always produce exactly one JSX component, starting with "<" if needed.
71
- - If partial doesn’t match any valid component, output nothing.
72
- - Never output two JSX elements. Always end with exactly one "/>".
73
- - Never add duplicate closing "/>".
74
- - Never output the component name as a prop.
75
- - Never add whitespace before your completion.
76
- - If the input is exactly "<", then start with the component name directly (like "resistor ... />") without adding another "<".
77
- - So that the final result is "<resistor ... />", not "<<resistor ... />".
78
- - Never produce a double "<".
79
-
80
- Examples:
81
- - Input: "<FILL_ME>"
82
- Output: <resistor name="R1" footprint="0603" pcbX={5} pcbY={7} schX={1} schY={2} resistance={1000} />
83
- - Input: "<ca<FILL_ME>"
84
- Output: pacitor name="C1" footprint="0805" pcbX={10} pcbY={15} schX={3} schY={4} />
85
- - Input: "<chip<FILL_ME>"
86
- Output: name="U1" footprint="SOIC-8" pinLabels={{}} pcbX={0} pcbY={0} schX={0} schY={0} />
87
- - Input: "<netl<FILL_ME>"
88
- Output: abel name="N1" />
89
- - NEVER output: <capacitor capacitor ... /> or <netnet ... />
90
- - Input: "<"
91
- Output: resistor name="R1" footprint="0603" pcbX={5} pcbY={7} schX={1} schY={2} resistance={1000} />
92
- - Input: "<ca"
93
- Output: pacitor name="C1" footprint="0805" pcbX={10} pcbY={15} schX={3} schY={4} />
94
- - Input: "<capacitor"
95
- Output: capacitance="1000pF" footprint="0805" name="C1" pcbX={10} pcbY={15} schX={3} schY={4} />`
96
-
97
- const chatCompletion = await openai.chat.completions.create({
98
- messages: [
99
- { role: "system", content: systemMessage },
100
- { role: "user", content: `${prefix}<FILL_ME>${suffix}` },
101
- ],
102
- model,
103
- })
104
-
105
- return chatCompletion.choices[0].message?.content ?? ""
106
- }
107
- export default withRouteSpec({
108
- methods: ["POST"],
109
- auth: "session", // ✅ Require user to be signed in
110
- jsonBody: z.object({
111
- prefix: z.string(),
112
- suffix: z.string(),
113
- model: z.string().optional(),
114
- language: z.string().optional(),
115
- }),
116
- jsonResponse: z.object({
117
- prediction: z.string(),
118
- }),
119
- })(async (req, ctx) => {
120
- const openai = getOpenAIClient()
121
- const { prefix, suffix, model, language } = req.jsonBody
122
-
123
- const readmeContent = await getCachedReadme()
124
- const predictionResult = await completion(
125
- openai,
126
- readmeContent,
127
- prefix,
128
- suffix,
129
- model,
130
- language,
131
- )
132
- return ctx.json({ prediction: predictionResult })
133
- })
@@ -1,100 +0,0 @@
1
- import { Button } from "@/components/ui/button"
2
- import { Card, CardContent } from "@/components/ui/card"
3
- import { Badge } from "@/components/ui/badge"
4
- import {
5
- Accordion,
6
- AccordionContent,
7
- AccordionItem,
8
- AccordionTrigger,
9
- } from "@/components/ui/accordion"
10
- import {
11
- CircuitBoard,
12
- Cpu,
13
- Layers,
14
- CloudLightningIcon as Lightning,
15
- Maximize2,
16
- Zap,
17
- } from "lucide-react"
18
- import { Link } from "wouter"
19
- import { Header2 } from "@/components/Header2"
20
-
21
- export const Footer2 = () => (
22
- <footer className="w-full py-6 bg-background">
23
- <div className="container px-4 md:px-6 mx-auto">
24
- <div className="grid gap-8 md:grid-cols-2 lg:grid-cols-4">
25
- <div className="space-y-4">
26
- <div className="flex items-center gap-2">
27
- <CircuitBoard className="h-6 w-6" />
28
- <span className="text-lg font-bold">tscircuit</span>
29
- </div>
30
- <p className="text-sm text-muted-foreground">
31
- Transforming electronic design with AI-powered tools.
32
- </p>
33
- </div>
34
- <div className="space-y-4">
35
- <h4 className="text-sm font-bold">Product</h4>
36
- <ul className="space-y-2 text-sm">
37
- <li>
38
- <Link className="text-muted-foreground hover:underline" href="#">
39
- Features
40
- </Link>
41
- </li>
42
- <li>
43
- <Link className="text-muted-foreground hover:underline" href="#">
44
- Pricing
45
- </Link>
46
- </li>
47
- <li>
48
- <Link className="text-muted-foreground hover:underline" href="#">
49
- Tutorials
50
- </Link>
51
- </li>
52
- </ul>
53
- </div>
54
- <div className="space-y-4">
55
- <h4 className="text-sm font-bold">Company</h4>
56
- <ul className="space-y-2 text-sm">
57
- <li>
58
- <Link className="text-muted-foreground hover:underline" href="#">
59
- About
60
- </Link>
61
- </li>
62
- <li>
63
- <Link className="text-muted-foreground hover:underline" href="#">
64
- Blog
65
- </Link>
66
- </li>
67
- <li>
68
- <Link className="text-muted-foreground hover:underline" href="#">
69
- Careers
70
- </Link>
71
- </li>
72
- </ul>
73
- </div>
74
- <div className="space-y-4">
75
- <h4 className="text-sm font-bold">Legal</h4>
76
- <ul className="space-y-2 text-sm">
77
- <li>
78
- <Link className="text-muted-foreground hover:underline" href="#">
79
- Privacy
80
- </Link>
81
- </li>
82
- <li>
83
- <Link className="text-muted-foreground hover:underline" href="#">
84
- Terms
85
- </Link>
86
- </li>
87
- <li>
88
- <Link className="text-muted-foreground hover:underline" href="#">
89
- Cookie Policy
90
- </Link>
91
- </li>
92
- </ul>
93
- </div>
94
- </div>
95
- <div className="mt-8 border-t pt-8 text-center text-sm text-muted-foreground">
96
- © {new Date().getFullYear()} tscircuit. All rights reserved.
97
- </div>
98
- </div>
99
- </footer>
100
- )