@cardelli/ambit 0.3.0 → 0.3.2

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 (46) hide show
  1. package/README.md +32 -13
  2. package/esm/cli/commands/create/index.js +10 -28
  3. package/esm/cli/commands/create/machine.d.ts +2 -1
  4. package/esm/cli/commands/create/machine.d.ts.map +1 -1
  5. package/esm/cli/commands/create/machine.js +69 -28
  6. package/esm/cli/commands/list/apps.d.ts +2 -0
  7. package/esm/cli/commands/list/apps.d.ts.map +1 -0
  8. package/esm/cli/commands/list/apps.js +72 -0
  9. package/esm/cli/commands/list/index.d.ts +2 -0
  10. package/esm/cli/commands/list/index.d.ts.map +1 -0
  11. package/esm/cli/commands/list/index.js +62 -0
  12. package/esm/cli/commands/list/networks.d.ts +2 -0
  13. package/esm/cli/commands/list/networks.d.ts.map +1 -0
  14. package/esm/cli/commands/{list.js → list/networks.js} +17 -27
  15. package/esm/cli/commands/status/app.d.ts +2 -0
  16. package/esm/cli/commands/status/app.d.ts.map +1 -0
  17. package/esm/cli/commands/status/app.js +141 -0
  18. package/esm/cli/commands/status/index.d.ts +2 -0
  19. package/esm/cli/commands/status/index.d.ts.map +1 -0
  20. package/esm/cli/commands/status/index.js +68 -0
  21. package/esm/cli/commands/status/network.d.ts +2 -0
  22. package/esm/cli/commands/status/network.d.ts.map +1 -0
  23. package/esm/cli/commands/status/network.js +104 -0
  24. package/esm/cli/commands/status/networks.d.ts +2 -0
  25. package/esm/cli/commands/status/networks.d.ts.map +1 -0
  26. package/esm/cli/commands/status/networks.js +62 -0
  27. package/esm/deno.js +1 -1
  28. package/esm/main.d.ts +2 -2
  29. package/esm/main.d.ts.map +1 -1
  30. package/esm/main.js +5 -2
  31. package/esm/router/start.sh +7 -4
  32. package/esm/schemas/fly.d.ts +84 -4
  33. package/esm/schemas/fly.d.ts.map +1 -1
  34. package/esm/schemas/fly.js +34 -2
  35. package/esm/util/constants.d.ts +0 -1
  36. package/esm/util/constants.d.ts.map +1 -1
  37. package/esm/util/constants.js +0 -1
  38. package/esm/util/discovery.d.ts +4 -1
  39. package/esm/util/discovery.d.ts.map +1 -1
  40. package/esm/util/discovery.js +3 -0
  41. package/package.json +1 -1
  42. package/esm/cli/commands/list.d.ts +0 -2
  43. package/esm/cli/commands/list.d.ts.map +0 -1
  44. package/esm/cli/commands/status.d.ts +0 -2
  45. package/esm/cli/commands/status.d.ts.map +0 -1
  46. package/esm/cli/commands/status.js +0 -334
