@cardelli/ambit 0.3.1 → 0.3.3

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.
Files changed (40) hide show
  1. package/README.md +32 -13
  2. package/esm/cli/commands/list/apps.d.ts +2 -0
  3. package/esm/cli/commands/list/apps.d.ts.map +1 -0
  4. package/esm/cli/commands/list/apps.js +72 -0
  5. package/esm/cli/commands/list/index.d.ts +2 -0
  6. package/esm/cli/commands/list/index.d.ts.map +1 -0
  7. package/esm/cli/commands/list/index.js +62 -0
  8. package/esm/cli/commands/list/networks.d.ts +2 -0
  9. package/esm/cli/commands/list/networks.d.ts.map +1 -0
  10. package/esm/cli/commands/{list.js → list/networks.js} +17 -27
  11. package/esm/cli/commands/status/app.d.ts +2 -0
  12. package/esm/cli/commands/status/app.d.ts.map +1 -0
  13. package/esm/cli/commands/status/app.js +141 -0
  14. package/esm/cli/commands/status/index.d.ts +2 -0
  15. package/esm/cli/commands/status/index.d.ts.map +1 -0
  16. package/esm/cli/commands/status/index.js +68 -0
  17. package/esm/cli/commands/status/network.d.ts +2 -0
  18. package/esm/cli/commands/status/network.d.ts.map +1 -0
  19. package/esm/cli/commands/status/network.js +104 -0
  20. package/esm/cli/commands/status/networks.d.ts +2 -0
  21. package/esm/cli/commands/status/networks.d.ts.map +1 -0
  22. package/esm/cli/commands/status/networks.js +62 -0
  23. package/esm/deno.js +1 -1
  24. package/esm/lib/cli.d.ts.map +1 -1
  25. package/esm/lib/cli.js +4 -13
  26. package/esm/main.d.ts +2 -2
  27. package/esm/main.d.ts.map +1 -1
  28. package/esm/main.js +5 -2
  29. package/esm/schemas/fly.d.ts +84 -4
  30. package/esm/schemas/fly.d.ts.map +1 -1
  31. package/esm/schemas/fly.js +34 -2
  32. package/esm/util/discovery.d.ts +4 -1
  33. package/esm/util/discovery.d.ts.map +1 -1
  34. package/esm/util/discovery.js +3 -0
  35. package/package.json +1 -1
  36. package/esm/cli/commands/list.d.ts +0 -2
  37. package/esm/cli/commands/list.d.ts.map +0 -1
  38. package/esm/cli/commands/status.d.ts +0 -2
  39. package/esm/cli/commands/status.d.ts.map +0 -1
  40. package/esm/cli/commands/status.js +0 -334
package/README.md CHANGED
@@ -160,32 +160,51 @@ These work with all three modes.
160
160
  | `-y`, `--yes` | Skip confirmation prompts |
161
161
  | `--json` | Machine-readable JSON output |
162
162
 
163
- ### `ambit status [network|app]`
163
+ ### `ambit list networks|apps`
164
164
 
165
- Without a subcommand, defaults to showing all routers (same as `status network`).
165
+ #### `ambit list networks`
166
166
 
167
- #### `ambit status network [<name>]`
167
+ Lists all networks and their routers in a table showing the network name, app name, region, machine state, Tailscale connectivity status, and ACL tag.
168
168
 
169
- Without a network name, shows a summary table of all routers. With a name, shows detailed status for a specific network: machine state, SOCKS proxy, Tailscale IP, subnet, and apps on the network.
169
+ | Flag | Description |
170
+ | ----------------- | ------------------------------ |
171
+ | `--org <org>` | Fly.io organization slug |
172
+ | `--json` | Machine-readable JSON output |
173
+
174
+ #### `ambit list apps <network>`
175
+
176
+ Lists all workload apps on a specific network in a table showing the app name, region, and machine state.
170
177
 
171
178
  | Flag | Description |
172
179
  | ----------------- | ------------------------------ |
173
180
  | `--org <org>` | Fly.io organization slug |
174
181
  | `--json` | Machine-readable JSON output |
175
182
 
176
- #### `ambit status app <app>.<network>`
183
+ ### `ambit status [networks|network|app]`
177
184
 
178
- Shows detailed status for a specific app: machines, Flycast IPs, and the backing router.
185
+ Without a subcommand, defaults to showing all networks (same as `status networks`).
179
186
 
