xtra-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +87 -0
  3. package/dist/bin/xtra.js +138 -0
  4. package/dist/commands/access.js +184 -0
  5. package/dist/commands/admin.js +118 -0
  6. package/dist/commands/audit.js +67 -0
  7. package/dist/commands/branch.js +212 -0
  8. package/dist/commands/checkout.js +73 -0
  9. package/dist/commands/ci.js +341 -0
  10. package/dist/commands/completion.js +227 -0
  11. package/dist/commands/diff.js +162 -0
  12. package/dist/commands/doctor.js +164 -0
  13. package/dist/commands/env.js +70 -0
  14. package/dist/commands/export.js +83 -0
  15. package/dist/commands/generate.js +179 -0
  16. package/dist/commands/history.js +77 -0
  17. package/dist/commands/import.js +121 -0
  18. package/dist/commands/init.js +205 -0
  19. package/dist/commands/integration.js +188 -0
  20. package/dist/commands/local.js +198 -0
  21. package/dist/commands/login.js +198 -0
  22. package/dist/commands/login.test.js +51 -0
  23. package/dist/commands/logs.js +121 -0
  24. package/dist/commands/profile.js +184 -0
  25. package/dist/commands/project.js +165 -0
  26. package/dist/commands/rollback.js +95 -0
  27. package/dist/commands/rotate.js +93 -0
  28. package/dist/commands/run.js +215 -0
  29. package/dist/commands/scan.js +127 -0
  30. package/dist/commands/secrets.js +305 -0
  31. package/dist/commands/simulate.js +109 -0
  32. package/dist/commands/status.js +93 -0
  33. package/dist/commands/template.js +276 -0
  34. package/dist/commands/ui.js +289 -0
  35. package/dist/commands/watch.js +123 -0
  36. package/dist/lib/api.js +187 -0
  37. package/dist/lib/api.test.js +89 -0
  38. package/dist/lib/audit.js +136 -0
  39. package/dist/lib/config.js +70 -0
  40. package/dist/lib/config.test.js +47 -0
  41. package/dist/lib/crypto.js +50 -0
  42. package/dist/lib/manifest.js +52 -0
  43. package/dist/lib/profiles.js +103 -0
  44. package/package.json +67 -0
