@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.
- package/.github/workflows/bun-formatcheck.yml +2 -2
- package/.github/workflows/bun-pver-release.yml +3 -3
- package/.github/workflows/bun-test.yml +1 -1
- package/.github/workflows/bun-typecheck.yml +2 -2
- package/.github/workflows/update-snapshots.yml +1 -1
- package/README.md +4 -0
- package/api/generated-index.js +37 -3
- package/biome.json +2 -1
- package/bun-tests/fake-snippets-api/fixtures/get-test-server.ts +31 -3
- package/bun-tests/fake-snippets-api/fixtures/preload.ts +18 -0
- package/bun-tests/fake-snippets-api/routes/orgs/add_member.test.ts +26 -0
- package/bun-tests/fake-snippets-api/routes/orgs/create.test.ts +37 -0
- package/bun-tests/fake-snippets-api/routes/orgs/get.test.ts +52 -0
- package/bun-tests/fake-snippets-api/routes/orgs/list.test.ts +17 -0
- package/bun-tests/fake-snippets-api/routes/orgs/list_members.test.ts +23 -0
- package/bun-tests/fake-snippets-api/routes/orgs/remove_member.test.ts +81 -0
- package/bun-tests/fake-snippets-api/routes/orgs/update.test.ts +99 -0
- package/bun-tests/fake-snippets-api/routes/package_builds/get.test.ts +1 -1
- package/bun-tests/fake-snippets-api/routes/package_files/create.test.ts +15 -13
- package/bun-tests/fake-snippets-api/routes/package_files/create_or_update.test.ts +26 -24
- package/bun-tests/fake-snippets-api/routes/package_files/delete.test.ts +9 -9
- package/bun-tests/fake-snippets-api/routes/package_files/download.test.ts +4 -4
- package/bun-tests/fake-snippets-api/routes/package_files/get.test.ts +38 -28
- package/bun-tests/fake-snippets-api/routes/package_files/list.test.ts +23 -15
- package/bun-tests/fake-snippets-api/routes/package_releases/create.test.ts +33 -0
- package/bun-tests/fake-snippets-api/routes/package_releases/get.test.ts +4 -4
- package/bun-tests/fake-snippets-api/routes/package_releases/get_image_generation_fields.test.ts +38 -0
- package/bun-tests/fake-snippets-api/routes/packages/create.test.ts +19 -0
- package/bun-tests/fake-snippets-api/routes/packages/fork.test.ts +3 -4
- package/bun-tests/fake-snippets-api/routes/packages/get.test.ts +30 -0
- package/bun-tests/fake-snippets-api/routes/packages/images.test.ts +4 -2
- package/bun-tests/fake-snippets-api/routes/packages/list-1.test.ts +34 -0
- package/bun.lock +389 -450
- package/bunfig.toml +2 -1
- package/dist/bundle.js +1255 -625
- package/dist/index.d.ts +296 -4
- package/dist/index.js +325 -24
- package/dist/schema.d.ts +282 -1
- package/dist/schema.js +54 -2
- package/fake-snippets-api/lib/db/autoload-dev-packages.ts +31 -20
- package/fake-snippets-api/lib/db/db-client.ts +214 -3
- package/fake-snippets-api/lib/db/schema.ts +62 -0
- package/fake-snippets-api/lib/db/seed.ts +100 -0
- package/fake-snippets-api/lib/middleware/with-session-auth.ts +1 -1
- package/fake-snippets-api/lib/package_file/get-package-file-id-from-file-descriptor.ts +2 -2
- package/fake-snippets-api/lib/public-mapping/public-map-org.ts +32 -0
- package/fake-snippets-api/lib/public-mapping/public-map-package-build.ts +10 -0
- package/fake-snippets-api/lib/public-mapping/public-map-package-release.ts +17 -0
- package/fake-snippets-api/routes/api/orgs/add_member.ts +52 -0
- package/fake-snippets-api/routes/api/orgs/create.ts +46 -0
- package/fake-snippets-api/routes/api/orgs/get.ts +39 -0
- package/fake-snippets-api/routes/api/orgs/list.ts +31 -0
- package/fake-snippets-api/routes/api/orgs/list_members.ts +67 -0
- package/fake-snippets-api/routes/api/orgs/remove_member.ts +46 -0
- package/fake-snippets-api/routes/api/orgs/update.ts +93 -0
- package/fake-snippets-api/routes/api/package_files/get.ts +3 -6
- package/fake-snippets-api/routes/api/package_files/list.ts +7 -4
- package/fake-snippets-api/routes/api/packages/create.ts +54 -10
- package/fake-snippets-api/routes/api/packages/get.ts +23 -0
- package/fake-snippets-api/routes/api/packages/images/[owner_github_username]/[unscoped_name]/[view_format].ts +13 -11
- package/fake-snippets-api/routes/api/packages/list.ts +29 -2
- package/fake-snippets-api/routes/api/packages/update_ai_description.ts +37 -0
- package/package.json +27 -24
- package/renovate.json +1 -1
- package/scripts/generate-sitemap.ts +1 -1
- package/src/App.tsx +29 -10
- package/src/ContextProviders.tsx +25 -2
- package/src/components/CircuitJsonImportDialog.tsx +1 -1
- package/src/components/CmdKMenu.tsx +281 -247
- package/src/components/DownloadButtonAndMenu.tsx +133 -36
- package/src/components/FileSidebar.tsx +41 -50
- package/src/components/Footer.tsx +8 -10
- package/src/components/Header.tsx +19 -32
- package/src/components/Header2.tsx +16 -32
- package/src/components/HeaderDropdown.tsx +13 -8
- package/src/components/HeaderLogin.tsx +44 -16
- package/src/components/HiddenFilesDropdown.tsx +0 -2
- package/src/components/NotFound.tsx +5 -5
- package/src/components/PackageBreadcrumb.tsx +6 -12
- package/src/components/PackageCard.tsx +0 -1
- package/src/components/PackageSearchResults.tsx +1 -1
- package/src/components/PrefetchPageLink.tsx +7 -1
- package/src/components/ProfileRouter.tsx +32 -0
- package/src/components/SearchComponent.tsx +12 -8
- package/src/components/UserCard.tsx +80 -0
- package/src/components/ViewPackagePage/components/ShikiCodeViewer.tsx +20 -11
- package/src/components/ViewPackagePage/components/build-status.tsx +1 -1
- package/src/components/ViewPackagePage/components/important-files-view.tsx +174 -87
- package/src/components/ViewPackagePage/components/main-content-header.tsx +8 -4
- package/src/components/ViewPackagePage/components/main-content-view-selector.tsx +1 -2
- package/src/components/ViewPackagePage/components/mobile-sidebar.tsx +54 -20
- package/src/components/ViewPackagePage/components/package-header.tsx +26 -37
- package/src/components/ViewPackagePage/components/preview-image-squares.tsx +11 -19
- package/src/components/ViewPackagePage/components/repo-page-content.tsx +33 -25
- package/src/components/ViewPackagePage/components/sidebar-about-section.tsx +16 -10
- package/src/components/ViewPackagePage/components/sidebar-releases-section.tsx +11 -11
- package/src/components/ViewPackagePage/components/sidebar.tsx +0 -2
- package/src/components/ViewPackagePage/components/tab-views/files-view.tsx +18 -17
- package/src/components/ViewPackagePage/components/tab-views/pcb-view.tsx +1 -2
- package/src/components/ViewPackagePage/components/tab-views/schematic-view.tsx +2 -1
- package/src/components/ViewPackagePage/components/theme-toggle.tsx +0 -2
- package/src/components/ViewPackagePage/hooks/use-toast.tsx +0 -1
- package/src/components/dialogs/GitHubRepositorySelector.tsx +56 -49
- package/src/components/dialogs/edit-package-details-dialog.tsx +5 -6
- package/src/components/dialogs/import-component-dialog.tsx +16 -9
- package/src/components/dialogs/import-package-dialog.tsx +3 -2
- package/src/components/dialogs/new-package-save-prompt-dialog.tsx +190 -0
- package/src/components/organization/OrganizationCard.tsx +204 -0
- package/src/components/organization/OrganizationCardSkeleton.tsx +55 -0
- package/src/components/organization/OrganizationHeader.tsx +154 -0
- package/src/components/organization/OrganizationMembers.tsx +146 -0
- package/src/components/package-port/CodeAndPreview.tsx +32 -46
- package/src/components/package-port/CodeEditor.tsx +28 -31
- package/src/components/package-port/CodeEditorHeader.tsx +128 -63
- package/src/components/package-port/EditorNav.tsx +32 -49
- package/src/components/preview/ConnectedPackagesList.tsx +8 -8
- package/src/components/preview/ConnectedRepoOverview.tsx +102 -2
- package/src/components/preview/PackageReleasesDashboard.tsx +53 -36
- package/src/components/ui/tree-view.tsx +6 -3
- package/src/hooks/use-add-org-member-mutation.ts +51 -0
- package/src/hooks/use-create-org-mutation.ts +38 -0
- package/src/hooks/use-create-package-mutation.ts +3 -0
- package/src/hooks/use-current-package-id.ts +5 -30
- package/src/hooks/use-current-package-info.ts +29 -5
- package/src/hooks/use-current-package-release.ts +4 -3
- package/src/hooks/use-download-zip.ts +2 -2
- package/src/hooks/use-global-store.ts +6 -4
- package/src/hooks/use-jlcpcb-component-import.tsx +164 -0
- package/src/hooks/use-list-org-members.ts +27 -0
- package/src/hooks/use-list-user-orgs.ts +25 -0
- package/src/hooks/use-org-by-github-handle.ts +26 -0
- package/src/hooks/use-org.ts +24 -0
- package/src/hooks/use-organization.ts +42 -0
- package/src/hooks/use-package-as-snippet.ts +4 -2
- package/src/hooks/use-package-builds.ts +6 -2
- package/src/hooks/use-package-files.ts +5 -3
- package/src/hooks/use-package-release-by-id-or-version.ts +29 -20
- package/src/hooks/use-package-release-images.ts +105 -0
- package/src/hooks/use-package-release.ts +2 -2
- package/src/hooks/use-package-stars.ts +80 -4
- package/src/hooks/use-preview-images.ts +6 -3
- package/src/hooks/use-remove-org-member-mutation.ts +32 -0
- package/src/hooks/use-update-ai-description-mutation.ts +42 -0
- package/src/hooks/use-update-org-mutation.ts +41 -0
- package/src/hooks/use-warn-user-on-page-change.ts +71 -4
- package/src/hooks/useFileManagement.ts +183 -35
- package/src/hooks/useOptimizedPackageFilesLoader.ts +136 -0
- package/src/hooks/usePackageFilesLoader.ts +2 -2
- package/src/hooks/useUpdatePackageFilesMutation.ts +15 -1
- package/src/lib/download-fns/download-circuit-png.ts +11 -3
- package/src/lib/download-fns/download-gltf-from-circuit-json.ts +44 -0
- package/src/lib/download-fns/download-kicad-files.ts +12 -11
- package/src/lib/normalize-svg-for-tile.ts +50 -0
- package/src/lib/posthog.ts +11 -9
- package/src/lib/react-query-api-failure-tracking.ts +148 -0
- package/src/lib/sentry.ts +14 -0
- package/src/lib/templates/blank-circuit-board-template.ts +0 -4
- package/src/lib/ts-lib-cache.ts +122 -7
- package/src/lib/utils/checkIfManualEditsImported.ts +4 -4
- package/src/lib/utils/findTargetFile.ts +45 -10
- package/src/lib/utils/isComponentExported.ts +10 -0
- package/src/main.tsx +2 -1
- package/src/pages/authorize.tsx +0 -2
- package/src/pages/create-organization.tsx +168 -0
- package/src/pages/dashboard.tsx +38 -6
- package/src/pages/datasheet.tsx +1 -1
- package/src/pages/datasheets.tsx +3 -3
- package/src/pages/editor.tsx +4 -6
- package/src/pages/landing.tsx +6 -7
- package/src/pages/latest.tsx +3 -0
- package/src/pages/organization-profile.tsx +199 -0
- package/src/pages/organization-settings.tsx +566 -0
- package/src/pages/package-editor.tsx +21 -21
- package/src/pages/preview-release.tsx +76 -136
- package/src/pages/quickstart.tsx +159 -123
- package/src/pages/release-detail.tsx +119 -31
- package/src/pages/search.tsx +192 -57
- package/src/pages/settings-redirect.tsx +44 -0
- package/src/pages/trending.tsx +29 -20
- package/src/pages/user-profile.tsx +58 -7
- package/src/pages/view-package.tsx +21 -26
- package/vite.config.ts +9 -0
- package/fake-snippets-api/routes/api/autocomplete/create_autocomplete.ts +0 -133
- package/src/components/Footer2.tsx +0 -100
- package/src/components/JLCPCBImportDialog.tsx +0 -280
- package/src/components/PackageBuildsPage/LogContent.tsx +0 -72
- package/src/components/PackageBuildsPage/PackageBuildDetailsPage.tsx +0 -115
- package/src/components/PackageBuildsPage/build-preview-content.tsx +0 -27
- package/src/components/PackageBuildsPage/collapsible-section.tsx +0 -63
- package/src/components/PackageBuildsPage/package-build-details-panel.tsx +0 -166
- package/src/components/PackageBuildsPage/package-build-header.tsx +0 -79
- package/src/components/PageSearchComponent.tsx +0 -148
- package/src/components/ShippingInformationForm.tsx +0 -423
- package/src/components/StaticViewSnippetHeader.tsx +0 -70
- package/src/components/ViewPackagePage/components/file-explorer.tsx +0 -67
- package/src/components/ViewPackagePage/components/readme-view.tsx +0 -58
- package/src/components/ViewPackagePage/components/repo-header-button.tsx +0 -36
- package/src/components/ViewPackagePage/components/repo-header.tsx +0 -4
- package/src/components/ViewPackagePage/components/sidebar-contributors-section.tsx +0 -31
- package/src/components/ViewSnippetHeader.tsx +0 -181
- package/src/components/ui/input-otp.tsx +0 -69
- package/src/pages/package-builds.tsx +0 -33
- 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")
|
|
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
|
|
149
|
-
|
|
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
|
|
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-
|
|
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 {
|
|
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 {
|
|
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
|
-
|
|
22
|
+
packageRelease,
|
|
22
23
|
error: packageReleaseError,
|
|
23
24
|
isLoading: isLoadingPackageRelease,
|
|
24
|
-
} =
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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 } =
|
|
37
|
-
packageRelease?.package_release_id
|
|
38
|
-
)
|
|
31
|
+
const { data: packageFiles, isFetched: arePackageFilesFetched } =
|
|
32
|
+
usePackageFiles(packageRelease?.package_release_id)
|
|
39
33
|
|
|
40
|
-
if (!
|
|
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
|
|
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
|
-
)
|