@tscircuit/fake-snippets 0.0.24 → 0.0.26
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/api/generated-index.js +8 -1
- package/bun-tests/fake-snippets-api/routes/orders/get.test.ts +1 -4
- package/dist/bundle.js +46 -64
- package/fake-snippets-api/routes/api/_fake/move_orders_forward.ts +39 -42
- package/fake-snippets-api/routes/api/orders/get.ts +1 -21
- package/fake-snippets-api/routes/api/package_releases/create.ts +8 -0
- package/package.json +1 -1
- package/src/App.tsx +2 -0
- package/src/components/OptimizedImage.tsx +8 -4
- package/src/hooks/use-create-package-files-mutation.ts +76 -0
- package/src/hooks/use-create-package-mutation.ts +60 -0
- package/src/hooks/use-create-package-release-mutation.ts +57 -0
- package/src/hooks/use-fork-package-mutation.ts +103 -0
- package/src/hooks/use-package-by-package-id.ts +23 -0
- package/src/hooks/use-package-by-package-name.ts +23 -0
- package/src/hooks/use-package-files.ts +84 -0
- package/src/hooks/use-package-release.ts +51 -0
- package/src/pages/beta.tsx +184 -0
|
@@ -3,66 +3,63 @@ import { z } from "zod"
|
|
|
3
3
|
import { orderSteps } from "fake-snippets-api/utils/order-steps"
|
|
4
4
|
|
|
5
5
|
export default withRouteSpec({
|
|
6
|
-
methods: ["
|
|
6
|
+
methods: ["GET"],
|
|
7
7
|
auth: "session",
|
|
8
|
-
jsonBody: z.object({
|
|
9
|
-
order_id: z.string(),
|
|
10
|
-
}),
|
|
11
8
|
jsonResponse: z.object({
|
|
12
9
|
success: z.boolean(),
|
|
13
|
-
current_step: z.string().nullable(),
|
|
14
10
|
}),
|
|
15
11
|
})(async (req, ctx) => {
|
|
16
|
-
|
|
12
|
+
// Get all orders that aren't finished
|
|
13
|
+
const orders = ctx.db.orders.filter((order) => !order.is_finished)
|
|
14
|
+
const updatedOrders = []
|
|
17
15
|
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
error_code: "order_state_not_found",
|
|
22
|
-
message: "Order state not found",
|
|
23
|
-
})
|
|
24
|
-
}
|
|
16
|
+
for (const order of orders) {
|
|
17
|
+
const orderState = ctx.db.getJlcpcbOrderStatesByOrderId(order.order_id)
|
|
18
|
+
if (!orderState) continue
|
|
25
19
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
20
|
+
// Find the next step to complete
|
|
21
|
+
let nextStepIndex = -1
|
|
22
|
+
for (let i = 0; i < orderSteps.length; i++) {
|
|
23
|
+
const step = orderSteps[i]
|
|
24
|
+
if (!orderState[step]) {
|
|
25
|
+
nextStepIndex = i
|
|
26
|
+
break
|
|
27
|
+
}
|
|
33
28
|
}
|
|
34
|
-
}
|
|
35
29
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
30
|
+
// If all steps are completed or no next step found
|
|
31
|
+
if (nextStepIndex === -1) {
|
|
32
|
+
updatedOrders.push({
|
|
33
|
+
order_id: order.order_id,
|
|
34
|
+
current_step: null,
|
|
35
|
+
})
|
|
36
|
+
continue
|
|
37
|
+
}
|
|
43
38
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
39
|
+
// Update the next step to true
|
|
40
|
+
const nextStep = orderSteps[nextStepIndex]
|
|
41
|
+
const updates = {
|
|
42
|
+
[nextStep]: true,
|
|
43
|
+
current_step: nextStep,
|
|
44
|
+
}
|
|
50
45
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (order) {
|
|
55
|
-
ctx.db.updateOrder(order_id, {
|
|
46
|
+
// If this is the last step, also update the order status
|
|
47
|
+
if (nextStepIndex === orderSteps.length - 1) {
|
|
48
|
+
ctx.db.updateOrder(order.order_id, {
|
|
56
49
|
is_finished: true,
|
|
57
50
|
completed_at: new Date().toISOString(),
|
|
58
51
|
})
|
|
59
52
|
}
|
|
60
|
-
}
|
|
61
53
|
|
|
62
|
-
|
|
54
|
+
ctx.db.updateJlcpcbOrderState(order.order_id, updates)
|
|
55
|
+
|
|
56
|
+
updatedOrders.push({
|
|
57
|
+
order_id: order.order_id,
|
|
58
|
+
current_step: nextStep,
|
|
59
|
+
})
|
|
60
|
+
}
|
|
63
61
|
|
|
64
62
|
return ctx.json({
|
|
65
63
|
success: true,
|
|
66
|
-
current_step: nextStep,
|
|
67
64
|
})
|
|
68
65
|
})
|
|
@@ -5,27 +5,7 @@ import {
|
|
|
5
5
|
} from "fake-snippets-api/lib/db/schema"
|
|
6
6
|
import { withRouteSpec } from "fake-snippets-api/lib/middleware/with-winter-spec"
|
|
7
7
|
import { z } from "zod"
|
|
8
|
-
|
|
9
|
-
export const simulateScenarios = [
|
|
10
|
-
"are_gerbers_generated",
|
|
11
|
-
"are_gerbers_uploaded",
|
|
12
|
-
"is_gerber_analyzed",
|
|
13
|
-
"are_initial_costs_calculated",
|
|
14
|
-
"is_pcb_added_to_cart",
|
|
15
|
-
"is_bom_uploaded",
|
|
16
|
-
"is_pnp_uploaded",
|
|
17
|
-
"is_bom_pnp_analyzed",
|
|
18
|
-
"is_bom_parsing_complete",
|
|
19
|
-
"are_components_available",
|
|
20
|
-
"is_patch_map_generated",
|
|
21
|
-
"is_json_merge_file_created",
|
|
22
|
-
"is_dfm_result_generated",
|
|
23
|
-
"are_files_downloaded",
|
|
24
|
-
"are_product_categories_fetched",
|
|
25
|
-
"are_final_costs_calculated",
|
|
26
|
-
"is_json_merge_file_updated",
|
|
27
|
-
"is_added_to_cart",
|
|
28
|
-
] as const
|
|
8
|
+
import { orderSteps as simulateScenarios } from "fake-snippets-api/utils/order-steps"
|
|
29
9
|
|
|
30
10
|
const defaultOrderState = {
|
|
31
11
|
are_gerbers_uploaded: false,
|
|
@@ -76,6 +76,14 @@ export default withRouteSpec({
|
|
|
76
76
|
commit_sha: commit_sha ?? null,
|
|
77
77
|
})
|
|
78
78
|
|
|
79
|
+
// Update the package's latest_package_release_id if this is the latest release
|
|
80
|
+
if (is_latest) {
|
|
81
|
+
ctx.db.updatePackage(package_id, {
|
|
82
|
+
latest_package_release_id: newPackageRelease.package_release_id,
|
|
83
|
+
latest_version: version,
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
|
|
79
87
|
return ctx.json({
|
|
80
88
|
ok: true,
|
|
81
89
|
package_release: publicMapPackageRelease(newPackageRelease),
|
package/package.json
CHANGED
package/src/App.tsx
CHANGED
|
@@ -70,6 +70,7 @@ const UserProfilePage = lazyImport(() => import("@/pages/user-profile"))
|
|
|
70
70
|
const ViewOrderPage = lazyImport(() => import("@/pages/view-order"))
|
|
71
71
|
const ViewSnippetPage = lazyImport(() => import("@/pages/view-snippet"))
|
|
72
72
|
const DevLoginPage = lazyImport(() => import("@/pages/dev-login"))
|
|
73
|
+
const BetaPage = lazyImport(() => import("@/pages/beta"))
|
|
73
74
|
|
|
74
75
|
class ErrorBoundary extends React.Component<
|
|
75
76
|
{ children: React.ReactNode },
|
|
@@ -99,6 +100,7 @@ function App() {
|
|
|
99
100
|
<Suspense fallback={<FullPageLoader />}>
|
|
100
101
|
<Switch>
|
|
101
102
|
<Route path="/" component={LandingPage} />
|
|
103
|
+
<Route path="/beta" component={BetaPage} />
|
|
102
104
|
<Route path="/editor" component={EditorPage} />
|
|
103
105
|
<Route path="/quickstart" component={QuickstartPage} />
|
|
104
106
|
<Route path="/dashboard" component={DashboardPage} />
|
|
@@ -28,6 +28,7 @@ interface OptimizedImageProps
|
|
|
28
28
|
src: string
|
|
29
29
|
alt: string
|
|
30
30
|
priority?: boolean
|
|
31
|
+
fallbackSrc?: string
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
const getImageSizes = (src: string) => {
|
|
@@ -51,10 +52,12 @@ export function OptimizedImage({
|
|
|
51
52
|
alt,
|
|
52
53
|
className,
|
|
53
54
|
priority = false,
|
|
55
|
+
fallbackSrc = "/assets/fallback-image.svg",
|
|
54
56
|
...props
|
|
55
57
|
}: OptimizedImageProps) {
|
|
58
|
+
const [currentSrc, setCurrentSrc] = useState(src)
|
|
56
59
|
const [imageLoading, setImageLoading] = useState(true)
|
|
57
|
-
const { srcSet, sizes } = getImageSizes(
|
|
60
|
+
const { srcSet, sizes } = getImageSizes(currentSrc)
|
|
58
61
|
|
|
59
62
|
useEffect(() => {
|
|
60
63
|
if (priority) {
|
|
@@ -75,7 +78,7 @@ export function OptimizedImage({
|
|
|
75
78
|
|
|
76
79
|
return (
|
|
77
80
|
<img
|
|
78
|
-
src={
|
|
81
|
+
src={currentSrc}
|
|
79
82
|
srcSet={srcSet}
|
|
80
83
|
sizes={sizes}
|
|
81
84
|
alt={alt}
|
|
@@ -86,8 +89,9 @@ export function OptimizedImage({
|
|
|
86
89
|
imageLoading ? "animate-pulse bg-gray-200" : ""
|
|
87
90
|
} object-contain`}
|
|
88
91
|
onLoad={() => setImageLoading(false)}
|
|
89
|
-
onError={(
|
|
90
|
-
console.error("Image failed to load:",
|
|
92
|
+
onError={() => {
|
|
93
|
+
console.error("Image failed to load:", currentSrc)
|
|
94
|
+
setCurrentSrc(fallbackSrc)
|
|
91
95
|
setImageLoading(false)
|
|
92
96
|
}}
|
|
93
97
|
{...props}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { PackageFile } from "fake-snippets-api/lib/db/schema"
|
|
2
|
+
import { useMutation } from "react-query"
|
|
3
|
+
import { useAxios } from "./use-axios"
|
|
4
|
+
|
|
5
|
+
export const useCreatePackageFilesMutation = ({
|
|
6
|
+
onSuccess,
|
|
7
|
+
}: { onSuccess?: (packageFile: PackageFile) => void } = {}) => {
|
|
8
|
+
const axios = useAxios()
|
|
9
|
+
|
|
10
|
+
return useMutation(
|
|
11
|
+
["createPackageFiles"],
|
|
12
|
+
async ({
|
|
13
|
+
file_path,
|
|
14
|
+
content_text,
|
|
15
|
+
content_base64,
|
|
16
|
+
content_mimetype,
|
|
17
|
+
package_release_id,
|
|
18
|
+
package_name_with_version,
|
|
19
|
+
is_release_tarball = false,
|
|
20
|
+
npm_pack_output,
|
|
21
|
+
}: {
|
|
22
|
+
file_path: string
|
|
23
|
+
content_text?: string
|
|
24
|
+
content_base64?: string
|
|
25
|
+
content_mimetype?: string
|
|
26
|
+
package_release_id?: string
|
|
27
|
+
package_name_with_version?: string
|
|
28
|
+
is_release_tarball?: boolean
|
|
29
|
+
npm_pack_output?: any
|
|
30
|
+
}) => {
|
|
31
|
+
// Validate that either content_text or content_base64 is provided, but not both
|
|
32
|
+
if (
|
|
33
|
+
(!content_text && !content_base64) ||
|
|
34
|
+
(content_text && content_base64)
|
|
35
|
+
) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
"Must provide either content_text or content_base64, but not both",
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Validate that either package_release_id or package_name_with_version is provided
|
|
42
|
+
if (!package_release_id && !package_name_with_version) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
"Must provide either package_release_id or package_name_with_version",
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const {
|
|
49
|
+
data: { package_file: newPackageFile },
|
|
50
|
+
} = await axios.post("/package_files/create", {
|
|
51
|
+
file_path,
|
|
52
|
+
content_text,
|
|
53
|
+
content_base64,
|
|
54
|
+
content_mimetype,
|
|
55
|
+
package_release_id,
|
|
56
|
+
package_name_with_version,
|
|
57
|
+
is_release_tarball,
|
|
58
|
+
npm_pack_output,
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
if (!newPackageFile) {
|
|
62
|
+
throw new Error("Failed to create package file")
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return newPackageFile
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
onSuccess: (packageFile: PackageFile) => {
|
|
69
|
+
onSuccess?.(packageFile)
|
|
70
|
+
},
|
|
71
|
+
onError: (error: any) => {
|
|
72
|
+
console.error("Error creating package file:", error)
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
)
|
|
76
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { Package } from "fake-snippets-api/lib/db/schema"
|
|
2
|
+
import { useMutation } from "react-query"
|
|
3
|
+
import { useAxios } from "./use-axios"
|
|
4
|
+
import { useGlobalStore } from "./use-global-store"
|
|
5
|
+
import { useUrlParams } from "./use-url-params"
|
|
6
|
+
|
|
7
|
+
export const useCreatePackageMutation = ({
|
|
8
|
+
onSuccess,
|
|
9
|
+
}: { onSuccess?: (pkg: Package) => void } = {}) => {
|
|
10
|
+
const urlParams = useUrlParams()
|
|
11
|
+
const templateName = urlParams.template
|
|
12
|
+
const axios = useAxios()
|
|
13
|
+
const session = useGlobalStore((s) => s.session)
|
|
14
|
+
|
|
15
|
+
return useMutation(
|
|
16
|
+
["createPackage"],
|
|
17
|
+
async ({
|
|
18
|
+
name,
|
|
19
|
+
description,
|
|
20
|
+
is_private,
|
|
21
|
+
is_unlisted,
|
|
22
|
+
}: {
|
|
23
|
+
name: string
|
|
24
|
+
description?: string
|
|
25
|
+
is_private?: boolean
|
|
26
|
+
is_unlisted?: boolean
|
|
27
|
+
}) => {
|
|
28
|
+
if (!session) throw new Error("No session")
|
|
29
|
+
|
|
30
|
+
const {
|
|
31
|
+
data: { package: newPackage },
|
|
32
|
+
} = await axios.post("/packages/create", {
|
|
33
|
+
name,
|
|
34
|
+
description,
|
|
35
|
+
is_private,
|
|
36
|
+
is_unlisted,
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
if (!newPackage) {
|
|
40
|
+
throw new Error("Failed to create package")
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return newPackage
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
onSuccess: (pkg: Package) => {
|
|
47
|
+
const url = new URL(window.location.href)
|
|
48
|
+
url.searchParams.set("package_id", pkg.package_id)
|
|
49
|
+
url.searchParams.delete("template")
|
|
50
|
+
url.searchParams.delete("should_create_package")
|
|
51
|
+
window.history.pushState({}, "", url.toString())
|
|
52
|
+
onSuccess?.(pkg)
|
|
53
|
+
window.dispatchEvent(new Event("popstate"))
|
|
54
|
+
},
|
|
55
|
+
onError: (error: any) => {
|
|
56
|
+
console.error("Error creating package:", error)
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
)
|
|
60
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { PackageRelease } from "fake-snippets-api/lib/db/schema"
|
|
2
|
+
import { useMutation } from "react-query"
|
|
3
|
+
import { useAxios } from "./use-axios"
|
|
4
|
+
|
|
5
|
+
export const useCreatePackageReleaseMutation = ({
|
|
6
|
+
onSuccess,
|
|
7
|
+
}: { onSuccess?: (packageRelease: PackageRelease) => void } = {}) => {
|
|
8
|
+
const axios = useAxios()
|
|
9
|
+
|
|
10
|
+
return useMutation(
|
|
11
|
+
["createPackageRelease"],
|
|
12
|
+
async ({
|
|
13
|
+
package_id,
|
|
14
|
+
version,
|
|
15
|
+
is_latest = true,
|
|
16
|
+
commit_sha,
|
|
17
|
+
package_name_with_version,
|
|
18
|
+
}: {
|
|
19
|
+
package_id?: string
|
|
20
|
+
version?: string
|
|
21
|
+
is_latest?: boolean
|
|
22
|
+
commit_sha?: string
|
|
23
|
+
package_name_with_version?: string
|
|
24
|
+
}) => {
|
|
25
|
+
// Validate that either package_id + version or package_name_with_version is provided
|
|
26
|
+
if (!package_name_with_version && (!package_id || !version)) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
"Must provide either package_id + version or package_name_with_version",
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const {
|
|
33
|
+
data: { package_release: newPackageRelease },
|
|
34
|
+
} = await axios.post("/package_releases/create", {
|
|
35
|
+
package_id,
|
|
36
|
+
version,
|
|
37
|
+
is_latest,
|
|
38
|
+
commit_sha,
|
|
39
|
+
package_name_with_version,
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
if (!newPackageRelease) {
|
|
43
|
+
throw new Error("Failed to create package release")
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return newPackageRelease
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
onSuccess: (packageRelease: PackageRelease) => {
|
|
50
|
+
onSuccess?.(packageRelease)
|
|
51
|
+
},
|
|
52
|
+
onError: (error: any) => {
|
|
53
|
+
console.error("Error creating package release:", error)
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
)
|
|
57
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Package,
|
|
3
|
+
PackageFile,
|
|
4
|
+
PackageRelease,
|
|
5
|
+
} from "fake-snippets-api/lib/db/schema"
|
|
6
|
+
import { useMutation } from "react-query"
|
|
7
|
+
import { useAxios } from "./use-axios"
|
|
8
|
+
import { useGlobalStore } from "./use-global-store"
|
|
9
|
+
import { useToast } from "./use-toast"
|
|
10
|
+
import { useCreatePackageMutation } from "./use-create-package-mutation"
|
|
11
|
+
import { useCreatePackageReleaseMutation } from "./use-create-package-release-mutation"
|
|
12
|
+
import { useCreatePackageFilesMutation } from "./use-create-package-files-mutation"
|
|
13
|
+
|
|
14
|
+
export const useForkPackageMutation = ({
|
|
15
|
+
onSuccess,
|
|
16
|
+
}: {
|
|
17
|
+
onSuccess?: (forkedPackage: Package) => void
|
|
18
|
+
} = {}) => {
|
|
19
|
+
const axios = useAxios()
|
|
20
|
+
const session = useGlobalStore((s) => s.session)
|
|
21
|
+
const { toast } = useToast()
|
|
22
|
+
|
|
23
|
+
const { mutateAsync: createPackage } = useCreatePackageMutation()
|
|
24
|
+
const { mutateAsync: createRelease } = useCreatePackageReleaseMutation()
|
|
25
|
+
const { mutateAsync: createFile } = useCreatePackageFilesMutation()
|
|
26
|
+
|
|
27
|
+
return useMutation(
|
|
28
|
+
["forkPackage"],
|
|
29
|
+
async (packageId: string) => {
|
|
30
|
+
if (!session) throw new Error("No session")
|
|
31
|
+
|
|
32
|
+
// Step 1: Fetch source package data
|
|
33
|
+
const { data: packageData } = await axios.get("/packages/get", {
|
|
34
|
+
params: { package_id: packageId },
|
|
35
|
+
})
|
|
36
|
+
const sourcePackage: Package = packageData.package
|
|
37
|
+
if (!sourcePackage) throw new Error("Source package not found")
|
|
38
|
+
|
|
39
|
+
console.log("sourcePackage", sourcePackage)
|
|
40
|
+
// Step 2: Fetch latest release
|
|
41
|
+
const { data: releaseData } = await axios.post("/package_releases/get", {
|
|
42
|
+
package_release_id: sourcePackage.latest_package_release_id,
|
|
43
|
+
})
|
|
44
|
+
const sourceRelease: PackageRelease = releaseData.package_release
|
|
45
|
+
if (!sourceRelease) throw new Error("Source release not found")
|
|
46
|
+
|
|
47
|
+
// Step 3: Fetch all files for the release
|
|
48
|
+
const { data: filesData } = await axios.post("/package_files/list", {
|
|
49
|
+
package_release_id: sourceRelease.package_release_id,
|
|
50
|
+
})
|
|
51
|
+
const sourceFiles: PackageFile[] = filesData.package_files
|
|
52
|
+
if (!sourceFiles?.length) throw new Error("No source files found")
|
|
53
|
+
|
|
54
|
+
// Step 4: Create new package
|
|
55
|
+
const newPackage = await createPackage({
|
|
56
|
+
name: `@${session.github_username}/${sourcePackage.unscoped_name}`,
|
|
57
|
+
description: `Fork of ${sourcePackage.name}`,
|
|
58
|
+
is_private: false,
|
|
59
|
+
is_unlisted: false,
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
// Step 5: Create new release
|
|
63
|
+
const newRelease = await createRelease({
|
|
64
|
+
package_id: newPackage.package_id,
|
|
65
|
+
version: sourceRelease.version ?? undefined,
|
|
66
|
+
is_latest: true,
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
// Step 6: Create all files
|
|
70
|
+
const newFiles = await Promise.all(
|
|
71
|
+
sourceFiles.map((file: PackageFile) =>
|
|
72
|
+
createFile({
|
|
73
|
+
package_release_id: newRelease.package_release_id,
|
|
74
|
+
file_path: file.file_path,
|
|
75
|
+
content_text: file.content_text ?? undefined,
|
|
76
|
+
}),
|
|
77
|
+
),
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
package: newPackage,
|
|
82
|
+
release: newRelease,
|
|
83
|
+
files: newFiles,
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
onSuccess: (result) => {
|
|
88
|
+
toast({
|
|
89
|
+
title: "Package Forked",
|
|
90
|
+
description: `Successfully forked package to @${session?.github_username}/${result.package.unscoped_name}`,
|
|
91
|
+
})
|
|
92
|
+
onSuccess?.(result.package)
|
|
93
|
+
},
|
|
94
|
+
onError: (error: any) => {
|
|
95
|
+
toast({
|
|
96
|
+
title: "Error",
|
|
97
|
+
description: "Failed to fork package. Please try again.",
|
|
98
|
+
variant: "destructive",
|
|
99
|
+
})
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
)
|
|
103
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useQuery } from "react-query"
|
|
2
|
+
import { useAxios } from "@/hooks/use-axios"
|
|
3
|
+
import type { Package } from "fake-snippets-api/lib/db/schema"
|
|
4
|
+
|
|
5
|
+
export const usePackageById = (packageId: string | null) => {
|
|
6
|
+
const axios = useAxios()
|
|
7
|
+
return useQuery<Package, Error & { status: number }>(
|
|
8
|
+
["package", packageId],
|
|
9
|
+
async () => {
|
|
10
|
+
if (!packageId) return
|
|
11
|
+
const { data } = await axios.get("/packages/get", {
|
|
12
|
+
params: {
|
|
13
|
+
package_id: packageId,
|
|
14
|
+
},
|
|
15
|
+
})
|
|
16
|
+
return data.package
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
retry: false,
|
|
20
|
+
enabled: Boolean(packageId),
|
|
21
|
+
},
|
|
22
|
+
)
|
|
23
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useQuery } from "react-query"
|
|
2
|
+
import { useAxios } from "@/hooks/use-axios"
|
|
3
|
+
import type { Package } from "fake-snippets-api/lib/db/schema"
|
|
4
|
+
|
|
5
|
+
export const usePackageByName = (packageName: string | null) => {
|
|
6
|
+
const axios = useAxios()
|
|
7
|
+
return useQuery<Package, Error & { status: number }>(
|
|
8
|
+
["package", packageName],
|
|
9
|
+
async () => {
|
|
10
|
+
if (!packageName) return
|
|
11
|
+
const { data } = await axios.get("/packages/get", {
|
|
12
|
+
params: {
|
|
13
|
+
name: packageName,
|
|
14
|
+
},
|
|
15
|
+
})
|
|
16
|
+
return data.package
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
retry: false,
|
|
20
|
+
enabled: Boolean(packageName),
|
|
21
|
+
},
|
|
22
|
+
)
|
|
23
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { PackageFile } from "fake-snippets-api/lib/db/schema"
|
|
2
|
+
import { useQuery } from "react-query"
|
|
3
|
+
import { useAxios } from "./use-axios"
|
|
4
|
+
|
|
5
|
+
type PackageFileQuery =
|
|
6
|
+
| {
|
|
7
|
+
package_file_id: string
|
|
8
|
+
}
|
|
9
|
+
| {
|
|
10
|
+
package_release_id: string
|
|
11
|
+
file_path: string
|
|
12
|
+
}
|
|
13
|
+
| {
|
|
14
|
+
package_id: string
|
|
15
|
+
version?: string
|
|
16
|
+
file_path: string
|
|
17
|
+
}
|
|
18
|
+
| {
|
|
19
|
+
package_name: string
|
|
20
|
+
version?: string
|
|
21
|
+
file_path: string
|
|
22
|
+
}
|
|
23
|
+
| {
|
|
24
|
+
package_name_with_version: string
|
|
25
|
+
file_path: string
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const usePackageFile = (query: PackageFileQuery | null) => {
|
|
29
|
+
const axios = useAxios()
|
|
30
|
+
|
|
31
|
+
return useQuery<PackageFile, Error & { status: number }>(
|
|
32
|
+
["packageFile", query],
|
|
33
|
+
async () => {
|
|
34
|
+
if (!query) return
|
|
35
|
+
|
|
36
|
+
const { data } = await axios.post("/package_files/get", query)
|
|
37
|
+
|
|
38
|
+
if (!data.package_file) {
|
|
39
|
+
throw new Error("Package file not found")
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return data.package_file
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
retry: false,
|
|
46
|
+
enabled: Boolean(query),
|
|
47
|
+
},
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Convenience hooks for common use cases
|
|
52
|
+
export const usePackageFileById = (packageFileId: string | null) => {
|
|
53
|
+
return usePackageFile(
|
|
54
|
+
packageFileId ? { package_file_id: packageFileId } : null,
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const usePackageFileByPath = (
|
|
59
|
+
packageNameWithVersion: string | null,
|
|
60
|
+
filePath: string | null,
|
|
61
|
+
) => {
|
|
62
|
+
return usePackageFile(
|
|
63
|
+
packageNameWithVersion && filePath
|
|
64
|
+
? {
|
|
65
|
+
package_name_with_version: packageNameWithVersion,
|
|
66
|
+
file_path: filePath,
|
|
67
|
+
}
|
|
68
|
+
: null,
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const usePackageFileByRelease = (
|
|
73
|
+
packageReleaseId: string | null,
|
|
74
|
+
filePath: string | null,
|
|
75
|
+
) => {
|
|
76
|
+
return usePackageFile(
|
|
77
|
+
packageReleaseId && filePath
|
|
78
|
+
? {
|
|
79
|
+
package_release_id: packageReleaseId,
|
|
80
|
+
file_path: filePath,
|
|
81
|
+
}
|
|
82
|
+
: null,
|
|
83
|
+
)
|
|
84
|
+
}
|