inflight-cli 2.12.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.
@@ -1,4 +1,3 @@
1
1
  export declare function workspaceCommand(opts: {
2
- json?: boolean;
3
- set?: string;
2
+ workspace?: string;
4
3
  }): Promise<void>;
@@ -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 (opts.json) {
9
- console.log(JSON.stringify({ error: "not_authenticated", message: "Not logged in. Run inflight login first." }));
10
- process.exit(1);
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 login") + " first.");
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 (opts.json) {
18
- console.log(JSON.stringify({ error: "api_error", message: e.message }));
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
- // ── 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);
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: workspace.id });
43
- if (opts.json) {
44
- console.log(JSON.stringify({ success: true, active: workspace.id, name: workspace.name }));
48
+ writeWorkspaceConfig({ workspaceId: match.id });
49
+ if (isAgent) {
50
+ agentSuccess({ workspaceId: match.id, name: match.name });
45
51
  }
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 }));
52
+ p.outro(pc.green(`Workspace set to ${pc.bold(match.name)}`));
55
53
  return;
56
54
  }
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
- }
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: currentWorkspaceId === w.id ? "current" : undefined,
74
+ hint: w.id === currentId ? "current" : undefined,
75
75
  })),
76
76
  });
77
77
  if (p.isCancel(selected)) {
package/dist/index.js CHANGED
@@ -1,17 +1,35 @@
1
1
  #!/usr/bin/env node
2
+ import { spawn } from "node:child_process";
2
3
  import { Command } from "commander";
3
4
  import updateNotifier from "update-notifier";
5
+ import pc from "picocolors";
4
6
  import { loginCommand } from "./commands/login.js";
5
7
  import { shareCommand } from "./commands/share.js";
6
8
  import { logoutCommand } from "./commands/logout.js";
7
9
  import { resetCommand } from "./commands/reset.js";
8
10
  import { workspaceCommand } from "./commands/workspace.js";
9
- import { registerVercelCommand } from "./commands/vercel.js";
10
- import { registerNetlifyCommand } from "./commands/netlify.js";
11
11
  import { setupCommand } from "./commands/setup.js";
12
12
  import pkg from "../package.json" with { type: "json" };
13
13
  const { version } = pkg;
14
- updateNotifier({ pkg, updateCheckInterval: 1000 * 60 * 60 }).notify();
14
+ const notifier = updateNotifier({ pkg, updateCheckInterval: 1000 * 60 * 60 });
15
+ if (notifier.update && notifier.update.latest !== version) {
16
+ const latest = notifier.update.latest;
17
+ if (process.stdout.isTTY) {
18
+ console.log(pc.yellow(`\n Update available: v${version} → v${latest}`) +
19
+ pc.dim(`\n Auto-updating for next run…`) +
20
+ pc.dim(`\n If this persists, run: npm i -g inflight-cli@${latest}\n`));
21
+ }
22
+ try {
23
+ const child = spawn("npm", ["install", "-g", `inflight-cli@${latest}`], {
24
+ detached: true,
25
+ stdio: "ignore",
26
+ });
27
+ child.unref();
28
+ }
29
+ catch {
30
+ // Silent fail — banner will show again next run
31
+ }
32
+ }
15
33
  const program = new Command();
16
34
  program
17
35
  .name("inflight")
@@ -33,18 +51,14 @@ program
33
51
  .option("--workspace <id>", "Workspace ID (skip selection)")
34
52
  .option("--project <id>", "Project ID, or 'new' to create")
35
53
  .option("--provider <id>", "Deployment provider: vercel, netlify")
36
- .option("--deployment <url>", "Specific deployment URL")
37
54
  .option("--version-mode <mode>", "Version handling: 'override' or 'new'")
38
55
  .option("--skip-git-check", "Skip git state check (use after agent handled git)")
39
56
  .action((opts) => shareCommand(opts));
40
57
  program
41
58
  .command("workspace")
42
59
  .description("Get or set your active workspace")
43
- .option("--json", "Output as JSON")
44
- .option("--set <id>", "Set the active workspace")
60
+ .option("--workspace <id>", "Workspace ID (skip selection)")
45
61
  .action((opts) => workspaceCommand(opts));
46
- registerVercelCommand(program);
47
- registerNetlifyCommand(program);
48
62
  program.command("logout").description("Disconnect your Inflight account").action(logoutCommand);
49
63
  program.command("reset").description("Clear all Inflight auth and config").action(resetCommand);
50
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 | null;
4
- commitFull: string | null;
5
- commitMessage: string | null;
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 interface GitSyncState {
46
- /** "clean" = nothing to do, "uncommitted" = dirty working tree, "unpushed" = clean but commits not pushed, "no_remote" = branch has never been pushed */
47
- status: "clean" | "uncommitted" | "unpushed" | "no_remote" | "detached";
48
- /** Short file status lines from `git status --porcelain` (only when uncommitted) */
45
+ export type GitSyncState = {
46
+ status: "clean";
47
+ } | {
48
+ status: "detached";
49
+ } | {
50
+ status: "uncommitted";
51
+ branch: string;
49
52
  changedFiles: string[];
50
- /** Unpushed commit summary lines: "abc1234 commit message" (only when unpushed) */
53
+ } | {
54
+ status: "unpushed";
55
+ branch: string;
51
56
  unpushedCommits: string[];
52
- /** Current branch name (null if detached) */
53
- branch: string | null;
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 > unpushed > no_remote > clean
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 | null): 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 EMPTY_GIT_INFO;
227
+ return null;
228
+ const rawBranch = run("git rev-parse --abbrev-ref HEAD", cwd);
237
229
  return {
238
- branch: run("git rev-parse --abbrev-ref HEAD", cwd),
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 > unpushed > no_remote > clean
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", changedFiles: [], unpushedCommits: [], branch: null };
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
- const changedFiles = porcelain.split("\n").filter((l) => l.trim().length > 0);
271
- if (changedFiles.length > 0) {
272
- return { status: "uncommitted", changedFiles, unpushedCommits: [], branch };
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", changedFiles: [], unpushedCommits: [], branch };
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", changedFiles: [], unpushedCommits, branch };
271
+ return { status: "unpushed", branch, unpushedCommits };
284
272
  }
285
- return { status: "clean", changedFiles: [], unpushedCommits: [], branch };
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();
@@ -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".
@@ -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?.slice(0, 7) ?? null,
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".
@@ -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 {};
@@ -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: (d.meta?.githubCommitSha ?? d.meta?.gitlabCommitSha ?? d.meta?.bitbucketCommitSha ?? null)?.slice(0, 7) ??
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: (cwd: string, gitInfo: GitInfo, opts?: ProviderResolveOptions) => Promise<string | null>;
9
+ resolve: (gitRoot: string, gitInfo: GitInfo, opts?: ProviderResolveOptions) => Promise<string | null>;
10
10
  }
11
11
  export declare const providers: Provider[];
@@ -1,6 +1,13 @@
1
1
  import { resolveNetlifyUrl } from "./netlify.js";
2
2
  import { resolveVercelUrl } from "./vercel.js";
3
- export const providers = [
4
- { id: "vercel", label: "Vercel", resolve: resolveVercelUrl },
5
- { id: "netlify", label: "Netlify", resolve: resolveNetlifyUrl },
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
- import type { NetlifyConfig } from "../lib/config.js";
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>;