@r4security/cli 0.0.1
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 +59 -0
- package/lib/index.js +675 -0
- package/lib/index.js.map +1 -0
- package/package.json +44 -0
package/README.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# r4-cli
|
|
2
|
+
|
|
3
|
+
Official R4 CLI -- manage vaults, projects, and secrets from the terminal.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g r4-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Requires Node.js >= 18.0.0.
|
|
12
|
+
|
|
13
|
+
## Commands
|
|
14
|
+
|
|
15
|
+
### `r4 auth`
|
|
16
|
+
Manage API key authentication.
|
|
17
|
+
- `r4 auth login` -- Configure API key credentials
|
|
18
|
+
- `r4 auth logout` -- Remove stored credentials
|
|
19
|
+
- `r4 auth status` -- Show current authentication state
|
|
20
|
+
|
|
21
|
+
### `r4 vault`
|
|
22
|
+
Manage vault secrets.
|
|
23
|
+
- `r4 vault list` -- List all vaults in the project
|
|
24
|
+
- `r4 vault get <name>` -- Get a specific vault's secrets
|
|
25
|
+
|
|
26
|
+
### `r4 project`
|
|
27
|
+
Manage projects.
|
|
28
|
+
- `r4 project list` -- List all projects
|
|
29
|
+
- `r4 project get <id>` -- Get project details
|
|
30
|
+
- `r4 project create` -- Create a new project
|
|
31
|
+
|
|
32
|
+
### `r4 run <command...>`
|
|
33
|
+
Execute a command with vault secrets injected as environment variables.
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
r4 run --project-id abc123 node deploy.js
|
|
37
|
+
r4 run --prefix R4 -- docker compose up
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Global Options
|
|
41
|
+
|
|
42
|
+
| Flag | Description |
|
|
43
|
+
|--------------------|---------------------------------------------------|
|
|
44
|
+
| `--api-key <key>` | API key (overrides `R4_API_KEY` env var and config)|
|
|
45
|
+
| `--project-id <id>`| Project ID (overrides `R4_PROJECT_ID` env var) |
|
|
46
|
+
| `--base-url <url>` | API base URL (default: `https://r4.dev`) |
|
|
47
|
+
| `--json` | Output as JSON for scripting and piping |
|
|
48
|
+
|
|
49
|
+
## Dependencies
|
|
50
|
+
|
|
51
|
+
Uses `r4-sdk` (workspace) under the hood for API communication. Built with Commander, Chalk, ora, and cli-table3.
|
|
52
|
+
|
|
53
|
+
## Development
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pnpm run build # Build with tsup
|
|
57
|
+
pnpm run dev # Watch mode
|
|
58
|
+
pnpm run clean # Remove lib/
|
|
59
|
+
```
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,675 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import { Command as Command12 } from "commander";
|
|
5
|
+
|
|
6
|
+
// src/commands/auth/login.ts
|
|
7
|
+
import { Command } from "commander";
|
|
8
|
+
import readline from "node:readline";
|
|
9
|
+
|
|
10
|
+
// src/lib/config.ts
|
|
11
|
+
import fs from "node:fs";
|
|
12
|
+
import os from "node:os";
|
|
13
|
+
import path from "node:path";
|
|
14
|
+
var CONFIG_DIR = path.join(os.homedir(), ".r4");
|
|
15
|
+
var CONFIG_PATH = path.join(CONFIG_DIR, "config.json");
|
|
16
|
+
function loadConfig() {
|
|
17
|
+
try {
|
|
18
|
+
const raw = fs.readFileSync(CONFIG_PATH, "utf8");
|
|
19
|
+
return JSON.parse(raw);
|
|
20
|
+
} catch {
|
|
21
|
+
return {};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function saveConfig(config) {
|
|
25
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
26
|
+
fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + "\n", "utf8");
|
|
27
|
+
}
|
|
28
|
+
function clearConfig() {
|
|
29
|
+
try {
|
|
30
|
+
fs.unlinkSync(CONFIG_PATH);
|
|
31
|
+
} catch {
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function getConfigPath() {
|
|
35
|
+
return CONFIG_PATH;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// src/lib/output.ts
|
|
39
|
+
import chalk from "chalk";
|
|
40
|
+
import Table from "cli-table3";
|
|
41
|
+
function printTable(headers, rows, jsonMode, jsonData) {
|
|
42
|
+
if (jsonMode) {
|
|
43
|
+
console.log(JSON.stringify(jsonData ?? rows, null, 2));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const table = new Table({
|
|
47
|
+
head: headers.map((h) => chalk.cyan(h)),
|
|
48
|
+
style: { head: [], border: [] }
|
|
49
|
+
});
|
|
50
|
+
for (const row of rows) {
|
|
51
|
+
table.push(row);
|
|
52
|
+
}
|
|
53
|
+
console.log(table.toString());
|
|
54
|
+
}
|
|
55
|
+
function printDetail(entries, jsonMode, jsonData) {
|
|
56
|
+
if (jsonMode) {
|
|
57
|
+
console.log(JSON.stringify(jsonData, null, 2));
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const maxLen = Math.max(...entries.map(([k]) => k.length));
|
|
61
|
+
for (const [key, value] of entries) {
|
|
62
|
+
const label = chalk.gray(key.padEnd(maxLen));
|
|
63
|
+
const val = value ?? chalk.dim("(empty)");
|
|
64
|
+
console.log(` ${label} ${val}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function success(message) {
|
|
68
|
+
console.log(chalk.green("\u2713") + " " + message);
|
|
69
|
+
}
|
|
70
|
+
function warn(message) {
|
|
71
|
+
console.log(chalk.yellow("!") + " " + message);
|
|
72
|
+
}
|
|
73
|
+
function printError(message) {
|
|
74
|
+
console.error(chalk.red("\u2717") + " " + message);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// src/lib/errors.ts
|
|
78
|
+
function withErrorHandler(fn) {
|
|
79
|
+
return async (...args) => {
|
|
80
|
+
try {
|
|
81
|
+
await fn(...args);
|
|
82
|
+
} catch (err) {
|
|
83
|
+
if (err instanceof Error) {
|
|
84
|
+
printError(err.message);
|
|
85
|
+
} else {
|
|
86
|
+
printError("An unexpected error occurred");
|
|
87
|
+
}
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/commands/auth/login.ts
|
|
94
|
+
function prompt(question) {
|
|
95
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
96
|
+
return new Promise((resolve) => {
|
|
97
|
+
rl.question(question, (answer) => {
|
|
98
|
+
rl.close();
|
|
99
|
+
resolve(answer.trim());
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
function loginCommand() {
|
|
104
|
+
return new Command("login").description("Save your API key to the config file").action(
|
|
105
|
+
withErrorHandler(async (_opts, cmd) => {
|
|
106
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
107
|
+
let apiKey = globalOpts.apiKey || process.env.R4_API_KEY;
|
|
108
|
+
if (!apiKey) {
|
|
109
|
+
apiKey = await prompt("Enter your R4 API key: ");
|
|
110
|
+
}
|
|
111
|
+
if (!apiKey) {
|
|
112
|
+
throw new Error("No API key provided.");
|
|
113
|
+
}
|
|
114
|
+
if (!apiKey.includes(".")) {
|
|
115
|
+
warn("API key format is usually {accessKey}.{secret}");
|
|
116
|
+
}
|
|
117
|
+
const config = loadConfig();
|
|
118
|
+
config.apiKey = apiKey;
|
|
119
|
+
if (globalOpts.baseUrl) {
|
|
120
|
+
config.baseUrl = globalOpts.baseUrl;
|
|
121
|
+
}
|
|
122
|
+
saveConfig(config);
|
|
123
|
+
success(`API key saved to ${getConfigPath()}`);
|
|
124
|
+
})
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// src/commands/auth/logout.ts
|
|
129
|
+
import { Command as Command2 } from "commander";
|
|
130
|
+
function logoutCommand() {
|
|
131
|
+
return new Command2("logout").description("Remove saved API key from the config file").action(
|
|
132
|
+
withErrorHandler(async () => {
|
|
133
|
+
clearConfig();
|
|
134
|
+
success(`Config removed from ${getConfigPath()}`);
|
|
135
|
+
})
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/commands/auth/status.ts
|
|
140
|
+
import { Command as Command3 } from "commander";
|
|
141
|
+
import chalk2 from "chalk";
|
|
142
|
+
function maskKey(key) {
|
|
143
|
+
if (key.length <= 8) return key;
|
|
144
|
+
return key.substring(0, 8) + "...";
|
|
145
|
+
}
|
|
146
|
+
function statusCommand() {
|
|
147
|
+
return new Command3("status").description("Show current authentication status").action(
|
|
148
|
+
withErrorHandler(async (_opts, cmd) => {
|
|
149
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
150
|
+
const config = loadConfig();
|
|
151
|
+
let source;
|
|
152
|
+
let apiKey;
|
|
153
|
+
if (globalOpts.apiKey) {
|
|
154
|
+
source = "--api-key flag";
|
|
155
|
+
apiKey = globalOpts.apiKey;
|
|
156
|
+
} else if (process.env.R4_API_KEY) {
|
|
157
|
+
source = "R4_API_KEY env var";
|
|
158
|
+
apiKey = process.env.R4_API_KEY;
|
|
159
|
+
} else if (config.apiKey) {
|
|
160
|
+
source = `config file (${getConfigPath()})`;
|
|
161
|
+
apiKey = config.apiKey;
|
|
162
|
+
} else {
|
|
163
|
+
source = "none";
|
|
164
|
+
}
|
|
165
|
+
if (globalOpts.json) {
|
|
166
|
+
console.log(
|
|
167
|
+
JSON.stringify(
|
|
168
|
+
{
|
|
169
|
+
authenticated: !!apiKey,
|
|
170
|
+
source,
|
|
171
|
+
apiKey: apiKey ? maskKey(apiKey) : null,
|
|
172
|
+
baseUrl: globalOpts.baseUrl || process.env.R4_BASE_URL || config.baseUrl || "https://r4.dev"
|
|
173
|
+
},
|
|
174
|
+
null,
|
|
175
|
+
2
|
|
176
|
+
)
|
|
177
|
+
);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
console.log();
|
|
181
|
+
if (apiKey) {
|
|
182
|
+
console.log(chalk2.bold(" Authenticated"));
|
|
183
|
+
console.log();
|
|
184
|
+
printDetail(
|
|
185
|
+
[
|
|
186
|
+
["Source", source],
|
|
187
|
+
["API Key", maskKey(apiKey)],
|
|
188
|
+
[
|
|
189
|
+
"Base URL",
|
|
190
|
+
globalOpts.baseUrl || process.env.R4_BASE_URL || config.baseUrl || "https://r4.dev"
|
|
191
|
+
]
|
|
192
|
+
],
|
|
193
|
+
false
|
|
194
|
+
);
|
|
195
|
+
} else {
|
|
196
|
+
console.log(chalk2.bold(" Not authenticated"));
|
|
197
|
+
console.log();
|
|
198
|
+
console.log(" Run " + chalk2.cyan("r4 auth login") + " to save your API key.");
|
|
199
|
+
}
|
|
200
|
+
console.log();
|
|
201
|
+
})
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// src/commands/auth/whoami.ts
|
|
206
|
+
import { Command as Command4 } from "commander";
|
|
207
|
+
import chalk3 from "chalk";
|
|
208
|
+
function maskKey2(key) {
|
|
209
|
+
if (key.length <= 8) return key;
|
|
210
|
+
return key.substring(0, 8) + "...";
|
|
211
|
+
}
|
|
212
|
+
function whoamiCommand() {
|
|
213
|
+
return new Command4("whoami").description("Show current authenticated identity").action(
|
|
214
|
+
withErrorHandler(async (_opts, cmd) => {
|
|
215
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
216
|
+
const config = loadConfig();
|
|
217
|
+
const apiKey = globalOpts.apiKey || process.env.R4_API_KEY || config.apiKey;
|
|
218
|
+
const projectId = globalOpts.projectId || process.env.R4_PROJECT_ID || config.projectId;
|
|
219
|
+
const baseUrl = globalOpts.baseUrl || process.env.R4_BASE_URL || config.baseUrl || "https://r4.dev";
|
|
220
|
+
if (globalOpts.json) {
|
|
221
|
+
console.log(
|
|
222
|
+
JSON.stringify(
|
|
223
|
+
{
|
|
224
|
+
authenticated: !!apiKey,
|
|
225
|
+
apiKey: apiKey ? maskKey2(apiKey) : null,
|
|
226
|
+
projectId: projectId || null,
|
|
227
|
+
baseUrl,
|
|
228
|
+
configPath: getConfigPath()
|
|
229
|
+
},
|
|
230
|
+
null,
|
|
231
|
+
2
|
|
232
|
+
)
|
|
233
|
+
);
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
console.log();
|
|
237
|
+
if (!apiKey) {
|
|
238
|
+
console.log(chalk3.bold(" Not authenticated"));
|
|
239
|
+
console.log();
|
|
240
|
+
console.log(" Run " + chalk3.cyan("r4 auth login") + " to save your API key.");
|
|
241
|
+
console.log();
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
console.log(chalk3.bold(" Authenticated"));
|
|
245
|
+
console.log();
|
|
246
|
+
printDetail(
|
|
247
|
+
[
|
|
248
|
+
["API Key", maskKey2(apiKey)],
|
|
249
|
+
["Project ID", projectId || chalk3.dim("(not set)")],
|
|
250
|
+
["Base URL", baseUrl],
|
|
251
|
+
["Config File", getConfigPath()]
|
|
252
|
+
],
|
|
253
|
+
false
|
|
254
|
+
);
|
|
255
|
+
console.log();
|
|
256
|
+
})
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// src/commands/auth/index.ts
|
|
261
|
+
function registerAuthCommands(program2) {
|
|
262
|
+
const auth = program2.command("auth").description("Manage API key authentication");
|
|
263
|
+
auth.addCommand(loginCommand());
|
|
264
|
+
auth.addCommand(logoutCommand());
|
|
265
|
+
auth.addCommand(statusCommand());
|
|
266
|
+
auth.addCommand(whoamiCommand());
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// src/commands/vault/list.ts
|
|
270
|
+
import { Command as Command5 } from "commander";
|
|
271
|
+
import ora from "ora";
|
|
272
|
+
import R4 from "r4-sdk";
|
|
273
|
+
|
|
274
|
+
// src/lib/resolve-auth.ts
|
|
275
|
+
function resolveAuth(opts) {
|
|
276
|
+
const config = loadConfig();
|
|
277
|
+
const apiKey = opts.apiKey || process.env.R4_API_KEY || config.apiKey;
|
|
278
|
+
if (!apiKey) {
|
|
279
|
+
throw new Error(
|
|
280
|
+
"No API key found. Provide one via:\n --api-key <key> CLI flag\n R4_API_KEY environment variable\n r4 auth login save to config file"
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
const projectId = opts.projectId || process.env.R4_PROJECT_ID || config.projectId;
|
|
284
|
+
if (!projectId) {
|
|
285
|
+
throw new Error(
|
|
286
|
+
"No project ID found. Provide one via:\n --project-id <id> CLI flag\n R4_PROJECT_ID environment variable\n ~/.r4/config.json config file (projectId field)"
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
const baseUrl = opts.baseUrl || process.env.R4_BASE_URL || config.baseUrl || "https://r4.dev";
|
|
290
|
+
return { apiKey, projectId, baseUrl };
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// src/commands/vault/list.ts
|
|
294
|
+
function listCommand() {
|
|
295
|
+
return new Command5("list").description("List all project environment variables").action(
|
|
296
|
+
withErrorHandler(async (_opts, cmd) => {
|
|
297
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
298
|
+
const config = resolveAuth(globalOpts);
|
|
299
|
+
const spinner = ora("Fetching environment variables...").start();
|
|
300
|
+
const r4 = await R4.create(config);
|
|
301
|
+
spinner.stop();
|
|
302
|
+
const env = r4.env;
|
|
303
|
+
const keys = Object.keys(env).sort();
|
|
304
|
+
if (globalOpts.json) {
|
|
305
|
+
console.log(JSON.stringify(env, null, 2));
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
if (keys.length === 0) {
|
|
309
|
+
console.log("\n No environment variables found.\n");
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
const rows = keys.map((key) => [key, env[key]]);
|
|
313
|
+
console.log();
|
|
314
|
+
printTable(["Key", "Value"], rows, false);
|
|
315
|
+
console.log();
|
|
316
|
+
})
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// src/commands/vault/get.ts
|
|
321
|
+
import { Command as Command6 } from "commander";
|
|
322
|
+
import ora2 from "ora";
|
|
323
|
+
import R42 from "r4-sdk";
|
|
324
|
+
function getCommand() {
|
|
325
|
+
return new Command6("get").description("Get a specific environment variable value").argument("<key>", "Environment variable key (SCREAMING_SNAKE_CASE)").action(
|
|
326
|
+
withErrorHandler(
|
|
327
|
+
async (keyArg, _opts, cmd) => {
|
|
328
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
329
|
+
const config = resolveAuth(globalOpts);
|
|
330
|
+
const spinner = ora2("Fetching environment variables...").start();
|
|
331
|
+
const r4 = await R42.create(config);
|
|
332
|
+
spinner.stop();
|
|
333
|
+
const env = r4.env;
|
|
334
|
+
const key = keyArg.toUpperCase();
|
|
335
|
+
const value = env[key];
|
|
336
|
+
if (value === void 0) {
|
|
337
|
+
const available = Object.keys(env).sort().join(", ") || "(none)";
|
|
338
|
+
throw new Error(`Key "${key}" not found. Available keys: ${available}`);
|
|
339
|
+
}
|
|
340
|
+
if (globalOpts.json) {
|
|
341
|
+
console.log(JSON.stringify({ key, value }, null, 2));
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
process.stdout.write(value);
|
|
345
|
+
}
|
|
346
|
+
)
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// src/commands/vault/items.ts
|
|
351
|
+
import { Command as Command7 } from "commander";
|
|
352
|
+
import ora3 from "ora";
|
|
353
|
+
import R43 from "r4-sdk";
|
|
354
|
+
function deriveItems(env) {
|
|
355
|
+
const keys = Object.keys(env).sort();
|
|
356
|
+
return keys.map((key) => ({
|
|
357
|
+
name: key,
|
|
358
|
+
fields: [{ name: key, key }]
|
|
359
|
+
}));
|
|
360
|
+
}
|
|
361
|
+
function itemsCommand() {
|
|
362
|
+
return new Command7("items").description("List all vault items with their field names and types").action(
|
|
363
|
+
withErrorHandler(async (_opts, cmd) => {
|
|
364
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
365
|
+
const config = resolveAuth(globalOpts);
|
|
366
|
+
const spinner = ora3("Fetching vault items...").start();
|
|
367
|
+
const r4 = await R43.create(config);
|
|
368
|
+
spinner.stop();
|
|
369
|
+
const env = r4.env;
|
|
370
|
+
const items = deriveItems(env);
|
|
371
|
+
if (globalOpts.json) {
|
|
372
|
+
console.log(JSON.stringify(items, null, 2));
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
if (items.length === 0) {
|
|
376
|
+
console.log("\n No vault items found.\n");
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
const rows = items.map((item) => [
|
|
380
|
+
item.name,
|
|
381
|
+
"secret",
|
|
382
|
+
item.fields.map((f) => f.name).join(", ")
|
|
383
|
+
]);
|
|
384
|
+
console.log();
|
|
385
|
+
printTable(["Name", "Type", "Fields"], rows, false);
|
|
386
|
+
console.log();
|
|
387
|
+
})
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// src/commands/vault/search.ts
|
|
392
|
+
import { Command as Command8 } from "commander";
|
|
393
|
+
import ora4 from "ora";
|
|
394
|
+
import R44 from "r4-sdk";
|
|
395
|
+
function searchCommand() {
|
|
396
|
+
return new Command8("search").description("Search vault items by name").argument("<query>", "Search query (case-insensitive match against key names)").action(
|
|
397
|
+
withErrorHandler(
|
|
398
|
+
async (query, _opts, cmd) => {
|
|
399
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
400
|
+
const config = resolveAuth(globalOpts);
|
|
401
|
+
const spinner = ora4("Searching vault items...").start();
|
|
402
|
+
const r4 = await R44.create(config);
|
|
403
|
+
spinner.stop();
|
|
404
|
+
const env = r4.env;
|
|
405
|
+
const lowerQuery = query.toLowerCase();
|
|
406
|
+
const matches = Object.keys(env).filter((key) => key.toLowerCase().includes(lowerQuery)).sort();
|
|
407
|
+
if (globalOpts.json) {
|
|
408
|
+
const result = matches.map((key) => ({ key, value: env[key] }));
|
|
409
|
+
console.log(JSON.stringify(result, null, 2));
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
if (matches.length === 0) {
|
|
413
|
+
console.log(`
|
|
414
|
+
No items matching "${query}" found.
|
|
415
|
+
`);
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
const rows = matches.map((key) => [key, env[key]]);
|
|
419
|
+
console.log();
|
|
420
|
+
printTable(["Key", "Value"], rows, false);
|
|
421
|
+
console.log();
|
|
422
|
+
}
|
|
423
|
+
)
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// src/commands/vault/index.ts
|
|
428
|
+
function registerVaultCommands(program2) {
|
|
429
|
+
const vault = program2.command("vault").description("Manage vault secrets");
|
|
430
|
+
vault.addCommand(listCommand());
|
|
431
|
+
vault.addCommand(getCommand());
|
|
432
|
+
vault.addCommand(itemsCommand());
|
|
433
|
+
vault.addCommand(searchCommand());
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// src/commands/project/list.ts
|
|
437
|
+
import { Command as Command9 } from "commander";
|
|
438
|
+
import ora5 from "ora";
|
|
439
|
+
|
|
440
|
+
// src/lib/client.ts
|
|
441
|
+
var CliClient = class {
|
|
442
|
+
apiKey;
|
|
443
|
+
baseUrl;
|
|
444
|
+
constructor(apiKey, baseUrl) {
|
|
445
|
+
this.apiKey = apiKey;
|
|
446
|
+
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Make an authenticated request to the machine API.
|
|
450
|
+
* Handles error responses consistently with the SDK pattern.
|
|
451
|
+
*/
|
|
452
|
+
async request(method, path2, body) {
|
|
453
|
+
const url = `${this.baseUrl}${path2}`;
|
|
454
|
+
const response = await fetch(url, {
|
|
455
|
+
method,
|
|
456
|
+
headers: {
|
|
457
|
+
"X-API-Key": this.apiKey,
|
|
458
|
+
"Content-Type": "application/json"
|
|
459
|
+
},
|
|
460
|
+
body: body ? JSON.stringify(body) : void 0
|
|
461
|
+
});
|
|
462
|
+
if (!response.ok) {
|
|
463
|
+
const errorBody = await response.json().catch(() => ({}));
|
|
464
|
+
const error = errorBody?.error;
|
|
465
|
+
const errorMessage = error?.message || `HTTP ${response.status}: ${response.statusText}`;
|
|
466
|
+
throw new Error(`R4 API Error: ${errorMessage}`);
|
|
467
|
+
}
|
|
468
|
+
return response.json();
|
|
469
|
+
}
|
|
470
|
+
/** List all projects. GET /api/v1/machine/project */
|
|
471
|
+
async listProjects() {
|
|
472
|
+
return this.request("GET", "/api/v1/machine/project");
|
|
473
|
+
}
|
|
474
|
+
/** Get project details. GET /api/v1/machine/project/:id */
|
|
475
|
+
async getProject(id) {
|
|
476
|
+
return this.request("GET", `/api/v1/machine/project/${id}`);
|
|
477
|
+
}
|
|
478
|
+
/** Create a new project. POST /api/v1/machine/project */
|
|
479
|
+
async createProject(data) {
|
|
480
|
+
return this.request("POST", "/api/v1/machine/project", data);
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
// src/commands/project/list.ts
|
|
485
|
+
function listCommand2() {
|
|
486
|
+
return new Command9("list").description("List all projects").action(
|
|
487
|
+
withErrorHandler(async (_opts, cmd) => {
|
|
488
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
489
|
+
const config = resolveAuth(globalOpts);
|
|
490
|
+
const client = new CliClient(config.apiKey, config.baseUrl || "https://r4.dev");
|
|
491
|
+
const spinner = ora5("Fetching projects...").start();
|
|
492
|
+
const response = await client.listProjects();
|
|
493
|
+
spinner.stop();
|
|
494
|
+
const rows = response.projects.map((p) => [
|
|
495
|
+
p.id,
|
|
496
|
+
p.name,
|
|
497
|
+
p.externalId || "-",
|
|
498
|
+
String(p.vaultsCount),
|
|
499
|
+
String(p.licensesCount),
|
|
500
|
+
String(p.licenseGroupsCount)
|
|
501
|
+
]);
|
|
502
|
+
console.log();
|
|
503
|
+
printTable(
|
|
504
|
+
["ID", "Name", "External ID", "Vaults", "Licenses", "License Groups"],
|
|
505
|
+
rows,
|
|
506
|
+
!!globalOpts.json,
|
|
507
|
+
response.projects
|
|
508
|
+
);
|
|
509
|
+
console.log();
|
|
510
|
+
})
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// src/commands/project/get.ts
|
|
515
|
+
import { Command as Command10 } from "commander";
|
|
516
|
+
import chalk4 from "chalk";
|
|
517
|
+
import ora6 from "ora";
|
|
518
|
+
function getCommand2() {
|
|
519
|
+
return new Command10("get").description("Get project details").argument("<id>", "Project ID").action(
|
|
520
|
+
withErrorHandler(async (id, _opts, cmd) => {
|
|
521
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
522
|
+
const config = resolveAuth(globalOpts);
|
|
523
|
+
const client = new CliClient(config.apiKey, config.baseUrl || "https://r4.dev");
|
|
524
|
+
const spinner = ora6("Fetching project...").start();
|
|
525
|
+
const project = await client.getProject(id);
|
|
526
|
+
spinner.stop();
|
|
527
|
+
if (globalOpts.json) {
|
|
528
|
+
console.log(JSON.stringify(project, null, 2));
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
console.log();
|
|
532
|
+
console.log(chalk4.bold(` ${project.name}`));
|
|
533
|
+
console.log();
|
|
534
|
+
printDetail(
|
|
535
|
+
[
|
|
536
|
+
["ID", project.id],
|
|
537
|
+
["External ID", project.externalId],
|
|
538
|
+
["Description", project.description],
|
|
539
|
+
["Created At", project.createdAt],
|
|
540
|
+
["Vaults", String(project.vaultsCount)],
|
|
541
|
+
["Licenses", String(project.licensesCount)],
|
|
542
|
+
["License Groups", String(project.licenseGroupsCount)]
|
|
543
|
+
],
|
|
544
|
+
false
|
|
545
|
+
);
|
|
546
|
+
if (project.vaults.length > 0) {
|
|
547
|
+
console.log();
|
|
548
|
+
console.log(chalk4.bold(" Vaults"));
|
|
549
|
+
console.log();
|
|
550
|
+
printTable(
|
|
551
|
+
["ID", "Name", "Encrypted"],
|
|
552
|
+
project.vaults.map((v) => [v.id, v.name, v.isEncrypted ? "Yes" : "No"]),
|
|
553
|
+
false
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
if (project.licenses.length > 0) {
|
|
557
|
+
console.log();
|
|
558
|
+
console.log(chalk4.bold(" Licenses"));
|
|
559
|
+
console.log();
|
|
560
|
+
printTable(
|
|
561
|
+
["ID", "Name", "Type"],
|
|
562
|
+
project.licenses.map((l) => [l.id, l.name || "-", l.type]),
|
|
563
|
+
false
|
|
564
|
+
);
|
|
565
|
+
}
|
|
566
|
+
if (project.licenseGroups.length > 0) {
|
|
567
|
+
console.log();
|
|
568
|
+
console.log(chalk4.bold(" License Groups"));
|
|
569
|
+
console.log();
|
|
570
|
+
printTable(
|
|
571
|
+
["ID", "Name"],
|
|
572
|
+
project.licenseGroups.map((lg) => [lg.id, lg.name]),
|
|
573
|
+
false
|
|
574
|
+
);
|
|
575
|
+
}
|
|
576
|
+
console.log();
|
|
577
|
+
})
|
|
578
|
+
);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// src/commands/project/create.ts
|
|
582
|
+
import { Command as Command11 } from "commander";
|
|
583
|
+
import readline2 from "node:readline";
|
|
584
|
+
import ora7 from "ora";
|
|
585
|
+
function prompt2(question) {
|
|
586
|
+
const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
|
|
587
|
+
return new Promise((resolve) => {
|
|
588
|
+
rl.question(question, (answer) => {
|
|
589
|
+
rl.close();
|
|
590
|
+
resolve(answer.trim());
|
|
591
|
+
});
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
function createCommand() {
|
|
595
|
+
return new Command11("create").description("Create a new project").option("--name <name>", "Project name").option("--description <description>", "Project description").option("--external-id <externalId>", "External identifier").action(
|
|
596
|
+
withErrorHandler(async (opts, cmd) => {
|
|
597
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
598
|
+
const config = resolveAuth(globalOpts);
|
|
599
|
+
const client = new CliClient(config.apiKey, config.baseUrl || "https://r4.dev");
|
|
600
|
+
let name = opts.name;
|
|
601
|
+
if (!name) {
|
|
602
|
+
name = await prompt2("Project name: ");
|
|
603
|
+
}
|
|
604
|
+
if (!name) {
|
|
605
|
+
throw new Error("Project name is required.");
|
|
606
|
+
}
|
|
607
|
+
const spinner = ora7("Creating project...").start();
|
|
608
|
+
const response = await client.createProject({
|
|
609
|
+
name,
|
|
610
|
+
description: opts.description,
|
|
611
|
+
externalId: opts.externalId
|
|
612
|
+
});
|
|
613
|
+
spinner.stop();
|
|
614
|
+
if (globalOpts.json) {
|
|
615
|
+
console.log(JSON.stringify(response, null, 2));
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
success(`Project created with ID: ${response.id}`);
|
|
619
|
+
})
|
|
620
|
+
);
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// src/commands/project/index.ts
|
|
624
|
+
function registerProjectCommands(program2) {
|
|
625
|
+
const project = program2.command("project").description("Manage projects");
|
|
626
|
+
project.addCommand(listCommand2());
|
|
627
|
+
project.addCommand(getCommand2());
|
|
628
|
+
project.addCommand(createCommand());
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// src/commands/run/index.ts
|
|
632
|
+
import { spawn } from "node:child_process";
|
|
633
|
+
import ora8 from "ora";
|
|
634
|
+
import R45 from "r4-sdk";
|
|
635
|
+
function registerRunCommand(program2) {
|
|
636
|
+
program2.command("run").description("Run a command with vault secrets injected as environment variables").argument("<command...>", "Command and arguments to execute").option("--prefix <prefix>", "Add prefix to all injected env var names").action(
|
|
637
|
+
withErrorHandler(
|
|
638
|
+
async (commandParts, opts, cmd) => {
|
|
639
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
640
|
+
const config = resolveAuth(globalOpts);
|
|
641
|
+
const spinner = ora8("Loading vault secrets...").start();
|
|
642
|
+
const r4 = await R45.create(config);
|
|
643
|
+
spinner.stop();
|
|
644
|
+
const env = r4.env;
|
|
645
|
+
const secretEnv = {};
|
|
646
|
+
for (const key of Object.keys(env)) {
|
|
647
|
+
const envName = opts.prefix ? `${opts.prefix.toUpperCase()}_${key}` : key;
|
|
648
|
+
secretEnv[envName] = env[key];
|
|
649
|
+
}
|
|
650
|
+
const [command, ...args] = commandParts;
|
|
651
|
+
const child = spawn(command, args, {
|
|
652
|
+
stdio: "inherit",
|
|
653
|
+
env: { ...process.env, ...secretEnv },
|
|
654
|
+
shell: true
|
|
655
|
+
});
|
|
656
|
+
child.on("close", (code) => {
|
|
657
|
+
process.exit(code ?? 1);
|
|
658
|
+
});
|
|
659
|
+
child.on("error", (err) => {
|
|
660
|
+
throw new Error(`Failed to execute command "${command}": ${err.message}`);
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
)
|
|
664
|
+
);
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
// src/index.ts
|
|
668
|
+
var program = new Command12();
|
|
669
|
+
program.name("r4").description("R4 CLI \u2014 manage vaults, projects, and secrets from the terminal").version("0.0.1").option("--api-key <key>", "API key (overrides R4_API_KEY env var and config file)").option("--project-id <id>", "Project ID (overrides R4_PROJECT_ID env var and config file)").option("--base-url <url>", "API base URL (default: https://r4.dev)").option("--json", "Output as JSON for scripting and piping", false);
|
|
670
|
+
registerAuthCommands(program);
|
|
671
|
+
registerVaultCommands(program);
|
|
672
|
+
registerProjectCommands(program);
|
|
673
|
+
registerRunCommand(program);
|
|
674
|
+
program.parse();
|
|
675
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/auth/login.ts","../src/lib/config.ts","../src/lib/output.ts","../src/lib/errors.ts","../src/commands/auth/logout.ts","../src/commands/auth/status.ts","../src/commands/auth/whoami.ts","../src/commands/auth/index.ts","../src/commands/vault/list.ts","../src/lib/resolve-auth.ts","../src/commands/vault/get.ts","../src/commands/vault/items.ts","../src/commands/vault/search.ts","../src/commands/vault/index.ts","../src/commands/project/list.ts","../src/lib/client.ts","../src/commands/project/get.ts","../src/commands/project/create.ts","../src/commands/project/index.ts","../src/commands/run/index.ts"],"sourcesContent":["import { Command } from 'commander'\nimport { registerAuthCommands } from './commands/auth/index.js'\nimport { registerVaultCommands } from './commands/vault/index.js'\nimport { registerProjectCommands } from './commands/project/index.js'\nimport { registerRunCommand } from './commands/run/index.js'\n\n/**\n * R4 CLI entry point.\n *\n * Sets up the commander program with global options and command groups:\n * - auth: Manage API key authentication\n * - vault: Manage vault secrets\n * - project: Manage projects\n * - run: Execute commands with vault secrets injected as env vars\n */\nconst program = new Command()\n\nprogram\n .name('r4')\n .description('R4 CLI — manage vaults, projects, and secrets from the terminal')\n .version('0.0.1')\n .option('--api-key <key>', 'API key (overrides R4_API_KEY env var and config file)')\n .option('--project-id <id>', 'Project ID (overrides R4_PROJECT_ID env var and config file)')\n .option('--base-url <url>', 'API base URL (default: https://r4.dev)')\n .option('--json', 'Output as JSON for scripting and piping', false)\n\nregisterAuthCommands(program)\nregisterVaultCommands(program)\nregisterProjectCommands(program)\nregisterRunCommand(program)\n\nprogram.parse()\n","import { Command } from 'commander'\nimport readline from 'node:readline'\nimport { loadConfig, saveConfig, getConfigPath } from '../../lib/config.js'\nimport { success, warn } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/**\n * Prompt the user for input via stdin.\n * Used when no --api-key flag is provided.\n */\nfunction prompt(question: string): Promise<string> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout })\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close()\n resolve(answer.trim())\n })\n })\n}\n\n/** r4 auth login — Save API key to config file */\nexport function loginCommand(): Command {\n return new Command('login')\n .description('Save your API key to the config file')\n .action(\n withErrorHandler(async (_opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n\n let apiKey = globalOpts.apiKey || process.env.R4_API_KEY\n\n if (!apiKey) {\n apiKey = await prompt('Enter your R4 API key: ')\n }\n\n if (!apiKey) {\n throw new Error('No API key provided.')\n }\n\n if (!apiKey.includes('.')) {\n warn('API key format is usually {accessKey}.{secret}')\n }\n\n const config = loadConfig()\n config.apiKey = apiKey\n\n if (globalOpts.baseUrl) {\n config.baseUrl = globalOpts.baseUrl\n }\n\n saveConfig(config)\n success(`API key saved to ${getConfigPath()}`)\n }),\n )\n}\n","import fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\nimport type { R4ConfigFile } from '../types.js'\n\nconst CONFIG_DIR = path.join(os.homedir(), '.r4')\nconst CONFIG_PATH = path.join(CONFIG_DIR, 'config.json')\n\n/**\n * Load the R4 config file from ~/.r4/config.json.\n * Returns an empty object if the file does not exist or is invalid.\n */\nexport function loadConfig(): R4ConfigFile {\n try {\n const raw = fs.readFileSync(CONFIG_PATH, 'utf8')\n return JSON.parse(raw) as R4ConfigFile\n } catch {\n return {}\n }\n}\n\n/**\n * Save the R4 config file to ~/.r4/config.json.\n * Creates the ~/.r4 directory if it does not exist.\n */\nexport function saveConfig(config: R4ConfigFile): void {\n fs.mkdirSync(CONFIG_DIR, { recursive: true })\n fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + '\\n', 'utf8')\n}\n\n/**\n * Remove the R4 config file.\n */\nexport function clearConfig(): void {\n try {\n fs.unlinkSync(CONFIG_PATH)\n } catch {\n // File doesn't exist, nothing to do\n }\n}\n\n/**\n * Get the path to the config file (for display purposes).\n */\nexport function getConfigPath(): string {\n return CONFIG_PATH\n}\n","import chalk from 'chalk'\nimport Table from 'cli-table3'\n\n/**\n * Print data as a formatted table, or as JSON if --json flag is set.\n */\nexport function printTable(\n headers: string[],\n rows: string[][],\n jsonMode: boolean,\n jsonData?: unknown,\n): void {\n if (jsonMode) {\n console.log(JSON.stringify(jsonData ?? rows, null, 2))\n return\n }\n\n const table = new Table({\n head: headers.map((h) => chalk.cyan(h)),\n style: { head: [], border: [] },\n })\n for (const row of rows) {\n table.push(row)\n }\n console.log(table.toString())\n}\n\n/**\n * Print a key-value detail view.\n */\nexport function printDetail(\n entries: [string, string | null | undefined][],\n jsonMode: boolean,\n jsonData?: unknown,\n): void {\n if (jsonMode) {\n console.log(JSON.stringify(jsonData, null, 2))\n return\n }\n\n const maxLen = Math.max(...entries.map(([k]) => k.length))\n for (const [key, value] of entries) {\n const label = chalk.gray(key.padEnd(maxLen))\n const val = value ?? chalk.dim('(empty)')\n console.log(` ${label} ${val}`)\n }\n}\n\n/** Print a success message */\nexport function success(message: string): void {\n console.log(chalk.green('✓') + ' ' + message)\n}\n\n/** Print a warning */\nexport function warn(message: string): void {\n console.log(chalk.yellow('!') + ' ' + message)\n}\n\n/** Print an error message to stderr */\nexport function printError(message: string): void {\n console.error(chalk.red('✗') + ' ' + message)\n}\n","import { printError } from './output.js'\n\n/**\n * Wrap a command handler to catch errors and exit with proper codes.\n * Formats R4 API errors and auth errors with helpful messages.\n */\nexport function withErrorHandler<T extends unknown[]>(\n fn: (...args: T) => Promise<void>,\n): (...args: T) => Promise<void> {\n return async (...args: T) => {\n try {\n await fn(...args)\n } catch (err) {\n if (err instanceof Error) {\n printError(err.message)\n } else {\n printError('An unexpected error occurred')\n }\n process.exit(1)\n }\n }\n}\n","import { Command } from 'commander'\nimport { clearConfig, getConfigPath } from '../../lib/config.js'\nimport { success } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\n\n/** r4 auth logout — Remove saved credentials */\nexport function logoutCommand(): Command {\n return new Command('logout')\n .description('Remove saved API key from the config file')\n .action(\n withErrorHandler(async () => {\n clearConfig()\n success(`Config removed from ${getConfigPath()}`)\n }),\n )\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport { loadConfig, getConfigPath } from '../../lib/config.js'\nimport { printDetail } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/** Mask an API key for display, showing only the first 8 characters */\nfunction maskKey(key: string): string {\n if (key.length <= 8) return key\n return key.substring(0, 8) + '...'\n}\n\n/** r4 auth status — Show current auth status */\nexport function statusCommand(): Command {\n return new Command('status')\n .description('Show current authentication status')\n .action(\n withErrorHandler(async (_opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = loadConfig()\n\n let source: string\n let apiKey: string | undefined\n\n if (globalOpts.apiKey) {\n source = '--api-key flag'\n apiKey = globalOpts.apiKey\n } else if (process.env.R4_API_KEY) {\n source = 'R4_API_KEY env var'\n apiKey = process.env.R4_API_KEY\n } else if (config.apiKey) {\n source = `config file (${getConfigPath()})`\n apiKey = config.apiKey\n } else {\n source = 'none'\n }\n\n if (globalOpts.json) {\n console.log(\n JSON.stringify(\n {\n authenticated: !!apiKey,\n source,\n apiKey: apiKey ? maskKey(apiKey) : null,\n baseUrl: globalOpts.baseUrl || process.env.R4_BASE_URL || config.baseUrl || 'https://r4.dev',\n },\n null,\n 2,\n ),\n )\n return\n }\n\n console.log()\n if (apiKey) {\n console.log(chalk.bold(' Authenticated'))\n console.log()\n printDetail(\n [\n ['Source', source],\n ['API Key', maskKey(apiKey)],\n [\n 'Base URL',\n globalOpts.baseUrl || process.env.R4_BASE_URL || config.baseUrl || 'https://r4.dev',\n ],\n ],\n false,\n )\n } else {\n console.log(chalk.bold(' Not authenticated'))\n console.log()\n console.log(' Run ' + chalk.cyan('r4 auth login') + ' to save your API key.')\n }\n console.log()\n }),\n )\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport { loadConfig, getConfigPath } from '../../lib/config.js'\nimport { printDetail } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/** Mask an API key for display, showing only the first 8 characters */\nfunction maskKey(key: string): string {\n if (key.length <= 8) return key\n return key.substring(0, 8) + '...'\n}\n\n/**\n * r4 auth whoami — Show the current authenticated identity.\n * Displays the resolved org context, project ID, and base URL\n * based on CLI flags, environment variables, and config file.\n */\nexport function whoamiCommand(): Command {\n return new Command('whoami')\n .description('Show current authenticated identity')\n .action(\n withErrorHandler(async (_opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = loadConfig()\n\n const apiKey = globalOpts.apiKey || process.env.R4_API_KEY || config.apiKey\n const projectId = globalOpts.projectId || process.env.R4_PROJECT_ID || config.projectId\n const baseUrl =\n globalOpts.baseUrl || process.env.R4_BASE_URL || config.baseUrl || 'https://r4.dev'\n\n if (globalOpts.json) {\n console.log(\n JSON.stringify(\n {\n authenticated: !!apiKey,\n apiKey: apiKey ? maskKey(apiKey) : null,\n projectId: projectId || null,\n baseUrl,\n configPath: getConfigPath(),\n },\n null,\n 2,\n ),\n )\n return\n }\n\n console.log()\n if (!apiKey) {\n console.log(chalk.bold(' Not authenticated'))\n console.log()\n console.log(' Run ' + chalk.cyan('r4 auth login') + ' to save your API key.')\n console.log()\n return\n }\n\n console.log(chalk.bold(' Authenticated'))\n console.log()\n printDetail(\n [\n ['API Key', maskKey(apiKey)],\n ['Project ID', projectId || chalk.dim('(not set)')],\n ['Base URL', baseUrl],\n ['Config File', getConfigPath()],\n ],\n false,\n )\n console.log()\n }),\n )\n}\n","import type { Command } from 'commander'\nimport { loginCommand } from './login.js'\nimport { logoutCommand } from './logout.js'\nimport { statusCommand } from './status.js'\nimport { whoamiCommand } from './whoami.js'\n\n/** Register auth subcommands on the CLI program */\nexport function registerAuthCommands(program: Command): void {\n const auth = program.command('auth').description('Manage API key authentication')\n\n auth.addCommand(loginCommand())\n auth.addCommand(logoutCommand())\n auth.addCommand(statusCommand())\n auth.addCommand(whoamiCommand())\n}\n","import { Command } from 'commander'\nimport ora from 'ora'\nimport R4 from 'r4-sdk'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { printTable } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/**\n * r4 vault list — List all project environment variables as a table.\n * Uses the R4 SDK env endpoint to fetch a flat key-value map.\n */\nexport function listCommand(): Command {\n return new Command('list')\n .description('List all project environment variables')\n .action(\n withErrorHandler(async (_opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n\n const spinner = ora('Fetching environment variables...').start()\n const r4 = await R4.create(config)\n spinner.stop()\n\n const env = r4.env\n const keys = Object.keys(env).sort()\n\n if (globalOpts.json) {\n console.log(JSON.stringify(env, null, 2))\n return\n }\n\n if (keys.length === 0) {\n console.log('\\n No environment variables found.\\n')\n return\n }\n\n const rows = keys.map((key) => [key, env[key]])\n\n console.log()\n printTable(['Key', 'Value'], rows, false)\n console.log()\n }),\n )\n}\n","import type { R4Config } from 'r4-sdk'\nimport type { GlobalOptions } from '../types.js'\nimport { loadConfig } from './config.js'\n\n/**\n * Resolve R4 SDK configuration from CLI flags, environment variables, and config file.\n *\n * Precedence (highest to lowest):\n * 1. CLI flags (--api-key, --base-url, --project-id)\n * 2. Environment variables (R4_API_KEY, R4_BASE_URL, R4_PROJECT_ID)\n * 3. Config file (~/.r4/config.json)\n * 4. Defaults (baseUrl: https://r4.dev)\n *\n * Throws if no API key or project ID is found from any source.\n */\nexport function resolveAuth(opts: GlobalOptions): R4Config {\n const config = loadConfig()\n\n const apiKey = opts.apiKey || process.env.R4_API_KEY || config.apiKey\n if (!apiKey) {\n throw new Error(\n 'No API key found. Provide one via:\\n' +\n ' --api-key <key> CLI flag\\n' +\n ' R4_API_KEY environment variable\\n' +\n ' r4 auth login save to config file',\n )\n }\n\n const projectId = opts.projectId || process.env.R4_PROJECT_ID || config.projectId\n if (!projectId) {\n throw new Error(\n 'No project ID found. Provide one via:\\n' +\n ' --project-id <id> CLI flag\\n' +\n ' R4_PROJECT_ID environment variable\\n' +\n ' ~/.r4/config.json config file (projectId field)',\n )\n }\n\n const baseUrl = opts.baseUrl || process.env.R4_BASE_URL || config.baseUrl || 'https://r4.dev'\n\n return { apiKey, projectId, baseUrl }\n}\n","import { Command } from 'commander'\nimport ora from 'ora'\nimport R4 from 'r4-sdk'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/**\n * r4 vault get <KEY> — Get a specific environment variable value.\n * Outputs the raw value, perfect for piping: r4 vault get PRODUCTION_DB_PASSWORD | pbcopy\n */\nexport function getCommand(): Command {\n return new Command('get')\n .description('Get a specific environment variable value')\n .argument('<key>', 'Environment variable key (SCREAMING_SNAKE_CASE)')\n .action(\n withErrorHandler(\n async (keyArg: string, _opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n\n const spinner = ora('Fetching environment variables...').start()\n const r4 = await R4.create(config)\n spinner.stop()\n\n const env = r4.env\n const key = keyArg.toUpperCase()\n const value = env[key]\n\n if (value === undefined) {\n const available = Object.keys(env).sort().join(', ') || '(none)'\n throw new Error(`Key \"${key}\" not found. Available keys: ${available}`)\n }\n\n if (globalOpts.json) {\n console.log(JSON.stringify({ key, value }, null, 2))\n return\n }\n\n // Raw output — perfect for piping: r4 vault get PRODUCTION_DB_PASSWORD | pbcopy\n process.stdout.write(value)\n },\n ),\n )\n}\n","import { Command } from 'commander'\nimport ora from 'ora'\nimport R4 from 'r4-sdk'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { printTable } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/**\n * Represents a vault item derived from environment variable keys.\n * Groups related fields that share the same item name prefix.\n */\ninterface VaultItem {\n name: string\n fields: { name: string; key: string }[]\n}\n\n/**\n * Derive vault items from a flat env map.\n *\n * Env keys follow the pattern: ITEM_NAME_FIELD_NAME (SCREAMING_SNAKE_CASE).\n * Since we only have the flat map, we group by common prefix heuristic:\n * - Each unique env key is treated as a single-field item\n * - The full key is the item name\n *\n * This provides a useful overview of all available secrets.\n */\nfunction deriveItems(env: Record<string, string>): VaultItem[] {\n const keys = Object.keys(env).sort()\n return keys.map((key) => ({\n name: key,\n fields: [{ name: key, key }],\n }))\n}\n\n/**\n * r4 vault items — List all vault items with their field names and types.\n * Uses the R4 SDK env endpoint to fetch variables and groups them by item.\n */\nexport function itemsCommand(): Command {\n return new Command('items')\n .description('List all vault items with their field names and types')\n .action(\n withErrorHandler(async (_opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n\n const spinner = ora('Fetching vault items...').start()\n const r4 = await R4.create(config)\n spinner.stop()\n\n const env = r4.env\n const items = deriveItems(env)\n\n if (globalOpts.json) {\n console.log(JSON.stringify(items, null, 2))\n return\n }\n\n if (items.length === 0) {\n console.log('\\n No vault items found.\\n')\n return\n }\n\n const rows = items.map((item) => [\n item.name,\n 'secret',\n item.fields.map((f) => f.name).join(', '),\n ])\n\n console.log()\n printTable(['Name', 'Type', 'Fields'], rows, false)\n console.log()\n }),\n )\n}\n","import { Command } from 'commander'\nimport ora from 'ora'\nimport R4 from 'r4-sdk'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { printTable } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/**\n * r4 vault search <query> — Search vault items by name (case-insensitive).\n * Matches env variable keys that contain the search query.\n * Useful for finding secrets when you know part of the name.\n */\nexport function searchCommand(): Command {\n return new Command('search')\n .description('Search vault items by name')\n .argument('<query>', 'Search query (case-insensitive match against key names)')\n .action(\n withErrorHandler(\n async (query: string, _opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n\n const spinner = ora('Searching vault items...').start()\n const r4 = await R4.create(config)\n spinner.stop()\n\n const env = r4.env\n const lowerQuery = query.toLowerCase()\n\n const matches = Object.keys(env)\n .filter((key) => key.toLowerCase().includes(lowerQuery))\n .sort()\n\n if (globalOpts.json) {\n const result = matches.map((key) => ({ key, value: env[key] }))\n console.log(JSON.stringify(result, null, 2))\n return\n }\n\n if (matches.length === 0) {\n console.log(`\\n No items matching \"${query}\" found.\\n`)\n return\n }\n\n const rows = matches.map((key) => [key, env[key]])\n\n console.log()\n printTable(['Key', 'Value'], rows, false)\n console.log()\n },\n ),\n )\n}\n","import type { Command } from 'commander'\nimport { listCommand } from './list.js'\nimport { getCommand } from './get.js'\nimport { itemsCommand } from './items.js'\nimport { searchCommand } from './search.js'\n\n/** Register vault subcommands on the CLI program */\nexport function registerVaultCommands(program: Command): void {\n const vault = program.command('vault').description('Manage vault secrets')\n\n vault.addCommand(listCommand())\n vault.addCommand(getCommand())\n vault.addCommand(itemsCommand())\n vault.addCommand(searchCommand())\n}\n","import { Command } from 'commander'\nimport ora from 'ora'\nimport { CliClient } from '../../lib/client.js'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { printTable } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/** r4 project list — List all projects as a table */\nexport function listCommand(): Command {\n return new Command('list')\n .description('List all projects')\n .action(\n withErrorHandler(async (_opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n const client = new CliClient(config.apiKey, config.baseUrl || 'https://r4.dev')\n\n const spinner = ora('Fetching projects...').start()\n const response = await client.listProjects()\n spinner.stop()\n\n const rows = response.projects.map((p) => [\n p.id,\n p.name,\n p.externalId || '-',\n String(p.vaultsCount),\n String(p.licensesCount),\n String(p.licenseGroupsCount),\n ])\n\n console.log()\n printTable(\n ['ID', 'Name', 'External ID', 'Vaults', 'Licenses', 'License Groups'],\n rows,\n !!globalOpts.json,\n response.projects,\n )\n console.log()\n }),\n )\n}\n","import type {\n ProjectListResponse,\n ProjectDetail,\n CreateProjectRequest,\n CreateProjectResponse,\n} from '../types.js'\n\n/**\n * HTTP client for machine API endpoints not covered by the r4-sdk.\n * Follows the same fetch + X-API-Key pattern as the SDK's R4Client.\n */\nexport class CliClient {\n private apiKey: string\n private baseUrl: string\n\n constructor(apiKey: string, baseUrl: string) {\n this.apiKey = apiKey\n this.baseUrl = baseUrl.replace(/\\/$/, '')\n }\n\n /**\n * Make an authenticated request to the machine API.\n * Handles error responses consistently with the SDK pattern.\n */\n private async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`\n\n const response = await fetch(url, {\n method,\n headers: {\n 'X-API-Key': this.apiKey,\n 'Content-Type': 'application/json',\n },\n body: body ? JSON.stringify(body) : undefined,\n })\n\n if (!response.ok) {\n const errorBody = (await response.json().catch(() => ({}))) as Record<string, unknown>\n const error = errorBody?.error as Record<string, unknown> | undefined\n const errorMessage = error?.message || `HTTP ${response.status}: ${response.statusText}`\n throw new Error(`R4 API Error: ${errorMessage}`)\n }\n\n return response.json() as Promise<T>\n }\n\n /** List all projects. GET /api/v1/machine/project */\n async listProjects(): Promise<ProjectListResponse> {\n return this.request<ProjectListResponse>('GET', '/api/v1/machine/project')\n }\n\n /** Get project details. GET /api/v1/machine/project/:id */\n async getProject(id: string): Promise<ProjectDetail> {\n return this.request<ProjectDetail>('GET', `/api/v1/machine/project/${id}`)\n }\n\n /** Create a new project. POST /api/v1/machine/project */\n async createProject(data: CreateProjectRequest): Promise<CreateProjectResponse> {\n return this.request<CreateProjectResponse>('POST', '/api/v1/machine/project', data)\n }\n}\n","import { Command } from 'commander'\nimport chalk from 'chalk'\nimport ora from 'ora'\nimport { CliClient } from '../../lib/client.js'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { printDetail, printTable } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/** r4 project get <id> — Show project details with associated resources */\nexport function getCommand(): Command {\n return new Command('get')\n .description('Get project details')\n .argument('<id>', 'Project ID')\n .action(\n withErrorHandler(async (id: string, _opts: unknown, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n const client = new CliClient(config.apiKey, config.baseUrl || 'https://r4.dev')\n\n const spinner = ora('Fetching project...').start()\n const project = await client.getProject(id)\n spinner.stop()\n\n if (globalOpts.json) {\n console.log(JSON.stringify(project, null, 2))\n return\n }\n\n console.log()\n console.log(chalk.bold(` ${project.name}`))\n console.log()\n\n printDetail(\n [\n ['ID', project.id],\n ['External ID', project.externalId],\n ['Description', project.description],\n ['Created At', project.createdAt],\n ['Vaults', String(project.vaultsCount)],\n ['Licenses', String(project.licensesCount)],\n ['License Groups', String(project.licenseGroupsCount)],\n ],\n false,\n )\n\n if (project.vaults.length > 0) {\n console.log()\n console.log(chalk.bold(' Vaults'))\n console.log()\n printTable(\n ['ID', 'Name', 'Encrypted'],\n project.vaults.map((v) => [v.id, v.name, v.isEncrypted ? 'Yes' : 'No']),\n false,\n )\n }\n\n if (project.licenses.length > 0) {\n console.log()\n console.log(chalk.bold(' Licenses'))\n console.log()\n printTable(\n ['ID', 'Name', 'Type'],\n project.licenses.map((l) => [l.id, l.name || '-', l.type]),\n false,\n )\n }\n\n if (project.licenseGroups.length > 0) {\n console.log()\n console.log(chalk.bold(' License Groups'))\n console.log()\n printTable(\n ['ID', 'Name'],\n project.licenseGroups.map((lg) => [lg.id, lg.name]),\n false,\n )\n }\n\n console.log()\n }),\n )\n}\n","import { Command } from 'commander'\nimport readline from 'node:readline'\nimport ora from 'ora'\nimport { CliClient } from '../../lib/client.js'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { success } from '../../lib/output.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/** Prompt the user for input via stdin */\nfunction prompt(question: string): Promise<string> {\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout })\n return new Promise((resolve) => {\n rl.question(question, (answer) => {\n rl.close()\n resolve(answer.trim())\n })\n })\n}\n\n/** r4 project create — Create a new project */\nexport function createCommand(): Command {\n return new Command('create')\n .description('Create a new project')\n .option('--name <name>', 'Project name')\n .option('--description <description>', 'Project description')\n .option('--external-id <externalId>', 'External identifier')\n .action(\n withErrorHandler(async (opts: { name?: string; description?: string; externalId?: string }, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n const client = new CliClient(config.apiKey, config.baseUrl || 'https://r4.dev')\n\n let name = opts.name\n if (!name) {\n name = await prompt('Project name: ')\n }\n if (!name) {\n throw new Error('Project name is required.')\n }\n\n const spinner = ora('Creating project...').start()\n const response = await client.createProject({\n name,\n description: opts.description,\n externalId: opts.externalId,\n })\n spinner.stop()\n\n if (globalOpts.json) {\n console.log(JSON.stringify(response, null, 2))\n return\n }\n\n success(`Project created with ID: ${response.id}`)\n }),\n )\n}\n","import type { Command } from 'commander'\nimport { listCommand } from './list.js'\nimport { getCommand } from './get.js'\nimport { createCommand } from './create.js'\n\n/** Register project subcommands on the CLI program */\nexport function registerProjectCommands(program: Command): void {\n const project = program.command('project').description('Manage projects')\n\n project.addCommand(listCommand())\n project.addCommand(getCommand())\n project.addCommand(createCommand())\n}\n","import { Command } from 'commander'\nimport { spawn } from 'node:child_process'\nimport ora from 'ora'\nimport R4 from 'r4-sdk'\nimport { resolveAuth } from '../../lib/resolve-auth.js'\nimport { withErrorHandler } from '../../lib/errors.js'\nimport type { GlobalOptions } from '../../types.js'\n\n/**\n * r4 run <command...> — Run a command with vault secrets injected as environment variables.\n *\n * Env var naming: SCREAMING_SNAKE_CASE keys from the project env endpoint.\n *\n * Examples:\n * r4 run --project-id abc123 node deploy.js\n * r4 run --prefix R4 -- docker compose up\n */\nexport function registerRunCommand(program: Command): void {\n program\n .command('run')\n .description('Run a command with vault secrets injected as environment variables')\n .argument('<command...>', 'Command and arguments to execute')\n .option('--prefix <prefix>', 'Add prefix to all injected env var names')\n .action(\n withErrorHandler(\n async (commandParts: string[], opts: { prefix?: string }, cmd: Command) => {\n const globalOpts = cmd.optsWithGlobals<GlobalOptions>()\n const config = resolveAuth(globalOpts)\n\n // 1. Fetch project env vars via the R4 SDK\n const spinner = ora('Loading vault secrets...').start()\n const r4 = await R4.create(config)\n spinner.stop()\n\n const env = r4.env\n\n // 2. Build environment variable map (optionally with prefix)\n const secretEnv: Record<string, string> = {}\n\n for (const key of Object.keys(env)) {\n const envName = opts.prefix\n ? `${opts.prefix.toUpperCase()}_${key}`\n : key\n secretEnv[envName] = env[key]\n }\n\n // 3. Spawn the child process with merged environment\n const [command, ...args] = commandParts\n const child = spawn(command, args, {\n stdio: 'inherit',\n env: { ...process.env, ...secretEnv },\n shell: true,\n })\n\n // 4. Forward the child's exit code\n child.on('close', (code) => {\n process.exit(code ?? 1)\n })\n\n child.on('error', (err) => {\n throw new Error(`Failed to execute command \"${command}\": ${err.message}`)\n })\n },\n ),\n )\n}\n"],"mappings":"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","names":["Command","Command","Command","Command","chalk","Command","chalk","Command","chalk","maskKey","Command","chalk","program","Command","Command","Command","ora","R4","Command","ora","R4","Command","ora","R4","Command","ora","R4","Command","ora","R4","Command","ora","R4","program","Command","ora","path","listCommand","Command","ora","Command","chalk","ora","getCommand","Command","ora","chalk","Command","readline","ora","prompt","readline","Command","ora","program","listCommand","getCommand","ora","R4","program","ora","R4","Command"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@r4security/cli",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Official R4 CLI — manage vaults, projects, and secrets from the terminal",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"r4": "./lib/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"lib"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsup",
|
|
14
|
+
"clean": "rm -rf lib",
|
|
15
|
+
"dev": "tsup --watch"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"r4",
|
|
19
|
+
"cli",
|
|
20
|
+
"vault",
|
|
21
|
+
"secrets",
|
|
22
|
+
"devops",
|
|
23
|
+
"secret-management"
|
|
24
|
+
],
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18.0.0"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"r4-sdk": "workspace:*",
|
|
34
|
+
"commander": "^12.0.0",
|
|
35
|
+
"chalk": "^5.3.0",
|
|
36
|
+
"cli-table3": "^0.6.4",
|
|
37
|
+
"ora": "^8.0.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/node": "^20.11.24",
|
|
41
|
+
"tsup": "8.2.4",
|
|
42
|
+
"typescript": "5.5.3"
|
|
43
|
+
}
|
|
44
|
+
}
|