inflight-cli 2.13.0 → 2.14.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.
- package/dist/commands/share.d.ts +0 -1
- package/dist/commands/share.js +386 -466
- package/dist/commands/workspace.d.ts +1 -2
- package/dist/commands/workspace.js +47 -47
- package/dist/index.js +1 -7
- package/dist/lib/git.d.ts +20 -14
- package/dist/lib/git.js +14 -28
- package/dist/lib/netlify.d.ts +4 -5
- package/dist/lib/netlify.js +22 -10
- package/dist/lib/vercel.d.ts +6 -9
- package/dist/lib/vercel.js +26 -33
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.js +11 -4
- package/dist/providers/netlify.d.ts +1 -3
- package/dist/providers/netlify.js +75 -272
- package/dist/providers/shared.d.ts +39 -0
- package/dist/providers/shared.js +249 -0
- package/dist/providers/vercel.d.ts +1 -1
- package/dist/providers/vercel.js +88 -259
- package/package.json +1 -1
|
@@ -2,76 +2,76 @@ import * as p from "@clack/prompts";
|
|
|
2
2
|
import pc from "picocolors";
|
|
3
3
|
import { readGlobalAuth, readWorkspaceConfig, writeWorkspaceConfig } from "../lib/config.js";
|
|
4
4
|
import { apiGetMe } from "../lib/api.js";
|
|
5
|
+
import { isAgent, agentError, agentActionRequired, agentSuccess } from "../lib/agent.js";
|
|
5
6
|
export async function workspaceCommand(opts) {
|
|
6
7
|
const auth = readGlobalAuth();
|
|
7
8
|
if (!auth) {
|
|
8
|
-
if (
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
if (isAgent) {
|
|
10
|
+
agentError({
|
|
11
|
+
type: "not_authenticated",
|
|
12
|
+
message: "Not logged in. Run inflight setup first.",
|
|
13
|
+
suggestion: "inflight setup",
|
|
14
|
+
});
|
|
11
15
|
}
|
|
12
|
-
p.log.error("Not logged in. Run " + pc.cyan("inflight
|
|
16
|
+
p.log.error("Not logged in. Run " + pc.cyan("inflight setup") + " first.");
|
|
13
17
|
process.exit(1);
|
|
14
18
|
}
|
|
15
|
-
// ── Fetch workspaces ──
|
|
16
19
|
const me = await apiGetMe(auth.apiKey).catch((e) => {
|
|
17
|
-
if (
|
|
18
|
-
|
|
19
|
-
process.exit(1);
|
|
20
|
-
}
|
|
20
|
+
if (isAgent)
|
|
21
|
+
agentError({ type: "api_error", message: e.message });
|
|
21
22
|
p.log.error(e.message);
|
|
22
23
|
process.exit(1);
|
|
23
24
|
});
|
|
24
25
|
const workspaces = me.workspaces;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
26
|
+
if (workspaces.length === 0) {
|
|
27
|
+
if (isAgent) {
|
|
28
|
+
agentError({ type: "no_workspaces", message: "No workspaces found. Create one at inflight.co first." });
|
|
29
|
+
}
|
|
30
|
+
p.log.error("No workspaces found. Create one at " + pc.cyan("inflight.co") + " first.");
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
const currentId = readWorkspaceConfig()?.workspaceId;
|
|
34
|
+
// --workspace flag: set directly
|
|
35
|
+
if (opts.workspace) {
|
|
36
|
+
const match = workspaces.find((w) => w.id === opts.workspace);
|
|
37
|
+
if (!match) {
|
|
38
|
+
if (isAgent) {
|
|
39
|
+
agentError({
|
|
40
|
+
type: "invalid_workspace",
|
|
41
|
+
message: `Workspace "${opts.workspace}" not found.`,
|
|
42
|
+
suggestion: `Valid IDs: ${workspaces.map((w) => w.id).join(", ")}`,
|
|
43
|
+
});
|
|
39
44
|
}
|
|
45
|
+
p.log.error(`Workspace "${opts.workspace}" not found.`);
|
|
40
46
|
process.exit(1);
|
|
41
47
|
}
|
|
42
|
-
writeWorkspaceConfig({ workspaceId:
|
|
43
|
-
if (
|
|
44
|
-
|
|
48
|
+
writeWorkspaceConfig({ workspaceId: match.id });
|
|
49
|
+
if (isAgent) {
|
|
50
|
+
agentSuccess({ workspaceId: match.id, name: match.name });
|
|
45
51
|
}
|
|
46
|
-
|
|
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 }));
|
|
52
|
+
p.outro(pc.green(`Workspace set to ${pc.bold(match.name)}`));
|
|
55
53
|
return;
|
|
56
54
|
}
|
|
57
|
-
//
|
|
58
|
-
if (
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
55
|
+
// Agent mode: always present choices
|
|
56
|
+
if (isAgent) {
|
|
57
|
+
agentActionRequired({
|
|
58
|
+
type: "choose_workspace",
|
|
59
|
+
message: "Ask the user which workspace to use.",
|
|
60
|
+
choices: workspaces.map((w) => ({
|
|
61
|
+
id: w.id,
|
|
62
|
+
label: w.name,
|
|
63
|
+
hint: w.id === currentId ? "current" : undefined,
|
|
64
|
+
})),
|
|
65
|
+
nextCommand: "inflight workspace --workspace <ID>",
|
|
66
|
+
});
|
|
68
67
|
}
|
|
68
|
+
// Interactive: always show picker
|
|
69
69
|
const selected = await p.select({
|
|
70
70
|
message: "Select a workspace",
|
|
71
71
|
options: workspaces.map((w) => ({
|
|
72
72
|
value: w.id,
|
|
73
73
|
label: w.name,
|
|
74
|
-
hint:
|
|
74
|
+
hint: w.id === currentId ? "current" : undefined,
|
|
75
75
|
})),
|
|
76
76
|
});
|
|
77
77
|
if (p.isCancel(selected)) {
|
package/dist/index.js
CHANGED
|
@@ -8,8 +8,6 @@ import { shareCommand } from "./commands/share.js";
|
|
|
8
8
|
import { logoutCommand } from "./commands/logout.js";
|
|
9
9
|
import { resetCommand } from "./commands/reset.js";
|
|
10
10
|
import { workspaceCommand } from "./commands/workspace.js";
|
|
11
|
-
import { registerVercelCommand } from "./commands/vercel.js";
|
|
12
|
-
import { registerNetlifyCommand } from "./commands/netlify.js";
|
|
13
11
|
import { setupCommand } from "./commands/setup.js";
|
|
14
12
|
import pkg from "../package.json" with { type: "json" };
|
|
15
13
|
const { version } = pkg;
|
|
@@ -53,18 +51,14 @@ program
|
|
|
53
51
|
.option("--workspace <id>", "Workspace ID (skip selection)")
|
|
54
52
|
.option("--project <id>", "Project ID, or 'new' to create")
|
|
55
53
|
.option("--provider <id>", "Deployment provider: vercel, netlify")
|
|
56
|
-
.option("--deployment <url>", "Specific deployment URL")
|
|
57
54
|
.option("--version-mode <mode>", "Version handling: 'override' or 'new'")
|
|
58
55
|
.option("--skip-git-check", "Skip git state check (use after agent handled git)")
|
|
59
56
|
.action((opts) => shareCommand(opts));
|
|
60
57
|
program
|
|
61
58
|
.command("workspace")
|
|
62
59
|
.description("Get or set your active workspace")
|
|
63
|
-
.option("--
|
|
64
|
-
.option("--set <id>", "Set the active workspace")
|
|
60
|
+
.option("--workspace <id>", "Workspace ID (skip selection)")
|
|
65
61
|
.action((opts) => workspaceCommand(opts));
|
|
66
|
-
registerVercelCommand(program);
|
|
67
|
-
registerNetlifyCommand(program);
|
|
68
62
|
program.command("logout").description("Disconnect your Inflight account").action(logoutCommand);
|
|
69
63
|
program.command("reset").description("Clear all Inflight auth and config").action(resetCommand);
|
|
70
64
|
program.parse();
|
package/dist/lib/git.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export interface GitInfo {
|
|
2
2
|
branch: string | null;
|
|
3
|
-
commitShort: string
|
|
4
|
-
commitFull: string
|
|
5
|
-
commitMessage: string
|
|
3
|
+
commitShort: string;
|
|
4
|
+
commitFull: string;
|
|
5
|
+
commitMessage: string;
|
|
6
6
|
remoteUrl: string | null;
|
|
7
7
|
isDirty: boolean;
|
|
8
8
|
diff: string | null;
|
|
@@ -38,23 +38,29 @@ export declare function parseDiffStat(diffStat: string): Array<{
|
|
|
38
38
|
insertions: number;
|
|
39
39
|
deletions: number;
|
|
40
40
|
}>;
|
|
41
|
-
export declare function getGitInfo(cwd: string): GitInfo;
|
|
41
|
+
export declare function getGitInfo(cwd: string): GitInfo | null;
|
|
42
42
|
export declare function isGitRepo(cwd: string): boolean;
|
|
43
43
|
/** Returns the root directory of the git repo, or null if not in one. */
|
|
44
44
|
export declare function getGitRoot(cwd: string): string | null;
|
|
45
|
-
export
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
export type GitSyncState = {
|
|
46
|
+
status: "clean";
|
|
47
|
+
} | {
|
|
48
|
+
status: "detached";
|
|
49
|
+
} | {
|
|
50
|
+
status: "uncommitted";
|
|
51
|
+
branch: string;
|
|
49
52
|
changedFiles: string[];
|
|
50
|
-
|
|
53
|
+
} | {
|
|
54
|
+
status: "unpushed";
|
|
55
|
+
branch: string;
|
|
51
56
|
unpushedCommits: string[];
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
} | {
|
|
58
|
+
status: "no_remote";
|
|
59
|
+
branch: string;
|
|
60
|
+
};
|
|
55
61
|
/**
|
|
56
62
|
* Determines whether the local repo has changes that haven't been deployed.
|
|
57
|
-
* Priority: detached > uncommitted >
|
|
63
|
+
* Priority: detached > uncommitted > no_remote > unpushed > clean
|
|
58
64
|
*/
|
|
59
65
|
export declare function getGitSyncState(cwd: string): GitSyncState;
|
|
60
66
|
/**
|
|
@@ -63,7 +69,7 @@ export declare function getGitSyncState(cwd: string): GitSyncState;
|
|
|
63
69
|
* "fix-header-alignment" → "Update header alignment"
|
|
64
70
|
* "main" → "Update main"
|
|
65
71
|
*/
|
|
66
|
-
export declare function generateCommitMessage(branch: string
|
|
72
|
+
export declare function generateCommitMessage(branch: string): string;
|
|
67
73
|
/**
|
|
68
74
|
* Stages all changes, commits with the given message, and pushes.
|
|
69
75
|
* Uses `git add -A` (tracked + untracked — .gitignore handles exclusions).
|
package/dist/lib/git.js
CHANGED
|
@@ -222,23 +222,15 @@ export function parseDiffStat(diffStat) {
|
|
|
222
222
|
})
|
|
223
223
|
.filter((entry) => entry !== null);
|
|
224
224
|
}
|
|
225
|
-
const EMPTY_GIT_INFO = {
|
|
226
|
-
branch: null,
|
|
227
|
-
commitShort: null,
|
|
228
|
-
commitFull: null,
|
|
229
|
-
commitMessage: null,
|
|
230
|
-
remoteUrl: null,
|
|
231
|
-
isDirty: false,
|
|
232
|
-
diff: null,
|
|
233
|
-
};
|
|
234
225
|
export function getGitInfo(cwd) {
|
|
235
226
|
if (!isGitRepo(cwd))
|
|
236
|
-
return
|
|
227
|
+
return null;
|
|
228
|
+
const rawBranch = run("git rev-parse --abbrev-ref HEAD", cwd);
|
|
237
229
|
return {
|
|
238
|
-
branch:
|
|
239
|
-
commitShort: run("git rev-parse --short HEAD", cwd),
|
|
240
|
-
commitFull: run("git rev-parse HEAD", cwd),
|
|
241
|
-
commitMessage: run("git log -1 --pretty=%s", cwd),
|
|
230
|
+
branch: rawBranch === "HEAD" ? null : rawBranch,
|
|
231
|
+
commitShort: run("git rev-parse --short HEAD", cwd) ?? "",
|
|
232
|
+
commitFull: run("git rev-parse HEAD", cwd) ?? "",
|
|
233
|
+
commitMessage: run("git log -1 --pretty=%s", cwd) ?? "",
|
|
242
234
|
remoteUrl: run("git remote get-url origin", cwd),
|
|
243
235
|
isDirty: run("git status --porcelain", cwd) !== "",
|
|
244
236
|
diff: getDiff(cwd),
|
|
@@ -253,36 +245,32 @@ export function getGitRoot(cwd) {
|
|
|
253
245
|
}
|
|
254
246
|
/**
|
|
255
247
|
* Determines whether the local repo has changes that haven't been deployed.
|
|
256
|
-
* Priority: detached > uncommitted >
|
|
248
|
+
* Priority: detached > uncommitted > no_remote > unpushed > clean
|
|
257
249
|
*/
|
|
258
250
|
export function getGitSyncState(cwd) {
|
|
259
251
|
const branch = run("git rev-parse --abbrev-ref HEAD", cwd);
|
|
260
252
|
// Detached HEAD — can't push meaningfully
|
|
261
253
|
if (!branch || branch === "HEAD") {
|
|
262
|
-
return { status: "detached"
|
|
263
|
-
}
|
|
264
|
-
// No origin remote — can't push anywhere
|
|
265
|
-
if (!run("git remote get-url origin", cwd)) {
|
|
266
|
-
return { status: "clean", changedFiles: [], unpushedCommits: [], branch };
|
|
254
|
+
return { status: "detached" };
|
|
267
255
|
}
|
|
268
256
|
// Check for uncommitted changes (staged + unstaged + untracked)
|
|
269
257
|
const porcelain = run("git status --porcelain", cwd) ?? "";
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
return { status: "uncommitted",
|
|
258
|
+
if (porcelain.length > 0) {
|
|
259
|
+
const changedFiles = porcelain.split("\n").filter((l) => l.trim().length > 0);
|
|
260
|
+
return { status: "uncommitted", branch, changedFiles };
|
|
273
261
|
}
|
|
274
262
|
// Check if branch has a remote tracking branch
|
|
275
263
|
const upstream = run(`git rev-parse --abbrev-ref ${branch}@{upstream}`, cwd);
|
|
276
264
|
if (!upstream) {
|
|
277
|
-
return { status: "no_remote",
|
|
265
|
+
return { status: "no_remote", branch };
|
|
278
266
|
}
|
|
279
267
|
// Check for unpushed commits
|
|
280
268
|
const log = run(`git log ${upstream}..HEAD --oneline`, cwd) ?? "";
|
|
281
269
|
if (log.length > 0) {
|
|
282
270
|
const unpushedCommits = log.split("\n").filter((l) => l.trim().length > 0);
|
|
283
|
-
return { status: "unpushed",
|
|
271
|
+
return { status: "unpushed", branch, unpushedCommits };
|
|
284
272
|
}
|
|
285
|
-
return { status: "clean"
|
|
273
|
+
return { status: "clean" };
|
|
286
274
|
}
|
|
287
275
|
/**
|
|
288
276
|
* Auto-generates a short commit message from the branch name.
|
|
@@ -291,8 +279,6 @@ export function getGitSyncState(cwd) {
|
|
|
291
279
|
* "main" → "Update main"
|
|
292
280
|
*/
|
|
293
281
|
export function generateCommitMessage(branch) {
|
|
294
|
-
if (!branch)
|
|
295
|
-
return "Update changes";
|
|
296
282
|
// Strip common prefixes: feature/, fix/, feat/, chore/, etc.
|
|
297
283
|
const stripped = branch.replace(/^(feature|fix|feat|chore|bugfix|hotfix|release)\/?/i, "");
|
|
298
284
|
const humanized = (stripped || branch).replace(/[-_/]/g, " ").replace(/\s+/g, " ").trim();
|
package/dist/lib/netlify.d.ts
CHANGED
|
@@ -51,17 +51,16 @@ export interface NetlifyDeploy {
|
|
|
51
51
|
context: string;
|
|
52
52
|
createdAt: number;
|
|
53
53
|
}
|
|
54
|
-
export declare function getNetlifyUser(token: string): Promise<{
|
|
55
|
-
id: string;
|
|
56
|
-
name: string;
|
|
57
|
-
email: string;
|
|
58
|
-
} | null>;
|
|
59
54
|
export declare function getNetlifySites(token: string): Promise<NetlifySite[]>;
|
|
60
55
|
export declare function getNetlifySiteById(token: string, siteId: string): Promise<NetlifySite | null>;
|
|
61
56
|
export declare function getNetlifyDeploys(token: string, siteId: string, siteName: string, opts?: {
|
|
62
57
|
branch?: string;
|
|
63
58
|
limit?: number;
|
|
64
59
|
}): Promise<NetlifyDeploy[]>;
|
|
60
|
+
/**
|
|
61
|
+
* Fetches a single deploy by ID.
|
|
62
|
+
*/
|
|
63
|
+
export declare function getNetlifyDeployById(token: string, deployId: string, siteName: string): Promise<NetlifyDeploy | null>;
|
|
65
64
|
/**
|
|
66
65
|
* Matches Netlify sites against a git remote's owner/repo.
|
|
67
66
|
* Compares build_settings.repo_path against "owner/repo".
|
package/dist/lib/netlify.js
CHANGED
|
@@ -128,15 +128,6 @@ export function writeLocalNetlifySite(root, siteId) {
|
|
|
128
128
|
}
|
|
129
129
|
// --- API calls (all take token explicitly) ---
|
|
130
130
|
const NETLIFY_API = "https://api.netlify.com/api/v1";
|
|
131
|
-
export async function getNetlifyUser(token) {
|
|
132
|
-
const res = await fetch(`${NETLIFY_API}/user`, {
|
|
133
|
-
headers: { Authorization: `Bearer ${token}` },
|
|
134
|
-
});
|
|
135
|
-
if (!res.ok)
|
|
136
|
-
return null;
|
|
137
|
-
const data = (await res.json());
|
|
138
|
-
return { id: data.id, name: data.full_name, email: data.email };
|
|
139
|
-
}
|
|
140
131
|
export async function getNetlifySites(token) {
|
|
141
132
|
const all = [];
|
|
142
133
|
let page = 1;
|
|
@@ -179,7 +170,7 @@ export async function getNetlifyDeploys(token, siteId, siteName, opts) {
|
|
|
179
170
|
id: d.id,
|
|
180
171
|
state: d.state,
|
|
181
172
|
branch: d.branch,
|
|
182
|
-
commitRef: d.commit_ref
|
|
173
|
+
commitRef: d.commit_ref ?? null,
|
|
183
174
|
commitMessage: d.title,
|
|
184
175
|
// Construct the immutable per-deploy permalink
|
|
185
176
|
deploySslUrl: `https://${d.id}--${siteName}.netlify.app`,
|
|
@@ -187,6 +178,27 @@ export async function getNetlifyDeploys(token, siteId, siteName, opts) {
|
|
|
187
178
|
createdAt: new Date(d.created_at).getTime(),
|
|
188
179
|
}));
|
|
189
180
|
}
|
|
181
|
+
/**
|
|
182
|
+
* Fetches a single deploy by ID.
|
|
183
|
+
*/
|
|
184
|
+
export async function getNetlifyDeployById(token, deployId, siteName) {
|
|
185
|
+
const res = await fetch(`${NETLIFY_API}/deploys/${encodeURIComponent(deployId)}`, {
|
|
186
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
187
|
+
});
|
|
188
|
+
if (!res.ok)
|
|
189
|
+
return null;
|
|
190
|
+
const d = (await res.json());
|
|
191
|
+
return {
|
|
192
|
+
id: d.id,
|
|
193
|
+
state: d.state,
|
|
194
|
+
branch: d.branch,
|
|
195
|
+
commitRef: d.commit_ref ?? null,
|
|
196
|
+
commitMessage: d.title,
|
|
197
|
+
deploySslUrl: `https://${d.id}--${siteName}.netlify.app`,
|
|
198
|
+
context: d.context,
|
|
199
|
+
createdAt: new Date(d.created_at).getTime(),
|
|
200
|
+
};
|
|
201
|
+
}
|
|
190
202
|
/**
|
|
191
203
|
* Matches Netlify sites against a git remote's owner/repo.
|
|
192
204
|
* Compares build_settings.repo_path against "owner/repo".
|
package/dist/lib/vercel.d.ts
CHANGED
|
@@ -45,6 +45,7 @@ export interface VercelProject {
|
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
export interface VercelDeployment {
|
|
48
|
+
id: string;
|
|
48
49
|
url: string;
|
|
49
50
|
state: string;
|
|
50
51
|
branch: string | null;
|
|
@@ -70,20 +71,16 @@ export declare function matchVercelProjectsByRepo(projects: VercelProject[], git
|
|
|
70
71
|
* Creates a new Vercel project linked to a git repository.
|
|
71
72
|
*/
|
|
72
73
|
export declare function createVercelProject(token: string, teamId: string, name: string, repo: string, repoType: "github" | "gitlab" | "bitbucket"): Promise<VercelProject>;
|
|
73
|
-
/**
|
|
74
|
-
* Fetches the branch alias URL (stable, auto-updates with each push).
|
|
75
|
-
* Returns null if no deployment exists for this branch.
|
|
76
|
-
*/
|
|
77
|
-
export interface BranchAlias {
|
|
78
|
-
url: string;
|
|
79
|
-
state: string;
|
|
80
|
-
}
|
|
81
|
-
export declare function getBranchAlias(token: string, teamId: string, projectId: string, branch: string | null): Promise<BranchAlias | null>;
|
|
82
74
|
/**
|
|
83
75
|
* Fetches recent deployments for a project.
|
|
84
76
|
*/
|
|
85
77
|
export declare function getVercelDeployments(token: string, teamId: string, projectId: string, opts?: {
|
|
86
78
|
limit?: number;
|
|
87
79
|
branch?: string;
|
|
80
|
+
sha?: string;
|
|
88
81
|
}): Promise<VercelDeployment[]>;
|
|
82
|
+
/**
|
|
83
|
+
* Fetches a single deployment by ID.
|
|
84
|
+
*/
|
|
85
|
+
export declare function getVercelDeploymentById(token: string, deploymentId: string, teamId: string): Promise<VercelDeployment | null>;
|
|
89
86
|
export {};
|
package/dist/lib/vercel.js
CHANGED
|
@@ -222,37 +222,6 @@ export async function createVercelProject(token, teamId, name, repo, repoType) {
|
|
|
222
222
|
const data = (await res.json());
|
|
223
223
|
return { id: data.id, name: data.name, teamId };
|
|
224
224
|
}
|
|
225
|
-
export async function getBranchAlias(token, teamId, projectId, branch) {
|
|
226
|
-
if (!branch)
|
|
227
|
-
return null;
|
|
228
|
-
const params = new URLSearchParams({
|
|
229
|
-
projectId,
|
|
230
|
-
teamId,
|
|
231
|
-
limit: "1",
|
|
232
|
-
branch,
|
|
233
|
-
});
|
|
234
|
-
const res = await fetch(`https://api.vercel.com/v6/deployments?${params}`, {
|
|
235
|
-
headers: { Authorization: `Bearer ${token}` },
|
|
236
|
-
});
|
|
237
|
-
if (!res.ok)
|
|
238
|
-
return null;
|
|
239
|
-
const data = (await res.json());
|
|
240
|
-
const deploy = data.deployments[0];
|
|
241
|
-
if (!deploy)
|
|
242
|
-
return null;
|
|
243
|
-
// Fetch the automatic alias for this deployment
|
|
244
|
-
const aliasParams = new URLSearchParams({ teamId });
|
|
245
|
-
const aliasRes = await fetch(`https://api.vercel.com/v13/deployments/${deploy.uid}?${aliasParams}`, {
|
|
246
|
-
headers: { Authorization: `Bearer ${token}` },
|
|
247
|
-
});
|
|
248
|
-
if (!aliasRes.ok)
|
|
249
|
-
return null;
|
|
250
|
-
const aliasData = (await aliasRes.json());
|
|
251
|
-
const url = aliasData.automaticAliases?.[0];
|
|
252
|
-
if (!url)
|
|
253
|
-
return null;
|
|
254
|
-
return { url, state: deploy.state };
|
|
255
|
-
}
|
|
256
225
|
/**
|
|
257
226
|
* Fetches recent deployments for a project.
|
|
258
227
|
*/
|
|
@@ -265,6 +234,9 @@ export async function getVercelDeployments(token, teamId, projectId, opts) {
|
|
|
265
234
|
if (opts?.branch) {
|
|
266
235
|
params.set("branch", opts.branch);
|
|
267
236
|
}
|
|
237
|
+
if (opts?.sha) {
|
|
238
|
+
params.set("sha", opts.sha);
|
|
239
|
+
}
|
|
268
240
|
const res = await fetch(`https://api.vercel.com/v6/deployments?${params}`, {
|
|
269
241
|
headers: { Authorization: `Bearer ${token}` },
|
|
270
242
|
});
|
|
@@ -272,12 +244,33 @@ export async function getVercelDeployments(token, teamId, projectId, opts) {
|
|
|
272
244
|
return [];
|
|
273
245
|
const data = (await res.json());
|
|
274
246
|
return data.deployments.map((d) => ({
|
|
247
|
+
id: d.uid,
|
|
275
248
|
url: d.url,
|
|
276
249
|
state: d.state,
|
|
277
250
|
branch: d.meta?.githubCommitRef ?? d.meta?.gitlabCommitRef ?? d.meta?.bitbucketCommitRef ?? null,
|
|
278
|
-
commitSha:
|
|
279
|
-
null,
|
|
251
|
+
commitSha: d.meta?.githubCommitSha ?? d.meta?.gitlabCommitSha ?? d.meta?.bitbucketCommitSha ?? null,
|
|
280
252
|
commitMessage: d.meta?.githubCommitMessage ?? d.meta?.gitlabCommitMessage ?? d.meta?.bitbucketCommitMessage ?? null,
|
|
281
253
|
createdAt: d.created,
|
|
282
254
|
}));
|
|
283
255
|
}
|
|
256
|
+
/**
|
|
257
|
+
* Fetches a single deployment by ID.
|
|
258
|
+
*/
|
|
259
|
+
export async function getVercelDeploymentById(token, deploymentId, teamId) {
|
|
260
|
+
const params = new URLSearchParams({ teamId });
|
|
261
|
+
const res = await fetch(`https://api.vercel.com/v13/deployments/${encodeURIComponent(deploymentId)}?${params}`, {
|
|
262
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
263
|
+
});
|
|
264
|
+
if (!res.ok)
|
|
265
|
+
return null;
|
|
266
|
+
const d = (await res.json());
|
|
267
|
+
return {
|
|
268
|
+
id: d.uid,
|
|
269
|
+
url: d.url,
|
|
270
|
+
state: d.status,
|
|
271
|
+
branch: d.meta?.githubCommitRef ?? d.meta?.gitlabCommitRef ?? d.meta?.bitbucketCommitRef ?? null,
|
|
272
|
+
commitSha: d.meta?.githubCommitSha ?? d.meta?.gitlabCommitSha ?? d.meta?.bitbucketCommitSha ?? null,
|
|
273
|
+
commitMessage: d.meta?.githubCommitMessage ?? d.meta?.gitlabCommitMessage ?? d.meta?.bitbucketCommitMessage ?? null,
|
|
274
|
+
createdAt: d.created,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
@@ -6,6 +6,6 @@ export interface ProviderResolveOptions {
|
|
|
6
6
|
export interface Provider {
|
|
7
7
|
id: string;
|
|
8
8
|
label: string;
|
|
9
|
-
resolve: (
|
|
9
|
+
resolve: (gitRoot: string, gitInfo: GitInfo, opts?: ProviderResolveOptions) => Promise<string | null>;
|
|
10
10
|
}
|
|
11
11
|
export declare const providers: Provider[];
|
package/dist/providers/index.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { resolveNetlifyUrl } from "./netlify.js";
|
|
2
2
|
import { resolveVercelUrl } from "./vercel.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
const VercelProvider = {
|
|
4
|
+
id: "vercel",
|
|
5
|
+
label: "Vercel",
|
|
6
|
+
resolve: resolveVercelUrl,
|
|
7
|
+
};
|
|
8
|
+
const NetlifyProvider = {
|
|
9
|
+
id: "netlify",
|
|
10
|
+
label: "Netlify",
|
|
11
|
+
resolve: resolveNetlifyUrl,
|
|
12
|
+
};
|
|
13
|
+
export const providers = [VercelProvider, NetlifyProvider];
|
|
@@ -1,5 +1,3 @@
|
|
|
1
1
|
import type { GitInfo } from "../lib/git.js";
|
|
2
2
|
import type { ProviderResolveOptions } from "./index.js";
|
|
3
|
-
|
|
4
|
-
export declare function pickNetlifySite(token: string): Promise<NetlifyConfig | null>;
|
|
5
|
-
export declare function resolveNetlifyUrl(cwd: string, gitInfo: GitInfo, opts?: ProviderResolveOptions): Promise<string | null>;
|
|
3
|
+
export declare function resolveNetlifyUrl(gitRoot: string, gitInfo: GitInfo, opts?: ProviderResolveOptions): Promise<string | null>;
|