@@ -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"}
@@ -0,0 +1,62 @@
1
+ // =============================================================================
2
+ // Status Networks — Summary Table of All Networks
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 { discoverRouters } from "../../../util/discovery.js";
10
+ import { initSession } from "../../../util/session.js";
11
+ // =============================================================================
12
+ // Status Networks Subcommand
13
+ // =============================================================================
14
+ export const statusNetworks = async (argv) => {
15
+ const opts = { string: ["org"], boolean: ["help", "json"] };
16
+ const args = parseArgs(argv, opts);
17
+ checkArgs(args, opts, "ambit status networks");
18
+ if (args.help) {
19
+ console.log(`
20
+ ${bold("ambit status networks")} - Show Status of All Networks
21
+
22
+ ${bold("USAGE")}
23
+ ambit status networks [--org <org>] [--json]
24
+
25
+ ${bold("OPTIONS")}
26
+ --org <org> Fly.io organization slug
27
+ --json Output as JSON
28
+ `);
29
+ return;
30
+ }
31
+ const out = createOutput(args.json);
32
+ const { fly, tailscale, org } = await initSession(out, {
33
+ json: args.json,
34
+ org: args.org,
35
+ });
36
+ const routers = await discoverRouters(out, fly, tailscale, org);
37
+ if (routers.length === 0) {
38
+ out.blank()
39
+ .text("No Networks Found.")
40
+ .dim(" Create One with: ambit create <network>")
41
+ .blank();
42
+ out.done({ routers: [] });
43
+ out.print();
44
+ return;
45
+ }
46
+ out.blank().header("Network Status").blank();
47
+ const rows = routers.map((r) => {
48
+ const tsStatus = r.tailscale
49
+ ? (r.tailscale.online ? "online" : "offline")
50
+ : "not found";
51
+ return [r.network, r.appName, r.status, tsStatus];
52
+ });
53
+ const table = new Table()
54
+ .header(["Network", "App", "Status", "Tailscale"])
55
+ .body(rows)
56
+ .indent(2)
57
+ .padding(2);
58
+ out.text(table.toString());
59
+ out.blank();
60
+ out.done({ routers });
61
+ out.print();
62
+ };
package/esm/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "@cardelli/ambit",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Deploy apps to the cloud that only you and your AI agents can reach",
5
5
  "license": "MIT",
6
6
  "tasks": {
package/esm/main.d.ts CHANGED
@@ -3,8 +3,8 @@ import "./_dnt.polyfills.js";
3
3
  import "./cli/commands/create/index.js";
4
4
  import "./cli/commands/deploy/index.js";
5
5
  import "./cli/commands/share.js";
6
- import "./cli/commands/list.js";
7
- import "./cli/commands/status.js";
6
+ import "./cli/commands/list/index.js";
7
+ import "./cli/commands/status/index.js";
8
8
  import "./cli/commands/destroy/index.js";
9
9
  import "./cli/commands/doctor.js";
10
10
  //# sourceMappingURL=main.d.ts.map
package/esm/main.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AACA,OAAO,qBAAqB,CAAC;AA+B7B,OAAO,gCAAgC,CAAC;AACxC,OAAO,gCAAgC,CAAC;AACxC,OAAO,yBAAyB,CAAC;AACjC,OAAO,wBAAwB,CAAC;AAChC,OAAO,0BAA0B,CAAC;AAClC,OAAO,iCAAiC,CAAC;AACzC,OAAO,0BAA0B,CAAC"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AACA,OAAO,qBAAqB,CAAC;AAkC7B,OAAO,gCAAgC,CAAC;AACxC,OAAO,gCAAgC,CAAC;AACxC,OAAO,yBAAyB,CAAC;AACjC,OAAO,8BAA8B,CAAC;AACtC,OAAO,gCAAgC,CAAC;AACxC,OAAO,iCAAiC,CAAC;AACzC,OAAO,0BAA0B,CAAC"}
package/esm/main.js CHANGED
@@ -19,7 +19,10 @@ import * as dntShim from "./_dnt.shims.js";
19
19
  //
20
20
  // Examples:
21
21
  // ambit create browsers
22
+ // ambit list networks
23
+ // ambit list apps browsers
22
24
  // ambit status
25
+ // ambit status network browsers
23
26
  // ambit destroy network browsers
24
27
  // ambit destroy app my-app.browsers
25
28
  // ambit doctor
@@ -30,8 +33,8 @@ import { Spinner, statusErr } from "./lib/cli.js";
30
33
  import "./cli/commands/create/index.js";
31
34
  import "./cli/commands/deploy/index.js";
32
35
  import "./cli/commands/share.js";
33
- import "./cli/commands/list.js";
34
- import "./cli/commands/status.js";
36
+ import "./cli/commands/list/index.js";
37
+ import "./cli/commands/status/index.js";
35
38
  import "./cli/commands/destroy/index.js";
36
39
  import "./cli/commands/doctor.js";
37
40
  // =============================================================================
@@ -5,7 +5,8 @@ set -e
5
5
  # ambit - Self-Configuring Tailscale Subnet Router
6
6
  # =============================================================================
7
7
  # State is persisted to /var/lib/tailscale via Fly volume.
