@tscircuit/fake-snippets 0.0.3 → 0.0.4

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 (41) hide show
  1. package/.github/workflows/bundle-size-analysis.yml +2 -2
  2. package/bun-tests/fake-snippets-api/routes/packages/create.test.ts +26 -0
  3. package/bun-tests/fake-snippets-api/routes/packages/delete.test.ts +100 -0
  4. package/bun-tests/fake-snippets-api/routes/packages/get.test.ts +59 -0
  5. package/bun-tests/fake-snippets-api/routes/packages/list.test.ts +167 -0
  6. package/bun.lock +3500 -0
  7. package/dist/bundle.js +467 -106
  8. package/fake-snippets-api/lib/db/db-client.ts +49 -2
  9. package/fake-snippets-api/lib/db/schema.ts +53 -0
  10. package/fake-snippets-api/lib/public-mapping/public-map-package.ts +31 -0
  11. package/fake-snippets-api/lib/with-winter-spec.ts +1 -0
  12. package/fake-snippets-api/routes/api/package_files/download.ts +170 -0
  13. package/fake-snippets-api/routes/api/package_files/get.ts +52 -0
  14. package/fake-snippets-api/routes/api/package_files/list.ts +60 -0
  15. package/fake-snippets-api/routes/api/packages/create.ts +58 -0
  16. package/fake-snippets-api/routes/api/packages/delete.ts +43 -0
  17. package/fake-snippets-api/routes/api/packages/get.ts +36 -0
  18. package/fake-snippets-api/routes/api/packages/list.ts +56 -0
  19. package/fake-snippets-api/routes/api/snippets/create.ts +5 -3
  20. package/package.json +10 -9
  21. package/playwright-tests/cmd-click.spec.ts +1 -1
  22. package/playwright-tests/editor-page.spec.ts +1 -1
  23. package/playwright-tests/preview-page.spec.ts +2 -9
  24. package/playwright-tests/snapshots/cmd-click.spec.ts-underlined-imports.png +0 -0
  25. package/playwright-tests/snapshots/editor-page.spec.ts-editor-with-snippet.png +0 -0
  26. package/playwright-tests/snapshots/preview-page.spec.ts-preview-snippet-pcb.png +0 -0
  27. package/src/components/CodeAndPreview.tsx +60 -2
  28. package/src/components/EditorNav.tsx +23 -2
  29. package/src/components/FootprintDialog.tsx +3 -6
  30. package/src/components/Header2.tsx +7 -0
  31. package/src/components/PrefetchPageLink.tsx +4 -1
  32. package/src/components/SuspenseRunFrame.tsx +16 -0
  33. package/src/components/dialogs/import-snippet-dialog.tsx +12 -8
  34. package/src/hooks/use-debounce.ts +17 -0
  35. package/src/hooks/use-global-store.ts +5 -0
  36. package/src/hooks/use-run-tsx/index.tsx +1 -0
  37. package/src/pages/landing.tsx +2 -2
  38. package/src/pages/preview.tsx +2 -28
  39. package/vite.config.ts +1 -1
  40. package/bun.lockb +0 -0
  41. package/playwright-tests/snapshots/preview-page.spec.ts-preview-snippet-schematic.png +0 -0
@@ -20,7 +20,7 @@ jobs:
20
20
  - uses: actions/checkout@v4
21
21
 
22
22
  - name: Setup Bun
23
- uses: oven-sh/setup-bun@v1
23
+ uses: oven-sh/setup-bun@v2
24
24
  with:
25
25
  bun-version: latest
26
26
 
@@ -33,7 +33,7 @@ jobs:
33
33
 
34
34
  - name: Save stats as artifact
35
35
  if: success()
36
- uses: actions/upload-artifact@v3
36
+ uses: actions/upload-artifact@v4
37
37
  with:
38
38
  name: bundle-stats
39
39
  path: dist/stats.html
