@liiift-studio/deploy-vercel-from-sanity 0.1.3 → 0.1.6

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.mjs CHANGED
@@ -14,10 +14,11 @@ import {
14
14
  Heading as Heading2,
15
15
  Spinner as Spinner4,
16
16
  Button as Button4,
17
+ Badge as Badge4,
17
18
  Dialog as Dialog2,
18
19
  useToast
19
20
  } from "@sanity/ui";
20
- import { RocketIcon as RocketIcon2, TokenIcon as TokenIcon2, TrashIcon as TrashIcon2, WarningOutlineIcon } from "@sanity/icons";
21
+ import { RocketIcon as RocketIcon2, TokenIcon as TokenIcon2, TrashIcon as TrashIcon2, WarningOutlineIcon as WarningOutlineIcon2 } from "@sanity/icons";
21
22
 
22
23
  // src/components/DeployItem.tsx
23
24
  import { useState as useState2, useEffect as useEffect2, useCallback as useCallback2, useRef } from "react";
@@ -33,18 +34,23 @@ import {
33
34
  Spinner as Spinner3,
34
35
  MenuButton,
35
36
  Menu,
36
- MenuItem
37
+ MenuItem,
38
+ Code
37
39
  } from "@sanity/ui";
38
40
  import {
39
41
  RocketIcon,
40
42
  ClockIcon,
41
43
  TrashIcon,
42
44
  EllipsisVerticalIcon,
43
- LaunchIcon as LaunchIcon2
45
+ LaunchIcon as LaunchIcon2,
46
+ CopyIcon,
47
+ CheckmarkIcon,
48
+ WarningOutlineIcon
44
49
  } from "@sanity/icons";
45
50
 
46
51
  // src/lib/api.ts
47
52
  var BASE = "https://api.vercel.com";