@@ -0,0 +1,289 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.uiCommand = void 0;
40
+ const commander_1 = require("commander");
41
+ const chalk_1 = __importDefault(require("chalk"));
42
+ const readline = __importStar(require("readline"));
43
+ const api_1 = require("../lib/api");
44
+ const config_1 = require("../lib/config");
45
+ const ENVS = ["development", "staging", "production"];
46
+ const ENV_COLORS = {
47
+ development: chalk_1.default.green,
48
+ staging: chalk_1.default.yellow,
49
+ production: chalk_1.default.red,
50
+ };
51
+ const W = process.stdout.columns || 120;
52
+ // ─── Box Drawing Helpers ─────────────────────────────────────────────────────
53
+ const B = {
54
+ tl: "╭", tr: "╮", bl: "╰", br: "╯",
55
+ h: "─", v: "│", x: "┼",
56
+ lt: "├", rt: "┤", tt: "┬", bt: "┴",
57
+ };
58
+ function hline(width, c = B.h) { return c.repeat(width); }
59
+ function box(title, lines, width, active) {
60
+ const border = active ? chalk_1.default.cyan : chalk_1.default.hex("#2d3a4d");
61
+ const inner = width - 2;
62
+ const pad = (s) => s.padEnd(inner).slice(0, inner);
63
+ const label = active
64
+ ? chalk_1.default.bold.cyan(` ${title} `)
65
+ : chalk_1.default.hex("#4a5568")(` ${title} `);
66
+ const titleLine = border(B.tl) + label + border(hline(inner - title.length - 2)) + border(B.tr);
67
+ const body = lines.map(l => border(B.v) + l.slice(0, inner).padEnd(inner) + border(B.v));
68
+ const foot = border(B.bl) + border(hline(inner)) + border(B.br);
69
+ return [titleLine, ...body, foot];
70
+ }
71
+ function clear() { process.stdout.write("\x1B[H\x1B[2J\x1B[3J"); }
72
+ // ─── Main TUI ────────────────────────────────────────────────────────────────
73
+ async function runUI() {
74
+ let panel = "projects";
75
+ let projects = [];
76
+ let projIdx = 0;
77
+ let envIdx = 0;
78
+ let secrets = [];
79
+ let secIdx = 0;
80
+ let status = "Loading…";
81
+ let loading = false;
82
+ let showValues = false;
83
+ // ── Loaders ────────────────────────────────────────────────────────────────
84
+ async function loadProjects() {
85
+ status = "Loading projects…";
86
+ draw();
87
+ try {
88
+ const raw = await api_1.api.getProjects();
89
+ projects = Array.isArray(raw) ? raw : raw.projects ?? [];
90
+ status = projects.length > 0
91
+ ? `${projects.length} project(s) found · ↑↓ navigate · Enter to load secrets`
92
+ : "No projects found. Run `xtra login` first.";
93
+ }
94
+ catch (e) {
95
+ status = chalk_1.default.red(`✗ ${e.message}`);
96
+ }
97
+ draw();
98
+ }
99
+ async function loadSecrets() {
100
+ if (!projects[projIdx])
101
+ return;
102
+ loading = true;
103
+ status = `Fetching secrets for ${chalk_1.default.cyan(projects[projIdx].name)} / ${ENV_COLORS[ENVS[envIdx]](ENVS[envIdx])}…`;
104
+ draw();
105
+ try {
106
+ const rc = (0, config_1.getRcConfig)();
107
+ const branch = rc.branch || "main";
108
+ const raw = await api_1.api.getSecrets(projects[projIdx].id, ENVS[envIdx], branch);
109
+ if (raw && typeof raw === "object" && !Array.isArray(raw)) {
110
+ secrets = Object.entries(raw).map(([key, value]) => ({
111
+ id: key, key, value: String(value), updatedAt: new Date().toISOString(),
112
+ }));
113
+ }
114
+ else if (Array.isArray(raw)) {
115
+ secrets = raw;
116
+ }
117
+ else {
118
+ secrets = [];
119
+ }
120
+ secIdx = 0;
121
+ status = secrets.length > 0
122
+ ? `${secrets.length} secret(s) · V toggle values · Tab switch panel · Q quit`
123
+ : "No secrets in this environment.";
124
+ }
125
+ catch (e) {
126
+ secrets = [];
127
+ status = chalk_1.default.red(`✗ ${e.message}`);
128
+ }
129
+ loading = false;
130
+ draw();
131
+ }
132
+ // ── Render ─────────────────────────────────────────────────────────────────
133
+ function draw() {
134
+ clear();
135
+ // ── Header ──────────────────────────────────────────────────────────────
136
+ const appTitle = chalk_1.default.bold.cyan(" 🔒 XtraSecurity") + chalk_1.default.hex("#4a5a6b")(" — Interactive Secrets Shell");
137
+ const env = ENV_COLORS[ENVS[envIdx]] ? ENV_COLORS[ENVS[envIdx]](ENVS[envIdx]) : chalk_1.default.white(ENVS[envIdx]);
138
+ const crumb = projects[projIdx]
139
+ ? chalk_1.default.hex("#4a5568")(` ${projects[projIdx].name} `) + chalk_1.default.hex("#4a5568")("/") + chalk_1.default.hex("#4a5568")(` ${ENVS[envIdx]}`)
140
+ : chalk_1.default.hex("#4a5568")(" No project selected");
141
+ console.log();
142
+ console.log(appTitle + chalk_1.default.hex("#2d3a4d")(" │") + crumb);
143
+ console.log(chalk_1.default.hex("#1e293b")(hline(W)));
144
+ console.log();
145
+ // ── Left column: Projects (22 chr) + Env (22 chr) ─────────────────────
146
+ const LEFT_W = 26;
147
+ const RIGHT_W = W - LEFT_W - 3;
148
+ // Projects panel
149
+ const projLines = (projects.length > 0 ? projects : [{ id: "", name: "(loading…)" }]).map((p, i) => {
150
+ const active = i === projIdx;
151
+ const icon = active ? chalk_1.default.cyan("▶ ") : " ";
152
+ const name = active && panel === "projects"
153
+ ? chalk_1.default.bold.bgCyan.black(` ${p.name} `.padEnd(LEFT_W - 4))
154
+ : active
155
+ ? chalk_1.default.bold.cyan(p.name)
156
+ : chalk_1.default.hex("#6b7c93")(p.name);
157
+ return ` ${icon}${name}`;
158
+ });
159
+ const projBox = box("PROJECTS", projLines, LEFT_W, panel === "projects");
160
+ // Env panel
161
+ const envLines = ENVS.map((e, i) => {
162
+ const active = i === envIdx;
163
+ const icon = active ? chalk_1.default.cyan("▶ ") : " ";
164
+ const col = ENV_COLORS[e] ?? chalk_1.default.white;
165
+ const name = active && panel === "env"
166
+ ? chalk_1.default.bold.bgCyan.black(` ${e} `.padEnd(LEFT_W - 4))
167
+ : active
168
+ ? col.bold(e)
169
+ : chalk_1.default.hex("#6b7c93")(e);
170
+ return ` ${icon}${name}`;
171
+ });
172
+ const envBox = box("ENVIRONMENT", envLines, LEFT_W, panel === "env");
173
+ // Secrets panel
174
+ const KW = Math.floor((RIGHT_W - 3) * 0.45);
175
+ const VW = Math.floor((RIGHT_W - 3) * 0.35);
176
+ const DW = RIGHT_W - KW - VW - 4;
177
+ const secHeader = chalk_1.default.bold.hex("#64748b")("KEY".padEnd(KW)) + " " + chalk_1.default.bold.hex("#64748b")("VALUE".padEnd(VW)) + " " + chalk_1.default.bold.hex("#64748b")("UPDATED".padEnd(DW));
178
+ const divider = chalk_1.default.hex("#1e293b")(hline(KW) + " " + hline(VW) + " " + hline(DW));
179
+ let secLines;
180
+ if (loading) {
181
+ secLines = [` ${chalk_1.default.cyan("⠋")} Loading…`];
182
+ }
183
+ else if (secrets.length === 0) {
184
+ secLines = [` ${chalk_1.default.hex("#4a5568")("No secrets in this environment.")}`];
185
+ }
186
+ else {
187
+ secLines = [" " + secHeader, " " + divider, ...secrets.map((s, i) => {
188
+ const sel = i === secIdx && panel === "secrets";
189
+ const key = s.key.padEnd(KW).slice(0, KW);
190
+ const val = showValues ? s.value.padEnd(VW).slice(0, VW) : "●".repeat(Math.min(8, VW)).padEnd(VW).slice(0, VW);
191
+ const dt = new Date(s.updatedAt).toLocaleDateString("en-GB", { day: "2-digit", month: "short" }).padEnd(DW);
192
+ if (sel) {
193
+ return chalk_1.default.bold.bgHex("#0e243e")(" ▶ " + chalk_1.default.cyan(key) + " " + chalk_1.default.greenBright(val) + " " + chalk_1.default.hex("#4a9eff")(dt) + " ");
194
+ }
195
+ return " " + chalk_1.default.white(key) + " " + chalk_1.default.hex("#4a5568")(val) + " " + chalk_1.default.hex("#374151")(dt);
196
+ })];
197
+ }
198
+ const secBox = box(`SECRETS (${secrets.length})`, secLines, RIGHT_W, panel === "secrets");
199
+ // ── Print side-by-side ────────────────────────────────────────────────
200
+ const leftPanel = [...projBox, ...["", ""], ...envBox];
201
+ const maxRows = Math.max(leftPanel.length, secBox.length);
202
+ const gap = chalk_1.default.hex("#1e293b")(" │ ");
203
+ for (let r = 0; r < maxRows; r++) {
204
+ const l = leftPanel[r] ?? " ".repeat(LEFT_W);
205
+ const rr = secBox[r] ?? " ".repeat(RIGHT_W);
206
+ console.log(l + gap + rr);
207
+ }
208
+ // ── Footer ───────────────────────────────────────────────────────────
209
+ console.log();
210
+ console.log(chalk_1.default.hex("#1e293b")(hline(W)));
211
+ const keys = [
212
+ [chalk_1.default.hex("#64748b")("↑↓"), "Navigate"],
213
+ [chalk_1.default.hex("#64748b")("Enter"), "Select"],
214
+ [chalk_1.default.hex("#64748b")("Tab"), "Switch Panel"],
215
+ [chalk_1.default.hex("#64748b")("V"), showValues ? chalk_1.default.green("Hide values") : chalk_1.default.yellow("Show values")],
216
+ [chalk_1.default.hex("#64748b")("Q"), "Quit"],
217
+ ].map(([k, a]) => `${k} ${chalk_1.default.hex("#374151")(a)}`).join(chalk_1.default.hex("#1e293b")(" · "));
218
+ console.log(" " + keys);
219
+ console.log();
220
+ console.log(" " + (status || ""));
221
+ }
222
+ // ── Keyboard ──────────────────────────────────────────────────────────────
223
+ readline.emitKeypressEvents(process.stdin);
224
+ if (process.stdin.isTTY)
225
+ process.stdin.setRawMode(true);
226
+ process.stdin.on("keypress", async (_str, key) => {
227
+ if (!key)
228
+ return;
229
+ // Quit
230
+ if (key.name === "q" || (key.ctrl && key.name === "c")) {
231
+ if (process.stdin.isTTY)
232
+ process.stdin.setRawMode(false);
233
+ clear();
234
+ console.log(chalk_1.default.cyan(" Goodbye! 👋\n"));
235
+ process.exit(0);
236
+ }
237
+ // Toggle secret values with V
238
+ if (key.name === "v") {
239
+ showValues = !showValues;
240
+ draw();
241
+ return;
242
+ }
243
+ // Tab cycle panels
244
+ if (key.name === "tab") {
245
+ panel = panel === "projects" ? "env" : panel === "env" ? "secrets" : "projects";
246
+ draw();
247
+ return;
248
+ }
249
+ if (panel === "projects") {
250
+ if (key.name === "up")
251
+ projIdx = Math.max(0, projIdx - 1);
252
+ if (key.name === "down")
253
+ projIdx = Math.min(projects.length - 1, projIdx + 1);
254
+ if (key.name === "return") {
255
+ panel = "env";
256
+ draw();
257
+ return;
258
+ }
259
+ }
260
+ if (panel === "env") {
261
+ if (key.name === "up")
262
+ envIdx = Math.max(0, envIdx - 1);
263
+ if (key.name === "down")
264
+ envIdx = Math.min(ENVS.length - 1, envIdx + 1);
265
+ if (key.name === "return") {
266
+ panel = "secrets";
267
+ await loadSecrets();
268
+ return;
269
+ }
270
+ }
271
+ if (panel === "secrets") {
272
+ if (key.name === "up")
273
+ secIdx = Math.max(0, secIdx - 1);
274
+ if (key.name === "down")
275
+ secIdx = Math.min(secrets.length - 1, secIdx + 1);
276
+ }
277
+ draw();
278
+ });
279
+ // ── Boot ──────────────────────────────────────────────────────────────────
280
+ await loadProjects();
281
+ if (projects.length > 0)
282
+ await loadSecrets();
283
+ else
284
+ draw();
285
+ }
286
+ // ─── Commander ───────────────────────────────────────────────────────────────
287
+ exports.uiCommand = new commander_1.Command("ui")
288
+ .description("Launch interactive TUI secrets dashboard (arrow keys, Tab, Q to quit)")
289
+ .action(async () => { await runUI(); });
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.watchCommand = void 0;
7
+ /**
8
+ * watch.ts — Live reload secrets in dev mode
9
+ *
10
+ * Polls XtraSecurity Cloud for secret changes at a configurable interval.
11
+ * When a change is detected, restarts the child process with fresh secrets.
12
+ *
13
+ * Usage:
14
+ * xtra watch -p proj123 -e dev node app.js
15
+ * xtra watch -p proj123 -e dev --interval 10 npm run dev --shell
16
+ */
17
+ const commander_1 = require("commander");
18
+ const api_1 = require("../lib/api");
19
+ const config_1 = require("../lib/config");
20
+ const chalk_1 = __importDefault(require("chalk"));
21
+ const child_process_1 = require("child_process");
22
+ let child = null;
23
+ let lastHash = "";
24
+ function hashSecrets(secrets) {
25
+ return JSON.stringify(Object.keys(secrets).sort().map(k => `${k}=${secrets[k]}`));
26
+ }
27
+ async function startProcess(command, args, secrets, useShell) {
28
+ if (child) {
29
+ process.stdout.write(chalk_1.default.cyan("\n [watch] ") + chalk_1.default.yellow("Secret change detected — restarting...\n"));
30
+ child.kill("SIGTERM");
31
+ // Give it 500ms to terminate gracefully
32
+ await new Promise(r => setTimeout(r, 500));
33
+ }
34
+ const envVars = { ...process.env, ...secrets };
35
+ process.stdout.write(chalk_1.default.cyan(" [watch] ") + chalk_1.default.green(`Starting: ${command} ${args.join(" ")}\n`));
36
+ child = (0, child_process_1.spawn)(command, args, {
37
+ env: envVars,
38
+ stdio: "inherit",
39
+ shell: useShell,
40
+ });
41
+ child.on("exit", (code) => {
42
+ if (code !== null && code !== 0) {
43
+ process.stdout.write(chalk_1.default.cyan(" [watch] ") + chalk_1.default.red(`Process exited with code ${code}\n`));
44
+ }
45
+ child = null;
46
+ });
47
+ child.on("error", (err) => {
48
+ process.stdout.write(chalk_1.default.cyan(" [watch] ") + chalk_1.default.red(`Failed to start: ${err.message}\n`));
49
+ child = null;
50
+ });
51
+ }
52
+ exports.watchCommand = new commander_1.Command("watch")
53
+ .description("Live reload — auto-restart process when secrets change in cloud")
54
+ .option("-p, --project <id>", "Project ID")
55
+ .option("-e, --env <environment>", "Environment", "development")
56
+ .option("-b, --branch <branch>", "Branch", "main")
57
+ .option("--interval <seconds>", "Poll interval in seconds", "5")
58
+ .option("--shell", "Use shell mode for the child process (for npm run etc.)", false)
59
+ .argument("<command>", "Command to run")
60
+ .argument("[args...]", "Command arguments")
61
+ .addHelpText("after", `
62
+ Examples:
63
+ $ xtra watch -p proj123 -e dev node app.js
64
+ $ xtra watch -p proj123 -e dev --interval 10 --shell npm run dev
65
+ $ xtra watch -p proj123 -e dev -- node -r dotenv/config server.js
66
+ `)
67
+ .action(async (command, args, options) => {
68
+ let { project, env, branch, interval, shell: useShell } = options;
69
+ const envMap = { dev: "development", stg: "staging", prod: "production" };
70
+ env = envMap[env] || env;
71
+ if (!project)
72
+ project = (0, config_1.getRcConfig)().project;
73
+ if (!project) {
74
+ console.error(chalk_1.default.red("Error: Project ID required. Use -p <id> or run 'xtra project set'."));
75
+ process.exit(1);
76
+ }
77
+ // Block production watch — too dangerous
78
+ if (env === "production") {
79
+ console.error(chalk_1.default.red("⚠ xtra watch is not allowed in PRODUCTION for safety reasons."));
80
+ console.error(chalk_1.default.gray(" Use 'xtra run' for one-shot production injection."));
81
+ process.exit(1);
82
+ }
83
+ const pollMs = Math.max(3, parseInt(interval)) * 1000;
84
+ const isWindows = process.platform === "win32";
85
+ const finalShell = useShell || isWindows;
86
+ console.log(chalk_1.default.bold.cyan("\n● xtra watch") + chalk_1.default.bold(` — watching ${env}/${branch} (every ${interval}s)\n`));
87
+ console.log(chalk_1.default.gray(` Press Ctrl+C to stop.\n`));
88
+ // Graceful shutdown
89
+ process.on("SIGINT", () => {
90
+ if (child)
91
+ child.kill("SIGTERM");
92
+ console.log(chalk_1.default.cyan("\n [watch] ") + chalk_1.default.gray("Stopped."));
93
+ process.exit(0);
94
+ });
95
+ // Initial fetch & start
96
+ try {
97
+ const secrets = await api_1.api.getSecrets(project, env, branch);
98
+ lastHash = hashSecrets(secrets);
99
+ await startProcess(command, args, secrets, finalShell);
100
+ }
101
+ catch (e) {
102
+ console.error(chalk_1.default.red("Failed to fetch secrets: " + (e?.response?.data?.error || e.message)));
103
+ process.exit(1);
104
+ }
105
+ // Poll loop
106
+ setInterval(async () => {
107
+ try {
108
+ const secrets = await api_1.api.getSecrets(project, env, branch);
109
+ const hash = hashSecrets(secrets);
110
+ if (hash !== lastHash) {
111
+ lastHash = hash;
112
+ await startProcess(command, args, secrets, finalShell);
113
+ }
114
+ else {
115
+ process.stdout.write(chalk_1.default.cyan(" [watch] ") + chalk_1.default.gray(`${new Date().toLocaleTimeString()} — no changes \r`));
116
+ }
117
+ }
118
+ catch (e) {
119
+ process.stdout.write(chalk_1.default.cyan("\n [watch] ") + chalk_1.default.yellow(`Poll failed: ${e.message}\n`));
120
+ // Don't exit — keep trying
121
+ }
122
+ }, pollMs);
123
+ });
@@ -0,0 +1,187 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.api = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const config_1 = require("./config");
9
+ const getClient = () => {
10
+ const { apiUrl } = (0, config_1.getConfig)();
11
+ const token = (0, config_1.getAuthToken)();
12
+ const client = axios_1.default.create({
13
+ baseURL: apiUrl,
14
+ headers: {
15
+ "Content-Type": "application/json",
16
+ ...(token ? { Authorization: `Bearer ${token}` } : {}),
17
+ },
18
+ });
19
+ return client;
20
+ };
21
+ exports.api = {
22
+ login: async (email, password, apiKey) => {
23
+ const response = await getClient().post("/auth/cli-login", {
24
+ email,
25
+ password,
26
+ apiKey,
27
+ });
28
+ return response.data;
29
+ },
30
+ // Placeholders for future methods
31
+ getSecrets: async (projectId, env, branch = "main") => {
32
+ // Fixed path to match Next.js dynamic route folder structure
33
+ const response = await getClient().get(`/projects/${projectId}/envs/${env}/secrets?branch=${branch}`);
34
+ return response.data;
35
+ },
36
+ getSecretVersions: async (projectId, env, branch = "main") => {
37
+ const response = await getClient().get(`/projects/${projectId}/envs/${env}/secrets?includeVersions=true&branch=${branch}`);
38
+ return response.data;
39
+ },
40
+ setSecrets: async (projectId, env, secrets, expectedVersions, branch = "main") => {
41
+ const response = await getClient().post(`/projects/${projectId}/envs/${env}/secrets`, { secrets, expectedVersions, branch });
42
+ return response.data;
43
+ },
44
+ getSecretDetails: async (projectId, env, key, branch = "main") => {
45
+ const response = await getClient().get(`/projects/${projectId}/envs/${env}/secrets/${key}?branch=${branch}`);
46
+ return response.data;
47
+ },
48
+ syncLogs: async (logs) => {
49
+ const response = await getClient().post("/audit/cli-logs", { logs });
50
+ return response.data;
51
+ },
52
+ linkSecret: async (projectId, env, key, sourceProjectId, sourceEnv, sourceKey) => {
53
+ const response = await getClient().post(`/projects/${projectId}/envs/${env}/secrets/link`, {
54
+ key,
55
+ sourceProjectId,
56
+ sourceEnv,
57
+ sourceKey
58
+ });
59
+ return response.data;
60
+ },
61
+ rotateSecret: async (projectId, env, key, strategy, parsedNewValue) => {
62
+ const response = await getClient().post(`/projects/${projectId}/envs/${env}/secrets/${key}/rotate`, {
63
+ strategy,
64
+ parsedNewValue
65
+ });
66
+ return response.data;
67
+ },
68
+ promoteSecret: async (projectId, env, key) => {
69
+ const response = await getClient().post(`/projects/${projectId}/envs/${env}/secrets/${key}/promote`, {});
70
+ return response.data;
71
+ },
72
+ verifyAuditLogs: async () => {
73
+ const response = await getClient().get("/audit/verify");
74
+ return response.data;
75
+ },
76
+ exportAuditLogs: async (format, start, end, projectId) => {
77
+ const body = { format };
78
+ if (start)
79
+ body.startDate = start;
80
+ if (end)
81
+ body.endDate = end;
82
+ if (projectId)
83
+ body.projectId = projectId;
84
+ const response = await getClient().post("/audit/export", body, { responseType: format === "csv" ? "text" : "json" });
85
+ return response.data;
86
+ },
87
+ // JIT Access
88
+ requestAccess: async (projectId, reason, duration, secretId) => {
89
+ const response = await getClient().post("/access/request", { projectId, secretId, reason, duration });
90
+ return response.data;
91
+ },
92
+ approveAccess: async (requestId, decision) => {
93
+ const response = await getClient().post("/access/approve", { requestId, decision });
94
+ return response.data;
95
+ },
96
+ listAccessRequests: async (mode) => {
97
+ const response = await getClient().get(`/access/list?mode=${mode}`);
98
+ return response.data;
99
+ },
100
+ // Project Management
101
+ getProjects: async () => {
102
+ const { workspace } = (0, config_1.getConfig)();
103
+ const url = workspace ? `/project?workspaceId=${workspace}` : "/project";
104
+ const response = await getClient().get(url);
105
+ return response.data;
106
+ },
107
+ // Branch Management
108
+ getBranches: async (projectId) => {
109
+ const response = await getClient().get(`/branch?projectId=${projectId}`);
110
+ return response.data;
111
+ },
112
+ createBranch: async (projectId, name, description) => {
113
+ const response = await getClient().post("/branch", { projectId, name, description });
114
+ return response.data;
115
+ },
116
+ deleteBranch: async (branchId) => {
117
+ const response = await getClient().delete(`/branch/${branchId}`);
118
+ return response.data;
119
+ },
120
+ updateBranch: async (branchId, updates) => {
121
+ const response = await getClient().put("/branch", { id: branchId, ...updates });
122
+ return response.data;
123
+ },
124
+ // Admin - Role Management
125
+ getRoles: async () => {
126
+ const response = await getClient().get("/admin/roles");
127
+ return response.data;
128
+ },
129
+ getUsers: async (teamId) => {
130
+ const params = teamId ? `?teamId=${teamId}` : "";
131
+ const response = await getClient().get(`/admin/users${params}`);
132
+ return response.data;
133
+ },
134
+ setUserRole: async (email, role, teamId) => {
135
+ const response = await getClient().put("/admin/users/role", { email, role, teamId });
136
+ return response.data;
137
+ },
138
+ // Integrations
139
+ getIntegrationStatus: async (provider) => {
140
+ const response = await getClient().get(`/integrations/${provider}`);
141
+ return response.data;
142
+ },
143
+ getIntegrationRepos: async (provider) => {
144
+ const response = await getClient().get(`/integrations/${provider}/sync`);
145
+ return response.data.repos;
146
+ },
147
+ syncSecretsToGithub: async (data) => {
148
+ const response = await getClient().post("/api/integrations/github/sync", data);
149
+ return response.data;
150
+ },
151
+ exportKubernetesSecret: async (projectId, params) => {
152
+ const query = new URLSearchParams(params).toString();
153
+ const response = await getClient().get(`/projects/${projectId}/kubernetes?${query}`);
154
+ return response.data; // This returns the YAML string directly
155
+ },
156
+ // Advanced Features
157
+ getSecretHistory: async (projectId, env, key) => {
158
+ const response = await getClient().get(`/projects/${projectId}/envs/${env}/secrets/${key}/history`);
159
+ return response.data;
160
+ },
161
+ rollbackSecret: async (projectId, env, key, version) => {
162
+ const response = await getClient().post(`/projects/${projectId}/envs/${env}/secrets/${key}/history`, { version });
163
+ return response.data;
164
+ },
165
+ cloneEnvironment: async (projectId, fromEnv, toEnv, overwrite, branch) => {
166
+ const response = await getClient().post(`/projects/${projectId}/envs/clone`, { fromEnv, toEnv, overwrite, branch });
167
+ return response.data;
168
+ },
169
+ // JIT Link Management
170
+ generateJitLink: async (opts) => {
171
+ const response = await getClient().post("/jit/generate", opts);
172
+ return response.data;
173
+ },
174
+ claimJitLink: async (token) => {
175
+ const response = await getClient().post("/jit/claim", { token });
176
+ return response.data;
177
+ },
178
+ getJitInfo: async (token) => {
179
+ const response = await getClient().get(`/jit/${token}`);
180
+ return response.data;
181
+ },
182
+ // Generic POST method for audit logging and other uses
183
+ post: async (endpoint, data) => {
184
+ const response = await getClient().post(endpoint, data);
185
+ return response.data;
186
+ }
187
+ };