@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.
Files changed (64) hide show
  1. package/esm/deno.d.ts +1 -0
  2. package/esm/deno.js +3 -2
  3. package/esm/deps/jsr.io/@std/cli/1.0.28/_data.d.ts.map +1 -0
  4. package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/_run_length.d.ts.map +1 -1
  5. package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/mod.d.ts.map +1 -1
  6. package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/parse_args.d.ts.map +1 -1
  7. package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/parse_args.js +17 -3
  8. package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/prompt_secret.d.ts.map +1 -1
  9. package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/unicode_width.d.ts.map +1 -1
  10. package/esm/deps/jsr.io/@std/collections/{1.1.3 → 1.1.6}/deep_merge.d.ts +2 -2
  11. package/esm/deps/jsr.io/@std/collections/{1.1.3 → 1.1.6}/deep_merge.d.ts.map +1 -1
  12. package/esm/deps/jsr.io/@std/collections/{1.1.3 → 1.1.6}/deep_merge.js +30 -20
  13. package/esm/deps/jsr.io/@std/toml/1.0.11/_parser.js +1 -1
  14. package/esm/deps/jsr.io/@zod/zod/4.3.6/src/v4/core/json-schema-generator.d.ts +1 -1
  15. package/esm/lib/cli.d.ts +0 -1
  16. package/esm/lib/cli.d.ts.map +1 -1
  17. package/esm/lib/cli.js +41 -26
  18. package/esm/lib/command.d.ts +23 -48
  19. package/esm/lib/command.d.ts.map +1 -1
  20. package/esm/lib/command.js +60 -89
  21. package/esm/lib/output.d.ts +1 -1
  22. package/esm/lib/output.d.ts.map +1 -1
  23. package/esm/lib/output.js +5 -9
  24. package/esm/lib/result.d.ts +19 -7
  25. package/esm/lib/result.d.ts.map +1 -1
  26. package/esm/lib/result.js +47 -1
  27. package/esm/main.d.ts.map +1 -1
  28. package/esm/main.js +3 -2
  29. package/esm/src/cli/commands/create.js +111 -97
  30. package/esm/src/cli/commands/deploy.js +61 -35
  31. package/esm/src/cli/commands/destroy.js +224 -29
  32. package/esm/src/cli/commands/doctor.js +2 -2
  33. package/esm/src/cli/commands/list.js +1 -1
  34. package/esm/src/cli/commands/status.js +1 -1
  35. package/esm/src/cli/mod.d.ts.map +1 -1
  36. package/esm/src/cli/mod.js +4 -3
  37. package/esm/src/discovery.d.ts +13 -0
  38. package/esm/src/discovery.d.ts.map +1 -1
  39. package/esm/src/discovery.js +42 -0
  40. package/esm/src/docker/router/start.sh +18 -72
  41. package/esm/src/providers/fly.d.ts +6 -0
  42. package/esm/src/providers/fly.d.ts.map +1 -1
  43. package/esm/src/providers/fly.js +77 -81
  44. package/esm/src/providers/tailscale.d.ts.map +1 -1
  45. package/esm/src/providers/tailscale.js +5 -11
  46. package/esm/src/template.d.ts +8 -7
  47. package/esm/src/template.d.ts.map +1 -1
  48. package/esm/src/template.js +32 -26
  49. package/package.json +7 -1
  50. package/esm/deps/jsr.io/@std/cli/1.0.27/_data.d.ts.map +0 -1
  51. package/esm/deps/jsr.io/@std/collections/1.1.3/_utils.d.ts +0 -6
  52. package/esm/deps/jsr.io/@std/collections/1.1.3/_utils.d.ts.map +0 -1
  53. package/esm/deps/jsr.io/@std/collections/1.1.3/_utils.js +0 -18
  54. /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/_data.d.ts +0 -0
  55. /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/_data.js +0 -0
  56. /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/_run_length.d.ts +0 -0
  57. /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/_run_length.js +0 -0
  58. /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/mod.d.ts +0 -0
  59. /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/mod.js +0 -0
  60. /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/parse_args.d.ts +0 -0
  61. /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/prompt_secret.d.ts +0 -0
  62. /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/prompt_secret.js +0 -0
  63. /package/esm/deps/jsr.io/@std/cli/{1.0.27 → 1.0.28}/unicode_width.d.ts +0 -0
  64. /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":"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"}
