@tscircuit/fake-snippets 0.0.69 → 0.0.71

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.
@@ -18,11 +18,12 @@ function getHtmlWithModifiedSeoTags({
18
18
  description,
19
19
  canonicalUrl,
20
20
  imageUrl,
21
+ ssrPackageData,
21
22
  }) {
22
23
  const seoStartTag = "<!-- SEO_START -->"
23
24
  const seoEndTag = "<!-- SEO_END -->"
24
- const startIndex = htmlContent.indexOf(seoStartTag)
25
- const endIndex = htmlContent.indexOf(seoEndTag) + seoEndTag.length
25
+ const seoStartIndex = htmlContent.indexOf(seoStartTag)
26
+ const seoEndIndex = htmlContent.indexOf(seoEndTag) + seoEndTag.length
26
27
 
27
28
  const seoTags = `
28
29
  <title>${title}</title>
@@ -42,7 +43,47 @@ function getHtmlWithModifiedSeoTags({
42
43
  <link rel="canonical" href="${canonicalUrl}" />
43
44
  `
44
45
 
45
- return `${htmlContent.substring(0, startIndex)}${seoTags}${htmlContent.substring(endIndex)}`
46
+ // First replace SEO tags
47
+ let modifiedHtml = `${htmlContent.substring(0, seoStartIndex)}${seoTags}${htmlContent.substring(seoEndIndex)}`
48
+
49
+ // Then handle SSR data injection
50
+ if (ssrPackageData) {
51
+ const ssrStartTag = "<!-- SSR_START -->"
52
+ const ssrEndTag = "<!-- SSR_END -->"
53
+ const {
54
+ package: packageData,
55
+ packageRelease,
56
+ packageFiles,
57
+ } = ssrPackageData
58
+
59
+ const assignments = []
60
+ if (packageData) {
61
+ assignments.push(`window.SSR_PACKAGE = ${JSON.stringify(packageData)};`)
62
+ }
63
+ if (packageRelease) {
64
+ assignments.push(
65
+ `window.SSR_PACKAGE_RELEASE = ${JSON.stringify(packageRelease)};`,
66
+ )
67
+ }
68
+ if (packageFiles) {
69
+ assignments.push(
70
+ `window.SSR_PACKAGE_FILES = ${JSON.stringify(packageFiles)};`,
71
+ )
72
+ }
73
+
74
+ const ssrScripts =
75
+ assignments.length > 0 ? `<script>${assignments.join(" ")}</script>` : ""
76
+
77
+ if (ssrScripts) {
78
+ const ssrContent = `\n ${ssrScripts}\n `
79
+ modifiedHtml = modifiedHtml.replace(
80
+ `${ssrStartTag}\n ${ssrEndTag}`,
81
+ `${ssrStartTag}${ssrContent}${ssrEndTag}`,
82
+ )
83
+ }
84
+ }
85
+
86
+ return modifiedHtml
46
87
  }
47
88
 
48
89
  async function handleCustomPackageHtml(req, res) {
@@ -64,6 +105,38 @@ async function handleCustomPackageHtml(req, res) {
64
105
  throw new Error("Package not found")
65
106
  }
66
107
 
108
+ let packageRelease = null
109
+ let packageFiles = null
110
+ try {
111
+ const releaseResponse = await ky
112
+ .post(`https://registry-api.tscircuit.com/package_releases/get`, {
113
+ json: {
114
+ package_id: packageInfo.package_id,
115
+ is_latest: true,
116
+ },
117
+ })
118
+ .json()
119
+ packageRelease = releaseResponse.package_release
120
+
121
+ // Get package files for the latest release
122
+ if (packageRelease?.package_release_id) {
123
+ try {
124
+ const filesResponse = await ky
125
+ .post(`https://registry-api.tscircuit.com/package_files/list`, {
126
+ json: {
127
+ package_release_id: packageRelease.package_release_id,
128
+ },
129
+ })
130
+ .json()
131
+ packageFiles = filesResponse.package_files || []
132
+ } catch (e) {
133
+ console.warn("Failed to fetch package files:", e)
134
+ }
135
+ }
136
+ } catch (e) {
137
+ console.warn("Failed to fetch package release:", e)
138
+ }
139
+
67
140
  const description = he.encode(
68
141
  `${packageInfo.description || packageInfo.ai_description || "A tscircuit component created by " + author} ${packageInfo.ai_usage_instructions ?? ""}`,
69
142
  )
@@ -74,6 +147,7 @@ async function handleCustomPackageHtml(req, res) {
74
147
  description,
75
148
  canonicalUrl: `https://tscircuit.com/${he.encode(author)}/${he.encode(unscopedPackageName)}`,
76
149
  imageUrl: `https://registry-api.tscircuit.com/snippets/images/${he.encode(author)}/${he.encode(unscopedPackageName)}/pcb.png`,
150
+ ssrPackageData: { package: packageInfo, packageRelease, packageFiles },
77
151
  })
78
152
 
79
153
  res.setHeader("Content-Type", "text/html; charset=utf-8")
@@ -0,0 +1,53 @@
1
+ import { getTestServer } from "bun-tests/fake-snippets-api/fixtures/get-test-server"
2
+ import { expect, test } from "bun:test"
3
+
4
+ test("GET /api/accounts/get - should return account when authenticated", async () => {
5
+ const { axios } = await getTestServer()
6
+
7
+ // The test server should automatically create a test account and set up authentication
8
+ const response = await axios.get("/api/accounts/get")
9
+
10
+ expect(response.status).toBe(200)
11
+ expect(response.data.account).toBeDefined()
12
+ expect(response.data.account.account_id).toBeDefined()
13
+ })
14
+
15
+ test("GET /api/accounts/get - should return 404 if account not found", async () => {
16
+ const { unauthenticatedAxios } = await getTestServer()
17
+
18
+ try {
19
+ await unauthenticatedAxios.get("/api/accounts/get")
20
+ throw new Error("Expected request to fail")
21
+ } catch (error: any) {
22
+ expect(error.status).toBe(404)
23
+ expect(error.data.error.error_code).toBe("account_not_found")
24
+ expect(error.data.error.message).toBe("Account not found")
25
+ }
26
+ })
27
+
28
+ test("POST /api/accounts/get - should return account when authenticated", async () => {
29
+ const { axios } = await getTestServer()
30
+
31
+ const response = await axios.post("/api/accounts/get", {
32
+ github_username: "testuser",
33
+ })
34
+
35
+ expect(response.status).toBe(200)
36
+ expect(response.data.account).toBeDefined()
37
+ expect(response.data.account.account_id).toBeDefined()
38
+ })
39
+
40
+ test("POST /api/accounts/get - should return 404 if account not found", async () => {
41
+ const { axios } = await getTestServer()
42
+
43
+ try {
44
+ await axios.post("/api/accounts/get", {
45
+ github_username: "nonexistentuser",
46
+ })
47
+ throw new Error("Expected request to fail")
48
+ } catch (error: any) {
49
+ expect(error.status).toBe(404)
50
+ expect(error.data.error.error_code).toBe("account_not_found")
51
+ expect(error.data.error.message).toBe("Account not found")
52
+ }
53
+ })