xtra-cli 0.1.4 → 0.1.8
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 +16 -2
- package/dist/commands/init.js +47 -13
- package/dist/commands/project.js +1 -0
- package/dist/lib/api.js +3 -1
- package/package.json +2 -2
package/dist/bin/xtra.js
CHANGED
|
@@ -76,8 +76,11 @@ program
|
|
|
76
76
|
.description("XtraSync CLI - Secure Runtime Secret Injection")
|
|
77
77
|
.version(pkg.version)
|
|
78
78
|
.option("--profile <name>", "Use a specific named profile for this command");
|
|
79
|
-
//
|
|
80
|
-
|
|
79
|
+
// Commands that do NOT require authentication
|
|
80
|
+
const PUBLIC_COMMANDS = new Set(["login", "completion", "doctor", "help"]);
|
|
81
|
+
// Apply profile + auth guard before any subcommand runs
|
|
82
|
+
program.hook("preSubcommand", (thisCommand, subCommand) => {
|
|
83
|
+
// ── Profile override ──────────────────────────────────────────
|
|
81
84
|
const profileName = thisCommand.opts().profile;
|
|
82
85
|
if (profileName) {
|
|
83
86
|
try {
|
|
@@ -88,6 +91,17 @@ program.hook("preSubcommand", (thisCommand) => {
|
|
|
88
91
|
process.exit(1);
|
|
89
92
|
}
|
|
90
93
|
}
|
|
94
|
+
// ── Auth guard ────────────────────────────────────────────────
|
|
95
|
+
const cmdName = subCommand.name();
|
|
96
|
+
if (PUBLIC_COMMANDS.has(cmdName))
|
|
97
|
+
return; // allow unauthenticated
|
|
98
|
+
const { getAuthToken } = require("../lib/config");
|
|
99
|
+
const token = getAuthToken();
|
|
100
|
+
if (!token) {
|
|
101
|
+
console.error("\x1b[31m✖ You are not logged in.\x1b[0m\n" +
|
|
102
|
+
" Run \x1b[36mxtra login\x1b[0m to authenticate before using this command.\n");
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
91
105
|
});
|
|
92
106
|
program.addCommand(login_1.loginCommand);
|
|
93
107
|
program.addCommand(run_1.runCommand);
|
package/dist/commands/init.js
CHANGED
|
@@ -74,19 +74,37 @@ exports.initCommand = new commander_1.Command("init")
|
|
|
74
74
|
// Interactive prompts if not --yes
|
|
75
75
|
if (!options.yes) {
|
|
76
76
|
// ── API Projects Fetch ─────────────────────────────────────────────
|
|
77
|
+
const { getAuthToken } = await Promise.resolve().then(() => __importStar(require("../lib/config")));
|
|
78
|
+
const token = getAuthToken();
|
|
77
79
|
const ora = (await Promise.resolve().then(() => __importStar(require("ora")))).default;
|
|
78
|
-
const apiSpinner = ora("Fetching your projects...").start();
|
|
79
80
|
let remoteProjects = [];
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
apiSpinner.succeed(`Found ${remoteProjects.length} projects`);
|
|
81
|
+
if (!token) {
|
|
82
|
+
console.log(chalk_1.default.yellow(" ℹ Not logged in — project list unavailable. Run `xtra login` first."));
|
|
83
|
+
console.log(chalk_1.default.yellow(" You can still enter a Project ID manually below.\n"));
|
|
84
84
|
}
|
|
85
|
-
|
|
86
|
-
apiSpinner
|
|
85
|
+
else {
|
|
86
|
+
const apiSpinner = ora("Fetching your projects...").start();
|
|
87
|
+
try {
|
|
88
|
+
const { api } = await Promise.resolve().then(() => __importStar(require("../lib/api")));
|
|
89
|
+
const result = await api.getProjects();
|
|
90
|
+
// API might return { projects: [...] } or directly an array
|
|
91
|
+
remoteProjects = Array.isArray(result) ? result : result.projects ?? [];
|
|
92
|
+
if (remoteProjects.length === 0) {
|
|
93
|
+
apiSpinner.warn(chalk_1.default.yellow("No projects found in your workspace. Create one at xtra-security.vercel.app first."));
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
apiSpinner.succeed(`Found ${remoteProjects.length} project${remoteProjects.length > 1 ? "s" : ""}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
const reason = err?.response?.status === 401
|
|
101
|
+
? "session expired — run `xtra login` again"
|
|
102
|
+
: err?.response?.data?.error || err?.message || "network error";
|
|
103
|
+
apiSpinner.warn(chalk_1.default.yellow(`Could not fetch projects (${reason}). Enter the Project ID manually.`));
|
|
104
|
+
}
|
|
87
105
|
}
|
|
88
106
|
const fallbackProject = project || (0, config_1.getConfigValue)("project") || "";
|
|
89
|
-
const
|
|
107
|
+
const { project: selectedProject } = await inquirer_1.default.prompt([
|
|
90
108
|
{
|
|
91
109
|
type: remoteProjects.length > 0 ? "list" : "input",
|
|
92
110
|
name: "project",
|
|
@@ -96,7 +114,21 @@ exports.initCommand = new commander_1.Command("init")
|
|
|
96
114
|
: undefined,
|
|
97
115
|
default: fallbackProject,
|
|
98
116
|
validate: (v) => v.trim() ? true : "Project ID is required",
|
|
99
|
-
}
|
|
117
|
+
}
|
|
118
|
+
]);
|
|
119
|
+
project = selectedProject.trim();
|
|
120
|
+
// Fetch branches for selected project
|
|
121
|
+
let remoteBranches = [];
|
|
122
|
+
const branchSpinner = ora("Fetching branches...").start();
|
|
123
|
+
try {
|
|
124
|
+
const { api } = await Promise.resolve().then(() => __importStar(require("../lib/api")));
|
|
125
|
+
remoteBranches = await api.getBranches(project);
|
|
126
|
+
branchSpinner.stop();
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
branchSpinner.warn(chalk_1.default.yellow("Could not fetch branches."));
|
|
130
|
+
}
|
|
131
|
+
const answers = await inquirer_1.default.prompt([
|
|
100
132
|
{
|
|
101
133
|
type: "list",
|
|
102
134
|
name: "env",
|
|
@@ -105,10 +137,13 @@ exports.initCommand = new commander_1.Command("init")
|
|
|
105
137
|
default: env || "development",
|
|
106
138
|
},
|
|
107
139
|
{
|
|
108
|
-
type: "input",
|
|
140
|
+
type: remoteBranches.length > 0 ? "list" : "input",
|
|
109
141
|
name: "branch",
|
|
110
|
-
message: "Default branch:",
|
|
111
|
-
|
|
142
|
+
message: remoteBranches.length > 0 ? "Default branch:" : "Default branch name:",
|
|
143
|
+
choices: remoteBranches.length > 0
|
|
144
|
+
? remoteBranches.map(b => ({ name: b.name, value: b.name }))
|
|
145
|
+
: undefined,
|
|
146
|
+
default: branch || (remoteBranches.length > 0 ? remoteBranches[0].name : "main"),
|
|
112
147
|
},
|
|
113
148
|
{
|
|
114
149
|
type: "confirm",
|
|
@@ -117,7 +152,6 @@ exports.initCommand = new commander_1.Command("init")
|
|
|
117
152
|
default: true,
|
|
118
153
|
},
|
|
119
154
|
]);
|
|
120
|
-
project = answers.project.trim();
|
|
121
155
|
env = answers.env;
|
|
122
156
|
branch = answers.branch;
|
|
123
157
|
// Add to .gitignore
|
package/dist/commands/project.js
CHANGED
|
@@ -11,6 +11,7 @@ const inquirer_1 = __importDefault(require("inquirer"));
|
|
|
11
11
|
const config_1 = require("../lib/config");
|
|
12
12
|
const api_1 = require("../lib/api");
|
|
13
13
|
exports.projectCommand = new commander_1.Command("project")
|
|
14
|
+
.alias("projects")
|
|
14
15
|
.description("Manage project context");
|
|
15
16
|
// SET
|
|
16
17
|
exports.projectCommand
|
package/dist/lib/api.js
CHANGED
|
@@ -99,7 +99,9 @@ exports.api = {
|
|
|
99
99
|
},
|
|
100
100
|
// Project Management
|
|
101
101
|
getProjects: async () => {
|
|
102
|
-
const
|
|
102
|
+
const { workspace } = (0, config_1.getConfig)();
|
|
103
|
+
const url = workspace ? `/project?workspaceId=${workspace}` : "/project";
|
|
104
|
+
const response = await getClient().get(url);
|
|
103
105
|
return response.data;
|
|
104
106
|
},
|
|
105
107
|
// Branch Management
|
package/package.json
CHANGED