xtra-cli 1.0.4 → 1.0.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/dist/bin/xtra.js +2 -294
- package/dist/commands/access.js +1 -184
- package/dist/commands/admin.js +5 -118
- package/dist/commands/audit.js +1 -67
- package/dist/commands/branch.js +1 -212
- package/dist/commands/checkout.js +1 -80
- package/dist/commands/ci.js +31 -341
- package/dist/commands/completion.js +85 -224
- package/dist/commands/diff.js +6 -162
- package/dist/commands/doctor.js +2 -164
- package/dist/commands/env.js +2 -70
- package/dist/commands/export.js +2 -83
- package/dist/commands/generate.js +3 -179
- package/dist/commands/history.js +4 -77
- package/dist/commands/import.js +1 -121
- package/dist/commands/init.js +7 -205
- package/dist/commands/integration.js +11 -188
- package/dist/commands/jit-run.js +5 -0
- package/dist/commands/local.js +16 -198
- package/dist/commands/login.js +16 -198
- package/dist/commands/login.test.js +16 -51
- package/dist/commands/logout.js +1 -0
- package/dist/commands/logs.js +3 -121
- package/dist/commands/profile.js +14 -184
- package/dist/commands/project.js +1 -165
- package/dist/commands/rollback.js +1 -95
- package/dist/commands/rotate.js +3 -93
- package/dist/commands/run.js +11 -215
- package/dist/commands/scan.js +25 -127
- package/dist/commands/secrets.js +14 -305
- package/dist/commands/simulate.js +6 -109
- package/dist/commands/status.js +2 -93
- package/dist/commands/template.js +22 -276
- package/dist/commands/ui.js +2 -289
- package/dist/commands/watch.js +17 -123
- package/dist/lib/api.js +1 -187
- package/dist/lib/api.test.js +1 -89
- package/dist/lib/audit.js +1 -136
- package/dist/lib/config.js +1 -72
- package/dist/lib/config.test.js +1 -47
- package/dist/lib/crypto.js +1 -50
- package/dist/lib/manifest.js +1 -52
- package/dist/lib/profiles.js +1 -103
- package/package.json +2 -2
|
@@ -1,227 +1,88 @@
|
|
|
1
|
-
"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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.completionCommand = void 0;
|
|
40
|
-
const commander_1 = require("commander");
|
|
41
|
-
const fs = __importStar(require("fs"));
|
|
42
|
-
const path = __importStar(require("path"));
|
|
43
|
-
const os = __importStar(require("os"));
|
|
44
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
45
|
-
// ─── All CLI top-level commands ───────────────────────────────────────────────
|
|
46
|
-
const ALL_COMMANDS = [
|
|
47
|
-
"login", "run", "secrets", "generate", "status", "diff", "rollback",
|
|
48
|
-
"scan", "logs", "export", "import", "rotate", "audit", "access",
|
|
49
|
-
"branch", "checkout", "project", "admin", "integration", "kubernetes",
|
|
50
|
-
"history", "env", "ui", "completion"
|
|
51
|
-
];
|
|
52
|
-
const SUBCOMMANDS = {
|
|
53
|
-
secrets: ["list", "set", "link"],
|
|
54
|
-
branch: ["list", "create", "delete", "update"],
|
|
55
|
-
admin: ["users", "roles", "role", "set-role"],
|
|
56
|
-
access: ["request", "list", "approve"],
|
|
57
|
-
audit: ["verify", "export"],
|
|
58
|
-
integration: ["sync", "export", "apply"],
|
|
59
|
-
env: ["clone"],
|
|
60
|
-
project: ["set", "current"],
|
|
61
|
-
completion: ["bash", "zsh", "powershell", "install"],
|
|
62
|
-
};
|
|
63
|
-
// ─── Bash completion script ───────────────────────────────────────────────────
|
|
64
|
-
function bashScript() {
|
|
65
|
-
const subMap = Object.entries(SUBCOMMANDS)
|
|
66
|
-
.map(([cmd, subs]) => ` ${cmd}) echo "${subs.join(" ")}" ;;`)
|
|
67
|
-
.join("\n");
|
|
68
|
-
return `# xtra bash completion
|
|
69
|
-
# Add to ~/.bashrc: source <(xtra completion bash)
|
|
70
|
-
_xtra_completions() {
|
|
71
|
-
local cur prev words
|
|
72
|
-
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
73
|
-
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
74
|
-
|
|
75
|
-
if [ "\${COMP_CWORD}" -eq 1 ]; then
|
|
76
|
-
COMPREPLY=( $(compgen -W "${ALL_COMMANDS.join(" ")}" -- "$cur") )
|
|
77
|
-
return
|
|
78
|
-
fi
|
|
79
|
-
|
|
80
|
-
local subcommands=""
|
|
81
|
-
case "\${COMP_WORDS[1]}" in
|
|
82
|
-
${subMap}
|
|
83
|
-
*) ;;
|
|
84
|
-
esac
|
|
85
|
-
|
|
86
|
-
if [ -n "$subcommands" ]; then
|
|
87
|
-
COMPREPLY=( $(compgen -W "$subcommands" -- "$cur") )
|
|
88
|
-
fi
|
|
89
|
-
}
|
|
90
|
-
complete -F _xtra_completions xtra
|
|
91
|
-
`;
|
|
1
|
+
var f=Object.create;var c=Object.defineProperty;var g=Object.getOwnPropertyDescriptor;var _=Object.getOwnPropertyNames;var O=Object.getPrototypeOf,P=Object.prototype.hasOwnProperty;var S=(o,e)=>{for(var t in e)c(o,t,{get:e[t],enumerable:!0})},d=(o,e,t,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of _(e))!P.call(o,n)&&n!==t&&c(o,n,{get:()=>e[n],enumerable:!(s=g(e,n))||s.enumerable});return o};var i=(o,e,t)=>(t=o!=null?f(O(o)):{},d(e||!o||!o.__esModule?c(t,"default",{value:o,enumerable:!0}):t,o)),j=o=>d(c({},"__esModule",{value:!0}),o);var M={};S(M,{completionCommand:()=>y});module.exports=j(M);var $=require("commander"),a=i(require("fs")),l=i(require("path")),b=i(require("os")),r=i(require("chalk")),m=["login","run","secrets","generate","status","diff","rollback","scan","logs","export","import","rotate","audit","access","branch","checkout","project","admin","integration","kubernetes","history","env","ui","completion"],p={secrets:["list","set","link"],branch:["list","create","delete","update"],admin:["users","roles","role","set-role"],access:["request","list","approve"],audit:["verify","export"],integration:["sync","export","apply"],env:["clone"],project:["set","current"],completion:["bash","zsh","powershell","install"]};function x(){let o=Object.entries(p).map(([e,t])=>` ${e}) echo "${t.join(" ")}" ;;`).join(`
|
|
2
|
+
`);return`# xtra bash completion
|
|
3
|
+
# Add to ~/.bashrc: source <(xtra completion bash)
|
|
4
|
+
_xtra_completions() {
|
|
5
|
+
local cur prev words
|
|
6
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
7
|
+
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
8
|
+
|
|
9
|
+
if [ "\${COMP_CWORD}" -eq 1 ]; then
|
|
10
|
+
COMPREPLY=( $(compgen -W "${m.join(" ")}" -- "$cur") )
|
|
11
|
+
return
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
local subcommands=""
|
|
15
|
+
case "\${COMP_WORDS[1]}" in
|
|
16
|
+
${o}
|
|
17
|
+
*) ;;
|
|
18
|
+
esac
|
|
19
|
+
|
|
20
|
+
if [ -n "$subcommands" ]; then
|
|
21
|
+
COMPREPLY=( $(compgen -W "$subcommands" -- "$cur") )
|
|
22
|
+
fi
|
|
92
23
|
}
|
|
93
|
-
|
|
94
|
-
function
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
# xtra zsh
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
'
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
esac
|
|
116
|
-
}
|
|
117
|
-
_xtra
|
|
118
|
-
`;
|
|
24
|
+
complete -F _xtra_completions xtra
|
|
25
|
+
`}function C(){let o=Object.entries(p).map(([e,t])=>` (${e})
|
|
26
|
+
local subcmds=(${t.map(s=>`'${s}'`).join(" ")})
|
|
27
|
+
_describe 'subcommand' subcmds ;;`).join(`
|
|
28
|
+
`);return`#compdef xtra
|
|
29
|
+
# xtra zsh completion
|
|
30
|
+
# Add to ~/.zshrc: source <(xtra completion zsh)
|
|
31
|
+
_xtra() {
|
|
32
|
+
local state
|
|
33
|
+
_arguments \\
|
|
34
|
+
'1: :->command' \\
|
|
35
|
+
'*: :->args'
|
|
36
|
+
|
|
37
|
+
case $state in
|
|
38
|
+
command)
|
|
39
|
+
local commands=(${m.map(e=>`'${e}'`).join(" ")})
|
|
40
|
+
_describe 'command' commands ;;
|
|
41
|
+
args)
|
|
42
|
+
case $words[2] in
|
|
43
|
+
${o}
|
|
44
|
+
esac ;;
|
|
45
|
+
esac
|
|
119
46
|
}
|
|
120
|
-
|
|
121
|
-
function
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
$tokens
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
$
|
|
141
|
-
}
|
|
142
|
-
$subCommands | Where-Object { $_ -like "$wordToComplete*" } |
|
|
143
|
-
ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) }
|
|
144
|
-
}
|
|
145
|
-
`;
|
|
47
|
+
_xtra
|
|
48
|
+
`}function w(){let o=Object.entries(p).map(([e,t])=>` '${e}' { $subCommands = @(${t.map(s=>`'${s}'`).join(", ")}) }`).join(`
|
|
49
|
+
`);return`# xtra PowerShell completion
|
|
50
|
+
# Add to $PROFILE: xtra completion powershell | Invoke-Expression
|
|
51
|
+
Register-ArgumentCompleter -Native -CommandName xtra -ScriptBlock {
|
|
52
|
+
param($wordToComplete, $commandAst, $cursorPosition)
|
|
53
|
+
$tokens = $commandAst.CommandElements
|
|
54
|
+
$topCommands = @(${m.map(e=>`'${e}'`).join(", ")})
|
|
55
|
+
|
|
56
|
+
if ($tokens.Count -le 2) {
|
|
57
|
+
$topCommands | Where-Object { $_ -like "$wordToComplete*" } |
|
|
58
|
+
ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) }
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
$subCommands = @()
|
|
63
|
+
switch ($tokens[1]) {
|
|
64
|
+
${o}
|
|
65
|
+
}
|
|
66
|
+
$subCommands | Where-Object { $_ -like "$wordToComplete*" } |
|
|
67
|
+
ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) }
|
|
146
68
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
script = powershellScript();
|
|
168
|
-
break;
|
|
169
|
-
default:
|
|
170
|
-
console.error(chalk_1.default.red(`Unsupported shell: ${shell}. Use bash, zsh, or powershell.`));
|
|
171
|
-
process.exit(1);
|
|
172
|
-
}
|
|
173
|
-
// Write the completion script to a temp file path for reference
|
|
174
|
-
const scriptPath = path.join(home, `.xtra-completion.${shell}`);
|
|
175
|
-
fs.writeFileSync(scriptPath, script, "utf8");
|
|
176
|
-
// Append sourcing snippet to rc file if not already there
|
|
177
|
-
let rcContent = "";
|
|
178
|
-
try {
|
|
179
|
-
rcContent = fs.readFileSync(rcFile, "utf8");
|
|
180
|
-
}
|
|
181
|
-
catch (_) { }
|
|
182
|
-
if (rcContent.includes("xtra completion")) {
|
|
183
|
-
console.log(chalk_1.default.yellow(`Completion already installed in ${rcFile}. Skipping.`));
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
fs.appendFileSync(rcFile, snippet, "utf8");
|
|
187
|
-
console.log(chalk_1.default.green(`✅ Completion installed!\n`));
|
|
188
|
-
console.log(` Script saved to: ${chalk_1.default.cyan(scriptPath)}`);
|
|
189
|
-
console.log(` Sourced in: ${chalk_1.default.cyan(rcFile)}`);
|
|
190
|
-
console.log(`\nRestart your shell or run: ${chalk_1.default.bold(`source ${rcFile}`)}`);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
// ─── Commander command ────────────────────────────────────────────────────────
|
|
194
|
-
exports.completionCommand = new commander_1.Command("completion")
|
|
195
|
-
.description("Generate shell completion scripts (bash, zsh, powershell)")
|
|
196
|
-
.argument("[shell]", "Target shell: bash | zsh | powershell", "bash")
|
|
197
|
-
.option("--install", "Automatically install completion into your shell profile")
|
|
198
|
-
.addHelpText("after", `
|
|
199
|
-
Examples:
|
|
200
|
-
$ xtra completion bash # Print bash completion script
|
|
201
|
-
$ xtra completion zsh # Print zsh completion script
|
|
202
|
-
$ xtra completion powershell # Print PowerShell completion script
|
|
203
|
-
$ source <(xtra completion bash) # Activate in current session
|
|
204
|
-
$ xtra completion bash --install # Auto-install to ~/.bashrc
|
|
205
|
-
$ xtra completion powershell --install # Auto-install to $PROFILE
|
|
206
|
-
`)
|
|
207
|
-
.action((shell, options) => {
|
|
208
|
-
const normalizedShell = shell.toLowerCase();
|
|
209
|
-
if (options.install) {
|
|
210
|
-
installCompletion(normalizedShell);
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
213
|
-
switch (normalizedShell) {
|
|
214
|
-
case "bash":
|
|
215
|
-
process.stdout.write(bashScript());
|
|
216
|
-
break;
|
|
217
|
-
case "zsh":
|
|
218
|
-
process.stdout.write(zshScript());
|
|
219
|
-
break;
|
|
220
|
-
case "powershell":
|
|
221
|
-
process.stdout.write(powershellScript());
|
|
222
|
-
break;
|
|
223
|
-
default:
|
|
224
|
-
console.error(chalk_1.default.red(`Unknown shell: '${shell}'. Use bash, zsh, or powershell.`));
|
|
225
|
-
process.exit(1);
|
|
226
|
-
}
|
|
227
|
-
});
|
|
69
|
+
`}function k(o){let e=b.homedir(),t,s,n;switch(o){case"bash":t=l.join(e,".bashrc"),s=`
|
|
70
|
+
# xtra CLI completion
|
|
71
|
+
source <(xtra completion bash)
|
|
72
|
+
`,n=x();break;case"zsh":t=l.join(e,".zshrc"),s=`
|
|
73
|
+
# xtra CLI completion
|
|
74
|
+
source <(xtra completion zsh)
|
|
75
|
+
`,n=C();break;case"powershell":t=l.join(e,"Documents","WindowsPowerShell","Microsoft.PowerShell_profile.ps1"),s=`
|
|
76
|
+
# xtra CLI completion
|
|
77
|
+
xtra completion powershell | Invoke-Expression
|
|
78
|
+
`,n=w();break;default:console.error(r.default.red(`Unsupported shell: ${o}. Use bash, zsh, or powershell.`)),process.exit(1)}let h=l.join(e,`.xtra-completion.${o}`);a.writeFileSync(h,n,"utf8");let u="";try{u=a.readFileSync(t,"utf8")}catch{}u.includes("xtra completion")?console.log(r.default.yellow(`Completion already installed in ${t}. Skipping.`)):(a.appendFileSync(t,s,"utf8"),console.log(r.default.green(`\u2705 Completion installed!
|
|
79
|
+
`)),console.log(` Script saved to: ${r.default.cyan(h)}`),console.log(` Sourced in: ${r.default.cyan(t)}`),console.log(`
|
|
80
|
+
Restart your shell or run: ${r.default.bold(`source ${t}`)}`))}var y=new $.Command("completion").description("Generate shell completion scripts (bash, zsh, powershell)").argument("[shell]","Target shell: bash | zsh | powershell","bash").option("--install","Automatically install completion into your shell profile").addHelpText("after",`
|
|
81
|
+
Examples:
|
|
82
|
+
$ xtra completion bash # Print bash completion script
|
|
83
|
+
$ xtra completion zsh # Print zsh completion script
|
|
84
|
+
$ xtra completion powershell # Print PowerShell completion script
|
|
85
|
+
$ source <(xtra completion bash) # Activate in current session
|
|
86
|
+
$ xtra completion bash --install # Auto-install to ~/.bashrc
|
|
87
|
+
$ xtra completion powershell --install # Auto-install to $PROFILE
|
|
88
|
+
`).action((o,e)=>{let t=o.toLowerCase();if(e.install){k(t);return}switch(t){case"bash":process.stdout.write(x());break;case"zsh":process.stdout.write(C());break;case"powershell":process.stdout.write(w());break;default:console.error(r.default.red(`Unknown shell: '${o}'. Use bash, zsh, or powershell.`)),process.exit(1)}});0&&(module.exports={completionCommand});
|
package/dist/commands/diff.js
CHANGED
|
@@ -1,162 +1,6 @@
|
|
|
1
|
-
"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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.diffCommand = void 0;
|
|
40
|
-
const commander_1 = require("commander");
|
|
41
|
-
const api_1 = require("../lib/api");
|
|
42
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
43
|
-
const ora_1 = __importDefault(require("ora"));
|
|
44
|
-
const config_1 = require("../lib/config");
|
|
45
|
-
const crypto_1 = require("../lib/crypto");
|
|
46
|
-
const diff = __importStar(require("diff"));
|
|
47
|
-
exports.diffCommand = new commander_1.Command("diff")
|
|
48
|
-
.description("Show differences between local cache and remote secrets")
|
|
49
|
-
.argument("[env1]", "Source Environment")
|
|
50
|
-
.argument("[env2]", "Target Environment")
|
|
51
|
-
.option("-p, --project <projectId>", "Project ID")
|
|
52
|
-
.option("-e, --env <environment>", "Environment (dev, stg, prod)", "dev")
|
|
53
|
-
.option("-b, --branch <branchName>", "Branch Name")
|
|
54
|
-
.option("--show", "Show actual value differences (sensitive)", false)
|
|
55
|
-
.action(async (env1, env2, options) => {
|
|
56
|
-
let { project, env, branch, show } = options;
|
|
57
|
-
// Use config fallback
|
|
58
|
-
if (!project)
|
|
59
|
-
project = (0, config_1.getRcConfig)().project;
|
|
60
|
-
if (!branch) {
|
|
61
|
-
branch = (0, config_1.getRcConfig)().branch || "main";
|
|
62
|
-
}
|
|
63
|
-
if (!project) {
|
|
64
|
-
console.error(chalk_1.default.red("Error: Project ID is required. Use -p <id> or run 'xtra project set' first."));
|
|
65
|
-
process.exit(1);
|
|
66
|
-
}
|
|
67
|
-
// Normalize Env Map
|
|
68
|
-
const envMap = { dev: "development", stg: "staging", prod: "production" };
|
|
69
|
-
if (env1 && env2) {
|
|
70
|
-
// COMPARE TWO REMOTE ENVIRONMENTS
|
|
71
|
-
const sourceEnv = envMap[env1] || env1;
|
|
72
|
-
const targetEnv = envMap[env2] || env2;
|
|
73
|
-
const spinner = (0, ora_1.default)(`Fetching secrets for ${sourceEnv} and ${targetEnv} (branch: ${branch})...`).start();
|
|
74
|
-
try {
|
|
75
|
-
const [sourceSecrets, targetSecrets] = await Promise.all([
|
|
76
|
-
api_1.api.getSecrets(project, sourceEnv, branch),
|
|
77
|
-
api_1.api.getSecrets(project, targetEnv, branch)
|
|
78
|
-
]);
|
|
79
|
-
spinner.stop();
|
|
80
|
-
console.log(chalk_1.default.bold(`\nDiff Report (${sourceEnv} <-> ${targetEnv} @ ${branch}):\n`));
|
|
81
|
-
compareSecrets(sourceSecrets, targetSecrets, show);
|
|
82
|
-
}
|
|
83
|
-
catch (error) {
|
|
84
|
-
spinner.fail("Failed to fetch secrets");
|
|
85
|
-
console.error(chalk_1.default.red(error.message));
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
// DEFAULT: COMPARE REMOTE VS LOCAL CACHE
|
|
90
|
-
const targetEnv = envMap[env] || env;
|
|
91
|
-
const spinner = (0, ora_1.default)(`Fetching remote state for ${targetEnv} (branch: ${branch})...`).start();
|
|
92
|
-
try {
|
|
93
|
-
const remoteSecrets = await api_1.api.getSecrets(project, targetEnv, branch);
|
|
94
|
-
let localSecrets = {};
|
|
95
|
-
try {
|
|
96
|
-
const cacheKey = `cache.${project}.${targetEnv}.${branch}`;
|
|
97
|
-
const encrypted = (0, config_1.getConfigValue)(cacheKey);
|
|
98
|
-
if (encrypted) {
|
|
99
|
-
const decryptedStr = (0, crypto_1.decrypt)(encrypted);
|
|
100
|
-
localSecrets = JSON.parse(decryptedStr);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
catch (e) { }
|
|
104
|
-
spinner.stop();
|
|
105
|
-
console.log(chalk_1.default.bold(`\nDiff Report (Remote ${targetEnv} vs Local Cache):\n`));
|
|
106
|
-
compareSecrets(remoteSecrets, localSecrets, show); // Note: verify order or adjust message
|
|
107
|
-
// existing logic compared local (arg1) to remote (arg2)
|
|
108
|
-
// But usually diff is "What is in A that is not in B"
|
|
109
|
-
// Let's call a shared helper or inline it but consistent
|
|
110
|
-
// To match previous behavior: comparing LOCAL against REMOTE
|
|
111
|
-
// But wait, user wants to see what's different in Remote.
|
|
112
|
-
// Let's stick to the previous logic structure for consistency if I extract it.
|
|
113
|
-
// Actually, I'll just rewrite the comparison block to be generic.
|
|
114
|
-
}
|
|
115
|
-
catch (error) {
|
|
116
|
-
spinner.fail("Failed to run diff.");
|
|
117
|
-
console.error(chalk_1.default.red(error.message));
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
function compareSecrets(source, target, show) {
|
|
122
|
-
const allKeys = new Set([...Object.keys(source), ...Object.keys(target)]);
|
|
123
|
-
let hasDiff = false;
|
|
124
|
-
allKeys.forEach(key => {
|
|
125
|
-
const val1 = source[key];
|
|
126
|
-
const val2 = target[key];
|
|
127
|
-
if (val1 === val2)
|
|
128
|
-
return;
|
|
129
|
-
hasDiff = true;
|
|
130
|
-
if (val1 === undefined) {
|
|
131
|
-
// Present in Target, missing in Source
|
|
132
|
-
console.log(chalk_1.default.green(`+ ${key} (Only in Target)`));
|
|
133
|
-
if (show)
|
|
134
|
-
console.log(chalk_1.default.green(` + "${val2}"`));
|
|
135
|
-
}
|
|
136
|
-
else if (val2 === undefined) {
|
|
137
|
-
// Present in Source, missing in Target
|
|
138
|
-
console.log(chalk_1.default.red(`- ${key} (Only in Source)`));
|
|
139
|
-
if (show)
|
|
140
|
-
console.log(chalk_1.default.red(` - "${val1}"`));
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
console.log(chalk_1.default.yellow(`~ ${key} (Modified)`));
|
|
144
|
-
if (show) {
|
|
145
|
-
const changes = diff.diffChars(val1, val2);
|
|
146
|
-
let diffStr = " ";
|
|
147
|
-
changes.forEach(part => {
|
|
148
|
-
const color = part.added ? chalk_1.default.green :
|
|
149
|
-
part.removed ? chalk_1.default.red : chalk_1.default.gray;
|
|
150
|
-
diffStr += color(part.value);
|
|
151
|
-
});
|
|
152
|
-
console.log(diffStr);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
|
-
if (!hasDiff) {
|
|
157
|
-
console.log(chalk_1.default.green("✔ No differences found."));
|
|
158
|
-
}
|
|
159
|
-
else if (!show) {
|
|
160
|
-
console.log(chalk_1.default.gray("\n(Use --show to reveal secret values)"));
|
|
161
|
-
}
|
|
162
|
-
}
|
|
1
|
+
var J=Object.create;var h=Object.defineProperty;var K=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var H=Object.getPrototypeOf,M=Object.prototype.hasOwnProperty;var X=(e,t)=>{for(var s in t)h(e,s,{get:t[s],enumerable:!0})},C=(e,t,s,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of V(t))!M.call(e,o)&&o!==s&&h(e,o,{get:()=>t[o],enumerable:!(r=K(t,o))||r.enumerable});return e};var c=(e,t,s)=>(s=e!=null?J(H(e)):{},C(t||!e||!e.__esModule?h(s,"default",{value:e,enumerable:!0}):s,e)),z=e=>C(h({},"__esModule",{value:!0}),e);var ee={};X(ee,{diffCommand:()=>Z});module.exports=z(ee);var q=require("commander");var P=c(require("axios"));var R=c(require("conf")),j=c(require("fs")),B=c(require("path")),b="https://www.xtrasecurity.in/api",l=new R.default({projectName:"xtra-cli",defaults:{apiUrl:b}}),S=l.get("apiUrl");S&&!process.env.XTRA_API_URL&&(S.includes("localhost")||S.includes("xtra-security.vercel.app"))&&l.set("apiUrl",b);var v=()=>({...l.store,apiUrl:process.env.XTRA_API_URL||l.get("apiUrl")||b}),U=e=>l.get(e);var A=()=>l.get("token");var x=()=>{let e={};try{let t=B.default.join(process.cwd(),".xtrarc");j.default.existsSync(t)&&(e=JSON.parse(j.default.readFileSync(t,"utf-8")))}catch{}return{project:e.project||l.get("project")||"",env:e.env||l.get("env")||"development",branch:e.branch||l.get("branch")||"main"}};var L=c(require("fs")),T=c(require("path")),Q=JSON.parse(L.readFileSync(T.join(__dirname,"../../package.json"),"utf-8")),n=()=>{let{apiUrl:e}=v(),t=A();return P.default.create({baseURL:e,headers:{"Content-Type":"application/json","X-CLI-Version":Q.version,...t?{Authorization:`Bearer ${t}`}:{}}})},$={login:async(e,t,s)=>(await n().post("/auth/cli-login",{email:e,password:t,apiKey:s})).data,getSecrets:async(e,t,s="main")=>(await n().get(`/projects/${e}/envs/${t}/secrets?branch=${s}`)).data,getSecretVersions:async(e,t,s="main")=>(await n().get(`/projects/${e}/envs/${t}/secrets?includeVersions=true&branch=${s}`)).data,setSecrets:async(e,t,s,r,o="main")=>(await n().post(`/projects/${e}/envs/${t}/secrets`,{secrets:s,expectedVersions:r,branch:o})).data,getSecretDetails:async(e,t,s,r="main")=>(await n().get(`/projects/${e}/envs/${t}/secrets/${s}?branch=${r}`)).data,syncLogs:async e=>(await n().post("/audit/cli-logs",{logs:e})).data,linkSecret:async(e,t,s,r,o,a)=>(await n().post(`/projects/${e}/envs/${t}/secrets/link`,{key:s,sourceProjectId:r,sourceEnv:o,sourceKey:a})).data,rotateSecret:async(e,t,s,r,o)=>(await n().post(`/projects/${e}/envs/${t}/secrets/${s}/rotate`,{strategy:r,parsedNewValue:o})).data,promoteSecret:async(e,t,s)=>(await n().post(`/projects/${e}/envs/${t}/secrets/${s}/promote`,{})).data,verifyAuditLogs:async()=>(await n().get("/audit/verify")).data,exportAuditLogs:async(e,t,s,r)=>{let o={format:e};return t&&(o.startDate=t),s&&(o.endDate=s),r&&(o.projectId=r),(await n().post("/audit/export",o,{responseType:e==="csv"?"text":"json"})).data},requestAccess:async(e,t,s,r)=>(await n().post("/access/request",{projectId:e,secretId:r,reason:t,duration:s})).data,approveAccess:async(e,t)=>(await n().post("/access/approve",{requestId:e,decision:t})).data,listAccessRequests:async e=>{let{workspace:t}=v(),s=t?`&workspaceId=${t}`:"";return(await n().get(`/access/list?mode=${e}${s}`)).data},getAccessRequestStatus:async e=>(await n().get(`/access/request?id=${e}`)).data,getProjects:async()=>{let{workspace:e}=v(),t=e?`/project?workspaceId=${e}`:"/project";return(await n().get(t)).data},getBranches:async e=>(await n().get(`/branch?projectId=${e}`)).data,createBranch:async(e,t,s)=>(await n().post("/branch",{projectId:e,name:t,description:s})).data,deleteBranch:async e=>(await n().delete(`/branch/${e}`)).data,updateBranch:async(e,t)=>(await n().put("/branch",{id:e,...t})).data,getRoles:async()=>(await n().get("/admin/roles")).data,getUsers:async e=>{let t=e?`?teamId=${e}`:"";return(await n().get(`/admin/users${t}`)).data},setUserRole:async(e,t,s)=>(await n().put("/admin/users/role",{email:e,role:t,teamId:s})).data,getIntegrationStatus:async e=>(await n().get(`/integrations/${e}`)).data,getIntegrationRepos:async e=>(await n().get(`/integrations/${e}/sync`)).data.repos,syncSecretsToGithub:async e=>(await n().post("/integrations/github/sync",e)).data,exportKubernetesSecret:async(e,t)=>{let s=new URLSearchParams(t).toString();return(await n().get(`/projects/${e}/kubernetes?${s}`)).data},getSecretHistory:async(e,t,s)=>(await n().get(`/projects/${e}/envs/${t}/secrets/${s}/history`)).data,rollbackSecret:async(e,t,s,r)=>(await n().post(`/projects/${e}/envs/${t}/secrets/${s}/history`,{version:r})).data,cloneEnvironment:async(e,t,s,r,o)=>(await n().post(`/projects/${e}/envs/clone`,{fromEnv:t,toEnv:s,overwrite:r,branch:o})).data,generateJitLink:async e=>(await n().post("/jit/generate",e)).data,claimJitLink:async e=>(await n().post("/jit/claim",{token:e})).data,getJitInfo:async e=>(await n().get(`/jit/${e}`)).data,post:async(e,t)=>(await n().post(e,t)).data};var i=c(require("chalk")),k=c(require("ora"));var w=c(require("crypto")),O=c(require("conf")),_=require("node-machine-id"),W="aes-256-gcm",N=new O.default({projectName:"xtra-cli-crypto"});function Y(){let e=N.get("masterKey");e||(e=w.default.randomBytes(32).toString("hex"),N.set("masterKey",e));let t=(0,_.machineIdSync)();return w.default.createHash("sha256").update(e+t).digest()}var D=e=>{let t=Y(),s=Buffer.from(e.iv,"hex"),r=Buffer.from(e.tag,"hex"),o=w.default.createDecipheriv(W,t,s);o.setAuthTag(r);let a=o.update(e.content,"hex","utf8");return a+=o.final("utf8"),a};var F=c(require("diff")),Z=new q.Command("diff").description("Show differences between local cache and remote secrets").argument("[env1]","Source Environment").argument("[env2]","Target Environment").option("-p, --project <projectId>","Project ID").option("-e, --env <environment>","Environment (dev, stg, prod)","dev").option("-b, --branch <branchName>","Branch Name").option("--show","Show actual value differences (sensitive)",!1).action(async(e,t,s)=>{let{project:r,env:o,branch:a,show:f}=s;r||(r=x().project),a||(a=x().branch||"main"),r||(console.error(i.default.red("Error: Project ID is required. Use -p <id> or run 'xtra project set' first.")),process.exit(1));let u={dev:"development",stg:"staging",prod:"production"};if(e&&t){let g=u[e]||e,d=u[t]||t,p=(0,k.default)(`Fetching secrets for ${g} and ${d} (branch: ${a})...`).start();try{let[m,y]=await Promise.all([$.getSecrets(r,g,a),$.getSecrets(r,d,a)]);p.stop(),console.log(i.default.bold(`
|
|
2
|
+
Diff Report (${g} <-> ${d} @ ${a}):
|
|
3
|
+
`)),E(m,y,f)}catch(m){p.fail("Failed to fetch secrets"),console.error(i.default.red(m.message))}}else{let g=u[o]||o,d=(0,k.default)(`Fetching remote state for ${g} (branch: ${a})...`).start();try{let p=await $.getSecrets(r,g,a),m={};try{let y=`cache.${r}.${g}.${a}`,I=U(y);if(I){let G=D(I);m=JSON.parse(G)}}catch{}d.stop(),console.log(i.default.bold(`
|
|
4
|
+
Diff Report (Remote ${g} vs Local Cache):
|
|
5
|
+
`)),E(p,m,f)}catch(p){d.fail("Failed to run diff."),console.error(i.default.red(p.message))}}});function E(e,t,s){let r=new Set([...Object.keys(e),...Object.keys(t)]),o=!1;r.forEach(a=>{let f=e[a],u=t[a];if(f!==u){if(o=!0,f===void 0)console.log(i.default.green(`+ ${a} (Only in Target)`)),s&&console.log(i.default.green(` + "${u}"`));else if(u===void 0)console.log(i.default.red(`- ${a} (Only in Source)`)),s&&console.log(i.default.red(` - "${f}"`));else if(console.log(i.default.yellow(`~ ${a} (Modified)`)),s){let g=F.diffChars(f,u),d=" ";g.forEach(p=>{let m=p.added?i.default.green:p.removed?i.default.red:i.default.gray;d+=m(p.value)}),console.log(d)}}}),o?s||console.log(i.default.gray(`
|
|
6
|
+
(Use --show to reveal secret values)`)):console.log(i.default.green("\u2714 No differences found."))}0&&(module.exports={diffCommand});
|