@tscircuit/fake-snippets 0.0.6 → 0.0.7
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/routes/package_files/create.test.ts +375 -0
- package/bun-tests/fake-snippets-api/routes/package_files/download.test.ts +248 -0
- package/bun-tests/fake-snippets-api/routes/package_files/get.test.ts +220 -0
- package/bun-tests/fake-snippets-api/routes/package_files/list.test.ts +204 -0
- package/bun-tests/fake-snippets-api/routes/package_releases/get.test.ts +0 -1
- package/bun.lock +97 -73
- package/dist/bundle.js +584 -212
- package/fake-snippets-api/lib/db/db-client.ts +13 -0
- package/fake-snippets-api/lib/package_file/get-package-file-id-from-file-descriptor.ts +168 -0
- package/fake-snippets-api/lib/package_release/find-package-release-id.ts +122 -0
- package/fake-snippets-api/routes/api/package_files/create.ts +132 -0
- package/fake-snippets-api/routes/api/package_files/download.ts +70 -153
- package/fake-snippets-api/routes/api/package_files/get.ts +24 -5
- package/fake-snippets-api/routes/api/package_files/list.ts +16 -28
- package/index.html +12 -1
- package/package.json +9 -9
- package/playwright-tests/profile-page.spec.ts +59 -0
- package/playwright-tests/snapshots/profile-page.spec.ts-profile-page-before-delete.png +0 -0
- package/playwright-tests/snapshots/profile-page.spec.ts-profile-page-delete-dialog.png +0 -0
- package/playwright-tests/snapshots/profile-page.spec.ts-profile-page-dropdown-open.png +0 -0
- package/scripts/generate-image-sizes.ts +0 -1
- package/scripts/generate_bundle_stats.js +22 -6
- package/src/components/AiChatInterface.tsx +8 -0
- package/src/components/Analytics.tsx +1 -1
- package/src/components/CodeAndPreview.tsx +9 -3
- package/src/components/CreateNewSnippetWithAiHero.tsx +6 -2
- package/src/components/EditorNav.tsx +4 -0
- package/src/components/Footer.tsx +1 -1
- package/src/components/Header.tsx +7 -10
- package/src/components/HeaderLogin.tsx +1 -1
- package/src/components/PreviewContent.tsx +4 -1
- package/src/components/SnippetList.tsx +71 -0
- package/src/lib/templates/blinking-led-board-template.ts +2 -1
- package/src/pages/dashboard.tsx +19 -44
- package/src/pages/editor.tsx +1 -1
- package/src/pages/landing.tsx +8 -16
- package/src/pages/quickstart.tsx +9 -9
- package/src/pages/user-profile.tsx +50 -3
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
packageSchema,
|
|
19
19
|
Package,
|
|
20
20
|
PackageRelease,
|
|
21
|
+
PackageFile,
|
|
21
22
|
} from "./schema.ts"
|
|
22
23
|
import { combine } from "zustand/middleware"
|
|
23
24
|
import { seed as seedFn } from "./seed"
|
|
@@ -417,4 +418,16 @@ const initializer = combine(databaseSchema.parse({}), (set, get) => ({
|
|
|
417
418
|
),
|
|
418
419
|
}))
|
|
419
420
|
},
|
|
421
|
+
addPackageFile: (
|
|
422
|
+
packageFile: Omit<PackageFile, "package_file_id">,
|
|
423
|
+
): PackageFile => {
|
|
424
|
+
const newPackageFile = {
|
|
425
|
+
package_file_id: `package_file_${Date.now()}`,
|
|
426
|
+
...packageFile,
|
|
427
|
+
}
|
|
428
|
+
set((state) => ({
|
|
429
|
+
packageFiles: [...state.packageFiles, newPackageFile],
|
|
430
|
+
}))
|
|
431
|
+
return newPackageFile
|
|
432
|
+
},
|
|
420
433
|
}))
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { NotFoundError } from "winterspec/middleware"
|
|
2
|
+
import * as ZT from "../db/schema"
|
|
3
|
+
export const getPackageFileIdFromFileDescriptor = async (
|
|
4
|
+
descriptor:
|
|
5
|
+
| { package_file_id: string }
|
|
6
|
+
| { package_release_id: string; file_path: string }
|
|
7
|
+
| { package_id: string; version?: string; file_path: string }
|
|
8
|
+
| { package_name: string; version?: string; file_path: string }
|
|
9
|
+
| { package_name_with_version: string; file_path: string },
|
|
10
|
+
ctx: { db: any },
|
|
11
|
+
): Promise<string> => {
|
|
12
|
+
if ("package_file_id" in descriptor) {
|
|
13
|
+
const packageFile = ctx.db.packageFiles.find(
|
|
14
|
+
(pf: ZT.PackageFile) => pf.package_file_id === descriptor.package_file_id,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
if (!packageFile) {
|
|
18
|
+
throw new NotFoundError("Package file not found")
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return descriptor.package_file_id
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if ("package_release_id" in descriptor) {
|
|
25
|
+
const { package_release_id, file_path } = descriptor
|
|
26
|
+
const packageFile = ctx.db.packageFiles.find(
|
|
27
|
+
(pf: ZT.PackageFile) =>
|
|
28
|
+
pf.package_release_id === package_release_id &&
|
|
29
|
+
pf.file_path === file_path,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
if (!packageFile) {
|
|
33
|
+
throw new NotFoundError("Package file not found")
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return packageFile.package_file_id
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if ("package_id" in descriptor) {
|
|
40
|
+
const { package_id, version, file_path } = descriptor
|
|
41
|
+
|
|
42
|
+
// Verify package exists
|
|
43
|
+
const pkg = ctx.db.packages.find(
|
|
44
|
+
(p: ZT.Package) => p.package_id === package_id,
|
|
45
|
+
)
|
|
46
|
+
if (!pkg) {
|
|
47
|
+
throw new NotFoundError("Package not found")
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Find the package release
|
|
51
|
+
let packageRelease
|
|
52
|
+
if (version) {
|
|
53
|
+
packageRelease = ctx.db.packageReleases.find(
|
|
54
|
+
(pr: ZT.PackageRelease) =>
|
|
55
|
+
pr.package_id === package_id && pr.version === version,
|
|
56
|
+
)
|
|
57
|
+
} else {
|
|
58
|
+
packageRelease = ctx.db.packageReleases.find(
|
|
59
|
+
(pr: ZT.PackageRelease) => pr.package_id === package_id && pr.is_latest,
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!packageRelease) {
|
|
64
|
+
throw new NotFoundError("Package release not found")
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Find the file
|
|
68
|
+
const packageFile = ctx.db.packageFiles.find(
|
|
69
|
+
(pf: ZT.PackageFile) =>
|
|
70
|
+
pf.package_release_id === packageRelease.package_release_id &&
|
|
71
|
+
pf.file_path === file_path,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
if (!packageFile) {
|
|
75
|
+
throw new NotFoundError("Package file not found")
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return packageFile.package_file_id
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if ("package_name" in descriptor) {
|
|
82
|
+
const { package_name, version, file_path } = descriptor
|
|
83
|
+
|
|
84
|
+
// Find the package first
|
|
85
|
+
const pkg = ctx.db.packages.find((p: ZT.Package) => p.name === package_name)
|
|
86
|
+
if (!pkg) {
|
|
87
|
+
throw new NotFoundError(`Package not found: ${package_name}`)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Find the package release
|
|
91
|
+
let packageRelease
|
|
92
|
+
if (version) {
|
|
93
|
+
packageRelease = ctx.db.packageReleases.find(
|
|
94
|
+
(pr: ZT.PackageRelease) =>
|
|
95
|
+
pr.package_id === pkg.package_id && pr.version === version,
|
|
96
|
+
)
|
|
97
|
+
} else {
|
|
98
|
+
packageRelease = ctx.db.packageReleases.find(
|
|
99
|
+
(pr: ZT.PackageRelease) =>
|
|
100
|
+
pr.package_id === pkg.package_id && pr.is_latest,
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (!packageRelease) {
|
|
105
|
+
throw new NotFoundError("Package release not found")
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Find the file
|
|
109
|
+
const packageFile = ctx.db.packageFiles.find(
|
|
110
|
+
(pf: ZT.PackageFile) =>
|
|
111
|
+
pf.package_release_id === packageRelease.package_release_id &&
|
|
112
|
+
pf.file_path === file_path,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
if (!packageFile) {
|
|
116
|
+
throw new NotFoundError("Package file not found")
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return packageFile.package_file_id
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if ("package_name_with_version" in descriptor) {
|
|
123
|
+
const { package_name_with_version, file_path } = descriptor
|
|
124
|
+
const packageName = package_name_with_version.split("@")[1]
|
|
125
|
+
const version = package_name_with_version.split("@")[2]
|
|
126
|
+
|
|
127
|
+
// Find the package
|
|
128
|
+
const pkg = ctx.db.packages.find((p: ZT.Package) => p.name === packageName)
|
|
129
|
+
if (!pkg) {
|
|
130
|
+
throw new NotFoundError(`Package not found: ${packageName}`)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Find the package release
|
|
134
|
+
let packageRelease
|
|
135
|
+
if (!version || version === "latest") {
|
|
136
|
+
packageRelease = ctx.db.packageReleases.find(
|
|
137
|
+
(pr: ZT.PackageRelease) =>
|
|
138
|
+
pr.package_id === pkg.package_id && pr.is_latest,
|
|
139
|
+
)
|
|
140
|
+
} else {
|
|
141
|
+
packageRelease = ctx.db.packageReleases.find(
|
|
142
|
+
(pr: ZT.PackageRelease) =>
|
|
143
|
+
pr.package_id === pkg.package_id && pr.version === version,
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (!packageRelease) {
|
|
148
|
+
throw new NotFoundError(
|
|
149
|
+
`Package release not found for version: ${version || "latest"}`,
|
|
150
|
+
)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Find the file
|
|
154
|
+
const packageFile = ctx.db.packageFiles.find(
|
|
155
|
+
(pf: ZT.PackageFile) =>
|
|
156
|
+
pf.package_release_id === packageRelease.package_release_id &&
|
|
157
|
+
pf.file_path === file_path,
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
if (!packageFile) {
|
|
161
|
+
throw new NotFoundError(`Package file not found: ${file_path}`)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return packageFile.package_file_id
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
throw new NotFoundError("Invalid package file descriptor")
|
|
168
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { Package, PackageRelease } from "fake-snippets-api/lib/db/schema"
|
|
2
|
+
|
|
3
|
+
export const findPackageReleaseId = async (
|
|
4
|
+
params:
|
|
5
|
+
| string
|
|
6
|
+
| {
|
|
7
|
+
package_release_id: string
|
|
8
|
+
}
|
|
9
|
+
| {
|
|
10
|
+
package_name: string
|
|
11
|
+
use_latest_version: true
|
|
12
|
+
}
|
|
13
|
+
| {
|
|
14
|
+
package_name_with_version: string
|
|
15
|
+
}
|
|
16
|
+
| {
|
|
17
|
+
package_release_id?: string | undefined
|
|
18
|
+
package_name_with_version?: string | undefined
|
|
19
|
+
},
|
|
20
|
+
ctx: { db: any },
|
|
21
|
+
): Promise<string | null> => {
|
|
22
|
+
if (typeof params === "string") {
|
|
23
|
+
return findPackageReleaseIdFromPackageNameWithVersion(params, ctx.db)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (
|
|
27
|
+
"package_name_with_version" in params &&
|
|
28
|
+
params.package_name_with_version
|
|
29
|
+
) {
|
|
30
|
+
const { package_name_with_version } = params
|
|
31
|
+
|
|
32
|
+
if (package_name_with_version.endsWith("@latest")) {
|
|
33
|
+
const [packageName] = package_name_with_version.split("@")
|
|
34
|
+
return findPackageReleaseId(
|
|
35
|
+
{
|
|
36
|
+
package_name: packageName!,
|
|
37
|
+
use_latest_version: true,
|
|
38
|
+
},
|
|
39
|
+
ctx,
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
return findPackageReleaseIdFromPackageNameWithVersion(
|
|
43
|
+
package_name_with_version!,
|
|
44
|
+
ctx.db,
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if ("package_release_id" in params && params.package_release_id) {
|
|
49
|
+
const packageRelease = ctx.db.packageReleases.find(
|
|
50
|
+
(pr: PackageRelease) =>
|
|
51
|
+
pr.package_release_id === params.package_release_id,
|
|
52
|
+
)
|
|
53
|
+
if (!packageRelease) {
|
|
54
|
+
return null
|
|
55
|
+
}
|
|
56
|
+
return params.package_release_id
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if ("package_name" in params) {
|
|
60
|
+
const { package_name, use_latest_version } = params
|
|
61
|
+
|
|
62
|
+
if (!use_latest_version) {
|
|
63
|
+
throw new Error("use_latest_version must be true")
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const pkg = ctx.db.packages.find(
|
|
67
|
+
(p: Package) => p.name === package_name.replace(/^@/, ""),
|
|
68
|
+
)
|
|
69
|
+
if (!pkg) {
|
|
70
|
+
return null
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const packageRelease = ctx.db.packageReleases.find(
|
|
74
|
+
(pr: PackageRelease) => pr.package_id === pkg.package_id && pr.is_latest,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
if (!packageRelease) {
|
|
78
|
+
return null
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return packageRelease.package_release_id
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return null
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export const findPackageReleaseIdFromPackageNameWithVersion = (
|
|
88
|
+
packageNameWithVersion: string,
|
|
89
|
+
db: any,
|
|
90
|
+
): string | null => {
|
|
91
|
+
if (!packageNameWithVersion) return null
|
|
92
|
+
|
|
93
|
+
const [packageName, version] = packageNameWithVersion
|
|
94
|
+
.replace(/^@/, "")
|
|
95
|
+
.split("@")
|
|
96
|
+
|
|
97
|
+
const pkg = db.packages.find((p: Package) => p.name === packageName)
|
|
98
|
+
if (!pkg) {
|
|
99
|
+
return null
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
let packageRelease
|
|
103
|
+
|
|
104
|
+
if (!version || version === "latest") {
|
|
105
|
+
packageRelease = db.packageReleases.find(
|
|
106
|
+
(pr: PackageRelease) => pr.package_id === pkg.package_id && pr.is_latest,
|
|
107
|
+
)
|
|
108
|
+
} else {
|
|
109
|
+
packageRelease = db.packageReleases.find(
|
|
110
|
+
(pr: PackageRelease) =>
|
|
111
|
+
pr.package_id === pkg.package_id && pr.version === version,
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (!packageRelease) {
|
|
116
|
+
return null
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
console.log("packageRelease", packageRelease)
|
|
120
|
+
|
|
121
|
+
return packageRelease.package_release_id
|
|
122
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import * as zt from "fake-snippets-api/lib/db/schema"
|
|
2
|
+
import { findPackageReleaseId } from "fake-snippets-api/lib/package_release/find-package-release-id"
|
|
3
|
+
import { withRouteSpec } from "fake-snippets-api/lib/with-winter-spec"
|
|
4
|
+
import { z } from "zod"
|
|
5
|
+
|
|
6
|
+
const routeSpec = {
|
|
7
|
+
methods: ["POST"],
|
|
8
|
+
auth: "none",
|
|
9
|
+
jsonBody: z
|
|
10
|
+
.object({
|
|
11
|
+
file_path: z.string(),
|
|
12
|
+
is_release_tarball: z.boolean().optional().default(false),
|
|
13
|
+
content_mimetype: z.string().optional(),
|
|
14
|
+
content_text: z.string().optional(),
|
|
15
|
+
content_base64: z.string().optional(),
|
|
16
|
+
package_release_id: z.string().optional(),
|
|
17
|
+
package_name_with_version: z.string().optional(),
|
|
18
|
+
npm_pack_output: z.any().optional(),
|
|
19
|
+
})
|
|
20
|
+
.refine((v) => {
|
|
21
|
+
if (v.package_release_id) return true
|
|
22
|
+
if (v.package_name_with_version) return true
|
|
23
|
+
return false
|
|
24
|
+
}, "Must specify either package_release_id or package_name_with_version")
|
|
25
|
+
.refine((v) => {
|
|
26
|
+
if (v.package_release_id && v.package_name_with_version) return false
|
|
27
|
+
return true
|
|
28
|
+
}, "Cannot specify both package_release_id and package_name_with_version")
|
|
29
|
+
.refine((v) => {
|
|
30
|
+
if (v.content_base64 && v.content_text) return false
|
|
31
|
+
if (!v.content_base64 && !v.content_text) return false
|
|
32
|
+
return true
|
|
33
|
+
}, "Either content_base64 or content_text is required"),
|
|
34
|
+
jsonResponse: z.object({
|
|
35
|
+
ok: z.boolean(),
|
|
36
|
+
package_file: zt.packageFileSchema,
|
|
37
|
+
}),
|
|
38
|
+
} as const
|
|
39
|
+
|
|
40
|
+
export default withRouteSpec(routeSpec)(async (req, ctx) => {
|
|
41
|
+
const {
|
|
42
|
+
file_path,
|
|
43
|
+
content_mimetype: providedContentMimetype,
|
|
44
|
+
content_base64,
|
|
45
|
+
content_text,
|
|
46
|
+
is_release_tarball,
|
|
47
|
+
npm_pack_output,
|
|
48
|
+
} = req.jsonBody
|
|
49
|
+
|
|
50
|
+
if (is_release_tarball && !npm_pack_output) {
|
|
51
|
+
return ctx.error(400, {
|
|
52
|
+
error_code: "missing_options",
|
|
53
|
+
message: "npm_pack_output is required for release tarballs",
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!is_release_tarball && npm_pack_output) {
|
|
58
|
+
return ctx.error(404, {
|
|
59
|
+
error_code: "invalid_options",
|
|
60
|
+
message: "npm_pack_output is only valid for release tarballs",
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let packageReleaseId = req.jsonBody.package_release_id
|
|
65
|
+
|
|
66
|
+
if (!packageReleaseId && req.jsonBody.package_name_with_version) {
|
|
67
|
+
const foundPackageReleaseId = await findPackageReleaseId(
|
|
68
|
+
req.jsonBody.package_name_with_version,
|
|
69
|
+
ctx,
|
|
70
|
+
)
|
|
71
|
+
if (foundPackageReleaseId) {
|
|
72
|
+
packageReleaseId = foundPackageReleaseId
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (!packageReleaseId) {
|
|
77
|
+
return ctx.error(404, {
|
|
78
|
+
error_code: "package_release_not_found",
|
|
79
|
+
message: "Package release not found",
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Verify the package release exists
|
|
84
|
+
const packageRelease = ctx.db.packageReleases.find(
|
|
85
|
+
(pr) => pr.package_release_id === packageReleaseId,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
if (!packageRelease) {
|
|
89
|
+
return ctx.error(404, {
|
|
90
|
+
error_code: "package_release_not_found",
|
|
91
|
+
message: "Package release not found",
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Determine content mimetype
|
|
96
|
+
const contentMimetype =
|
|
97
|
+
providedContentMimetype ||
|
|
98
|
+
(file_path.endsWith(".ts") || file_path.endsWith(".tsx")
|
|
99
|
+
? "text/typescript"
|
|
100
|
+
: null) ||
|
|
101
|
+
(file_path.endsWith(".js") ? "application/javascript" : null) ||
|
|
102
|
+
(file_path.endsWith(".json") ? "application/json" : null) ||
|
|
103
|
+
(file_path.endsWith(".md") ? "text/markdown" : null) ||
|
|
104
|
+
(file_path.endsWith(".html") ? "text/html" : null) ||
|
|
105
|
+
(file_path.endsWith(".css") ? "text/css" : null) ||
|
|
106
|
+
"application/octet-stream"
|
|
107
|
+
|
|
108
|
+
// Create the package file
|
|
109
|
+
const newPackageFile = {
|
|
110
|
+
package_file_id: crypto.randomUUID(),
|
|
111
|
+
package_release_id: packageReleaseId,
|
|
112
|
+
file_path,
|
|
113
|
+
content_text:
|
|
114
|
+
content_text ||
|
|
115
|
+
(content_base64
|
|
116
|
+
? Buffer.from(content_base64, "base64").toString()
|
|
117
|
+
: null),
|
|
118
|
+
content_mimetype: contentMimetype,
|
|
119
|
+
is_directory: false,
|
|
120
|
+
is_release_tarball: is_release_tarball || false,
|
|
121
|
+
npm_pack_output: npm_pack_output || null,
|
|
122
|
+
created_at: new Date().toISOString(),
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Add to the test database
|
|
126
|
+
ctx.db.addPackageFile(newPackageFile)
|
|
127
|
+
|
|
128
|
+
return ctx.json({
|
|
129
|
+
ok: true,
|
|
130
|
+
package_file: newPackageFile,
|
|
131
|
+
})
|
|
132
|
+
})
|
|
@@ -1,170 +1,87 @@
|
|
|
1
|
+
import { getPackageFileIdFromFileDescriptor } from "fake-snippets-api/lib/package_file/get-package-file-id-from-file-descriptor"
|
|
2
|
+
import { findPackageReleaseId } from "fake-snippets-api/lib/package_release/find-package-release-id"
|
|
1
3
|
import { withRouteSpec } from "fake-snippets-api/lib/with-winter-spec"
|
|
2
4
|
import { z } from "zod"
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
methods: ["GET"],
|
|
6
|
+
const routeSpec = {
|
|
7
|
+
methods: ["GET", "POST"],
|
|
6
8
|
auth: "none",
|
|
7
|
-
queryParams: z
|
|
8
|
-
|
|
9
|
-
.
|
|
10
|
-
.optional()
|
|
11
|
-
.transform((v) => v === "true"),
|
|
12
|
-
jsdelivr_path: z.string(),
|
|
13
|
-
}),
|
|
14
|
-
jsonResponse: z.any(),
|
|
15
|
-
})(async (req, ctx) => {
|
|
16
|
-
const { jsdelivr_path, jsdelivr_resolve } = req.query
|
|
17
|
-
|
|
18
|
-
// Parse the file path
|
|
19
|
-
const [owner, packageWithVersion, ...rest] = jsdelivr_path.split("/")
|
|
20
|
-
if (!packageWithVersion) {
|
|
21
|
-
return ctx.error(400, {
|
|
22
|
-
error_code: "invalid_path",
|
|
23
|
-
message: "Invalid path",
|
|
9
|
+
queryParams: z
|
|
10
|
+
.object({
|
|
11
|
+
package_file_id: z.string(),
|
|
24
12
|
})
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
13
|
+
.or(
|
|
14
|
+
z.object({
|
|
15
|
+
package_name_with_version: z.string(),
|
|
16
|
+
file_path: z.string(),
|
|
17
|
+
}),
|
|
18
|
+
),
|
|
19
|
+
jsonResponse: z.any(), // Using any because we're returning binary data
|
|
20
|
+
} as const
|
|
28
21
|
|
|
29
|
-
|
|
30
|
-
|
|
22
|
+
export default withRouteSpec(routeSpec)(async (req, ctx) => {
|
|
23
|
+
let packageFileId: string | undefined
|
|
24
|
+
const params = req.query
|
|
31
25
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
// })
|
|
37
|
-
// }
|
|
26
|
+
if ("package_file_id" in params) {
|
|
27
|
+
packageFileId = params.package_file_id
|
|
28
|
+
} else if ("package_name_with_version" in params) {
|
|
29
|
+
const { package_name_with_version, file_path } = params
|
|
38
30
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
// latest: "0.0.1",
|
|
44
|
-
// },
|
|
45
|
-
// versions: ["0.0.1"],
|
|
46
|
-
// }),
|
|
47
|
-
// {
|
|
48
|
-
// status: 200,
|
|
49
|
-
// headers: { "Content-Type": "application/json" },
|
|
50
|
-
// },
|
|
51
|
-
// )
|
|
52
|
-
// }
|
|
31
|
+
const packageReleaseId = await findPackageReleaseId(
|
|
32
|
+
package_name_with_version,
|
|
33
|
+
ctx,
|
|
34
|
+
)
|
|
53
35
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
// status: 200,
|
|
61
|
-
// headers: { "Content-Type": "application/json" },
|
|
62
|
-
// },
|
|
63
|
-
// )
|
|
64
|
-
// }
|
|
36
|
+
if (!packageReleaseId) {
|
|
37
|
+
return ctx.error(404, {
|
|
38
|
+
error_code: "not_found",
|
|
39
|
+
message: "Package release not found",
|
|
40
|
+
})
|
|
41
|
+
}
|
|
65
42
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
43
|
+
try {
|
|
44
|
+
packageFileId = await getPackageFileIdFromFileDescriptor(
|
|
45
|
+
{
|
|
46
|
+
package_release_id: packageReleaseId,
|
|
47
|
+
file_path: file_path,
|
|
48
|
+
},
|
|
49
|
+
ctx,
|
|
50
|
+
)
|
|
51
|
+
} catch (error) {
|
|
52
|
+
return ctx.error(404, {
|
|
53
|
+
error_code: "not_found",
|
|
54
|
+
message: "Package file not found",
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
}
|
|
79
58
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
// hash: "placeholder_hash",
|
|
87
|
-
// time: snippet.updated_at,
|
|
88
|
-
// size: snippet.code?.length ?? 0,
|
|
89
|
-
// },
|
|
90
|
-
// {
|
|
91
|
-
// type: "file",
|
|
92
|
-
// name: "index.d.ts",
|
|
93
|
-
// hash: "placeholder_hash",
|
|
94
|
-
// time: snippet.updated_at,
|
|
95
|
-
// size: dtsFile?.content_text?.length ?? 0,
|
|
96
|
-
// },
|
|
97
|
-
// {
|
|
98
|
-
// type: "file",
|
|
99
|
-
// name: "package.json",
|
|
100
|
-
// hash: "placeholder_hash",
|
|
101
|
-
// time: snippet.updated_at,
|
|
102
|
-
// size: JSON.stringify({
|
|
103
|
-
// name: `@tsci/${owner}.${packageName}`,
|
|
104
|
-
// version: version || "0.0.1",
|
|
105
|
-
// main: "index.ts",
|
|
106
|
-
// types: "index.d.ts",
|
|
107
|
-
// }).length,
|
|
108
|
-
// },
|
|
109
|
-
// ]
|
|
59
|
+
if (!packageFileId) {
|
|
60
|
+
return ctx.error(400, {
|
|
61
|
+
error_code: "bad_request",
|
|
62
|
+
message: "Could not determine package_file_id",
|
|
63
|
+
})
|
|
64
|
+
}
|
|
110
65
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
// fileName === "flat"
|
|
115
|
-
// ? files.map((f) => ({
|
|
116
|
-
// name: `/${f.name}`,
|
|
117
|
-
// hash: f.hash,
|
|
118
|
-
// time: f.time,
|
|
119
|
-
// size: f.size,
|
|
120
|
-
// }))
|
|
121
|
-
// : [
|
|
122
|
-
// {
|
|
123
|
-
// type: "directory",
|
|
124
|
-
// name: ".",
|
|
125
|
-
// files: files,
|
|
126
|
-
// },
|
|
127
|
-
// ],
|
|
128
|
-
// }
|
|
66
|
+
const packageFile = ctx.db.packageFiles.find(
|
|
67
|
+
(pf) => pf.package_file_id === packageFileId,
|
|
68
|
+
)
|
|
129
69
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
70
|
+
if (!packageFile) {
|
|
71
|
+
return ctx.error(404, {
|
|
72
|
+
error_code: "not_found",
|
|
73
|
+
message: "Package file not found",
|
|
74
|
+
})
|
|
75
|
+
}
|
|
135
76
|
|
|
136
|
-
|
|
137
|
-
// let content: string
|
|
138
|
-
// switch (fileName) {
|
|
139
|
-
// case "index.ts":
|
|
140
|
-
// content = snippet.code ?? ""
|
|
141
|
-
// break
|
|
142
|
-
// case "index.d.ts":
|
|
143
|
-
// content = dtsFile?.content_text ?? ""
|
|
144
|
-
// break
|
|
145
|
-
// case "package.json":
|
|
146
|
-
// content = JSON.stringify(
|
|
147
|
-
// {
|
|
148
|
-
// name: `@tsci/${owner}.${packageName}`,
|
|
149
|
-
// version: version || "0.0.1",
|
|
150
|
-
// main: "index.ts",
|
|
151
|
-
// types: "index.d.ts",
|
|
152
|
-
// },
|
|
153
|
-
// null,
|
|
154
|
-
// 2,
|
|
155
|
-
// )
|
|
156
|
-
// break
|
|
157
|
-
// default:
|
|
158
|
-
// return ctx.error(404, {
|
|
159
|
-
// error_code: "file_not_found",
|
|
160
|
-
// message: "Requested file not found",
|
|
161
|
-
// })
|
|
162
|
-
// }
|
|
77
|
+
const contentType = "text/plain"
|
|
163
78
|
|
|
164
|
-
const
|
|
79
|
+
const headers = {
|
|
80
|
+
"Content-Type": contentType,
|
|
81
|
+
"Content-Disposition": `attachment; filename="${packageFile.file_path.split("/").pop()}"`,
|
|
82
|
+
"Cache-Control": "public, max-age=86400, stale-while-revalidate=604800",
|
|
83
|
+
Expires: new Date(Date.now() + 86400000).toUTCString(),
|
|
84
|
+
}
|
|
165
85
|
|
|
166
|
-
return new Response(
|
|
167
|
-
status: 200,
|
|
168
|
-
headers: { "Content-Type": "text/plain" },
|
|
169
|
-
})
|
|
86
|
+
return new Response(packageFile.content_text, { headers })
|
|
170
87
|
})
|