@tscircuit/fake-snippets 0.0.7 → 0.0.9
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/bun-tests/fake-snippets-api/fixtures/get-test-server.ts +2 -5
- package/bun-tests/fake-snippets-api/routes/packages/{list.test.ts → list-1.test.ts} +0 -55
- package/bun-tests/fake-snippets-api/routes/packages/list-2.test.ts +59 -0
- package/bun-tests/fake-snippets-api/routes/snippets/add_star.test.ts +32 -27
- package/bun-tests/fake-snippets-api/routes/snippets/create.test.ts +34 -1
- package/bun-tests/fake-snippets-api/routes/snippets/get.test.ts +114 -0
- package/bun-tests/fake-snippets-api/routes/snippets/get_image.test.ts +10 -6
- package/bun-tests/fake-snippets-api/routes/snippets/images.test.ts +8 -6
- package/bun-tests/fake-snippets-api/routes/snippets/list_newest.test.ts +2 -2
- package/bun-tests/fake-snippets-api/routes/snippets/list_trending.test.ts +10 -10
- package/bun-tests/fake-snippets-api/routes/snippets/remove_star.test.ts +8 -6
- package/bun-tests/fake-snippets-api/routes/snippets/search.test.ts +1 -1
- package/bun-tests/fake-snippets-api/routes/snippets/star-count.test.ts +19 -12
- package/bun-tests/fake-snippets-api/routes/snippets/update.test.ts +57 -16
- package/bun.lock +148 -569
- package/dist/bundle.js +844 -194
- package/fake-snippets-api/lib/db/db-client.ts +761 -147
- package/fake-snippets-api/lib/db/schema.ts +27 -6
- package/fake-snippets-api/lib/public-mapping/public-map-package.ts +8 -0
- package/fake-snippets-api/routes/api/packages/list.ts +4 -1
- package/fake-snippets-api/routes/api/snippets/add_star.ts +30 -8
- package/fake-snippets-api/routes/api/snippets/create.ts +123 -29
- package/fake-snippets-api/routes/api/snippets/delete.ts +5 -5
- package/fake-snippets-api/routes/api/snippets/download.ts +24 -10
- package/fake-snippets-api/routes/api/snippets/get.ts +46 -13
- package/fake-snippets-api/routes/api/snippets/list.ts +37 -2
- package/fake-snippets-api/routes/api/snippets/update.ts +36 -14
- package/package.json +4 -5
- package/src/components/CodeAndPreview.tsx +13 -48
- package/src/components/CodeEditor.tsx +10 -7
- package/src/components/EditorNav.tsx +0 -21
- package/src/components/PreviewContent.tsx +2 -2
- package/src/components/ViewSnippetHeader.tsx +4 -0
- package/src/hooks/use-global-store.ts +0 -5
- package/src/hooks/use-package-as-snippet.ts +78 -0
- package/src/hooks/use-run-tsx/index.tsx +4 -0
- package/src/lib/jlc-parts-engine.ts +4 -2
|
@@ -91,6 +91,7 @@ export const orderFileSchema = z.object({
|
|
|
91
91
|
})
|
|
92
92
|
export type OrderFile = z.infer<typeof orderFileSchema>
|
|
93
93
|
|
|
94
|
+
// TODO: Remove this schema after migration to accountPackages is complete
|
|
94
95
|
export const accountSnippetSchema = z.object({
|
|
95
96
|
account_id: z.string(),
|
|
96
97
|
snippet_id: z.string(),
|
|
@@ -100,6 +101,16 @@ export const accountSnippetSchema = z.object({
|
|
|
100
101
|
})
|
|
101
102
|
export type AccountSnippet = z.infer<typeof accountSnippetSchema>
|
|
102
103
|
|
|
104
|
+
export const accountPackageSchema = z.object({
|
|
105
|
+
account_package_id: z.string(),
|
|
106
|
+
account_id: z.string(),
|
|
107
|
+
package_id: z.string(),
|
|
108
|
+
is_starred: z.boolean(),
|
|
109
|
+
created_at: z.string(),
|
|
110
|
+
updated_at: z.string(),
|
|
111
|
+
})
|
|
112
|
+
export type AccountPackage = z.infer<typeof accountPackageSchema>
|
|
113
|
+
|
|
103
114
|
export const packageReleaseSchema = z.object({
|
|
104
115
|
package_release_id: z.string(),
|
|
105
116
|
package_id: z.string(),
|
|
@@ -124,18 +135,27 @@ export type PackageFile = z.infer<typeof packageFileSchema>
|
|
|
124
135
|
export const packageSchema = z.object({
|
|
125
136
|
package_id: z.string(),
|
|
126
137
|
creator_account_id: z.string(),
|
|
127
|
-
latest_package_release_id: z.string().nullable(),
|
|
128
|
-
latest_version: z.string().nullable(),
|
|
129
|
-
license: z.string().nullable(),
|
|
130
138
|
owner_org_id: z.string(),
|
|
131
139
|
owner_github_username: z.string().nullable(),
|
|
132
|
-
is_source_from_github: z.boolean(),
|
|
133
|
-
description: z.string().nullable(),
|
|
134
140
|
name: z.string(),
|
|
135
141
|
unscoped_name: z.string(),
|
|
136
|
-
|
|
142
|
+
description: z.string().nullable(),
|
|
137
143
|
created_at: z.string().datetime(),
|
|
138
144
|
updated_at: z.string().datetime(),
|
|
145
|
+
is_snippet: z.boolean().default(false),
|
|
146
|
+
is_board: z.boolean().default(false),
|
|
147
|
+
is_package: z.boolean().default(false),
|
|
148
|
+
is_model: z.boolean().default(false),
|
|
149
|
+
is_footprint: z.boolean().default(false),
|
|
150
|
+
is_private: z.boolean().nullable().default(false),
|
|
151
|
+
is_public: z.boolean().nullable().default(true),
|
|
152
|
+
is_unlisted: z.boolean().nullable().default(false),
|
|
153
|
+
is_source_from_github: z.boolean().default(false),
|
|
154
|
+
snippet_type: z.enum(["board", "package", "model", "footprint"]).optional(),
|
|
155
|
+
latest_package_release_id: z.string().nullable(),
|
|
156
|
+
latest_version: z.string().nullable(),
|
|
157
|
+
license: z.string().nullable(),
|
|
158
|
+
star_count: z.number().default(0),
|
|
139
159
|
ai_description: z.string().nullable(),
|
|
140
160
|
})
|
|
141
161
|
export type Package = z.infer<typeof packageSchema>
|
|
@@ -163,5 +183,6 @@ export const databaseSchema = z.object({
|
|
|
163
183
|
orders: z.array(orderSchema).default([]),
|
|
164
184
|
orderFiles: z.array(orderFileSchema).default([]),
|
|
165
185
|
accountSnippets: z.array(accountSnippetSchema).default([]),
|
|
186
|
+
accountPackages: z.array(accountPackageSchema).default([]),
|
|
166
187
|
})
|
|
167
188
|
export type DatabaseSchema = z.infer<typeof databaseSchema>
|
|
@@ -17,6 +17,11 @@ export const publicMapPackage = (internal_package: {
|
|
|
17
17
|
updated_at: string
|
|
18
18
|
created_at: string
|
|
19
19
|
ai_description: string | null
|
|
20
|
+
is_snippet: boolean
|
|
21
|
+
is_board: boolean
|
|
22
|
+
is_package: boolean
|
|
23
|
+
is_model: boolean
|
|
24
|
+
is_footprint: boolean
|
|
20
25
|
}): ZT.Package => {
|
|
21
26
|
return {
|
|
22
27
|
...internal_package,
|
|
@@ -27,5 +32,8 @@ export const publicMapPackage = (internal_package: {
|
|
|
27
32
|
star_count: internal_package.star_count ?? 0,
|
|
28
33
|
created_at: internal_package.created_at,
|
|
29
34
|
updated_at: internal_package.updated_at,
|
|
35
|
+
is_private: false,
|
|
36
|
+
is_public: true,
|
|
37
|
+
is_unlisted: false,
|
|
30
38
|
}
|
|
31
39
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { withRouteSpec } from "fake-snippets-api/lib/middleware/with-winter-spec"
|
|
2
2
|
import { z } from "zod"
|
|
3
|
-
import { accountSnippetSchema } from "fake-snippets-api/lib/db/schema"
|
|
4
3
|
|
|
5
4
|
export default withRouteSpec({
|
|
6
5
|
methods: ["POST"],
|
|
@@ -10,13 +9,15 @@ export default withRouteSpec({
|
|
|
10
9
|
}),
|
|
11
10
|
jsonResponse: z.object({
|
|
12
11
|
ok: z.boolean(),
|
|
13
|
-
account_snippet: accountSnippetSchema,
|
|
14
12
|
}),
|
|
15
13
|
})(async (req, ctx) => {
|
|
16
14
|
const { snippet_id } = req.jsonBody
|
|
17
15
|
|
|
18
|
-
// Check if snippet exists
|
|
19
|
-
const snippet = ctx.db.
|
|
16
|
+
// Check if snippet exists (as a package)
|
|
17
|
+
const snippet = ctx.db.packages.find(
|
|
18
|
+
(pkg) => pkg.package_id === snippet_id && pkg.is_snippet === true,
|
|
19
|
+
)
|
|
20
|
+
|
|
20
21
|
if (!snippet) {
|
|
21
22
|
return ctx.error(404, {
|
|
22
23
|
error_code: "snippet_not_found",
|
|
@@ -25,18 +26,39 @@ export default withRouteSpec({
|
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
// Check if already starred
|
|
28
|
-
|
|
29
|
+
const existing = ctx.db.accountPackages.find(
|
|
30
|
+
(ap) =>
|
|
31
|
+
ap.account_id === ctx.auth.account_id && ap.package_id === snippet_id,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
if (existing?.is_starred) {
|
|
29
35
|
return ctx.error(400, {
|
|
30
36
|
error_code: "already_starred",
|
|
31
37
|
message: "You have already starred this snippet",
|
|
32
38
|
})
|
|
33
39
|
}
|
|
34
40
|
|
|
35
|
-
//
|
|
36
|
-
|
|
41
|
+
// Update the package's star count
|
|
42
|
+
snippet.star_count = (snippet.star_count || 0) + 1
|
|
43
|
+
|
|
44
|
+
if (existing) {
|
|
45
|
+
// If record exists but is_starred is false, update to is_starred=true
|
|
46
|
+
existing.is_starred = true
|
|
47
|
+
existing.updated_at = new Date().toISOString()
|
|
48
|
+
} else {
|
|
49
|
+
// Add star by creating a new account_package record
|
|
50
|
+
const newAccountPackage = {
|
|
51
|
+
account_package_id: `ap_${Math.random().toString(36).substring(2, 15)}`,
|
|
52
|
+
account_id: ctx.auth.account_id,
|
|
53
|
+
package_id: snippet_id,
|
|
54
|
+
is_starred: true,
|
|
55
|
+
created_at: new Date().toISOString(),
|
|
56
|
+
updated_at: new Date().toISOString(),
|
|
57
|
+
}
|
|
58
|
+
ctx.db.addAccountPackage(newAccountPackage)
|
|
59
|
+
}
|
|
37
60
|
|
|
38
61
|
return ctx.json({
|
|
39
62
|
ok: true,
|
|
40
|
-
account_snippet: accountSnippet,
|
|
41
63
|
})
|
|
42
64
|
})
|
|
@@ -29,51 +29,145 @@ export default withRouteSpec({
|
|
|
29
29
|
dts,
|
|
30
30
|
} = req.jsonBody
|
|
31
31
|
|
|
32
|
+
const timestamp = Date.now()
|
|
33
|
+
const currentTime = new Date(timestamp).toISOString()
|
|
34
|
+
|
|
32
35
|
if (!unscoped_name) {
|
|
33
|
-
|
|
36
|
+
// Count snippets of this type for this user
|
|
37
|
+
const userSnippets = ctx.db.packages.filter(
|
|
38
|
+
(p) =>
|
|
39
|
+
p.owner_github_username === ctx.auth.github_username &&
|
|
40
|
+
p.is_snippet === true &&
|
|
41
|
+
((p.is_board && snippet_type === "board") ||
|
|
42
|
+
(p.is_package && snippet_type === "package") ||
|
|
43
|
+
(p.is_model && snippet_type === "model") ||
|
|
44
|
+
(p.is_footprint && snippet_type === "footprint")),
|
|
45
|
+
)
|
|
46
|
+
unscoped_name = `untitled-${snippet_type}-${userSnippets.length + 1}`
|
|
34
47
|
}
|
|
35
48
|
|
|
36
|
-
const
|
|
37
|
-
(
|
|
38
|
-
|
|
39
|
-
|
|
49
|
+
const existingPackage = ctx.db.packages.find(
|
|
50
|
+
(pkg) =>
|
|
51
|
+
pkg.unscoped_name === unscoped_name &&
|
|
52
|
+
pkg.owner_github_username === ctx.auth.github_username,
|
|
40
53
|
)
|
|
41
54
|
|
|
42
|
-
if (
|
|
55
|
+
if (existingPackage) {
|
|
43
56
|
return ctx.error(400, {
|
|
44
57
|
error_code: "snippet_already_exists",
|
|
45
58
|
message: "You have already forked this snippet in your account.",
|
|
46
59
|
})
|
|
47
60
|
}
|
|
48
61
|
|
|
49
|
-
let newSnippet: Omit<
|
|
50
|
-
z.input<typeof snippetSchema>,
|
|
51
|
-
"snippet_id" | "package_release_id"
|
|
52
|
-
> = {
|
|
53
|
-
name: `${ctx.auth.github_username}/${unscoped_name}`,
|
|
54
|
-
unscoped_name,
|
|
55
|
-
owner_name: ctx.auth.github_username,
|
|
56
|
-
code,
|
|
57
|
-
created_at: new Date().toISOString(),
|
|
58
|
-
updated_at: new Date().toISOString(),
|
|
59
|
-
snippet_type,
|
|
60
|
-
description,
|
|
61
|
-
compiled_js,
|
|
62
|
-
circuit_json,
|
|
63
|
-
dts,
|
|
64
|
-
}
|
|
65
|
-
|
|
66
62
|
try {
|
|
67
|
-
|
|
63
|
+
// Create the package directly (which will serve as our snippet)
|
|
64
|
+
const newPackage = {
|
|
65
|
+
package_id: `pkg_${timestamp}`,
|
|
66
|
+
creator_account_id: ctx.auth.account_id,
|
|
67
|
+
owner_org_id: ctx.auth.personal_org_id,
|
|
68
|
+
owner_github_username: ctx.auth.github_username,
|
|
69
|
+
is_source_from_github: false,
|
|
70
|
+
description: description,
|
|
71
|
+
name: `${ctx.auth.github_username}/${unscoped_name}`,
|
|
72
|
+
unscoped_name: unscoped_name,
|
|
73
|
+
latest_version: "0.0.1",
|
|
74
|
+
license: null,
|
|
75
|
+
star_count: 0,
|
|
76
|
+
created_at: currentTime,
|
|
77
|
+
updated_at: currentTime,
|
|
78
|
+
ai_description: null,
|
|
79
|
+
is_snippet: true,
|
|
80
|
+
is_board: snippet_type === "board",
|
|
81
|
+
is_package: snippet_type === "package",
|
|
82
|
+
is_model: snippet_type === "model",
|
|
83
|
+
is_footprint: snippet_type === "footprint",
|
|
84
|
+
snippet_type: snippet_type,
|
|
85
|
+
is_private: false,
|
|
86
|
+
is_public: true,
|
|
87
|
+
is_unlisted: false,
|
|
88
|
+
latest_package_release_id: `package_release_${timestamp}`,
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
ctx.db.addPackage(newPackage)
|
|
92
|
+
|
|
93
|
+
const newPackageRelease = {
|
|
94
|
+
package_release_id: `package_release_${timestamp}`,
|
|
95
|
+
package_id: newPackage.package_id,
|
|
96
|
+
version: "0.0.1",
|
|
97
|
+
is_latest: true,
|
|
98
|
+
is_locked: false,
|
|
99
|
+
created_at: currentTime,
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
ctx.db.addPackageRelease(newPackageRelease)
|
|
103
|
+
|
|
104
|
+
// Add package files
|
|
105
|
+
// Add index.tsx file with the code content
|
|
106
|
+
ctx.db.addPackageFile({
|
|
107
|
+
package_release_id: newPackageRelease.package_release_id,
|
|
108
|
+
file_path: "index.tsx",
|
|
109
|
+
content_text: code,
|
|
110
|
+
created_at: currentTime,
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
// Add DTS file if provided
|
|
114
|
+
if (dts) {
|
|
115
|
+
ctx.db.addPackageFile({
|
|
116
|
+
package_release_id: newPackageRelease.package_release_id,
|
|
117
|
+
file_path: "/dist/index.d.ts",
|
|
118
|
+
content_text: dts,
|
|
119
|
+
created_at: currentTime,
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Add compiled JS if provided
|
|
124
|
+
if (compiled_js) {
|
|
125
|
+
ctx.db.addPackageFile({
|
|
126
|
+
package_release_id: newPackageRelease.package_release_id,
|
|
127
|
+
file_path: "/dist/index.js",
|
|
128
|
+
content_text: compiled_js,
|
|
129
|
+
created_at: currentTime,
|
|
130
|
+
})
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Add circuit JSON if provided
|
|
134
|
+
if (circuit_json) {
|
|
135
|
+
ctx.db.addPackageFile({
|
|
136
|
+
package_release_id: newPackageRelease.package_release_id,
|
|
137
|
+
file_path: "/dist/circuit.json",
|
|
138
|
+
content_text: JSON.stringify(circuit_json),
|
|
139
|
+
created_at: currentTime,
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Create the snippet response object
|
|
144
|
+
const snippetResponse = {
|
|
145
|
+
snippet_id: newPackage.package_id,
|
|
146
|
+
package_release_id: newPackageRelease.package_release_id,
|
|
147
|
+
name: newPackage.name,
|
|
148
|
+
unscoped_name: newPackage.unscoped_name,
|
|
149
|
+
owner_name: ctx.auth.github_username,
|
|
150
|
+
code,
|
|
151
|
+
dts,
|
|
152
|
+
compiled_js,
|
|
153
|
+
star_count: 0,
|
|
154
|
+
created_at: currentTime,
|
|
155
|
+
updated_at: currentTime,
|
|
156
|
+
snippet_type: snippet_type,
|
|
157
|
+
circuit_json: circuit_json || [],
|
|
158
|
+
description: description,
|
|
159
|
+
is_starred: false,
|
|
160
|
+
version: "0.0.1",
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return ctx.json({
|
|
164
|
+
ok: true,
|
|
165
|
+
snippet: snippetResponse,
|
|
166
|
+
})
|
|
68
167
|
} catch (error) {
|
|
69
168
|
return ctx.error(500, {
|
|
70
169
|
error_code: "snippet_creation_failed",
|
|
71
170
|
message: `Failed to create snippet: ${error}`,
|
|
72
171
|
})
|
|
73
172
|
}
|
|
74
|
-
|
|
75
|
-
return ctx.json({
|
|
76
|
-
ok: true,
|
|
77
|
-
snippet: newSnippet as any,
|
|
78
|
-
})
|
|
79
173
|
})
|
|
@@ -13,8 +13,8 @@ export default withRouteSpec({
|
|
|
13
13
|
})(async (req, ctx) => {
|
|
14
14
|
const { snippet_id } = req.jsonBody
|
|
15
15
|
|
|
16
|
-
const snippetIndex = ctx.db.
|
|
17
|
-
(s) => s.
|
|
16
|
+
const snippetIndex = ctx.db.packages.findIndex(
|
|
17
|
+
(s) => s.package_id === snippet_id,
|
|
18
18
|
)
|
|
19
19
|
|
|
20
20
|
if (snippetIndex === -1) {
|
|
@@ -24,16 +24,16 @@ export default withRouteSpec({
|
|
|
24
24
|
})
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
const snippet = ctx.db.
|
|
27
|
+
const snippet = ctx.db.packages[snippetIndex]
|
|
28
28
|
|
|
29
|
-
if (snippet.
|
|
29
|
+
if (snippet.creator_account_id !== ctx.auth.github_username) {
|
|
30
30
|
return ctx.error(403, {
|
|
31
31
|
error_code: "forbidden",
|
|
32
32
|
message: "You don't have permission to delete this snippet",
|
|
33
33
|
})
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
ctx.db.
|
|
36
|
+
ctx.db.packages.splice(snippetIndex, 1)
|
|
37
37
|
|
|
38
38
|
return ctx.json({
|
|
39
39
|
ok: true,
|
|
@@ -21,11 +21,19 @@ export default withRouteSpec({
|
|
|
21
21
|
const fileName = rest.join("/")
|
|
22
22
|
|
|
23
23
|
// Find the snippet
|
|
24
|
-
const
|
|
25
|
-
(s) => s.
|
|
24
|
+
const _package = ctx.db.packages.find(
|
|
25
|
+
(s) => s.owner_github_username === owner && s.unscoped_name === packageName,
|
|
26
26
|
)
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
const packageRelease = ctx.db.packageReleases.find(
|
|
29
|
+
(p) => p.package_id === _package?.package_id,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
const packageFiles = ctx.db.packageFiles.filter(
|
|
33
|
+
(p) => p.package_release_id === packageRelease?.package_release_id,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
if (!_package) {
|
|
29
37
|
return ctx.error(404, {
|
|
30
38
|
error_code: "snippet_not_found",
|
|
31
39
|
message: "Snippet not found",
|
|
@@ -64,21 +72,23 @@ export default withRouteSpec({
|
|
|
64
72
|
type: "file",
|
|
65
73
|
name: "index.ts",
|
|
66
74
|
hash: "placeholder_hash",
|
|
67
|
-
time:
|
|
68
|
-
size:
|
|
75
|
+
time: packageRelease?.created_at,
|
|
76
|
+
size: packageFiles.find((f) => f.file_path === "index.ts")?.content_text
|
|
77
|
+
?.length,
|
|
69
78
|
},
|
|
70
79
|
{
|
|
71
80
|
type: "file",
|
|
72
81
|
name: "index.d.ts",
|
|
73
82
|
hash: "placeholder_hash",
|
|
74
|
-
time:
|
|
75
|
-
size: (
|
|
83
|
+
time: packageRelease?.created_at,
|
|
84
|
+
size: packageFiles.find((f) => f.file_path === "index.d.ts")
|
|
85
|
+
?.content_text?.length,
|
|
76
86
|
},
|
|
77
87
|
{
|
|
78
88
|
type: "file",
|
|
79
89
|
name: "package.json",
|
|
80
90
|
hash: "placeholder_hash",
|
|
81
|
-
time:
|
|
91
|
+
time: packageRelease?.created_at,
|
|
82
92
|
size: JSON.stringify({
|
|
83
93
|
name: `@tsci/${owner}.${packageName}`,
|
|
84
94
|
version: version || "0.0.1",
|
|
@@ -117,10 +127,14 @@ export default withRouteSpec({
|
|
|
117
127
|
let content: string
|
|
118
128
|
switch (fileName) {
|
|
119
129
|
case "index.ts":
|
|
120
|
-
content =
|
|
130
|
+
content =
|
|
131
|
+
packageFiles.find((f) => f.file_path === "index.tsx")?.content_text ||
|
|
132
|
+
""
|
|
121
133
|
break
|
|
122
134
|
case "index.d.ts":
|
|
123
|
-
content =
|
|
135
|
+
content =
|
|
136
|
+
packageFiles.find((f) => f.file_path === "/dist/index.d.ts")
|
|
137
|
+
?.content_text || ""
|
|
124
138
|
break
|
|
125
139
|
case "package.json":
|
|
126
140
|
content = JSON.stringify(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { snippetSchema } from "fake-snippets-api/lib/db/schema"
|
|
1
2
|
import { withRouteSpec } from "fake-snippets-api/lib/middleware/with-winter-spec"
|
|
2
3
|
import { z } from "zod"
|
|
3
|
-
import { snippetSchema } from "fake-snippets-api/lib/db/schema"
|
|
4
4
|
|
|
5
5
|
export default withRouteSpec({
|
|
6
6
|
methods: ["GET", "POST"],
|
|
@@ -19,16 +19,50 @@ export default withRouteSpec({
|
|
|
19
19
|
})(async (req, ctx) => {
|
|
20
20
|
const { snippet_id, name, owner_name, unscoped_name } = req.commonParams
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
ctx.db.
|
|
25
|
-
|
|
26
|
-
if (
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
// First try to find by snippet_id
|
|
23
|
+
if (snippet_id) {
|
|
24
|
+
const foundSnippet = ctx.db.getSnippetById(snippet_id)
|
|
25
|
+
if (foundSnippet) {
|
|
26
|
+
if (ctx.auth) {
|
|
27
|
+
foundSnippet.is_starred = ctx.db.hasStarred(
|
|
28
|
+
ctx.auth.account_id,
|
|
29
|
+
foundSnippet.snippet_id,
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
return ctx.json({
|
|
33
|
+
ok: true,
|
|
34
|
+
snippet: foundSnippet,
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// If not found by ID, try to find by other parameters
|
|
40
|
+
const foundPackage = ctx.db.packages.find((pkg) => {
|
|
41
|
+
if (!pkg.is_snippet) return false
|
|
42
|
+
if (name && pkg.name.toLowerCase() !== name.toLowerCase()) return false
|
|
43
|
+
if (
|
|
44
|
+
owner_name &&
|
|
45
|
+
pkg.owner_github_username?.toLowerCase() !== owner_name.toLowerCase()
|
|
46
|
+
)
|
|
47
|
+
return false
|
|
48
|
+
if (
|
|
49
|
+
unscoped_name &&
|
|
50
|
+
pkg.unscoped_name.toLowerCase() !== unscoped_name.toLowerCase()
|
|
51
|
+
)
|
|
52
|
+
return false
|
|
53
|
+
return true
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
if (!foundPackage) {
|
|
57
|
+
return ctx.error(404, {
|
|
58
|
+
error_code: "snippet_not_found",
|
|
59
|
+
message: `Snippet not found (searched using ${JSON.stringify(req.commonParams)})`,
|
|
29
60
|
})
|
|
61
|
+
}
|
|
30
62
|
|
|
31
|
-
|
|
63
|
+
// Convert package to snippet format
|
|
64
|
+
const snippet = ctx.db.getSnippetById(foundPackage.package_id)
|
|
65
|
+
if (!snippet) {
|
|
32
66
|
return ctx.error(404, {
|
|
33
67
|
error_code: "snippet_not_found",
|
|
34
68
|
message: `Snippet not found (searched using ${JSON.stringify(req.commonParams)})`,
|
|
@@ -36,15 +70,14 @@ export default withRouteSpec({
|
|
|
36
70
|
}
|
|
37
71
|
|
|
38
72
|
if (ctx.auth) {
|
|
39
|
-
|
|
73
|
+
snippet.is_starred = ctx.db.hasStarred(
|
|
40
74
|
ctx.auth.account_id,
|
|
41
|
-
|
|
75
|
+
snippet.snippet_id,
|
|
42
76
|
)
|
|
43
|
-
foundSnippet.is_starred = starred
|
|
44
77
|
}
|
|
45
78
|
|
|
46
79
|
return ctx.json({
|
|
47
80
|
ok: true,
|
|
48
|
-
snippet
|
|
81
|
+
snippet,
|
|
49
82
|
})
|
|
50
83
|
})
|
|
@@ -17,10 +17,45 @@ export default withRouteSpec({
|
|
|
17
17
|
})(async (req, ctx) => {
|
|
18
18
|
const { owner_name, unscoped_name } = req.commonParams
|
|
19
19
|
|
|
20
|
-
const
|
|
21
|
-
.
|
|
20
|
+
const packages = ctx.db
|
|
21
|
+
.getPackagesByAuthor(owner_name)
|
|
22
22
|
.filter((s) => !unscoped_name || s.unscoped_name === unscoped_name)
|
|
23
23
|
|
|
24
|
+
const snippets = packages.map((pkg) => {
|
|
25
|
+
const packageRelease = ctx.db.getPackageReleaseById(
|
|
26
|
+
pkg.latest_package_release_id || "",
|
|
27
|
+
)
|
|
28
|
+
const packageFiles = ctx.db.getPackageFilesByReleaseId(
|
|
29
|
+
packageRelease?.package_release_id || "",
|
|
30
|
+
)
|
|
31
|
+
const codeFile = packageFiles.find(
|
|
32
|
+
(file) => file.file_path === "index.ts" || file.file_path === "index.tsx",
|
|
33
|
+
)
|
|
34
|
+
const starCount = ctx.db.getStarCount(pkg.package_id)
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
snippet_id: pkg.package_id,
|
|
38
|
+
package_release_id: pkg.latest_package_release_id || "",
|
|
39
|
+
unscoped_name: pkg.unscoped_name,
|
|
40
|
+
name: pkg.name,
|
|
41
|
+
owner_name: pkg.owner_github_username || "",
|
|
42
|
+
description: pkg.description || "",
|
|
43
|
+
snippet_type: pkg.snippet_type || "board",
|
|
44
|
+
code: codeFile?.content_text || "",
|
|
45
|
+
dts:
|
|
46
|
+
packageFiles.find((file) => file.file_path === "/dist/index.d.ts")
|
|
47
|
+
?.content_text || "",
|
|
48
|
+
compiled_js:
|
|
49
|
+
packageFiles.find((file) => file.file_path === "/dist/index.js")
|
|
50
|
+
?.content_text || "",
|
|
51
|
+
created_at: pkg.created_at,
|
|
52
|
+
updated_at: pkg.updated_at,
|
|
53
|
+
star_count: starCount,
|
|
54
|
+
is_starred: false,
|
|
55
|
+
version: pkg.latest_version || "0.0.1",
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
|
|
24
59
|
return ctx.json({
|
|
25
60
|
ok: true,
|
|
26
61
|
snippets,
|
|
@@ -33,20 +33,39 @@ export default withRouteSpec({
|
|
|
33
33
|
manual_edits_json_content,
|
|
34
34
|
} = req.jsonBody
|
|
35
35
|
|
|
36
|
-
const
|
|
37
|
-
(s) => s.
|
|
36
|
+
const packageIndex = ctx.db.packages.findIndex(
|
|
37
|
+
(s) => s.package_id === snippet_id,
|
|
38
38
|
)
|
|
39
39
|
|
|
40
|
-
if (
|
|
40
|
+
if (packageIndex === -1) {
|
|
41
41
|
return ctx.error(404, {
|
|
42
42
|
error_code: "snippet_not_found",
|
|
43
43
|
message: "Snippet not found",
|
|
44
44
|
})
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
const
|
|
47
|
+
const _package = ctx.db.packages[packageIndex]
|
|
48
|
+
const packageRelease = ctx.db.packageReleases.find(
|
|
49
|
+
(r) => r.package_release_id === _package.latest_package_release_id,
|
|
50
|
+
)
|
|
51
|
+
const packageFiles = ctx.db.packageFiles.filter(
|
|
52
|
+
(f) => f.package_release_id === packageRelease?.package_release_id,
|
|
53
|
+
)
|
|
54
|
+
const codeFile = packageFiles.find(
|
|
55
|
+
(f) => f.file_path === "index.tsx" || f.file_path === "index.ts",
|
|
56
|
+
)
|
|
57
|
+
const dtsFile = packageFiles.find((f) => f.file_path === "/dist/index.d.ts")
|
|
58
|
+
const compiledJsFile = packageFiles.find(
|
|
59
|
+
(f) => f.file_path === "/dist/index.js",
|
|
60
|
+
)
|
|
61
|
+
const manualEditsJsonFile = packageFiles.find(
|
|
62
|
+
(f) => f.file_path === "manual-edits.json",
|
|
63
|
+
)
|
|
64
|
+
const circuitJsonFile = packageFiles.find(
|
|
65
|
+
(f) => f.file_path === "/dist/circuit.json",
|
|
66
|
+
)
|
|
48
67
|
|
|
49
|
-
if (
|
|
68
|
+
if (_package.creator_account_id !== ctx.auth.account_id) {
|
|
50
69
|
return ctx.error(403, {
|
|
51
70
|
error_code: "forbidden",
|
|
52
71
|
message: "You don't have permission to update this snippet",
|
|
@@ -54,21 +73,24 @@ export default withRouteSpec({
|
|
|
54
73
|
}
|
|
55
74
|
|
|
56
75
|
const updatedSnippet = ctx.db.updateSnippet(snippet_id, {
|
|
57
|
-
code: code ??
|
|
58
|
-
description: description ??
|
|
59
|
-
unscoped_name: unscoped_name ??
|
|
76
|
+
code: code ?? codeFile?.content_text ?? "",
|
|
77
|
+
description: description ?? _package.description ?? "",
|
|
78
|
+
unscoped_name: unscoped_name ?? _package.unscoped_name,
|
|
60
79
|
name: unscoped_name
|
|
61
80
|
? `${ctx.auth.github_username}/${unscoped_name}`
|
|
62
|
-
:
|
|
63
|
-
dts: dts ??
|
|
64
|
-
compiled_js: compiled_js
|
|
81
|
+
: _package.name,
|
|
82
|
+
dts: dts ?? dtsFile?.content_text ?? "",
|
|
83
|
+
compiled_js: compiled_js ?? compiledJsFile?.content_text ?? "",
|
|
65
84
|
manual_edits_json_content:
|
|
66
85
|
manual_edits_json_content !== undefined
|
|
67
86
|
? manual_edits_json_content
|
|
68
|
-
:
|
|
87
|
+
: (manualEditsJsonFile?.content_text ?? ""),
|
|
69
88
|
circuit_json:
|
|
70
|
-
circuit_json
|
|
71
|
-
|
|
89
|
+
circuit_json ??
|
|
90
|
+
(circuitJsonFile?.content_text
|
|
91
|
+
? JSON.parse(circuitJsonFile.content_text)
|
|
92
|
+
: []),
|
|
93
|
+
snippet_type: snippet_type ?? _package.snippet_type,
|
|
72
94
|
updated_at: new Date().toISOString(),
|
|
73
95
|
})
|
|
74
96
|
|