180
- | Flag | Description |
181
- | -------------------- | -------------------------------------------- |
182
- | `--network <name>` | Target network (if not using dot syntax) |
183
- | `--org <org>` | Fly.io organization slug |
184
- | `--json` | Machine-readable JSON output |
187
+ #### `ambit status networks`
188
+
189
+ Shows a summary table of all networks and their routers.
185
190
 
186
- ### `ambit list`
191
+ | Flag | Description |
192
+ | ----------------- | ------------------------------ |
193
+ | `--org <org>` | Fly.io organization slug |
194
+ | `--json` | Machine-readable JSON output |
195
+
196
+ #### `ambit status network <name>`
197
+
198
+ Shows detailed status for a specific network: machine state, SOCKS proxy, Tailscale IP, subnet, and apps on the network.
199
+
200
+ | Flag | Description |
201
+ | ----------------- | ------------------------------ |
202
+ | `--org <org>` | Fly.io organization slug |
203
+ | `--json` | Machine-readable JSON output |
187
204
 
188
- Lists all discovered routers across networks in a table showing the network name, app name, region, machine state, Tailscale connectivity status, and ACL tag.
205
+ #### `ambit status app <app>.<network>`
206
+
207
+ Shows detailed status for a specific app: machines, Flycast IPs, and the backing router.
189
208
 
190
209
  | Flag | Description |
191
210
  | ----------------- | ------------------------------ |