@@ -0,0 +1,26 @@
1
+ import { getTestServer } from "bun-tests/fake-snippets-api/fixtures/get-test-server"
2
+ import { test, expect } from "bun:test"
3
+
4
+ test("create package", async () => {
5
+ const { axios } = await getTestServer()
6
+
7
+ const response = await axios.post(
8
+ "/api/packages/create",
9
+ {
10
+ name: "TestPackage",
11
+ description: "Test Description",
12
+ },
13
+ {
14
+ headers: {
15
+ Authorization: "Bearer 1234",
16
+ },
17
+ },
18
+ )
19
+
20
+ expect(response.status).toBe(200)
21
+ expect(response.data.package.name).toBe("TestPackage")
22
+ expect(response.data.package.description).toBe("Test Description")
23
+ expect(response.data.package.owner_github_username).toBe("testuser")
24
+ expect(response.data.package.description).toBe("Test Description")
25
+ expect(response.data.package.latest_package_release_id).toBeDefined()
26
+ })
@@ -0,0 +1,100 @@
1
+ import { getTestServer } from "bun-tests/fake-snippets-api/fixtures/get-test-server"
2
+ import { expect, test } from "bun:test"
3
+
4
+ test("delete package", async () => {
5
+ const { axios, db } = await getTestServer()
6
+
7
+ // Add a test package
8
+ const pkg = {
9
+ name: "test-package",
10
+ owner_org_id: "org-1234", // Changed to match the default auth context's personal_org_id
11
+ created_at: "2023-01-01T00:00:00Z",
12
+ updated_at: "2023-01-01T00:00:00Z",
13
+ description: "Test Description",
14
+ }
15
+ const addedPackage: any = db.addPackage(pkg as any)
16
+
17
+ // Delete the package
18
+ const response = await axios.post(
19
+ "/api/packages/delete",
20
+ {
21
+ package_id: addedPackage.package_id,
22
+ },
23
+ {
24
+ headers: {
25
+ Authorization: "Bearer 1234",
26
+ },
27
+ },
28
+ )
29
+
30
+ expect(response.status).toBe(200)
31
+ expect(response.data.ok).toBe(true)
32
+
33
+ // Verify the package was deleted from the database
34
+ const deletedPackage = db.getPackageById(addedPackage.package_id)
35
+ expect(deletedPackage).toBeUndefined()
36
+
37
+ // List all the packages and verify the deleted package is not in the list
38
+ const listResponse = await axios.get("/api/packages/list")
39
+
40
+ expect(listResponse.status).toBe(200)
41
+ expect(listResponse.data.packages).toHaveLength(0)
42
+ })
43
+
44
+ test("delete non-existent package", async () => {
45
+ const { axios } = await getTestServer()
46
+
47
+ try {
48
+ await axios.post(
49
+ "/api/packages/delete",
50
+ {
51
+ package_id: "non-existent-id",
52
+ },
53
+ {
54
+ headers: {
55
+ Authorization: "Bearer 1234",
56
+ },
57
+ },
58
+ )
59
+ // If the request doesn't throw an error, fail the test
60
+ expect(true).toBe(false)
61
+ } catch (error: any) {
62
+ expect(error.status).toBe(404)
63
+ expect(error.data.error.message).toBe("Package not found")
64
+ }
65
+ })
66
+
67
+ test("delete package without permission", async () => {
68
+ const { axios, db } = await getTestServer()
69
+
70
+ // Add a test package with a different owner org
71
+ const pkg = {
72
+ name: "test-package",
73
+ owner_org_id: "different-org", // Different from the personal_org_id in auth
74
+ created_at: "2023-01-01T00:00:00Z",
75
+ updated_at: "2023-01-01T00:00:00Z",
76
+ description: "Test Description",
77
+ }
78
+ const addedPackage: any = db.addPackage(pkg as any)
79
+
80
+ try {
81
+ await axios.post(
82
+ "/api/packages/delete",
83
+ {
84
+ package_id: addedPackage.package_id,
85
+ },
86
+ {
87
+ headers: {
88
+ Authorization: "Bearer 1234",
89
+ },
90
+ },
91
+ )
92
+ // If the request doesn't throw an error, fail the test
93
+ expect(true).toBe(false)
94
+ } catch (error: any) {
95
+ expect(error.status).toBe(403)
96
+ expect(error.data.error.message).toBe(
97
+ "You don't have permission to delete this package",
98
+ )
99
+ }
100
+ })
@@ -0,0 +1,59 @@
1
+ import { getTestServer } from "bun-tests/fake-snippets-api/fixtures/get-test-server"
2
+ import { expect, test } from "bun:test"
3
+ import { packageSchema } from "fake-snippets-api/lib/db/schema"
4
+
5
+ test("GET /api/packages/get - should return package by package_id", async () => {
6
+ const { axios } = await getTestServer()
7
+
8
+ // Create a new package using the /create endpoint
9
+ const newPackageData = {
10
+ name: "test-package",
11
+ description: "A test package",
12
+ creator_account_id: "test_account_id",
13
+ owner_org_id: "test_org_id",
14
+ owner_github_username: "test_github_username",
15
+ latest_package_release_id: null,
16
+ latest_version: null,
17
+ license: null,
18
+ is_source_from_github: false,
19
+ created_at: new Date().toISOString(),
20
+ updated_at: new Date().toISOString(),
21
+ unscoped_name: "test-package",
22
+ star_count: 0,
23
+ ai_description: "test-package",
24
+ }
25
+
26
+ const createResponse = await axios.post(
27
+ "/api/packages/create",
28
+ newPackageData,
29
+ )
30
+ expect(createResponse.status).toBe(200)
31
+ const createdPackage = createResponse.data.package
32
+
33
+ // Get the created package using the /get endpoint
34
+ const getResponse = await axios.get("/api/packages/get", {
35
+ params: { package_id: createdPackage.package_id },
36
+ })
37
+
38
+ expect(getResponse.status).toBe(200)
39
+ const responseBody = getResponse.data
40
+ expect(responseBody.ok).toBe(true)
41
+ expect(responseBody.package).toEqual(packageSchema.parse(createdPackage))
42
+ })
43
+
44
+ test("GET /api/packages/get - should return 404 if package not found", async () => {
45
+ const { axios } = await getTestServer()
46
+
47
+ try {
48
+ await axios.get("/api/packages/get", {
49
+ params: { package_id: "non_existent_package_id" },
50
+ })
51
+ throw new Error("Expected request to fail")
52
+ } catch (error: any) {
53
+ expect(error.status).toBe(404)
54
+ expect(error.data.error.error_code).toBe("package_not_found")
55
+ expect(error.data.error.message).toBe(
56
+ 'Package not found (searched using {"package_id":"non_existent_package_id"})',
57
+ )
58
+ }
59
+ })
@@ -0,0 +1,167 @@
1
+ import { getTestServer } from "bun-tests/fake-snippets-api/fixtures/get-test-server"
2
+ import { expect, test } from "bun:test"
3
+
4
+ test("list packages", async () => {
5
+ const { axios, db } = await getTestServer()
6
+
7
+ // Add some test packages
8
+ const packages = [
9
+ {
10
+ name: "Package1",
11
+ unscoped_name: "Package1",
12
+ owner_github_username: "user1",
13
+ creator_account_id: "creator1",
14
+ created_at: "2023-01-01T00:00:00Z",
15
+ updated_at: "2023-01-01T00:00:00Z",
16
+ description: "Description 1",
17
+ ai_description: "AI Description 1",
18
+ owner_org_id: "org1",
19
+ latest_version: "1.0.0",
20
+ license: "MIT",
21
+ is_source_from_github: true,
22
+ star_count: 0,
23
+ },
24
+ {
25
+ name: "Package2",
26
+ unscoped_name: "Package2",
27
+ owner_github_username: "user2",
28
+ creator_account_id: "creator2",
29
+ created_at: "2023-01-02T00:00:00Z",
30
+ updated_at: "2023-01-02T00:00:00Z",
31
+ description: "Description 2",
32
+ ai_description: "AI Description 2",
33
+ owner_org_id: "org2",
34
+ latest_version: "1.0.0",
35
+ license: "MIT",
36
+ is_source_from_github: true,
37
+ star_count: 0,
38
+ },
39
+ {
40
+ name: "Package3",
41
+ unscoped_name: "Package3",
42
+ owner_github_username: "user1",
43
+ creator_account_id: "creator1",
44
+ created_at: "2023-01-03T00:00:00Z",
45
+ updated_at: "2023-01-03T00:00:00Z",
46
+ description: "Description 3",
47
+ ai_description: "AI Description 3",
48
+ owner_org_id: "org1",
49
+ latest_version: "1.0.0",
50
+ license: "MIT",
51
+ is_source_from_github: true,
52
+ star_count: 0,
53
+ },
54
+ ]
55
+
56
+ for (const pkg of packages) {
57
+ db.addPackage(pkg as any)
58
+ }
59
+
60
+ // Test with no parameters (should return all packages)
61
+ const { data: allData } = await axios.get("/api/packages/list")
62
+ expect(allData.ok).toBe(true)
63
+ expect(allData.packages).toHaveLength(3)
64
+
65
+ // Test with owner_github_username parameter
66
+ const { data: user1Data } = await axios.get("/api/packages/list", {
67
+ params: { owner_github_username: "user1" },
68
+ })
69
+ expect(user1Data.packages).toHaveLength(2)
70
+ expect(
71
+ user1Data.packages.every(
72
+ (pkg: { owner_github_username: string }) =>
73
+ pkg.owner_github_username === "user1",
74
+ ),
75
+ ).toBe(true)
76
+
77
+ // Test with creator_account_id parameter
78
+ const { data: creator1Data } = await axios.get("/api/packages/list", {
79
+ params: { creator_account_id: "creator1" },
80
+ })
81
+ expect(creator1Data.packages).toHaveLength(2)
82
+ expect(
83
+ creator1Data.packages.every(
84
+ (pkg: { creator_account_id: string }) =>
85
+ pkg.creator_account_id === "creator1",
86
+ ),
87
+ ).toBe(true)
88
+
89
+ // Test with name parameter (must include another filter parameter)
90
+ const { data: nameData } = await axios.get("/api/packages/list", {
91
+ params: {
92
+ name: "Package1",
93
+ owner_github_username: "user1",
94
+ },
95
+ })
96
+ expect(nameData.packages).toHaveLength(1)
97
+ expect(nameData.packages[0].name).toBe("Package1")
98
+
99
+ // Test with non-existent owner
100
+ const { data: nonExistentData } = await axios.get("/api/packages/list", {
101
+ params: { owner_github_username: "nonexistentuser" },
102
+ })
103
+ expect(nonExistentData.packages).toHaveLength(0)
104
+
105
+ // Test with authenticated request
106
+ const { data: authData } = await axios.get("/api/packages/list", {
107
+ headers: {
108
+ Authorization: "Bearer 1234",
109
+ },
110
+ })
111
+ expect(authData.packages).toHaveLength(3) // Should return all packages when authenticated
112
+ })
113
+
114
+ test("list packages with is_writable filter", async () => {
115
+ const { axios, db } = await getTestServer()
116
+
117
+ // Add test packages
118
+ const packages = [
119
+ {
120
+ package_id: "pkg1",
121
+ name: "Package1",
122
+ unscoped_name: "Package1",
123
+ owner_github_username: "testuser", // Matches auth context github_username
124
+ creator_account_id: "account-1234", // Matches auth context account_id
125
+ created_at: "2023-01-01T00:00:00Z",
126
+ updated_at: "2023-01-01T00:00:00Z",
127
+ description: "Description 1",
128
+ ai_description: "AI Description 1",
129
+ owner_org_id: "org-1234", // Matches auth context personal_org_id
130
+ latest_version: "1.0.0",
131
+ license: "MIT",
132
+ is_source_from_github: true,
133
+ star_count: 0,
134
+ },
135
+ {
136
+ package_id: "pkg2",
137
+ name: "Package2",
138
+ unscoped_name: "Package2",
139
+ owner_github_username: "user2",
140
+ creator_account_id: "creator2",
141
+ created_at: "2023-01-02T00:00:00Z",
142
+ updated_at: "2023-01-02T00:00:00Z",
143
+ description: "Description 2",
144
+ ai_description: "AI Description 2",
145
+ owner_org_id: "other-org",
146
+ latest_version: "1.0.0",
147
+ license: "MIT",
148
+ is_source_from_github: true,
149
+ star_count: 0,
150
+ },
151
+ ]
152
+
153
+ // Add only these test packages
154
+ for (const pkg of packages) {
155
+ db.addPackage(pkg as any)
156
+ }
157
+
158
+ // Test with is_writable filter (requires auth)
159
+ const { data: writableData } = await axios.get("/api/packages/list", {
160
+ params: { is_writable: true },
161
+ headers: {
162
+ Authorization: "Bearer 1234",
163
+ },
164
+ })
165
+ expect(writableData.packages).toHaveLength(1)
166
+ expect(writableData.packages[0].owner_org_id).toBe("org-1234")
167
+ })