@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
@@ -0,0 +1,41 @@
1
+ import * as ZT from "fake-snippets-api/lib/db/schema"
2
+
3
+ export const publicMapPackageBuild = (
4
+ internalPackageBuild: ZT.PackageBuild,
5
+ options: {
6
+ include_logs?: boolean
7
+ } = {
8
+ include_logs: false,
9
+ },
10
+ ): ZT.PackageBuild => {
11
+ const result = {
12
+ ...internalPackageBuild,
13
+ created_at: internalPackageBuild.created_at,
14
+ transpilation_started_at: internalPackageBuild.transpilation_started_at,
15
+ transpilation_completed_at: internalPackageBuild.transpilation_completed_at,
16
+ transpilation_logs: options.include_logs
17
+ ? internalPackageBuild.transpilation_logs
18
+ : [],
19
+ transpilation_error: internalPackageBuild.transpilation_error,
20
+ circuit_json_build_started_at:
21
+ internalPackageBuild.circuit_json_build_started_at,
22
+ circuit_json_build_completed_at:
23
+ internalPackageBuild.circuit_json_build_completed_at,
24
+ circuit_json_build_logs: options.include_logs
25
+ ? internalPackageBuild.circuit_json_build_logs
26
+ : [],
27
+ circuit_json_build_error: internalPackageBuild.circuit_json_build_error,
28
+ build_started_at: internalPackageBuild.build_started_at,
29
+ build_completed_at: internalPackageBuild.build_completed_at,
30
+ build_error: internalPackageBuild.build_error,
31
+ build_error_last_updated_at:
32
+ internalPackageBuild.build_error_last_updated_at,
33
+ preview_url: internalPackageBuild.preview_url,
34
+ build_logs: options.include_logs ? internalPackageBuild.build_logs : null,
35
+ branch_name: internalPackageBuild.branch_name,
36
+ commit_message: internalPackageBuild.commit_message,
37
+ commit_author: internalPackageBuild.commit_author,
38
+ }
39
+
40
+ return result
41
+ }
@@ -0,0 +1,70 @@
1
+ import { withRouteSpec } from "fake-snippets-api/lib/middleware/with-winter-spec"
2
+ import { z } from "zod"
3
+ import { publicMapPackageBuild } from "fake-snippets-api/lib/public-mapping/public-map-package-build"
4
+
5
+ export default withRouteSpec({
6
+ methods: ["GET"],
7
+ auth: "session",
8
+ queryParams: z.object({
9
+ package_build_id: z.string(),
10
+ }),
11
+ jsonResponse: z.object({
12
+ package_build: z.any(),
13
+ }),
14
+ })(async (req, ctx) => {
15
+ const { package_build_id } = req.query
16
+
17
+ if (!package_build_id) {
18
+ return ctx.error(400, {
19
+ error_code: "invalid_request",
20
+ message: "package_build_id is required",
21
+ })
22
+ }
23
+
24
+ const packageBuild = ctx.db.packageBuilds.find(
25
+ (build) => build.package_build_id === package_build_id,
26
+ )
27
+
28
+ if (!packageBuild) {
29
+ return ctx.error(404, {
30
+ error_code: "package_build_not_found",
31
+ message: "Package build not found",
32
+ })
33
+ }
34
+
35
+ const packageRelease = ctx.db.packageReleases.find(
36
+ (pr) => pr.package_release_id === packageBuild.package_release_id,
37
+ )
38
+
39
+ if (!packageRelease) {
40
+ return ctx.error(404, {
41
+ error_code: "package_release_not_found",
42
+ message: "Package release not found",
43
+ })
44
+ }
45
+
46
+ const pkg = ctx.db.packages.find(
47
+ (p) => p.package_id === packageRelease.package_id,
48
+ )
49
+ if (!pkg) {
50
+ return ctx.error(404, {
51
+ error_code: "package_not_found",
52
+ message: "Package not found",
53
+ })
54
+ }
55
+
56
+ if (pkg.creator_account_id !== ctx.auth.account_id) {
57
+ return ctx.error(403, {
58
+ error_code: "unauthorized",
59
+ message: "You are not authorized to access this package build",
60
+ })
61
+ }
62
+
63
+ const publicBuild = publicMapPackageBuild(packageBuild, {
64
+ include_logs: true,
65
+ })
66
+
67
+ return ctx.json({
68
+ package_build: publicBuild,
69
+ })
70
+ })
@@ -0,0 +1,97 @@
1
+ import { withRouteSpec } from "fake-snippets-api/lib/middleware/with-winter-spec"
2
+ import { z } from "zod"
3
+ import { publicMapPackageBuild } from "fake-snippets-api/lib/public-mapping/public-map-package-build"
4
+
5
+ export default withRouteSpec({
6
+ methods: ["GET"],
7
+ auth: "session",
8
+ queryParams: z.object({
9
+ package_id: z.string().optional(),
10
+ package_release_id: z.string().optional(),
11
+ }),
12
+ jsonResponse: z.object({
13
+ package_builds: z.array(z.any()),
14
+ }),
15
+ })(async (req, ctx) => {
16
+ const { package_id, package_release_id } = req.query
17
+ if (!package_id && !package_release_id) {
18
+ return ctx.error(400, {
19
+ error_code: "invalid_request",
20
+ message: "Either package_id or package_release_id must be provided",
21
+ })
22
+ }
23
+
24
+ let targetPackageId = package_id
25
+
26
+ if (package_release_id) {
27
+ const packageRelease = ctx.db.packageReleases.find(
28
+ (pr) => pr.package_release_id === package_release_id,
29
+ )
30
+ if (!packageRelease) {
31
+ return ctx.error(404, {
32
+ error_code: "package_release_not_found",
33
+ message: "Package release not found",
34
+ })
35
+ }
36
+ targetPackageId = packageRelease.package_id
37
+ }
38
+
39
+ if (targetPackageId) {
40
+ const pkg = ctx.db.packages.find((p) => p.package_id === targetPackageId)
41
+ if (!pkg) {
42
+ return ctx.error(404, {
43
+ error_code: "package_not_found",
44
+ message: "Package not found",
45
+ })
46
+ }
47
+ if (pkg.creator_account_id !== ctx.auth.account_id) {
48
+ return ctx.error(403, {
49
+ error_code: "unauthorized",
50
+ message: "You are not authorized to access this package",
51
+ })
52
+ }
53
+ }
54
+
55
+ let builds = ctx.db.packageBuilds
56
+
57
+ if (package_id) {
58
+ const packageReleases = ctx.db.packageReleases.filter(
59
+ (x) => x.package_id === package_id,
60
+ )
61
+ if (packageReleases.length === 0) {
62
+ return ctx.error(404, {
63
+ error_code: "package_not_found",
64
+ message: "Package not found",
65
+ })
66
+ }
67
+
68
+ const packageReleaseIds = packageReleases
69
+ .filter((pr) => pr.package_id === package_id)
70
+ .map((pr) => pr.package_release_id)
71
+
72
+ builds = builds.filter((build) =>
73
+ packageReleaseIds.includes(build.package_release_id),
74
+ )
75
+ }
76
+
77
+ if (package_release_id) {
78
+ builds = builds.filter(
79
+ (build) => build.package_release_id === package_release_id,
80
+ )
81
+ }
82
+
83
+ builds = builds.sort(
84
+ (a, b) =>
85
+ new Date(b.created_at).getTime() - new Date(a.created_at).getTime(),
86
+ )
87
+
88
+ const publicBuilds = builds.map((build) =>
89
+ publicMapPackageBuild(build, {
90
+ include_logs: false,
91
+ }),
92
+ )
93
+
94
+ return ctx.json({
95
+ package_builds: publicBuilds,
96
+ })
97
+ })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/fake-snippets",
3
- "version": "0.0.105",
3
+ "version": "0.0.107",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -30,7 +30,8 @@
30
30
  "build:fake-api": "bun run build:fake-api:tsup && bun run build:fake-api:bundle && bun run build:fake-api:schema",