@@ -0,0 +1,2 @@
1
+ export declare const listApps: (argv: string[]) => Promise<void>;
2
+ //# sourceMappingURL=apps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/list/apps.ts"],"names":[],"mappings":"AAgCA,eAAO,MAAM,QAAQ,GAAU,MAAM,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CAqE3D,CAAC"}
@@ -0,0 +1,72 @@
1
+ // =============================================================================
2
+ // List Apps — List All Workload Apps on a Network
3
+ // =============================================================================
4
+ import { parseArgs } from "../../../deps/jsr.io/@std/cli/1.0.28/mod.js";
5
+ import { Table } from "../../../deps/jsr.io/@cliffy/table/1.0.0/mod.js";
6
+ import { bold } from "../../../lib/cli.js";
7
+ import { checkArgs } from "../../../lib/args.js";
8
+ import { createOutput } from "../../../lib/output.js";
9
+ import { findRouterApp, listWorkloadAppsOnNetwork, } from "../../../util/discovery.js";
10
+ import { initSession } from "../../../util/session.js";
11
+ // =============================================================================
12
+ // List Apps Command
13
+ // =============================================================================
14
+ export const listApps = async (argv) => {
15
+ const opts = { string: ["org"], boolean: ["help", "json"] };
16
+ const args = parseArgs(argv, opts);
17
+ checkArgs(args, opts, "ambit list apps");
18
+ if (args.help) {
19
+ console.log(`
20
+ ${bold("ambit list apps")} - List Apps on a Network
21
+
22
+ ${bold("USAGE")}
23
+ ambit list apps <network> [--org <org>] [--json]
24
+
25
+ ${bold("OPTIONS")}
26
+ --org <org> Fly.io organization slug
27
+ --json Output as JSON
28
+
29
+ ${bold("EXAMPLES")}
30
+ ambit list apps browsers
31
+ ambit list apps browsers --json
32
+ `);
33
+ return;
34
+ }
35
+ const out = createOutput(args.json);
36
+ const network = typeof args._[0] === "string" ? args._[0] : undefined;
37
+ if (!network) {
38
+ return out.die("Missing Network Name. Usage: ambit list apps <network>");
39
+ }
40
+ const { fly, org } = await initSession(out, {
41
+ json: args.json,
42
+ org: args.org,
43
+ });
44
+ const router = await findRouterApp(fly, org, network);
45
+ if (!router) {
46
+ return out.die(`No Network Found: '${network}'`);
47
+ }
48
+ const workloads = await listWorkloadAppsOnNetwork(fly, org, network);
49
+ if (workloads.length === 0) {
50
+ out.blank()
51
+ .text(`No Apps Found on Network '${network}'.`)
52
+ .dim(" Deploy one with: ambit deploy <app>.<network>")
53
+ .blank();
54
+ out.done({ network, apps: [] });
55
+ out.print();
56
+ return;
57
+ }
58
+ out.blank().header(`Apps on '${network}'`).blank();
59
+ const rows = workloads.map((w) => [w.appName, w.status]);
60
+ const table = new Table()
61
+ .header(["App", "Status"])
62
+ .body(rows)
63
+ .indent(2)
64
+ .padding(2);
65
+ out.text(table.toString());
66
+ out.blank();
67
+ out.done({
68
+ network,
69
+ apps: workloads.map((w) => ({ appName: w.appName, status: w.status })),
70
+ });
71
+ out.print();
72
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/list/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,62 @@
1
+ // =============================================================================
2
+ // List Command - List Networks or Apps
3
+ // =============================================================================
4
+ import * as dntShim from "../../../_dnt.shims.js";
5
+ import { parseArgs } from "../../../deps/jsr.io/@std/cli/1.0.28/mod.js";
6
+ import { bold } from "../../../lib/cli.js";
7
+ import { registerCommand } from "../../mod.js";
8
+ import { listNetworks } from "./networks.js";
9
+ import { listApps } from "./apps.js";
10
+ // =============================================================================
11
+ // Top-Level Help
12
+ // =============================================================================
13
+ const showListHelp = () => {
14
+ console.log(`
15
+ ${bold("ambit list")} - List Networks or Apps
16
+
17
+ ${bold("USAGE")}
18
+ ambit list networks [options]
19
+ ambit list apps <network> [options]
20
+
21
+ ${bold("SUBCOMMANDS")}
22
+ networks List all networks and their routers
23
+ apps List workload apps on a specific network
24
+
25
+ ${bold("OPTIONS")}
26
+ --org <org> Fly.io organization slug
27
+ --json Output as JSON
28
+
29
+ ${bold("EXAMPLES")}
30
+ ambit list networks
31
+ ambit list apps browsers
32
+ ambit list apps browsers --json
33
+
34
+ Run 'ambit list networks --help' or 'ambit list apps --help' for details.
35
+ `);
36
+ };
37
+ // =============================================================================
38
+ // Dispatcher
39
+ // =============================================================================
40
+ const list = async (argv) => {
41
+ const subcommand = typeof argv[0] === "string" ? argv[0] : undefined;
42
+ if (subcommand === "networks")
43
+ return listNetworks(argv.slice(1));
44
+ if (subcommand === "apps")
45
+ return listApps(argv.slice(1));
46
+ const args = parseArgs(argv, { boolean: ["help"] });
47
+ if (args.help) {
48
+ showListHelp();
49
+ return;
50
+ }
51
+ showListHelp();
52
+ dntShim.Deno.exit(1);
53
+ };
54
+ // =============================================================================
55
+ // Register Command
56
+ // =============================================================================
57
+ registerCommand({
58
+ name: "list",
59
+ description: "List networks or apps",
60
+ usage: "ambit list networks|apps [options]",
61
+ run: list,
62
+ });
@@ -0,0 +1,2 @@
1
+ export declare const listNetworks: (argv: string[]) => Promise<void>;
2
+ //# sourceMappingURL=networks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"networks.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/list/networks.ts"],"names":[],"mappings":"AAqEA,eAAO,MAAM,YAAY,GAAU,MAAM,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CA2B/D,CAAC"}
@@ -1,28 +1,27 @@
1
1
  // =============================================================================
2
- // List Command - List All Discovered Routers
2
+ // List Networks List All Discovered Routers Across Networks
3
3
  // =============================================================================
4
- import { parseArgs } from "../../deps/jsr.io/@std/cli/1.0.28/mod.js";
5
- import { Table } from "../../deps/jsr.io/@cliffy/table/1.0.0/mod.js";
6
- import { bold } from "../../lib/cli.js";
7
- import { checkArgs } from "../../lib/args.js";
8
- import { createOutput } from "../../lib/output.js";
9
- import { registerCommand } from "../mod.js";
10
- import { discoverRouters } from "../../util/discovery.js";
11
- import { initSession } from "../../util/session.js";
4
+ import { parseArgs } from "../../../deps/jsr.io/@std/cli/1.0.28/mod.js";
5
+ import { Table } from "../../../deps/jsr.io/@cliffy/table/1.0.0/mod.js";
6
+ import { bold } from "../../../lib/cli.js";
7
+ import { checkArgs } from "../../../lib/args.js";
8
+ import { createOutput } from "../../../lib/output.js";
9
+ import { discoverRouters } from "../../../util/discovery.js";
10
+ import { initSession } from "../../../util/session.js";
12
11
  // =============================================================================
13
12
  // Stage: Render
14
13
  // =============================================================================
15
14
  const stageRender = (out, routers) => {
16
15
  if (routers.length === 0) {
17
16
  out.blank()
18
- .text("No Routers Found.")
17
+ .text("No Networks Found.")
19
18
  .dim(" Create one with: ambit create <network>")
20
19
  .blank();
21
20
  out.done({ routers: [] });
22
21
  out.print();
23
22
  return;
24
23
  }
25
- out.blank().header("Routers").blank();
24
+ out.blank().header("Networks").blank();
26
25
  const rows = routers.map((r) => {
27
26
  const tsStatus = r.tailscale
28
27
  ? (r.tailscale.online ? "online" : "offline")
@@ -31,14 +30,14 @@ const stageRender = (out, routers) => {
31
30
  return [
32
31
  r.network,
33
32
  r.appName,
33
+ r.status,
34
34
  r.machine?.region ?? "-",
35
- r.machine?.state ?? "unknown",
36
35
  tsStatus,
37
36
  tag,
38
37
  ];
39
38
  });
40
39
  const table = new Table()
41
- .header(["Network", "App", "Region", "State", "Tailscale", "Tag"])
40
+ .header(["Network", "App", "Status", "Region", "Tailscale", "Tag"])
42
41
  .body(rows)
43
42
  .indent(2)
44
43
  .padding(2);
@@ -48,18 +47,18 @@ const stageRender = (out, routers) => {
48
47
  out.print();
49
48
  };
50
49
  // =============================================================================
51
- // List Command
50
+ // List Networks Command
52
51
  // =============================================================================
53
- const list = async (argv) => {
52
+ export const listNetworks = async (argv) => {
54
53
  const opts = { string: ["org"], boolean: ["help", "json"] };
55
54
  const args = parseArgs(argv, opts);
56
- checkArgs(args, opts, "ambit list");
55
+ checkArgs(args, opts, "ambit list networks");
57
56
  if (args.help) {
58
57
  console.log(`
59
- ${bold("ambit list")} - List All Discovered Routers
58
+ ${bold("ambit list networks")} - List All Networks
60
59
 
61
60
  ${bold("USAGE")}
62
- ambit list [--org <org>] [--json]
61
+ ambit list networks [--org <org>] [--json]
63
62
 
64
63
  ${bold("OPTIONS")}
65
64
  --org <org> Fly.io organization slug
@@ -75,12 +74,3 @@ ${bold("OPTIONS")}
75
74
  const routers = await discoverRouters(out, fly, tailscale, org);
76
75
  stageRender(out, routers);
77
76
  };
78
- // =============================================================================
79
- // Register Command
80
- // =============================================================================
81
- registerCommand({
82
- name: "list",
83
- description: "List all discovered routers across networks",
84
- usage: "ambit list [--org <org>] [--json]",
85
- run: list,
86
- });
@@ -0,0 +1,2 @@
1
+ export declare const statusApp: (argv: string[]) => Promise<void>;
2
+ //# sourceMappingURL=app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/status/app.ts"],"names":[],"mappings":"AA4JA,eAAO,MAAM,SAAS,GAAU,MAAM,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CAyD5D,CAAC"}
@@ -0,0 +1,141 @@
1
+ // =============================================================================
2
+ // Status App — Show App Status
3
+ // =============================================================================
4
+ import { parseArgs } from "../../../deps/jsr.io/@std/cli/1.0.28/mod.js";
5
+ import { bold } from "../../../lib/cli.js";
6
+ import { checkArgs } from "../../../lib/args.js";
7
+ import { createOutput } from "../../../lib/output.js";
8
+ import { findRouterApp, findWorkloadApp, getRouterMachineInfo, getRouterTailscaleInfo, } from "../../../util/discovery.js";
9
+ import { initSession } from "../../../util/session.js";
10
+ import { SOCKS_PROXY_PORT } from "../../../util/constants.js";
11
+ // =============================================================================
12
+ // Detailed App View
13
+ // =============================================================================
14
+ const stageAppStatus = async (fly, tailscale, app, network, org, json) => {
15
+ const out = createOutput(json);
16
+ const workload = await findWorkloadApp(fly, org, app, network);
17
+ if (!workload) {
18
+ return out.die(`App '${app}' Not Found on Network '${network}'`);
19
+ }
20
+ const machines = await fly.machines.list(workload.appName);
21
+ const ips = await fly.ips.list(workload.appName);
22
+ const mappedMachines = machines.map((m) => ({
23
+ id: m.id,
24
+ region: m.region,
25
+ state: m.state,
26
+ privateIp: m.private_ip,
27
+ }));
28
+ const mappedIps = ips.map((ip) => ({
29
+ address: ip.Address,
30
+ type: ip.Type,
31
+ network: ip.Network?.Name,
32
+ }));
33
+ const router = await findRouterApp(fly, org, network);
34
+ out.blank()
35
+ .header(`Ambit Status: ${app}.${network}`)
36
+ .blank()
37
+ .text(` App: ${bold(app)}`)
38
+ .text(` Network: ${network}`)
39
+ .text(` Fly App: ${workload.appName}`)
40
+ .text(` Status: ${workload.status}`)
41
+ .blank();
42
+ if (machines.length === 0) {
43
+ out.text(" Machines: None");
44
+ }
45
+ else {
46
+ out.header(" Machines").blank();
47
+ for (const m of machines) {
48
+ out.text(` ${m.id} ${m.region} ${m.state}${m.private_ip ? ` ${m.private_ip}` : ""}`);
49
+ }
50
+ }
51
+ out.blank();
52
+ const flycastIps = ips.filter((ip) => ip.Type === "private_v6");
53
+ const publicIps = ips.filter((ip) => ip.Type !== "private_v6");
54
+ if (flycastIps.length > 0) {
55
+ out.header(" Flycast IPs").blank();
56
+ for (const ip of flycastIps) {
57
+ out.text(` ${ip.Address} (network: ${ip.Network?.Name ?? "default"})`);
58
+ }
59
+ out.blank();
60
+ }
61
+ if (publicIps.length > 0) {
62
+ out.header(" Public IPs (Warning: Ambit Apps Should Not Have Public IPs)")
63
+ .blank();
64
+ for (const ip of publicIps) {
65
+ out.text(` ${ip.Address} ${ip.Type}`);
66
+ }
67
+ out.blank();
68
+ }
69
+ if (router) {
70
+ const routerMachine = await getRouterMachineInfo(fly, router.appName);
71
+ const ts = await getRouterTailscaleInfo(tailscale, router.appName);
72
+ out.header(" Router").blank()
73
+ .text(` App: ${router.appName}`)
74
+ .text(` State: ${routerMachine?.state ?? "unknown"}`)
75
+ .text(` Tailscale: ${ts ? (ts.online ? "online" : "offline") : "not found"}`);
76
+ if (routerMachine?.privateIp) {
77
+ out.text(` SOCKS Proxy: socks5://[${routerMachine.privateIp}]:${SOCKS_PROXY_PORT}`);
78
+ }
79
+ }
80
+ else {
81
+ out.text(" Router: Not Found");
82
+ }
83
+ out.blank();
84
+ out.done({
85
+ app,
86
+ network,
87
+ flyAppName: workload.appName,
88
+ machines: mappedMachines,
89
+ ips: mappedIps,
90
+ router,
91
+ });
92
+ out.print();
93
+ };
94
+ // =============================================================================
95
+ // Status App Subcommand
96
+ // =============================================================================
97
+ export const statusApp = async (argv) => {
98
+ const opts = {
99
+ string: ["org"],
100
+ boolean: ["help", "json"],
101
+ };
102
+ const args = parseArgs(argv, opts);
103
+ checkArgs(args, opts, "ambit status app");
104
+ if (args.help) {
105
+ console.log(`
106
+ ${bold("ambit status app")} - Show App Status
107
+
108
+ ${bold("USAGE")}
109
+ ambit status app <app>.<network> [--org <org>] [--json]
110
+
111
+ ${bold("OPTIONS")}
112
+ --org <org> Fly.io organization slug
113
+ --json Output as JSON
114
+
115
+ ${bold("EXAMPLES")}
116
+ ambit status app my-app.browsers
117
+ ambit status app my-app.browsers --json
118
+ `);
119
+ return;
120
+ }
121
+ const out = createOutput(args.json);
122
+ const appArg = args._[0];
123
+ if (!appArg || typeof appArg !== "string") {
124
+ return out.die("Missing App Name. Usage: ambit status app <app>.<network>");
125
+ }
126
+ if (!appArg.includes(".")) {
127
+ return out.die(`Missing Network. Use: ambit status app ${appArg}.<network>`);
128
+ }
129
+ const parts = appArg.split(".");
130
+ if (parts.length !== 2 || !parts[0] || !parts[1]) {
131
+ return out.die(`'${appArg}' Should Have Exactly One Dot, Like my-app.my-network`);
132
+ }
133
+ const app = parts[0];
134
+ const network = parts[1];
135
+ const prereqOut = createOutput(args.json);
136
+ const { fly, tailscale, org } = await initSession(prereqOut, {
137
+ json: args.json,
138
+ org: args.org,
139
+ });
140
+ await stageAppStatus(fly, tailscale, app, network, org, args.json);
141
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/status/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,68 @@
1
+ // =============================================================================
2
+ // Status Command - Show Network, App, and Router Status
3
+ // =============================================================================
4
+ import { parseArgs } from "../../../deps/jsr.io/@std/cli/1.0.28/mod.js";
5
+ import { bold } from "../../../lib/cli.js";
6
+ import { registerCommand } from "../../mod.js";
7
+ import { statusNetworks } from "./networks.js";
8
+ import { statusNetwork } from "./network.js";
9
+ import { statusApp } from "./app.js";
10
+ // =============================================================================
11
+ // Top-Level Help
12
+ // =============================================================================
13
+ const showStatusHelp = () => {
14
+ console.log(`
15
+ ${bold("ambit status")} - Show Network, App, and Router Status
16
+
17
+ ${bold("USAGE")}
18
+ ambit status [options]
19
+ ambit status networks [options]
20
+ ambit status network <name> [options]
21
+ ambit status app <app>.<network> [options]
22
+
23
+ ${bold("SUBCOMMANDS")}
24
+ networks Show summary of all networks — default when no subcommand given
25
+ network Show detailed status for a specific network
26
+ app Show a specific app's status
27
+
28
+ ${bold("OPTIONS")}
29
+ --org <org> Fly.io organization slug
30
+ --json Output as JSON
31
+
32
+ ${bold("EXAMPLES")}
33
+ ambit status
34
+ ambit status networks
35
+ ambit status network browsers
36
+ ambit status app my-app.browsers
37
+
38
+ Run 'ambit status networks --help', 'ambit status network --help',
39
+ or 'ambit status app --help' for details.
40
+ `);
41
+ };
42
+ // =============================================================================
43
+ // Dispatcher
44
+ // =============================================================================
45
+ const status = async (argv) => {
46
+ const subcommand = typeof argv[0] === "string" ? argv[0] : undefined;
47
+ if (subcommand === "networks")
48
+ return statusNetworks(argv.slice(1));
49
+ if (subcommand === "network")
50
+ return statusNetwork(argv.slice(1));
51
+ if (subcommand === "app")
52
+ return statusApp(argv.slice(1));
53
+ const args = parseArgs(argv, { boolean: ["help"] });
54
+ if (args.help) {
55
+ showStatusHelp();
56
+ return;
57
+ }
58
+ return statusNetworks(argv);
59
+ };
60
+ // =============================================================================
61
+ // Register Command
62
+ // =============================================================================
63
+ registerCommand({
64
+ name: "status",
65
+ description: "Show network, app, and router status",
66
+ usage: "ambit status [networks|network|app] [<name>] [--org <org>] [--json]",
67
+ run: status,
68
+ });
@@ -0,0 +1,2 @@
1
+ export declare const statusNetwork: (argv: string[]) => Promise<void>;
2
+ //# sourceMappingURL=network.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/status/network.ts"],"names":[],"mappings":"AAgHA,eAAO,MAAM,aAAa,GAAU,MAAM,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CAsChE,CAAC"}
@@ -0,0 +1,104 @@
1
+ // =============================================================================
2
+ // Status Network — Show Detailed Status for a Single Network
3
+ // =============================================================================
4
+ import { parseArgs } from "../../../deps/jsr.io/@std/cli/1.0.28/mod.js";
5
+ import { bold } from "../../../lib/cli.js";
6
+ import { checkArgs } from "../../../lib/args.js";
7
+ import { createOutput } from "../../../lib/output.js";
8
+ import { findRouterApp, getRouterMachineInfo, getRouterTailscaleInfo, listWorkloadAppsOnNetwork, } from "../../../util/discovery.js";
9
+ import { initSession } from "../../../util/session.js";
10
+ import { SOCKS_PROXY_PORT } from "../../../util/constants.js";
11
+ // =============================================================================
12
+ // Detailed View
13
+ // =============================================================================
14
+ const stageNetworkStatus = async (fly, tailscale, network, org, json) => {
15
+ const out = createOutput(json);
16
+ const app = await findRouterApp(fly, org, network);
17
+ if (!app) {
18
+ return out.die(`No Router Found for Network '${network}'`);
19
+ }
20
+ const machine = await getRouterMachineInfo(fly, app.appName);
21
+ const ts = await getRouterTailscaleInfo(tailscale, app.appName);
22
+ const tag = ts?.tags?.[0] ?? null;
23
+ out.blank()
24
+ .header("Ambit Status: Network")
25
+ .blank()
26
+ .text(` Network: ${bold(app.network)}`)
27
+ .text(` TLD: *.${app.network}`)
28
+ .text(` Tag: ${tag ?? "unknown"}`)
29
+ .text(` Status: ${app.status}`)
30
+ .blank()
31
+ .text(` Router App: ${app.appName}`)
32
+ .text(` Region: ${machine?.region ?? "unknown"}`)
33
+ .text(` Machine State: ${machine?.state ?? "no machines"}`)
34
+ .text(` Private IP: ${machine?.privateIp ?? "unknown"}`)
35
+ .text(` SOCKS Proxy: ${machine?.privateIp
36
+ ? `socks5://[${machine.privateIp}]:${SOCKS_PROXY_PORT}`
37
+ : "unknown"}`);
38
+ if (machine?.subnet) {
39
+ out.text(` Subnet: ${machine.subnet}`);
40
+ }
41
+ out.blank();
42
+ if (ts) {
43
+ out.text(` Tailscale IP: ${ts.ip}`)
44
+ .text(` Online: ${ts.online ? "yes" : "no"}`);
45
+ }
46
+ else {
47
+ out.text(" Tailscale: Not Found in Tailnet");
48
+ }
49
+ // Show workload apps on this network
50
+ const workloads = await listWorkloadAppsOnNetwork(fly, org, network);
51
+ if (workloads.length > 0) {
52
+ out.blank().header(" Apps on Network").blank();
53
+ for (const w of workloads) {
54
+ const machines = await fly.machines.list(w.appName);
55
+ const state = machines[0]?.state ?? "no machines";
56
+ const region = machines[0]?.region ?? "-";
57
+ out.text(` ${w.appName} ${region} ${state}`);
58
+ }
59
+ }
60
+ out.blank();
61
+ out.done({
62
+ network: app.network,
63
+ router: app,
64
+ machine,
65
+ tag,
66
+ tailscale: ts,
67
+ });
68
+ out.print();
69
+ };
70
+ // =============================================================================
71
+ // Status Network Subcommand
72
+ // =============================================================================
73
+ export const statusNetwork = async (argv) => {
74
+ const opts = { string: ["org"], boolean: ["help", "json"] };
75
+ const args = parseArgs(argv, opts);
76
+ checkArgs(args, opts, "ambit status network");
77
+ if (args.help) {
78
+ console.log(`
79
+ ${bold("ambit status network")} - Show Detailed Status for a Network
80
+
81
+ ${bold("USAGE")}
82
+ ambit status network <name> [--org <org>] [--json]
83
+
84
+ ${bold("OPTIONS")}
85
+ --org <org> Fly.io organization slug
86
+ --json Output as JSON
87
+
88
+ ${bold("EXAMPLES")}
89
+ ambit status network browsers
90
+ `);
91
+ return;
92
+ }
93
+ const out = createOutput(args.json);
94
+ const network = typeof args._[0] === "string" ? args._[0] : undefined;
95
+ if (!network) {
96
+ return out.die("Missing Network Name. Usage: ambit status network <name>");
97
+ }
98
+ const prereqOut = createOutput(args.json);
99
+ const { fly, tailscale, org } = await initSession(prereqOut, {
100
+ json: args.json,
101
+ org: args.org,
102
+ });
103
+ await stageNetworkStatus(fly, tailscale, network, org, args.json);
104
+ };
@@ -0,0 +1,2 @@
1
+ export declare const statusNetworks: (argv: string[]) => Promise<void>;
2
+ //# sourceMappingURL=networks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"networks.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/status/networks.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,cAAc,GAAU,MAAM,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CAwDjE,CAAC"}