@cardelli/ambit 0.1.5 → 0.2.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.
Files changed (139) hide show
  1. package/esm/cli/commands/create/index.d.ts +2 -0
  2. package/esm/cli/commands/create/index.d.ts.map +1 -0
  3. package/esm/cli/commands/create/index.js +292 -0
  4. package/esm/cli/commands/create/machine.d.ts +33 -0
  5. package/esm/cli/commands/create/machine.d.ts.map +1 -0
  6. package/esm/cli/commands/create/machine.js +162 -0
  7. package/esm/cli/commands/deploy/index.d.ts +2 -0
  8. package/esm/cli/commands/deploy/index.d.ts.map +1 -0
  9. package/esm/cli/commands/deploy/index.js +290 -0
  10. package/esm/cli/commands/deploy/machine.d.ts +52 -0
  11. package/esm/cli/commands/deploy/machine.d.ts.map +1 -0
  12. package/esm/cli/commands/deploy/machine.js +116 -0
  13. package/esm/cli/commands/deploy/modes.d.ts +18 -0
  14. package/esm/cli/commands/deploy/modes.d.ts.map +1 -0
  15. package/esm/cli/commands/deploy/modes.js +152 -0
  16. package/esm/cli/commands/destroy/app.d.ts +2 -0
  17. package/esm/cli/commands/destroy/app.d.ts.map +1 -0
  18. package/esm/cli/commands/destroy/app.js +173 -0
  19. package/esm/cli/commands/destroy/index.d.ts +2 -0
  20. package/esm/cli/commands/destroy/index.d.ts.map +1 -0
  21. package/esm/cli/commands/destroy/index.js +63 -0
  22. package/esm/cli/commands/destroy/network.d.ts +2 -0
  23. package/esm/cli/commands/destroy/network.d.ts.map +1 -0
  24. package/esm/cli/commands/destroy/network.js +210 -0
  25. package/esm/cli/commands/doctor.d.ts.map +1 -0
  26. package/esm/cli/commands/doctor.js +295 -0
  27. package/esm/{src/cli → cli}/commands/list.d.ts.map +1 -1
  28. package/esm/{src/cli → cli}/commands/list.js +39 -54
  29. package/esm/cli/commands/status.d.ts.map +1 -0
  30. package/esm/cli/commands/status.js +331 -0
  31. package/esm/cli/mod.d.ts.map +1 -0
  32. package/esm/{src/cli → cli}/mod.js +4 -4
  33. package/esm/deno.d.ts +4 -18
  34. package/esm/deno.js +5 -19
  35. package/esm/deps/jsr.io/@std/path/1.1.4/constants.d.ts +1 -1
  36. package/esm/lib/args.d.ts +11 -0
  37. package/esm/lib/args.d.ts.map +1 -0
  38. package/esm/lib/args.js +28 -0
  39. package/esm/lib/cli.d.ts +0 -1
  40. package/esm/lib/cli.d.ts.map +1 -1
  41. package/esm/lib/cli.js +0 -1
  42. package/esm/lib/command.d.ts +0 -3
  43. package/esm/lib/command.d.ts.map +1 -1
  44. package/esm/lib/command.js +2 -13
  45. package/esm/lib/machine.d.ts +11 -0
  46. package/esm/lib/machine.d.ts.map +1 -0
  47. package/esm/lib/machine.js +15 -0
  48. package/esm/lib/output.d.ts +2 -1
  49. package/esm/lib/output.d.ts.map +1 -1
  50. package/esm/lib/output.js +21 -3
  51. package/esm/lib/result.d.ts +0 -1
  52. package/esm/lib/result.d.ts.map +1 -1
  53. package/esm/lib/result.js +0 -1
  54. package/esm/main.d.ts +6 -6
  55. package/esm/main.d.ts.map +1 -1
  56. package/esm/main.js +7 -9
  57. package/esm/providers/fly.d.ts +81 -0
  58. package/esm/providers/fly.d.ts.map +1 -0
  59. package/esm/providers/fly.js +372 -0
  60. package/esm/providers/tailscale.d.ts +31 -0
  61. package/esm/providers/tailscale.d.ts.map +1 -0
  62. package/esm/providers/tailscale.js +150 -0
  63. package/esm/{src/schemas → schemas}/fly.d.ts +1 -11
  64. package/esm/schemas/fly.d.ts.map +1 -0
  65. package/esm/{src/schemas → schemas}/fly.js +14 -56
  66. package/esm/{src/schemas → schemas}/tailscale.d.ts +1 -2
  67. package/esm/schemas/tailscale.d.ts.map +1 -0
  68. package/esm/{src/schemas → schemas}/tailscale.js +2 -3
  69. package/esm/src/{docker/router → router}/Dockerfile +0 -11
  70. package/esm/src/{docker/router → router}/start.sh +18 -9
  71. package/esm/util/constants.d.ts +13 -0
  72. package/esm/util/constants.d.ts.map +1 -0
  73. package/esm/util/constants.js +34 -0
  74. package/esm/{src → util}/credentials.d.ts +0 -1
  75. package/esm/util/credentials.d.ts.map +1 -0
  76. package/esm/{src → util}/credentials.js +3 -5
  77. package/esm/{src → util}/discovery.d.ts +16 -3
  78. package/esm/util/discovery.d.ts.map +1 -0
  79. package/esm/{src → util}/discovery.js +24 -15
  80. package/esm/util/fly-transforms.d.ts +27 -0
  81. package/esm/util/fly-transforms.d.ts.map +1 -0
  82. package/esm/util/fly-transforms.js +87 -0
  83. package/esm/{src → util}/guard.d.ts +1 -2
  84. package/esm/util/guard.d.ts.map +1 -0
  85. package/esm/{src → util}/guard.js +27 -27
  86. package/esm/util/naming.d.ts +5 -0
  87. package/esm/util/naming.d.ts.map +1 -0
  88. package/esm/util/naming.js +12 -0
  89. package/esm/{src → util}/resolve.d.ts +2 -3
  90. package/esm/util/resolve.d.ts.map +1 -0
  91. package/esm/{src → util}/resolve.js +1 -2
  92. package/esm/util/session.d.ts +16 -0
  93. package/esm/util/session.d.ts.map +1 -0
  94. package/esm/util/session.js +19 -0
  95. package/esm/util/tailscale-local.d.ts +13 -0
  96. package/esm/util/tailscale-local.d.ts.map +1 -0
  97. package/esm/util/tailscale-local.js +63 -0
  98. package/esm/{src → util}/template.d.ts +0 -1
  99. package/esm/util/template.d.ts.map +1 -0
  100. package/esm/{src → util}/template.js +0 -1
  101. package/package.json +1 -49
  102. package/esm/lib/paths.d.ts +0 -3
  103. package/esm/lib/paths.d.ts.map +0 -1
  104. package/esm/lib/paths.js +0 -5
  105. package/esm/src/cli/commands/create.d.ts +0 -2
  106. package/esm/src/cli/commands/create.d.ts.map +0 -1
  107. package/esm/src/cli/commands/create.js +0 -308
  108. package/esm/src/cli/commands/deploy.d.ts +0 -2
  109. package/esm/src/cli/commands/deploy.d.ts.map +0 -1
  110. package/esm/src/cli/commands/deploy.js +0 -430
  111. package/esm/src/cli/commands/destroy.d.ts +0 -2
  112. package/esm/src/cli/commands/destroy.d.ts.map +0 -1
  113. package/esm/src/cli/commands/destroy.js +0 -340
  114. package/esm/src/cli/commands/doctor.d.ts.map +0 -1
  115. package/esm/src/cli/commands/doctor.js +0 -141
  116. package/esm/src/cli/commands/status.d.ts.map +0 -1
  117. package/esm/src/cli/commands/status.js +0 -152
  118. package/esm/src/cli/mod.d.ts.map +0 -1
  119. package/esm/src/credentials.d.ts.map +0 -1
  120. package/esm/src/discovery.d.ts.map +0 -1
  121. package/esm/src/guard.d.ts.map +0 -1
  122. package/esm/src/providers/fly.d.ts +0 -76
  123. package/esm/src/providers/fly.d.ts.map +0 -1
  124. package/esm/src/providers/fly.js +0 -407
  125. package/esm/src/providers/tailscale.d.ts +0 -31
  126. package/esm/src/providers/tailscale.d.ts.map +0 -1
  127. package/esm/src/providers/tailscale.js +0 -189
  128. package/esm/src/resolve.d.ts.map +0 -1
  129. package/esm/src/schemas/config.d.ts +0 -5
  130. package/esm/src/schemas/config.d.ts.map +0 -1
  131. package/esm/src/schemas/config.js +0 -22
  132. package/esm/src/schemas/fly.d.ts.map +0 -1
  133. package/esm/src/schemas/tailscale.d.ts.map +0 -1
  134. package/esm/src/template.d.ts.map +0 -1
  135. /package/esm/{src/cli → cli}/commands/doctor.d.ts +0 -0
  136. /package/esm/{src/cli → cli}/commands/list.d.ts +0 -0
  137. /package/esm/{src/cli → cli}/commands/status.d.ts +0 -0
  138. /package/esm/{src/cli → cli}/mod.d.ts +0 -0
  139. /package/esm/src/{docker/router → router}/fly.toml +0 -0
