@liiift-studio/deploy-vercel-from-sanity 1.5.1 → 1.6.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/index.d.mts CHANGED
@@ -60,6 +60,12 @@ interface VercelDeployment {
60
60
  * deployment comes back BLOCKED.
61
61
  */
62
62
  githubCommitAuthorLogin?: string;
63
+ /**
64
+ * Branch the deploy hook is configured for. Present only on hook-triggered
65
+ * deployments, and more reliable than githubCommitRef for learning which branch
66
+ * a target follows, since it describes the hook rather than one commit.
67
+ */
68
+ deployHookRef?: string;
63
69
  /** GitHub repo in "org/repo" format — used to construct commit links */
64
70
  githubRepo?: string;
65
71
  /** GitHub org slug — fallback when githubRepo is absent */
package/dist/index.d.ts CHANGED
@@ -60,6 +60,12 @@ interface VercelDeployment {
60
60
  * deployment comes back BLOCKED.
61
61
  */
62
62
  githubCommitAuthorLogin?: string;
63
+ /**
64
+ * Branch the deploy hook is configured for. Present only on hook-triggered
65
+ * deployments, and more reliable than githubCommitRef for learning which branch
66
+ * a target follows, since it describes the hook rather than one commit.
67
+ */
68
+ deployHookRef?: string;
63
69
  /** GitHub repo in "org/repo" format — used to construct commit links */
64
70
  githubRepo?: string;
65
71
  /** GitHub org slug — fallback when githubRepo is absent */
package/dist/index.js CHANGED
@@ -617,7 +617,7 @@ async function vercelFetch(path, token, init) {
617
617
  async function listDeployments(opts) {
618
618
  const params = new URLSearchParams({
619
619
  projectId: opts.projectId,
620
- "meta-deployHookId": opts.hookId,
620
+ ...opts.branch ? { "meta-githubCommitRef": opts.branch } : { "meta-deployHookId": opts.hookId },
621
621
  limit: String(opts.limit ?? 10)
622
622
  });
623
623
  if (opts.teamId) params.set("teamId", opts.teamId);
@@ -671,7 +671,7 @@ async function proxyFetch(url, statusKey, init) {
671
671
  }
672
672
  return res.json();
673
673
  }
674
- async function fetchDeployments(transport, target, limit) {
674
+ async function fetchDeployments(transport, target, limit, branch) {
675
675
  if (transport.mode === "direct") {
676
676
  if (!target.projectId || !target.hookId) return [];
677
677
  return listDeployments({
@@ -679,11 +679,13 @@ async function fetchDeployments(transport, target, limit) {
679
679
  hookId: target.hookId,
680
680
  token: transport.token,
681
681
  teamId: target.teamId,
682
- limit
682
+ limit,
683
+ branch
683
684
  });
684
685
  }
685
686
  const params = new URLSearchParams({ key: target.proxyKey ?? "" });
686
687
  if (limit) params.set("limit", String(limit));
688
+ if (branch) params.set("branch", branch);
687
689
  const data = await proxyFetch(
688
690
  `${transport.proxyUrl}/deployments?${params}`,
689
691
  transport.statusKey
@@ -952,7 +954,7 @@ function StatusBadge({ state, showSpinner }) {
952
954
  // src/components/DeployHistory.tsx
953
955
  var import_react7 = require("react");
954
956
  var import_jsx_runtime9 = require("react/jsx-runtime");
955
- function DeployHistory({ target, token, onClose }) {
957
+ function DeployHistory({ target, token, branch, onClose }) {
956
958
  const dialogId = (0, import_react7.useId)();
957
959
  const pluginConfig = usePluginConfig();
958
960
  const [deployments, setDeployments] = (0, import_react7.useState)([]);
@@ -971,14 +973,14 @@ function DeployHistory({ target, token, onClose }) {
971
973
  setLoading(true);
972
974
  setError(null);
973
975
  try {
974
- const data = await fetchDeployments(transport, targetRef, 20);
976
+ const data = await fetchDeployments(transport, targetRef, 20, branch);
975
977
  setDeployments(data);
976
978
  } catch (err) {
977
979
  setError(err instanceof Error ? err.message : "Failed to load history");
978
980
  } finally {
979
981
  setLoading(false);
980
982
  }
981
- }, [transport, targetRef]);
983
+ }, [transport, targetRef, branch]);
982
984
  (0, import_react7.useEffect)(() => {
983
985
  load();
984
986
  }, [load]);
@@ -1004,7 +1006,7 @@ function DeployHistory({ target, token, onClose }) {
1004
1006
  ] }) }),
1005
1007
  deployments.map((d) => {
1006
1008
  const { label, tone } = stateLabel(d.state);
1007
- const branch = d.meta?.githubCommitRef ?? "\u2014";
1009
+ const branch2 = d.meta?.githubCommitRef ?? "\u2014";
1008
1010
  const sha = shortSha(d.meta?.githubCommitSha);
1009
1011
  const message = d.meta?.githubCommitMessage?.split("\n")[0] ?? "";
1010
1012
  return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Card, { padding: 3, radius: 2, shadow: 1, tone: "default", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Flex, { gap: 3, align: "center", children: [
@@ -1020,7 +1022,7 @@ function DeployHistory({ target, token, onClose }) {
1020
1022
  ) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { size: 1, muted: true, children: "\u2014" }) }),
1021
1023
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Box, { flex: 1, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Badge, { tone, children: label }) }),
1022
1024
  /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Box, { flex: 2, style: { overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Stack, { space: 1, children: [
1023
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { size: 1, children: branch }),
1025
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Text, { size: 1, children: branch2 }),
1024
1026
  sha && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Text, { size: 0, muted: true, children: [
1025
1027
  sha,
1026
1028
  message ? ` \xB7 ${message.slice(0, 40)}${message.length > 40 ? "\u2026" : ""}` : ""
@@ -1085,6 +1087,7 @@ function DeployItem({ target, token, onDelete, onEdit }) {
1085
1087
  const [pollError, setPollError] = (0, import_react8.useState)(null);
1086
1088
  const [bumping, setBumping] = (0, import_react8.useState)(false);
1087
1089
  const [awaitingBump, setAwaitingBump] = (0, import_react8.useState)(false);
1090
+ const [knownBranch, setKnownBranch] = (0, import_react8.useState)(void 0);
1088
1091
  const [bumpResult, setBumpResult] = (0, import_react8.useState)(null);
1089
1092
  const triggeredFromUidRef = (0, import_react8.useRef)(void 0);
1090
1093
  const bumpedFromUidRef = (0, import_react8.useRef)(void 0);
@@ -1104,16 +1107,20 @@ function DeployItem({ target, token, onDelete, onEdit }) {
1104
1107
  if (!ready) return;
1105
1108
  const seq = ++requestSeqRef.current;
1106
1109
  try {
1107
- const data = await fetchDeployments(transport, targetRef);
1110
+ const data = await fetchDeployments(transport, targetRef, void 0, knownBranch);
1108
1111
  if (seq !== requestSeqRef.current || !mountedRef.current) return;
1109
1112
  setDeployments(data);
1110
1113
  setPollError(null);
1114
+ if (!knownBranch) {
1115
+ const learned = data[0]?.meta?.deployHookRef ?? data[0]?.meta?.githubCommitRef;
1116
+ if (learned) setKnownBranch(learned);
1117
+ }
1111
1118
  } catch (err) {
1112
1119
  if (seq !== requestSeqRef.current || !mountedRef.current) return;
1113
1120
  setPollError(err instanceof Error ? err.message : "Could not reach the Vercel API");
1114
1121
  console.error("Deploy-vercel-from-sanity: fetch error", err);
1115
1122
  }
1116
- }, [transport, targetRef]);
1123
+ }, [transport, targetRef, knownBranch]);
1117
1124
  (0, import_react8.useEffect)(() => {
1118
1125
  fetchDeployments2().finally(() => setLoadingInitial(false));
1119
1126
  }, [fetchDeployments2]);
@@ -1602,6 +1609,7 @@ function DeployItem({ target, token, onDelete, onEdit }) {
1602
1609
  {
1603
1610
  target,
1604
1611
  token,
1612
+ branch: knownBranch,
1605
1613
  onClose: () => setShowHistory(false)
1606
1614
  }
1607
1615
  )
@@ -1887,7 +1895,7 @@ function DeployTargetForm({ initial, onSaved, onClose }) {
1887
1895
  }
1888
1896
 
1889
1897
  // src/version.ts
1890
- var VERSION = "1.5.1";
1898
+ var VERSION = "1.6.0";
1891
1899
 
1892
1900
  // src/components/DeployTool.tsx
1893
1901
  var import_jsx_runtime13 = require("react/jsx-runtime");
package/dist/index.mjs CHANGED
@@ -582,7 +582,7 @@ async function vercelFetch(path, token, init) {
582
582
  async function listDeployments(opts) {
583
583
  const params = new URLSearchParams({
584
584
  projectId: opts.projectId,
585
- "meta-deployHookId": opts.hookId,
585
+ ...opts.branch ? { "meta-githubCommitRef": opts.branch } : { "meta-deployHookId": opts.hookId },
586
586
  limit: String(opts.limit ?? 10)
587
587
  });
588
588
  if (opts.teamId) params.set("teamId", opts.teamId);
@@ -636,7 +636,7 @@ async function proxyFetch(url, statusKey, init) {
636
636
  }
637
637
  return res.json();
638
638
  }
639
- async function fetchDeployments(transport, target, limit) {
639
+ async function fetchDeployments(transport, target, limit, branch) {
640
640
  if (transport.mode === "direct") {
641
641
  if (!target.projectId || !target.hookId) return [];
642
642
  return listDeployments({
@@ -644,11 +644,13 @@ async function fetchDeployments(transport, target, limit) {
644
644
  hookId: target.hookId,
645
645
  token: transport.token,
646
646
  teamId: target.teamId,
647
- limit
647
+ limit,
648
+ branch
648
649
  });
649
650
  }
650
651
  const params = new URLSearchParams({ key: target.proxyKey ?? "" });
651
652
  if (limit) params.set("limit", String(limit));
653
+ if (branch) params.set("branch", branch);
652
654
  const data = await proxyFetch(
653
655
  `${transport.proxyUrl}/deployments?${params}`,
654
656
  transport.statusKey
@@ -917,7 +919,7 @@ function StatusBadge({ state, showSpinner }) {
917
919
  // src/components/DeployHistory.tsx
918
920
  import { useId as useId3, useEffect as useEffect3, useMemo, useState as useState4, useCallback as useCallback3 } from "react";
919
921
  import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
920
- function DeployHistory({ target, token, onClose }) {
922
+ function DeployHistory({ target, token, branch, onClose }) {
921
923
  const dialogId = useId3();
922
924
  const pluginConfig = usePluginConfig();
923
925
  const [deployments, setDeployments] = useState4([]);
@@ -936,14 +938,14 @@ function DeployHistory({ target, token, onClose }) {
936
938
  setLoading(true);
937
939
  setError(null);
938
940
  try {
939
- const data = await fetchDeployments(transport, targetRef, 20);
941
+ const data = await fetchDeployments(transport, targetRef, 20, branch);
940
942
  setDeployments(data);
941
943
  } catch (err) {
942
944
  setError(err instanceof Error ? err.message : "Failed to load history");
943
945
  } finally {
944
946
  setLoading(false);
945
947
  }
946
- }, [transport, targetRef]);
948
+ }, [transport, targetRef, branch]);
947
949
  useEffect3(() => {
948
950
  load();
949
951
  }, [load]);
@@ -969,7 +971,7 @@ function DeployHistory({ target, token, onClose }) {
969
971
  ] }) }),
970
972
  deployments.map((d) => {
971
973
  const { label, tone } = stateLabel(d.state);
972
- const branch = d.meta?.githubCommitRef ?? "\u2014";
974
+ const branch2 = d.meta?.githubCommitRef ?? "\u2014";
973
975
  const sha = shortSha(d.meta?.githubCommitSha);
974
976
  const message = d.meta?.githubCommitMessage?.split("\n")[0] ?? "";
975
977
  return /* @__PURE__ */ jsx9(Card, { padding: 3, radius: 2, shadow: 1, tone: "default", children: /* @__PURE__ */ jsxs5(Flex, { gap: 3, align: "center", children: [
@@ -985,7 +987,7 @@ function DeployHistory({ target, token, onClose }) {
985
987
  ) : /* @__PURE__ */ jsx9(Text, { size: 1, muted: true, children: "\u2014" }) }),
986
988
  /* @__PURE__ */ jsx9(Box, { flex: 1, children: /* @__PURE__ */ jsx9(Badge, { tone, children: label }) }),
987
989
  /* @__PURE__ */ jsx9(Box, { flex: 2, style: { overflow: "hidden" }, children: /* @__PURE__ */ jsxs5(Stack, { space: 1, children: [
988
- /* @__PURE__ */ jsx9(Text, { size: 1, children: branch }),
990
+ /* @__PURE__ */ jsx9(Text, { size: 1, children: branch2 }),
989
991
  sha && /* @__PURE__ */ jsxs5(Text, { size: 0, muted: true, children: [
990
992
  sha,
991
993
  message ? ` \xB7 ${message.slice(0, 40)}${message.length > 40 ? "\u2026" : ""}` : ""
@@ -1050,6 +1052,7 @@ function DeployItem({ target, token, onDelete, onEdit }) {
1050
1052
  const [pollError, setPollError] = useState5(null);
1051
1053
  const [bumping, setBumping] = useState5(false);
1052
1054
  const [awaitingBump, setAwaitingBump] = useState5(false);
1055
+ const [knownBranch, setKnownBranch] = useState5(void 0);
1053
1056
  const [bumpResult, setBumpResult] = useState5(null);
1054
1057
  const triggeredFromUidRef = useRef2(void 0);
1055
1058
  const bumpedFromUidRef = useRef2(void 0);
@@ -1069,16 +1072,20 @@ function DeployItem({ target, token, onDelete, onEdit }) {
1069
1072
  if (!ready) return;
1070
1073
  const seq = ++requestSeqRef.current;
1071
1074
  try {
1072
- const data = await fetchDeployments(transport, targetRef);
1075
+ const data = await fetchDeployments(transport, targetRef, void 0, knownBranch);
1073
1076
  if (seq !== requestSeqRef.current || !mountedRef.current) return;
1074
1077
  setDeployments(data);
1075
1078
  setPollError(null);
1079
+ if (!knownBranch) {
1080
+ const learned = data[0]?.meta?.deployHookRef ?? data[0]?.meta?.githubCommitRef;
1081
+ if (learned) setKnownBranch(learned);
1082
+ }
1076
1083
  } catch (err) {
1077
1084
  if (seq !== requestSeqRef.current || !mountedRef.current) return;
1078
1085
  setPollError(err instanceof Error ? err.message : "Could not reach the Vercel API");
1079
1086
  console.error("Deploy-vercel-from-sanity: fetch error", err);
1080
1087
  }
1081
- }, [transport, targetRef]);
1088
+ }, [transport, targetRef, knownBranch]);
1082
1089
  useEffect4(() => {
1083
1090
  fetchDeployments2().finally(() => setLoadingInitial(false));
1084
1091
  }, [fetchDeployments2]);
@@ -1567,6 +1574,7 @@ function DeployItem({ target, token, onDelete, onEdit }) {
1567
1574
  {
1568
1575
  target,
1569
1576
  token,
1577
+ branch: knownBranch,
1570
1578
  onClose: () => setShowHistory(false)
1571
1579
  }
1572
1580
  )
@@ -1852,7 +1860,7 @@ function DeployTargetForm({ initial, onSaved, onClose }) {
1852
1860
  }
1853
1861
 
1854
1862
  // src/version.ts
1855
- var VERSION = "1.5.1";
1863
+ var VERSION = "1.6.0";
1856
1864
 
1857
1865
  // src/components/DeployTool.tsx
1858
1866
  import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liiift-studio/deploy-vercel-from-sanity",
3
- "version": "1.5.1",
3
+ "version": "1.6.0",
4
4
  "description": "Sanity Studio plugin — trigger and monitor Vercel deployments with full status, history, and build logs. Supports Studio v3.30 through v6.",
5
5
  "license": "MIT",
6
6
  "author": "Liiift Studio",
package/proxy/core.ts CHANGED
@@ -184,7 +184,7 @@ async function assertDeploymentInProject(
184
184
 
185
185
  /** List recent deployments for a proxy key. */
186
186
  export async function handleDeployments(
187
- params: { key: string | null; limit?: number; statusKey: string | null },
187
+ params: { key: string | null; limit?: number; statusKey: string | null; branch?: string | null },
188
188
  env: ProxyEnv,
189
189
  ): Promise<ProxyResult> {
190
190
  const denied = checkStatusKey(params.statusKey, env)
@@ -192,9 +192,20 @@ export async function handleDeployments(
192
192
  const project = params.key ? env.projects[params.key.trim().toLowerCase()] : undefined
193
193
  if (!project) return { status: 404, body: { error: 'Unknown target key' } }
194
194
 
195
+ // Branch names come from the caller, so they are held to git's own character set
196
+ // before being spliced into an authenticated query. Anything else is ignored
197
+ // rather than rejected, which degrades to the previous hook-only behaviour.
198
+ const branch = params.branch && /^[A-Za-z0-9._\-/]{1,255}$/.test(params.branch)
199
+ ? params.branch
200
+ : undefined
201
+
195
202
  const query = new URLSearchParams({
196
203
  projectId: project.projectId,
197
- 'meta-deployHookId': project.hookId,
204
+ // Branch filtering reports what is actually live on that branch; hook filtering
205
+ // only ever shows deployments this tool triggered, so a git push never appears.
206
+ ...(branch
207
+ ? { 'meta-githubCommitRef': branch }
208
+ : { 'meta-deployHookId': project.hookId }),
198
209
  limit: String(params.limit ?? 10),
199
210
  })
200
211
  if (project.teamId) query.set('teamId', project.teamId)
@@ -87,7 +87,7 @@ async function handleGet(request: Request): Promise<Response> {
87
87
  switch (operation(request)) {
88
88
  case 'deployments': {
89
89
  const limit = Number(url.searchParams.get('limit')) || undefined
90
- return json(await handleDeployments({ key, limit, statusKey }, env), request)
90
+ return json(await handleDeployments({ key, limit, statusKey, branch: url.searchParams.get('branch') }, env), request)
91
91
  }
92
92
  case 'events':
93
93
  return json(await handleEvents({ key, deploymentId: url.searchParams.get('deploymentId'), statusKey }, env), request)