@zuplo/cli 1.32.0 → 1.34.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 CHANGED
@@ -9,8 +9,26 @@ Commands:
9
9
  zup deploy Deploys current Git branch of the current directory
10
10
  zup list Lists all deployed zups
11
11
  zup test Runs the tests under /tests against an endpoint
12
+ zup tunnel Tunnel commands
13
+
14
+ zup tunnel
15
+
16
+ Tunnel commands
17
+
18
+ Commands:
19
+ zup tunnel create Creates a new tunnel in your account
20
+ zup tunnel delete Deletes a tunnel in your account
21
+ zup tunnel describe Describes a tunnel in your account
22
+ zup tunnel list Lists the tunnels in your account
23
+ zup tunnel rotate-token Rotates the token for a tunnel in your account
24
+ zup tunnel services Tunnel services commands
25
+
26
+ zup tunnel services
27
+
28
+ Tunnel services commands
29
+
30
+ Commands:
31
+ zup tunnel services describe Describes the services for this tunnel
32
+ zup tunnel services update Updates the services for this tunnel
12
33
 
13
- Options:
14
- --version Show version number [boolean]
15
- --help Show help [boolean]
16
34
  ```
package/dist/cli.js CHANGED
@@ -8,6 +8,7 @@ import deleteZup from "./cmds/delete.js";
8
8
  import deploy from "./cmds/deploy.js";
9
9
  import list from "./cmds/list.js";
10
10
  import test from "./cmds/test.js";
11
+ import tunnel from "./cmds/tunnel/index.js";
11
12
  import { printCriticalFailureToConsoleAndExit } from "./common/output.js";
12
13
  const MIN_NODE_VERSION = "18.0.0";
13
14
  if (gte(process.versions.node, MIN_NODE_VERSION)) {
@@ -18,6 +19,7 @@ if (gte(process.versions.node, MIN_NODE_VERSION)) {
18
19
  .command(deploy)
19
20
  .command(list)
20
21
  .command(test)
22
+ .command(tunnel)
21
23
  .demandCommand()
22
24
  .strictCommands()
23
25
  .help().argv;
@@ -0,0 +1,24 @@
1
+ import setBlocking from "../../common/output.js";
2
+ import { create } from "../../tunnel/create/handler.js";
3
+ export default {
4
+ desc: "Creates a new tunnel in your account",
5
+ command: "create",
6
+ builder: (yargs) => {
7
+ return yargs
8
+ .option("tunnel-name", {
9
+ type: "string",
10
+ describe: "The name of the tunnel to create",
11
+ })
12
+ .option("api-key", {
13
+ type: "string",
14
+ describe: "The API Key from Zuplo",
15
+ envVar: "API_KEY",
16
+ })
17
+ .demandOption(["api-key", "tunnel-name"])
18
+ .middleware([setBlocking]);
19
+ },
20
+ handler: async (argv) => {
21
+ create(argv);
22
+ },
23
+ };
24
+ //# sourceMappingURL=create.js.map
@@ -0,0 +1,20 @@
1
+ import setBlocking from "../../common/output.js";
2
+ import { deleteTunnel } from "../../tunnel/delete/handler.js";
3
+ export default {
4
+ desc: "Deletes a tunnel in your account",
5
+ command: "delete",
6
+ builder: (yargs) => {
7
+ return yargs
8
+ .option("api-key", {
9
+ type: "string",
10
+ describe: "The API Key from Zuplo",
11
+ envVar: "API_KEY",
12
+ })
13
+ .demandOption(["api-key"])
14
+ .middleware([setBlocking]);
15
+ },
16
+ handler: async (argv) => {
17
+ deleteTunnel(argv);
18
+ },
19
+ };
20
+ //# sourceMappingURL=delete.js.map
@@ -0,0 +1,24 @@
1
+ import setBlocking from "../../common/output.js";
2
+ import { describe } from "../../tunnel/describe/handler.js";
3
+ export default {
4
+ desc: "Describes a tunnel in your account",
5
+ command: "describe",
6
+ builder: (yargs) => {
7
+ return yargs
8
+ .option("tunnel-id", {
9
+ type: "string",
10
+ describe: "The ID of the tunnel to describe",
11
+ })
12
+ .option("api-key", {
13
+ type: "string",
14
+ describe: "The API Key from Zuplo",
15
+ envVar: "API_KEY",
16
+ })
17
+ .demandOption(["api-key", "tunnel-id"])
18
+ .middleware([setBlocking]);
19
+ },
20
+ handler: async (argv) => {
21
+ describe(argv);
22
+ },
23
+ };
24
+ //# sourceMappingURL=describe.js.map
@@ -0,0 +1,24 @@
1
+ import { groupHandler } from "../../common/handler.js";
2
+ import create from "./create.js";
3
+ import deleteTunnel from "./delete.js";
4
+ import describe from "./describe.js";
5
+ import list from "./list.js";
6
+ import rotateToken from "./rotate-token.js";
7
+ import services from "./services/index.js";
8
+ const commands = {
9
+ describe: "Tunnel commands",
10
+ command: "tunnel",
11
+ builder: (yargs) => {
12
+ return yargs
13
+ .command(create)
14
+ .command(deleteTunnel)
15
+ .command(describe)
16
+ .command(list)
17
+ .command(rotateToken)
18
+ .command(services)
19
+ .help();
20
+ },
21
+ handler: groupHandler,
22
+ };
23
+ export default commands;
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,20 @@
1
+ import setBlocking from "../../common/output.js";
2
+ import { list } from "../../tunnel/list/handler.js";
3
+ export default {
4
+ desc: "Lists the tunnels in your account",
5
+ command: "list",
6
+ builder: (yargs) => {
7
+ return yargs
8
+ .option("api-key", {
9
+ type: "string",
10
+ describe: "The API Key from Zuplo",
11
+ envVar: "API_KEY",
12
+ })
13
+ .demandOption(["api-key"])
14
+ .middleware([setBlocking]);
15
+ },
16
+ handler: async (argv) => {
17
+ await list(argv);
18
+ },
19
+ };
20
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1,24 @@
1
+ import setBlocking from "../../common/output.js";
2
+ import { rotateToken } from "../../tunnel/rotate-token/handler.js";
3
+ export default {
4
+ desc: "Rotates the token for a tunnel in your account",
5
+ command: "rotate-token",
6
+ builder: (yargs) => {
7
+ return yargs
8
+ .option("tunnel-id", {
9
+ type: "string",
10
+ describe: "The ID of the tunnel to rotate the token for",
11
+ })
12
+ .option("api-key", {
13
+ type: "string",
14
+ describe: "The API Key from Zuplo",
15
+ envVar: "API_KEY",
16
+ })
17
+ .demandOption(["api-key", "tunnel-id"])
18
+ .middleware([setBlocking]);
19
+ },
20
+ handler: async (argv) => {
21
+ rotateToken(argv);
22
+ },
23
+ };
24
+ //# sourceMappingURL=rotate-token.js.map
@@ -0,0 +1,24 @@
1
+ import setBlocking from "../../../common/output.js";
2
+ import { describe, } from "../../../tunnel/services/describe/handler.js";
3
+ export default {
4
+ desc: "Describes the services for this tunnel",
5
+ command: "describe",
6
+ builder: (yargs) => {
7
+ return yargs
8
+ .option("tunnel-id", {
9
+ type: "string",
10
+ describe: "The ID of the tunnel containing the services",
11
+ })
12
+ .option("api-key", {
13
+ type: "string",
14
+ describe: "The API Key from Zuplo",
15
+ envVar: "API_KEY",
16
+ })
17
+ .demandOption(["api-key", "tunnel-id"])
18
+ .middleware([setBlocking]);
19
+ },
20
+ handler: async (argv) => {
21
+ describe(argv);
22
+ },
23
+ };
24
+ //# sourceMappingURL=describe.js.map
@@ -0,0 +1,13 @@
1
+ import { groupHandler } from "../../../common/handler.js";
2
+ import describe from "./describe.js";
3
+ import update from "./update.js";
4
+ const commands = {
5
+ describe: "Tunnel services commands",
6
+ command: "services",
7
+ builder: (yargs) => {
8
+ return yargs.command(describe).command(update).help();
9
+ },
10
+ handler: groupHandler,
11
+ };
12
+ export default commands;
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,28 @@
1
+ import setBlocking from "../../../common/output.js";
2
+ import { updateServices, } from "../../../tunnel/services/update/handler.js";
3
+ export default {
4
+ desc: "Updates the services for this tunnel",
5
+ command: "update",
6
+ builder: (yargs) => {
7
+ return yargs
8
+ .option("configuration-file", {
9
+ type: "string",
10
+ describe: "The path to the configuration file",
11
+ })
12
+ .option("tunnel-id", {
13
+ type: "string",
14
+ describe: "The ID of the tunnel containing the services",
15
+ })
16
+ .option("api-key", {
17
+ type: "string",
18
+ describe: "The API Key from Zuplo",
19
+ envVar: "API_KEY",
20
+ })
21
+ .demandOption(["api-key", "configuration-file", "tunnel-id"])
22
+ .middleware([setBlocking]);
23
+ },
24
+ handler: async (argv) => {
25
+ updateServices(argv);
26
+ },
27
+ };
28
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1,4 @@
1
+ export function groupHandler() {
2
+ console.log("Run with --help to see available commands");
3
+ }
4
+ //# sourceMappingURL=handler.js.map
@@ -9,10 +9,17 @@ export function printCriticalFailureToConsoleAndExit(message) {
9
9
  export function printResultToConsole(message) {
10
10
  console.log(chalk.bold.green(message));
11
11
  }
12
+ export function printTableToConsole(table) {
13
+ console.table(table);
14
+ }
12
15
  export function printResultToConsoleAndExitGracefully(message) {
13
16
  printResultToConsole(message);
14
17
  process.exit(0);
15
18
  }
19
+ export function printTableToConsoleAndExitGracefully(table) {
20
+ printTableToConsole(table);
21
+ process.exit(0);
22
+ }
16
23
  export default function setBlocking() {
17
24
  if (typeof process === "undefined")
18
25
  return;
@@ -0,0 +1,39 @@
1
+ import { logger } from "../../common/logger.js";
2
+ import { printCriticalFailureToConsoleAndExit, printDiagnosticsToConsole, printTableToConsoleAndExitGracefully, } from "../../common/output.js";
3
+ import settings from "../../common/settings.js";
4
+ export async function create(argv) {
5
+ const whoAmIResponse = await fetch(`${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/who-am-i`, {
6
+ method: "GET",
7
+ headers: {
8
+ Authorization: `Bearer ${argv["api-key"]}`,
9
+ },
10
+ });
11
+ if (whoAmIResponse.ok) {
12
+ const { account } = await whoAmIResponse.json();
13
+ const createResponse = await fetch(`${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/accounts/${account}/tunnels`, {
14
+ method: "POST",
15
+ headers: {
16
+ Authorization: `Bearer ${argv["api-key"]}`,
17
+ "Content-Type": "application/json",
18
+ },
19
+ body: JSON.stringify({ name: argv["tunnel-name"] }),
20
+ });
21
+ if (createResponse.ok) {
22
+ const tunnel = await createResponse.json();
23
+ printTableToConsoleAndExitGracefully(tunnel);
24
+ }
25
+ else {
26
+ logger.error({
27
+ status: createResponse.status,
28
+ statusText: createResponse.statusText,
29
+ response: await createResponse.text(),
30
+ }, "Failed to create tunnel for account");
31
+ printDiagnosticsToConsole("Error: Failed to create tunnel for your account. Check the arguments.");
32
+ }
33
+ }
34
+ else {
35
+ logger.error({ status: whoAmIResponse.status, statusText: whoAmIResponse.statusText }, "Failed to determine who-am-i");
36
+ printCriticalFailureToConsoleAndExit("Error: Failed to validate the API key. Check your API key.");
37
+ }
38
+ }
39
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1,49 @@
1
+ import { logger } from "../../common/logger.js";
2
+ import { printCriticalFailureToConsoleAndExit, printDiagnosticsToConsole, printResultToConsoleAndExitGracefully, } from "../../common/output.js";
3
+ import settings from "../../common/settings.js";
4
+ import { pollTeardownOperation } from "./poll-teardown-operation.js";
5
+ export async function deleteTunnel(argv) {
6
+ const whoAmIResponse = await fetch(`${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/who-am-i`, {
7
+ method: "GET",
8
+ headers: {
9
+ Authorization: `Bearer ${argv["api-key"]}`,
10
+ },
11
+ });
12
+ if (whoAmIResponse.ok) {
13
+ const { account } = await whoAmIResponse.json();
14
+ const deleteResponse = await fetch(`${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/accounts/${account}/tunnels/${argv["tunnel-id"]}`, {
15
+ method: "DELETE",
16
+ headers: {
17
+ Authorization: `Bearer ${argv["api-key"]}`,
18
+ },
19
+ });
20
+ if (deleteResponse.ok) {
21
+ const teardownOperation = await deleteResponse.json();
22
+ printDiagnosticsToConsole(`Deleting tunnel ${argv["tunnel-id"]} on account ${account}...`);
23
+ const polledTearDownOperation = await pollTeardownOperation({
24
+ argv,
25
+ account,
26
+ teardownOperationId: teardownOperation.id,
27
+ });
28
+ if (polledTearDownOperation.status === "success") {
29
+ printResultToConsoleAndExitGracefully(`Tunnel ${argv["tunnel-id"]} deleted successfully.`);
30
+ }
31
+ else {
32
+ printCriticalFailureToConsoleAndExit(`Tunnel ${argv["tunnel-id"]} failed to delete. Here's the error: ${polledTearDownOperation.message}`);
33
+ }
34
+ }
35
+ else {
36
+ logger.error({
37
+ status: deleteResponse.status,
38
+ statusText: deleteResponse.statusText,
39
+ response: await deleteResponse.text(),
40
+ }, "Failed to delete tunnel for account");
41
+ printDiagnosticsToConsole("Error: Failed to delete the tunnel for your account. Check the arguments.");
42
+ }
43
+ }
44
+ else {
45
+ logger.error({ status: whoAmIResponse.status, statusText: whoAmIResponse.statusText }, "Failed to determine who-am-i");
46
+ printCriticalFailureToConsoleAndExit("Error: Failed to validate the API key. Check your API key.");
47
+ }
48
+ }
49
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1,37 @@
1
+ import { logger } from "../../common/logger.js";
2
+ import { printDiagnosticsToConsole } from "../../common/output.js";
3
+ import settings from "../../common/settings.js";
4
+ function wait(duration = settings.POLL_INTERVAL) {
5
+ return new Promise((resolve) => setTimeout(resolve, duration));
6
+ }
7
+ export async function pollTeardownOperation(args) {
8
+ const apiKey = args.argv["api-key"];
9
+ const tunnelId = args.argv["tunnel-id"];
10
+ for (let pollRetry = 0; pollRetry < settings.MAX_POLL_RETRIES; pollRetry++) {
11
+ printDiagnosticsToConsole(`Polling for teardown operation status... (${pollRetry}/${settings.MAX_POLL_RETRIES})`);
12
+ const response = await fetch(`${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/accounts/${args.account}/tunnels/${tunnelId}/teardown-operations/${args.teardownOperationId}`, {
13
+ method: "GET",
14
+ headers: {
15
+ Authorization: `Bearer ${apiKey}`,
16
+ },
17
+ });
18
+ if (response.ok) {
19
+ const teardownOperation = await response.json();
20
+ switch (teardownOperation.status) {
21
+ case "error":
22
+ return teardownOperation;
23
+ case "in-progress":
24
+ await wait();
25
+ continue;
26
+ case "success":
27
+ return teardownOperation;
28
+ }
29
+ }
30
+ else {
31
+ logger.error(`Unexpected error from server while polling for teardown operation status: ${response.status} ${response.statusText} ${await response.json()}`);
32
+ throw new Error(`Unexpected response from server while polling for teardown operation status: ${response.status} ${response.statusText}`);
33
+ }
34
+ }
35
+ throw new Error("Unexpected error while polling for teardown operation status");
36
+ }
37
+ //# sourceMappingURL=poll-teardown-operation.js.map
@@ -0,0 +1,37 @@
1
+ import { logger } from "../../common/logger.js";
2
+ import { printCriticalFailureToConsoleAndExit, printDiagnosticsToConsole, printTableToConsoleAndExitGracefully, } from "../../common/output.js";
3
+ import settings from "../../common/settings.js";
4
+ export async function describe(argv) {
5
+ const whoAmIResponse = await fetch(`${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/who-am-i`, {
6
+ method: "GET",
7
+ headers: {
8
+ Authorization: `Bearer ${argv["api-key"]}`,
9
+ },
10
+ });
11
+ if (whoAmIResponse.ok) {
12
+ const { account } = await whoAmIResponse.json();
13
+ const describeResponse = await fetch(`${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/accounts/${account}/tunnels/${argv["tunnel-id"]}`, {
14
+ method: "GET",
15
+ headers: {
16
+ Authorization: `Bearer ${argv["api-key"]}`,
17
+ },
18
+ });
19
+ if (describeResponse.ok) {
20
+ const tunnel = await describeResponse.json();
21
+ printTableToConsoleAndExitGracefully(tunnel);
22
+ }
23
+ else {
24
+ logger.error({
25
+ status: describeResponse.status,
26
+ statusText: describeResponse.statusText,
27
+ response: await describeResponse.text(),
28
+ }, "Failed to describe tunnel for account");
29
+ printDiagnosticsToConsole("Error: Failed to describe tunnel for your account. Check the arguments.");
30
+ }
31
+ }
32
+ else {
33
+ logger.error({ status: whoAmIResponse.status, statusText: whoAmIResponse.statusText }, "Failed to determine who-am-i");
34
+ printCriticalFailureToConsoleAndExit("Error: Failed to validate the API key. Check your API key.");
35
+ }
36
+ }
37
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1,46 @@
1
+ import { logger } from "../../common/logger.js";
2
+ import { printCriticalFailureToConsoleAndExit, printDiagnosticsToConsole, printResultToConsoleAndExitGracefully, printTableToConsoleAndExitGracefully, } from "../../common/output.js";
3
+ import settings from "../../common/settings.js";
4
+ export async function list(argv) {
5
+ const whoAmIResponse = await fetch(`${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/who-am-i`, {
6
+ method: "GET",
7
+ headers: {
8
+ Authorization: `Bearer ${argv["api-key"]}`,
9
+ },
10
+ });
11
+ if (whoAmIResponse.ok) {
12
+ const { account } = await whoAmIResponse.json();
13
+ const listResponse = await fetch(`${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/accounts/${account}/tunnels`, {
14
+ method: "GET",
15
+ headers: {
16
+ Authorization: `Bearer ${argv["api-key"]}`,
17
+ },
18
+ });
19
+ if (listResponse.ok) {
20
+ const tunnels = await listResponse.json();
21
+ if (tunnels.length === 0) {
22
+ const output = "No tunnels found";
23
+ printResultToConsoleAndExitGracefully(output);
24
+ }
25
+ else {
26
+ const table = tunnels.map((tunnel) => {
27
+ return { "tunnel-id": tunnel.id, name: tunnel.name };
28
+ });
29
+ printTableToConsoleAndExitGracefully(table);
30
+ }
31
+ }
32
+ else {
33
+ logger.error({
34
+ status: listResponse.status,
35
+ statusText: listResponse.statusText,
36
+ response: await listResponse.text(),
37
+ }, "Failed to list tunnels for account");
38
+ printDiagnosticsToConsole("Error: Failed to list tunnels for your account. Try again later.");
39
+ }
40
+ }
41
+ else {
42
+ logger.error({ status: whoAmIResponse.status, statusText: whoAmIResponse.statusText }, "Failed to determine who-am-i");
43
+ printCriticalFailureToConsoleAndExit("Error: Failed to validate the API key. Check your API key.");
44
+ }
45
+ }
46
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1,37 @@
1
+ import { logger } from "../../common/logger.js";
2
+ import { printCriticalFailureToConsoleAndExit, printDiagnosticsToConsole, printTableToConsoleAndExitGracefully, } from "../../common/output.js";
3
+ import settings from "../../common/settings.js";
4
+ export async function rotateToken(argv) {
5
+ const whoAmIResponse = await fetch(`${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/who-am-i`, {
6
+ method: "GET",
7
+ headers: {
8
+ Authorization: `Bearer ${argv["api-key"]}`,
9
+ },
10
+ });
11
+ if (whoAmIResponse.ok) {
12
+ const { account } = await whoAmIResponse.json();
13
+ const rotateResponse = await fetch(`${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/accounts/${account}/tunnels/${argv["tunnel-id"]}/$rotate-token`, {
14
+ method: "POST",
15
+ headers: {
16
+ Authorization: `Bearer ${argv["api-key"]}`,
17
+ },
18
+ });
19
+ if (rotateResponse.ok) {
20
+ const tunnel = await rotateResponse.json();
21
+ printTableToConsoleAndExitGracefully(tunnel);
22
+ }
23
+ else {
24
+ logger.error({
25
+ status: rotateResponse.status,
26
+ statusText: rotateResponse.statusText,
27
+ response: await rotateResponse.text(),
28
+ }, "Failed to rotate token for tunnel");
29
+ printDiagnosticsToConsole("Error: Failed to rotate token for tunnel. Check the arguments.");
30
+ }
31
+ }
32
+ else {
33
+ logger.error({ status: whoAmIResponse.status, statusText: whoAmIResponse.statusText }, "Failed to determine who-am-i");
34
+ printCriticalFailureToConsoleAndExit("Error: Failed to validate the API key. Check your API key.");
35
+ }
36
+ }
37
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1,37 @@
1
+ import { logger } from "../../../common/logger.js";
2
+ import { printCriticalFailureToConsoleAndExit, printDiagnosticsToConsole, printResultToConsoleAndExitGracefully, } from "../../../common/output.js";
3
+ import settings from "../../../common/settings.js";
4
+ export async function describe(argv) {
5
+ const whoAmIResponse = await fetch(`${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/who-am-i`, {
6
+ method: "GET",
7
+ headers: {
8
+ Authorization: `Bearer ${argv["api-key"]}`,
9
+ },
10
+ });
11
+ if (whoAmIResponse.ok) {
12
+ const { account } = await whoAmIResponse.json();
13
+ const describeResponse = await fetch(`${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/accounts/${account}/tunnels/${argv["tunnel-id"]}/services-configuration`, {
14
+ method: "GET",
15
+ headers: {
16
+ Authorization: `Bearer ${argv["api-key"]}`,
17
+ },
18
+ });
19
+ if (describeResponse.ok) {
20
+ const tunnel = await describeResponse.json();
21
+ printResultToConsoleAndExitGracefully(JSON.stringify(tunnel, null, 2));
22
+ }
23
+ else {
24
+ logger.error({
25
+ status: describeResponse.status,
26
+ statusText: describeResponse.statusText,
27
+ response: await describeResponse.text(),
28
+ }, "Failed to describe services for tunnel");
29
+ printDiagnosticsToConsole("Error: Failed to describe the services for your tunnel. Check the arguments.");
30
+ }
31
+ }
32
+ else {
33
+ logger.error({ status: whoAmIResponse.status, statusText: whoAmIResponse.statusText }, "Failed to determine who-am-i");
34
+ printCriticalFailureToConsoleAndExit("Error: Failed to validate the API key. Check your API key.");
35
+ }
36
+ }
37
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1,59 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { logger } from "../../../common/logger.js";
3
+ import { printCriticalFailureToConsoleAndExit, printDiagnosticsToConsole, printResultToConsoleAndExitGracefully, } from "../../../common/output.js";
4
+ import settings from "../../../common/settings.js";
5
+ import { pollProvisioningOperation } from "./poll-provisioning-operations.js";
6
+ export async function updateServices(argv) {
7
+ const whoAmIResponse = await fetch(`${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/who-am-i`, {
8
+ method: "GET",
9
+ headers: {
10
+ Authorization: `Bearer ${argv["api-key"]}`,
11
+ },
12
+ });
13
+ if (whoAmIResponse.ok) {
14
+ let contents;
15
+ try {
16
+ contents = await readFile(argv["configuration-file"], "utf-8");
17
+ }
18
+ catch (err) {
19
+ printCriticalFailureToConsoleAndExit(`Error reading the configuration file at ${argv["configuration-file"]}: ${err.message}}`);
20
+ }
21
+ const { account } = await whoAmIResponse.json();
22
+ const deleteResponse = await fetch(`${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/accounts/${account}/tunnels/${argv["tunnel-id"]}/services-configuration`, {
23
+ method: "PUT",
24
+ headers: {
25
+ Authorization: `Bearer ${argv["api-key"]}`,
26
+ "Content-Type": "application/json",
27
+ },
28
+ body: contents,
29
+ });
30
+ if (deleteResponse.ok) {
31
+ const provisioningOperation = await deleteResponse.json();
32
+ printDiagnosticsToConsole(`Updating services on tunnel ${argv["tunnel-id"]} on account ${account}...`);
33
+ const polledProvisioningOperation = await pollProvisioningOperation({
34
+ argv,
35
+ account,
36
+ provisioningOperationId: provisioningOperation.id,
37
+ });
38
+ if (polledProvisioningOperation.status === "success") {
39
+ printResultToConsoleAndExitGracefully(`Tunnel ${argv["tunnel-id"]} updated successfully.`);
40
+ }
41
+ else {
42
+ printCriticalFailureToConsoleAndExit(`Tunnel ${argv["tunnel-id"]} failed to update. Here's the error: ${polledProvisioningOperation.message}`);
43
+ }
44
+ }
45
+ else {
46
+ logger.error({
47
+ status: deleteResponse.status,
48
+ statusText: deleteResponse.statusText,
49
+ response: await deleteResponse.text(),
50
+ }, "Failed to update tunnel for account");
51
+ printDiagnosticsToConsole("Error: Failed to update the tunnel for your account. Check the arguments.");
52
+ }
53
+ }
54
+ else {
55
+ logger.error({ status: whoAmIResponse.status, statusText: whoAmIResponse.statusText }, "Failed to determine who-am-i");
56
+ printCriticalFailureToConsoleAndExit("Error: Failed to validate the API key. Check your API key.");
57
+ }
58
+ }
59
+ //# sourceMappingURL=handler.js.map
@@ -0,0 +1,37 @@
1
+ import { logger } from "../../../common/logger.js";
2
+ import { printDiagnosticsToConsole } from "../../../common/output.js";
3
+ import settings from "../../../common/settings.js";
4
+ function wait(duration = settings.POLL_INTERVAL) {
5
+ return new Promise((resolve) => setTimeout(resolve, duration));
6
+ }
7
+ export async function pollProvisioningOperation(args) {
8
+ const apiKey = args.argv["api-key"];
9
+ const tunnelId = args.argv["tunnel-id"];
10
+ for (let pollRetry = 0; pollRetry < settings.MAX_POLL_RETRIES; pollRetry++) {
11
+ printDiagnosticsToConsole(`Polling for provisioning operation status... (${pollRetry}/${settings.MAX_POLL_RETRIES})`);
12
+ const response = await fetch(`${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/accounts/${args.account}/tunnels/${tunnelId}/provisioning-operations/${args.provisioningOperationId}`, {
13
+ method: "GET",
14
+ headers: {
15
+ Authorization: `Bearer ${apiKey}`,
16
+ },
17
+ });
18
+ if (response.ok) {
19
+ const provisioningOperation = await response.json();
20
+ switch (provisioningOperation.status) {
21
+ case "error":
22
+ return provisioningOperation;
23
+ case "in-progress":
24
+ await wait();
25
+ continue;
26
+ case "success":
27
+ return provisioningOperation;
28
+ }
29
+ }
30
+ else {
31
+ logger.error(`Unexpected error from server while polling for provisioning operation status: ${response.status} ${response.statusText} ${await response.json()}`);
32
+ throw new Error(`Unexpected response from server while polling for provisioning operation status: ${response.status} ${response.statusText}`);
33
+ }
34
+ }
35
+ throw new Error("Unexpected error while polling for provisioning operation status");
36
+ }
37
+ //# sourceMappingURL=poll-provisioning-operations.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zuplo/cli",
3
- "version": "1.32.0",
3
+ "version": "1.34.0",
4
4
  "type": "module",
