@cardelli/ambit 0.3.4 → 0.3.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/README.md +55 -0
- package/esm/cli/commands/create/index.js +1 -1
- package/esm/cli/commands/create/machine.d.ts +1 -1
- package/esm/cli/commands/create/machine.d.ts.map +1 -1
- package/esm/cli/commands/deploy/machine.d.ts +1 -1
- package/esm/cli/commands/deploy/machine.d.ts.map +1 -1
- package/esm/cli/commands/deploy/modes.d.ts +1 -1
- package/esm/cli/commands/deploy/modes.d.ts.map +1 -1
- package/esm/cli/commands/list/apps.d.ts.map +1 -1
- package/esm/cli/commands/list/apps.js +1 -1
- package/esm/cli/commands/logs.d.ts +2 -0
- package/esm/cli/commands/logs.d.ts.map +1 -0
- package/esm/cli/commands/logs.js +142 -0
- package/esm/cli/commands/secrets.d.ts +2 -0
- package/esm/cli/commands/secrets.d.ts.map +1 -0
- package/esm/cli/commands/secrets.js +302 -0
- package/esm/cli/mod.d.ts.map +1 -1
- package/esm/cli/mod.js +2 -0
- package/esm/deno.js +1 -1
- package/esm/lib/command.d.ts +9 -0
- package/esm/lib/command.d.ts.map +1 -1
- package/esm/lib/command.js +32 -0
- package/esm/lib/table.d.ts +23 -0
- package/esm/lib/table.d.ts.map +1 -0
- package/esm/lib/table.js +64 -0
- package/esm/main.d.ts +2 -0
- package/esm/main.d.ts.map +1 -1
- package/esm/main.js +4 -0
- package/esm/providers/fly.d.ts +8 -0
- package/esm/providers/fly.d.ts.map +1 -1
- package/esm/providers/fly.js +28 -0
- package/esm/util/fly-transforms.d.ts +1 -2
- package/esm/util/fly-transforms.d.ts.map +1 -1
- package/esm/util/resolve.d.ts.map +1 -1
- package/esm/util/resolve.js +3 -1
- package/esm/util/template.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -211,6 +211,61 @@ Shows detailed status for a specific app: machines, Flycast IPs, and the backing
|
|
|
211
211
|
| `--org <org>` | Fly.io organization slug |
|
|
212
212
|
| `--json` | Machine-readable JSON output |
|
|
213
213
|
|
|
214
|
+
### `ambit secrets list|set|unset|deploy <app>.<network>`
|
|
215
|
+
|
|
216
|
+
Manage secrets for workload apps. Secrets are encrypted environment variables provided to the app at runtime.
|
|
217
|
+
|
|
218
|
+
#### `ambit secrets list <app>.<network>`
|
|
219
|
+
|
|
220
|
+
Lists secret names and digests (not values) for an app.
|
|
221
|
+
|
|
222
|
+
#### `ambit secrets set <app>.<network> KEY=VALUE ...`
|
|
223
|
+
|
|
224
|
+
Sets one or more secrets. Positional `KEY=VALUE` pairs and `--env` can be combined — positional args take precedence.
|
|
225
|
+
|
|
226
|
+
| Flag | Description |
|
|
227
|
+
| ----------------- | -------------------------------------------- |
|
|
228
|
+
| `--env <file>` | Load secrets from an env file |
|
|
229
|
+
| `--stage` | Stage secrets without deploying |
|
|
230
|
+
| `--org <org>` | Fly.io organization slug |
|
|
231
|
+
| `--json` | Machine-readable JSON output |
|
|
232
|
+
|
|
233
|
+
#### `ambit secrets unset <app>.<network> KEY ...`
|
|
234
|
+
|
|
235
|
+
Removes one or more secrets by name.
|
|
236
|
+
|
|
237
|
+
| Flag | Description |
|
|
238
|
+
| ----------------- | -------------------------------------------- |
|
|
239
|
+
| `--stage` | Stage removal without deploying |
|
|
240
|
+
| `--org <org>` | Fly.io organization slug |
|
|
241
|
+
| `--json` | Machine-readable JSON output |
|
|
242
|
+
|
|
243
|
+
#### `ambit secrets deploy <app>.<network>`
|
|
244
|
+
|
|
245
|
+
Deploys staged secrets (from `set --stage` or `unset --stage`).
|
|
246
|
+
|
|
247
|
+
| Flag | Description |
|
|
248
|
+
| ----------------- | -------------------------------------------- |
|
|
249
|
+
| `--org <org>` | Fly.io organization slug |
|
|
250
|
+
| `--json` | Machine-readable JSON output |
|
|
251
|
+
|
|
252
|
+
### `ambit logs <app>.<network>`
|
|
253
|
+
|
|
254
|
+
Streams logs for a workload app. By default, logs are streamed continuously. Use `--no-tail` to fetch only buffered logs. Pipe through `less` for scrollable output:
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
npx @cardelli/ambit logs my-app.lab | less +F -R # stream with scroll (Ctrl+C to scroll, F to resume)
|
|
258
|
+
npx @cardelli/ambit logs my-app.lab --no-tail | less -R # scroll buffered logs
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
| Flag | Description |
|
|
262
|
+
| -------------------- | -------------------------------------------- |
|
|
263
|
+
| `-r`, `--region <r>` | Filter by region |
|
|
264
|
+
| `--machine <id>` | Filter by machine ID |
|
|
265
|
+
| `-n`, `--no-tail` | Only fetch buffered logs (no streaming) |
|
|
266
|
+
| `--org <org>` | Fly.io organization slug |
|
|
267
|
+
| `--json` | JSON output |
|
|
268
|
+
|
|
214
269
|
### `ambit destroy network <name>`
|
|
215
270
|
|
|
216
271
|
Tears down a network: destroys the router, cleans up DNS, removes the Tailscale device, and automatically removes the router's tag from your Tailscale ACL policy (tagOwners and autoApprovers). If there are workload apps still on the network, ambit warns you before proceeding.
|
|
@@ -169,7 +169,7 @@ const stageDeploy = async (out, fly, tailscale, opts) => {
|
|
|
169
169
|
// =============================================================================
|
|
170
170
|
// Stage 4: Summary
|
|
171
171
|
// =============================================================================
|
|
172
|
-
const stageSummary = async (out,
|
|
172
|
+
const stageSummary = async (out, _fly, tailscale, ctx, opts) => {
|
|
173
173
|
const policy = await tailscale.acl.getPolicy();
|
|
174
174
|
const hasAutoApprover = isAutoApproverConfigured(policy, opts.tag);
|
|
175
175
|
out.done({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Output } from "../../../lib/output.js";
|
|
2
2
|
import { Result } from "../../../lib/result.js";
|
|
3
3
|
import { type FlyProvider } from "../../../providers/fly.js";
|
|
4
4
|
import type { TailscaleProvider } from "../../../providers/tailscale.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"machine.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/create/machine.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"machine.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/create/machine.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAQhD,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAW7E,OAAO,KAAK,EAAgB,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACvF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAOrE,MAAM,MAAM,WAAW,GACnB,YAAY,GACZ,eAAe,GACf,gBAAgB,GAChB,eAAe,GACf,eAAe,GACf,UAAU,CAAC;AAMf,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IACxD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,WAAW,CAAC;IACjB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,GAAG,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAcD,eAAO,MAAM,aAAa,GACxB,KAAK,MAAM,CAAC,YAAY,CAAC,EACzB,YAAY,WAAW,SAMxB,CAAC;AAMF,eAAO,MAAM,aAAa,GACxB,KAAK,SAAS,KACb,OAAO,CAAC,WAAW,CA4BrB,CAAC;AAMF,eAAO,MAAM,gBAAgB,GAC3B,OAAO,WAAW,EAClB,KAAK,SAAS,KACb,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CA+K7B,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Output } from "../../../lib/output.js";
|
|
2
2
|
import { Result } from "../../../lib/result.js";
|
|
3
3
|
import { type FlyProvider, type SafeDeployOptions } from "../../../providers/fly.js";
|
|
4
4
|
import type { DeployConfig } from "./modes.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"machine.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/deploy/machine.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"machine.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/deploy/machine.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACvB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAM/C,MAAM,MAAM,WAAW,GACnB,YAAY,GACZ,WAAW,GACX,QAAQ,GACR,OAAO,GACP,UAAU,CAAC;AAMf,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE;QACL,mBAAmB,EAAE,MAAM,CAAC;QAC5B,aAAa,EAAE,MAAM,CAAC;QACtB,mBAAmB,EAAE,KAAK,CAAC;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACjE,QAAQ,EAAE,MAAM,EAAE,CAAC;KACpB,CAAC;IACF,SAAS,EAAE;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;KACpB,CAAC;CACH,CAAC;AAEF,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,WAAW,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,OAAO,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,YAAY,CAAC;IAC3B,aAAa,EAAE,iBAAiB,CAAC;IACjC,KAAK,CAAC,EAAE;QACN,mBAAmB,EAAE,MAAM,CAAC;QAC5B,aAAa,EAAE,MAAM,CAAC;QACtB,mBAAmB,EAAE,KAAK,CAAC;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACjE,QAAQ,EAAE,MAAM,EAAE,CAAC;KACpB,CAAC;CACH;AAaD,eAAO,MAAM,mBAAmB,GAC9B,KAAK,MAAM,CAAC,YAAY,CAAC,EACzB,YAAY,WAAW,SAMxB,CAAC;AAMF,eAAO,MAAM,aAAa,GACxB,KAAK,SAAS,KACb,OAAO,CAAC,WAAW,CAMrB,CAAC;AAMF,eAAO,MAAM,gBAAgB,GAC3B,OAAO,WAAW,EAClB,KAAK,SAAS,KACb,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CA6G7B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modes.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/deploy/modes.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"modes.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/deploy/modes.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAQ3D,8EAA8E;AAC9E,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAoCD,sDAAsD;AACtD,eAAO,MAAM,gBAAgB,GAC3B,OAAO,MAAM,EACb,aAAa,MAAM,EACnB,KAAK,UAAU,CAAC,OAAO,YAAY,CAAC,KACnC,YAAY,GAAG,IAmBjB,CAAC;AAMF,uEAAuE;AACvE,eAAO,MAAM,iBAAiB,GAC5B,gBAAgB,MAAM,GAAG,SAAS,EAClC,KAAK,UAAU,CAAC,OAAO,YAAY,CAAC,KACnC,OAAO,CAAC,YAAY,GAAG,IAAI,CAqC7B,CAAC;AAMF,4DAA4D;AAC5D,eAAO,MAAM,mBAAmB,GAC9B,aAAa,MAAM,EACnB,KAAK,UAAU,CAAC,OAAO,YAAY,CAAC,KACnC,OAAO,CAAC,YAAY,GAAG,IAAI,CAyE7B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/list/apps.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/list/apps.ts"],"names":[],"mappings":"AA6BA,eAAO,MAAM,QAAQ,GAAU,MAAM,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CAqE3D,CAAC"}
|
|
@@ -6,7 +6,7 @@ import { Table } from "../../../deps/jsr.io/@cliffy/table/1.0.0/mod.js";
|
|
|
6
6
|
import { bold } from "../../../lib/cli.js";
|
|
7
7
|
import { checkArgs } from "../../../lib/args.js";
|
|
8
8
|
import { createOutput } from "../../../lib/output.js";
|
|
9
|
-
import { findRouterApp, listWorkloadAppsOnNetwork
|
|
9
|
+
import { findRouterApp, listWorkloadAppsOnNetwork } from "../../../util/discovery.js";
|
|
10
10
|
import { initSession } from "../../../util/session.js";
|
|
11
11
|
// =============================================================================
|
|
12
12
|
// List Apps Command
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/logs.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Logs Command - Stream Logs for Workload Apps
|
|
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 { streamCommand } from "../../lib/command.js";
|
|
9
|
+
import { registerCommand } from "../mod.js";
|
|
10
|
+
import { findWorkloadApp } from "../../util/discovery.js";
|
|
11
|
+
import { initSession } from "../../util/session.js";
|
|
12
|
+
import { StreamTable } from "../../lib/table.js";
|
|
13
|
+
// =============================================================================
|
|
14
|
+
// Log Table
|
|
15
|
+
// =============================================================================
|
|
16
|
+
const logTable = new StreamTable([
|
|
17
|
+
{ name: "Timestamp", width: 19 },
|
|
18
|
+
{ name: "Region", width: 6 },
|
|
19
|
+
{ name: "Level", width: 5 },
|
|
20
|
+
{ name: "Message", width: 0 },
|
|
21
|
+
]);
|
|
22
|
+
const formatTimestamp = (ts) => {
|
|
23
|
+
return ts.replace("T", " ").replace(/\.\d+Z$/, "");
|
|
24
|
+
};
|
|
25
|
+
// =============================================================================
|
|
26
|
+
// Logs Command
|
|
27
|
+
// =============================================================================
|
|
28
|
+
const logs = async (argv) => {
|
|
29
|
+
const opts = {
|
|
30
|
+
string: ["org", "region", "machine"],
|
|
31
|
+
boolean: ["help", "json", "no-tail"],
|
|
32
|
+
alias: { r: "region", n: "no-tail" },
|
|
33
|
+
};
|
|
34
|
+
const args = parseArgs(argv, opts);
|
|
35
|
+
checkArgs(args, opts, "ambit logs", 1);
|
|
36
|
+
if (args.help) {
|
|
37
|
+
console.log(`
|
|
38
|
+
${bold("ambit logs")} - Stream Logs for a Workload App
|
|
39
|
+
|
|
40
|
+
${bold("USAGE")}
|
|
41
|
+
ambit logs <app>.<network> [options]
|
|
42
|
+
|
|
43
|
+
${bold("OPTIONS")}
|
|
44
|
+
--org <org> Fly.io organization slug
|
|
45
|
+
-r, --region <r> Filter by region
|
|
46
|
+
--machine <id> Filter by machine ID
|
|
47
|
+
-n, --no-tail Only fetch buffered logs (no streaming)
|
|
48
|
+
--json JSON output
|
|
49
|
+
|
|
50
|
+
${bold("EXAMPLES")}
|
|
51
|
+
ambit logs my-app.browsers
|
|
52
|
+
ambit logs my-app.browsers | less +F -R
|
|
53
|
+
ambit logs my-app.browsers --no-tail | less -R
|
|
54
|
+
ambit logs my-app.browsers --region iad --json
|
|
55
|
+
`);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const out = createOutput(args.json);
|
|
59
|
+
const appArg = args._[0];
|
|
60
|
+
if (!appArg || typeof appArg !== "string") {
|
|
61
|
+
return out.die("Missing App Name. Usage: ambit logs <app>.<network>");
|
|
62
|
+
}
|
|
63
|
+
if (!appArg.includes(".")) {
|
|
64
|
+
return out.die(`Missing Network. Use: ambit logs ${appArg}.<network>`);
|
|
65
|
+
}
|
|
66
|
+
const parts = appArg.split(".");
|
|
67
|
+
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
68
|
+
return out.die(`'${appArg}' Should Have Exactly One Dot, Like my-app.my-network`);
|
|
69
|
+
}
|
|
70
|
+
const app = parts[0];
|
|
71
|
+
const network = parts[1];
|
|
72
|
+
const { fly, org } = await initSession(out, {
|
|
73
|
+
json: args.json,
|
|
74
|
+
org: args.org,
|
|
75
|
+
});
|
|
76
|
+
const workload = await findWorkloadApp(fly, org, app, network);
|
|
77
|
+
if (!workload) {
|
|
78
|
+
return out.die(`App '${app}' Not Found on Network '${network}'`);
|
|
79
|
+
}
|
|
80
|
+
// Always request JSON from fly so we can parse and format
|
|
81
|
+
const flyArgs = ["fly", "logs", "-a", workload.appName, "--json"];
|
|
82
|
+
if (args["no-tail"])
|
|
83
|
+
flyArgs.push("--no-tail");
|
|
84
|
+
if (args.region)
|
|
85
|
+
flyArgs.push("--region", args.region);
|
|
86
|
+
if (args.machine)
|
|
87
|
+
flyArgs.push("--machine", args.machine);
|
|
88
|
+
const stream = streamCommand(flyArgs);
|
|
89
|
+
out.blank();
|
|
90
|
+
out.text(logTable.header());
|
|
91
|
+
out.text(logTable.separator());
|
|
92
|
+
// fly logs --json emits pretty-printed multi-line JSON objects.
|
|
93
|
+
// Accumulate lines and parse when brace depth returns to zero.
|
|
94
|
+
let buf = [];
|
|
95
|
+
let depth = 0;
|
|
96
|
+
for await (const line of stream.lines) {
|
|
97
|
+
const trimmed = line.trim();
|
|
98
|
+
if (!trimmed)
|
|
99
|
+
continue;
|
|
100
|
+
for (const ch of trimmed) {
|
|
101
|
+
if (ch === "{")
|
|
102
|
+
depth++;
|
|
103
|
+
else if (ch === "}")
|
|
104
|
+
depth--;
|
|
105
|
+
}
|
|
106
|
+
buf.push(trimmed);
|
|
107
|
+
if (depth === 0 && buf.length > 0) {
|
|
108
|
+
const block = buf.join("");
|
|
109
|
+
buf = [];
|
|
110
|
+
try {
|
|
111
|
+
const entry = JSON.parse(block);
|
|
112
|
+
if (out.isJson()) {
|
|
113
|
+
console.log(JSON.stringify(entry));
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
out.text(logTable.row([
|
|
117
|
+
formatTimestamp(entry.timestamp ?? ""),
|
|
118
|
+
entry.region ?? "",
|
|
119
|
+
entry.level ?? "",
|
|
120
|
+
entry.message ?? "",
|
|
121
|
+
]));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
out.dim(` ${block}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const result = await stream.done;
|
|
130
|
+
if (!result.ok && result.stderr) {
|
|
131
|
+
out.err(result.stderr.trim());
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
// =============================================================================
|
|
135
|
+
// Register Command
|
|
136
|
+
// =============================================================================
|
|
137
|
+
registerCommand({
|
|
138
|
+
name: "logs",
|
|
139
|
+
description: "Stream logs for a workload app",
|
|
140
|
+
usage: "ambit logs <app>.<network> [--region <r>] [--no-tail] [--json]",
|
|
141
|
+
run: logs,
|
|
142
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/secrets.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Secrets Command - Manage Secrets for Workload Apps
|
|
3
|
+
// =============================================================================
|
|
4
|
+
import * as dntShim from "../../_dnt.shims.js";
|
|
5
|
+
import { parseArgs } from "../../deps/jsr.io/@std/cli/1.0.28/mod.js";
|
|
6
|
+
import { Table } from "../../deps/jsr.io/@cliffy/table/1.0.0/mod.js";
|
|
7
|
+
import { bold } from "../../lib/cli.js";
|
|
8
|
+
import { checkArgs } from "../../lib/args.js";
|
|
9
|
+
import { createOutput } from "../../lib/output.js";
|
|
10
|
+
import { registerCommand } from "../mod.js";
|
|
11
|
+
import { findWorkloadApp } from "../../util/discovery.js";
|
|
12
|
+
import { initSession } from "../../util/session.js";
|
|
13
|
+
// =============================================================================
|
|
14
|
+
// Shared Helpers
|
|
15
|
+
// =============================================================================
|
|
16
|
+
const resolveAppTarget = (out, appArg, command) => {
|
|
17
|
+
if (!appArg || typeof appArg !== "string") {
|
|
18
|
+
return out.die(`Missing App Name. Usage: ${command} <app>.<network>`);
|
|
19
|
+
}
|
|
20
|
+
if (!appArg.includes(".")) {
|
|
21
|
+
return out.die(`Missing Network. Use: ${command} ${appArg}.<network>`);
|
|
22
|
+
}
|
|
23
|
+
const parts = appArg.split(".");
|
|
24
|
+
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
25
|
+
return out.die(`'${appArg}' Should Have Exactly One Dot, Like my-app.my-network`);
|
|
26
|
+
}
|
|
27
|
+
return { app: parts[0], network: parts[1] };
|
|
28
|
+
};
|
|
29
|
+
const resolveFlyAppName = async (out, fly, org, app, network) => {
|
|
30
|
+
const workload = await findWorkloadApp(fly, org, app, network);
|
|
31
|
+
if (!workload) {
|
|
32
|
+
return out.die(`App '${app}' Not Found on Network '${network}'`);
|
|
33
|
+
}
|
|
34
|
+
return workload.appName;
|
|
35
|
+
};
|
|
36
|
+
// =============================================================================
|
|
37
|
+
// Secrets List
|
|
38
|
+
// =============================================================================
|
|
39
|
+
const secretsList = async (argv) => {
|
|
40
|
+
const opts = { string: ["org"], boolean: ["help", "json"] };
|
|
41
|
+
const args = parseArgs(argv, opts);
|
|
42
|
+
checkArgs(args, opts, "ambit secrets list", 1);
|
|
43
|
+
if (args.help) {
|
|
44
|
+
console.log(`
|
|
45
|
+
${bold("ambit secrets list")} - List Secrets for an App
|
|
46
|
+
|
|
47
|
+
${bold("USAGE")}
|
|
48
|
+
ambit secrets list <app>.<network> [--org <org>] [--json]
|
|
49
|
+
|
|
50
|
+
${bold("OPTIONS")}
|
|
51
|
+
--org <org> Fly.io organization slug
|
|
52
|
+
--json Output as JSON
|
|
53
|
+
|
|
54
|
+
${bold("EXAMPLES")}
|
|
55
|
+
ambit secrets list my-app.browsers
|
|
56
|
+
ambit secrets list my-app.browsers --json
|
|
57
|
+
`);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const out = createOutput(args.json);
|
|
61
|
+
const { app, network } = resolveAppTarget(out, args._[0], "ambit secrets list");
|
|
62
|
+
const { fly, org } = await initSession(out, {
|
|
63
|
+
json: args.json,
|
|
64
|
+
org: args.org,
|
|
65
|
+
});
|
|
66
|
+
const flyAppName = await resolveFlyAppName(out, fly, org, app, network);
|
|
67
|
+
const secrets = await fly.secrets.list(flyAppName);
|
|
68
|
+
if (secrets.length === 0) {
|
|
69
|
+
out.blank()
|
|
70
|
+
.text(`No Secrets Found for ${app}.${network}.`)
|
|
71
|
+
.blank();
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
out.blank().header(`Secrets for ${app}.${network}`).blank();
|
|
75
|
+
const table = new Table()
|
|
76
|
+
.header(["Name", "Digest"])
|
|
77
|
+
.body(secrets.map((s) => [s.name, s.digest]))
|
|
78
|
+
.indent(2)
|
|
79
|
+
.padding(2);
|
|
80
|
+
out.text(table.toString());
|
|
81
|
+
out.blank();
|
|
82
|
+
}
|
|
83
|
+
out.done({ app, network, flyAppName, secrets });
|
|
84
|
+
out.print();
|
|
85
|
+
};
|
|
86
|
+
// =============================================================================
|
|
87
|
+
// Secrets Set
|
|
88
|
+
// =============================================================================
|
|
89
|
+
const secretsSet = async (argv) => {
|
|
90
|
+
const opts = {
|
|
91
|
+
string: ["org", "env"],
|
|
92
|
+
boolean: ["help", "json", "stage"],
|
|
93
|
+
};
|
|
94
|
+
const args = parseArgs(argv, opts);
|
|
95
|
+
checkArgs(args, opts, "ambit secrets set", Infinity);
|
|
96
|
+
if (args.help) {
|
|
97
|
+
console.log(`
|
|
98
|
+
${bold("ambit secrets set")} - Set Secrets for an App
|
|
99
|
+
|
|
100
|
+
${bold("USAGE")}
|
|
101
|
+
ambit secrets set <app>.<network> KEY=VALUE ... [--org <org>] [--stage] [--json]
|
|
102
|
+
ambit secrets set <app>.<network> --env <file> [--org <org>] [--stage] [--json]
|
|
103
|
+
|
|
104
|
+
${bold("OPTIONS")}
|
|
105
|
+
--env <file> Load secrets from an env file (KEY=VALUE per line)
|
|
106
|
+
--org <org> Fly.io organization slug
|
|
107
|
+
--stage Stage secrets without deploying
|
|
108
|
+
--json Output as JSON
|
|
109
|
+
|
|
110
|
+
${bold("EXAMPLES")}
|
|
111
|
+
ambit secrets set my-app.browsers API_KEY=abc123
|
|
112
|
+
ambit secrets set my-app.browsers KEY1=val1 KEY2=val2 --stage
|
|
113
|
+
ambit secrets set my-app.browsers --env .env
|
|
114
|
+
`);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const out = createOutput(args.json);
|
|
118
|
+
const { app, network } = resolveAppTarget(out, args._[0], "ambit secrets set");
|
|
119
|
+
const secretsObj = {};
|
|
120
|
+
// Load from env file if provided
|
|
121
|
+
if (args.env) {
|
|
122
|
+
let content;
|
|
123
|
+
try {
|
|
124
|
+
content = await dntShim.Deno.readTextFile(args.env);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return out.die(`Failed to Read Env File: ${args.env}`);
|
|
128
|
+
}
|
|
129
|
+
for (const line of content.split("\n")) {
|
|
130
|
+
const trimmed = line.trim();
|
|
131
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
132
|
+
continue;
|
|
133
|
+
const eq = trimmed.indexOf("=");
|
|
134
|
+
if (eq === -1)
|
|
135
|
+
continue;
|
|
136
|
+
secretsObj[trimmed.slice(0, eq)] = trimmed.slice(eq + 1);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// Load from positional KEY=VALUE args
|
|
140
|
+
const pairs = args._.slice(1).map(String);
|
|
141
|
+
for (const pair of pairs) {
|
|
142
|
+
const eq = pair.indexOf("=");
|
|
143
|
+
if (eq === -1) {
|
|
144
|
+
return out.die(`Invalid Format: '${pair}'. Expected KEY=VALUE`);
|
|
145
|
+
}
|
|
146
|
+
secretsObj[pair.slice(0, eq)] = pair.slice(eq + 1);
|
|
147
|
+
}
|
|
148
|
+
if (Object.keys(secretsObj).length === 0) {
|
|
149
|
+
return out.die("No Secrets Provided. Use KEY=VALUE args or --env <file>");
|
|
150
|
+
}
|
|
151
|
+
const { fly, org } = await initSession(out, {
|
|
152
|
+
json: args.json,
|
|
153
|
+
org: args.org,
|
|
154
|
+
});
|
|
155
|
+
const flyAppName = await resolveFlyAppName(out, fly, org, app, network);
|
|
156
|
+
await out.spin(args.stage ? "Staging Secrets" : "Setting Secrets", () => fly.secrets.set(flyAppName, secretsObj, { stage: args.stage }));
|
|
157
|
+
out.done({ app, network, flyAppName });
|
|
158
|
+
out.print();
|
|
159
|
+
};
|
|
160
|
+
// =============================================================================
|
|
161
|
+
// Secrets Unset
|
|
162
|
+
// =============================================================================
|
|
163
|
+
const secretsUnset = async (argv) => {
|
|
164
|
+
const opts = {
|
|
165
|
+
string: ["org"],
|
|
166
|
+
boolean: ["help", "json", "stage"],
|
|
167
|
+
};
|
|
168
|
+
const args = parseArgs(argv, opts);
|
|
169
|
+
checkArgs(args, opts, "ambit secrets unset", Infinity);
|
|
170
|
+
if (args.help) {
|
|
171
|
+
console.log(`
|
|
172
|
+
${bold("ambit secrets unset")} - Remove Secrets from an App
|
|
173
|
+
|
|
174
|
+
${bold("USAGE")}
|
|
175
|
+
ambit secrets unset <app>.<network> KEY ... [--org <org>] [--stage] [--json]
|
|
176
|
+
|
|
177
|
+
${bold("OPTIONS")}
|
|
178
|
+
--org <org> Fly.io organization slug
|
|
179
|
+
--stage Stage removal without deploying
|
|
180
|
+
--json Output as JSON
|
|
181
|
+
|
|
182
|
+
${bold("EXAMPLES")}
|
|
183
|
+
ambit secrets unset my-app.browsers API_KEY
|
|
184
|
+
ambit secrets unset my-app.browsers KEY1 KEY2 --stage
|
|
185
|
+
`);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
const out = createOutput(args.json);
|
|
189
|
+
const { app, network } = resolveAppTarget(out, args._[0], "ambit secrets unset");
|
|
190
|
+
const keys = args._.slice(1).map(String);
|
|
191
|
+
if (keys.length === 0) {
|
|
192
|
+
return out.die("No Secret Names Provided. Usage: ambit secrets unset <app>.<network> KEY ...");
|
|
193
|
+
}
|
|
194
|
+
const { fly, org } = await initSession(out, {
|
|
195
|
+
json: args.json,
|
|
196
|
+
org: args.org,
|
|
197
|
+
});
|
|
198
|
+
const flyAppName = await resolveFlyAppName(out, fly, org, app, network);
|
|
199
|
+
await out.spin(args.stage ? "Staging Secrets Removal" : "Removing Secrets", () => fly.secrets.unset(flyAppName, keys, { stage: args.stage }));
|
|
200
|
+
out.done({ app, network, flyAppName });
|
|
201
|
+
out.print();
|
|
202
|
+
};
|
|
203
|
+
// =============================================================================
|
|
204
|
+
// Secrets Deploy
|
|
205
|
+
// =============================================================================
|
|
206
|
+
const secretsDeploy = async (argv) => {
|
|
207
|
+
const opts = { string: ["org"], boolean: ["help", "json"] };
|
|
208
|
+
const args = parseArgs(argv, opts);
|
|
209
|
+
checkArgs(args, opts, "ambit secrets deploy", 1);
|
|
210
|
+
if (args.help) {
|
|
211
|
+
console.log(`
|
|
212
|
+
${bold("ambit secrets deploy")} - Deploy Staged Secrets
|
|
213
|
+
|
|
214
|
+
${bold("USAGE")}
|
|
215
|
+
ambit secrets deploy <app>.<network> [--org <org>] [--json]
|
|
216
|
+
|
|
217
|
+
${bold("OPTIONS")}
|
|
218
|
+
--org <org> Fly.io organization slug
|
|
219
|
+
--json Output as JSON
|
|
220
|
+
|
|
221
|
+
${bold("EXAMPLES")}
|
|
222
|
+
ambit secrets deploy my-app.browsers
|
|
223
|
+
`);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
const out = createOutput(args.json);
|
|
227
|
+
const { app, network } = resolveAppTarget(out, args._[0], "ambit secrets deploy");
|
|
228
|
+
const { fly, org } = await initSession(out, {
|
|
229
|
+
json: args.json,
|
|
230
|
+
org: args.org,
|
|
231
|
+
});
|
|
232
|
+
const flyAppName = await resolveFlyAppName(out, fly, org, app, network);
|
|
233
|
+
await out.spin("Deploying Secrets", () => fly.secrets.deploy(flyAppName));
|
|
234
|
+
out.done({ app, network, flyAppName });
|
|
235
|
+
out.print();
|
|
236
|
+
};
|
|
237
|
+
// =============================================================================
|
|
238
|
+
// Top-Level Help
|
|
239
|
+
// =============================================================================
|
|
240
|
+
const showSecretsHelp = () => {
|
|
241
|
+
console.log(`
|
|
242
|
+
${bold("ambit secrets")} - Manage Secrets for Workload Apps
|
|
243
|
+
|
|
244
|
+
${bold("USAGE")}
|
|
245
|
+
ambit secrets list <app>.<network> [options]
|
|
246
|
+
ambit secrets set <app>.<network> KEY=VALUE ... [options]
|
|
247
|
+
ambit secrets unset <app>.<network> KEY ... [options]
|
|
248
|
+
ambit secrets deploy <app>.<network> [options]
|
|
249
|
+
|
|
250
|
+
${bold("SUBCOMMANDS")}
|
|
251
|
+
list List secret names and digests
|
|
252
|
+
set Set one or more secrets
|
|
253
|
+
unset Remove one or more secrets
|
|
254
|
+
deploy Deploy staged secrets
|
|
255
|
+
|
|
256
|
+
${bold("OPTIONS")}
|
|
257
|
+
--org <org> Fly.io organization slug
|
|
258
|
+
--stage Stage changes without deploying (set/unset only)
|
|
259
|
+
--json Output as JSON
|
|
260
|
+
|
|
261
|
+
${bold("EXAMPLES")}
|
|
262
|
+
ambit secrets list my-app.browsers
|
|
263
|
+
ambit secrets set my-app.browsers API_KEY=abc123
|
|
264
|
+
ambit secrets unset my-app.browsers API_KEY
|
|
265
|
+
ambit secrets deploy my-app.browsers
|
|
266
|
+
|
|
267
|
+
Run 'ambit secrets <subcommand> --help' for details.
|
|
268
|
+
`);
|
|
269
|
+
};
|
|
270
|
+
// =============================================================================
|
|
271
|
+
// Dispatcher
|
|
272
|
+
// =============================================================================
|
|
273
|
+
const secrets = async (argv) => {
|
|
274
|
+
const subcommand = typeof argv[0] === "string" ? argv[0] : undefined;
|
|
275
|
+
if (subcommand === "list" || subcommand === "ls") {
|
|
276
|
+
return secretsList(argv.slice(1));
|
|
277
|
+
}
|
|
278
|
+
if (subcommand === "set")
|
|
279
|
+
return secretsSet(argv.slice(1));
|
|
280
|
+
if (subcommand === "unset")
|
|
281
|
+
return secretsUnset(argv.slice(1));
|
|
282
|
+
if (subcommand === "deploy")
|
|
283
|
+
return secretsDeploy(argv.slice(1));
|
|
284
|
+
const opts = { boolean: ["help"] };
|
|
285
|
+
const args = parseArgs(argv, opts);
|
|
286
|
+
checkArgs(args, opts, "ambit secrets", 0);
|
|
287
|
+
if (args.help) {
|
|
288
|
+
showSecretsHelp();
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
showSecretsHelp();
|
|
292
|
+
dntShim.Deno.exit(1);
|
|
293
|
+
};
|
|
294
|
+
// =============================================================================
|
|
295
|
+
// Register Command
|
|
296
|
+
// =============================================================================
|
|
297
|
+
registerCommand({
|
|
298
|
+
name: "secrets",
|
|
299
|
+
description: "Manage secrets for workload apps",
|
|
300
|
+
usage: "ambit secrets list|set|unset|deploy <app>.<network> [options]",
|
|
301
|
+
run: secrets,
|
|
302
|
+
});
|
package/esm/cli/mod.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/cli/mod.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAQD,eAAO,MAAM,eAAe,GAAI,SAAS,OAAO,KAAG,IAElD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,KAAG,OAAO,GAAG,SAEnD,CAAC;AAEF,eAAO,MAAM,cAAc,QAAO,OAAO,EAExC,CAAC;AAQF,eAAO,MAAM,QAAQ,QAAO,
|
|
1
|
+
{"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../src/cli/mod.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AAQD,eAAO,MAAM,eAAe,GAAI,SAAS,OAAO,KAAG,IAElD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,MAAM,MAAM,KAAG,OAAO,GAAG,SAEnD,CAAC;AAEF,eAAO,MAAM,cAAc,QAAO,OAAO,EAExC,CAAC;AAQF,eAAO,MAAM,QAAQ,QAAO,IAiC3B,CAAC;AAEF,eAAO,MAAM,WAAW,QAAO,IAE9B,CAAC;AAMF,eAAO,MAAM,MAAM,GAAU,MAAM,MAAM,EAAE,KAAG,OAAO,CAAC,IAAI,CAuCzD,CAAC"}
|
package/esm/cli/mod.js
CHANGED
|
@@ -35,6 +35,8 @@ ${bold("COMMANDS")}
|
|
|
35
35
|
share Grant a Tailscale group access to a network via ACL rules
|
|
36
36
|
list List all discovered routers across networks
|
|
37
37
|
status Show router status, network, and tailnet info
|
|
38
|
+
secrets Manage secrets for workload apps
|
|
39
|
+
logs Stream logs for a workload app
|
|
38
40
|
destroy Destroy a network (router) or a workload app
|
|
39
41
|
doctor Check that Tailscale and the router are working correctly
|
|
40
42
|
|
package/esm/deno.js
CHANGED
package/esm/lib/command.d.ts
CHANGED
|
@@ -23,4 +23,13 @@ export declare class CmdResult {
|
|
|
23
23
|
export declare const runCommand: (args: string[], options?: RunOptions) => Promise<CmdResult>;
|
|
24
24
|
/** Run and parse stdout as JSON. */
|
|
25
25
|
export declare const runJson: <T>(args: string[], options?: RunOptions) => Promise<Result<T>>;
|
|
26
|
+
export interface StreamHandle {
|
|
27
|
+
lines: AsyncIterable<string>;
|
|
28
|
+
done: Promise<CmdResult>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Spawn a command and stream stdout line-by-line via an async iterable.
|
|
32
|
+
* Use `done` to check the exit code after the stream ends.
|
|
33
|
+
*/
|
|
34
|
+
export declare const streamCommand: (args: string[], options?: Omit<RunOptions, "interactive">) => StreamHandle;
|
|
26
35
|
//# sourceMappingURL=command.d.ts.map
|
package/esm/lib/command.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/lib/command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/lib/command.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAMrC,MAAM,WAAW,UAAU;IACzB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,KAAK,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;CAC5B;AAMD,qBAAa,SAAS;IAIlB,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM;IALzB,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;gBAGV,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM;IAKzB,iDAAiD;IACjD,IAAI,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC;IAapB,8BAA8B;IAC9B,IAAI,MAAM,IAAI,MAAM,CAEnB;CACF;AAMD;;;GAGG;AACH,eAAO,MAAM,UAAU,GACrB,MAAM,MAAM,EAAE,EACd,UAAU,UAAU,KACnB,OAAO,CAAC,SAAS,CAyCnB,CAAC;AAMF,oCAAoC;AACpC,eAAO,MAAM,OAAO,GAAI,CAAC,EACvB,MAAM,MAAM,EAAE,EACd,UAAU,UAAU,KACnB,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAuD,CAAC;AAM5E,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC7B,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;CAC1B;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,GACxB,MAAM,MAAM,EAAE,EACd,UAAU,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,KACxC,YA+BF,CAAC"}
|
package/esm/lib/command.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
// Shell Command Helpers
|
|
3
3
|
// =============================================================================
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
5
|
+
import { createInterface } from "node:readline";
|
|
6
|
+
import process from "node:process";
|
|
5
7
|
import { Result } from "./result.js";
|
|
6
8
|
// =============================================================================
|
|
7
9
|
// Command Result
|
|
@@ -82,3 +84,33 @@ export const runCommand = (args, options) => {
|
|
|
82
84
|
// =============================================================================
|
|
83
85
|
/** Run and parse stdout as JSON. */
|
|
84
86
|
export const runJson = (args, options) => runCommand(args, options).then((r) => r.json());
|
|
87
|
+
/**
|
|
88
|
+
* Spawn a command and stream stdout line-by-line via an async iterable.
|
|
89
|
+
* Use `done` to check the exit code after the stream ends.
|
|
90
|
+
*/
|
|
91
|
+
export const streamCommand = (args, options) => {
|
|
92
|
+
const [cmd, ...cmdArgs] = args;
|
|
93
|
+
const child = spawn(cmd, cmdArgs, {
|
|
94
|
+
cwd: options?.cwd,
|
|
95
|
+
env: options?.env ? { ...process.env, ...options.env } : undefined,
|
|
96
|
+
stdio: [
|
|
97
|
+
options?.stdin === "inherit" ? "inherit" : "ignore",
|
|
98
|
+
"pipe",
|
|
99
|
+
"pipe",
|
|
100
|
+
],
|
|
101
|
+
});
|
|
102
|
+
child.stdout.setEncoding("utf8");
|
|
103
|
+
child.stderr.setEncoding("utf8");
|
|
104
|
+
const rl = createInterface({ input: child.stdout });
|
|
105
|
+
const stderr = [];
|
|
106
|
+
child.stderr.on("data", (chunk) => stderr.push(chunk));
|
|
107
|
+
const done = new Promise((resolve) => {
|
|
108
|
+
child.on("error", (error) => {
|
|
109
|
+
resolve(new CmdResult(-1, "", error.message));
|
|
110
|
+
});
|
|
111
|
+
child.on("close", (code) => {
|
|
112
|
+
resolve(new CmdResult(code ?? 1, "", stderr.join("")));
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
return { lines: rl, done };
|
|
116
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface Column {
|
|
2
|
+
name: string;
|
|
3
|
+
width: number;
|
|
4
|
+
}
|
|
5
|
+
export interface StreamTableOptions {
|
|
6
|
+
indent?: number;
|
|
7
|
+
padding?: number;
|
|
8
|
+
}
|
|
9
|
+
export declare class StreamTable {
|
|
10
|
+
private columns;
|
|
11
|
+
private indent;
|
|
12
|
+
private padding;
|
|
13
|
+
constructor(columns: Column[], opts?: StreamTableOptions);
|
|
14
|
+
/** Render the header row (bold column names). */
|
|
15
|
+
header(): string;
|
|
16
|
+
/** Render a separator line under the header. */
|
|
17
|
+
separator(): string;
|
|
18
|
+
/** Render a single data row. */
|
|
19
|
+
row(values: string[]): string;
|
|
20
|
+
private effectiveWidth;
|
|
21
|
+
private pad;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=table.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../src/lib/table.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAMD,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAW;IAC1B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,kBAAkB;IAMxD,iDAAiD;IACjD,MAAM,IAAI,MAAM;IAMhB,gDAAgD;IAChD,SAAS,IAAI,MAAM;IAWnB,gCAAgC;IAChC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM;IAU7B,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,GAAG;CAMZ"}
|
package/esm/lib/table.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// StreamTable - Fixed-Width Column Formatter for Streaming Output
|
|
3
|
+
// =============================================================================
|
|
4
|
+
//
|
|
5
|
+
// Unlike @cliffy/table which needs all rows upfront to calculate widths,
|
|
6
|
+
// StreamTable uses fixed column widths so rows can be rendered one at a time.
|
|
7
|
+
// Each method returns a string — pass it to out.text() for JSON mode guard.
|
|
8
|
+
//
|
|
9
|
+
// =============================================================================
|
|
10
|
+
import { bold, dim } from "./cli.js";
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// StreamTable
|
|
13
|
+
// =============================================================================
|
|
14
|
+
export class StreamTable {
|
|
15
|
+
columns;
|
|
16
|
+
indent;
|
|
17
|
+
padding;
|
|
18
|
+
constructor(columns, opts) {
|
|
19
|
+
this.columns = columns;
|
|
20
|
+
this.indent = " ".repeat(opts?.indent ?? 2);
|
|
21
|
+
this.padding = " ".repeat(opts?.padding ?? 2);
|
|
22
|
+
}
|
|
23
|
+
/** Render the header row (bold column names). */
|
|
24
|
+
header() {
|
|
25
|
+
return this.indent + this.columns
|
|
26
|
+
.map((col, i) => bold(this.pad(col.name, col.width, i)))
|
|
27
|
+
.join(this.padding);
|
|
28
|
+
}
|
|
29
|
+
/** Render a separator line under the header. */
|
|
30
|
+
separator() {
|
|
31
|
+
return this.indent + dim(this.columns
|
|
32
|
+
.map((col, i) => {
|
|
33
|
+
const w = this.effectiveWidth(col.width, i);
|
|
34
|
+
return w > 0 ? "─".repeat(w) : "─".repeat(col.name.length);
|
|
35
|
+
})
|
|
36
|
+
.join(this.padding));
|
|
37
|
+
}
|
|
38
|
+
/** Render a single data row. */
|
|
39
|
+
row(values) {
|
|
40
|
+
return this.indent + this.columns
|
|
41
|
+
.map((col, i) => this.pad(values[i] ?? "", col.width, i))
|
|
42
|
+
.join(this.padding);
|
|
43
|
+
}
|
|
44
|
+
// ===========================================================================
|
|
45
|
+
// Internal
|
|
46
|
+
// ===========================================================================
|
|
47
|
+
effectiveWidth(width, index) {
|
|
48
|
+
// width=0 on last column means unbounded
|
|
49
|
+
if (width === 0 && index === this.columns.length - 1)
|
|
50
|
+
return 0;
|
|
51
|
+
// width=0 on non-last column falls back to header name length
|
|
52
|
+
if (width === 0)
|
|
53
|
+
return this.columns[index].name.length;
|
|
54
|
+
return width;
|
|
55
|
+
}
|
|
56
|
+
pad(value, width, index) {
|
|
57
|
+
const w = this.effectiveWidth(width, index);
|
|
58
|
+
if (w === 0)
|
|
59
|
+
return value; // unbounded last column
|
|
60
|
+
if (value.length > w)
|
|
61
|
+
return value.slice(0, w - 1) + "…";
|
|
62
|
+
return value.padEnd(w);
|
|
63
|
+
}
|
|
64
|
+
}
|
package/esm/main.d.ts
CHANGED
|
@@ -7,4 +7,6 @@ import "./cli/commands/list/index.js";
|
|
|
7
7
|
import "./cli/commands/status/index.js";
|
|
8
8
|
import "./cli/commands/destroy/index.js";
|
|
9
9
|
import "./cli/commands/doctor.js";
|
|
10
|
+
import "./cli/commands/secrets.js";
|
|
11
|
+
import "./cli/commands/logs.js";
|
|
10
12
|
//# 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;
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AACA,OAAO,qBAAqB,CAAC;AAoC7B,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;AAClC,OAAO,2BAA2B,CAAC;AACnC,OAAO,wBAAwB,CAAC"}
|
package/esm/main.js
CHANGED
|
@@ -14,6 +14,8 @@ import * as dntShim from "./_dnt.shims.js";
|
|
|
14
14
|
// deploy Deploy an app safely on a custom private network
|
|
15
15
|
// share Grant a group access to a network via Tailscale ACL rules
|
|
16
16
|
// status Show router status, network, and tailnet info
|
|
17
|
+
// secrets Manage secrets for workload apps
|
|
18
|
+
// logs Stream logs for a workload app
|
|
17
19
|
// destroy Destroy a network (router) or a workload app
|
|
18
20
|
// doctor Check that Tailscale and the router are working correctly
|
|
19
21
|
//
|
|
@@ -37,6 +39,8 @@ import "./cli/commands/list/index.js";
|
|
|
37
39
|
import "./cli/commands/status/index.js";
|
|
38
40
|
import "./cli/commands/destroy/index.js";
|
|
39
41
|
import "./cli/commands/doctor.js";
|
|
42
|
+
import "./cli/commands/secrets.js";
|
|
43
|
+
import "./cli/commands/logs.js";
|
|
40
44
|
// =============================================================================
|
|
41
45
|
// Main
|
|
42
46
|
// =============================================================================
|
package/esm/providers/fly.d.ts
CHANGED
|
@@ -57,9 +57,17 @@ export interface FlyProvider {
|
|
|
57
57
|
destroy(app: string, machineId: string): Promise<void>;
|
|
58
58
|
};
|
|
59
59
|
secrets: {
|
|
60
|
+
list(app: string): Promise<Array<{
|
|
61
|
+
name: string;
|
|
62
|
+
digest: string;
|
|
63
|
+
}>>;
|
|
60
64
|
set(app: string, secrets: Record<string, string>, opts?: {
|
|
61
65
|
stage?: boolean;
|
|
62
66
|
}): Promise<void>;
|
|
67
|
+
unset(app: string, keys: string[], opts?: {
|
|
68
|
+
stage?: boolean;
|
|
69
|
+
}): Promise<void>;
|
|
70
|
+
deploy(app: string): Promise<void>;
|
|
63
71
|
};
|
|
64
72
|
ips: {
|
|
65
73
|
list(app: string): Promise<FlyIp[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fly.d.ts","sourceRoot":"","sources":["../../src/providers/fly.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"fly.d.ts","sourceRoot":"","sources":["../../src/providers/fly.ts"],"names":[],"mappings":"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"}
|
package/esm/providers/fly.js
CHANGED
|
@@ -246,6 +246,10 @@ export const createFlyProvider = () => {
|
|
|
246
246
|
},
|
|
247
247
|
},
|
|
248
248
|
secrets: {
|
|
249
|
+
async list(app) {
|
|
250
|
+
const result = await runJson(["fly", "secrets", "list", "-a", app, "--json"]);
|
|
251
|
+
return result.unwrapOr([]);
|
|
252
|
+
},
|
|
249
253
|
async set(app, secrets, opts) {
|
|
250
254
|
const pairs = Object.entries(secrets)
|
|
251
255
|
.filter(([_, v]) => v !== undefined && v !== "")
|
|
@@ -261,6 +265,30 @@ export const createFlyProvider = () => {
|
|
|
261
265
|
return die("Failed to Set Secrets");
|
|
262
266
|
}
|
|
263
267
|
},
|
|
268
|
+
async unset(app, keys, opts) {
|
|
269
|
+
if (keys.length === 0)
|
|
270
|
+
return;
|
|
271
|
+
const args = ["fly", "secrets", "unset", ...keys, "-a", app];
|
|
272
|
+
if (opts?.stage) {
|
|
273
|
+
args.push("--stage");
|
|
274
|
+
}
|
|
275
|
+
const result = await runCommand(args);
|
|
276
|
+
if (!result.ok) {
|
|
277
|
+
return die("Failed to Unset Secrets");
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
async deploy(app) {
|
|
281
|
+
const result = await runCommand([
|
|
282
|
+
"fly",
|
|
283
|
+
"secrets",
|
|
284
|
+
"deploy",
|
|
285
|
+
"-a",
|
|
286
|
+
app,
|
|
287
|
+
]);
|
|
288
|
+
if (!result.ok) {
|
|
289
|
+
return die("Failed to Deploy Secrets");
|
|
290
|
+
}
|
|
291
|
+
},
|
|
264
292
|
},
|
|
265
293
|
ips: {
|
|
266
294
|
async list(app) {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { FlyMachine } from "../schemas/fly.js";
|
|
2
|
-
import { type FlyMachineGuestSchema } from "../schemas/fly.js";
|
|
1
|
+
import type { FlyMachine, FlyMachineGuestSchema } from "../schemas/fly.js";
|
|
3
2
|
import type { z } from "../deps/jsr.io/@zod/zod/4.3.6/src/index.js";
|
|
4
3
|
/**
|
|
5
4
|
* Map Fly machine state to internal state.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fly-transforms.d.ts","sourceRoot":"","sources":["../../src/util/fly-transforms.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"fly-transforms.d.ts","sourceRoot":"","sources":["../../src/util/fly-transforms.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,4CAA4C,CAAC;AAMpE;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAC7B,UAAU,MAAM,KACf,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,QAiBtC,CAAC;AAMF;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,KAC5C,eAAe,GAAG,eAAe,GAAG,eAOtC,CAAC;AAMF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,6DAA6D;AAC7D,eAAO,MAAM,WAAW,GAAI,KAAK,UAAU,EAAE,KAAG,aAAa,EAQ5D,CAAC;AAMF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,eAAO,MAAM,aAAa,GACxB,MAAM,WAAW,KAChB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CASlC,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAAI,QAAQ,MAAM,KAAG,MAOnD,CAAC;AAMF,eAAO,MAAM,aAAa,GAAI,WAAW,MAAM,KAAG,MAKjD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/util/resolve.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAMvD;;GAEG;AACH,eAAO,MAAM,UAAU,GACrB,KAAK,WAAW,EAChB,MAAM;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/util/resolve.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAMvD;;GAEG;AACH,eAAO,MAAM,UAAU,GACrB,KAAK,WAAW,EAChB,MAAM;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,EAEtC,KAAK,MAAM,CAAC,GAAG,CAAC,KACf,OAAO,CAAC,MAAM,CA6BhB,CAAC"}
|
package/esm/util/resolve.js
CHANGED
|
@@ -8,7 +8,9 @@ import { prompt } from "../lib/cli.js";
|
|
|
8
8
|
/**
|
|
9
9
|
* Resolve Fly.io organization: --org flag → single org auto-select → prompt.
|
|
10
10
|
*/
|
|
11
|
-
export const resolveOrg = async (fly, args,
|
|
11
|
+
export const resolveOrg = async (fly, args,
|
|
12
|
+
// deno-lint-ignore no-explicit-any
|
|
13
|
+
out) => {
|
|
12
14
|
if (args.org)
|
|
13
15
|
return args.org;
|
|
14
16
|
if (args.json) {
|
package/esm/util/template.js
CHANGED
|
@@ -24,7 +24,7 @@ import { Result } from "../lib/result.js";
|
|
|
24
24
|
/** Shorthand for returning a typed fetch error. */
|
|
25
25
|
const fail = (message) => Result.err(message);
|
|
26
26
|
/** Format a template reference for display. */
|
|
27
|
-
const
|
|
27
|
+
const _formatRef = (ref) => {
|
|
28
28
|
const base = ref.path === "."
|
|
29
29
|
? `${ref.owner}/${ref.repo}`
|
|
30
30
|
: `${ref.owner}/${ref.repo}/${ref.path}`;
|