31
31
  "build:fake-api:schema": "tsup-node ./fake-snippets-api/lib/db/schema.ts --format esm --dts",
32
32
  "generate-images": "bun run scripts/generate-image-sizes.ts",
33
- "generate-sitemap": "bun run scripts/generate-sitemap.ts"
33
+ "generate-sitemap": "bun run scripts/generate-sitemap.ts",
34
+ "typecheck": "tsc --noEmit"
34
35
  },
35
36
  "devDependencies": {
36
37
  "@anthropic-ai/sdk": "^0.27.3",
package/src/App.tsx CHANGED
@@ -79,9 +79,9 @@ const PackageEditorPage = lazyImport(async () => {
79
79
  ])
80
80
  return editorModule
81
81
  })
82
- const ViewConnectedRepoPage = lazyImport(
83
- () => import("@/pages/view-connected-repo"),
84
- )
82
+ const ReleasesPage = lazyImport(() => import("@/pages/releases"))
83
+ const ReleaseDetailPage = lazyImport(() => import("@/pages/release-detail"))
84
+ const ReleaseBuildsPage = lazyImport(() => import("@/pages/release-builds"))
85
85
  const PreviewBuildPage = lazyImport(() => import("@/pages/preview-build"))
86
86
 
87
87
  class ErrorBoundary extends React.Component<
