@pocketenv/cli 0.3.5 → 0.4.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/README.md +1 -0
- package/dist/index.js +173 -3
- package/package.json +1 -1
- package/src/cmd/service.ts +191 -0
- package/src/cmd/start.ts +6 -1
- package/src/index.ts +56 -0
- package/src/types/service.ts +9 -0
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Pocketenv CLI
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@pocketenv/cli)
|
|
4
|
+

|
|
4
5
|
[](https://discord.gg/9ada4pFUFS)
|
|
5
6
|
[](https://opensource.org/licenses/MPL-2.0)
|
|
6
7
|
|
package/dist/index.js
CHANGED
|
@@ -23,8 +23,9 @@ import { execSync } from 'child_process';
|
|
|
23
23
|
import * as fs from 'fs';
|
|
24
24
|
import { password, editor, input } from '@inquirer/prompts';
|
|
25
25
|
import sodium from 'libsodium-wrappers';
|
|
26
|
+
import process$1 from 'node:process';
|
|
26
27
|
|
|
27
|
-
var version = "0.
|
|
28
|
+
var version = "0.4.0";
|
|
28
29
|
|
|
29
30
|
async function getAccessToken() {
|
|
30
31
|
const tokenPath = path.join(os.homedir(), ".pocketenv", "token.json");
|
|
@@ -440,7 +441,11 @@ async function waitUntilRunning(name, authToken, timeoutMs = 6e4, intervalMs = 2
|
|
|
440
441
|
);
|
|
441
442
|
}
|
|
442
443
|
|
|
443
|
-
async function start(name, {
|
|
444
|
+
async function start(name, {
|
|
445
|
+
ssh: ssh$1,
|
|
446
|
+
repo,
|
|
447
|
+
keepAlive
|
|
448
|
+
}) {
|
|
444
449
|
const token = await getAccessToken();
|
|
445
450
|
if (repo) repo = expandRepo(repo);
|
|
446
451
|
try {
|
|
@@ -448,7 +453,8 @@ async function start(name, { ssh: ssh$1, repo }) {
|
|
|
448
453
|
await client.post(
|
|
449
454
|
"/xrpc/io.pocketenv.sandbox.startSandbox",
|
|
450
455
|
{
|
|
451
|
-
repo
|
|
456
|
+
repo,
|
|
457
|
+
keepAlive
|
|
452
458
|
},
|
|
453
459
|
{
|
|
454
460
|
params: {
|
|
@@ -1645,6 +1651,160 @@ async function exec(sandbox, command) {
|
|
|
1645
1651
|
}
|
|
1646
1652
|
}
|
|
1647
1653
|
|
|
1654
|
+
dayjs.extend(relativeTime);
|
|
1655
|
+
async function createService(sandboxId, name, command, { ports, description }) {
|
|
1656
|
+
const token = await getAccessToken();
|
|
1657
|
+
try {
|
|
1658
|
+
await client.post(
|
|
1659
|
+
"/xrpc/io.pocketenv.service.addService",
|
|
1660
|
+
{
|
|
1661
|
+
service: {
|
|
1662
|
+
name,
|
|
1663
|
+
command: command.join(" "),
|
|
1664
|
+
description,
|
|
1665
|
+
ports: ports?.map((port) => parseInt(port))
|
|
1666
|
+
}
|
|
1667
|
+
},
|
|
1668
|
+
{
|
|
1669
|
+
params: {
|
|
1670
|
+
sandboxId
|
|
1671
|
+
},
|
|
1672
|
+
headers: {
|
|
1673
|
+
Authorization: `Bearer ${env$1.POCKETENV_TOKEN || token}`
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
);
|
|
1677
|
+
consola.success(`Service ${c.highlight(name)} created successfully`);
|
|
1678
|
+
} catch (error) {
|
|
1679
|
+
consola.error("Failed to create service", error);
|
|
1680
|
+
process$1.exit(1);
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
async function listServices(sandboxId) {
|
|
1684
|
+
const token = await getAccessToken();
|
|
1685
|
+
try {
|
|
1686
|
+
const { data } = await client.get(
|
|
1687
|
+
"/xrpc/io.pocketenv.service.getServices",
|
|
1688
|
+
{
|
|
1689
|
+
params: {
|
|
1690
|
+
sandboxId
|
|
1691
|
+
},
|
|
1692
|
+
headers: {
|
|
1693
|
+
Authorization: `Bearer ${env$1.POCKETENV_TOKEN || token}`
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
);
|
|
1697
|
+
const table = new Table({
|
|
1698
|
+
head: [
|
|
1699
|
+
c.primary("ID"),
|
|
1700
|
+
c.primary("NAME"),
|
|
1701
|
+
c.primary("COMMAND"),
|
|
1702
|
+
c.primary("STATUS"),
|
|
1703
|
+
c.primary("CREATED AT")
|
|
1704
|
+
],
|
|
1705
|
+
chars: {
|
|
1706
|
+
top: "",
|
|
1707
|
+
"top-mid": "",
|
|
1708
|
+
"top-left": "",
|
|
1709
|
+
"top-right": "",
|
|
1710
|
+
bottom: "",
|
|
1711
|
+
"bottom-mid": "",
|
|
1712
|
+
"bottom-left": "",
|
|
1713
|
+
"bottom-right": "",
|
|
1714
|
+
left: "",
|
|
1715
|
+
"left-mid": "",
|
|
1716
|
+
mid: "",
|
|
1717
|
+
"mid-mid": "",
|
|
1718
|
+
right: "",
|
|
1719
|
+
"right-mid": "",
|
|
1720
|
+
middle: " "
|
|
1721
|
+
},
|
|
1722
|
+
style: {
|
|
1723
|
+
border: [],
|
|
1724
|
+
head: []
|
|
1725
|
+
}
|
|
1726
|
+
});
|
|
1727
|
+
for (const service of data.services) {
|
|
1728
|
+
table.push([
|
|
1729
|
+
c.secondary(service.id),
|
|
1730
|
+
service.name,
|
|
1731
|
+
service.command,
|
|
1732
|
+
service.status === "RUNNING" ? c.highlight(service.status) : service.status,
|
|
1733
|
+
dayjs(service.createdAt).fromNow()
|
|
1734
|
+
]);
|
|
1735
|
+
}
|
|
1736
|
+
consola.log(table.toString());
|
|
1737
|
+
} catch (error) {
|
|
1738
|
+
consola.error("Failed to list services", error);
|
|
1739
|
+
process$1.exit(1);
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
async function restartService(serviceId) {
|
|
1743
|
+
const token = await getAccessToken();
|
|
1744
|
+
try {
|
|
1745
|
+
await client.post("/xrpc/io.pocketenv.service.restartService", void 0, {
|
|
1746
|
+
params: {
|
|
1747
|
+
serviceId
|
|
1748
|
+
},
|
|
1749
|
+
headers: {
|
|
1750
|
+
Authorization: `Bearer ${env$1.POCKETENV_TOKEN || token}`
|
|
1751
|
+
}
|
|
1752
|
+
});
|
|
1753
|
+
} catch (error) {
|
|
1754
|
+
consola.error(`Failed to restart service ${serviceId}`, error);
|
|
1755
|
+
process$1.exit(1);
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
async function startService(serviceId) {
|
|
1759
|
+
const token = await getAccessToken();
|
|
1760
|
+
try {
|
|
1761
|
+
await client.post("/xrpc/io.pocketenv.service.startService", void 0, {
|
|
1762
|
+
params: {
|
|
1763
|
+
serviceId
|
|
1764
|
+
},
|
|
1765
|
+
headers: {
|
|
1766
|
+
Authorization: `Bearer ${env$1.POCKETENV_TOKEN || token}`
|
|
1767
|
+
}
|
|
1768
|
+
});
|
|
1769
|
+
} catch (error) {
|
|
1770
|
+
consola.error(`Failed to start service ${serviceId}`, error);
|
|
1771
|
+
process$1.exit(1);
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1774
|
+
async function stopService(serviceId) {
|
|
1775
|
+
const token = await getAccessToken();
|
|
1776
|
+
try {
|
|
1777
|
+
await client.post("/xrpc/io.pocketenv.service.stopService", void 0, {
|
|
1778
|
+
params: {
|
|
1779
|
+
serviceId
|
|
1780
|
+
},
|
|
1781
|
+
headers: {
|
|
1782
|
+
Authorization: `Bearer ${env$1.POCKETENV_TOKEN || token}`
|
|
1783
|
+
}
|
|
1784
|
+
});
|
|
1785
|
+
} catch (error) {
|
|
1786
|
+
consola.error(`Failed to stop service ${serviceId}`, error);
|
|
1787
|
+
process$1.exit(1);
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
async function deleteService(serviceId) {
|
|
1791
|
+
const token = await getAccessToken();
|
|
1792
|
+
try {
|
|
1793
|
+
await client.post("/xrpc/io.pocketenv.service.deleteService", void 0, {
|
|
1794
|
+
params: {
|
|
1795
|
+
serviceId
|
|
1796
|
+
},
|
|
1797
|
+
headers: {
|
|
1798
|
+
Authorization: `Bearer ${env$1.POCKETENV_TOKEN || token}`
|
|
1799
|
+
}
|
|
1800
|
+
});
|
|
1801
|
+
consola.success(`Service ${c.highlight(serviceId)} deleted successfully`);
|
|
1802
|
+
} catch (error) {
|
|
1803
|
+
consola.error(`Failed to delete service ${serviceId}`, error);
|
|
1804
|
+
process$1.exit(1);
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1648
1808
|
const program = new Command();
|
|
1649
1809
|
program.name("pocketenv").description(
|
|
1650
1810
|
`${chalk.bold.rgb(0, 232, 198)(`pocketenv v${version}`)} ${c.muted("\u2500")} ${c.muted("Open, interoperable sandbox platform for agents and humans")}`
|
|
@@ -1674,6 +1834,9 @@ program.command("ls").description("list sandboxes").action(listSandboxes);
|
|
|
1674
1834
|
program.command("start").argument("<sandbox>", "the sandbox to start").option("--ssh, -s", "connect to the Sandbox and automatically open a shell").option(
|
|
1675
1835
|
"--repo, -r <repo>",
|
|
1676
1836
|
"the repository to clone into the sandbox (e.g., github:user/repo, tangled:user/repo, or a Git URL)"
|
|
1837
|
+
).option(
|
|
1838
|
+
"--keep-alive, -k",
|
|
1839
|
+
"keep the sandbox alive, ignoring inactivity timeout"
|
|
1677
1840
|
).description("start the given sandbox").action(start);
|
|
1678
1841
|
program.command("stop").argument("<sandbox>", "the sandbox to stop").description("stop the given sandbox").action(stop);
|
|
1679
1842
|
program.command("create").aliases(["new"]).option("--provider, -p <provider>", "the provider to use for the sandbox").option(
|
|
@@ -1726,6 +1889,13 @@ sshkeys.command("get").argument("<sandbox>", "the sandbox to get the SSH key fro
|
|
|
1726
1889
|
const tailscale = program.command("tailscale").description("manage Tailscale");
|
|
1727
1890
|
tailscale.command("put").argument("<sandbox>", "the sandbox to put the Tailscale Auth Key in").description("put a Tailscale Auth Key in the given sandbox").action(putAuthKey);
|
|
1728
1891
|
tailscale.command("get").argument("<sandbox>", "the sandbox to get the Tailscale Auth Key from").description("get a Tailscale Auth Key (redacted) from the given sandbox").action(getTailscaleAuthKey);
|
|
1892
|
+
const service = program.command("service").description("manage services");
|
|
1893
|
+
service.command("create").argument("<sandbox>", "the sandbox to create the service in").argument("<name>", "the name of the service").argument("<command...>", "the command to run for the service").option("--description, -d <description>", "a description for the service").option("--ports, -p <ports...>", "a list of ports to expose for the service").description("create a new service in the given sandbox").action(createService);
|
|
1894
|
+
service.command("list").aliases(["ls"]).argument("<sandbox>", "the sandbox to list services for").description("list services in the given sandbox").action(listServices);
|
|
1895
|
+
service.command("delete").aliases(["rm", "remove"]).argument("<service_id>", "the ID of the service to delete").description("delete a service").action(deleteService);
|
|
1896
|
+
service.command("start").argument("<service_id>", "the ID of the service to start").description("start a service").action(startService);
|
|
1897
|
+
service.command("stop").argument("<service_id>", "the ID of the service to stop").description("stop a service").action(stopService);
|
|
1898
|
+
service.command("restart").argument("<service_id>", "the ID of the service to restart").description("restart a service").action(restartService);
|
|
1729
1899
|
if (process.argv.length <= 2) {
|
|
1730
1900
|
program.help();
|
|
1731
1901
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import consola from "consola";
|
|
2
|
+
import { client } from "../client";
|
|
3
|
+
import { env } from "../lib/env";
|
|
4
|
+
import getAccessToken from "../lib/getAccessToken";
|
|
5
|
+
import type { Service } from "../types/service";
|
|
6
|
+
import Table from "cli-table3";
|
|
7
|
+
import dayjs from "dayjs";
|
|
8
|
+
import relativeTime from "dayjs/plugin/relativeTime";
|
|
9
|
+
import { c } from "../theme";
|
|
10
|
+
import process from "node:process";
|
|
11
|
+
|
|
12
|
+
dayjs.extend(relativeTime);
|
|
13
|
+
|
|
14
|
+
type CreateServiceOptions = {
|
|
15
|
+
ports?: string[];
|
|
16
|
+
description?: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export async function createService(
|
|
20
|
+
sandboxId: string,
|
|
21
|
+
name: string,
|
|
22
|
+
command: string[],
|
|
23
|
+
{ ports, description }: CreateServiceOptions,
|
|
24
|
+
) {
|
|
25
|
+
const token = await getAccessToken();
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
await client.post(
|
|
29
|
+
"/xrpc/io.pocketenv.service.addService",
|
|
30
|
+
{
|
|
31
|
+
service: {
|
|
32
|
+
name,
|
|
33
|
+
command: command.join(" "),
|
|
34
|
+
description,
|
|
35
|
+
ports: ports?.map((port) => parseInt(port)),
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
params: {
|
|
40
|
+
sandboxId,
|
|
41
|
+
},
|
|
42
|
+
headers: {
|
|
43
|
+
Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
consola.success(`Service ${c.highlight(name)} created successfully`);
|
|
49
|
+
} catch (error) {
|
|
50
|
+
consola.error("Failed to create service", error);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export async function listServices(sandboxId: string) {
|
|
56
|
+
const token = await getAccessToken();
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const { data } = await client.get<{ services: Service[] }>(
|
|
60
|
+
"/xrpc/io.pocketenv.service.getServices",
|
|
61
|
+
{
|
|
62
|
+
params: {
|
|
63
|
+
sandboxId,
|
|
64
|
+
},
|
|
65
|
+
headers: {
|
|
66
|
+
Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`,
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
const table = new Table({
|
|
72
|
+
head: [
|
|
73
|
+
c.primary("ID"),
|
|
74
|
+
c.primary("NAME"),
|
|
75
|
+
c.primary("COMMAND"),
|
|
76
|
+
c.primary("STATUS"),
|
|
77
|
+
c.primary("CREATED AT"),
|
|
78
|
+
],
|
|
79
|
+
chars: {
|
|
80
|
+
top: "",
|
|
81
|
+
"top-mid": "",
|
|
82
|
+
"top-left": "",
|
|
83
|
+
"top-right": "",
|
|
84
|
+
bottom: "",
|
|
85
|
+
"bottom-mid": "",
|
|
86
|
+
"bottom-left": "",
|
|
87
|
+
"bottom-right": "",
|
|
88
|
+
left: "",
|
|
89
|
+
"left-mid": "",
|
|
90
|
+
mid: "",
|
|
91
|
+
"mid-mid": "",
|
|
92
|
+
right: "",
|
|
93
|
+
"right-mid": "",
|
|
94
|
+
middle: " ",
|
|
95
|
+
},
|
|
96
|
+
style: {
|
|
97
|
+
border: [],
|
|
98
|
+
head: [],
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
for (const service of data.services) {
|
|
103
|
+
table.push([
|
|
104
|
+
c.secondary(service.id),
|
|
105
|
+
service.name,
|
|
106
|
+
service.command,
|
|
107
|
+
service.status === "RUNNING"
|
|
108
|
+
? c.highlight(service.status)
|
|
109
|
+
: service.status,
|
|
110
|
+
dayjs(service.createdAt).fromNow(),
|
|
111
|
+
]);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
consola.log(table.toString());
|
|
115
|
+
} catch (error) {
|
|
116
|
+
consola.error("Failed to list services", error);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export async function restartService(serviceId: string) {
|
|
122
|
+
const token = await getAccessToken();
|
|
123
|
+
try {
|
|
124
|
+
await client.post("/xrpc/io.pocketenv.service.restartService", undefined, {
|
|
125
|
+
params: {
|
|
126
|
+
serviceId,
|
|
127
|
+
},
|
|
128
|
+
headers: {
|
|
129
|
+
Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`,
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
} catch (error) {
|
|
133
|
+
consola.error(`Failed to restart service ${serviceId}`, error);
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export async function startService(serviceId: string) {
|
|
139
|
+
const token = await getAccessToken();
|
|
140
|
+
|
|
141
|
+
try {
|
|
142
|
+
await client.post("/xrpc/io.pocketenv.service.startService", undefined, {
|
|
143
|
+
params: {
|
|
144
|
+
serviceId,
|
|
145
|
+
},
|
|
146
|
+
headers: {
|
|
147
|
+
Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`,
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
} catch (error) {
|
|
151
|
+
consola.error(`Failed to start service ${serviceId}`, error);
|
|
152
|
+
process.exit(1);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export async function stopService(serviceId: string) {
|
|
157
|
+
const token = await getAccessToken();
|
|
158
|
+
|
|
159
|
+
try {
|
|
160
|
+
await client.post("/xrpc/io.pocketenv.service.stopService", undefined, {
|
|
161
|
+
params: {
|
|
162
|
+
serviceId,
|
|
163
|
+
},
|
|
164
|
+
headers: {
|
|
165
|
+
Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`,
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
} catch (error) {
|
|
169
|
+
consola.error(`Failed to stop service ${serviceId}`, error);
|
|
170
|
+
process.exit(1);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export async function deleteService(serviceId: string) {
|
|
175
|
+
const token = await getAccessToken();
|
|
176
|
+
|
|
177
|
+
try {
|
|
178
|
+
await client.post("/xrpc/io.pocketenv.service.deleteService", undefined, {
|
|
179
|
+
params: {
|
|
180
|
+
serviceId,
|
|
181
|
+
},
|
|
182
|
+
headers: {
|
|
183
|
+
Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`,
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
consola.success(`Service ${c.highlight(serviceId)} deleted successfully`);
|
|
187
|
+
} catch (error) {
|
|
188
|
+
consola.error(`Failed to delete service ${serviceId}`, error);
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
|
191
|
+
}
|
package/src/cmd/start.ts
CHANGED
|
@@ -9,7 +9,11 @@ import waitUntilRunning from "../lib/waitUntilRunning";
|
|
|
9
9
|
|
|
10
10
|
async function start(
|
|
11
11
|
name: string,
|
|
12
|
-
{
|
|
12
|
+
{
|
|
13
|
+
ssh,
|
|
14
|
+
repo,
|
|
15
|
+
keepAlive,
|
|
16
|
+
}: { ssh?: boolean; repo?: string; keepAlive?: boolean },
|
|
13
17
|
) {
|
|
14
18
|
const token = await getAccessToken();
|
|
15
19
|
if (repo) repo = expandRepo(repo);
|
|
@@ -20,6 +24,7 @@ async function start(
|
|
|
20
24
|
"/xrpc/io.pocketenv.sandbox.startSandbox",
|
|
21
25
|
{
|
|
22
26
|
repo,
|
|
27
|
+
keepAlive,
|
|
23
28
|
},
|
|
24
29
|
{
|
|
25
30
|
params: {
|
package/src/index.ts
CHANGED
|
@@ -23,6 +23,14 @@ import { listPorts } from "./cmd/ports";
|
|
|
23
23
|
import { c } from "./theme";
|
|
24
24
|
import { exposeVscode } from "./cmd/vscode";
|
|
25
25
|
import { exec } from "./cmd/exec";
|
|
26
|
+
import {
|
|
27
|
+
createService,
|
|
28
|
+
deleteService,
|
|
29
|
+
listServices,
|
|
30
|
+
restartService,
|
|
31
|
+
startService,
|
|
32
|
+
stopService,
|
|
33
|
+
} from "./cmd/service";
|
|
26
34
|
|
|
27
35
|
const program = new Command();
|
|
28
36
|
|
|
@@ -81,6 +89,10 @@ program
|
|
|
81
89
|
"--repo, -r <repo>",
|
|
82
90
|
"the repository to clone into the sandbox (e.g., github:user/repo, tangled:user/repo, or a Git URL)",
|
|
83
91
|
)
|
|
92
|
+
.option(
|
|
93
|
+
"--keep-alive, -k",
|
|
94
|
+
"keep the sandbox alive, ignoring inactivity timeout",
|
|
95
|
+
)
|
|
84
96
|
.description("start the given sandbox")
|
|
85
97
|
.action(start);
|
|
86
98
|
|
|
@@ -296,6 +308,50 @@ tailscale
|
|
|
296
308
|
.description("get a Tailscale Auth Key (redacted) from the given sandbox")
|
|
297
309
|
.action(getTailscaleAuthKey);
|
|
298
310
|
|
|
311
|
+
const service = program.command("service").description("manage services");
|
|
312
|
+
|
|
313
|
+
service
|
|
314
|
+
.command("create")
|
|
315
|
+
.argument("<sandbox>", "the sandbox to create the service in")
|
|
316
|
+
.argument("<name>", "the name of the service")
|
|
317
|
+
.argument("<command...>", "the command to run for the service")
|
|
318
|
+
.option("--description, -d <description>", "a description for the service")
|
|
319
|
+
.option("--ports, -p <ports...>", "a list of ports to expose for the service")
|
|
320
|
+
.description("create a new service in the given sandbox")
|
|
321
|
+
.action(createService);
|
|
322
|
+
|
|
323
|
+
service
|
|
324
|
+
.command("list")
|
|
325
|
+
.aliases(["ls"])
|
|
326
|
+
.argument("<sandbox>", "the sandbox to list services for")
|
|
327
|
+
.description("list services in the given sandbox")
|
|
328
|
+
.action(listServices);
|
|
329
|
+
|
|
330
|
+
service
|
|
331
|
+
.command("delete")
|
|
332
|
+
.aliases(["rm", "remove"])
|
|
333
|
+
.argument("<service_id>", "the ID of the service to delete")
|
|
334
|
+
.description("delete a service")
|
|
335
|
+
.action(deleteService);
|
|
336
|
+
|
|
337
|
+
service
|
|
338
|
+
.command("start")
|
|
339
|
+
.argument("<service_id>", "the ID of the service to start")
|
|
340
|
+
.description("start a service")
|
|
341
|
+
.action(startService);
|
|
342
|
+
|
|
343
|
+
service
|
|
344
|
+
.command("stop")
|
|
345
|
+
.argument("<service_id>", "the ID of the service to stop")
|
|
346
|
+
.description("stop a service")
|
|
347
|
+
.action(stopService);
|
|
348
|
+
|
|
349
|
+
service
|
|
350
|
+
.command("restart")
|
|
351
|
+
.argument("<service_id>", "the ID of the service to restart")
|
|
352
|
+
.description("restart a service")
|
|
353
|
+
.action(restartService);
|
|
354
|
+
|
|
299
355
|
if (process.argv.length <= 2) {
|
|
300
356
|
program.help();
|
|
301
357
|
}
|