8
- # On first run: authenticates with a pre-minted auth key, advertises routes.
8
+ # On first run: waits for TAILSCALE_AUTHKEY (delivered by the CLI after
9
+ # autoApprovers are in place), then authenticates and advertises routes.
9
10
  # On restart: reuses existing state, no new device created.
10
11
  # The router never receives the user's API token — only a single-use,
11
12
  # tag-scoped auth key that expires after 5 minutes.
@@ -41,10 +42,12 @@ if /usr/local/bin/tailscale status --json 2>/dev/null | jq -e '.BackendState ==
41
42
  --hostname="${FLY_APP_NAME:-ambit}" \
42
43
  --advertise-routes="${SUBNET}"
43
44
  else
44
- # First run - authenticate with pre-minted auth key
45
+ # First run auth key is delivered by the CLI via `fly secrets set` after
46
+ # autoApprovers are configured. If it's not here yet, wait for the restart
47
+ # that the non-staged secrets set triggers.
45
48
  if [ -z "${TAILSCALE_AUTHKEY}" ]; then
46
- echo "Router: ERROR - No TAILSCALE_AUTHKEY Provided"
47
- exit 1
49
+ echo "Router: Waiting for Auth Key (CLI will deliver via secrets)"
50
+ while true; do sleep 5; done
48
51
  fi
49
52
 
50
53
  echo "Router: Authenticating to Tailscale"
@@ -3,6 +3,40 @@ export declare const FlyAuthSchema: z.ZodObject<{
3
3
  email: z.ZodString;
4
4
  }, z.core.$loose>;
5
5
  export type FlyAuth = z.infer<typeof FlyAuthSchema>;
