inflight-cli 2.1.0 → 2.1.2
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 +1 -2
- package/dist/commands/setup.js +3 -3
- package/dist/commands/share.d.ts +0 -1
- package/dist/commands/share.js +58 -36
- package/dist/commands/vercel.js +60 -144
- package/dist/commands/workspace.d.ts +4 -0
- package/dist/commands/workspace.js +85 -0
- package/dist/index.js +10 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,8 +16,7 @@ That's it. The CLI installs globally, logs you in, adds the widget to your proje
|
|
|
16
16
|
| --------------------- | -------------------------------- |
|
|
17
17
|
| `inflight setup` | Set up Inflight in your project |
|
|
18
18
|
| `inflight share` | Share a staging URL for feedback |
|
|
19
|
-
| `inflight
|
|
20
|
-
| `inflight workspaces` | Change your Inflight workspace |
|
|
19
|
+
| `inflight workspace` | Get or set your active workspace |
|
|
21
20
|
| `inflight login` | Log in to your Inflight account |
|
|
22
21
|
| `inflight logout` | Log out of your Inflight account |
|
|
23
22
|
|
package/dist/commands/setup.js
CHANGED
|
@@ -55,7 +55,7 @@ export async function setupCommand() {
|
|
|
55
55
|
const existingWorkspace = existingConfig ? workspaces.find((w) => w.id === existingConfig.workspaceId) : null;
|
|
56
56
|
if (existingWorkspace) {
|
|
57
57
|
workspaceId = existingWorkspace.id;
|
|
58
|
-
p.log.success(`Workspace: ${pc.bold(existingWorkspace.name)} ${pc.dim("(change anytime with inflight
|
|
58
|
+
p.log.success(`Workspace: ${pc.bold(existingWorkspace.name)} ${pc.dim("(change anytime with inflight workspace)")}`);
|
|
59
59
|
}
|
|
60
60
|
else if (workspaces.length === 0) {
|
|
61
61
|
p.log.error("No workspaces found. Create one at " + pc.cyan("inflight.co") + " first.");
|
|
@@ -67,7 +67,7 @@ export async function setupCommand() {
|
|
|
67
67
|
}
|
|
68
68
|
else {
|
|
69
69
|
const selected = await p.select({
|
|
70
|
-
message: "Select a workspace " + pc.dim("(change anytime with inflight
|
|
70
|
+
message: "Select a workspace " + pc.dim("(change anytime with inflight workspace)"),
|
|
71
71
|
options: workspaces.map((w) => ({ value: w.id, label: w.name })),
|
|
72
72
|
});
|
|
73
73
|
if (p.isCancel(selected)) {
|
|
@@ -182,5 +182,5 @@ export async function setupCommand() {
|
|
|
182
182
|
// ── Done ──
|
|
183
183
|
p.log.success(pc.green("Setup complete!") + " Run " + pc.cyan("inflight share") + " anytime to share your staging URL.");
|
|
184
184
|
// ── Step 6: Share ──
|
|
185
|
-
await shareCommand(
|
|
185
|
+
await shareCommand();
|
|
186
186
|
}
|
package/dist/commands/share.d.ts
CHANGED
package/dist/commands/share.js
CHANGED
|
@@ -7,6 +7,7 @@ import { providers } from "../providers/index.js";
|
|
|
7
7
|
import { apiGetMe, apiCreateVersion } from "../lib/api.js";
|
|
8
8
|
export async function shareCommand(opts = {}) {
|
|
9
9
|
const cwd = process.cwd();
|
|
10
|
+
// ── Step 1: Auth ──
|
|
10
11
|
const auth = readGlobalAuth();
|
|
11
12
|
if (!auth) {
|
|
12
13
|
if (opts.json) {
|
|
@@ -18,15 +19,69 @@ export async function shareCommand(opts = {}) {
|
|
|
18
19
|
process.exit(1);
|
|
19
20
|
}
|
|
20
21
|
const gitInfo = getGitInfo(cwd);
|
|
21
|
-
// ──
|
|
22
|
-
|
|
22
|
+
// ── Step 2: Resolve workspace ──
|
|
23
|
+
const me = await apiGetMe(auth.apiKey).catch((e) => {
|
|
24
|
+
if (opts.json) {
|
|
25
|
+
console.log(JSON.stringify({ error: "api_error", message: e.message }));
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
p.log.error(e.message);
|
|
29
|
+
}
|
|
30
|
+
process.exit(1);
|
|
31
|
+
});
|
|
32
|
+
const workspaces = me.workspaces;
|
|
33
|
+
let workspaceId;
|
|
34
|
+
const savedConfig = readWorkspaceConfig();
|
|
35
|
+
const savedWorkspace = savedConfig ? workspaces.find((w) => w.id === savedConfig.workspaceId) : null;
|
|
36
|
+
if (savedWorkspace) {
|
|
37
|
+
workspaceId = savedWorkspace.id;
|
|
38
|
+
}
|
|
39
|
+
else if (workspaces.length === 0) {
|
|
40
|
+
if (opts.json) {
|
|
41
|
+
console.log(JSON.stringify({
|
|
42
|
+
error: "no_workspaces",
|
|
43
|
+
message: "No workspaces found. Create one at inflight.co first.",
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
p.log.error("No workspaces found. Create one at " + pc.cyan("inflight.co") + " first.");
|
|
48
|
+
}
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
else if (workspaces.length === 1) {
|
|
52
|
+
workspaceId = workspaces[0].id;
|
|
53
|
+
if (!opts.json)
|
|
54
|
+
p.log.success(`Workspace: ${pc.bold(workspaces[0].name)}`);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
if (opts.json) {
|
|
58
|
+
console.log(JSON.stringify({
|
|
59
|
+
error: "no_workspace_set",
|
|
60
|
+
message: "Multiple workspaces found. Run 'inflight workspace --set=ID' first.",
|
|
61
|
+
workspaces: workspaces.map((w) => ({ id: w.id, name: w.name })),
|
|
62
|
+
}));
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
const selected = await p.select({
|
|
66
|
+
message: "Select a workspace " + pc.dim("(change anytime with inflight workspace)"),
|
|
67
|
+
options: workspaces.map((w) => ({ value: w.id, label: w.name })),
|
|
68
|
+
});
|
|
69
|
+
if (p.isCancel(selected)) {
|
|
70
|
+
p.cancel("Cancelled.");
|
|
71
|
+
process.exit(0);
|
|
72
|
+
}
|
|
73
|
+
workspaceId = selected;
|
|
74
|
+
}
|
|
75
|
+
writeWorkspaceConfig({ workspaceId });
|
|
76
|
+
// ── Fast path: URL provided (agent / scripting) ──
|
|
77
|
+
if (opts.url) {
|
|
23
78
|
let stagingUrl = opts.url;
|
|
24
79
|
if (!stagingUrl.startsWith("http")) {
|
|
25
80
|
stagingUrl = `https://${stagingUrl}`;
|
|
26
81
|
}
|
|
27
82
|
const result = await apiCreateVersion({
|
|
28
83
|
apiKey: auth.apiKey,
|
|
29
|
-
workspaceId
|
|
84
|
+
workspaceId,
|
|
30
85
|
stagingUrl,
|
|
31
86
|
gitInfo,
|
|
32
87
|
}).catch((e) => {
|
|
@@ -48,39 +103,6 @@ export async function shareCommand(opts = {}) {
|
|
|
48
103
|
await open(stagingUrl);
|
|
49
104
|
return;
|
|
50
105
|
}
|
|
51
|
-
// ── Interactive path: prompt for missing inputs ──
|
|
52
|
-
// Resolve workspace
|
|
53
|
-
let workspaceId = opts.workspace ?? readWorkspaceConfig()?.workspaceId;
|
|
54
|
-
if (!workspaceId) {
|
|
55
|
-
const me = await apiGetMe(auth.apiKey).catch((e) => {
|
|
56
|
-
p.log.error(e.message);
|
|
57
|
-
process.exit(1);
|
|
58
|
-
});
|
|
59
|
-
if (me.workspaces.length === 0) {
|
|
60
|
-
p.log.error("No workspaces found. Create one at " + pc.cyan("inflight.co") + " first.");
|
|
61
|
-
process.exit(1);
|
|
62
|
-
}
|
|
63
|
-
else if (me.workspaces.length === 1) {
|
|
64
|
-
workspaceId = me.workspaces[0].id;
|
|
65
|
-
p.log.info(`Workspace: ${pc.bold(me.workspaces[0].name)}`);
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
const selected = await p.select({
|
|
69
|
-
message: "Select a workspace " + pc.dim("(change anytime with inflight workspaces)"),
|
|
70
|
-
options: me.workspaces.map((w) => ({ value: w.id, label: w.name })),
|
|
71
|
-
});
|
|
72
|
-
if (p.isCancel(selected)) {
|
|
73
|
-
p.cancel("Cancelled.");
|
|
74
|
-
process.exit(0);
|
|
75
|
-
}
|
|
76
|
-
workspaceId = selected;
|
|
77
|
-
}
|
|
78
|
-
writeWorkspaceConfig({ workspaceId });
|
|
79
|
-
}
|
|
80
|
-
if (!workspaceId) {
|
|
81
|
-
p.log.error("No workspace configured. Run " + pc.cyan("inflight workspaces") + " or " + pc.cyan("inflight setup") + ".");
|
|
82
|
-
process.exit(1);
|
|
83
|
-
}
|
|
84
106
|
// Resolve staging URL
|
|
85
107
|
const providerChoice = await p.select({
|
|
86
108
|
message: "Where is your staging URL hosted?",
|
package/dist/commands/vercel.js
CHANGED
|
@@ -1,128 +1,65 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import { ensureVercelCli, ensureVercelAuth, getVercelToken, getVercelTeams, getVercelProjects, getRecentDeployments, getBranchAlias, } from "../lib/vercel.js";
|
|
5
|
-
import { pickVercelProject } from "../providers/vercel.js";
|
|
1
|
+
import { readVercelConfig } from "../lib/config.js";
|
|
2
|
+
import { getGitInfo, parseGitRepo, getGitRoot } from "../lib/git.js";
|
|
3
|
+
import { getVercelToken, getRecentDeployments, getBranchAlias, readLocalVercelProject, fetchAllProjectsWithLinks, matchProjectsByRepo, } from "../lib/vercel.js";
|
|
6
4
|
// --- Action handlers ---
|
|
7
|
-
async function
|
|
8
|
-
// Fast path: non-interactive set (for agents)
|
|
9
|
-
if (opts.team && opts.project) {
|
|
10
|
-
const token = requireVercelToken();
|
|
11
|
-
const teams = await getVercelTeams(token);
|
|
12
|
-
const team = teams.find((t) => t.id === opts.team);
|
|
13
|
-
if (!team) {
|
|
14
|
-
const msg = `Team '${opts.team}' not found. Available: ${teams.map((t) => `${t.name} (${t.id})`).join(", ")}`;
|
|
15
|
-
if (opts.json) {
|
|
16
|
-
console.log(JSON.stringify({ error: "team_not_found", message: msg }));
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
p.log.error(msg);
|
|
20
|
-
}
|
|
21
|
-
process.exit(1);
|
|
22
|
-
}
|
|
23
|
-
const projects = await getVercelProjects(token, opts.team);
|
|
24
|
-
const project = projects.find((proj) => proj.id === opts.project);
|
|
25
|
-
if (!project) {
|
|
26
|
-
const msg = `Project '${opts.project}' not found on team '${team.name}'.`;
|
|
27
|
-
if (opts.json) {
|
|
28
|
-
console.log(JSON.stringify({ error: "project_not_found", message: msg }));
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
p.log.error(msg);
|
|
32
|
-
}
|
|
33
|
-
process.exit(1);
|
|
34
|
-
}
|
|
35
|
-
writeVercelConfig({ teamId: team.id, teamName: team.name, projectId: project.id, projectName: project.name });
|
|
36
|
-
if (opts.json) {
|
|
37
|
-
console.log(JSON.stringify({
|
|
38
|
-
saved: true,
|
|
39
|
-
teamId: team.id,
|
|
40
|
-
teamName: team.name,
|
|
41
|
-
projectId: project.id,
|
|
42
|
-
projectName: project.name,
|
|
43
|
-
}));
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
p.log.success(`Saved! Using ${pc.bold(project.name)} on ${pc.bold(team.name)}.`);
|
|
47
|
-
}
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
// Interactive path
|
|
51
|
-
const cliOk = await ensureVercelCli((msg) => p.log.step(msg));
|
|
52
|
-
if (!cliOk) {
|
|
53
|
-
p.log.error("Failed to install Vercel CLI. Install manually: " + pc.cyan("npm install -g vercel"));
|
|
54
|
-
process.exit(1);
|
|
55
|
-
}
|
|
56
|
-
p.log.step("Checking Vercel authentication...");
|
|
57
|
-
const token = await ensureVercelAuth();
|
|
58
|
-
if (!token) {
|
|
59
|
-
p.log.error("Vercel login failed.");
|
|
60
|
-
process.exit(1);
|
|
61
|
-
}
|
|
62
|
-
const current = readVercelConfig();
|
|
63
|
-
if (current) {
|
|
64
|
-
p.log.info(`Current: ${pc.bold(current.projectName)} on ${pc.bold(current.teamName)}`);
|
|
65
|
-
}
|
|
66
|
-
const config = await pickVercelProject(token);
|
|
67
|
-
if (!config)
|
|
68
|
-
process.exit(1);
|
|
69
|
-
p.log.success(`Saved! ${pc.cyan("inflight share")} will now use ${pc.bold(config.projectName)} on ${pc.bold(config.teamName)}.`);
|
|
70
|
-
}
|
|
71
|
-
async function listTeams() {
|
|
72
|
-
const token = requireVercelToken();
|
|
73
|
-
const teams = await getVercelTeams(token);
|
|
74
|
-
console.log(JSON.stringify(teams));
|
|
75
|
-
}
|
|
76
|
-
async function listProjects(opts) {
|
|
5
|
+
async function listProjects() {
|
|
77
6
|
const token = requireVercelToken();
|
|
78
|
-
const projects = await
|
|
79
|
-
console.log(JSON.stringify(projects));
|
|
7
|
+
const projects = await fetchAllProjectsWithLinks(token);
|
|
8
|
+
console.log(JSON.stringify(projects.map((p) => ({ id: p.id, name: p.name, teamId: p.teamId, teamName: p.teamName }))));
|
|
80
9
|
}
|
|
81
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Resolves teamId + projectId for subcommands.
|
|
12
|
+
* Priority: explicit flags → .vercel/project.json → git remote match → saved global config → error
|
|
13
|
+
*/
|
|
14
|
+
async function resolveProject(opts) {
|
|
15
|
+
if (opts.team && opts.project) {
|
|
16
|
+
return { teamId: opts.team, projectId: opts.project };
|
|
17
|
+
}
|
|
82
18
|
const token = requireVercelToken();
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (
|
|
86
|
-
const
|
|
87
|
-
if (
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
19
|
+
const cwd = process.cwd();
|
|
20
|
+
const gitRoot = getGitRoot(cwd);
|
|
21
|
+
if (gitRoot) {
|
|
22
|
+
const local = readLocalVercelProject(gitRoot);
|
|
23
|
+
if (local)
|
|
24
|
+
return { teamId: local.orgId, projectId: local.projectId };
|
|
25
|
+
}
|
|
26
|
+
const gitInfo = getGitInfo(cwd);
|
|
27
|
+
if (gitInfo.remoteUrl) {
|
|
28
|
+
const gitRepo = parseGitRepo(gitInfo.remoteUrl);
|
|
29
|
+
if (gitRepo) {
|
|
30
|
+
try {
|
|
31
|
+
const allProjects = await fetchAllProjectsWithLinks(token);
|
|
32
|
+
const matches = matchProjectsByRepo(allProjects, gitRepo.owner, gitRepo.name);
|
|
33
|
+
if (matches.length === 1) {
|
|
34
|
+
return { teamId: matches[0].teamId, projectId: matches[0].id };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch { }
|
|
93
38
|
}
|
|
94
|
-
teamId = teamId ?? config.teamId;
|
|
95
|
-
projectId = projectId ?? config.projectId;
|
|
96
39
|
}
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
40
|
+
const config = readVercelConfig();
|
|
41
|
+
if (config)
|
|
42
|
+
return { teamId: config.teamId, projectId: config.projectId };
|
|
43
|
+
console.log(JSON.stringify({
|
|
44
|
+
error: "vercel_not_configured",
|
|
45
|
+
message: "Could not auto-detect Vercel project. Run 'inflight vercel projects' to list available projects, then pass --team and --project to 'inflight vercel deployments'.",
|
|
46
|
+
}));
|
|
47
|
+
process.exit(1);
|
|
102
48
|
}
|
|
103
|
-
async function
|
|
49
|
+
async function listDeployments(opts) {
|
|
104
50
|
const token = requireVercelToken();
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
projectId = projectId ?? config.projectId;
|
|
118
|
-
}
|
|
119
|
-
const alias = await getBranchAlias(token, teamId, projectId, opts.branch);
|
|
120
|
-
if (alias) {
|
|
121
|
-
console.log(JSON.stringify({ url: alias.url, state: alias.state, branch: opts.branch }));
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
console.log(JSON.stringify({ url: null, branch: opts.branch, message: "No deployment found for this branch." }));
|
|
125
|
-
}
|
|
51
|
+
const { teamId, projectId } = await resolveProject(opts);
|
|
52
|
+
const cwd = process.cwd();
|
|
53
|
+
const gitInfo = getGitInfo(cwd);
|
|
54
|
+
const currentBranch = gitInfo.branch;
|
|
55
|
+
const [deployments, branchAlias] = await Promise.all([
|
|
56
|
+
getRecentDeployments(token, teamId, projectId),
|
|
57
|
+
currentBranch ? getBranchAlias(token, teamId, projectId, currentBranch) : Promise.resolve(null),
|
|
58
|
+
]);
|
|
59
|
+
console.log(JSON.stringify({
|
|
60
|
+
branchAlias: branchAlias ? { url: branchAlias.url, state: branchAlias.state, branch: currentBranch } : null,
|
|
61
|
+
deployments,
|
|
62
|
+
}));
|
|
126
63
|
}
|
|
127
64
|
/** Gets token silently, exits with JSON error if unavailable. */
|
|
128
65
|
function requireVercelToken() {
|
|
@@ -130,7 +67,7 @@ function requireVercelToken() {
|
|
|
130
67
|
if (!token) {
|
|
131
68
|
console.log(JSON.stringify({
|
|
132
69
|
error: "vercel_not_authenticated",
|
|
133
|
-
message: "Vercel auth expired or missing. Run '
|
|
70
|
+
message: "Vercel auth expired or missing. Run 'vercel login' first.",
|
|
134
71
|
}));
|
|
135
72
|
process.exit(1);
|
|
136
73
|
}
|
|
@@ -138,33 +75,12 @@ function requireVercelToken() {
|
|
|
138
75
|
}
|
|
139
76
|
// --- Command registration ---
|
|
140
77
|
export function registerVercelCommand(program) {
|
|
141
|
-
const vercel = program
|
|
142
|
-
|
|
143
|
-
.description("Set up or change your Vercel project")
|
|
144
|
-
.passThroughOptions()
|
|
145
|
-
.option("--team <id>", "Vercel team ID (non-interactive)")
|
|
146
|
-
.option("--project <id>", "Vercel project ID (non-interactive)")
|
|
147
|
-
.option("--json", "Output as JSON (non-interactive)")
|
|
148
|
-
.action(vercelSetup);
|
|
149
|
-
vercel.command("teams").description("List Vercel teams (JSON)").action(listTeams);
|
|
150
|
-
vercel
|
|
151
|
-
.command("projects")
|
|
152
|
-
.description("List projects for a Vercel team (JSON)")
|
|
153
|
-
.requiredOption("--team <id>", "Vercel team ID")
|
|
154
|
-
.action(listProjects);
|
|
155
|
-
vercel
|
|
156
|
-
.command("branch-url")
|
|
157
|
-
.description("Get the stable branch preview URL (JSON)")
|
|
158
|
-
.requiredOption("--branch <name>", "Git branch name")
|
|
159
|
-
.option("--team <id>", "Vercel team ID (reads from saved config if omitted)")
|
|
160
|
-
.option("--project <id>", "Vercel project ID (reads from saved config if omitted)")
|
|
161
|
-
.action(branchUrl);
|
|
78
|
+
const vercel = program.command("vercel").description("Vercel integration commands");
|
|
79
|
+
vercel.command("projects").description("List all Vercel projects (JSON)").action(listProjects);
|
|
162
80
|
vercel
|
|
163
81
|
.command("deployments")
|
|
164
|
-
.description("List recent deployments (JSON)")
|
|
165
|
-
.option("--team <id>", "Vercel team ID (
|
|
166
|
-
.option("--project <id>", "Vercel project ID (
|
|
167
|
-
.option("--branch <name>", "Filter by git branch")
|
|
168
|
-
.option("--limit <n>", "Number of deployments", "10")
|
|
82
|
+
.description("List recent deployments + branch alias (JSON)")
|
|
83
|
+
.option("--team <id>", "Vercel team ID (auto-detected if omitted)")
|
|
84
|
+
.option("--project <id>", "Vercel project ID (auto-detected if omitted)")
|
|
169
85
|
.action(listDeployments);
|
|
170
86
|
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import * as p from "@clack/prompts";
|
|
2
|
+
import pc from "picocolors";
|
|
3
|
+
import { readGlobalAuth, readWorkspaceConfig, writeWorkspaceConfig } from "../lib/config.js";
|
|
4
|
+
import { apiGetMe } from "../lib/api.js";
|
|
5
|
+
export async function workspaceCommand(opts) {
|
|
6
|
+
const auth = readGlobalAuth();
|
|
7
|
+
if (!auth) {
|
|
8
|
+
if (opts.json) {
|
|
9
|
+
console.log(JSON.stringify({ error: "not_authenticated", message: "Not logged in. Run inflight login first." }));
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
p.log.error("Not logged in. Run " + pc.cyan("inflight login") + " first.");
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
// ── Fetch workspaces ──
|
|
16
|
+
const me = await apiGetMe(auth.apiKey).catch((e) => {
|
|
17
|
+
if (opts.json) {
|
|
18
|
+
console.log(JSON.stringify({ error: "api_error", message: e.message }));
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
p.log.error(e.message);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
});
|
|
24
|
+
const workspaces = me.workspaces;
|
|
25
|
+
// ── Set active workspace ──
|
|
26
|
+
if (opts.set) {
|
|
27
|
+
const workspace = workspaces.find((w) => w.id === opts.set);
|
|
28
|
+
if (!workspace) {
|
|
29
|
+
const msg = `Workspace '${opts.set}' not found.`;
|
|
30
|
+
if (opts.json) {
|
|
31
|
+
console.log(JSON.stringify({
|
|
32
|
+
error: "workspace_not_found",
|
|
33
|
+
message: msg,
|
|
34
|
+
available: workspaces.map((w) => ({ id: w.id, name: w.name })),
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
p.log.error(msg);
|
|
39
|
+
}
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
writeWorkspaceConfig({ workspaceId: workspace.id });
|
|
43
|
+
if (opts.json) {
|
|
44
|
+
console.log(JSON.stringify({ success: true, active: workspace.id, name: workspace.name }));
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
p.outro(pc.green(`Workspace set to ${pc.bold(workspace.name)}`));
|
|
48
|
+
}
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
// ── JSON mode: list + active ──
|
|
52
|
+
if (opts.json) {
|
|
53
|
+
const active = readWorkspaceConfig()?.workspaceId ?? null;
|
|
54
|
+
console.log(JSON.stringify({ active, workspaces }));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
// ── Interactive mode: select workspace ──
|
|
58
|
+
if (workspaces.length === 0) {
|
|
59
|
+
p.log.error("No workspaces found. Create one at inflight.co");
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
const currentWorkspaceId = readWorkspaceConfig()?.workspaceId;
|
|
63
|
+
if (currentWorkspaceId) {
|
|
64
|
+
const currentWs = workspaces.find((w) => w.id === currentWorkspaceId);
|
|
65
|
+
if (currentWs) {
|
|
66
|
+
p.log.info(`Current workspace: ${pc.bold(currentWs.name)}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const selected = await p.select({
|
|
70
|
+
message: "Select a workspace",
|
|
71
|
+
options: workspaces.map((w) => ({
|
|
72
|
+
value: w.id,
|
|
73
|
+
label: w.name,
|
|
74
|
+
hint: currentWorkspaceId === w.id ? "current" : undefined,
|
|
75
|
+
})),
|
|
76
|
+
});
|
|
77
|
+
if (p.isCancel(selected)) {
|
|
78
|
+
p.cancel("Cancelled.");
|
|
79
|
+
process.exit(0);
|
|
80
|
+
}
|
|
81
|
+
const workspaceId = selected;
|
|
82
|
+
writeWorkspaceConfig({ workspaceId });
|
|
83
|
+
const name = workspaces.find((w) => w.id === workspaceId)?.name ?? workspaceId;
|
|
84
|
+
p.outro(pc.green(`Workspace set to ${pc.bold(name)}`));
|
|
85
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -5,36 +5,32 @@ import { loginCommand } from "./commands/login.js";
|
|
|
5
5
|
import { shareCommand } from "./commands/share.js";
|
|
6
6
|
import { logoutCommand } from "./commands/logout.js";
|
|
7
7
|
import { resetCommand } from "./commands/reset.js";
|
|
8
|
-
import {
|
|
8
|
+
import { workspaceCommand } from "./commands/workspace.js";
|
|
9
9
|
import { registerVercelCommand } from "./commands/vercel.js";
|
|
10
10
|
import { setupCommand } from "./commands/setup.js";
|
|
11
11
|
import pkg from "../package.json" with { type: "json" };
|
|
12
12
|
const { version } = pkg;
|
|
13
|
-
updateNotifier({ pkg }).notify();
|
|
13
|
+
updateNotifier({ pkg, updateCheckInterval: 1000 * 60 * 60 }).notify();
|
|
14
14
|
const program = new Command();
|
|
15
|
-
program
|
|
15
|
+
program
|
|
16
|
+
.name("inflight")
|
|
17
|
+
.description("Get feedback directly on your staging URL")
|
|
18
|
+
.version(version)
|
|
19
|
+
.enablePositionalOptions();
|
|
16
20
|
program.command("setup").description("Set up Inflight in your project").action(setupCommand);
|
|
17
21
|
program.command("login").description("Authenticate with your Inflight account").action(loginCommand);
|
|
18
22
|
program
|
|
19
23
|
.command("share")
|
|
20
24
|
.description("Get feedback on your staging URL")
|
|
21
25
|
.option("--url <url>", "Staging URL (skips provider selection)")
|
|
22
|
-
.option("--workspace <id>", "Workspace ID (skips workspace selection)")
|
|
23
26
|
.option("--json", "Output result as JSON")
|
|
24
27
|
.action((opts) => shareCommand(opts));
|
|
25
|
-
// program
|
|
26
|
-
// .command("preview")
|
|
27
|
-
// .description("Preview a live component from your code")
|
|
28
|
-
// .option("-m, --message <message>", "Pre-fill the intent prompt")
|
|
29
|
-
// .option("--scope <mode>", "Skip scope prompt: branch, uncommitted, staged")
|
|
30
|
-
// .option("--no-open", "Don't open result in browser")
|
|
31
|
-
// .action((opts) => previewCommand(opts));
|
|
32
28
|
program
|
|
33
|
-
.command("
|
|
34
|
-
.description("
|
|
29
|
+
.command("workspace")
|
|
30
|
+
.description("Get or set your active workspace")
|
|
35
31
|
.option("--json", "Output as JSON")
|
|
36
32
|
.option("--set <id>", "Set the active workspace")
|
|
37
|
-
.action((opts) =>
|
|
33
|
+
.action((opts) => workspaceCommand(opts));
|
|
38
34
|
registerVercelCommand(program);
|
|
39
35
|
program.command("logout").description("Disconnect your Inflight account").action(logoutCommand);
|
|
40
36
|
program.command("reset").description("Clear all Inflight auth and config").action(resetCommand);
|