@pocketenv/cli 0.2.5 → 0.3.0
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/index.js +425 -50
- package/package.json +1 -1
- package/src/cmd/create.ts +3 -3
- package/src/cmd/env.ts +8 -8
- package/src/cmd/expose.ts +38 -0
- package/src/cmd/file.ts +139 -0
- package/src/cmd/list.ts +7 -7
- package/src/cmd/ports.ts +63 -0
- package/src/cmd/secret.ts +34 -19
- package/src/cmd/tailscale.ts +6 -6
- package/src/cmd/unexpose.ts +31 -0
- package/src/cmd/volume.ts +123 -0
- package/src/cmd/vscode.ts +32 -0
- package/src/index.ts +99 -10
- package/src/theme.ts +12 -0
- package/src/types/port.ts +5 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import consola from "consola";
|
|
2
|
+
import getAccessToken from "../lib/getAccessToken";
|
|
3
|
+
import { client } from "../client";
|
|
4
|
+
import { env } from "../lib/env";
|
|
5
|
+
import { c } from "../theme";
|
|
6
|
+
|
|
7
|
+
export async function exposePort(
|
|
8
|
+
sandbox: string,
|
|
9
|
+
port: number,
|
|
10
|
+
description?: string,
|
|
11
|
+
) {
|
|
12
|
+
const token = await getAccessToken();
|
|
13
|
+
try {
|
|
14
|
+
const response = await client.post<{ previewUrl?: string }>(
|
|
15
|
+
`/xrpc/io.pocketenv.sandbox.exposePort`,
|
|
16
|
+
{ port, description },
|
|
17
|
+
{
|
|
18
|
+
params: {
|
|
19
|
+
id: sandbox,
|
|
20
|
+
},
|
|
21
|
+
headers: {
|
|
22
|
+
Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
consola.success(
|
|
28
|
+
`Port ${c.primary(port)} exposed for sandbox ${c.primary(sandbox)}`,
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
if (response.data.previewUrl) {
|
|
32
|
+
consola.success(`Preview URL: ${c.secondary(response.data.previewUrl)}`);
|
|
33
|
+
}
|
|
34
|
+
} catch (error) {
|
|
35
|
+
consola.error("Failed to expose port:", error);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
}
|
package/src/cmd/file.ts
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import consola from "consola";
|
|
2
|
+
import getAccessToken from "../lib/getAccessToken";
|
|
3
|
+
import dayjs from "dayjs";
|
|
4
|
+
import relativeTime from "dayjs/plugin/relativeTime";
|
|
5
|
+
import { client } from "../client";
|
|
6
|
+
import { env } from "../lib/env";
|
|
7
|
+
import CliTable3 from "cli-table3";
|
|
8
|
+
import type { File } from "../types/file";
|
|
9
|
+
import { c } from "../theme";
|
|
10
|
+
import { editor } from "@inquirer/prompts";
|
|
11
|
+
import fs from "fs/promises";
|
|
12
|
+
import path from "path";
|
|
13
|
+
import encrypt from "../lib/sodium";
|
|
14
|
+
|
|
15
|
+
dayjs.extend(relativeTime);
|
|
16
|
+
|
|
17
|
+
export async function putFile(
|
|
18
|
+
sandbox: string,
|
|
19
|
+
remotePath: string,
|
|
20
|
+
localPath?: string,
|
|
21
|
+
) {
|
|
22
|
+
const token = await getAccessToken();
|
|
23
|
+
|
|
24
|
+
let content: string;
|
|
25
|
+
if (!process.stdin.isTTY) {
|
|
26
|
+
const chunks: Buffer[] = [];
|
|
27
|
+
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
28
|
+
content = Buffer.concat(chunks).toString().trim();
|
|
29
|
+
} else if (localPath) {
|
|
30
|
+
const resolvedPath = path.resolve(localPath);
|
|
31
|
+
try {
|
|
32
|
+
await fs.access(resolvedPath);
|
|
33
|
+
} catch (err) {
|
|
34
|
+
consola.error(`No such file: ${c.error(localPath)}`);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
content = await fs.readFile(resolvedPath, "utf-8");
|
|
38
|
+
} else {
|
|
39
|
+
content = (
|
|
40
|
+
await editor({
|
|
41
|
+
message: "File content (opens in $EDITOR):",
|
|
42
|
+
waitForUserInput: false,
|
|
43
|
+
})
|
|
44
|
+
).trim();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
await client.post(
|
|
49
|
+
"/xrpc/io.pocketenv.file.addFile",
|
|
50
|
+
{
|
|
51
|
+
file: {
|
|
52
|
+
sandboxId: sandbox,
|
|
53
|
+
path: remotePath,
|
|
54
|
+
content: await encrypt(content),
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
headers: {
|
|
59
|
+
Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`,
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
consola.success(
|
|
65
|
+
`File ${c.primary(remotePath)} successfully created in sandbox ${c.primary(sandbox)}`,
|
|
66
|
+
);
|
|
67
|
+
} catch (error) {
|
|
68
|
+
consola.error(`Failed to create file: ${error}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export async function listFiles(sandboxId: string) {
|
|
73
|
+
const token = await getAccessToken();
|
|
74
|
+
|
|
75
|
+
const response = await client.get<{ files: File[] }>(
|
|
76
|
+
"/xrpc/io.pocketenv.file.getFiles",
|
|
77
|
+
{
|
|
78
|
+
params: {
|
|
79
|
+
sandboxId,
|
|
80
|
+
},
|
|
81
|
+
headers: {
|
|
82
|
+
Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`,
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
const table = new CliTable3({
|
|
88
|
+
head: [c.primary("ID"), c.primary("PATH"), c.primary("CREATED AT")],
|
|
89
|
+
chars: {
|
|
90
|
+
top: "",
|
|
91
|
+
"top-mid": "",
|
|
92
|
+
"top-left": "",
|
|
93
|
+
"top-right": "",
|
|
94
|
+
bottom: "",
|
|
95
|
+
"bottom-mid": "",
|
|
96
|
+
"bottom-left": "",
|
|
97
|
+
"bottom-right": "",
|
|
98
|
+
left: "",
|
|
99
|
+
"left-mid": "",
|
|
100
|
+
mid: "",
|
|
101
|
+
"mid-mid": "",
|
|
102
|
+
right: "",
|
|
103
|
+
"right-mid": "",
|
|
104
|
+
middle: " ",
|
|
105
|
+
},
|
|
106
|
+
style: {
|
|
107
|
+
border: [],
|
|
108
|
+
head: [],
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
for (const file of response.data.files) {
|
|
113
|
+
table.push([
|
|
114
|
+
c.secondary(file.id),
|
|
115
|
+
file.path,
|
|
116
|
+
dayjs(file.createdAt).fromNow(),
|
|
117
|
+
]);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
consola.log(table.toString());
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export async function deleteFile(id: string) {
|
|
124
|
+
const token = await getAccessToken();
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
await client.post(`/xrpc/io.pocketenv.file.deleteFile`, undefined, {
|
|
128
|
+
params: {
|
|
129
|
+
id,
|
|
130
|
+
},
|
|
131
|
+
headers: {
|
|
132
|
+
Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`,
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
consola.success(`File ${c.primary(id)} successfully deleted from sandbox`);
|
|
136
|
+
} catch (error) {
|
|
137
|
+
consola.error(`Failed to delete file: ${error}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
package/src/cmd/list.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { client } from "../client";
|
|
2
|
-
import chalk from "chalk";
|
|
3
2
|
import consola from "consola";
|
|
4
3
|
import { env } from "../lib/env";
|
|
5
4
|
import getAccessToken from "../lib/getAccessToken";
|
|
@@ -8,6 +7,7 @@ import Table from "cli-table3";
|
|
|
8
7
|
import dayjs from "dayjs";
|
|
9
8
|
import relativeTime from "dayjs/plugin/relativeTime";
|
|
10
9
|
import type { Profile } from "../types/profile";
|
|
10
|
+
import { c } from "../theme";
|
|
11
11
|
dayjs.extend(relativeTime);
|
|
12
12
|
|
|
13
13
|
async function listSandboxes() {
|
|
@@ -35,10 +35,10 @@ async function listSandboxes() {
|
|
|
35
35
|
|
|
36
36
|
const table = new Table({
|
|
37
37
|
head: [
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
c.primary("NAME"),
|
|
39
|
+
c.primary("BASE"),
|
|
40
|
+
c.primary("STATUS"),
|
|
41
|
+
c.primary("CREATED AT"),
|
|
42
42
|
],
|
|
43
43
|
chars: {
|
|
44
44
|
top: "",
|
|
@@ -65,10 +65,10 @@ async function listSandboxes() {
|
|
|
65
65
|
|
|
66
66
|
for (const sandbox of response.data.sandboxes) {
|
|
67
67
|
table.push([
|
|
68
|
-
|
|
68
|
+
c.secondary(sandbox.name),
|
|
69
69
|
sandbox.baseSandbox,
|
|
70
70
|
sandbox.status === "RUNNING"
|
|
71
|
-
?
|
|
71
|
+
? c.highlight(sandbox.status)
|
|
72
72
|
: sandbox.status,
|
|
73
73
|
dayjs(sandbox.createdAt).fromNow(),
|
|
74
74
|
]);
|
package/src/cmd/ports.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { client } from "../client";
|
|
3
|
+
import { env } from "../lib/env";
|
|
4
|
+
import getAccessToken from "../lib/getAccessToken";
|
|
5
|
+
import type { Port } from "../types/port";
|
|
6
|
+
import CliTable3 from "cli-table3";
|
|
7
|
+
import consola from "consola";
|
|
8
|
+
import { c } from "../theme";
|
|
9
|
+
|
|
10
|
+
export async function listPorts(sandbox: string) {
|
|
11
|
+
const token = await getAccessToken();
|
|
12
|
+
|
|
13
|
+
const response = await client.get<{ ports: Port[] }>(
|
|
14
|
+
"/xrpc/io.pocketenv.sandbox.getExposedPorts",
|
|
15
|
+
{
|
|
16
|
+
params: {
|
|
17
|
+
id: sandbox,
|
|
18
|
+
},
|
|
19
|
+
headers: {
|
|
20
|
+
Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
const table = new CliTable3({
|
|
26
|
+
head: [
|
|
27
|
+
c.primary("PORT"),
|
|
28
|
+
c.primary("DESCRIPTION"),
|
|
29
|
+
c.primary("PREVIEW URL"),
|
|
30
|
+
],
|
|
31
|
+
chars: {
|
|
32
|
+
top: "",
|
|
33
|
+
"top-mid": "",
|
|
34
|
+
"top-left": "",
|
|
35
|
+
"top-right": "",
|
|
36
|
+
bottom: "",
|
|
37
|
+
"bottom-mid": "",
|
|
38
|
+
"bottom-left": "",
|
|
39
|
+
"bottom-right": "",
|
|
40
|
+
left: "",
|
|
41
|
+
"left-mid": "",
|
|
42
|
+
mid: "",
|
|
43
|
+
"mid-mid": "",
|
|
44
|
+
right: "",
|
|
45
|
+
"right-mid": "",
|
|
46
|
+
middle: " ",
|
|
47
|
+
},
|
|
48
|
+
style: {
|
|
49
|
+
border: [],
|
|
50
|
+
head: [],
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
for (const port of response.data.ports) {
|
|
55
|
+
table.push([
|
|
56
|
+
c.secondary(port.port),
|
|
57
|
+
port.description || "-",
|
|
58
|
+
c.link(port.previewUrl || "-"),
|
|
59
|
+
]);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
consola.log(table.toString());
|
|
63
|
+
}
|
package/src/cmd/secret.ts
CHANGED
|
@@ -10,6 +10,7 @@ import dayjs from "dayjs";
|
|
|
10
10
|
import relativeTime from "dayjs/plugin/relativeTime";
|
|
11
11
|
import { env } from "../lib/env";
|
|
12
12
|
import encrypt from "../lib/sodium";
|
|
13
|
+
import { c } from "../theme";
|
|
13
14
|
|
|
14
15
|
dayjs.extend(relativeTime);
|
|
15
16
|
|
|
@@ -41,7 +42,7 @@ export async function listSecrets(sandbox: string) {
|
|
|
41
42
|
);
|
|
42
43
|
|
|
43
44
|
const table = new Table({
|
|
44
|
-
head: [
|
|
45
|
+
head: [c.primary("ID"), c.primary("NAME"), c.primary("CREATED AT")],
|
|
45
46
|
chars: {
|
|
46
47
|
top: "",
|
|
47
48
|
"top-mid": "",
|
|
@@ -67,8 +68,8 @@ export async function listSecrets(sandbox: string) {
|
|
|
67
68
|
|
|
68
69
|
for (const secret of response.data.secrets) {
|
|
69
70
|
table.push([
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
c.secondary(secret.id),
|
|
72
|
+
c.highlight(secret.name),
|
|
72
73
|
dayjs(secret.createdAt).fromNow(),
|
|
73
74
|
]);
|
|
74
75
|
}
|
|
@@ -78,7 +79,15 @@ export async function listSecrets(sandbox: string) {
|
|
|
78
79
|
|
|
79
80
|
export async function putSecret(sandbox: string, key: string) {
|
|
80
81
|
const token = await getAccessToken();
|
|
81
|
-
const
|
|
82
|
+
const isStdinPiped = !process.stdin.isTTY;
|
|
83
|
+
const value = isStdinPiped
|
|
84
|
+
? await new Promise<string>((resolve) => {
|
|
85
|
+
let data = "";
|
|
86
|
+
process.stdin.setEncoding("utf8");
|
|
87
|
+
process.stdin.on("data", (chunk) => (data += chunk));
|
|
88
|
+
process.stdin.on("end", () => resolve(data.trimEnd()));
|
|
89
|
+
})
|
|
90
|
+
: await password({ message: "Enter secret value" });
|
|
82
91
|
|
|
83
92
|
const { data } = await client.get("/xrpc/io.pocketenv.sandbox.getSandbox", {
|
|
84
93
|
params: {
|
|
@@ -94,21 +103,27 @@ export async function putSecret(sandbox: string, key: string) {
|
|
|
94
103
|
process.exit(1);
|
|
95
104
|
}
|
|
96
105
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
106
|
+
try {
|
|
107
|
+
await client.post(
|
|
108
|
+
"/xrpc/io.pocketenv.secret.addSecret",
|
|
109
|
+
{
|
|
110
|
+
secret: {
|
|
111
|
+
sandboxId: data.sandbox.id,
|
|
112
|
+
name: key,
|
|
113
|
+
value: await encrypt(value),
|
|
114
|
+
},
|
|
104
115
|
},
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
116
|
+
{
|
|
117
|
+
headers: {
|
|
118
|
+
Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`,
|
|
119
|
+
},
|
|
109
120
|
},
|
|
110
|
-
|
|
111
|
-
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
consola.success("Secret added successfully");
|
|
124
|
+
} catch (error) {
|
|
125
|
+
consola.error("Failed to add secret:", error);
|
|
126
|
+
}
|
|
112
127
|
}
|
|
113
128
|
|
|
114
129
|
export async function deleteSecret(id: string) {
|
|
@@ -125,7 +140,7 @@ export async function deleteSecret(id: string) {
|
|
|
125
140
|
});
|
|
126
141
|
|
|
127
142
|
consola.success("Secret deleted successfully");
|
|
128
|
-
} catch {
|
|
129
|
-
consola.error("Failed to delete secret");
|
|
143
|
+
} catch (error) {
|
|
144
|
+
consola.error("Failed to delete secret:", error);
|
|
130
145
|
}
|
|
131
146
|
}
|
package/src/cmd/tailscale.ts
CHANGED
|
@@ -3,10 +3,10 @@ import getAccessToken from "../lib/getAccessToken";
|
|
|
3
3
|
import { client } from "../client";
|
|
4
4
|
import type { Sandbox } from "../types/sandbox";
|
|
5
5
|
import consola from "consola";
|
|
6
|
-
import chalk from "chalk";
|
|
7
6
|
import type { TailscaleAuthKey } from "../types/tailscale-auth-key";
|
|
8
7
|
import { env } from "../lib/env";
|
|
9
8
|
import encrypt from "../lib/sodium";
|
|
9
|
+
import { c } from "../theme";
|
|
10
10
|
|
|
11
11
|
export async function putAuthKey(sandbox: string) {
|
|
12
12
|
const token = await getAccessToken();
|
|
@@ -33,7 +33,7 @@ export async function putAuthKey(sandbox: string) {
|
|
|
33
33
|
);
|
|
34
34
|
|
|
35
35
|
if (!data.sandbox) {
|
|
36
|
-
consola.error(`Sandbox not found: ${
|
|
36
|
+
consola.error(`Sandbox not found: ${c.primary(sandbox)}`);
|
|
37
37
|
process.exit(1);
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -60,7 +60,7 @@ export async function putAuthKey(sandbox: string) {
|
|
|
60
60
|
|
|
61
61
|
consola.success(redacted);
|
|
62
62
|
consola.success(
|
|
63
|
-
`Tailscale auth key saved for sandbox: ${
|
|
63
|
+
`Tailscale auth key saved for sandbox: ${c.primary(sandbox)}`,
|
|
64
64
|
);
|
|
65
65
|
}
|
|
66
66
|
|
|
@@ -80,7 +80,7 @@ export async function getTailscaleAuthKey(sandbox: string) {
|
|
|
80
80
|
);
|
|
81
81
|
|
|
82
82
|
if (!data.sandbox) {
|
|
83
|
-
consola.error(`Sandbox not found: ${
|
|
83
|
+
consola.error(`Sandbox not found: ${c.primary(sandbox)}`);
|
|
84
84
|
process.exit(1);
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -96,10 +96,10 @@ export async function getTailscaleAuthKey(sandbox: string) {
|
|
|
96
96
|
},
|
|
97
97
|
},
|
|
98
98
|
);
|
|
99
|
-
consola.info(`Tailscale auth key: ${
|
|
99
|
+
consola.info(`Tailscale auth key: ${c.primary(tailscale.authKey)}`);
|
|
100
100
|
} catch {
|
|
101
101
|
consola.error(
|
|
102
|
-
`No Tailscale Auth Key found for sandbox: ${
|
|
102
|
+
`No Tailscale Auth Key found for sandbox: ${c.primary(sandbox)}`,
|
|
103
103
|
);
|
|
104
104
|
process.exit(1);
|
|
105
105
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import consola from "consola";
|
|
2
|
+
import getAccessToken from "../lib/getAccessToken";
|
|
3
|
+
import { client } from "../client";
|
|
4
|
+
import { env } from "../lib/env";
|
|
5
|
+
import { c } from "../theme";
|
|
6
|
+
|
|
7
|
+
export async function unexposePort(sandbox: string, port: number) {
|
|
8
|
+
const token = await getAccessToken();
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
await client.post(
|
|
12
|
+
`/xrpc/io.pocketenv.sandbox.unexposePort`,
|
|
13
|
+
{ port },
|
|
14
|
+
{
|
|
15
|
+
params: {
|
|
16
|
+
id: sandbox,
|
|
17
|
+
},
|
|
18
|
+
headers: {
|
|
19
|
+
Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
consola.success(
|
|
25
|
+
`Port ${c.primary(port)} unexposed for sandbox ${c.primary(sandbox)}`,
|
|
26
|
+
);
|
|
27
|
+
} catch (error) {
|
|
28
|
+
consola.error(`Failed to unexpose port: ${error}`);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import consola from "consola";
|
|
3
|
+
import getAccessToken from "../lib/getAccessToken";
|
|
4
|
+
import { client } from "../client";
|
|
5
|
+
import { env } from "../lib/env";
|
|
6
|
+
import type { Volume } from "../types/volume";
|
|
7
|
+
import CliTable3 from "cli-table3";
|
|
8
|
+
import { c } from "../theme";
|
|
9
|
+
import dayjs from "dayjs";
|
|
10
|
+
import relativeTime from "dayjs/plugin/relativeTime";
|
|
11
|
+
|
|
12
|
+
dayjs.extend(relativeTime);
|
|
13
|
+
|
|
14
|
+
export async function listVolumes(sandboxId: string) {
|
|
15
|
+
const token = await getAccessToken();
|
|
16
|
+
|
|
17
|
+
const response = await client.get<{ volumes: Volume[] }>(
|
|
18
|
+
"/xrpc/io.pocketenv.volume.getVolumes",
|
|
19
|
+
{
|
|
20
|
+
params: {
|
|
21
|
+
sandboxId,
|
|
22
|
+
},
|
|
23
|
+
headers: {
|
|
24
|
+
Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const table = new CliTable3({
|
|
30
|
+
head: [
|
|
31
|
+
c.primary("ID"),
|
|
32
|
+
c.primary("NAME"),
|
|
33
|
+
c.primary("PATH"),
|
|
34
|
+
c.primary("CREATED AT"),
|
|
35
|
+
],
|
|
36
|
+
chars: {
|
|
37
|
+
top: "",
|
|
38
|
+
"top-mid": "",
|
|
39
|
+
"top-left": "",
|
|
40
|
+
"top-right": "",
|
|
41
|
+
bottom: "",
|
|
42
|
+
"bottom-mid": "",
|
|
43
|
+
"bottom-left": "",
|
|
44
|
+
"bottom-right": "",
|
|
45
|
+
left: "",
|
|
46
|
+
"left-mid": "",
|
|
47
|
+
mid: "",
|
|
48
|
+
"mid-mid": "",
|
|
49
|
+
right: "",
|
|
50
|
+
"right-mid": "",
|
|
51
|
+
middle: " ",
|
|
52
|
+
},
|
|
53
|
+
style: {
|
|
54
|
+
border: [],
|
|
55
|
+
head: [],
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
for (const volume of response.data.volumes) {
|
|
60
|
+
table.push([
|
|
61
|
+
c.secondary(volume.id),
|
|
62
|
+
volume.name,
|
|
63
|
+
volume.path,
|
|
64
|
+
dayjs(volume.createdAt).fromNow(),
|
|
65
|
+
]);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
consola.log(table.toString());
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export async function createVolume(
|
|
72
|
+
sandbox: string,
|
|
73
|
+
name: string,
|
|
74
|
+
path: string,
|
|
75
|
+
) {
|
|
76
|
+
const token = await getAccessToken();
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
await client.post(
|
|
80
|
+
"/xrpc/io.pocketenv.volume.addVolume",
|
|
81
|
+
{
|
|
82
|
+
volume: {
|
|
83
|
+
sandboxId: sandbox,
|
|
84
|
+
name,
|
|
85
|
+
path,
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
headers: {
|
|
90
|
+
Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`,
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
consola.success(
|
|
96
|
+
`Volume ${chalk.rgb(0, 232, 198)(name)} successfully mounted in sandbox ${chalk.rgb(0, 232, 198)(sandbox)} at path ${chalk.rgb(0, 232, 198)(path)}`,
|
|
97
|
+
);
|
|
98
|
+
} catch (error) {
|
|
99
|
+
consola.error("Failed to create volume:", error);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export async function deleteVolume(id: string) {
|
|
104
|
+
const token = await getAccessToken();
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
await client.post(`/xrpc/io.pocketenv.volume.deleteVolume`, undefined, {
|
|
108
|
+
params: {
|
|
109
|
+
id,
|
|
110
|
+
},
|
|
111
|
+
headers: {
|
|
112
|
+
Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`,
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
} catch (error) {
|
|
116
|
+
consola.error(`Failed to delete volume: ${error}`);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
consola.success(
|
|
121
|
+
`Volume ${chalk.rgb(0, 232, 198)(id)} successfully deleted from sandbox`,
|
|
122
|
+
);
|
|
123
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import consola from "consola";
|
|
2
|
+
import getAccessToken from "../lib/getAccessToken";
|
|
3
|
+
import { client } from "../client";
|
|
4
|
+
import { env } from "../lib/env";
|
|
5
|
+
import { c } from "../theme";
|
|
6
|
+
|
|
7
|
+
export async function exposeVscode(sandbox: string) {
|
|
8
|
+
const token = await getAccessToken();
|
|
9
|
+
try {
|
|
10
|
+
const response = await client.post<{ previewUrl?: string }>(
|
|
11
|
+
`/xrpc/io.pocketenv.sandbox.exposeVscode`,
|
|
12
|
+
undefined,
|
|
13
|
+
{
|
|
14
|
+
params: {
|
|
15
|
+
id: sandbox,
|
|
16
|
+
},
|
|
17
|
+
headers: {
|
|
18
|
+
Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
consola.success(`VS Code Server exposed for sandbox ${c.primary(sandbox)}`);
|
|
24
|
+
|
|
25
|
+
if (response.data.previewUrl) {
|
|
26
|
+
consola.success(`Preview URL: ${c.secondary(response.data.previewUrl)}`);
|
|
27
|
+
}
|
|
28
|
+
} catch (error) {
|
|
29
|
+
consola.error("Failed to expose VS Code:", error);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
}
|