5
5
  "repository": "https://github.com/zuplo/cli",
6
6
  "author": "Zuplo, Inc.",
@@ -27,43 +27,43 @@
27
27
  "devDependencies": {
28
28
  "@types/chai": "^4.3.4",
29
29
  "@types/mocha": "^10.0.1",
30
- "@types/node": "^18.11.5",
30
+ "@types/node": "^18.15.11",
31
31
  "@types/prettier": "^2.7.2",
32
32
  "@types/rimraf": "^3.0.2",
33
33
  "@types/semver": "^7.3.13",
34
- "@types/tar": "^6.1.3",
34
+ "@types/tar": "^6.1.4",
35
35
  "@types/temp": "^0.9.1",
36
- "@types/yargs": "^17.0.13",
37
- "@typescript-eslint/eslint-plugin": "^5.42.0",
38
- "@typescript-eslint/parser": "^5.42.0",
36
+ "@types/yargs": "^17.0.24",
37
+ "@typescript-eslint/eslint-plugin": "^5.57.1",
38
+ "@typescript-eslint/parser": "^5.57.1",
39
39
  "chai": "^4.3.7",
40
- "eslint": "^8.26.0",
41
- "eslint-config-prettier": "^8.5.0",
42
- "eslint-plugin-import": "^2.26.0",
40
+ "eslint": "^8.37.0",
41
+ "eslint-config-prettier": "^8.8.0",
42
+ "eslint-plugin-import": "^2.27.5",
43
43
  "eslint-plugin-node": "^11.1.0",
44
44
  "eslint-plugin-unicorn": "^44.0.2",
45
- "husky": "^8.0.1",
46
- "lint-staged": "^13.0.3",
45
+ "husky": "^8.0.3",
46
+ "lint-staged": "^13.2.0",
47
47
  "mocha": "^10.2.0",
48
- "prettier-plugin-organize-imports": "^3.1.1",
49
- "typescript": "^4.8.4"
48
+ "prettier-plugin-organize-imports": "^3.2.2",
49
+ "typescript": "5.0.3"
50
50
  },
51
51
  "dependencies": {
52
52
  "chalk": "^5.1.2",
53
53
  "deno-bin": "1.31.1",
54
54
  "dotenv": "^16.0.3",
55
- "esbuild": "^0.15.13",
55
+ "esbuild": "^0.15.18",
56
56
  "execa": "^6.1.0",
57
57
  "fast-glob": "^3.2.12",
58
- "ignore": "^5.2.0",
59
- "pino": "^8.7.0",
60
- "pino-pretty": "^9.1.1",
61
- "prettier": "^2.8.4",
58
+ "ignore": "^5.2.4",
59
+ "pino": "^8.11.0",
60
+ "pino-pretty": "^9.4.0",
61
+ "prettier": "^2.8.7",
62
62
  "rimraf": "^3.0.2",
63
63
  "semver": "^7.3.8",
64
- "simple-git": "^3.16.0",
65
- "tar": "^6.1.11",
64
+ "simple-git": "^3.17.0",
65
+ "tar": "^6.1.13",
66
66
  "temp": "^0.9.4",
67
- "yargs": "^17.6.0"
67
+ "yargs": "^17.7.1"
68
68
  }
69
69
  }