@sampleapp.ai/sdk 1.0.48 → 1.0.49
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/dist/components/sandbox/guardian/ui/download-and-open-buttons.js +35 -9
- package/dist/index.d.ts +13 -0
- package/dist/index.es.js +1231 -1201
- package/dist/lib/api-client.js +18 -1
- package/package.json +1 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import React from "react";
|
|
3
|
-
import { DownloadIcon, Check, Copy } from "lucide-react";
|
|
3
|
+
import { DownloadIcon, Check, Copy, Loader2 } from "lucide-react";
|
|
4
4
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, } from "./dialog";
|
|
5
5
|
import vscodeLogo from "../../../../assets/vscode.png";
|
|
6
6
|
import { handleSandboxDownload } from "../utils";
|
|
7
|
+
import { createApiClient } from "../../../../lib/api-client";
|
|
7
8
|
// VSCode logo component using imported asset
|
|
8
9
|
function VSCodeLogo({ className }) {
|
|
9
10
|
return (React.createElement("img", { src: vscodeLogo, alt: "VSCode", width: 20, height: 20, className: className }));
|
|
@@ -11,16 +12,19 @@ function VSCodeLogo({ className }) {
|
|
|
11
12
|
export const DownloadAndOpenButtons = ({ downloadUrl, themeColor, gitUrl, browserUrl, sandboxId, apiKey, }) => {
|
|
12
13
|
const [isModalOpen, setIsModalOpen] = React.useState(false);
|
|
13
14
|
const [hasCopied, setHasCopied] = React.useState(false);
|
|
15
|
+
const [isCloning, setIsCloning] = React.useState(false);
|
|
14
16
|
// Build the npx command using the SDK download endpoint
|
|
15
17
|
// Use default MAIN_APP_URL for SDK (can be overridden via env)
|
|
16
|
-
const MAIN_APP_URL = typeof window !== "undefined" &&
|
|
18
|
+
const MAIN_APP_URL = typeof window !== "undefined" &&
|
|
19
|
+
window.SAMPLEAPP_MAIN_URL
|
|
17
20
|
? window.SAMPLEAPP_MAIN_URL
|
|
18
21
|
: "https://sampleapp.ai";
|
|
19
22
|
const npxCommand = React.useMemo(() => {
|
|
20
23
|
if (!sandboxId) {
|
|
21
24
|
return "";
|
|
22
25
|
}
|
|
23
|
-
const apiBaseUrl = typeof window !== "undefined" &&
|
|
26
|
+
const apiBaseUrl = typeof window !== "undefined" &&
|
|
27
|
+
window.SAMPLEAPP_API_URL
|
|
24
28
|
? window.SAMPLEAPP_API_URL
|
|
25
29
|
: MAIN_APP_URL.replace("sampleapp.ai", "api.sampleapp.ai");
|
|
26
30
|
return `npx sampleappai add "${apiBaseUrl}/api/v1/sdk/download-code?sandbox_id=${sandboxId}"`;
|
|
@@ -28,10 +32,32 @@ export const DownloadAndOpenButtons = ({ downloadUrl, themeColor, gitUrl, browse
|
|
|
28
32
|
const handleDownload = async () => {
|
|
29
33
|
await handleSandboxDownload(sandboxId, apiKey, () => setIsModalOpen(true));
|
|
30
34
|
};
|
|
31
|
-
const handleOpenInVSCode = () => {
|
|
32
|
-
|
|
35
|
+
const handleOpenInVSCode = async () => {
|
|
36
|
+
// If we have a sandboxId and apiKey, fetch an authenticated clone URL from the backend
|
|
37
|
+
if (sandboxId && apiKey) {
|
|
38
|
+
setIsCloning(true);
|
|
33
39
|
try {
|
|
34
|
-
|
|
40
|
+
const client = createApiClient({ apiKey });
|
|
41
|
+
const { clone_url } = await client.sdk.getCloneUrl(sandboxId);
|
|
42
|
+
window.location.href = `vscode://vscode.git/clone?url=${encodeURIComponent(clone_url)}`;
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
console.error("Failed to get clone URL:", err);
|
|
46
|
+
// Fall back to direct gitUrl or modal
|
|
47
|
+
if (gitUrl) {
|
|
48
|
+
window.location.href = `vscode://vscode.git/clone?url=${encodeURIComponent(gitUrl)}`;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
setIsModalOpen(true);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
setIsCloning(false);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else if (gitUrl) {
|
|
59
|
+
try {
|
|
60
|
+
window.location.href = `vscode://vscode.git/clone?url=${encodeURIComponent(gitUrl)}`;
|
|
35
61
|
}
|
|
36
62
|
catch (_a) {
|
|
37
63
|
// Silently fail if vscode:// protocol isn't registered
|
|
@@ -59,9 +85,9 @@ export const DownloadAndOpenButtons = ({ downloadUrl, themeColor, gitUrl, browse
|
|
|
59
85
|
React.createElement("button", { type: "button", className: "inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md !text-white transition-all hover:opacity-90 active:scale-[0.98]", style: { backgroundColor: themeColor }, onClick: handleDownload },
|
|
60
86
|
React.createElement(DownloadIcon, { className: "w-3.5 h-3.5 !text-white" }),
|
|
61
87
|
"Download example"),
|
|
62
|
-
React.createElement("button", { type: "button", className: "inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md border transition-all hover:opacity-90 active:scale-[0.98] bg-zinc-100 dark:bg-zinc-800 border-zinc-300 dark:border-zinc-700 text-zinc-900 dark:text-white", onClick: handleOpenInVSCode },
|
|
63
|
-
React.createElement(VSCodeLogo, { className: "w-3.5 h-3.5" }),
|
|
64
|
-
"Integrate in VS Code")),
|
|
88
|
+
React.createElement("button", { type: "button", className: "inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md border transition-all hover:opacity-90 active:scale-[0.98] bg-zinc-100 dark:bg-zinc-800 border-zinc-300 dark:border-zinc-700 text-zinc-900 dark:text-white disabled:opacity-50", onClick: handleOpenInVSCode, disabled: isCloning },
|
|
89
|
+
isCloning ? (React.createElement(Loader2, { className: "w-3.5 h-3.5 animate-spin" })) : (React.createElement(VSCodeLogo, { className: "w-3.5 h-3.5" })),
|
|
90
|
+
isCloning ? "Opening..." : "Integrate in VS Code")),
|
|
65
91
|
React.createElement(Dialog, { open: isModalOpen, onOpenChange: setIsModalOpen },
|
|
66
92
|
React.createElement(DialogContent, { className: "max-w-[90vw] sm:max-w-md w-full" },
|
|
67
93
|
React.createElement(DialogHeader, null,
|
package/dist/index.d.ts
CHANGED
|
@@ -120,6 +120,15 @@ declare class ApiClient {
|
|
|
120
120
|
* @returns Promise that resolves when download is initiated
|
|
121
121
|
*/
|
|
122
122
|
downloadCode: (sandboxId: string) => Promise<void>;
|
|
123
|
+
/**
|
|
124
|
+
* Get an authenticated clone URL for a private GitHub repository.
|
|
125
|
+
* Returns an HTTPS URL with a short-lived token (expires in 1 hour)
|
|
126
|
+
* that can be used with vscode://vscode.git/clone or git clone directly.
|
|
127
|
+
*
|
|
128
|
+
* @param sandboxId - The sandbox content UID
|
|
129
|
+
* @returns Clone URL response with authenticated URL
|
|
130
|
+
*/
|
|
131
|
+
getCloneUrl: (sandboxId: string) => Promise<CloneUrlResponse>;
|
|
123
132
|
/**
|
|
124
133
|
* Start VM endpoint that starts a desktop sandbox, launches Chrome,
|
|
125
134
|
* navigates to the target URL, and returns a VNC viewer URL
|
|
@@ -216,6 +225,10 @@ declare interface ChatButtonProps {
|
|
|
216
225
|
onClick?: () => void;
|
|
217
226
|
}
|
|
218
227
|
|
|
228
|
+
declare interface CloneUrlResponse {
|
|
229
|
+
clone_url: string;
|
|
230
|
+
}
|
|
231
|
+
|
|
219
232
|
declare enum CodeLanguage {
|
|
220
233
|
JAVASCRIPT = "javascript",
|
|
221
234
|
TYPESCRIPT = "typescript",
|