1
+ {"version":3,"file":"fly.d.ts","sourceRoot":"","sources":["../../../src/src/providers/fly.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,8 @@
3
3
  // =============================================================================
4
4
  import "../../_dnt.polyfills.js";
5
5
  import * as dntShim from "../../_dnt.shims.js";
6
- import { runCommand, runCommandJson, runInteractive, runQuiet, } from "../../lib/command.js";
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.success) {
68
- try {
69
- const parsed = FlyAuthSchema.safeParse(JSON.parse(result.stdout));
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 runInteractive(["fly", "auth", "login"]);
82
- if (!loginResult.success) {
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.success) {
87
+ if (!checkResult.ok) {
87
88
  return die("Fly.io Authentication Verification Failed");
88
89
  }
89
- const parsed = FlyAuthSchema.safeParse(JSON.parse(checkResult.stdout));
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 runCommandJson(["fly", "orgs", "list", "--json"]);
97
- if (!result.success || !result.data) {
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.data);
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
- if (!result.success) {
113
- return [];
114
- }
115
- try {
116
- const parsed = FlyAppsListSchema.safeParse(JSON.parse(result.stdout));
117
- return parsed.success ? parsed.data : [];
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 args = ["fly", "apps", "create", name, "--org", org, "--json"];
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.success) {
130
- return die(`Failed to Create App '${name}'`);
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.success) {
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
- if (!result.success)
148
- return false;
149
- try {
150
- const parsed = FlyStatusSchema.safeParse(JSON.parse(result.stdout));
151
- return parsed.success && !!parsed.data.ID;
152
- }
153
- catch {
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 runCommandJson(["fly", "machines", "list", "-a", app, "--json"]);
159
- if (!result.success || !result.data) {
160
- return [];
161
- }
162
- const parsed = FlyMachinesListSchema.safeParse(result.data);
163
- return parsed.success ? parsed.data : [];
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.success) {
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.success) {
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.success) {
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.success) {
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
- if (!result.success)
271
- return [];
272
- try {
273
- const parsed = FlyIpListSchema.safeParse(JSON.parse(result.stdout));
274
- return parsed.success ? parsed.data : [];
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.success) {
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.success) {
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
- if (!result.success)
311
- return null;
312
- try {
313
- return JSON.parse(result.stdout);
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", app, "--yes", "--no-public-ips");
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.success) {
337
- throw new FlyDeployError(app, result.stderr);
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
- if (!result.success)
350
- return [];
351
- try {
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
- // Router App Naming
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,CAY7D,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,QAAa,OAAO,CAAC,OAAO,CAG1D,CAAC"}
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
- if (!result.success) {
178
- return false;
179
- }
180
- try {
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.success;
188
+ return result.ok;
195
189
  };
@@ -1,6 +1,5 @@
1
- import type { Result } from "../lib/result.js";
2
- /** Kinds of errors that can occur when fetching a template from GitHub. */
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
- }, TemplateErrorKind>;
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. This is
24
- * unambiguous because GitHub owner and repo names cannot contain slashes.
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":"AAoBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAM/C,2EAA2E;AAC3E,MAAM,MAAM,iBAAiB,GACzB,UAAU,GACV,aAAa,GACb,WAAW,GACX,kBAAkB,GAClB,cAAc,GACd,kBAAkB,GAClB,cAAc,GACd,cAAc,CAAC;AAMnB,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,EACxC,iBAAiB,CAClB,CAAC;AA4BF;;;;;;;;;GASG;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,CAsH7B,CAAC"}
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"}
@@ -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-templates/cdp → default branch
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 = (kind, message) => ({
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) => `${ref.owner}/${ref.repo}/${ref.path}` + (ref.ref ? `@${ref.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. This is
43
- * unambiguous because GitHub owner and repo names cannot contain slashes.
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/path
65
+ // Need at least owner/repo
60
66
  const parts = body.split("/");
61
- if (parts.length < 3)
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 = (kind, message) => {
97
+ const cleanFail = (message) => {
92
98
  cleanup();
93
- return fail(kind, message);
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("NotFound", `Template Repository Not Found: ${repo}. ` +
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("RateLimited", "GitHub API Rate Limit Exceeded. Try again later.");
118
+ return cleanFail("GitHub API Rate Limit Exceeded. Try again later.");
113
119
  }
114
- return cleanFail("HttpError", `GitHub API Returned HTTP ${response.status} for ${repo}`);
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.success) {
131
- return cleanFail("ExtractionFailed", "Failed to Extract Template Archive");
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("EmptyArchive", "Template Archive Has No Top-Level Directory");
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("PathNotDirectory", `Template Path '${ref.path}' Is Not a Directory in ${formatRepo(ref)}`);
150
+ return cleanFail(`Template Path '${ref.path}' Is Not a Directory in ${formatRepo(ref)}`);
145
151
  }
146
152
  }
147
153
  catch {
148
- return cleanFail("PathNotFound", `Template Path '${ref.path}' Not Found in ${formatRepo(ref)}`);
154
+ return cleanFail(`Template Path '${ref.path}' Not Found in ${formatRepo(ref)}`);
149
155
  }
150
- return { ok: true, tempDir, templateDir };
156
+ return Result.ok({ tempDir, templateDir });
151
157
  }
152
158
  catch (e) {
153
159
  if (e instanceof TypeError) {
154
- return cleanFail("NetworkError", "Network Error: Could Not Reach GitHub");
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",
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
- }