53
+ var VERCEL_HOOK_RE = /^https:\/\/api\.vercel\.com\/v1\/integrations\/deploy\//;
48
54
  async function vercelFetch(path, token, init) {
49
55
  const res = await fetch(`${BASE}${path}`, {
50
56
  ...init,
@@ -80,9 +86,22 @@ async function cancelDeployment(opts) {
80
86
  });
81
87
  }
82
88
  async function triggerDeploy(hookUrl) {
89
+ if (!VERCEL_HOOK_RE.test(hookUrl)) {
90
+ throw new Error("Invalid deploy hook URL \u2014 must be a Vercel hook (api.vercel.com/v1/integrations/deploy/\u2026)");
91
+ }
83
92
  const res = await fetch(hookUrl, { method: "POST" });
84
93
  if (!res.ok) throw new Error(`Deploy hook returned ${res.status}`);
85
94
  }
95
+ async function getDeploymentEvents(opts) {
96
+ const params = new URLSearchParams({ limit: "100", direction: "backward" });
97
+ if (opts.teamId) params.set("teamId", opts.teamId);
98
+ const raw = await vercelFetch(
99
+ `/v2/deployments/${opts.deploymentId}/events?${params}`,
100
+ opts.token
101
+ );
102
+ const events = Array.isArray(raw) ? raw : raw.events ?? [];
103
+ return events.filter((e) => e.text?.trim());
104
+ }
86
105
 
87
106
  // src/lib/helpers.ts
88
107
  function parseHookUrl(url) {
@@ -151,6 +170,17 @@ function stateLabel(state) {
151
170
  return { label: "Unknown", tone: "default" };
152
171
  }
153
172
  }
173
+ function projectHref(inspectorUrl) {
174
+ if (!inspectorUrl) return null;
175
+ try {
176
+ const { origin, pathname } = new URL(inspectorUrl);
177
+ const parts = pathname.split("/").filter(Boolean);
178
+ if (parts.length < 2) return null;
179
+ return `${origin}/${parts[0]}/${parts[1]}`;
180
+ } catch {
181
+ return null;
182
+ }
183
+ }
154
184
 
155
185
  // src/components/StatusBadge.tsx
156
186
  import { Badge, Spinner, Flex } from "@sanity/ui";
@@ -274,6 +304,11 @@ function DeployItem({ target, token, onDelete }) {
274
304
  const [deployError, setDeployError] = useState2(null);
275
305
  const [showHistory, setShowHistory] = useState2(false);
276
306
  const [elapsed, setElapsed] = useState2(0);
307
+ const [copied, setCopied] = useState2(false);
308
+ const [showErrorLogs, setShowErrorLogs] = useState2(false);
309
+ const [errorLines, setErrorLines] = useState2([]);
310
+ const [loadingLogs, setLoadingLogs] = useState2(false);
311
+ const [logError, setLogError] = useState2(null);
277
312
  const latest = deployments[0];
278
313
  const isActive = triggering || isActiveState(latest?.state);
279
314
  const fetchDeployments = useCallback2(async () => {
@@ -294,10 +329,13 @@ function DeployItem({ target, token, onDelete }) {
294
329
  return () => clearInterval(id);
295
330
  }, [isActive, fetchDeployments]);
296
331
  useEffect2(() => {
297
- if (triggering && latest && latest.state !== void 0) {
298
- setTriggering(false);
299
- }
332
+ if (triggering && latest && latest.state !== void 0) setTriggering(false);
300
333
  }, [triggering, latest]);
334
+ useEffect2(() => {
335
+ setShowErrorLogs(false);
336
+ setErrorLines([]);
337
+ setLogError(null);
338
+ }, [latest?.uid]);
301
339
  const timerRef = useRef(null);
302
340
  useEffect2(() => {
303
341
  if (isActive) {
@@ -337,118 +375,276 @@ function DeployItem({ target, token, onDelete }) {
337
375
  setCanceling(false);
338
376
  }
339
377
  }, [latest?.uid, token, target.teamId, fetchDeployments]);
378
+ const copyUrl = useCallback2(() => {
379
+ if (!latest?.url) return;
380
+ navigator.clipboard.writeText(`https://${latest.url}`).then(() => {
381
+ setCopied(true);
382
+ setTimeout(() => setCopied(false), 2e3);
383
+ }).catch((err) => {
384
+ console.error("deploy-vercel-from-sanity: clipboard error", err);
385
+ });
386
+ }, [latest?.url]);
387
+ const fetchErrorLogs = useCallback2(async () => {
388
+ if (!latest?.uid) return;
389
+ setLoadingLogs(true);
390
+ setLogError(null);
391
+ try {
392
+ const events = await getDeploymentEvents({
393
+ deploymentId: latest.uid,
394
+ token,
395
+ teamId: target.teamId
396
+ });
397
+ const lines = events.filter((e) => e.type === "stderr" || e.type === "stdout").map((e) => e.text ?? "").filter(Boolean).reverse().slice(-30);
398
+ setErrorLines(lines.length > 0 ? lines : ["No log output captured."]);
399
+ } catch (err) {
400
+ setLogError(err instanceof Error ? err.message : "Failed to load build logs");
401
+ } finally {
402
+ setLoadingLogs(false);
403
+ }
404
+ }, [latest?.uid, token, target.teamId]);
405
+ const toggleErrorLogs = useCallback2(() => {
406
+ if (!showErrorLogs && errorLines.length === 0 && !logError) {
407
+ fetchErrorLogs();
408
+ }
409
+ setShowErrorLogs((v) => !v);
410
+ }, [showErrorLogs, errorLines.length, logError, fetchErrorLogs]);
340
411
  const branch = latest?.meta?.githubCommitRef;
341
412
  const commitMsg = latest?.meta?.githubCommitMessage?.split("\n")[0];
342
413
  const sha = shortSha(latest?.meta?.githubCommitSha);
343
414
  const creator = latest?.creator?.username;
344
415
  const deployedAt = latest?.created ? timeAgo(latest.created) : null;
416
+ const vercelProjectUrl = projectHref(latest?.inspectorUrl);
417
+ const isError = latest?.state === "ERROR";
345
418
  return /* @__PURE__ */ jsxs3(Fragment, { children: [
346
- /* @__PURE__ */ jsx3(Card2, { padding: 4, radius: 2, shadow: 1, tone: "default", children: /* @__PURE__ */ jsxs3(Stack2, { space: 4, children: [
347
- /* @__PURE__ */ jsxs3(Flex3, { align: "flex-start", justify: "space-between", gap: 3, children: [
348
- /* @__PURE__ */ jsxs3(Stack2, { space: 2, flex: 1, children: [
419
+ /* @__PURE__ */ jsx3(Card2, { padding: 4, radius: 2, shadow: 1, tone: "default", children: /* @__PURE__ */ jsxs3(Flex3, { gap: 4, align: "center", children: [
420
+ /* @__PURE__ */ jsxs3(Stack2, { space: 2, flex: 1, style: { minWidth: 0 }, children: [
421
+ /* @__PURE__ */ jsxs3(Flex3, { align: "center", justify: "space-between", gap: 2, children: [
349
422
  /* @__PURE__ */ jsx3(Text2, { size: 2, weight: "semibold", children: target.name }),
350
- /* @__PURE__ */ jsxs3(Flex3, { gap: 2, wrap: "wrap", children: [
351
- /* @__PURE__ */ jsx3(Text2, { size: 0, muted: true, children: projectId ? `${projectId.slice(0, 18)}\u2026` : "\u2014" }),
423
+ /* @__PURE__ */ jsx3(
424
+ MenuButton,
425
+ {
426
+ button: /* @__PURE__ */ jsx3(Button2, { mode: "ghost", icon: EllipsisVerticalIcon, padding: 2 }),
427
+ id: `menu-${target._id}`,
428
+ menu: /* @__PURE__ */ jsxs3(Menu, { children: [
429
+ /* @__PURE__ */ jsx3(
430
+ MenuItem,
431
+ {
432
+ text: "History",
433
+ icon: ClockIcon,
434
+ onClick: () => setShowHistory(true)
435
+ }
436
+ ),
437
+ safeHref(latest?.inspectorUrl) && /* @__PURE__ */ jsx3(
438
+ MenuItem,
439
+ {
440
+ text: "Build logs",
441
+ icon: LaunchIcon2,
442
+ as: "a",
443
+ href: safeHref(latest?.inspectorUrl),
444
+ target: "_blank",
445
+ rel: "noreferrer"
446
+ }
447
+ ),
448
+ vercelProjectUrl && /* @__PURE__ */ jsx3(
449
+ MenuItem,
450
+ {
451
+ text: "Open in Vercel",
452
+ icon: LaunchIcon2,
453
+ as: "a",
454
+ href: vercelProjectUrl,
455
+ target: "_blank",
456
+ rel: "noreferrer"
457
+ }
458
+ ),
459
+ !target.disableDeleteAction && /* @__PURE__ */ jsx3(
460
+ MenuItem,
461
+ {
462
+ text: "Delete",
463
+ icon: TrashIcon,
464
+ tone: "critical",
465
+ onClick: () => onDelete(target)
466
+ }
467
+ )
468
+ ] }),
469
+ popover: { placement: "bottom-end" }
470
+ }
471
+ )
472
+ ] }),
473
+ /* @__PURE__ */ jsxs3(Flex3, { gap: 2, wrap: "wrap", children: [
474
+ /* @__PURE__ */ jsx3(Text2, { size: 0, muted: true, children: projectId ? `${projectId.slice(0, 18)}\u2026` : "\u2014" }),
475
+ /* @__PURE__ */ jsx3(Text2, { size: 0, muted: true, children: "\xB7" }),
476
+ /* @__PURE__ */ jsxs3(Text2, { size: 0, muted: true, children: [
477
+ "Hook: ",
478
+ hookId || "\u2014"
479
+ ] }),
480
+ target.teamId && /* @__PURE__ */ jsxs3(Fragment, { children: [
352
481
  /* @__PURE__ */ jsx3(Text2, { size: 0, muted: true, children: "\xB7" }),
353
482
  /* @__PURE__ */ jsxs3(Text2, { size: 0, muted: true, children: [
354
- "Hook: ",
355
- hookId || "\u2014"
356
- ] }),
357
- target.teamId && /* @__PURE__ */ jsxs3(Fragment, { children: [
358
- /* @__PURE__ */ jsx3(Text2, { size: 0, muted: true, children: "\xB7" }),
359
- /* @__PURE__ */ jsxs3(Text2, { size: 0, muted: true, children: [
360
- "Team: ",
361
- target.teamId
362
- ] })
483
+ "Team: ",
484
+ target.teamId
363
485
  ] })
364
486
  ] })
365
487
  ] }),
366
- /* @__PURE__ */ jsx3(
367
- MenuButton,
368
- {
369
- button: /* @__PURE__ */ jsx3(Button2, { mode: "ghost", icon: EllipsisVerticalIcon }),
370
- id: `menu-${target._id}`,
371
- menu: /* @__PURE__ */ jsxs3(Menu, { children: [
488
+ loadingInitial ? /* @__PURE__ */ jsxs3(Flex3, { align: "center", gap: 2, children: [
489
+ /* @__PURE__ */ jsx3(Spinner3, { muted: true }),
490
+ /* @__PURE__ */ jsx3(Text2, { size: 1, muted: true, children: "Loading\u2026" })
491
+ ] }) : /* @__PURE__ */ jsxs3(Stack2, { space: 2, children: [
492
+ /* @__PURE__ */ jsxs3(Flex3, { align: "center", gap: 2, wrap: "wrap", children: [
493
+ triggering ? /* @__PURE__ */ jsxs3(Flex3, { align: "center", gap: 2, children: [
494
+ /* @__PURE__ */ jsx3(Spinner3, { muted: true }),
495
+ /* @__PURE__ */ jsx3(Badge3, { tone: "caution", mode: "outline", children: "Triggering\u2026" })
496
+ ] }) : /* @__PURE__ */ jsx3(StatusBadge, { state: latest?.state, showSpinner: true }),
497
+ isActive && elapsed > 0 ? /* @__PURE__ */ jsxs3(Flex3, { align: "center", gap: 1, children: [
498
+ /* @__PURE__ */ jsx3(ClockIcon, {}),
499
+ /* @__PURE__ */ jsx3(Text2, { size: 1, muted: true, children: formatDuration(elapsed) })
500
+ ] }) : !isActive && deployedAt ? /* @__PURE__ */ jsx3(Text2, { size: 1, muted: true, children: deployedAt }) : null,
501
+ branch && /* @__PURE__ */ jsxs3(Fragment, { children: [
502
+ /* @__PURE__ */ jsx3(Text2, { size: 1, muted: true, children: "\xB7" }),
503
+ /* @__PURE__ */ jsx3(Badge3, { tone: "default", mode: "outline", children: branch })
504
+ ] }),
505
+ sha && /* @__PURE__ */ jsx3(
506
+ Tooltip,
507
+ {
508
+ content: /* @__PURE__ */ jsx3(Box2, { padding: 2, children: /* @__PURE__ */ jsx3(Text2, { size: 1, children: commitMsg ?? sha }) }),
509
+ portal: true,
510
+ children: /* @__PURE__ */ jsx3(
511
+ Text2,
512
+ {
513
+ size: 1,
514
+ muted: true,
515
+ style: { cursor: "default", fontFamily: "monospace" },
516
+ children: sha
517
+ }
518
+ )
519
+ }
520
+ ),
521
+ creator && /* @__PURE__ */ jsxs3(Text2, { size: 1, muted: true, children: [
522
+ "by ",
523
+ creator
524
+ ] }),
525
+ latest?.url && latest.state === "READY" && /* @__PURE__ */ jsxs3(Fragment, { children: [
372
526
  /* @__PURE__ */ jsx3(
373
- MenuItem,
374
- {
375
- text: "History",
376
- icon: ClockIcon,
377
- onClick: () => setShowHistory(true)
378
- }
379
- ),
380
- safeHref(latest?.inspectorUrl) && /* @__PURE__ */ jsx3(
381
- MenuItem,
527
+ "a",
382
528
  {
383
- text: "Build logs",
384
- icon: LaunchIcon2,
385
- as: "a",
386
- href: safeHref(latest?.inspectorUrl),
529
+ href: `https://${latest.url}`,
387
530
  target: "_blank",
388
- rel: "noreferrer"
531
+ rel: "noreferrer",
532
+ style: { color: "inherit" },
533
+ children: /* @__PURE__ */ jsxs3(Flex3, { align: "center", gap: 1, children: [
534
+ /* @__PURE__ */ jsx3(LaunchIcon2, {}),
535
+ /* @__PURE__ */ jsx3(Text2, { size: 1, children: "Preview" })
536
+ ] })
389
537
  }
390
538
  ),
391
- !target.disableDeleteAction && /* @__PURE__ */ jsx3(
392
- MenuItem,
539
+ /* @__PURE__ */ jsx3(
540
+ Tooltip,
393
541
  {
394
- text: "Delete",
395
- icon: TrashIcon,
396
- tone: "critical",
397
- onClick: () => onDelete(target)
542
+ content: /* @__PURE__ */ jsx3(Box2, { padding: 2, children: /* @__PURE__ */ jsx3(Text2, { size: 1, children: copied ? "Copied!" : "Copy URL" }) }),
543
+ portal: true,
544
+ children: /* @__PURE__ */ jsx3(
545
+ Button2,
546
+ {
547
+ mode: "ghost",
548
+ icon: copied ? CheckmarkIcon : CopyIcon,
549
+ padding: 1,
550
+ tone: copied ? "positive" : "default",
551
+ onClick: copyUrl
552
+ }
553
+ )
398
554
  }
399
555
  )
400
- ] }),
401
- popover: { placement: "bottom-end" }
402
- }
403
- )
404
- ] }),
405
- loadingInitial ? /* @__PURE__ */ jsxs3(Flex3, { align: "center", gap: 2, children: [
406
- /* @__PURE__ */ jsx3(Spinner3, { muted: true }),
407
- /* @__PURE__ */ jsx3(Text2, { size: 1, muted: true, children: "Loading\u2026" })
408
- ] }) : /* @__PURE__ */ jsxs3(Stack2, { space: 3, children: [
409
- /* @__PURE__ */ jsxs3(Flex3, { align: "center", gap: 3, wrap: "wrap", children: [
410
- triggering ? /* @__PURE__ */ jsxs3(Flex3, { align: "center", gap: 2, children: [
411
- /* @__PURE__ */ jsx3(Spinner3, { muted: true }),
412
- /* @__PURE__ */ jsx3(Badge3, { tone: "caution", mode: "outline", children: "Triggering\u2026" })
413
- ] }) : /* @__PURE__ */ jsx3(StatusBadge, { state: latest?.state, showSpinner: true }),
414
- isActive && elapsed > 0 && /* @__PURE__ */ jsxs3(Flex3, { align: "center", gap: 1, children: [
415
- /* @__PURE__ */ jsx3(ClockIcon, {}),
416
- /* @__PURE__ */ jsx3(Text2, { size: 1, muted: true, children: formatDuration(elapsed) })
417
- ] }),
418
- !isActive && deployedAt && /* @__PURE__ */ jsx3(Text2, { size: 1, muted: true, children: deployedAt }),
419
- branch && /* @__PURE__ */ jsxs3(Fragment, { children: [
420
- /* @__PURE__ */ jsx3(Text2, { size: 1, muted: true, children: "\xB7" }),
421
- /* @__PURE__ */ jsx3(Badge3, { tone: "default", mode: "outline", children: branch })
556
+ ] })
422
557
  ] }),
423
- sha && /* @__PURE__ */ jsx3(
424
- Tooltip,
558
+ commitMsg && /* @__PURE__ */ jsx3(
559
+ Text2,
425
560
  {
426
- content: /* @__PURE__ */ jsx3(Box2, { padding: 2, children: /* @__PURE__ */ jsx3(Text2, { size: 1, children: commitMsg ?? sha }) }),
427
- portal: true,
428
- children: /* @__PURE__ */ jsx3(Text2, { size: 1, muted: true, style: { cursor: "default" }, children: sha })
561
+ size: 0,
562
+ muted: true,
563
+ style: {
564
+ overflow: "hidden",
565
+ textOverflow: "ellipsis",
566
+ whiteSpace: "nowrap"
567
+ },
568
+ children: commitMsg
429
569
  }
430
570
  ),
431
- creator && /* @__PURE__ */ jsxs3(Text2, { size: 1, muted: true, children: [
432
- "by ",
433
- creator
434
- ] }),
435
- latest?.url && latest.state === "READY" && /* @__PURE__ */ jsx3(
436
- "a",
437
- {
438
- href: `https://${latest.url}`,
439
- target: "_blank",
440
- rel: "noreferrer",
441
- style: { color: "inherit" },
442
- children: /* @__PURE__ */ jsxs3(Flex3, { align: "center", gap: 1, children: [
443
- /* @__PURE__ */ jsx3(LaunchIcon2, {}),
444
- /* @__PURE__ */ jsx3(Text2, { size: 1, children: "Preview" })
571
+ isError && /* @__PURE__ */ jsxs3(Stack2, { space: 2, children: [
572
+ /* @__PURE__ */ jsx3(
573
+ Button2,
574
+ {
575
+ text: showErrorLogs ? "Hide error details" : "Show error details",
576
+ mode: "ghost",
577
+ tone: "critical",
578
+ icon: WarningOutlineIcon,
579
+ fontSize: 1,
580
+ padding: 2,
581
+ onClick: toggleErrorLogs,
582
+ style: { alignSelf: "flex-start" }
583
+ }
584
+ ),
585
+ showErrorLogs && /* @__PURE__ */ jsxs3(Card2, { tone: "critical", radius: 2, padding: 3, children: [
586
+ loadingLogs && /* @__PURE__ */ jsxs3(Flex3, { align: "center", gap: 2, children: [
587
+ /* @__PURE__ */ jsx3(Spinner3, { muted: true }),
588
+ /* @__PURE__ */ jsx3(Text2, { size: 1, muted: true, children: "Loading logs\u2026" })
589
+ ] }),
590
+ logError && /* @__PURE__ */ jsxs3(Stack2, { space: 2, children: [
591
+ /* @__PURE__ */ jsx3(Text2, { size: 1, children: logError }),
592
+ safeHref(latest?.inspectorUrl) && /* @__PURE__ */ jsx3(
593
+ "a",
594
+ {
595
+ href: safeHref(latest?.inspectorUrl),
596
+ target: "_blank",
597
+ rel: "noreferrer",
598
+ style: { color: "inherit" },
599
+ children: /* @__PURE__ */ jsxs3(Flex3, { align: "center", gap: 1, children: [
600
+ /* @__PURE__ */ jsx3(LaunchIcon2, {}),
601
+ /* @__PURE__ */ jsx3(Text2, { size: 1, children: "View full logs in Vercel" })
602
+ ] })
603
+ }
604
+ )
605
+ ] }),
606
+ !loadingLogs && !logError && errorLines.length > 0 && /* @__PURE__ */ jsxs3(Stack2, { space: 2, children: [
607
+ /* @__PURE__ */ jsx3(
608
+ Box2,
609
+ {
610
+ style: {
611
+ maxHeight: 240,
612
+ overflowY: "auto",
613
+ fontFamily: "monospace",
614
+ fontSize: 11,
615
+ lineHeight: 1.6
616
+ },
617
+ children: errorLines.map((line, i) => /* @__PURE__ */ jsx3(
618
+ Code,
619
+ {
620
+ size: 1,
621
+ style: { display: "block", whiteSpace: "pre-wrap", wordBreak: "break-all" },
622
+ children: line
623
+ },
624
+ i
625
+ ))
626
+ }
627
+ ),
628
+ safeHref(latest?.inspectorUrl) && /* @__PURE__ */ jsx3(
629
+ "a",
630
+ {
631
+ href: safeHref(latest?.inspectorUrl),
632
+ target: "_blank",
633
+ rel: "noreferrer",
634
+ style: { color: "inherit" },
635
+ children: /* @__PURE__ */ jsxs3(Flex3, { align: "center", gap: 1, children: [
636
+ /* @__PURE__ */ jsx3(LaunchIcon2, {}),
637
+ /* @__PURE__ */ jsx3(Text2, { size: 1, children: "View full logs in Vercel" })
638
+ ] })
639
+ }
640
+ )
445
641
  ] })
446
- }
447
- )
448
- ] }),
449
- deployError && /* @__PURE__ */ jsx3(Card2, { tone: "critical", padding: 2, radius: 2, children: /* @__PURE__ */ jsx3(Text2, { size: 1, children: deployError }) })
642
+ ] })
643
+ ] }),
644
+ deployError && /* @__PURE__ */ jsx3(Card2, { tone: "critical", padding: 2, radius: 2, children: /* @__PURE__ */ jsx3(Text2, { size: 1, children: deployError }) })
645
+ ] })
450
646
  ] }),
451
- /* @__PURE__ */ jsxs3(Flex3, { align: "center", justify: "flex-end", gap: 2, children: [
647
+ /* @__PURE__ */ jsxs3(Stack2, { space: 2, style: { flexShrink: 0 }, children: [
452
648
  isActiveState(latest?.state) && /* @__PURE__ */ jsx3(
453
649
  Button2,
454
650
  {
@@ -498,7 +694,7 @@ import {
498
694
  } from "@sanity/ui";
499
695
  import { TokenIcon, CheckmarkCircleIcon } from "@sanity/icons";
500
696
  import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
501
- var TOKEN_DOC_ID = "secrets.vercelDeploy";
697
+ var TOKEN_DOC_ID = "config.vercelDeploy";
502
698
  function TokenSetup({ onSaved }) {
503
699
  const client = useClient({ apiVersion: "2025-01-01" });
504
700
  const [token, setToken] = useState3("");
@@ -571,7 +767,7 @@ function TokenSetup({ onSaved }) {
571
767
 
572
768
  // src/components/DeployTool.tsx
573
769
  import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
574
- var TOKEN_QUERY = `*[_id == "secrets.vercelDeploy"][0].accessToken`;
770
+ var TOKEN_QUERY = `*[_id == "config.vercelDeploy"][0].accessToken`;
575
771
  var TARGETS_QUERY = `*[_type == "vercel_deploy"] | order(_createdAt asc)`;
576
772
  function DeployTool() {
577
773
  const client = useClient2({ apiVersion: "2025-01-01" });
@@ -625,13 +821,7 @@ function DeployTool() {
625
821
  if (loading) {
626
822
  return /* @__PURE__ */ jsx5(Card4, { height: "fill", tone: "transparent", children: /* @__PURE__ */ jsx5(Flex5, { align: "center", justify: "center", height: "fill", children: /* @__PURE__ */ jsx5(Spinner4, { muted: true }) }) });
627
823
  }
628
- if (!token && !showTokenSetup) {
629
- return /* @__PURE__ */ jsx5(TokenSetup, { onSaved: () => {
630
- setShowTokenSetup(false);
631
- load();
632
- } });
633
- }
634
- if (showTokenSetup) {
824
+ if (!token || showTokenSetup) {
635
825
  return /* @__PURE__ */ jsx5(
636
826
  TokenSetup,
637
827
  {
@@ -649,26 +839,33 @@ function DeployTool() {
649
839
  /* @__PURE__ */ jsx5(RocketIcon2, {}),
650
840
  /* @__PURE__ */ jsx5(Heading2, { size: 2, children: "Deploy" })
651
841
  ] }),
652
- /* @__PURE__ */ jsx5(
653
- Button4,
654
- {
655
- text: "API Token",
656
- mode: "ghost",
657
- icon: TokenIcon2,
658
- fontSize: 1,
659
- onClick: () => setShowTokenSetup(true)
660
- }
661
- )
842
+ /* @__PURE__ */ jsxs5(Flex5, { align: "center", gap: 3, children: [
843
+ /* @__PURE__ */ jsx5(Badge4, { tone: "positive", mode: "outline", children: "Connected" }),
844
+ /* @__PURE__ */ jsx5(
845
+ Button4,
846
+ {
847
+ text: "Change Token",
848
+ mode: "ghost",
849
+ icon: TokenIcon2,
850
+ fontSize: 1,
851
+ onClick: () => setShowTokenSetup(true)
852
+ }
853
+ )
854
+ ] })
662
855
  ] }),
663
856
  targets.length === 0 && /* @__PURE__ */ jsx5(Card4, { padding: 5, radius: 2, tone: "transparent", shadow: 1, children: /* @__PURE__ */ jsxs5(Stack4, { space: 3, style: { textAlign: "center" }, children: [
664
857
  /* @__PURE__ */ jsx5(Text4, { size: 2, weight: "semibold", children: "No deploy targets configured" }),
665
858
  /* @__PURE__ */ jsxs5(Text4, { size: 1, muted: true, children: [
666
859
  "Create a ",
667
860
  /* @__PURE__ */ jsx5("code", { children: "vercel_deploy" }),
668
- " document in the dataset with a Vercel deploy hook URL, or add one via the Sanity CLI."
861
+ " document in the dataset with a Vercel deploy hook URL."
669
862
  ] })
670
863
  ] }) }),
671
- token && targets.map((target) => /* @__PURE__ */ jsx5(
864
+ targets.length > 0 && /* @__PURE__ */ jsx5("div", { style: {
865
+ display: "grid",
866
+ gridTemplateColumns: "repeat(auto-fill, minmax(380px, 1fr))",
867
+ gap: "12px"
868
+ }, children: targets.map((target) => /* @__PURE__ */ jsx5(
672
869
  DeployItem,
673
870
  {
674
871
  target,
@@ -676,7 +873,7 @@ function DeployTool() {
676
873
  onDelete: setPendingDelete
677
874
  },
678
875
  target._id
679
- ))
876
+ )) })
680
877
  ] }) }),
681
878
  pendingDelete && /* @__PURE__ */ jsx5(
682
879
  Dialog2,
@@ -708,7 +905,7 @@ function DeployTool() {
708
905
  ] }),
709
906
  children: /* @__PURE__ */ jsx5(Box4, { padding: 4, children: /* @__PURE__ */ jsxs5(Stack4, { space: 3, children: [
710
907
  /* @__PURE__ */ jsxs5(Flex5, { align: "center", gap: 2, children: [
711
- /* @__PURE__ */ jsx5(WarningOutlineIcon, {}),
908
+ /* @__PURE__ */ jsx5(WarningOutlineIcon2, {}),
712
909
  /* @__PURE__ */ jsx5(Text4, { size: 2, weight: "semibold", children: pendingDelete.name })
713
910
  ] }),
714
911
  /* @__PURE__ */ jsx5(Text4, { size: 1, muted: true, children: "This removes the deploy target from the dataset. The Vercel deploy hook itself is not affected." })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liiift-studio/deploy-vercel-from-sanity",
3
- "version": "0.1.3",
3
+ "version": "0.1.6",
4
4
  "description": "Sanity Studio v5 plugin — trigger and monitor Vercel deployments with full status, history, and build logs",
5
5
  "license": "MIT",
6
6
  "author": "Liiift Studio",