@cardelli/ambit 0.1.3 → 0.1.5
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/esm/deno.d.ts +1 -0
- package/esm/deno.js +3 -2
- package/esm/deps/jsr.io/@std/cli/1.0.28/_data.d.ts.map +1 -0
- package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/_run_length.d.ts.map +1 -1
- package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/mod.d.ts.map +1 -1
- package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/parse_args.d.ts.map +1 -1
- package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/parse_args.js +17 -3
- package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/prompt_secret.d.ts.map +1 -1
- package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/unicode_width.d.ts.map +1 -1
- package/esm/deps/jsr.io/@std/collections/{1.1.3 → 1.1.6}/deep_merge.d.ts +2 -2
- package/esm/deps/jsr.io/@std/collections/{1.1.3 → 1.1.6}/deep_merge.d.ts.map +1 -1
- package/esm/deps/jsr.io/@std/collections/{1.1.3 → 1.1.6}/deep_merge.js +30 -20
- package/esm/deps/jsr.io/@std/toml/1.0.11/_parser.js +1 -1
- package/esm/deps/jsr.io/@zod/zod/4.3.6/src/v4/core/json-schema-generator.d.ts +1 -1
- package/esm/lib/cli.d.ts +0 -1
- package/esm/lib/cli.d.ts.map +1 -1
- package/esm/lib/cli.js +41 -26
- package/esm/lib/command.d.ts +23 -48
- package/esm/lib/command.d.ts.map +1 -1
- package/esm/lib/command.js +60 -89
- package/esm/lib/output.d.ts +1 -1
- package/esm/lib/output.d.ts.map +1 -1
- package/esm/lib/output.js +5 -9
- package/esm/lib/result.d.ts +19 -7
- package/esm/lib/result.d.ts.map +1 -1
- package/esm/lib/result.js +47 -1
- package/esm/main.d.ts.map +1 -1
- package/esm/main.js +3 -2
- package/esm/src/cli/commands/create.js +111 -97
- package/esm/src/cli/commands/deploy.js +61 -35
- package/esm/src/cli/commands/destroy.js +224 -29
- package/esm/src/cli/commands/doctor.js +2 -2
- package/esm/src/cli/commands/list.js +1 -1
- package/esm/src/cli/commands/status.js +1 -1
- package/esm/src/cli/mod.d.ts.map +1 -1
- package/esm/src/cli/mod.js +4 -3
- package/esm/src/discovery.d.ts +13 -0
- package/esm/src/discovery.d.ts.map +1 -1
- package/esm/src/discovery.js +42 -0
- package/esm/src/docker/router/start.sh +18 -72
- package/esm/src/providers/fly.d.ts +6 -0
- package/esm/src/providers/fly.d.ts.map +1 -1
- package/esm/src/providers/fly.js +77 -81
- package/esm/src/providers/tailscale.d.ts.map +1 -1
- package/esm/src/providers/tailscale.js +5 -11
- package/esm/src/template.d.ts +8 -7
- package/esm/src/template.d.ts.map +1 -1
- package/esm/src/template.js +32 -26
- package/package.json +7 -1
- package/esm/deps/jsr.io/@std/cli/1.0.27/_data.d.ts.map +0 -1
- package/esm/deps/jsr.io/@std/collections/1.1.3/_utils.d.ts +0 -6
- package/esm/deps/jsr.io/@std/collections/1.1.3/_utils.d.ts.map +0 -1
- package/esm/deps/jsr.io/@std/collections/1.1.3/_utils.js +0 -18
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/_data.d.ts +0 -0
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/_data.js +0 -0
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/_run_length.d.ts +0 -0
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/_run_length.js +0 -0
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/mod.d.ts +0 -0
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/mod.js +0 -0
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/parse_args.d.ts +0 -0
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/prompt_secret.d.ts +0 -0
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/prompt_secret.js +0 -0
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/unicode_width.d.ts +0 -0
- /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/unicode_width.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fly.d.ts","sourceRoot":"","sources":["../../../src/src/providers/fly.ts"],"names":[],"mappings":"AAGA,OAAO,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"fly.d.ts","sourceRoot":"","sources":["../../../src/src/providers/fly.ts"],"names":[],"mappings":"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"}
|
package/esm/src/providers/fly.js
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
// =============================================================================
|
|
4
4
|
import "../../_dnt.polyfills.js";
|
|
5
5
|
import * as dntShim from "../../_dnt.shims.js";
|
|
6
|
-
import { runCommand,
|
|
6
|
+
import { runCommand, runJson, runQuiet } from "../../lib/command.js";
|
|
7
|
+
import { Result } from "../../lib/result.js";
|
|
7
8
|
import { commandExists, die, Spinner } from "../../lib/cli.js";
|
|
8
9
|
import { dirname, resolve } from "../../deps/jsr.io/@std/path/1.1.4/mod.js";
|
|
9
10
|
import { FlyAppInfoListSchema, FlyAppsListSchema, FlyAuthSchema, FlyIpListSchema, FlyMachinesListSchema, FlyOrgsSchema, FlyStatusSchema, mapFlyMachineSize, mapFlyMachineState, } from "../schemas/fly.js";
|
|
@@ -64,40 +65,40 @@ export const createFlyProvider = () => {
|
|
|
64
65
|
async ensureAuth(options) {
|
|
65
66
|
const interactive = options?.interactive ?? true;
|
|
66
67
|
const result = await runCommand(["fly", "auth", "whoami", "--json"]);
|
|
67
|
-
if (result.
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
if (result.ok) {
|
|
69
|
+
const auth = result.json();
|
|
70
|
+
if (auth.ok) {
|
|
71
|
+
const parsed = FlyAuthSchema.safeParse(auth.value);
|
|
70
72
|
if (parsed.success) {
|
|
71
73
|
return parsed.data.email;
|
|
72
74
|
}
|
|
73
75
|
}
|
|
74
|
-
catch {
|
|
75
|
-
// Parse failed, need to authenticate
|
|
76
|
-
}
|
|
77
76
|
}
|
|
78
77
|
if (!interactive) {
|
|
79
78
|
return die("Not Authenticated with Fly.io. Run 'fly auth login' First");
|
|
80
79
|
}
|
|
81
|
-
const loginResult = await
|
|
82
|
-
|
|
80
|
+
const loginResult = await runCommand(["fly", "auth", "login"], {
|
|
81
|
+
interactive: true,
|
|
82
|
+
});
|
|
83
|
+
if (!loginResult.ok) {
|
|
83
84
|
return die("Fly.io Authentication Failed");
|
|
84
85
|
}
|
|
85
86
|
const checkResult = await runCommand(["fly", "auth", "whoami", "--json"]);
|
|
86
|
-
if (!checkResult.
|
|
87
|
+
if (!checkResult.ok) {
|
|
87
88
|
return die("Fly.io Authentication Verification Failed");
|
|
88
89
|
}
|
|
89
|
-
const parsed = FlyAuthSchema.safeParse(
|
|
90
|
+
const parsed = FlyAuthSchema.safeParse(checkResult.json().unwrap());
|
|
90
91
|
if (!parsed.success || !parsed.data) {
|
|
91
92
|
return die("Fly.io Authentication Response Invalid");
|
|
92
93
|
}
|
|
93
94
|
return parsed.data.email;
|
|
94
95
|
},
|
|
95
96
|
async listOrgs() {
|
|
96
|
-
const result = await
|
|
97
|
-
if (!result.
|
|
97
|
+
const result = await runJson(["fly", "orgs", "list", "--json"]);
|
|
98
|
+
if (!result.ok) {
|
|
98
99
|
return die("Failed to List Organizations");
|
|
99
100
|
}
|
|
100
|
-
const parsed = FlyOrgsSchema.safeParse(result.
|
|
101
|
+
const parsed = FlyOrgsSchema.safeParse(result.value);
|
|
101
102
|
if (!parsed.success) {
|
|
102
103
|
return die("Failed to Parse Organizations");
|
|
103
104
|
}
|
|
@@ -109,25 +110,24 @@ export const createFlyProvider = () => {
|
|
|
109
110
|
args.push("--org", org);
|
|
110
111
|
}
|
|
111
112
|
const result = await runCommand(args);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
catch {
|
|
120
|
-
return [];
|
|
121
|
-
}
|
|
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([]);
|
|
122
119
|
},
|
|
123
120
|
async createApp(name, org, options) {
|
|
124
|
-
const
|
|
121
|
+
const appName = options?.routerId
|
|
122
|
+
? getWorkloadAppName(name, options.routerId)
|
|
123
|
+
: name;
|
|
124
|
+
const args = ["fly", "apps", "create", appName, "--org", org, "--json"];
|
|
125
125
|
if (options?.network) {
|
|
126
126
|
args.push("--network", options.network);
|
|
127
127
|
}
|
|
128
128
|
const result = await runQuiet("Creating App", args);
|
|
129
|
-
if (!result.
|
|
130
|
-
return die(`Failed to Create App '${
|
|
129
|
+
if (!result.ok) {
|
|
130
|
+
return die(`Failed to Create App '${appName}'`);
|
|
131
131
|
}
|
|
132
132
|
},
|
|
133
133
|
async deleteApp(name) {
|
|
@@ -138,29 +138,28 @@ export const createFlyProvider = () => {
|
|
|
138
138
|
name,
|
|
139
139
|
"--yes",
|
|
140
140
|
]);
|
|
141
|
-
if (!result.
|
|
141
|
+
if (!result.ok) {
|
|
142
142
|
return die(`Failed to Delete App '${name}'`);
|
|
143
143
|
}
|
|
144
144
|
},
|
|
145
145
|
async appExists(name) {
|
|
146
146
|
const result = await runCommand(["fly", "status", "-a", name, "--json"]);
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
return false;
|
|
155
|
-
}
|
|
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
|
+
});
|
|
156
154
|
},
|
|
157
155
|
async listMachines(app) {
|
|
158
|
-
const result = await
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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([]);
|
|
164
163
|
},
|
|
165
164
|
async listMachinesMapped(app) {
|
|
166
165
|
const raw = await this.listMachines(app);
|
|
@@ -198,7 +197,7 @@ export const createFlyProvider = () => {
|
|
|
198
197
|
const spinner = new Spinner();
|
|
199
198
|
spinner.start(`Creating ${config.size} Machine`);
|
|
200
199
|
const result = await runCommand(args);
|
|
201
|
-
if (!result.
|
|
200
|
+
if (!result.ok) {
|
|
202
201
|
spinner.fail("Machine Creation Failed");
|
|
203
202
|
return die(result.stderr || "Unknown Error");
|
|
204
203
|
}
|
|
@@ -221,7 +220,7 @@ export const createFlyProvider = () => {
|
|
|
221
220
|
app,
|
|
222
221
|
"--force",
|
|
223
222
|
]);
|
|
224
|
-
if (!result.
|
|
223
|
+
if (!result.ok) {
|
|
225
224
|
return die(`Failed to Destroy Machine '${shortId}'`);
|
|
226
225
|
}
|
|
227
226
|
},
|
|
@@ -236,7 +235,7 @@ export const createFlyProvider = () => {
|
|
|
236
235
|
args.push("--stage");
|
|
237
236
|
}
|
|
238
237
|
const result = await runQuiet(`Setting ${pairs.length} Secret(s)`, args);
|
|
239
|
-
if (!result.
|
|
238
|
+
if (!result.ok) {
|
|
240
239
|
return die("Failed to Set Secrets");
|
|
241
240
|
}
|
|
242
241
|
},
|
|
@@ -254,7 +253,7 @@ export const createFlyProvider = () => {
|
|
|
254
253
|
args.push("--primary-region", config.region);
|
|
255
254
|
}
|
|
256
255
|
const result = await runCommand(args);
|
|
257
|
-
if (!result.
|
|
256
|
+
if (!result.ok) {
|
|
258
257
|
throw new FlyDeployError(app, result.stderr);
|
|
259
258
|
}
|
|
260
259
|
},
|
|
@@ -267,15 +266,12 @@ export const createFlyProvider = () => {
|
|
|
267
266
|
app,
|
|
268
267
|
"--json",
|
|
269
268
|
]);
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
}
|
|
276
|
-
catch {
|
|
277
|
-
return [];
|
|
278
|
-
}
|
|
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([]);
|
|
279
275
|
},
|
|
280
276
|
async releaseIp(app, address) {
|
|
281
277
|
const result = await runCommand([
|
|
@@ -286,7 +282,7 @@ export const createFlyProvider = () => {
|
|
|
286
282
|
"-a",
|
|
287
283
|
app,
|
|
288
284
|
]);
|
|
289
|
-
if (!result.
|
|
285
|
+
if (!result.ok) {
|
|
290
286
|
return die(`Failed to Release IP ${address} from '${app}'`);
|
|
291
287
|
}
|
|
292
288
|
},
|
|
@@ -301,22 +297,21 @@ export const createFlyProvider = () => {
|
|
|
301
297
|
"-a",
|
|
302
298
|
app,
|
|
303
299
|
]);
|
|
304
|
-
if (!result.
|
|
300
|
+
if (!result.ok) {
|
|
305
301
|
return die(`Failed to Allocate Flycast IP on Network '${network}'`);
|
|
306
302
|
}
|
|
307
303
|
},
|
|
308
304
|
async getConfig(app) {
|
|
309
305
|
const result = await runCommand(["fly", "config", "show", "-a", app]);
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
}
|
|
315
|
-
catch {
|
|
316
|
-
return null;
|
|
317
|
-
}
|
|
306
|
+
return result.json().match({
|
|
307
|
+
ok: (v) => v,
|
|
308
|
+
err: () => null,
|
|
309
|
+
});
|
|
318
310
|
},
|
|
319
311
|
async deploySafe(app, options) {
|
|
312
|
+
const appName = options.routerId
|
|
313
|
+
? getWorkloadAppName(app, options.routerId)
|
|
314
|
+
: app;
|
|
320
315
|
const args = ["fly", "deploy"];
|
|
321
316
|
// When config is provided, use its parent directory as the build context
|
|
322
317
|
// so fly deploy finds the Dockerfile and COPY picks up the correct files
|
|
@@ -325,7 +320,7 @@ export const createFlyProvider = () => {
|
|
|
325
320
|
args.push(dirname(configAbs));
|
|
326
321
|
args.push("--config", configAbs);
|
|
327
322
|
}
|
|
328
|
-
args.push("-a",
|
|
323
|
+
args.push("-a", appName, "--yes", "--no-public-ips");
|
|
329
324
|
if (options.image) {
|
|
330
325
|
args.push("--image", options.image);
|
|
331
326
|
}
|
|
@@ -333,8 +328,8 @@ export const createFlyProvider = () => {
|
|
|
333
328
|
args.push("--primary-region", options.region);
|
|
334
329
|
}
|
|
335
330
|
const result = await runCommand(args);
|
|
336
|
-
if (!result.
|
|
337
|
-
throw new FlyDeployError(
|
|
331
|
+
if (!result.ok) {
|
|
332
|
+
throw new FlyDeployError(appName, result.stderr);
|
|
338
333
|
}
|
|
339
334
|
},
|
|
340
335
|
async listCerts(app) {
|
|
@@ -346,17 +341,9 @@ export const createFlyProvider = () => {
|
|
|
346
341
|
app,
|
|
347
342
|
"--json",
|
|
348
343
|
]);
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
const certs = JSON.parse(result.stdout);
|
|
353
|
-
return certs
|
|
354
|
-
.map((c) => c.Hostname)
|
|
355
|
-
.filter((h) => typeof h === "string");
|
|
356
|
-
}
|
|
357
|
-
catch {
|
|
358
|
-
return [];
|
|
359
|
-
}
|
|
344
|
+
return result.json().map((certs) => certs
|
|
345
|
+
.map((c) => c.Hostname)
|
|
346
|
+
.filter((h) => typeof h === "string")).unwrapOr([]);
|
|
360
347
|
},
|
|
361
348
|
async removeCert(app, hostname) {
|
|
362
349
|
await runCommand([
|
|
@@ -404,8 +391,17 @@ export const createFlyProvider = () => {
|
|
|
404
391
|
};
|
|
405
392
|
};
|
|
406
393
|
// =============================================================================
|
|
407
|
-
//
|
|
394
|
+
// App Naming
|
|
408
395
|
// =============================================================================
|
|
409
396
|
export const getRouterAppName = (network, randomSuffix) => {
|
|
410
397
|
return `${ROUTER_APP_PREFIX}${network}-${randomSuffix}`;
|
|
411
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 +1 @@
|
|
|
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,
|
|
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"}
|
|
@@ -174,16 +174,10 @@ export const isTailscaleInstalled = async () => {
|
|
|
174
174
|
*/
|
|
175
175
|
export const isAcceptRoutesEnabled = async () => {
|
|
176
176
|
const result = await runCommand(["tailscale", "debug", "prefs"]);
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
const prefs = JSON.parse(result.stdout);
|
|
182
|
-
return prefs.RouteAll === true;
|
|
183
|
-
}
|
|
184
|
-
catch {
|
|
185
|
-
return false;
|
|
186
|
-
}
|
|
177
|
+
return result.json().match({
|
|
178
|
+
ok: (prefs) => prefs.RouteAll === true,
|
|
179
|
+
err: () => false,
|
|
180
|
+
});
|
|
187
181
|
};
|
|
188
182
|
/**
|
|
189
183
|
* Enable accept-routes on the local client.
|
|
@@ -191,5 +185,5 @@ export const isAcceptRoutesEnabled = async () => {
|
|
|
191
185
|
*/
|
|
192
186
|
export const enableAcceptRoutes = async () => {
|
|
193
187
|
const result = await runCommand(["tailscale", "set", "--accept-routes"]);
|
|
194
|
-
return result.
|
|
188
|
+
return result.ok;
|
|
195
189
|
};
|
package/esm/src/template.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
export type TemplateErrorKind = "NotFound" | "RateLimited" | "HttpError" | "ExtractionFailed" | "PathNotFound" | "PathNotDirectory" | "EmptyArchive" | "NetworkError";
|
|
1
|
+
import "../_dnt.polyfills.js";
|
|
2
|
+
import { Result } from "../lib/result.js";
|
|
4
3
|
/** Parsed GitHub template reference. */
|
|
5
4
|
export interface TemplateRef {
|
|
6
5
|
owner: string;
|
|
@@ -12,16 +11,18 @@ export interface TemplateRef {
|
|
|
12
11
|
export type TemplateFetchResult = Result<{
|
|
13
12
|
tempDir: string;
|
|
14
13
|
templateDir: string;
|
|
15
|
-
}
|
|
14
|
+
}>;
|
|
16
15
|
/**
|
|
17
16
|
* Parse a template reference string into its components.
|
|
18
17
|
* Returns null if the format is invalid.
|
|
19
18
|
*
|
|
20
|
-
* Format: owner/repo/path[@ref]
|
|
19
|
+
* Format: owner/repo[/path][@ref]
|
|
21
20
|
*
|
|
22
21
|
* The first two segments are always owner/repo. Everything after the second
|
|
23
|
-
* slash up to an optional @ref is the path within the repository.
|
|
24
|
-
*
|
|
22
|
+
* slash up to an optional @ref is the path within the repository. When no
|
|
23
|
+
* path is provided, the repository root is used as the template directory.
|
|
24
|
+
* This is unambiguous because GitHub owner and repo names cannot contain
|
|
25
|
+
* slashes.
|
|
25
26
|
*/
|
|
26
27
|
export declare const parseTemplateRef: (raw: string) => TemplateRef | null;
|
|
27
28
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/src/template.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/src/template.ts"],"names":[],"mappings":"AAgBA,OAAO,sBAAsB,CAAC;AAO9B,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAM1C,wCAAwC;AACxC,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;CACzB;AAED,iDAAiD;AACjD,MAAM,MAAM,mBAAmB,GAAG,MAAM,CACtC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CACzC,CAAC;AAyBF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,KAAG,WAAW,GAAG,IAyB5D,CAAC;AAMF;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,GACxB,KAAK,WAAW,KACf,OAAO,CAAC,mBAAmB,CAqG7B,CAAC"}
|
package/esm/src/template.js
CHANGED
|
@@ -6,27 +6,31 @@
|
|
|
6
6
|
// template. Templates are expected to contain at least a fly.toml and
|
|
7
7
|
// typically a Dockerfile.
|
|
8
8
|
//
|
|
9
|
-
// Reference format: owner/repo/path[@ref]
|
|
9
|
+
// Reference format: owner/repo[/path][@ref]
|
|
10
10
|
//
|
|
11
|
-
// ToxicPine/ambit-
|
|
11
|
+
// ToxicPine/ambit-openclaw → repo root, default branch
|
|
12
|
+
// ToxicPine/ambit-templates/cdp → subdirectory, default branch
|
|
12
13
|
// ToxicPine/ambit-templates/cdp@v1.0 → tagged release
|
|
13
14
|
// ToxicPine/ambit-templates/cdp@main → explicit branch
|
|
14
15
|
//
|
|
15
16
|
// =============================================================================
|
|
17
|
+
import "../_dnt.polyfills.js";
|
|
16
18
|
import * as dntShim from "../_dnt.shims.js";
|
|
17
19
|
import { join } from "../deps/jsr.io/@std/path/1.1.4/mod.js";
|
|
18
20
|
import { runCommand } from "../lib/command.js";
|
|
21
|
+
import { Result } from "../lib/result.js";
|
|
19
22
|
// =============================================================================
|
|
20
23
|
// Internal Helpers
|
|
21
24
|
// =============================================================================
|
|
22
25
|
/** Shorthand for returning a typed fetch error. */
|
|
23
|
-
const fail = (
|
|
24
|
-
ok: false,
|
|
25
|
-
kind,
|
|
26
|
-
message,
|
|
27
|
-
});
|
|
26
|
+
const fail = (message) => Result.err(message);
|
|
28
27
|
/** Format a template reference for display. */
|
|
29
|
-
const formatRef = (ref) =>
|
|
28
|
+
const formatRef = (ref) => {
|
|
29
|
+
const base = ref.path === "."
|
|
30
|
+
? `${ref.owner}/${ref.repo}`
|
|
31
|
+
: `${ref.owner}/${ref.repo}/${ref.path}`;
|
|
32
|
+
return base + (ref.ref ? `@${ref.ref}` : "");
|
|
33
|
+
};
|
|
30
34
|
/** Format owner/repo with optional ref for display. */
|
|
31
35
|
const formatRepo = (ref) => `${ref.owner}/${ref.repo}` + (ref.ref ? `@${ref.ref}` : "");
|
|
32
36
|
// =============================================================================
|
|
@@ -36,11 +40,13 @@ const formatRepo = (ref) => `${ref.owner}/${ref.repo}` + (ref.ref ? `@${ref.ref}
|
|
|
36
40
|
* Parse a template reference string into its components.
|
|
37
41
|
* Returns null if the format is invalid.
|
|
38
42
|
*
|
|
39
|
-
* Format: owner/repo/path[@ref]
|
|
43
|
+
* Format: owner/repo[/path][@ref]
|
|
40
44
|
*
|
|
41
45
|
* The first two segments are always owner/repo. Everything after the second
|
|
42
|
-
* slash up to an optional @ref is the path within the repository.
|
|
43
|
-
*
|
|
46
|
+
* slash up to an optional @ref is the path within the repository. When no
|
|
47
|
+
* path is provided, the repository root is used as the template directory.
|
|
48
|
+
* This is unambiguous because GitHub owner and repo names cannot contain
|
|
49
|
+
* slashes.
|
|
44
50
|
*/
|
|
45
51
|
export const parseTemplateRef = (raw) => {
|
|
46
52
|
// Split off @ref suffix
|
|
@@ -56,13 +62,13 @@ export const parseTemplateRef = (raw) => {
|
|
|
56
62
|
else {
|
|
57
63
|
body = raw;
|
|
58
64
|
}
|
|
59
|
-
// Need at least owner/repo
|
|
65
|
+
// Need at least owner/repo
|
|
60
66
|
const parts = body.split("/");
|
|
61
|
-
if (parts.length <
|
|
67
|
+
if (parts.length < 2)
|
|
62
68
|
return null;
|
|
63
69
|
const owner = parts[0];
|
|
64
70
|
const repo = parts[1];
|
|
65
|
-
const path = parts.slice(2).join("/");
|
|
71
|
+
const path = parts.length > 2 ? parts.slice(2).join("/") : ".";
|
|
66
72
|
if (!owner || !repo || !path)
|
|
67
73
|
return null;
|
|
68
74
|
return { owner, repo, path, ref };
|
|
@@ -88,9 +94,9 @@ export const fetchTemplate = async (ref) => {
|
|
|
88
94
|
}
|
|
89
95
|
catch { /* ignore */ }
|
|
90
96
|
};
|
|
91
|
-
const cleanFail = (
|
|
97
|
+
const cleanFail = (message) => {
|
|
92
98
|
cleanup();
|
|
93
|
-
return fail(
|
|
99
|
+
return fail(message);
|
|
94
100
|
};
|
|
95
101
|
try {
|
|
96
102
|
const url = ref.ref
|
|
@@ -105,13 +111,13 @@ export const fetchTemplate = async (ref) => {
|
|
|
105
111
|
if (!response.ok) {
|
|
106
112
|
const repo = formatRepo(ref);
|
|
107
113
|
if (response.status === 404) {
|
|
108
|
-
return cleanFail(
|
|
114
|
+
return cleanFail(`Template Repository Not Found: ${repo}. ` +
|
|
109
115
|
"Check that the repository exists and is public.");
|
|
110
116
|
}
|
|
111
117
|
if (response.status === 403) {
|
|
112
|
-
return cleanFail("
|
|
118
|
+
return cleanFail("GitHub API Rate Limit Exceeded. Try again later.");
|
|
113
119
|
}
|
|
114
|
-
return cleanFail(
|
|
120
|
+
return cleanFail(`GitHub API Returned HTTP ${response.status} for ${repo}`);
|
|
115
121
|
}
|
|
116
122
|
// Write tarball to disk
|
|
117
123
|
const tarballPath = join(tempDir, "template.tar.gz");
|
|
@@ -127,31 +133,31 @@ export const fetchTemplate = async (ref) => {
|
|
|
127
133
|
"-C",
|
|
128
134
|
extractDir,
|
|
129
135
|
]);
|
|
130
|
-
if (!extractResult.
|
|
131
|
-
return cleanFail("
|
|
136
|
+
if (!extractResult.ok) {
|
|
137
|
+
return cleanFail("Failed to Extract Template Archive");
|
|
132
138
|
}
|
|
133
139
|
// GitHub tarballs have a single top-level dir (owner-repo-commitish/)
|
|
134
140
|
const entries = [...dntShim.Deno.readDirSync(extractDir)];
|
|
135
141
|
const topLevel = entries.find((e) => e.isDirectory);
|
|
136
142
|
if (!topLevel) {
|
|
137
|
-
return cleanFail("
|
|
143
|
+
return cleanFail("Template Archive Has No Top-Level Directory");
|
|
138
144
|
}
|
|
139
145
|
// Locate the template subdirectory
|
|
140
146
|
const templateDir = join(extractDir, topLevel.name, ref.path);
|
|
141
147
|
try {
|
|
142
148
|
const stat = dntShim.Deno.statSync(templateDir);
|
|
143
149
|
if (!stat.isDirectory) {
|
|
144
|
-
return cleanFail(
|
|
150
|
+
return cleanFail(`Template Path '${ref.path}' Is Not a Directory in ${formatRepo(ref)}`);
|
|
145
151
|
}
|
|
146
152
|
}
|
|
147
153
|
catch {
|
|
148
|
-
return cleanFail(
|
|
154
|
+
return cleanFail(`Template Path '${ref.path}' Not Found in ${formatRepo(ref)}`);
|
|
149
155
|
}
|
|
150
|
-
return {
|
|
156
|
+
return Result.ok({ tempDir, templateDir });
|
|
151
157
|
}
|
|
152
158
|
catch (e) {
|
|
153
159
|
if (e instanceof TypeError) {
|
|
154
|
-
return cleanFail("
|
|
160
|
+
return cleanFail("Network Error: Could Not Reach GitHub");
|
|
155
161
|
}
|
|
156
162
|
cleanup();
|
|
157
163
|
throw e;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cardelli/ambit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Deploy apps to the cloud that only you and your AI agents can reach",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"module": "./esm/src/providers/fly.js",
|
|
@@ -29,6 +29,9 @@
|
|
|
29
29
|
"./lib/output": {
|
|
30
30
|
"import": "./esm/lib/output.js"
|
|
31
31
|
},
|
|
32
|
+
"./lib/result": {
|
|
33
|
+
"import": "./esm/lib/result.js"
|
|
34
|
+
},
|
|
32
35
|
"./lib/paths": {
|
|
33
36
|
"import": "./esm/lib/paths.js"
|
|
34
37
|
},
|
|
@@ -43,6 +46,9 @@
|
|
|
43
46
|
},
|
|
44
47
|
"./src/resolve": {
|
|
45
48
|
"import": "./esm/src/resolve.js"
|
|
49
|
+
},
|
|
50
|
+
"./src/template": {
|
|
51
|
+
"import": "./esm/src/template.js"
|
|
46
52
|
}
|
|
47
53
|
},
|
|
48
54
|
"scripts": {},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_data.d.ts","sourceRoot":"","sources":["../../../../../../src/deps/jsr.io/@std/cli/1.0.27/_data.js"],"names":[],"mappings":""}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Filters the given array, removing all elements that do not match the given predicate
|
|
3
|
-
* **in place. This means `array` will be modified!**.
|
|
4
|
-
*/
|
|
5
|
-
export declare function filterInPlace<T>(array: Array<T>, predicate: (el: T) => boolean): Array<T>;
|
|
6
|
-
//# sourceMappingURL=_utils.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_utils.d.ts","sourceRoot":"","sources":["../../../../../../src/deps/jsr.io/@std/collections/1.1.3/_utils.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAC7B,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EACf,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,OAAO,GAC5B,KAAK,CAAC,CAAC,CAAC,CAeV"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
// Copyright 2018-2025 the Deno authors. MIT license.
|
|
2
|
-
// This module is browser compatible.
|
|
3
|
-
/**
|
|
4
|
-
* Filters the given array, removing all elements that do not match the given predicate
|
|
5
|
-
* **in place. This means `array` will be modified!**.
|
|
6
|
-
*/
|
|
7
|
-
export function filterInPlace(array, predicate) {
|
|
8
|
-
let outputIndex = 0;
|
|
9
|
-
for (const cur of array) {
|
|
10
|
-
if (!predicate(cur)) {
|
|
11
|
-
continue;
|
|
12
|
-
}
|
|
13
|
-
array[outputIndex] = cur;
|
|
14
|
-
outputIndex += 1;
|
|
15
|
-
}
|
|
16
|
-
array.splice(outputIndex);
|
|
17
|
-
return array;
|
|
18
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|