@@ -143,7 +143,8 @@ class ErrorBoundary extends React.Component<
143
143
  this.cleanup() // Clean up listeners before reload
144
144
  this.setState({ reloading: true })
145
145
  this.reloadTimeout = window.setTimeout(() => {
146
- // window.location.reload()
146
+ if (window?.location.href.includes("localhost:")) return
147
+ window.location.reload()
147
148
  }, 500)
148
149
  }
149
150
 
@@ -257,7 +258,22 @@ function App() {
257
258
  <Route path="/my-orders" component={MyOrdersPage} />
258
259
  <Route path="/dev-login" component={DevLoginPage} />
259
260
  <Route path="/:username" component={UserProfilePage} />
260
- <Route path="/build/:buildId" component={ViewConnectedRepoPage} />
261
+ <Route
262
+ path="/:author/:packageName/release/:releaseId/builds"
263
+ component={ReleaseBuildsPage}
264
+ />
265
+ <Route
266
+ path="/:author/:packageName/release/:releaseId"
267
+ component={ReleaseDetailPage}
268
+ />
269
+ <Route
270
+ path="/:author/:packageName/releases/:packageReleaseId"
271
+ component={ReleaseDetailPage}
272
+ />
273
+ <Route
274
+ path="/:author/:packageName/releases"
275
+ component={ReleasesPage}
276
+ />
261
277
  <Route
262
278
  path="/build/:buildId/preview"
263
279
  component={PreviewBuildPage}
@@ -0,0 +1,111 @@
1
+ import { PrefetchPageLink } from "@/components/PrefetchPageLink"
2
+ import {
3
+ Breadcrumb,
4
+ BreadcrumbList,
5
+ BreadcrumbItem,
6
+ BreadcrumbLink,
7
+ BreadcrumbPage,
8
+ BreadcrumbSeparator,
9
+ } from "@/components/ui/breadcrumb"
10
+
11
+ interface PackageBreadcrumbProps {
12
+ author: string
13
+ packageName: string
14
+ unscopedName?: string
15
+ currentPage?: "releases" | "builds" | string
16
+ releaseVersion?: string
17
+ }
18
+
19
+ export function PackageBreadcrumb({
20
+ author,
21
+ packageName,
22
+ unscopedName,
23
+ currentPage,
24
+ releaseVersion,
25
+ }: PackageBreadcrumbProps) {
26
+ return (
27
+ <Breadcrumb className="mb-4">
28
+ <BreadcrumbList>
29
+ {/* Author */}
30
+ <BreadcrumbItem>
31
+ <BreadcrumbLink asChild>
32
+ <PrefetchPageLink href={`/${author}`}>{author}</PrefetchPageLink>
33
+ </BreadcrumbLink>
34
+ </BreadcrumbItem>
35
+ <BreadcrumbSeparator>
36
+ <span>/</span>
37
+ </BreadcrumbSeparator>
38
+
39
+ {/* Package */}
40
+ <BreadcrumbItem>
41
+ <BreadcrumbLink asChild>
42
+ <PrefetchPageLink href={`/${packageName}`}>
43
+ {unscopedName || packageName}
44
+ </PrefetchPageLink>
45
+ </BreadcrumbLink>
46
+ </BreadcrumbItem>
47
+ <BreadcrumbSeparator>
48
+ <span>/</span>
49
+ </BreadcrumbSeparator>
50
+
51
+ {/* Releases */}
52
+ {(currentPage === "releases" ||
53
+ releaseVersion ||
54
+ currentPage === "builds") && (
55
+ <>
56
+ <BreadcrumbItem>
57
+ {currentPage === "releases" ? (
58
+ <BreadcrumbPage>releases</BreadcrumbPage>
59
+ ) : (
60
+ <BreadcrumbLink asChild>
61
+ <PrefetchPageLink href={`/${packageName}/releases`}>
62
+ releases
63
+ </PrefetchPageLink>
64
+ </BreadcrumbLink>
65
+ )}
66
+ </BreadcrumbItem>
67
+ <BreadcrumbSeparator>
68
+ <span>/</span>
69
+ </BreadcrumbSeparator>
70
+ </>
71
+ )}
72
+
73
+ {/* Release Version */}
74
+ {releaseVersion && (
75
+ <>
76
+ <BreadcrumbItem>
77
+ {currentPage === "builds" ? (
78
+ <BreadcrumbLink asChild>
79
+ <PrefetchPageLink
80
+ href={`/${packageName}/release/${releaseVersion}`}
81
+ >
82
+ {releaseVersion}
83
+ </PrefetchPageLink>
84
+ </BreadcrumbLink>
85
+ ) : (
86
+ <BreadcrumbPage>{releaseVersion}</BreadcrumbPage>
87
+ )}
88
+ </BreadcrumbItem>
89
+ {currentPage === "builds" && (
90
+ <>
91
+ <BreadcrumbSeparator>
92
+ <span>/</span>
93
+ </BreadcrumbSeparator>
94
+ <BreadcrumbItem>
95
+ <BreadcrumbPage>builds</BreadcrumbPage>
96
+ </BreadcrumbItem>
97
+ </>
98
+ )}
99
+ </>
100
+ )}
101
+
102
+ {/* Other current pages */}
103
+ {currentPage && !["releases", "builds"].includes(currentPage) && (
104
+ <BreadcrumbItem>
105
+ <BreadcrumbPage>{currentPage}</BreadcrumbPage>
106
+ </BreadcrumbItem>
107
+ )}
108
+ </BreadcrumbList>
109
+ </Breadcrumb>
110
+ )
111
+ }
@@ -5,12 +5,9 @@ import { usePackageReleaseById } from "@/hooks/use-package-release"
5
5
  import { timeAgo } from "@/lib/utils/timeAgo"
6
6
  import { BuildStatus, BuildStep } from "./build-status"
7
7
  import type { PackageRelease } from "fake-snippets-api/lib/db/schema"
8
- import {
9
- getBuildStatus,
10
- getLatestBuildFromPackageRelease,
11
- StatusIcon,
12
- } from "@/components/preview"
8
+ import { getBuildStatus, StatusIcon } from "@/components/preview"
13
9
  import { PrefetchPageLink } from "@/components/PrefetchPageLink"
10
+ import { usePackageBuild } from "@/hooks/use-package-builds"
14
11
 
15
12
  function getTranspilationStatus(
16
13
  pr?: PackageRelease | null,
@@ -45,6 +42,9 @@ export default function SidebarReleasesSection() {
45
42
  const { data: packageRelease } = usePackageReleaseById(
46
43
  packageInfo?.latest_package_release_id,
47
44
  )
45
+ const { data: latestBuild } = usePackageBuild(
46
+ packageRelease?.latest_package_build_id ?? null,
47
+ )
48
48
 
49
49
  const buildSteps: BuildStep[] = [
50
50
  {
@@ -74,16 +74,27 @@ export default function SidebarReleasesSection() {
74
74
  )
75
75
  }
76
76
 
77
- const latestBuild = getLatestBuildFromPackageRelease(packageRelease)
78
- const { status, label } = getBuildStatus(latestBuild)
77
+ const { status, label } = latestBuild
78
+ ? getBuildStatus(latestBuild)
79
+ : { status: "pending", label: "pending" }
79
80
  return (
80
81
  <div className="mb-6">
81
- <h2 className="text-lg font-semibold mb-2">Releases</h2>
82
+ <h2 className="text-lg font-semibold mb-2">
83
+ <PrefetchPageLink
84
+ href={`/${packageInfo?.owner_github_username}/${packageInfo?.unscoped_name}/releases`}
85
+ className="hover:underline"
86
+ >
87
+ Releases
88
+ </PrefetchPageLink>
89
+ </h2>
82
90
  <div className="flex flex-col space-y-2">
83
- <div className="flex items-center">
91
+ <PrefetchPageLink
92
+ href={`/${packageInfo?.owner_github_username}/${packageInfo?.unscoped_name}/releases`}
93
+ className="flex items-center hover:underline"
94
+ >
84
95
  <Tag className="h-4 w-4 mr-2 text-gray-500 dark:text-[#8b949e]" />
85
96
  <span className="text-sm font-medium">v{packageRelease.version}</span>
86
- </div>
97
+ </PrefetchPageLink>
87
98
  <div className="flex items-center">
88
99
  <Clock className="h-4 w-4 mr-2 text-gray-500 dark:text-[#8b949e]" />
89
100
  <span className="text-sm text-gray-500 dark:text-[#8b949e]">
@@ -103,7 +114,7 @@ export default function SidebarReleasesSection() {
103
114
  className="flex items-center gap-2 text-sm text-gray-500 dark:text-[#8b949e]"
104
115
  >
105
116
  <StatusIcon status={status} />
106
- <span>Package preview {label}</span>
117
+ <span>Package Preview {label}</span>
107
118
  </PrefetchPageLink>
108
119
  )}
109
120
  </div>