@@ -1,76 +0,0 @@
1
- import "../../_dnt.polyfills.js";
2
- import { type FlyApp, type FlyAppInfo, type FlyIp, type FlyMachine } from "../schemas/fly.js";
3
- /**
4
- * Thrown when a `fly deploy` command fails. Carries the raw stderr so callers
5
- * can surface it through `out` (respecting JSON mode) instead of printing
6
- * directly.
7
- */
8
- export declare class FlyDeployError extends Error {
9
- /** Last meaningful line from flyctl stderr. */
10
- readonly detail: string;
11
- constructor(app: string, stderr: string);
12
- }
13
- export type MachineSize = "shared-cpu-1x" | "shared-cpu-2x" | "shared-cpu-4x";
14
- export interface MachineConfig {
15
- size: MachineSize;
16
- memoryMb?: number;
17
- region?: string;
18
- autoStopSeconds?: number;
19
- }
20
- export declare const getSizeConfig: (size: MachineSize) => {
21
- cpus: number;
22
- memoryMb: number;
23
- };
24
- export interface MachineResult {
25
- id: string;
26
- state: string;
27
- size: string;
28
- region: string;
29
- privateIp?: string;
30
- }
31
- export interface SafeDeployOptions {
32
- image?: string;
33
- config?: string;
34
- region?: string;
35
- routerId?: string;
36
- }
37
- export interface FlyProvider {
38
- ensureInstalled(): Promise<void>;
39
- ensureAuth(options?: {
40
- interactive?: boolean;
41
- }): Promise<string>;
42
- listOrgs(): Promise<Record<string, string>>;
43
- createApp(name: string, org: string, options?: {
44
- network?: string;
45
- routerId?: string;
46
- }): Promise<void>;
47
- deleteApp(name: string): Promise<void>;
48
- listApps(org?: string): Promise<FlyApp[]>;
49
- appExists(name: string): Promise<boolean>;
50
- listMachines(app: string): Promise<FlyMachine[]>;
51
- listMachinesMapped(app: string): Promise<MachineResult[]>;
52
- createMachine(app: string, config: MachineConfig): Promise<MachineResult>;
53
- destroyMachine(app: string, machineId: string): Promise<void>;
54
- setSecrets(app: string, secrets: Record<string, string>, options?: {
55
- stage?: boolean;
56
- }): Promise<void>;
57
- routerDeploy(app: string, dockerfilePath: string, config?: {
58
- region?: string;
59
- }): Promise<void>;
60
- listIps(app: string): Promise<FlyIp[]>;
61
- releaseIp(app: string, address: string): Promise<void>;
62
- allocateFlycastIp(app: string, network: string): Promise<void>;
63
- getConfig(app: string): Promise<Record<string, unknown> | null>;
64
- deploySafe(app: string, options: SafeDeployOptions): Promise<void>;
65
- listCerts(app: string): Promise<string[]>;
66
- removeCert(app: string, hostname: string): Promise<void>;
67
- getFlyToken(): Promise<string>;
68
- listAppsWithNetwork(org: string): Promise<FlyAppInfo[]>;
69
- }
70
- export declare const createFlyProvider: () => FlyProvider;
71
- export declare const getRouterAppName: (network: string, randomSuffix: string) => string;
72
- /** Extract the routerId suffix from a router app name. */
73
- export declare const getRouterSuffix: (routerAppName: string, network: string) => string;
74
- /** Build the physical Fly app name for a workload. */
75
- export declare const getWorkloadAppName: (name: string, routerId: string) => string;
76
- //# sourceMappingURL=fly.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fly.d.ts","sourceRoot":"","sources":["../../../src/src/providers/fly.ts"],"names":[],"mappings":"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"}
@@ -1,407 +0,0 @@
1
- // =============================================================================
2
- // Fly.io Provider - Wraps flyctl CLI
3
- // =============================================================================
4
- import "../../_dnt.polyfills.js";
5
- import * as dntShim from "../../_dnt.shims.js";
6
- import { runCommand, runJson, runQuiet } from "../../lib/command.js";
7
- import { Result } from "../../lib/result.js";
8
- import { commandExists, die, Spinner } from "../../lib/cli.js";
9
- import { dirname, resolve } from "../../deps/jsr.io/@std/path/1.1.4/mod.js";
10
- import { FlyAppInfoListSchema, FlyAppsListSchema, FlyAuthSchema, FlyIpListSchema, FlyMachinesListSchema, FlyOrgsSchema, FlyStatusSchema, mapFlyMachineSize, mapFlyMachineState, } from "../schemas/fly.js";
11
- import { fileExists } from "../../lib/cli.js";
12
- // =============================================================================
13
- // Constants
14
- // =============================================================================
15
- const ROUTER_APP_PREFIX = "ambit-";
16
- // =============================================================================
17
- // Deploy Error
18
- // =============================================================================
19
- /**
20
- * Thrown when a `fly deploy` command fails. Carries the raw stderr so callers
21
- * can surface it through `out` (respecting JSON mode) instead of printing
22
- * directly.
23
- */
24
- export class FlyDeployError extends Error {
25
- /** Last meaningful line from flyctl stderr. */
26
- detail;
27
- constructor(app, stderr) {
28
- const detail = extractErrorDetail(stderr);
29
- super(`Deploy Failed for '${app}'`);
30
- this.name = "FlyDeployError";
31
- this.detail = detail;
32
- }
33
- }
34
- /**
35
- * Pull the last non-empty, non-decoration line from fly stderr.
36
- * Fly often prints progress lines then the actual error at the end.
37
- */
38
- const extractErrorDetail = (stderr) => {
39
- const lines = stderr
40
- .split("\n")
41
- .map((l) => l.replace(/\x1b\[[0-9;]*m/g, "").trim())
42
- .filter((l) => l.length > 0 && !l.startsWith("-->") && l !== "Error");
43
- return lines[lines.length - 1] ?? "unknown error";
44
- };
45
- export const getSizeConfig = (size) => {
46
- switch (size) {
47
- case "shared-cpu-1x":
48
- return { cpus: 1, memoryMb: 1024 };
49
- case "shared-cpu-2x":
50
- return { cpus: 2, memoryMb: 2048 };
51
- case "shared-cpu-4x":
52
- return { cpus: 4, memoryMb: 4096 };
53
- }
54
- };
55
- // =============================================================================
56
- // Create Fly Provider
57
- // =============================================================================
58
- export const createFlyProvider = () => {
59
- return {
60
- async ensureInstalled() {
61
- if (!(await commandExists("fly"))) {
62
- return die("Flyctl Not Found. Install from https://fly.io/docs/flyctl/install/");
63
- }
64
- },
65
- async ensureAuth(options) {
66
- const interactive = options?.interactive ?? true;
67
- const result = await runCommand(["fly", "auth", "whoami", "--json"]);
68
- if (result.ok) {
69
- const auth = result.json();
70
- if (auth.ok) {
71
- const parsed = FlyAuthSchema.safeParse(auth.value);
72
- if (parsed.success) {
73
- return parsed.data.email;
74
- }
75
- }
76
- }
77
- if (!interactive) {
78
- return die("Not Authenticated with Fly.io. Run 'fly auth login' First");
79
- }
80
- const loginResult = await runCommand(["fly", "auth", "login"], {
81
- interactive: true,
82
- });
83
- if (!loginResult.ok) {
84
- return die("Fly.io Authentication Failed");
85
- }
86
- const checkResult = await runCommand(["fly", "auth", "whoami", "--json"]);
87
- if (!checkResult.ok) {
88
- return die("Fly.io Authentication Verification Failed");
89
- }
90
- const parsed = FlyAuthSchema.safeParse(checkResult.json().unwrap());
91
- if (!parsed.success || !parsed.data) {
92
- return die("Fly.io Authentication Response Invalid");
93
- }
94
- return parsed.data.email;
95
- },
96
- async listOrgs() {
97
- const result = await runJson(["fly", "orgs", "list", "--json"]);
98
- if (!result.ok) {
99
- return die("Failed to List Organizations");
100
- }
101
- const parsed = FlyOrgsSchema.safeParse(result.value);
102
- if (!parsed.success) {
103
- return die("Failed to Parse Organizations");
104
- }
105
- return parsed.data;
106
- },
107
- async listApps(org) {
108
- const args = ["fly", "apps", "list", "--json"];
109
- if (org) {
110
- args.push("--org", org);
111
- }
112
- const result = await runCommand(args);
113
- return result.json().flatMap((data) => {
114
- const parsed = FlyAppsListSchema.safeParse(data);
115
- return parsed.success
116
- ? Result.ok(parsed.data)
117
- : Result.err("Parse Failed");
118
- }).unwrapOr([]);
119
- },
120
- async createApp(name, org, options) {
121
- const appName = options?.routerId
122
- ? getWorkloadAppName(name, options.routerId)
123
- : name;
124
- const args = ["fly", "apps", "create", appName, "--org", org, "--json"];
125
- if (options?.network) {
126
- args.push("--network", options.network);
127
- }
128
- const result = await runQuiet("Creating App", args);
129
- if (!result.ok) {
130
- return die(`Failed to Create App '${appName}'`);
131
- }
132
- },
133
- async deleteApp(name) {
134
- const result = await runQuiet("Deleting App", [
135
- "fly",
136
- "apps",
137
- "destroy",
138
- name,
139
- "--yes",
140
- ]);
141
- if (!result.ok) {
142
- return die(`Failed to Delete App '${name}'`);
143
- }
144
- },
145
- async appExists(name) {
146
- const result = await runCommand(["fly", "status", "-a", name, "--json"]);
147
- return result.json().match({
148
- ok: (data) => {
149
- const parsed = FlyStatusSchema.safeParse(data);
150
- return parsed.success && !!parsed.data.ID;
151
- },
152
- err: () => false,
153
- });
154
- },
155
- async listMachines(app) {
156
- const result = await runJson(["fly", "machines", "list", "-a", app, "--json"]);
157
- return result.flatMap((data) => {
158
- const parsed = FlyMachinesListSchema.safeParse(data);
159
- return parsed.success
160
- ? Result.ok(parsed.data)
161
- : Result.err("Parse Failed");
162
- }).unwrapOr([]);
163
- },
164
- async listMachinesMapped(app) {
165
- const raw = await this.listMachines(app);
166
- return raw.map((m) => ({
167
- id: m.id,
168
- state: mapFlyMachineState(m.state),
169
- size: mapFlyMachineSize(m.config?.guest),
170
- region: m.region,
171
- privateIp: m.private_ip,
172
- }));
173
- },
174
- async createMachine(app, config) {
175
- const existingMachines = await this.listMachinesMapped(app);
176
- if (existingMachines.length === 0) {
177
- return die("No Existing Machine to Clone. Run 'fly deploy' First");
178
- }
179
- const sourceMachine = existingMachines[0];
180
- const sizeConfig = getSizeConfig(config.size);
181
- const memoryMb = config.memoryMb ?? sizeConfig.memoryMb;
182
- const args = [
183
- "fly",
184
- "machine",
185
- "clone",
186
- sourceMachine.id,
187
- "-a",
188
- app,
189
- "--vm-cpus",
190
- String(sizeConfig.cpus),
191
- "--vm-memory",
192
- String(memoryMb),
193
- ];
194
- if (config.region) {
195
- args.push("--region", config.region);
196
- }
197
- const spinner = new Spinner();
198
- spinner.start(`Creating ${config.size} Machine`);
199
- const result = await runCommand(args);
200
- if (!result.ok) {
201
- spinner.fail("Machine Creation Failed");
202
- return die(result.stderr || "Unknown Error");
203
- }
204
- spinner.success(`Created ${config.size} Machine`);
205
- const machines = await this.listMachinesMapped(app);
206
- const newest = machines[machines.length - 1];
207
- if (!newest) {
208
- return die("Created Machine Not Found");
209
- }
210
- return newest;
211
- },
212
- async destroyMachine(app, machineId) {
213
- const shortId = machineId.slice(0, 8);
214
- const result = await runQuiet(`Destroying Machine ${shortId}`, [
215
- "fly",
216
- "machines",
217
- "destroy",
218
- machineId,
219
- "-a",
220
- app,
221
- "--force",
222
- ]);
223
- if (!result.ok) {
224
- return die(`Failed to Destroy Machine '${shortId}'`);
225
- }
226
- },
227
- async setSecrets(app, secrets, options) {
228
- const pairs = Object.entries(secrets)
229
- .filter(([_, v]) => v !== undefined && v !== "")
230
- .map(([k, v]) => `${k}=${v}`);
231
- if (pairs.length === 0)
232
- return;
233
- const args = ["fly", "secrets", "set", ...pairs, "-a", app];
234
- if (options?.stage) {
235
- args.push("--stage");
236
- }
237
- const result = await runQuiet(`Setting ${pairs.length} Secret(s)`, args);
238
- if (!result.ok) {
239
- return die("Failed to Set Secrets");
240
- }
241
- },
242
- async routerDeploy(app, dockerDir, config) {
243
- const args = [
244
- "fly",
245
- "deploy",
246
- dockerDir,
247
- "-a",
248
- app,
249
- "--yes",
250
- "--ha=false",
251
- ];
252
- if (config?.region) {
253
- args.push("--primary-region", config.region);
254
- }
255
- const result = await runCommand(args);
256
- if (!result.ok) {
257
- throw new FlyDeployError(app, result.stderr);
258
- }
259
- },
260
- async listIps(app) {
261
- const result = await runCommand([
262
- "fly",
263
- "ips",
264
- "list",
265
- "-a",
266
- app,
267
- "--json",
268
- ]);
269
- return result.json().flatMap((data) => {
270
- const parsed = FlyIpListSchema.safeParse(data);
271
- return parsed.success
272
- ? Result.ok(parsed.data)
273
- : Result.err("Parse Failed");
274
- }).unwrapOr([]);
275
- },
276
- async releaseIp(app, address) {
277
- const result = await runCommand([
278
- "fly",
279
- "ips",
280
- "release",
281
- address,
282
- "-a",
283
- app,
284
- ]);
285
- if (!result.ok) {
286
- return die(`Failed to Release IP ${address} from '${app}'`);
287
- }
288
- },
289
- async allocateFlycastIp(app, network) {
290
- const result = await runCommand([
291
- "fly",
292
- "ips",
293
- "allocate-v6",
294
- "--private",
295
- "--network",
296
- network,
297
- "-a",
298
- app,
299
- ]);
300
- if (!result.ok) {
301
- return die(`Failed to Allocate Flycast IP on Network '${network}'`);
302
- }
303
- },
304
- async getConfig(app) {
305
- const result = await runCommand(["fly", "config", "show", "-a", app]);
306
- return result.json().match({
307
- ok: (v) => v,
308
- err: () => null,
309
- });
310
- },
311
- async deploySafe(app, options) {
312
- const appName = options.routerId
313
- ? getWorkloadAppName(app, options.routerId)
314
- : app;
315
- const args = ["fly", "deploy"];
316
- // When config is provided, use its parent directory as the build context
317
- // so fly deploy finds the Dockerfile and COPY picks up the correct files
318
- if (options.config) {
319
- const configAbs = resolve(options.config);
320
- args.push(dirname(configAbs));
321
- args.push("--config", configAbs);
322
- }
323
- args.push("-a", appName, "--yes", "--no-public-ips");
324
- if (options.image) {
325
- args.push("--image", options.image);
326
- }
327
- if (options.region) {
328
- args.push("--primary-region", options.region);
329
- }
330
- const result = await runCommand(args);
331
- if (!result.ok) {
332
- throw new FlyDeployError(appName, result.stderr);
333
- }
334
- },
335
- async listCerts(app) {
336
- const result = await runCommand([
337
- "fly",
338
- "certs",
339
- "list",
340
- "-a",
341
- app,
342
- "--json",
343
- ]);
344
- return result.json().map((certs) => certs
345
- .map((c) => c.Hostname)
346
- .filter((h) => typeof h === "string")).unwrapOr([]);
347
- },
348
- async removeCert(app, hostname) {
349
- await runCommand([
350
- "fly",
351
- "certs",
352
- "remove",
353
- hostname,
354
- "-a",
355
- app,
356
- "--yes",
357
- ]);
358
- },
359
- async getFlyToken() {
360
- // Read access_token from ~/.fly/config.yml
361
- const home = dntShim.Deno.env.get("HOME") || dntShim.Deno.env.get("USERPROFILE") || "";
362
- const configPath = `${home}/.fly/config.yml`;
363
- if (!(await fileExists(configPath))) {
364
- return die("Fly Config Not Found at ~/.fly/config.yml. Run 'fly auth login' First");
365
- }
366
- const content = await dntShim.Deno.readTextFile(configPath);
367
- const match = content.match(/access_token:\s*(.+)/);
368
- if (!match || !match[1]) {
369
- return die("No Access Token Found in ~/.fly/config.yml. Run 'fly auth login' First");
370
- }
371
- return match[1].trim();
372
- },
373
- async listAppsWithNetwork(org) {
374
- const token = await this.getFlyToken();
375
- const response = await fetch(`https://api.machines.dev/v1/apps?org_slug=${encodeURIComponent(org)}`, {
376
- headers: {
377
- Authorization: `Bearer ${token}`,
378
- "Content-Type": "application/json",
379
- },
380
- });
381
- if (!response.ok) {
382
- return die(`Failed to List Apps via REST API: HTTP ${response.status}`);
383
- }
384
- const data = await response.json();
385
- const parsed = FlyAppInfoListSchema.safeParse(data);
386
- if (!parsed.success) {
387
- return die("Failed to Parse Apps REST API Response");
388
- }
389
- return parsed.data.apps;
390
- },
391
- };
392
- };
393
- // =============================================================================
394
- // App Naming
395
- // =============================================================================
396
- export const getRouterAppName = (network, randomSuffix) => {
397
- return `${ROUTER_APP_PREFIX}${network}-${randomSuffix}`;
398
- };
399
- /** Extract the routerId suffix from a router app name. */
400
- export const getRouterSuffix = (routerAppName, network) => {
401
- const prefix = `${ROUTER_APP_PREFIX}${network}-`;
402
- return routerAppName.slice(prefix.length);
403
- };
404
- /** Build the physical Fly app name for a workload. */
405
- export const getWorkloadAppName = (name, routerId) => {
406
- return `${name}-${routerId}`;
407
- };
@@ -1,31 +0,0 @@
1
- import "../../_dnt.polyfills.js";
2
- import { type AuthKeyCapabilities, type TailscaleDevice } from "../schemas/tailscale.js";
3
- export interface TailscaleProvider {
4
- validateApiKey(): Promise<boolean>;
5
- createAuthKey(opts?: AuthKeyCapabilities): Promise<string>;
6
- listDevices(): Promise<TailscaleDevice[]>;
7
- getDeviceByHostname(hostname: string): Promise<TailscaleDevice | null>;
8
- deleteDevice(id: string): Promise<void>;
9
- approveSubnetRoutes(deviceId: string, routes: string[]): Promise<void>;
10
- setSplitDns(domain: string, nameservers: string[]): Promise<void>;
11
- clearSplitDns(domain: string): Promise<void>;
12
- getPolicyFile(): Promise<Record<string, unknown> | null>;
13
- isTagOwnerConfigured(tag: string): Promise<boolean>;
14
- isAutoApproverConfigured(tag: string): Promise<boolean>;
15
- }
16
- export declare const createTailscaleProvider: (tailnet: string, apiKey: string) => TailscaleProvider;
17
- export declare const waitForDevice: (provider: TailscaleProvider, hostname: string, timeoutMs?: number) => Promise<TailscaleDevice>;
18
- /**
19
- * Check if the tailscale CLI is installed.
20
- */
21
- export declare const isTailscaleInstalled: () => Promise<boolean>;
22
- /**
23
- * Check if accept-routes is enabled on the local client.
24
- */
25
- export declare const isAcceptRoutesEnabled: () => Promise<boolean>;
26
- /**
27
- * Enable accept-routes on the local client.
28
- * Returns true if successful, false if it failed (likely permissions).
29
- */
30
- export declare const enableAcceptRoutes: () => Promise<boolean>;
31
- //# sourceMappingURL=tailscale.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tailscale.d.ts","sourceRoot":"","sources":["../../../src/src/providers/tailscale.ts"],"names":[],"mappings":"AAGA,OAAO,yBAAyB,CAAC;AAKjC,OAAO,EACL,KAAK,mBAAmB,EAExB,KAAK,eAAe,EAErB,MAAM,yBAAyB,CAAC;AAYjC,MAAM,WAAW,iBAAiB;IAChC,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,aAAa,CAAC,IAAI,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3D,WAAW,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IAC1C,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IACvE,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClE,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;IACzD,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpD,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACzD;AAiBD,eAAO,MAAM,uBAAuB,GAClC,SAAS,MAAM,EACf,QAAQ,MAAM,KACb,iBAoMF,CAAC;AAMF,eAAO,MAAM,aAAa,GACxB,UAAU,iBAAiB,EAC3B,UAAU,MAAM,EAChB,YAAW,MAAe,KACzB,OAAO,CAAC,eAAe,CAazB,CAAC;AAMF;;GAEG;AACH,eAAO,MAAM,oBAAoB,QAAa,OAAO,CAAC,OAAO,CAE5D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,QAAa,OAAO,CAAC,OAAO,CAM7D,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAAa,OAAO,CAAC,OAAO,CAG1D,CAAC"}