6
+ /** App-level status from the Fly GraphQL API / REST API (AppState enum). */
7
+ export declare const FlyAppStatusEnum: z.ZodEnum<{
8
+ deployed: "deployed";
9
+ pending: "pending";
10
+ suspended: "suspended";
11
+ }>;
12
+ export type FlyAppStatus = z.infer<typeof FlyAppStatusEnum>;
13
+ /**
14
+ * Machine-level state from the Fly Machines API.
15
+ * Persistent: created, started, stopped, suspended, failed
16
+ * Transient: creating, starting, stopping, restarting, suspending, destroying,
17
+ * updating, replacing, launch_failed
18
+ * Terminal: destroyed, replaced, migrated
19
+ */
20
+ export declare const FlyMachineStateEnum: z.ZodEnum<{
21
+ suspended: "suspended";
22
+ created: "created";
23
+ started: "started";
24
+ stopped: "stopped";
25
+ failed: "failed";
26
+ creating: "creating";
27
+ starting: "starting";
28
+ stopping: "stopping";
29
+ restarting: "restarting";
30
+ suspending: "suspending";
31
+ destroying: "destroying";
32
+ updating: "updating";
33
+ replacing: "replacing";
34
+ launch_failed: "launch_failed";
35
+ destroyed: "destroyed";
36
+ replaced: "replaced";
37
+ migrated: "migrated";
38
+ }>;
39
+ export type FlyMachineState = z.infer<typeof FlyMachineStateEnum>;
6
40
  export declare const FlyAppSchema: z.ZodObject<{
7
41
  Name: z.ZodString;
8
42
  Status: z.ZodString;
@@ -50,7 +84,25 @@ export declare const FlyMachineConfigSchema: z.ZodObject<{
50
84
  export declare const FlyMachineSchema: z.ZodObject<{
51
85
  id: z.ZodString;
52
86
  name: z.ZodString;
53
- state: z.ZodString;
87
+ state: z.ZodCatch<z.ZodEnum<{
88
+ suspended: "suspended";
89
+ created: "created";
90
+ started: "started";
91
+ stopped: "stopped";
92
+ failed: "failed";
93
+ creating: "creating";
94
+ starting: "starting";
95
+ stopping: "stopping";
96
+ restarting: "restarting";
97
+ suspending: "suspending";
98
+ destroying: "destroying";
99
+ updating: "updating";
100
+ replacing: "replacing";
101
+ launch_failed: "launch_failed";
102
+ destroyed: "destroyed";
103
+ replaced: "replaced";
104
+ migrated: "migrated";
105
+ }>>;
54
106
  region: z.ZodString;
55
107
  private_ip: z.ZodOptional<z.ZodString>;
56
108
  config: z.ZodOptional<z.ZodObject<{
@@ -77,7 +129,25 @@ export type FlyMachine = z.infer<typeof FlyMachineSchema>;
77
129
  export declare const FlyMachinesListSchema: z.ZodArray<z.ZodObject<{
78
130
  id: z.ZodString;
79
131
  name: z.ZodString;
80
- state: z.ZodString;
132
+ state: z.ZodCatch<z.ZodEnum<{
133
+ suspended: "suspended";
134
+ created: "created";
135
+ started: "started";
136
+ stopped: "stopped";
137
+ failed: "failed";
138
+ creating: "creating";
139
+ starting: "starting";
140
+ stopping: "stopping";
141
+ restarting: "restarting";
142
+ suspending: "suspending";
143
+ destroying: "destroying";
144
+ updating: "updating";
145
+ replacing: "replacing";
146
+ launch_failed: "launch_failed";
147
+ destroyed: "destroyed";
148
+ replaced: "replaced";
149
+ migrated: "migrated";
150
+ }>>;
81
151
  region: z.ZodString;
82
152
  private_ip: z.ZodOptional<z.ZodString>;
83
153
  config: z.ZodOptional<z.ZodObject<{
@@ -142,7 +212,12 @@ export declare const FlyIpListSchema: z.ZodArray<z.ZodObject<{
142
212
  export declare const FlyAppInfoSchema: z.ZodObject<{
143
213
  name: z.ZodString;
144
214
  network: z.ZodString;
145
- status: z.ZodString;
215
+ status: z.ZodCatch<z.ZodEnum<{
216
+ deployed: "deployed";
217
+ pending: "pending";
218
+ suspended: "suspended";
219
+ }>>;
220
+ machine_count: z.ZodOptional<z.ZodNumber>;
146
221
  organization: z.ZodOptional<z.ZodObject<{
147
222
  slug: z.ZodString;
148
223
  }, z.core.$strip>>;
@@ -153,7 +228,12 @@ export declare const FlyAppInfoListSchema: z.ZodObject<{
153
228
  apps: z.ZodArray<z.ZodObject<{
154
229
  name: z.ZodString;
155
230
  network: z.ZodString;
156
- status: z.ZodString;
231
+ status: z.ZodCatch<z.ZodEnum<{
232
+ deployed: "deployed";
233
+ pending: "pending";
234
+ suspended: "suspended";
235
+ }>>;
236
+ machine_count: z.ZodOptional<z.ZodNumber>;
157
237
  organization: z.ZodOptional<z.ZodObject<{
158
238
  slug: z.ZodString;
159
239
  }, z.core.$strip>>;
@@ -1 +1 @@
1
- {"version":3,"file":"fly.d.ts","sourceRoot":"","sources":["../../src/schemas/fly.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,4CAA4C,CAAC;AAM/D,eAAO,MAAM,aAAa;;iBAEhB,CAAC;AAEX,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAMpD,eAAO,MAAM,YAAY;;;;;;iBAMf,CAAC;AAEX,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,eAAO,MAAM,iBAAiB;;;;;;kBAAwB,CAAC;AAMvD,eAAO,MAAM,eAAe;;;;;iBAKlB,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAMxD,eAAO,MAAM,qBAAqB;;;;iBAIxB,CAAC;AAEX,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;iBAgBzB,CAAC;AAEX,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;iBASnB,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;kBAA4B,CAAC;AAM/D,eAAO,MAAM,aAAa,uCAAmC,CAAC;AAM9D,eAAO,MAAM,eAAe;;;iBAGlB,CAAC;AAEX,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAMpD,eAAO,MAAM,kBAAkB;;;;;iBAGrB,CAAC;AAEX,eAAO,MAAM,WAAW;;;;;;;;;;;;iBAOd,CAAC;AAEX,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEhD,eAAO,MAAM,eAAe;;;;;;;;;;;;kBAAuB,CAAC;AAMpD,eAAO,MAAM,gBAAgB;;;;;;;iBAKnB,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,oBAAoB;;;;;;;;;;iBAGvB,CAAC"}
1
+ {"version":3,"file":"fly.d.ts","sourceRoot":"","sources":["../../src/schemas/fly.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,4CAA4C,CAAC;AAM/D,eAAO,MAAM,aAAa;;iBAEhB,CAAC;AAEX,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAMpD,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB;;;;EAA+C,CAAC;AAC7E,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE5D;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;EAkB9B,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAMlE,eAAO,MAAM,YAAY;;;;;;iBAMf,CAAC;AAEX,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,eAAO,MAAM,iBAAiB;;;;;;kBAAwB,CAAC;AAMvD,eAAO,MAAM,eAAe;;;;;iBAKlB,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAMxD,eAAO,MAAM,qBAAqB;;;;iBAIxB,CAAC;AAEX,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;iBAgBzB,CAAC;AAEX,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBASnB,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAA4B,CAAC;AAM/D,eAAO,MAAM,aAAa,uCAAmC,CAAC;AAM9D,eAAO,MAAM,eAAe;;;iBAGlB,CAAC;AAEX,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAMpD,eAAO,MAAM,kBAAkB;;;;;iBAGrB,CAAC;AAEX,eAAO,MAAM,WAAW;;;;;;;;;;;;iBAOd,CAAC;AAEX,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEhD,eAAO,MAAM,eAAe;;;;;;;;;;;;kBAAuB,CAAC;AAMpD,eAAO,MAAM,gBAAgB;;;;;;;;;;;;iBAMnB,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;iBAGvB,CAAC"}
@@ -9,6 +9,37 @@ export const FlyAuthSchema = z.object({
9
9
  email: z.string(),
10
10
  }).loose();
11
11
  // =============================================================================
12
+ // State Enums
13
+ // =============================================================================
14
+ /** App-level status from the Fly GraphQL API / REST API (AppState enum). */
15
+ export const FlyAppStatusEnum = z.enum(["deployed", "pending", "suspended"]);
16
+ /**
17
+ * Machine-level state from the Fly Machines API.
18
+ * Persistent: created, started, stopped, suspended, failed
19
+ * Transient: creating, starting, stopping, restarting, suspending, destroying,
20
+ * updating, replacing, launch_failed
21
+ * Terminal: destroyed, replaced, migrated
22
+ */
23
+ export const FlyMachineStateEnum = z.enum([
24
+ "created",
25
+ "started",
26
+ "stopped",
27
+ "suspended",
28
+ "failed",
29
+ "creating",
30
+ "starting",
31
+ "stopping",
32
+ "restarting",
33
+ "suspending",
34
+ "destroying",
35
+ "updating",
36
+ "replacing",
37
+ "launch_failed",
38
+ "destroyed",
39
+ "replaced",
40
+ "migrated",
41
+ ]);
42
+ // =============================================================================
12
43
  // App Schemas
13
44
  // =============================================================================
14
45
  export const FlyAppSchema = z.object({
@@ -52,7 +83,7 @@ export const FlyMachineConfigSchema = z.object({
52
83
  export const FlyMachineSchema = z.object({
53
84
  id: z.string(),
54
85
  name: z.string(),
55
- state: z.string(),
86
+ state: FlyMachineStateEnum.catch("created"),
56
87
  region: z.string(),
57
88
  private_ip: z.string().optional(),
58
89
  config: FlyMachineConfigSchema.optional(),
@@ -93,7 +124,8 @@ export const FlyIpListSchema = z.array(FlyIpSchema);
93
124
  export const FlyAppInfoSchema = z.object({
94
125
  name: z.string(),
95
126
  network: z.string(),
96
- status: z.string(),
127
+ status: FlyAppStatusEnum.catch("pending"),
128
+ machine_count: z.number().optional(),
97
129
  organization: z.object({ slug: z.string() }).optional(),
98
130
  }).loose();
99
131
  export const FlyAppInfoListSchema = z.object({